/*
 * 5799-WZQ (C) COPYRIGHT IBM CORPORATION  1986,1987,1988
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header:ioccvar.h 12.0$ */
/* $ACIS:ioccvar.h 12.0$ */
/* $Source: /ibm/acis/usr/sys/caio/RCS/ioccvar.h,v $ */

#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsidioccvar = "$Header:ioccvar.h 12.0$";
#endif

/*
 * This file contains definitions related to the kernel structures
 * for dealing with the iocc subsystem.
 *
 * There is one iocc_hd structure per dma channel.
 * Each adapter on the I/O bus which can control more than one device
 * (such as the hard disk and floppy disk adapters) has a iocc_ctlr structure.
 * Each device on an adapter has a iocc_device structure.
 */


/*
 * The following structure is for callback in case a driver cannot get
 * it's dma channel. It's in ioccvar since iocc_hd needs it.
 */
struct dma_callback {
	struct	dma_callback *d_next;
	caddr_t	d_info;
	int	(*d_wakeup)();
};

#define IOCC_PAGE_SIZE 2
#define IOCC_REGION_SIZE 32
/*
 * Per dma channel structure.
 *
 * This structure hold pointers to dma registers, the state of the channel,
 * and TCW addresses.
 */
struct	iocc_hd {
	caddr_t	hd_addr;		/* dummy to keep config happy */
	caddr_t dh_8237_reg;		/* hardware register location */
	unsigned dh_pagebitmask[IOCC_PAGE_SIZE]; /* bitmap to allocate page mode TCW's */
	unsigned dh_region_map[IOCC_REGION_SIZE]; /* region mode map */
	short	dh_channel;		/* channel # */
	short	dh_subchan;		/* subchannel on the 8237 chip */
	short	dh_state;		/* state of this channel (see dmavar.h)*/
	struct	dma_callback *dh_callfwd; /* head of callback queue */
	struct	dma_callback *dh_calllst; /* tail of callback queue */
	struct	iocc_ctlr *dh_actf;	/* head of queue to transfer */
	struct  iocc_ctlr *dh_actl;	/* tail of queue to transfer */
};

/*
 * Per-controller structure.
 * (E.g. one for each hard disk adapter, and other things
 * that control more than one device.)
 *
 * 4.x BSD calls controllers what IBM calls adapters.  The words are
 * (almost) interchangeable.
 *
 * If an adapter has devices attached, then there are
 * cross-referenced iocc_device structures.
 * This structure is the one which is queued in iocc resource wait,
 * and saves the information about iocc resources which are used.
 * The queue of devices waiting to transfer is also attached here.
 */
struct iocc_ctlr {
	struct	iocc_driver *ic_driver;
	short	ic_ctlr;	/* controller index in driver */
	short	ic_alive;	/* controller exists */
	caddr_t	ic_addr;	/* address of device in i/o space */
	int	ic_irq;		/* the IRQ level of the device */
	/* end of ioconf filled in fields */
	struct	iocc_hd *ic_hd; /* link back to the header */
	struct	buf ic_tab;	/* queue of devices for this controller */
	short	ic_dmachannel;		/* dma channel number */
	int	ic_dmaflags;		/* dma transfer flags */
	struct	buf *ic_dmabuf;		/* buffer to transfer */
/* This is the forwrd link in a list of controllers on a dma channel */
	struct iocc_ctlr *ic_dmaforw;
};

/*
 * Per ``device'' structure.
 * (A controller has devices or uses dma).
 * (Everything else is a ``device''.)
 *
 * If a controller has many drives attached, then there will
 * be several iocc_device structures associated with a single iocc_ctlr
 * structure.
 *
 * This structure contains all the information necessary to run
 * a non-dma device such as an asy card.  It also contains information
 * for slaves of iocc controllers as to which device on the slave
 * this is.  A flags field here can also be given in the system specification
 * and is used to tell which asy lines are hard wired or other device
 * specific parameters.
 */
struct iocc_device {
	struct	iocc_driver *iod_driver; /* corresponding driver struct */
	short	iod_unit;	/* unit number on the system */
	short	iod_ctlr;	/* mass ctlr number; -1 if none */
	short	iod_slave;	/* slave on controller */
	caddr_t	iod_addr;	/* address of device in i/o space */
	short	iod_irq;	/* interrupt request level */
	short	iod_dk;		/* if init 1 set to number for iostat */
	int	iod_flags;	/* parameter from system specification */
	short	iod_alive;	/* device exists */
	short	iod_type;	/* driver specific type information */
	caddr_t	iod_physaddr;	/* phys addr, for standalone (dump) code */
/* this is the forward link in a list of devices on a controller */
	struct	iocc_device *iod_forw;
/* if the device is connected to a controller, this is the controller */
	struct	iocc_ctlr *iod_mi;
	struct	iocc_hd *iod_hd;
};

/*
 * Per-driver structure.
 *
 * Each iocc driver defines entries for a set of routines
 * as well as an array of types which are acceptable to it.
 * These are used at boot time by the configuration program.
 */
struct iocc_driver {
	int	(*idr_probe)();		/* see if a driver is really there */
	int	(*idr_slave)();		/* see if a slave is there */
	int	(*idr_attach)();	/* setup driver for a slave */
	int	(*idr_dgo)();		/* controller specific dma setup */
	caddr_t	*idr_addr;		/* device csr addresses */
	char	*idr_dname;		/* name of a device */
	struct	iocc_device **idr_dinfo;/* backpointers to iodinit structs */
	char	*idr_mname;		/* name of a controller */
	struct	iocc_ctlr **idr_minfo;	/* backpointers to iominit structs */
	int	(*idr_intr)();		/* interrupt service routine */
#define	INT_SERVICED	0
#define INT_NOT_MINE 	1
	int	idr_csr;		/* offset to read/write csr */
	int	(*idr_chanrelse)();	/* dma channel release request */
	char	idr_flags;		/* all zero in old drivers! */
#define	EARLY_INT	0x01	/* interrupt handler called on initial
				 * (probe) interrupt and int_8259 does the
				 * shared interrupt reset */
#define DRIVER_SUSPEND	0x02	/* driver wants call on suspend */
	int	(*idr_suspend)();	/* driver suspend */
#define SUSPEND_START	0		/* driver suspend start */
#define SUSPEND_DONE	1		/* driver suspend done */
};

#ifdef KERNEL
/*
 * Iominit and iodinit initialize the mass storage controller and
 * device tables specifying possible devices.
 */
extern	struct	iocc_ctlr iominit[];
extern	struct	iocc_device ioccdinit[];
extern char volatile *shr_int_reset[];	/* shared interrupt reset @s - in autoconf.c */

#endif KERNEL

#define PROBE_BAD	0		/* if the probe fails */
#define PROBE_NOINT	1		/* if probe ok but no interrupt */
#define PROBE_OK	2		/* if the probe was ok (interrupt caused) */
#define PROBE_BAD_INT	-1		/* we lost or didn't get interrupt */

/*
 * delay routine for probe routines:
 * quit when the interrupt is received or if we exceed the
 * loop count
 */
#define PROBE_DELAY(n) 		\
	{ extern int volatile int_level; register int N = (n); extern char delay_addr;\
			while (--N >= 0 && int_level < 0) \
				* (char volatile *) DELAY_ADDR = 0xff;	}
struct slihtab {
	int (*slih_rtn)();		  /* address of the actual slih */
	struct slihtab *slih_next;	  /* the address of the next slih entry */
	int slih_info;			  /* info for that SLIH */
	short slih_irq;			  /* irq level that caused it */
	short slih_flags;		  /* flag bits for autoconfig */
#	define FIXED	0x01		  /* if a fixed (predetermined) entry */

};

struct int_table {
	char *addr_8259;		  /* address of appropriate 8259 */
	struct slihtab *slihtab;	  /* address of the SLIH table */
};

struct int_table int3table, int4table;
