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

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

/*
 * $Header:rb.h 12.0$
 * $ACIS:rb.h 12.0$
 */

#ifndef NCPU
#define NCPU	2
#endif

/********************* STRUCTURE DEFINITIONS ****************************/


struct DESC
{
	unsigned int    lmt;
	unsigned int    basel;
	char            baseh;
	char            acc;
	unsigned int    res;
};

#include "cbcb.h"


/* The following is the ub queue definition */

struct UBQ
{
	u_long          unix_zcb;
	u_short         zcbflags;
};

typedef struct UBQ ubq_t;
typedef struct UBQ far *ubqaddr;

#define MAX_UBS     2
#define MAX_PAC_LEN 2000

/* This is for reading the I/O ports */
struct ubdevice
{
	char            ub_csr;	/* Control/Status reg */
	char            ub_ca;	/* Channel Attention port */
	char            ub_tic;	/* Timer Interrupt Clear port */
	char            ub_pos5;/* A read from this port will return the
				 * contents of POS location 5 */
};

/* These are the legal ram addresses */
#define ADDR1  0xD0000000
#define ADDR2  0xD8000000
#define ADDR3  0xC0000000
#define ADDR4  0xC8000000

/*
 * The following are the command blocks that are used with the Ethernet Card
 */

/*
 * Command Block Header -- Common to all commands
 */

typedef struct ZCB_Head
{
	char            ZCB_Command;
	char            ZCB_Status;
	char            ZCB_Result;
	char            ZCB_Report_Code;
	short           ZCB_Options;
	long            ZCB_Post_Routine;
	long            ZCB_Link;
}               ZCB_Header;

/*
 * Transmit Command Block
 */

typedef struct Transmit_ZCB
{
	short           ZCB_Xmt_Data_Length;
	long            ZCB_Xmt_Data_Address;
	short           ZCB_Xmt_Hdwr_Status;
	short           ZCB_Xmt_Bfr_ID;
	long            ZCB_Xmt_Bfr_Address;
}               ZCB_T;

/*
 * Receive Command Block
 */

typedef struct Receive_ZCB
{
	char            ZCB_Rcv_Mode;
	char            ZCB_Rcv_Status;
	short           ZCB_Bfr_Size;
	long            ZCB_Rcv_Bfr_Address;
	short           ZCB_Rcv_Data_Length;
	short           ZCB_Rcv_Frame_Count;
	short           ZCB_Rcv_Hdwr_Status;
	short           ZCB_Rcv_Frame_ID;
	long            ZCB_Rcv_Bfr_Ptr;
	short           ZCB_Rcv_Bfr_Count;
	long            ZCB_Rcv_Descriptor;
}               ZCB_R;

#define Rcv_Mode_Incremental	1

/*
 * Initialize command block
 */

typedef struct Initialize_ZCB
{
	short           ZCB_Init_Modes;
	short           ZCB_Max_Xmt_Len;
	short           ZCB_Num_Xmt_Bfrs;
	short           ZCB_Max_Rcv_Size;
	short           ZCB_Num_Rcv_Bfrs;
	char            ZCB_Hole1[16];
	short           ZCB_Acq_Modes;
	short           ZCB_Acq_Max_Xmt_Len;
	short           ZCB_Acq_Num_Xmt_Bfrs;
	short           ZCB_Acq_Max_Rcv_Size;
	short           ZCB_Acq_Num_Rcv_Bfrs;
	char            ZCB_Hole2[8];
}               ZCB_I;

/*
 * Status command block
 */

typedef struct Status_ZCB
{
	short           ZCB_Stat_State;
	short           ZCB_Stat_Modes;
	short           ZCB_Stat_Max_Xmt_Len;
	short           ZCB_Stat_Num_Xmt_Bfrs;
	short           ZCB_Stat_Max_Rcv_Size;
	short           ZCB_Stat_Num_Rcv_Bfrs;
	char            ZCB_Stat_Unique_ID[6];
	long            ZCB_Stat_Total_Xmts;
	long            ZCB_Stat_Total_Rcvs;
	long            ZCB_Stat_CRC_Errors;
	long            ZCB_Stat_ALN_Errors;
	long            ZCB_Stat_RSC_Errors;
	long            ZCB_Stat_OVR_Errors;
	char            ZCB_Hole3[24];
}               ZCB_S;

typedef struct ZCB
{
	ZCB_Header      header;
	union
	{
		ZCB_I           ZCBI;
		ZCB_S           ZCBS;
		ZCB_T           ZCBT;
		ZCB_R           ZCBR;
	}               ZCB_Body;
#define zcbi ZCB_Body.ZCBI
#define zcbs ZCB_Body.ZCBS
#define zcbt ZCB_Body.ZCBT
#define zcbr ZCB_Body.ZCBR
}               ZCB;

/* Ehternet software structure per adapter */

typedef struct UB_SOFTC
{
	ZCB             tmpzcb;
	ZCB             rcvzcb;
	ZCB             xmtzcb;
	u_long          xmt_zcb;	/* Unix address of the transmit ZCB */
	u_long          rcv_zcb;	/* Unix address of the receive ZCB */
	u_long          urcvbuff;	/* Unix address of the receive buffer */
	char            pcrcvbuff[MAX_PAC_LEN];
	char            pcxmtbuff[MAX_PAC_LEN];
	short             newxmt;
	short             newrcv;
	u_long          ram_addr;	/* pc segmented addr of the onboard
					 * FCI code */
	char		ram_save[256];	/* copy of initial state of ub ram */
	struct ubdevice	*addr;		/* I/O port address */
}               UB_SOFTC;

/*
 * These are the command codes for the Ethernet Card
 */

#define UB_INIT 	0x40	/* Initialize */
#define UB_XMT_FR	0x41	/* Transmit Frame */
#define UB_RCV		0x42	/* Receive */
#define UB_STAT 	0x43	/* Status */
#define UB_CAN_RCV	0x44	/* Cancel Receives */
#define UB_GT_XMT_BFR	0x45	/* Get Transmit Buffer */
#define UB_WR_XMT_BFR	0x46	/* Write Transmit Buffer */
#define UB_SD_XMT_BFR	0x47	/* Send Transmit Buffer */
#define UB_RL_XMT_BFR	0x48	/* Release Transmit Buffer */
#define UB_RD_FR_DT	0x49	/* Read Frame Data */
#define UB_NX_RCV_BFR	0x4A	/* Next Receive Buffer */
#define UB_FL_FR	0x4B	/* Flush Frame */

/*
 * These are the Result Codes for the Ethernet Card
 */

#define UB_XMT_LT_ERR		0x10	/* Data length to long or short */
#define UB_XMT_ADDR_ERR 	0x11	/* Data starts at odd address */
#define UB_UNKN_CMD_ERR 	0x12	/* Undefined command code in ZCB */
#define UB_UNIMPL_ERR		0x13	/* Unimplemented command code */
#define UB_XMT_COMP_SUC 	0x14	/* Transmit successfully complete */
#define UB_XMT_COMP_ERR 	0x15	/* Transmit completed with error */
#define UB_RCV_COMP_SUC 	0x16	/* Frame received successfully */
#define UB_RCV_FR_TRUN_ERR	0x17	/* Receive buffer was to small */
#define UB_INIT_COMP		0x18	/* Initialization completed */
#define UB_STAT_COMP		0x19	/* Status completed */
#define UB_NT_YT_INIT		0x1A	/* Not Yet Initialized */
#define UB_ALR_INIT		0x1B	/* Already Initialized */
#define UB_CMD_CAN		0x1C	/* Command cancelled */
#define UB_CAN_COMP		0x1D	/* Cancel complete */
#define UB_XMT_BFR_ASS		0x1E	/* Transmit buffer assigned */
#define UB_XMT_BFR_NT_ASS	0x1F	/* Transmit buffer not assigned */
#define UB_XMT_BFR_RL		0x20	/* Transmit buffer released */
#define UB_XMT_BFR_WR		0x21	/* Transmit buffer written */
#define UB_MR_DT_AVAIL		0x22	/* More Data available */
#define UB_NO_MR_RCV_BFR	0x23	/* No more receive buffers */
#define UB_FR_ID_INV		0x24	/* Frame ID invalid */
#define UB_FL_COMP		0x25	/* Flush completed */
#define UB_FR_TBL_OVRFL 	0x26	/* Frame table overflow */


/*
 * pcdpl - PC Disk Paramater List
 *
 * The following structure is used by disk i/o functions in the PC
 * code. The structure is filled out by the Unix device drivers
 * and operated on by the PC. The Unix code maintains it's own copy
 * of this structure. The address of the pcdpl in Unix memory is
 * placed into the cbcb_ent[HDENT].unix_cb by the Unix device driver.
 * This address is saved in  a pcqe (pc queue entry) when a Unix request
 * is sent to the PC. When the PC is ready to service this request
 * it copies the contents of the Unix pcdpl to local storage in the
 * PC.
 *
 * Warning: Code in dio.c is dependent on the order of this structure.
 */

struct pcdpl
{				/* disk parameter list for FD and HD */
	u_short         op_code;/* operation code */
	u_short         drive;	/* drive number (0,1) FD   (0x80,0x81) HD */
	u_short         head;	/* head or track number */
	u_short         cyl;	/* cylinder number */
	u_short         sector;	/* sector number */
	u_short         number;	/* number of sectors to operate on */
	u_long          atr_addr[32];	/* tcw entries */
	u_short         atr_cnt[32];
};

/* drive_status defines used for floppy disk*/
#define FD5LO	0x0000
#define FD5HI	0x0001
#define FD3LO	0x0002
#define FD3HI	0x0003
#define FDWP	0x0100

/* flag defines */
#define HDINFO_PRESENT	0x0001	/* drive present */
#define HDINFO_BADBLOCK 0x0002	/* bad block table read succesfully */
#define HDINFO_42PART	0x0004	/* 4.3 partition present 	 */
#define HDINFO_NOBRPT	0x0010	/* No Boot Record Partition Table */

/*
 * The Following structure is used to queue PC requests.
 */
struct pcplq
{
	u_short         op;	/* Op code from cbcb */
	u_short         flags;	/* Status flags */
	u_long          unix_cb;/* Operation specific control block */
	struct cbcb    *cbcb;	/* the cbcb for this request */
};

typedef struct pcplq pcplq_t;
typedef struct pcdpl pcdpl_t;
typedef struct pcplq *pcplqaddr_t;
typedef struct pcdpl *pcdpladdr_t;



/* The following structure defines a single entry in the partition table
 *  (	 all the data associated with a single partition. )
 */
struct pent
{
	char            bootid;	/* field indicating partition is bootable */
	char            shd;	/* Head where partition starts */
	char            ssec;	/* Starting sector */
	char            scyl;	/* Starting cylinder */
	char            sysid;	/* system ID field */
	char            ehd;	/* Head where partition Ends */
	char            esec;	/* Ending sector */
	char            ecyl;	/* Ending cylinder */
	u_long          relsect;/* number of sectors preceeding partition */
	u_long          numsect;/* number of sectors allocated to a partition */

};

struct ptable
{

	struct pent     pt[4];
	u_short         signature;
};

/*
 * Used by the PC code to keep track of where the Unix partitions
 * start.
 */

struct rb_part
{
	u_short          pstart;	/* starting cyl of 4.3 partition */
	u_short          plen;	/* # of cyls in 4.3 partition */
	u_short		dos_start;	/* starting cyl of dos */
	u_short		dos_end;	/* ending cyl of dos */
};



#define PTOFFSET 0x1be		/* Offset in sector where table starts */
#define ACIS42	0xdb		/* System Id for 4.3		   */
#define PCIX 'u'		/* System Id for PC/IX             */
#define DOS12 1			/* System Id for DOS 12-bit FAT    */
#define DOS16 4			/* System Id for DOS 16-bit FAT    */
#define DOSEXT 5		/* System Id for extended DOS	   */
#define XENIX 2			/* System Id for XENIX (/root)	   */
#define XENIX_USR 3		/* System Id for XENIX (/usr)	   */
#define BOOT_FLAG 0x80		/* Value for Bootable Partition    */
#define VALID_SIG 0xaa55	/* Valid Partition Table Signature */

struct kbdata
{
	u_char          kbsc;
	u_char          kbstatus;
	u_char          cmd_dest;
	u_char          cmd_code;
	u_char          fwd_int;
};

#ifndef ABIOS
struct hdgood
{
	u_short         cyl;
	u_char          hd;
	u_char          sec;
};
#endif /* ABIOS */

#define MAXBADBLOCKS 100

struct bbt_entry
{
	u_long          hdbad;
#ifndef ABIOS
	struct hdgood   hdgood;
#else  /* ABIOS */
	u_long		hdgood;
#endif /* ABIOS */
};


struct bbt
{
	u_short         numbad;
	struct bbt_entry bbt_entry[MAXBADBLOCKS];
};


union pcmem
{
	paddr_t         vector;	/* Double word	 */
	struct
	{
		u_short         offset;
		u_short         segment;
	}               os;
	char            byte[4];
};


/*
 * Characteristics of drives attached to system
 *   Used by: loadboot(), getdiskgeometry(), diskio(), write_config()
 */
struct drvparm
{
	unsigned        maxcyl, maxhd, maxsec;
};

struct dio_rtn_codes
{
	u_short         errno;
	u_short         pad;
	u_long          badblock;
};


#define SIZE_DD  256
#define SIZE_UD  (16 * 1024)

struct ubuff
{
	u_long          size_disp_data;	/* 4 bytes   */
	u_long          size_usr_data;	/* 4 bytes   */
	char            display_data[SIZE_DD];
	char            usr_data[SIZE_UD];
};


/*
 * Structuers used by biosreq() routine
 */

/* word registers */

struct wordregs
{
	u_short         ax, bx, cx, dx, si, di, bp;
	short           cflag;
};


/* byte registers */

struct byteregs
{
	u_char          al, ah, bl, bh, cl, ch, dl, dh;
};

/* general purpose registers union - overlays the corresponding word and
 * byte registers.
 */

union regs
{
	struct wordregs x;
	struct byteregs h;
};


/* segment registers */

struct sregs
{
	u_short         es, cs, ss, ds;
};


struct bios_int
{
	u_short         intr;
	u_short         finished;
	u_short         valid_reg;
	union regs      gen_reg;
	struct sregs    seg_reg;
};

struct XCLOCK
{
	unsigned char   sec;
	unsigned char   sal;
	unsigned char   min;
	unsigned char   mal;
	unsigned char   hrs;
	unsigned char   hal;
	unsigned char   dow;
	unsigned char   dom;
	unsigned char   mon;
	unsigned char   year;
	unsigned char   a;
	unsigned char   b;
	unsigned char   c;
	unsigned char   d;
};



struct msdata
{
	u_char          status;	/* mouse data presence, yes = 1, no = 0   */
	u_char          type;	/* data report (0) or command response (1) */
	u_char          exit_stat;	/* command exit status (CY)		  */
	/* success = 0, failure = 1		  */
	u_char          error;	/* command error code (AH), no error =0   */
	u_char          report[3];	/* data report or command bytes
					 * requested */
};				/* When  type = 1			  */
 /* report[0] has First Paramater	  */
 /* report[1] has second		  */
 /* report[2] has third		  */

struct pcms_cmd
{
	u_char          cmd;	/* mouse command code (AL)	 */
	u_char          param;	/* command parameter (BH)	 */
};

struct pcspk_cmd
{
	u_char          vol;	/* speaker volume (0 = off nonzero = full) */
	u_char          freqhigh;	/* hi frequency byte */
	u_char          freqlow;/* low frequency byte */
	u_char          pad;	/* unix alligns the short... */
	u_short         duration;	/* time delay */
};

struct spkdata
{
	u_char          status;
};

#define MAXINTQ 100

struct intque
{
	int             head;
	int             tail;
	int             irqlvl[MAXINTQ];	/* the irq lvl */
	int             fromintlvl[MAXINTQ];	/* from int flag */
	struct cbcb    *cbcb[MAXINTQ];		/* the proper cbcb */
};

#define MAXKBBUFF 512

struct kbqueue
{
	int             head;
	int             tail;
	u_short         buff[MAXKBBUFF];
};

#define MAXMSBUFF 256

struct msqueue
{
	int             head;
	int             tail;
	struct msdata   buff[MAXMSBUFF];
};

struct mask_int
{
	char            master;
	char            slave;
};


/********************* PCIF REGISTER DEFINES ****************************/



#define R_WIND1 0		/* window pointer 1 in ROMP memory */
#define R_WIND2 1		/* window pointer 2 in ROMP memory */
#define R_WIND3 2		/* window pointer 3 in ROMP memory */
#define R_WIND4 3		/* window pointer 4 in ROMP memory */

#define P_CTRL	6		/* PCIF control register */
#define P_BUF1	0x00		/* buffer mode for window 1 */
#define P_BUF2	0x01		/* buffer mode for window 2 */
#define P_BUF3	0x02		/* buffer mode for window 3 */
#define P_BUF4	0x03		/* buffer mode for window 4 */
#define P_ECCON 0x04		/* ECC enable */
#define P_DIAG	0x05		/* diagnostic mode on */
#define P_2WIND 0x06		/* use 2 windows */
#define P_4WIND 0x07		/* use 4 windows */

#define P_STAT	7		/* PCIF status register */
#define P_OIP	0x80		/* ROMP operation in progress */
#define P_ECCE	0x40		/* ECC error */
#define P_ICA	0x20		/* illegal coprocessor address */
#define P_IAP	0x10		/* illegal adderss mapping */
#define P_PCT	0x08		/* PC time-out */
#define P_MBE	0x04		/* multiple bit error */
#define P_PBP	0x02		/* PC bus preemption */
#define P_OK	0x00		/* everything is O.K. */

#define P_BASE	8		/* base address register */

#define P_ECCR	9		/* ECC register */

#define P_CONF	10		/* PCIF configuration register */
#define P_ATM	0x80		/* AT mode (coprocessor present) */

#define P_TCE	0x40		/* timeout count enabled */
#define P_PAR	0x20		/* parity mode enabled */
#define MEMSIZE(base) inp((base)+P_CONF) & 0x0f	/* # of meg of ROMP memory */

#define R_CLOCK 12		/* ROMP clock register */

#define R_CPOR	0x00		/* clock POR */
#define R_RSET	0x01		/* ROMP reset */
#define R_DBS	0x02		/* debug stop */
#define R_STEP	0x03		/* ROMP step */
#define R_ISE	0x04		/* instruction step enable */
#define R_FRW	0x05		/* register file read/write */
#define R_SCAN	0x06		/* ROMP scangate in */
#define R_T1T3	0x07		/* ROMP T1,T3 disable */

#define R_CTRL	13		/* ROMP control register */
#define R_HOLD	0x00		/* PC Hold RSC */
#define R_IPLC	0x01		/* IPL Complete */
#define R_MM	0x02		/* Master Mode */
#define R_INTL	0x04		/* Interleaved mode */
#define R_IREQ	0x06		/* PC Interrupt request */
#define R_IENAB 0x07		/* PC Interrupt enable */

#define R_INTR	14		/* PC -> ROMP interrupt register */
#define R_INT0	0x00		/* level 0 interrupt request */
#define R_INT1	0x01		/* level 1 interrupt request */
#define R_INT2	0x02		/* level 2 interrupt request */
#define R_INT3	0x03		/* level 3 interrupt request */
#define R_INT4	0x04		/* level 4 interrupt request */
#define R_INT5	0x05		/* level 5 interrupt request */
#define R_INT6	0x06		/* level 6 interrupt request */
#define R_INT7	0x07		/* trap    interrupt request */

#define R_INT3SET (0x80 >> R_INT3)
#define R_INT4SET (0x80 >> R_INT4)

#define R_STAT	15		/* ROMP status register */
#define R_IPLR	0x80		/* IPL ready */
#define R_CLKST 0x40		/* Clock stopped */
#define R_WAIT	0x20		/* ROMP wait */
#define R_FAIL	0x10		/* ROMP failure */
#define R_SYNC	0x08		/* ROMP sync */
#define R_ICMP	0x04		/* Instruction Complete */
#define R_DGO	0x02		/* ROMP  DGO */
#define R_STOP	0x01		/* ROMP Stop */




/************************  MISC DEFINES **********************************/

#define INTVEC_0  0x00000000
#define INTVEC_1  0x00000004
#define INTVEC_2  0x00000008
#define INTVEC_3  0x0000000c
#define INTVEC_4  0x00000010
#define INTVEC_5  0x00000014
#define INTVEC_6  0x00000018
#define INTVEC_7  0x0000001c

#define INTVEC_8  0x00000020
#define INTVEC_9  0x00000024
#define INTVEC_A  0x00000028
#define INTVEC_B  0x0000002c
#define INTVEC_C  0x00000030
#define INTVEC_D  0x00000034
#define INTVEC_E  0x00000038
#define INTVEC_F  0x0000003c
#define INTVEC_1C 0x00000070
#define INTVEC_70 0x000001c0
#define INTVEC_71 0x000001c4
#define INTVEC_72 0x000001c8
#define INTVEC_73 0x000001cc
#define INTVEC_74 0x000001d0
#define INTVEC_75 0x000001d4
#define HDVEC 0x76
#define INTVEC_76 0x000001d8
#define INTVEC_77 0x000001dc

#define INTMAST 0x20
#define INTSLAVE 0xa0
#define ISRREG 0x0b
#define INTEOI 0x60

#define IRQ0	0x01
#define IRQ1	0x02
#define IRQ2	0x04
#define IRQ3	0x08
#define IRQ4	0x10
#define IRQ5	0x20
#define IRQ6	0x40
#define IRQ7	0x80

#define ERR_BADADDR  0x8100


#define ESC 27
#define CR  13

#define READ 2
#define WRITE 3
#define BLOCKMOVE 0x8700
#define EMINT 0x15

#define RMEM	0x00000804

#define PCPLBUSY    0x0001	/* The op is being processed */
#define PCPLREQUEST 0x0002	/* The op has been queued    */
#define UBBUSY		0x0001
#define UBREQUEST	0x0002


#define REBOOT 0x1ff

#define IRQBIT(n) (1<<(n))		/* convert bit number to mask bit */

#define EOIPENDING 0x40			/* if we are waiting from ROMP */
#define QEOIPENDING 0x20		/* if romp will tell us */

struct debug_info {
char far       *faraddr;	/* far pointer to item */
u_long		offset;		/* offset in memory */
short		size;		/* size of each element */
short		count;		/* number of items in vector */
};

#define TRACE_PCPLQ	0
#define TRACE_PTR	1
#define TRACE_BUF	2
#define TRACE_END	3

#define OPTION_MSASY    	0x1	/* if using asy mouse */
#define OPTION_MSCOM2   	0x2	/* if mouse on com2 */
#define OPTION_CBCB		0x4	/* if on don't pass on cbcb requests */
#define OPTION_BLOCKMOVE	0x8	/* use BIOS block move function */
#define OPTION_QEOI		0x10	/* Q EOI requests instead of waiting */
#define OPTION_NOKBD		0x20	/* don't issue keyboard commands */
#define OPTION_ASCII		0x40	/* use ascii mode for keyboard */
#define OPTION_SCAN1		0x80	/* using Scan code set 1 */
#define OPTION_NOCLOCK		0x100	/* don't use sysclock */
#define OPTION_AT		0x200	/* AT support */
#define OPTION_OLDKBD		0x400	/* intercept keyboard at IRQ 1 */
#define OPTION_CLOCK		0x1000	/* don't update clock from cmos */
#define OPTION_NOMS		0x2000	/* ignore mouse commands */
#define OPTION_NOINT		0x4000	/* poll for op code only */
#define OPTION_PRINT		0x8000	/* log pc code mesages to the printer */
#define OPTION_NOEXIT		0x10000	/* don't exit (is SHELL) */
#define OPTION_FD		0x20000	/* indicate boot from floppy */
#define OPTION_HD		0x40000	/* indicate boot from hard disk 0 */
#define OPTION_NOSAVEUB		0x80000	/* don't save/restore UB state */
#define OPTION_AUTOIPL		0x100000/* automatically IPL slave cpu's */
#define OPTION_ONE_DISK		0x400000/* one disk per cpu (OS/2) */


/* take over an interrupt vector and save the old contents */
#if defined(MS_CL_5) && defined(DOSVECTOR)
typedef (_CDECL interrupt far * _CDECL intr_function)();
#define TAKE_VECTOR(vec, old, new)		\
	{ old = (u_long) _dos_getvect(vec);	\
	RESET_VECTOR(vec, new); }
#define RESET_VECTOR(vec, new)	\
	_dos_setvect(vec, (intr_function) new)
#else
#define TAKE_VECTOR(vec, old, new)		\
	{ old = pcmem[vec].vector; \
	RESET_VECTOR(vec, new); }
#define RESET_VECTOR(vec,new) \
	pcmem[vec].vector = (u_long) new
#endif /* MS_CL_5 && DOS */


/*
 * macro to align a pointer to a given boundary which must be a power
 * of two. near pointers can use 'short' as a type, far pointers should
 * specify 'long'.
 */
#define align(pointer, bdy, type) (((type) (pointer) + (bdy) - 1) & ~((bdy) - 1))

/*
 * the follow structures define the stack frames used in the various interrupt
 * handlers. Most handlers are only interested in the i_stack stuff. The last
 * half of the i_stack struct is only valid in the sysclock routine. Since
 * sysclock is called by bios, the stack frame only describes the bios stack.
 * the rest of the defines allow us to get to the original stack when the clock
 * tick came in.
 */
struct i_stack {
	/*
	 * the following is the stack frame as.asm builds to save the
	 * world. (this is done on the "interrupted process's" stack.
	 * The value of the stack is passed in as a parameter.)
	 */
	short	new_flags;			/* flags after intr */
	short	DI,SI,BP,SP,BX,DX,CX,AX;	/* pusha */
	short	ES;				/* push es */
	short	DS;				/* push ds */
	/*
 	 * these are put on the stack by the hardware (hardware int) or
	 * the INTx command.
	 */
	short	IP,CS,flags;			/* interrupt */
	/*
	 * this is the stack frame built by the bios system clock interrupt
	 * handler.
	 */
	short	b_DX,b_CX,b_AX,b_ES,b_DS;
	/*
	 * again the hardware/intx command. this time it was faked by
	 * the dos interrupt handler.
	 */
	short	b_IP,b_CS,b_flags; 
	/*
	 * this is the stack frame built by the dos interrupt handler.
	 * (points to a sys_stack_save structure in "old_stack"'s segment.)
	 */
	short	d_stackptr;
};

/*
 * only used by sysclock. save area for the user's stack before bios switches
 * it.
 */
struct sys_stack_save {
	short	valid_flag;
	struct dos_sys_stack far *saved_stack;
};

/*
 * only used by sysclock. the user's stack frame just before bios switches
 * stacks.
 */
struct dos_sys_stack {
	short	ES,BP,AX,IP,CS,flags;		/* registers saved on
						 * the original stack.
						 */
};
