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

#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsidcbcb = "$Header:cbcb.h 12.2$";
#endif

#define CBCB_MAGIC 0xcb010203		/* magic number to recognize the cbcb */

#define HDENT	0x00
#define FDENT	0x01
#define KBENT	0x02
#define SVENT	0x03
#define CLENT	0x04
#define BIOSENT 0x05
#define AFIENT	0x06
#define MSENT	0x07
#define SPKENT	0x08
#define UBENT	0x09
#define MASKENT	0x0A
#define DEBENT	0x0b			/* (old) pseudo entry for debug flags */
#define OPENT	0x0c			/* optical disk entry */
#define PUTCENT	0x0d			/* put a character */
#define ASYENT	0x0e			/* asy */
#define LPENT	0x0f			/* line printer */
#define TAPEENT	0x10			/* tape drive */
#define MCENT	0x11			/* micro channel */

#define MAXCBCBENT 32			/* total number of cbcb entries */

#define MAXCPU	4			/* MAX possible number of cpu's */

#ifndef __STDC__
#define volatile
#endif

/*
 * POS defines
 */
#define NO_PS_2_SLOTS	8
struct pos_data {
	unsigned char	pos[NO_PS_2_SLOTS];
};

/*
 * Control Block Control Block (CBCB)
 *
 * This structure is the primary control block used to implement
 * PC and Coprocessor communication.
 *
 * op_code  - This field is filled in by Unix to tell us what type of
 *	      PC operation it wants us to do. The strategy() routine
 *	      in the pc code uses this op code to queue the request.
 *	      This field is also used as a semaphore on the Unix
 *	      side of the world. No kernel driver may request a
 *	      PC operation until this field is zero (0). The the
 *	      Unix function pc_req(0) in the file /usr/sys/ca_atr/machdep.c
 *	      for further information.
 *
 * romp_int3
 * romp_int4 - Used to simulate the 8259 hardware as it is implemented on
 *	      the IBM RTPC. See the file /usr/sys/ca_atr/autoconf.c for
 *	      more info.
 *
 * cbcb_ent - Many PC operations require detailed info from Unix to do
 *	      their jobs. Rather than build a monolithic control block
 *	      that has every field required for every function we allow
 *	      either side (Unix or the PC) to tell the other where it
 *	      can find more information.
 *
 *		unix_cb - Unix address where the PC can find additional
 *			  data.
 *
 *		pc_cb	- PC address where Unix can find additional data.
 *
 * debug    -  Switch used to control PC debugging messages. See the file
 *	       /usr/sys/pc_code/pcparam.h for the levels of messages that
 *	       are used by the system.
 */

struct cbcb_ent
{
	u_long          unix_cb;
	u_long          pc_cb;
};

struct cbcb
{
	volatile u_short op_code;	/* 0...1 */
	volatile u_char  romp_int3;	/* 2 */
	volatile u_char  romp_int4;	/* 3 */
	struct cbcb_ent cbcb_ent[MAXCBCBENT];	/* original + expansion */
	u_long          debug;		/* 0 align */
	u_char          dummy3;		/* 0 align  Has '<' char */
#define dummy2 dummy3			/* we fake it */
	volatile u_char  romp_int0;	/* 1 align if level 0 interrupt from pc side
					 * to romp */
	u_short		debug_size;	/* 2 align size of info */
	u_long		debug_info;	/* 0 align where debug_info is */
	u_short		port;		/* 0 port address */
	u_short		cpu;		/* 2 cpu number */
	u_long		window;		/* 0 memory window base */
	u_long		physmem_bytes;	/* 0 memory size (bytes) */
	u_char		vec_map[16];	/* 0 per cpu vec_map */
	u_short		state;		/* 0 IPL, RUNNING etc */
	u_short		fill;		/* 2 */
	u_long		cbcb[MAXCPU];	/* 0 other cbcb entries */
	u_long		read_count;	/* 0 number read xfr's */
	u_long		read_bytes;	/* 0 number of bytes read */
	u_long		write_count;	/* 0 number of write xfr's */
	u_long		write_bytes;	/* 0 number of bytes written */
	u_long		magic;		/* 0 magic number */
};


/************************* CBCB DEFINES *********************************/

#define CB_SETMAP    0x0001     /* set the vector map in the PC */
#define CB_REBOOT    0x0002     /* reboot the PC code */
#define CB_TODREAD   0x0003     /* Read the TOD registers */
#define CB_TODRESET  0x0004     /* Reset the TOD chip */
#define CB_HALT	     0x0005	/* Halt (return to DOS) */
#define CB_RESTART   0x0006	/* Restart (ROMP) */
#define CB_QEOI	     0x0007	/* request queuing of EOI's */
#define CB_EOI3	     0x0008	/* send EOI on level 3 */
#define CB_EOI4	     0x0009	/* send EOI on level 4 */
#define CB_PUTC	     0x000a	/* send out character */
#define CB_SUSPEND   0x000b	/* suspend (go to dos but allow restart */
#define CB_POR	     0x000c	/* POR */
#define CB_IPL	     0x000d	/* IPL */
#define CB_TAPEREQ   0x0020		/* a TAPE request */
#define CB_HDREQ     0x0030		/* a HD request */
#define CB_FDREQ     0x0040		/* a FD request */
#define CB_UBREQ     0x0050		/* a UB request */
#define CB_OPREQ     0x0060		/* a OP request */
#define CB_BBT       0x0070		/* read and set the bad block table */
#define CB_BIOSREQ   0x0080		/* a BIOS request */
#define CB_AFIREQ    0x0090		/* a AFI request */
#define CB_MSREQ     0x00a0     /* Mouse Request */
#define CB_KBREQ     0x00b0     /* Keyboard Request */
#define CB_SPKREQ    0x00c0		/* Speaker Request */
#define CB_MASKREQ   0x00d0		/* Mask PS/2 interrupts Request */
#define CB_MCREQ     0x00e0		/* MC request */

/*
 * irq info passed with the irq level in the cbcb
 *	bits are
 *      7 - fake poll.
 *	6 - EIOPENDING
 *	5 - QEIOPENDING
 *	4 - irq info bit 1 - ( 0 is reserved, 1/2/3 are device specific)
 *	3 - irq info bit 0
 *	2 - irq number bit 2
 *	1 - irq number bit 1
 *	0 - irq number bit 0
 */
#define IRQ_INF_MASK	0x18
#define IRQ_INF_SHIFT	3
#define IRQ_PUT_INFO(x)	((x << IRQ_INF_SHIFT) & IRQ_INF_MASK)
#define IRQ_GET_INFO(x) ((x & IRQ_INF_MASK) >> IRQ_INF_SHIFT)

/*
 * kls interupt types
 */
#define	KLS_KEYBOARD_INTR	0x1
#define	KLS_MOUSE_INTR		0x2
#define	KLS_SPEAKER_INTR	0x3

/*
 * hdinfo - Hard Disk Configuration Information
 *
 * This structure is filled out by the PC and passed to Unix
 * at boot time.
 */

struct hdinfo
{				/* new disk info structure per drive */
	u_short          ncpd;	/* # of cyls per drive */
	u_short          ntpc;	/* # of tracks per cyl */
	u_short          nspt;	/* # of sectors per track */
	u_short          pstart;	/* starting cyl of 4.3 partition */
	u_short          plen;	/* # of cyls in 4.3 partition */
	u_short          flag;	/* drive status flag */
};


/*
 * config: copied into location 0x800 in the romp to pass needed
 * information during setup.
 */
struct postconfig
{
	u_short         mem_size;
	u_short         pcif_base;
	u_long          cbcb_addr;
	u_short         equip;
	u_char          ega_info;
	u_char          ega_switch;
	u_long          memconfig;
	struct hdinfo   hdinfo[2];
	u_char		fill[24];	/* just in case we get more disks */
	u_short		dst_flag;	/* if dst in effect locally */
	u_short		pc_mem_size;	/* how much pc memory > 1 meg in k */
	u_char		version[80];	/* version string */
	u_char		os_type;	/* os type of other side */
	u_char		cpu_type;	/* what sort of cpu */
	u_char		flags;		/* option flags */
	u_char		cpu;		/* cpu number */
	u_char		string[128];	/* string passed to unix */
	u_char		maxcpu;		/* max number of cpu's present */
	u_char		fill2[3];	/* align */
};

/* os_type codes (see above) */
#define OLD_TYPE	0		/* old version of unix.exe */
#define DOS_TYPE	1		/* running under DOS */
#define ABIOS_TYPE	2		/* using ABIOS support */
#define OS_2_TYPE	3		/* running under OS/2 */

#define OS_STRING(type) ((type) == OLD_TYPE ? "OLD_DOS" : (type) == DOS_TYPE ? "DOS" : (type) == ABIOS_TYPE ? "ABIOS" : (type) == OS_2_TYPE ? "OS_2" : "unknown")

/*
 * common ub defines
 */
/* ub pc data area */
struct ubpc {
	char	rcv_status;	/* recieve return code */
	char	xmit_status;	/* transmit return code */
	char	tmp_status;	/* return code for get status/init cmds */
	char	new;		/* non-zero if new support on unix side */
	char	ub_addr[6];	
	u_short  receive_length;
	u_long	 receive_addr;
};

/* intr_type fields */
#define UB_XMIT_INTR	1	/* transmit interrupt */
#define UB_RCV_INTR	2	/* receive interrupt */

/*
 * this control block is used to insure that in fact the romp is 
 * waiting to be restarted and is still executing. The magic number
 * is set to RESTART_MAGIC and the counter is still changing.
 * after a restart it is up to the unix side to pick up new copies 
 * of the various pointers and to restart the various devices that
 * need it.
 */
#define RESTART_MAGIC	0x1234CEAF
#define RESTART_ADDR	0x1100L

struct restart {
volatile long	magic;			/* the magic number while suspended */
volatile long	counter;		/* to see if its still alive */
};

#define STATE_IPL	0		/* is IPL'ing */
#define STATE_RUNNING	1		/* processor running */
#define STATE_HALT	2		/* halted */
#define STATE_REBOOT	3		/* rebooting */
#define STATE_SUSPEND	4		/* suspending */

#define CPU_STATES { "iplling", "running", "halted", "rebooting", "suspended" }

/* values put into kbstatus to indicate the type of value present */
#define KBD_EMPTY	0x00	/* no data present */
#define KBD_DATA	0x01	/* data (scan code) */
#define KBD_ASCII	0x02	/* data (ascii) */
#define KBD_HOT_KEY	0x03	/* hot key detected */
#define KBDSTAT_HOT_KEY	0x03	/* hot key detected */
#define KBD_CPUSTATE	0x04	/* cpu state change */
