/* vi: set sw=4 ts=4: */
/*
 * CCE - Console Chinese Environment -
 * Copyright (C) 1998-2003 Rui He (rhe@3eti.com)
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 */

/* osdep.h -- OS-dependent definitions */
#ifndef __CCE_OSDEP_H__
#define __CCE_OSDEP_H__

#if defined(__Minix__) || defined(__MSDOS__) || defined(__MINGW32__)

typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned int u_int;
typedef unsigned long u_long;

#endif

#if defined(__QNX__)
#include	<sys/neutrino.h>
#include	<sys/types.h>
#define mmap   mmap_file
#define munmap munmap_file

#elif defined(__MSDOS__)
#define SIGCHLD 0 

#undef HAVE_SYS_MMAN_H

#elif defined(__Lynx__)

#elif defined(__BEOS__)
#include <net/socket.h>  /* for fd_set & select etc */

#elif defined(__Minix__)

#ifdef HAVE_SYS_MEMIO_H
#include <sys/memio.h>      /* For Minix-vmd */
#undef USE_DEVMEM_FILE      /* use mmmap */
#else
#define USE_DEVMEM_FILE  1   /* For standard Minix */
#define USE_EXTERN_INOUT 1   

#endif

#endif   /* end of mmap-related stuff */

#ifndef HAVE_SYS_MMAN_H

#define MAP_FAILED ((void *)(-1))
#define PROT_READ  (0x01)
#define PROT_WRITE (0x02)
#define MAP_SHARED (0x01)

#define mmap  mmap_file
#define munmap munmap_file

extern void *mmap_file(void *start, size_t len, int prot, int flags, int fd, off_t offset);
extern int munmap_file(void *start, size_t len);

#endif

#if defined(linux)

#include	<linux/keyboard.h>

#elif defined(__FreeBSD__)

#include    <errno.h>
#include    <vm/vm_param.h>
#include    <osreldate.h>
#if __FreeBSD_version >= 410000  

#include	<sys/fbio.h>
#include    <sys/consio.h>
#include    <sys/kbio.h>
#else
#include    <machine/console.h>
#endif       /* endif __FreeBSD_version >= 410000 */

#elif defined(__NetBSD__) || defined(__OpenBSD__)

#include    <errno.h>
#include    <sys/time.h>
#include    <dev/wscons/wsconsio.h>
#include    <dev/wscons/wsdisplay_usl_io.h>

#elif defined(__Lynx__)  /* tested on Lynx 4.0 */

#define __NO_INCLUDE_WARN__  /* otherwise too many warnings regarding vt.h/kd.h */

#elif defined(__QNX__)  /* tested on QNX 6.2.1 */

#elif defined(__SunOS__) /* SunOS or Solaris? */
#include	<stropts.h>  /* for STREAM */
#include 	<sys/kbd.h>
#include	<sys/kbio.h>

#define PS_IOPL 0x3000  /* it's 0x3000, not 3!! bit 12-13 */
#define USE_EXTERN_INOUT  1

#endif

#ifdef HAVE_TERMIOS_H
#include    <termios.h>  /* This one is POSIX, termio.h is old */
#define SUPPORT_POSIX_TERMIOS 1
#endif

#ifdef HAVE_SYS_VTKD_H
#include	<sys/vtkd.h>  /* For SCO OpenServer 5.0.x, SysV kernel 3.2*/

#else

#ifdef HAVE_SYS_VT_H
#include    <sys/vt.h>
#endif
#ifdef HAVE_SYS_KD_H
#include    <sys/kd.h>
#endif

#endif

#ifndef XCASE
#define XCASE 0  /* For terminal settings */
#endif

#if defined(__MSDOS__) || defined(__WINDOWS__)
#  define R_CNTRL   "rb"
#  define W_CNTRL   "wb"
#define CCE_OPENFLAG O_BINARY /* we need O_BINARY, otherwise opened as text file */
#else  /* __MSDOS__ || _WINDOWS__ */
#  define R_CNTRL   "r"
#  define W_CNTRL   "w"
#define CCE_OPENFLAG 0
#endif /* __MSDOS__ */

#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#define HAVE_VT_PROCESS_SWITCH  1 /* have VT_PROCESS switching */
#define HAVE_TIOCCONS	        1 /* become virtual console */
#define HAVE_KDSETMODE			1 /* ioctl KDSETMODE */
#elif defined(__Lynx__)
#define HAVE_VT_PROCESS_SWITCH  1 /* have VT_PROCESS switching */
#else
#if defined(VT_SETMODE) && defined(VT_AUTO) && defined(VT_PROCESS)
#define HAVE_VT_PROCESS_SWITCH 1  /* assuming it has */
#endif
#if defined(TIOCCONS)
#define HAVE_TIOCCONS 1  /* assuming it has */
#endif
#if defined(KDSETMODE) && defined(KD_TEXT) && defined(KD_GRAPHICS)
#define HAVE_KDSETMODE 1     /* assuming it has */
#endif
#endif

#if defined(linux) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__Minix__) || defined(__SunOS__) || defined(__QNX__) || defined(__Lynx__)
#define HAVE_TIOCWINSZ        1  /* TIOCGWINSZ/TIOCSWINSZ, get/set win size */

#elif defined(TIOCGWINSZ) && defined(TIOCSWINSZ)  /* for Darwin and other unknown OS! */
#define HAVE_TIOCWINSZ      1

#endif

#ifndef HAVE_SELECT  /* a working select() call ? */

#define fd_set int
#undef FD_SET
#undef FD_CLR
#undef FD_ISSET
#undef FD_ZERO
#define FD_SET(n,p) 
#define FD_CLR(n,p) 
#define FD_ISSET(n,p)  (1)  /* always set */
#define FD_ZERO(p) 

#endif

#ifndef USE_EXTERN_INOUT  /* gcc inline assembly externsion! */

static inline u_char  PortInb(u_int port)
{
#ifdef CCE_TARGETARCH_I386
        u_char  _rval;

        __asm__ volatile ("inb %1,%0"
                :"=a" (_rval)
                :"d" ((u_short) port));

        return(_rval);
#endif
}

static inline void PortOutw(u_short value, u_int port)
{
#ifdef CCE_TARGETARCH_I386
    __asm__ ("outw %0,%1"
	     ::"a" ((u_short) value),
	     "d" ((u_short) port));
#endif
}

static inline void PortOutb(u_char value, u_int port)
{
#ifdef CCE_TARGETARCH_I386
    __asm__ ("outb %0,%1"
	     ::"a" ((u_char) value),
	     "d" ((u_short) port));
#endif
}

#else /* USE_EXTERN_INOUT */

extern u_char PortInb(u_int port);
extern void   PortOutw(unsigned short value, u_int port);
extern void   PortOutb(unsigned char value, u_int port);

#endif /* USE_EXTERN_INOUT */

#if  defined(__i386__) || defined(__ia64__) || defined(WIN32) || \
    (defined(__alpha__) || defined(__alpha)) || \
     defined(__arm__) || \
    (defined(__mips__) && defined(__MIPSEL__)) || \
     defined(__SYMBIAN32__) || \
     defined(__x86_64__) || \
     defined(__LITTLE_ENDIAN__)
#define CCE_TARGETARCH_LITTLEENDIAN  1
#else
#define CCE_TARGETARCH_BIGENDIAN     1
#endif

static inline void ConvertCPUToLE32(unsigned int src, unsigned char *dest)
{
	unsigned int data = src;  /* make a copy, src & dest may be the same address! */
	dest[0] = (unsigned char)(data & 0xFF);
	dest[1] = (unsigned char)((data >> 8) & 0xFF);
	dest[2] = (unsigned char)((data >> 16) & 0xFF);
	dest[3] = (unsigned char)((data >> 24) & 0xFF);
}

static inline unsigned int ConvertLE32ToCPU(unsigned char *src)
{
	unsigned int data = src[0] | (((unsigned int)src[1]) << 8) | 
		             (((unsigned int)src[2]) << 16) | (((unsigned int)src[3]) << 24);
	return data;
}

#endif  /* __CCE_OSDEP_H__ */

