/*
 * P_R_P_Q_# (C) COPYRIGHT IBM CORPORATION 1987
 * LICENSED MATERIALS - PROPERTY OF IBM
 * REFER TO COPYRIGHT INSTRUCTIONS FORM NUMBER G120-2083
 */
/* $Header: ioim.h,v 12.1 89/05/12 11:44:14 triha Exp $ */
/* $Source: /ibm/acis/usr/sys/ca/RCS/ioim.h,v $ */

#if !defined(lint) && !defined(LOCORE) && defined(RCS_HDRS)
static char *rcsidioim = "$Header: ioim.h,v 12.1 89/05/12 11:44:14 triha Exp $";
#endif

#ifdef ROMPC

/*
 * For initialization purposes, each IOR in the range 0x80XXXX addresses
 * the I/O Base Address register of a particular IOIM, etc.  So, the
 * way the board the ROMPC is on is wired, IOIM1 ALWAYS listens to
 * addresses like 0x80xYxx (where "Y&4 == 4") as being the address of
 * IOIM1's I/O Base Address register is.
 */

#define IOIM1_BASE	0x800400	/* base address for IOIM1 */
#define IOIM2_BASE	0x800100	/* base address for IOIM2 */

#define IOIM1		0x900000	/* IOIM1 normal address */
#define IOIM2		0x910000	/* IOIM2 normal address */

#define BUS1		0xa0		/* bus base */
#define BUS2		0xb0		/* bus base */

#define IOIM_BASE	0		/* offset to base register */
#define IOIM_MISC_0	1		/* misc control register 0 */
#define IOIM_REPLY	1		/* LAST PMUC reply register */
#define IOIM_MISC_1	2		/* misc control register 1 */
#define IOIM_SUB_SEG_1	3		/* sub-segment control 1  */
#define IOIM_SUB_PMUC	3		/* PMUC SUBSEGMENT PRESENT */
#define IOIM_SUB_SEG_2	4		/* sub-segment control 2 */
#define IOIM_SUB_PROB	4		/* PROBLEM STATE SUBSEGMENT */
#define IOIM_SUB_SEG_3	5		/* sub-segment control 3 */
#define IOIM_SUB_XLATE	5		/* XLATE bit for OUTGOING REQ */
#define IOIM_SUB_SEG_4	6		/* sub-segment control 4 */
#define IOIM_SUB_COPROC	6		/* CoProcessor active */
#define IOIM_SUB_SEG_5	7		/* sub-segment control 5 */
#define IOIM_SUB_LOEND	7		/* lo-end device mode */
#define IOIM_GCR	8		/* general control register */
#define IOIM_IRQ	9		/* interrupt request */
#define IOIM_ZSSP	10		/* bus SubSegment Present */
#define IOIM_GSR	11		/* general status register */
#define IOIM_SSCR	12		/* Special Subsegment Control Register */
#define IOIM_MCC	13		/* Miscellaneous Chip Configuration */
#define IOIM_CPS	14		/* CoProcessor Status */
#define IOIM_LASTOP	15		/* Last 68881 OP */

/* following are in GCR */
#define IOIM_ENABLE_INT		0x01	/* enable interrupts */
#define IOIM_2_CYCLE		0x02	/* two cycle memory */
#define IOIM_NO_SERIALIZE	0x04	/* don't serialized errors */
#define IOIM_NOPARITY		0x08	/* disable bus parity checks */
#define IOIM_IPL_READY		0x80	/* ipl ready */
#define IOIM_IPL_COMPLETE	0x100	/* ipl complete (IOIM1) */
#define IOIM_LOOPMODE		0x100	/* enable loop mode (IOIM2) */
#define IOIM_NO_DMA_CACHE	0x200	/* disable dma read cache */
#define IOIM_HOG_BUS		0x400	/* suspends fairness in arbitration */

/* following are in GSR (General Status Register) */
#define IOIM_EXTERNAL_INT	0x0001	/* reflects state of external interrupt  request */
#define IOIM_PMUC_DMA		0x0002	/* exception on request to RCS but not reportable (real plannar DMA) */
#define IOIM_BAD_PARITY		0x0004	/* bad parity detect on reply from PMUC */
#define IOIM_DISAPEARED		0x0008	/* request disappeared on PMUC */
#define IOIM_EXCEPTION		0x0010	/* exception reply to reqest sent to PMUC , plus I/O TRAP sensed */
#define IOIM_PARITY_ERROR	0x0020	/* parity error was signalled in response to request sent to PMUC */
#define IOIM_EXCEPT_REPLY	0x0040	/* exception reply sent to PMUC */
#define IOIM_NO_RESPONSE	0x0080	/* no response to a request sent to PMUC */
#define IOIM_REPLY_OUT		0x0100	/* BUS reply was outstanding when reset packet came */
#define IOIM_REPLY_ROMP		0x0200	/* Error signaled by ROMP in attempt to return reply */
#define IOIM_REPLY_ERR		0x0400	/* Error detect in reply from BUS */
#define IOIM_REPLY_IND		0x0800	/* Error indication in reply from BUS */
#define IOIM_PARITY_REC		0x1000	/* bad parity was signaled by receiver of an outstanding request; aborted */
#define IOIM_PARITY_PMUC		0x2000	/* bad parity was received on PMUC data; aborted */
#define IOIM_EXCEPT_ROMP	0x4000	/* exception return on a request from romp */
#define IOIM_NO_ZACK		0x8000	/* request sent to BUS received no Zack */
#define IOIM_NOT_REPORTED	0x10000	/* exception not reported for I/O Wrt or Real Wrt */

/* The following are in the Coprocessor Status Register */

	    /* No response to a request sent to PMUC */
#define	IOIM_CPS_PMUC_TIMEOUT		0x80
	    /* Exception reply to a request sent to PMUC */
#define	IOIM_CPS_PMUC_EXCEPTION		0x40
	    /* Parity Error was signaled in response to a request sent to PMUC */
#define	IOIM_CPS_PMUC_PARITY		0x20
	    /* Exception reply to a request sent to PMUC, plus I/O Trap sensed */
#define	IOIM_CPS_PMUC_EXCEPT_IOTRAP	0x10
	    /* Request disappeared on PMUC */
#define	IOIM_CPS_PMUC_DISAPPEARED 	0x08
	    /* Bad parity detected on reply from PMUC */
#define	IOIM_CPS_PMUC_REPLY_PARITY	0x04
	    /* EXCEPTION REPORTED BY 68881 */
#define	IOIM_CPS_68881_EXCEPTION	0x02
	    /* Last 68881 operation not completed */
#define	IOIM_CPS_68881_BUSY		0x01

#define IOIM_CPS_MASK			0xfe	/* mask for error conditions */

#define CPS_FMT "\20\1MC881-BUSY\2MC881-EXCEPTION\3PMUC-REPLY-PARITY\4PMUC-DISAPPEARED\5PMUC-EXCEPT-IOTRAP\6PMUC-PARITY\7PMUC-EXCEPTION\10PMUC-TIMEOUT"

/* IOIM subsegment numbers for use in subsegment control registers */
#define SEG_0	0x8000
#define SEG_1	0x4000
#define SEG_2	0x2000
#define SEG_3	0x1000
#define SEG_4	0x0800
#define SEG_5	0x0400
#define SEG_6	0x0200
#define SEG_7	0x0100
#define SEG_8	0x0080
#define SEG_9	0x0040
#define SEG_A	0x0020
#define SEG_B	0x0010
#define SEG_C	0x0008
#define SEG_D	0x0004
#define SEG_E	0x0002
#define SEG_F	0x0001

#define IOIM2_MISC_0	0xb		/* XXX */
#define IOIM2_MISC_1	0xbfe0		/* value for IOIM2 MISC register 1 */
#define IOIM2_VALUE1	SEG_C+SEG_D	/* PMUC sub-segment present */
#define IOIM2_PROB_ENABLE	SEG_C+SEG_D	/* allow problem state access */
#define IOIM2_PROB_DISABLE	0	/* disallow problem state access */
#define IOIM2_VALUE3	SEG_C+SEG_D	/* xlt bit for outgoing requests */
#define IOIM2_VALUE4	SEG_C		/* coprocessor mode active */
#define IOIM2_VALUE5	SEG_C+SEG_D	/* low-end device mode */
#define IOIM2_MCC	0x22		/* set TAG and ARB */

#define EX_L	0
#define EX_LM	1
#define EX_IOR	2
#define EX_LHA	3
#define EX_ST	4
#define EX_STM	5
#define EX_IOW	6

#define EX_BYTE	0
#define EX_HALF	1
#define EX_WORD	2
#define EX_TS	3

#define EX_CANCELLED 0x01

#define EX_GETOP(reg) (((reg)>>3) & 07)		/* get op type field */
#define EX_GETLEN(reg) (((reg)>>6) & 03)	/* get length field */
#define EX_GETREG(reg) (((reg)>>8) & 0x0f)	/* get register field */
#define IS_IOR_IOW(reg) (((reg>>3) & 03) == EX_IOR)	/* special case for IOR/IOW */
#define IS_STORE(reg) ((reg) & (EX_ST<<3))
		    /* GETSUBSEG() is defined in mmu.h */
#define IS_IOCC(reg) (GETSUBSEG(reg) == 0 || GETSUBSEG(reg) == 4)
#define IS_68881(reg) (GETSUBSEG(reg) == 0x0c || GETSUBSEG(reg) == 0x0d)
#define IS_FLOAT(reg) (GETSUBSEG(reg) >= 0x0c)
#define IS_FPA(reg) (GETSUBSEG(reg) == 0x0e || GETSUBSEG(reg) == 0x0f)
#define IS_CANCELLED(reg) ((reg)&EX_CANCELLED)
/**/
/*
 * The following describes IOIM2 which is
 * used in conjunction with the MC68881.
 */

/*
 * The IOIM will talk with the MC68881 in either of two modes.
 * In hardware assisted mode, the IOIM "knows" something about
 * the MC68881; in software control mode, everything is done
 * by software.  The IOIM distinguishes between these two
 * modes by what address (range) is used to address it.
 */

#define IOIM_881_HW_BASE	0xfc000000	/* hardware assisted mode */
#define	IOIM_881_SW_BASE	0xfd000000	/* software control mode */

/*
 * In software control mode, the mc881.h file should be consulted.
 *
 * In hardware assist mode, the address which is accessed on the
 * IOIM has semantics as follows:
 */

#define	IOIM_881_XFER_PATH_SHIFT		18
#define	IOIM_881_XFER_PATH_TO_881		(0x0<<IOIM_881_XFER_PATH_SHIFT)
#define	IOIM_881_XFER_PATH_LENGTH_REGISTER	(0x7<<IOIM_881_XFER_PATH_SHIFT)
#define	IOIM_881_XFER_PATH_FROM_881		(0xf<<IOIM_881_XFER_PATH_SHIFT)

#define	IOIM_881_COMMAND_SHIFT		2	/* shift command 2 bytes */
#define	IOIM_881_COMMAND_MASK		0xffff	/* BEFORE shift */

#define	IOIM_881_LENGTH_NONE		0x0	/* No data to be transferred */
#define	IOIM_881_LENGTH_1_WORD		0x1	/* Transfer 1 word */
#define	IOIM_881_LENGTH_2_WORDS		0x2	/* Transfer 2 words */
#define	IOIM_881_LENGTH_N_WORDS		0x3	/* Use length register */

/*
 * To do writes (and reads), we define macros.
 */

#define	IOIM_881_WRITE(path,command,length,value) \
    (*(u_int *) \
	(IOIM_881_HW_BASE|(path)|(command<<IOIM_881_COMMAND_SHIFT)|(length))) \
								= (value)
#define	IOIM_881_READ_LENGTH_REGISTER() \
    (*(u_int *) (IOIM_881_HW_BASE \
	|IOIM_881_XFER_PATH_LENGTH_REGISTER|0|(IOIM_881_LENGTH_N_WORDS)))\

#define	IOIM_881_WRITE_LENGTH_REGISTER(length) \
    IOIM_881_WRITE \
	(IOIM_881_XFER_PATH_LENGTH_REGISTER, 0, IOIM_881_LENGTH_N_WORDS, length)

#endif ROMPC
