/* rcsid[]="$Header: rfreg.h,v 820.1 86/12/04 19:56:18 root Exp $" */
/* sccsid[]="%W% %Y% %Q% %G%" */

/************************************************************************
*									*
*				Copyright 1984				*
*			VALID LOGIC SYSTEMS INCORPORATED		*
*									*
*	This listing contains confidential proprietary information	*
*	which is not to be disclosed to unauthorized persons without	*
*	written consent of an officer of Valid Logic Systems 		*
*	Incorporated.							*
*									*
*	The copyright notice appearing above is included to provide	*
*	statutory protection in the event of unauthorized or 		*
*	unintentional public disclosure.				*
*									*
************************************************************************/

/*
 * Rimfire 44/45 controller
 */

/*
 * The Rimfile controller uses 8086 style addresses.
 * We declare these address fields as longs, and use a macro
 * to convert 68000 addresses into 8086 addresses.
 */
#define rfsetaddr(v, a)	(((short *)&(v))[0] = (int)(a), \
				((short *)&(v))[1] = ((int)(a) & 0xf0000) >> 4)
#define rfpage(a)	((int)(a) >> 20)

struct rf_device {
	char rf_reset;
	char rf_atten;
};

	/* system configuration pointer */
struct rf_scp {
	u_char scp_unused;
	u_char scp_bus;		/* width of future dma transfers */
	u_long scp_addr;	/* address scb */
};

#define SCPBUS_8	0x00	/* 8 bit dma */
#define SCPBUS_16	0x01	/* 16 bit dma */

/*
 * The scp address is well known and shared between all controllers.
 */
#define RF_SCP		((struct rf_scp *)0x3fe6)

	/* system configuration block */
struct rf_scb {
	u_char scb_unused;
	u_char scb_03;		/* must be 0x03 */
	u_long scb_addr;	/* address of ccb */
};

	/* channel control block */
struct rf_ccb {
	u_char ccb_gate;
	u_char ccb_ccw;		/* channel control word */
	u_long ccb_addr;	/* address of parameter block */
	u_short ccb_00;		/* must be 0x00 */
};

#define CCBGATE_OPEN	0x00
#define CCBGATE_CLOSED	0xff
#define CCBCCW_NORMAL	0x11
#define CCBCCW_CLRINT	0x09

	/* disk parameter block */
struct rf_dp {
	u_short dp_cmd;		/* command */
	u_char dp_page;		/* address bits 23 to 20 */
	u_char dp_head;		/* head select */
	u_short dp_ctl;		/* command control information */
	u_short dp_cyl;		/* cylinder select */
	u_short dp_sec;		/* sector select, starts at 1 */
	union {
		u_short Dp_nsec;	/* number of sectors to transfer */
		u_char Dp_sense[2];	/* sense bytes */
	} dp_un;
#define dp_nsec dp_un.Dp_nsec
#define dp_sense dp_un.Dp_sense
	u_long dp_addr;		/* buffer address */
	u_char dp_cst;		/* controller status */
	u_char dp_dst;		/* drive status */
	u_long dp_link;		/* linked parameter block address */
	u_long dp_bcount;	/* transfer byte count, used by driver only */
};

	/* tape parameter block */
struct rf_tp {
	u_short tp_cmd;		/* command */
	u_char tp_page;		/* address bits 23 to 20 */
	u_char tp_unused;
	u_short tp_ctl;		/* command control information */
	u_short tp_retcnt;	/* return count */
	u_short tp_bufsiz;	/* buffer size */
	u_short tp_nrec;	/* number of records to seek */
#define tp_mst tp_nrec		/* micro status for cartridge tape */
	u_long tp_addr;		/* buffer address */
	u_char tp_cst;		/* controller status */
	u_char tp_dst;		/* drive status */
	u_long tp_link;		/* linked parameter block address */
};

	/* parameter block */
union rf_pb {
	struct rf_dp pb_d;
	struct rf_tp pb_t;
};

	/* disk commands */
#define DPCMD_CONFIG	0x00
#define DPCMD_STATUS	0x04	/* read status */
#define DPCMD_LOAD	0x18
#define DPCMD_UNLOAD	0x1c
#define DPCMD_RESET	0x6c
#define DPCMD_SEEK	0x78
#define DPCMD_READID	0x7c
#define DPCMD_INTERR	0x88	/* interrogate disk */
#define DPCMD_TEST	0x8c	/* test controller to disk interface */
#define DPCMD_RWPERMIT	0x98	/* set read and write permissions */
#define DPCMD_MICRO	0xa4	/* execute disk micro */
#define DPCMD_ZERO	0xab	/* rezero drive */
#define DPCMD_READ	0x10
#define DPCMD_WRITE	0x14
#define DPCMD_FORMAT	0x24
#define DPCMD_MAP	0x84	/* map track */

	/* tape commands */
#define TPCMD_STATUS	0x28
#define TPCMD_READ	0x2c
#define TPCMD_WRITE	0x30
#define TPCMD_REWIND	0x34
#define TPCMD_WRITEFM	0x40	/* write filemark */
#define TPCMD_ERASETAPE	0x50
#define TPCMD_RESET	0x90	/* drive reset */
	/* mag tape only */
#define TPCMD_OFFLINE	0x38
#define TPCMD_EDIT	0x3c
#define TPCMD_SEARCHFM	0x44	/* search filemark */
#define TPCMD_SPACE	0x48	/* space, not terminated by filemark */
#define TPCMD_ERASE	0x4c
#define TPCMD_SPACEF	0x70	/* space, terminated by filemark */
#define TPCMD_SEARCHMFM	0x94	/* search multiple filemark */
	/* cartridge tape only */
#define TPCMD_RETENSION	0x38
#define TPCMD_ERRCNT	0x3c	/* report error counters */
#define TPCMD_SPACEFM	0x48	/* space n filemarks */
#define TPCMD_RBREAD	0x70	/* ring buffer read */
#define TPCMD_RBWRITE	0x74	/* ring buffer write */
#define TPCMD_PASS	0xb4	/* pass command to the the drive */
#define	TPCMD_OETRM	0x4c	/* terminate open ended sequence */

	/* disk and tape common commands */
#define CMD_ID		0x20	/* return board id in dst */
#define CMD_CLRINT	0x9c	/* clear interrupt */

	/* dp_ctl and tp_ctl bits */
#define CTL_DS		0x0007	/* unit select, disk */
#define CTL_NORETRY	0x0008	/* retry disable */
#define CTL_MBOX	0x0010	/* mailbox interrupt enable */
#define CTL_INTR	0x0020	/* interrupt enable */
#define CTL_LINK	0x0040	/* link enable */
#define CTL_BUSLOCK	0x0080	/* bus lock enable */
#define CTL_TS		0x0300	/* unit select, tape */
#define CTL_TSSHIFT	8
#define CTL_INTRLV	0x0400	/* auto-interleave on format, disk */
#define CTL_REVERSE	0x0400	/* reverse direction, tape */
#define CTL_SD		0x0800	/* high speed or low density, tape */
#define CTL_CONTINUOUS	0x1000	/* continuous, tape */
#define CTL_ITBL	0x2000	/* calculate interleave table, disk */
#define CTL_NOMAP	0x4000	/* ignore alternate mapping, disk */
#define CTL_16BIT	0x8000	/* do 16 bit bus transfer */
#define CTL_NORMAL	CTL_16BIT

	/* dp_cst and tp_cst bits */
#define CST_ENTERED	0x80	/* command entered */
#define CST_DONE	0x40	/* command completed */
#define CST_ERROR	0x3f	/* error code */
#define CST_BITS "\20\10ENTERED\7DONE"
	/* important error codes */
#define ERR_SOFT	0x01	/* success after retries */
#define ERR_DATACRC	0x02
#define ERR_IDCRC	0x03
#define ERR_EOT		0x09	/* end of tape mark encountered */
#define ERR_TIMEOUT	0x0f	/* timeout during tape read or write */
#define ERR_WPROTECT	0x11	/* tape is write protected */
#define ERR_FM		0x15	/* filemark encountered during read */
#define ERR_ILLPARAM	0x19	/* bad parameter in control block */
#define ERR_BLANK	0x27	/* blank tape when data expected */
#define ERR_OFFLINE	0x2a	/* tape drive is offline */

	/* dp_dst bits */
#define DPDST_NOTRDY	0x01	/* not ready */
#define DPDST_BUSERR	0x02	/* control bus error */
#define DPDST_ILLCMD	0x04	/* illegal command */
#define DPDST_ILLPARAM	0x08	/* illegal parameter */
#define DPDST_SENSE1	0x10	/* sense byte 1 active */
#define DPDST_SENSE2	0x20	/* sense byte 2 active */
#define DPDST_BUSY	0x40	/* busy */
#define DPDST_DONE	0x80	/* normal completion */
#define DPDST_BITS "\20\10DONE\7BUSY\6SENSE2\5SENSE1\4ILLPARAM\3ILLCMD\2BUSERR\1NOTRDY"

	/* dp_sense[0] (sense byte 1) bits */
#define DPSN1_CMDREJECT	0x20	/* command rejected */
#define DPSN1_SPEEDERR	0x10	/* speed error */
#define DPSN1_PERMITERR	0x08	/* read/write permit error */
#define DPSN1_PWERFAULT	0x04	/* power fault */
#define DPSN1_RWFAULT	0x02	/* read/write fault */
#define DPSN1_SEEKERR	0x01	/* seek error */
#define DPSN1_BITS "\20\6CMDREJECT\5SPEEDERR\4PERMITERR\3PWERFAULT\2RWFAULT\1SEEKERR"

	/* dp_sense[1] (sense byte 2) bits */
#define DPSN2_PROTAREA	0x40	/* positioned within write protected area */
#define DPSN2_ATTRMOD	0x20	/* attribute table modified */
#define DPSN2_RDYTRANS	0x02	/* ready transition */
#define DPSN2_INITIAL	0x01	/* initial state */
#define DPSN2_BITS "\20\7PROTAREA\6ATTRMODIFIED\2RDYTRANSITION\1INITIAL"

	/* tp_dst bits for mag tape */
#define TPDST_WRTPROT	0x02	/* write protect */
#define TPDST_FMTBUSY	0x04	/* formatter busy */
#define TPDST_RDY	0x08	/* drive ready */
#define TPDST_EOT	0x10	/* at end of tape */
#define TPDST_LOADPT	0x20	/* at load point */
#define TPDST_ONLINE	0x40	/* drive on line */
#define TPDST_FM	0x80	/* filemark detected */
#define TPDST_BITS "\20\10FM\7ONLINE\6LOADPT\5EOT\4RDY\3FMTBUSY\2WRTPROT"

	/* tp_dst bits for cartridge tape */
#define CPDST_OPENENDED	0x01	/* in open ended sequence */
#define CPDST_WRTPROT	0x04	/* write protect */
#define CPDST_FM	0x08	/* filemark detected */
#define CPDST_EOT	0x10	/* at end of tape */
#define CPDST_HASTAPE	0x20	/* cartridge in place */
#define CPDST_EXCEPT	0x40	/* exception active */
#define CPDST_RDY	0x80	/* drive ready */
#define CPDST_BITS "\20\10RDY\7EXCEPT\6HASTAPE\5EOT\4FM\3WRTPROT\1OPENENDED"

	/* tp_mst bits */
#define TPMST_FM	0x0001	/* file mark detected */
#define TPMST_BIE	0x0002	/* block in error not located */
#define TPMST_DATAERR	0x0004	/* data error */
#define TPMST_EOM	0x0008	/* end of media */
#define TPMST_WRTPROT	0x0010	/* write protect */
#define TPMST_OFFLINE	0x0020	/* drive off line */
#define TPMST_NOTAPE	0x0040	/* cartridge not in place */
#define TPMST_EX0	0x0080	/* exception byte 0 */
#define TPMST_RESET	0x0100	/* reset occurred */
#define TPMST_BOM	0x0800	/* beginning of media */
#define TPMST_NODATA	0x2000	/* no data detected */
#define TPMST_ILLCMD	0x4000	/* illegal command */
#define TPMST_EX1	0x8000	/* exception byte 1 */
#define TPMST_BITS "\20\20EX1\17ILLCMD\16NODATA\14BOM\11RESET\10EX0\7NOTAPE\6OFFLINE\5WRTPROT\4EOM\3DATAERR\2BIE\1FM"

	/* controller id, from CMD_ID */
#define ID_44		0x40	/* rimfire 44 */
#define ID_45		0x20	/* rimfire 45, manual says 0x30 */

/*
 * For cartridge tapes that support both QIC-11 and QIC-24
 * formats.  We use TPCMD_PASS to send a configure
 * command to the drive, right after initializing it.
 */
#define CP_QIC11	0x26
#define CP_QIC24	0x27

	/* cartridge tape ring buffer, for detached data block */
struct rf_rb {
	u_char rb_page;
	u_char rb_gate;
	u_short rb_bcount;
	u_long rb_link;
	u_long rb_addr;
};

	/* rb_gate bits */
#define RBGATE_RDY	0x01	/* buffer ready */
#define RBGATE_BUSY	0x02	/* tape busy */
#define RBGATE_DONE	0x04	/* tape complete */
#define RBGATE_FAULT	0x08	/* tape fault */
#define RBGATE_LAST	0x10	/* last block */
#define RBGATE_DTERM	0x20	/* disk terminate */
#define RBGATE_DETACH	0x40	/* detached data and header */
#define RBGATE_INTR	0x80	/* block interrupt */
#define RBGATE_NORMAL	(RBGATE_RDY|RBGATE_LAST|RBGATE_DETACH)
#define RBGATE_BITS "\20\10INTR\7DETACH\6DTERM\5LAST\4FAULT\3DONE\2BUSY\1RDY"

	/* disk record for DPCMD_CONFIG command */
struct rf_dr {
	u_char dr_type;
	u_char dr_nhead;
	u_short dr_nsec;
	u_short dr_ncyl;
	u_short dr_secsize;
};

	/* disk attributes from 00 to 03 */
struct rf_attr {
	u_char attr_model1;
	u_char attr_user;
	u_char attr_revision;
	u_char attr_model0;
};

	/* known attr_model0 values */
#define PRIAM3450	0x04
#define PRIAM7050	0x05
#define PRIAM806	0x0b
#define KEN7340		0xac
#define KEN7380		0xd4

	/* disk sector id */
struct rf_id {
	u_char id_cyl0;			/* cylinder number, byte 0 */
	u_char id_cyl1;			/* cylinder number, byte 1 */
	u_char id_sec0;			/* sector number, byte 0 */
	u_char id_sec1;			/* sector number, byte 1 */
	u_char id_head;			/* head number */
	u_char id_type;			/* track type */
};

	/* id_type values */
#define IDTYPE_NORMAL	0xaa		/* normal track */
#define IDTYPE_DEFECT	0xc3		/* defective track */
#define IDTYPE_ALT	0x3c		/* alternate track */
