/*
 * OS specific settings for SCO
 */
#ifndef _OS_H_
#define _OS_H_

#include <sys/types.h>
#include <sys/errno.h>
#include <sys/signal.h>
#include <sys/fcntl.h>
#include <sys/tty.h>
#include <ctype.h>
#include <stdlib.h>
#include <sys/inode.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/fs/s5dir.h>
#include <sys/file.h>
#include <sys/immu.h>
#include <sys/region.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/sysmacros.h>
#include <sys/dma.h>
#include <sys/wait.h>

#include "local.h"

#ifdef CONFIGURE_SOUNDCARD

#undef ALLOW_SELECT
#undef SHORT_BANNERS
#undef SND_DEFAULT_ENABLE
#define SND_DEFAULT_ENABLE 0

#include "soundcard.h"

/* typedef struct uio snd_rw_buf; */
typedef char snd_rw_buf;

extern time_t lbolt;

#if 0
#define COPY_FROM_USER(target, source, offs, count) copyin(&((source)[offs]), (target), (count))
#define COPY_TO_USER(target, offs, source, count) copyout((source), &((target)[offs]), count)
#else
#define COPY_FROM_USER(target, source, offs, count) \
	if (copyin(&((source)[offs]), (target), (count))) { \
		printf ("snd: Bad copyin()!\n"); \
		/* return RET_ERROR(EIO); */ \
	}
#define COPY_TO_USER(target, offs, source, count) \
	if (copyout((source), &((target)[offs]), count)) { \
		printf ("snd: Bad copyout()!\n"); \
		/* return RET_ERROR(EIO); */ \
	}
#endif


#define IOCTL_FROM_USER(target, source, offs, count) copyin(&(((char *)source)[offs]), (target), (count))
#define IOCTL_TO_USER(target, offs, source, count) copyout((source), &(((char *)target)[offs]), (count))

#define GET_BYTE_FROM_USER(target, addr, offs)	target = fubyte(&((addr)[offs]))
#define GET_SHORT_FROM_USER(target, addr, offs)	copyin(&((addr)[offs]), (char*)&(target), 2)
#define GET_WORD_FROM_USER(target, addr, offs)	target = fuword(&((addr)[offs]))
#define PUT_WORD_TO_USER(addr, offs, data)	suword(data, &((addr)[offs]))

/*****
#define IOCTL_IN(arg)			(*(int*)arg)
******/
#define IOCTL_OUT(arg, ret)		*(int*)arg = ret
#define IOCTL_IN(arg)			fuword((int*)(arg))
/*****
#define IOCTL_OUT(arg, ret)		suword(ret, (int*)(arg))
******/

#define printk 		printf

extern int isc_sound_timeout(caddr_t arg);

#define PROCESS_ABORTING(q, f) ((u.u_procp)->p_sig || q & WK_SIGNAL)	/* Returns 1, if process has received
						   a signal which terminates it */
#define DO_SLEEP(A, F, ticks) { \
	int x, tid; \
	DISABLE_INTR(x); \
	if (ticks) \
	   tid=timeout(isc_sound_timeout, &(A), /*lbolt+*/(ticks)); \
	A = WK_SLEEP; \
	if (sleep(&(A), (PZERO+8)|PCATCH)) \
	   A = WK_SIGNAL; \
	if (ticks && A != WK_TIMEOUT) \
	   untimeout(tid); \
	RESTORE_INTR(x); \
	}
#define WAKE_UP(q, f)	{ int x; DISABLE_INTR(x);q = WK_WAKEUP; wakeup(&(q)); \
			  RESTORE_INTR(x); }
#define SET_ABORT_FLAG(q,f)
#define SOMEONE_WAITING(q, f)	(q & WK_SLEEP)
#define TIMED_OUT(q,f)		(q & WK_TIMEOUT)
#define RESET_WAIT_QUEUE(q,f)	q=0;

#define ALLOC_DMA_CHN(chn) !dma_alloc(chn, DMA_BLOCK)
#define RELEASE_DMA_CHN(chn) dma_relse(chn)

#define GET_TIME()	(lbolt)	/* Returns current time (1/HZ secs since boot) */

#define RELEASE_IRQ(irq_no)
/*
 * #define DEFINE_WAIT_QUEUE(name, flag) static int *name = NULL; static int flag = 0
 * #define DEFINE_WAIT_QUEUES(name, flag) static int *name = {NULL}; static int flag = {0}
 */

#define DEFINE_WAIT_QUEUE(name, flag) static volatile int name = 0
#define DEFINE_WAIT_QUEUES(name, flag) static volatile int name = {0}

#define DMA_MODE_READ		0
#define DMA_MODE_WRITE		1

#ifndef DMAMODE_AUTO
#define DMAMODE_AUTO		0x10
#endif

#ifndef HZ
extern int hz;
#define HZ	hz
#endif

#define DISABLE_INTR(flags)	flags = spl6()
#define RESTORE_INTR(flags)	splx(flags)

#define RET_ERROR(err)		-(err)

#define INB			inb
#define OUTB(addr, data)	outb(data, addr)
#define memcpy(d, s, c)		bcopy(s, d, c)

#ifndef TRUE
#define TRUE  1
#define FALSE 0
#endif
/* 
   KERNEL_MALLOC() allocates requested number of memory  and 
   KERNEL_FREE is used to free it. 
   These macros are never called from interrupt, in addition the
   nbytes will never be more than 4096 bytes. Generally the driver
   will allocate memory in blocks of 4k. If the kernel has just a
   page level memory allocation, 4K can be safely used as the size
   (the nbytes parameter can be ignored).
*/
#define KERNEL_MALLOC(nbytes)	sptalloc(btoc(4096), PG_P|PG_RW, 0, 0)
#define KERNEL_FREE(addr)	sptfree(addr, btoc(4096), 1)

/*
 * The macro PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr)
 * returns size bytes of
 * (kernel virtual) memory which will never get freed by the driver.
 * This macro is called only during boot. The linux_ptr is a linux specific
 * parameter which should be ignored in other operating systems.
 * The mem_ptr is a pointer variable where the macro assigns pointer to the
 * memory area. The type is the type of the mem_ptr.
 */
#define PERMANENT_MALLOC(typecast, mem_ptr, size, linux_ptr) \
  mem_ptr = (typecast)ctob(memget(btoc(size)))

#define NO_INLINE_ASM

/*
 * The macro DEFINE_TIMER defines variables for the ACTIVATE_TIMER if
 * required. The name is the variable/name to be used and the proc is
 * the procedure to be called when the timer expires.
 */

#define DEFINE_TIMER(name, proc) \
  static int name = 0

/*
 * The ACTIVATE_TIMER requests system to call 'proc' after 'time' ticks.
 */

#define ACTIVATE_TIMER(name, proc, time) \
	timeout(proc, &name, /*lbolt+*/ time)


#endif
#endif
