#ifndef __DRIVER_H
#define __DRIVER_H

/*
 *  Main header file for the ALSA driver
 *  Copyright (c) 1994-98 by Jaroslav Kysela <perex@jcu.cz>
 *
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

//#define SNDCFG_DEBUG
//#define SNDCFG_DEBUG_DETECT

#ifdef __QNXNTO__
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <hw/inout.h>
#include <hw/pci.h>
#include <time.h>
#include <unistd.h>
#include <devctl.h>
#include <atomic.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include <sys/dispatch.h>
#include <sys/iofunc.h>
#else
#include "qnx4.h"
#endif

#define SND_VERSION "0.01"

#define __SND_OSS_COMPAT__

#define SND_CARDS		8	/* number of supported soundcards - don't change - minor numbers */

#ifndef SNDCFG_MAJOR		/* standard configuration */
#define SNDCFG_MAJOR		14
#endif

/*
 *  ==========================================================================
 */

#include "asound.h"
#include "asoundid.h"

/*
 *  ==========================================================================
 */

#include "misc.h"
#include "schedule.h"

#ifdef SNDCFG_ISAPNP
#include "isapnp.h"
#endif

/* options */
#define SND_OPTIONS "p:i:d:x"
#define SND_IOPORT	'p'
#define SND_IRQ		'i'
#define SND_DMA		'd'
#define SND_NO_PNP	'x'

/* auto values */

#define SND_AUTO_PORT		0x00ff
#define SND_AUTO_IRQ		16
#define SND_AUTO_DMA		8
#define SND_AUTO_DMA_SIZE	(0x7fffffff)
#define SND_IRQ_DISABLE		0xffff
#define SND_DMA_DISABLE		0xffff

#ifdef __QNXNTO__
#define outb(v, p) out8(p, v)
#define inb(p) in8(p)
#define outw(v, p) out16(p, v)
#define inw(p) in16(p)
#define outl(v, p) out32(p, v)
#define inl(p) in32(p)
#endif

/* Hardware resources allocation */

#define SND_DMAS		4	/* max DMA # for soundcard */
#define SND_IRQS		4	/* max IRQ # for soundcard */
#define SND_PORTS		8	/* max PORT regions for soundcard */

/* Interrupts */

#define SND_IRQ_TYPE_ISA     0       /* ISA IRQ */
#define SND_IRQ_TYPE_PCI     1       /* PCI IRQ (shareable) */
#define SND_IRQ_TYPE_EISA    SND_IRQ_TYPE_PCI

typedef void snd_irq_handler_t( void * );

typedef struct snd_stru_irq {
    int type;       /* see to SND_IRQ_TYPE_XXXX */
    char *name;
    void *dev_id;
	snd_irq_handler_t *handler;
#ifdef __QNXNTO__
	pthread_t tid;
#else
    int tid;
    int iid;
#endif 
	int id;
	struct snd_stru_irq *next;
    unsigned short irq;
} snd_irq_t;

/* DMA */

#define SND_DMA_TYPE_ISA	0	/* ISA DMA */
#define SND_DMA_TYPE_PCI	1	/* PCI DMA (anywhere in kernel memory) */
#define SND_DMA_TYPE_PCI_16MB	2	/* PCI DMA (must be in low 16MB memory) */
#define SND_DMA_TYPE_HARDWARE	3	/* buffer mapped from device */

typedef struct snd_stru_dma {
	int type;		/* dma type - see SND_DMA_TYPE_XXXX */
	int dma;		/* DMA number */
	char *name;		/* pointer to name */
	char *shm_name;		/* pointer to shared memory object name (if shared) */
	unsigned char *buf;	/* pointer to DMA buffer */
	long size;		/* real size of DMA buffer */
	long rsize;		/* requested size of DMA buffer */
	char *owner;		/* owner of this DMA channel */
	char *soft_owner;	/* owner of soft DMA channel */
	struct snd_stru_dma *next;
	volatile unsigned short
	 mmaped:1,		/* mmaped area to user space */
	 mmap_free:1;		/* free mmaped buffer */
} snd_dma_t;

typedef struct snd_stru_port {
    unsigned short port;
    unsigned short size;
    char *name;
	struct snd_stru_port *next;
} snd_port_t;

/* main structure for soundcard */
typedef struct snd_stru_io snd_io_t;
typedef struct snd_stru_switch snd_kswitch_t;
typedef struct snd_stru_switch_list snd_kswitch_list_t;
typedef struct snd_stru_card snd_card_t;
typedef struct snd_info_entry snd_info_entry_t;
typedef struct snd_stru_pcm snd_pcm_t;
typedef struct snd_stru_mixer snd_kmixer_t;
typedef struct snd_stru_rawmidi snd_rawmidi_t;
typedef struct snd_stru_control snd_control_t;
typedef struct snd_stru_timer snd_timer_t;
typedef struct snd_stru_timer_instance snd_timer_instance_t;
typedef struct snd_stru_synth snd_synth_t;
typedef struct snd_stru_ocb snd_ocb_t;
typedef struct snd_stru_context snd_context_t;
typedef struct snd_stru_attr snd_attr_t;
typedef struct snd_stru_timer_entry snd_timer_entry_t;

struct snd_stru_ocb {
	iofunc_ocb_t 		iofunc_ocb;
	iofunc_notify_t 	notify[3];
	void 				*private_data;	
};

struct snd_stru_context {
#ifdef __QNXNTO__
	resmgr_context_t	*rctp;
#else
        pid_t           pid;
#endif
	snd_ocb_t			*ocb;
	int					rw_offset;
	int 				nonblock;
};

#include "switch.h"

struct snd_stru_card {
	int number;		/* number of soundcard (index to snd_cards) */

	unsigned int type;	/* type (number ID) of soundcard */

	char id[16];		/* id string of this card */
	char abbreviation[16];	/* abbreviation of soundcard name */
	char shortname[32];	/* short name of this soundcard */
	char longname[80];	/* name of this soundcard */

	void *private_data;	/* private data for soundcard */
	void (*private_free) (void *private);	/* callback for freeing of private data */

	void *static_data;	/* private static data for soundcard */

	int switches_count;		/* switches count */
	snd_kswitch_list_t switches;		/* switches */
	snd_irq_t *irqs;
	snd_port_t *ports;
	snd_dma_t *dmas;
	snd_attr_t *attr;
	snd_mutex_define(control);
    snd_info_entry_t *info_entries;     /* info entries */
};

/* device.c */

typedef int snd_open_t (void *data, snd_ocb_t *ocb);
typedef long snd_read_t (snd_context_t *ctp, long count);
typedef long snd_write_t (snd_context_t *ctp, long count);
typedef int snd_close_t (snd_ocb_t *ocb);
typedef int snd_ionotify_t (snd_ocb_t *ocb, int *trig);
typedef int snd_ioctl_t (snd_ocb_t *ocb, unsigned int cmd, unsigned long arg, int len);

struct snd_stru_io {
	char *comment;		
	snd_read_t *read;
	snd_write_t *write;
	snd_open_t *open;
	snd_close_t *close;
	snd_ionotify_t *io_notify;
	snd_ioctl_t *ioctl;
};

struct snd_stru_attr {
	iofunc_attr_t 		attr;
	void *		  		data;
	snd_io_t	  		io;
	int					id;
};

struct snd_stru_timer_entry
{
	int id;
	void (*function)(unsigned long data);
	unsigned long data;	
	unsigned long expires;
};

#define NOTIFY_INPUT	0x1
#define NOTIFY_OUTPUT	0x2
#define NOTIFY_EXCEPT	0x4

/* sound.c */
extern snd_attr_t *snd_register_io(void *data, char *dev_name, snd_io_t * io);
extern void snd_unregister_io(snd_attr_t *attr);
extern int snd_copy_to_user( snd_context_t *ctp, void *buffer, int nbytes);
extern int snd_copy_from_user( snd_context_t *ctp, void *buffer, int nbytes);
extern void snd_sound_init(void);
extern void snd_notify_trigger(snd_ocb_t *ocb, int n, int ndx);
extern int snd_ioctl_out(long *arg, long value);
extern long snd_ioctl_in(long *arg);

/* memory.c */

extern void snd_malloc_init(void);
extern void snd_malloc_done(void);
extern void *snd_malloc(unsigned long size);
extern void *snd_calloc(unsigned long size);
extern void snd_free(void *obj, unsigned long size);
extern char *snd_malloc_strdup(char *string);
extern void snd_free_str(char *string);
extern int snd_dma_malloc(snd_card_t * card, snd_dma_t *dmaptr, char *owner);
extern void snd_dma_free(snd_card_t * card, snd_dma_t *dmaptr);
extern char *snd_malloc_pages(unsigned long size, char **xname, int dma);
extern void snd_free_pages(char *xname, char *ptr, unsigned long size);
extern void *snd_device_mmap(unsigned long addr, unsigned long size);
extern int snd_device_munmap(void *addr, unsigned long size);

/* init.c */
extern int snd_start (void);
extern void snd_cleanup (void);
extern void snd_sound_cleanup (void);	/* OS specific portion of snd_cleanup() */
extern int snd_init(int argc, char **argv);
extern int snd_ecards_limit;
extern int snd_cards_count;
extern unsigned int snd_cards_bitmap;
extern snd_card_t *snd_cards[SND_CARDS];
extern snd_card_t *snd_card_new(int idx, char *id);
extern int snd_card_free(snd_card_t * card);
extern int snd_card_register(snd_card_t * card);
extern int snd_card_unregister(snd_card_t * card);
extern void snd_delay(int loops);
extern int snd_card_info_init(void);
extern int snd_card_info_done(void);

extern int snd_check_ioport(snd_card_t * card, int port, int size);
extern int snd_register_ioport(snd_card_t * card, int port, int size, char *name,
							   snd_port_t ** rport);
extern int snd_unregister_ioport(snd_card_t * card, snd_port_t * port);
extern int snd_unregister_ioports(snd_card_t * card);
extern int snd_register_dma_channel(snd_card_t * card, char *name, int number,
									int type, int rsize, int *possible_numbers,
									snd_dma_t ** rdma);
extern int snd_unregister_dma_channels(snd_card_t * card);
extern int snd_register_interrupt(snd_card_t * card, char *name, int number,
								  int type, snd_irq_handler_t * handler, void *dev_id,
								  int *possible_numbers, snd_irq_t ** rirq);
extern int snd_unregister_interrupts(snd_card_t * card);

extern void snd_disable_irq(snd_irq_t *irqptr);
extern void snd_enable_irq(snd_irq_t *irqptr);

int snd_timer_init(void);
int snd_add_timer( snd_timer_entry_t *timer);
void snd_del_timer(snd_timer_entry_t *timer);

/* --- */

#ifdef __QNXNTO__

#define snd_printk( args... ) fprintf(stderr,"snd: " ##args )
#ifdef SNDCFG_DEBUG
#define snd_printd( args... ) snd_printk( ##args )
#else
#define snd_printd( args... )	/* nothing */
#endif

#ifdef SNDCFG_DEBUG_DETECT
#define snd_printdd( args... ) snd_printk( ##args )
#else
#define snd_printdd( args... )	/* nothing */
#endif

#define SND_OSS_VERSION         ((3<<16)|(8<<8)|(1<<4)|(0))	/* 3.8.1a */
#endif				/* __DRIVER_H */


#endif
