/*
** OS specific settings for SVR4.2
** Produced for SVR4.2 by Ian Hartas, iph@oasis.icl.co.uk
*/

#ifndef _OS_H_
#define _OS_H_

#ifdef INKERNEL
#define _KERNEL
#endif

#include <sys/types.h>
#include <sys/errno.h>
#include <sys/signal.h>
#include <sys/fcntl.h>
#include <sys/tty.h>
#include <ctype.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 <sys/conf.h>
#include <sys/uio.h>
#include <sys/cred.h>
#include <sys/inline.h>
#include <sys/cmn_err.h>
#include <sys/kmem.h>
#include <sys/i8237A.h>
#ifndef SVR40
#include <sys/moddefs.h>
#endif /* SVR40 */
#include <sys/ddi.h>

#include "local.h"

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

#include "soundcard.h"

typedef struct uio snd_rw_buf;

extern time_t lbolt;
extern snd_itoa(int , char[]);

#ifdef DEBUG
#define DEB(x) x
#define printk printf

#define TIMER_ARMED	121234
#define TIMER_NOT_ARMED	1
#endif /* DEBUG */

#define NEED_SPRINTF
#define sprintf snd_sprintf

/*
** Move bytes from the buffer which the application given in a
** write() call.
** offs is position relative to the beginning of the buffer in
** user space. The count is number of bytes to be moved.
*/
#define COPY_FROM_USER(target, source, offs, count) \
	/* if (offs) source->uio_offset = (offs); */ \
	if (uiomove(target, count, UIO_WRITE, source)) \
	{ \
		printf ("sb: Bad copyin()!\n"); \
	} else
/* 
** Like COPY_FROM_USER but for writes. 
*/
#define COPY_TO_USER(target, offs, source, count) \
	/* if (offs) target->uio_offset = (offs); */ \
	if (uiomove(source, count, UIO_READ, target)) \
	{ \
		printf ("sb: Bad copyout()!\n"); \
	} else
/* 
** The following macros are like COPY_*_USER but work just with one byte (8bit),
** short (16 bit) or long (32 bit) at a time.
** The same restrictions apply than for COPY_*_USER
*/
 
#define GET_BYTE_FROM_USER(target, addr, offs)	{/*addr->uio_offset += (offs); */ \
	uiomove((char*)&(target), 1, UIO_WRITE, addr);}
#define GET_SHORT_FROM_USER(target, addr, offs)	{/*addr->uio_offset += (offs); */ \
	uiomove((char*)&(target), 2, UIO_WRITE, addr);} 


#define IOCTL_FROM_USER(target, source, offs, count) \
if (copyin(&(((char *)source)[offs]), (target), (count))) \
	cmn_err(CE_WARN, "IOCTL_FROM_USER fault\n"); \
else

#define IOCTL_TO_USER(target, offs, source, count)  \
if (copyout((source), &(((char *)target)[offs]), (count)) ) \
	cmn_err(CE_WARN, "IOCTL_TO_USER fault\n"); \
else


#define IOCTL_OUT(arg, ret) snd_ioctl_out(arg, ret)
#define IOCTL_IN(arg)	snd_ioctl_in(arg) 

#define printk 		printf

extern int snd_sound_timeout(caddr_t arg);

/* 
** Returns 1, if process has received a signal which terminates it 
*/
#define PROCESS_ABORTING(q, f)  snd_proc_abort(q, f)

#define DO_SLEEP(A, F, ticks) { \
	int x, tid; \
	DISABLE_INTR(x); \
	if (ticks) \
	   tid = timeout(snd_sound_timeout, &(A), (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;

/*
** DMA handling functions and macros
*/
#define ALLOC_DMA_CHN(chn, deviceID) snd_dma_alloc(chn)
#define RELEASE_DMA_CHN(chn)	snd_dma_release(chn) 
#define snd_dma_intr(chan)	dma_disable(chan)

#define GET_TIME()	snd_get_lbolt()	/* Returns 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 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 INW			inw
#define OUTB(data, port)	outb(port, data)
#define OUTW(data, port)	outw(port, data)
#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)	snd_alloc(nbytes, KM_SLEEP)
#define KERNEL_FREE(addr)	snd_free(addr)

/*
** 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)snd_alloc((size_t)size, KM_NOSLEEP)

#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, time)


/*
** The macro DECLARE_FILE() adds an entry to struct fileinfo referencing the
** connected filestructure.
** This entry must be initialized in sound_open() in soundcard.c
**
** ISSET_FILE_FLAG() allows checking of flags like O_NONBLOCK on files
**
*/
/* 
** DECLARE_FILE was: struct file *filp 
*/
#define DECLARE_FILE()                   int *dummy
#define ISSET_FILE_FLAG(fileinfo, flag)  0 /* (fileinfo->filp->f_flags & (flag) ? 1 : 0) */

/*
** Bytes to page boundary 
*/
#define pgbnd(a) (ptob(1) - ((ptob(1) - 1) & (int)(a)))

#define INT_HANDLER_PROTO() void(*hndlr)(int)
#define INT_HANDLER_PARMS(irq, parms) int irq
#define INT_HANDLER_CALL(irq) irq
#endif
