/* static char rcsid[] = "$Header: rfreg.h,v 2.1 86/07/21 14:56:52 bog Exp $" */

/************************************************************************
 *									*
 *				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 		*
 *	Incoroporated.							*
 *									*
 *	The copyright notice appearing above is included to provide	*
 *	statutory protection in the event of unauthorized or 		*
 *	unintentional public disclosure.				*
 *									*
 ************************************************************************/


/*
 * Rimfire 44/45 controller.
 */

/*
 * Minor device configuration.
 *
 * For disks, the standard controller, drive, partition combinatio
 * is used.
 * For tapes, bits 0 and 1 are the drive number; bit 2, no rewind on
 * close; bit 3, 1600 bpi or QIC-24 format for mag tape or cartridge
 * tape, respectively; bits 4 to 7 are the controller number.
 *
 * Tape devices with odd numbered controllers are cartridge drives.
 * Usually, we have at most two controllers.  Controller 0 is always
 * a Rimfire 45; controller 1, a 44.
 *
 * By "drive number," we mean the number of a drive within a controller.
 * By "unit number," we mean the number of a drive ignoring controller
 * boundaries.  Thus, disk drive 2 on controller 1 is unit 6.
 *
 * The controller really supports eight disks.  But we never use
 * more than two The only place we need to know about all eight drives
 * is in the disk records for the configuration command.
 *
 * We must have exactly 16 partitions, to conform with DK_NSIZES
 * in dkioctl.h.
 */
#define NUMRFD	8		/* Number of RF Disks */
#define MAXDK	3

#define RD_NDRIVE	4		/* disks per controller */
#define RD_NUNIT	(RD_NDRIVE * NRF)
#define RT_NDRIVE	4		/* tapes per controller */
#define RT_NUNIT	(RT_NDRIVE * NRF)
#define RD_NDR		8		/* for allocating struct rf_dr */
/*
 * These things should really do minor(d) first,
 * but we know the minor device number is the low byte,
 * so we save a few instructions.
 */
#define rdctlr(d)	((u_char)(d) >> 6)
#define rdunit(d)	((u_char)(d) >> 4)
#define rddrive(d)	((d) >> 4 & 3)
#define rdpart(d)	((d) & 15)
#define rtctlr(d)	((u_char)(d) >> 4)
#define rtunit(d)	((d) & 3 | (u_char)(d) >> 2 & ~3)
#define rtdrive(d)	((d) & 3)
#define rdmkdev(c, d, p) ((c) << 6 | (d) << 4 | (p))
#define rtmkdev(c, d)	((c) << 4 | (d) << 2 & ~0xf | (d) & 3)
#define RT_NOREWIND	0x04
#define RT_1600BPI	0x08	/* 1600 bpi if mag tape */
#define RT_QIC24	0x08	/* QIC-24 format if cartridge tape */
#define RT_CTAPE	0x10	/* this is a cartridge tape */

/*
 * 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 */

	/* 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 */
#ifdef UNIX
	u_long dp_bcount;	/* transfer byte count, used by driver only */
#else UNIX
	u_char dp_dummy;	/* dummy char */
	u_char dp_endhead;	/* XBKUP/XRSTR -- end head */
	u_short dp_endcyl;	/* XBKUP/XRSTR -- end cyl */
	u_short dp_endsec;	/* XBKUP/XRSTR -- end sector */
#endif UNIX
};

	/* 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 sectors to transfer */
#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_NOPID	0x20
#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 */

/*
 * These aren't really disk commands but they do use the disk paramter
 * block structure...
 */
#define DPCMD_DUMP	0x54
#define DPCMD_RESTORE	0x58

	/* 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	/* from old driver */

	/* disk and tape common commands */
#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_INTERLEAVE	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_NORMAL	0x00
#define ERR_SOFT	0x01	/* success after retries */
#define ERR_DATACRC	0x02
#define ERR_IDCRC	0x03
#define ERR_DATA	0x0A
#define ERR_TIMEOUT	0x0f	/* timeout during tape read or write */
#define ERR_FM		0x15	/* filemark encountered during read */

	/* 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_OPENENDED	0x01	/* in open ended sequence */
#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\1OPENENDED"

	/* tp_dst bits for cartridge tape */
#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"

	/* 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"

/*
 * 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

	/* 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 */


/*
 * Bytes / cyl = (bytes / sector) * (sectors / track) * (heads / cyl)
 */
struct rim_dkinfo {
	u_short	modelnum;	/* Model number */
	u_char	type;		/* Type of drive */
	u_char  numhead;	/* Number of heads */
	u_short	spt;		/* Sectors / track */
	u_short numcyl;		/* Number of cyls */
	u_short numalt;		/* Number of alternates */
	u_short	bps;		/* Bytes / sector */
	u_long bpc;		/* Bytes / cyl */
	u_short buff_numhead;	/* Number of heads in a buffer */
	u_short buff_numsector;	/* Number of sectors in a buffer */
	u_short buff_totcyl;	/* Total number of sectors in a buffer */
	u_short buff_tothead;	/* Total number of heads in a buffer */
	u_short buff_totsector;	/* Total number of sectors in a buffer */
	char	*name;		/* ASCII name */
	struct dk_sizes sizes[DK_NSIZES];
};

struct rf_controller {
	u_short			rf_cst;		/* Cassette */
	u_short			*rf_unit;	/* Unit # */
	struct rim_dkinfo	**rf_dtable;	/* Disk table */
	char			*rf_name;
	struct rf_device	*rf_device;	/* Device */
	struct rf_scp		*rf_scp;	/* Sys Config Ptr */
	struct rf_scb		*rf_scb;	/* Sys Config Block */
	struct rf_ccb		*rf_ccb;	/* Chan Cntrl Block */
	union  rf_pb		*rf_pb;		/* Param Block */
	struct rf_dp		*rf_dp;		/* Disk Param Block */
	struct rf_tp		*rf_tp;		/* Tape Param Block */
	u_char 			*rf_dr;		/* Disk record for CONFIG */
	struct rf_rb		*rf_rb1;	/* Cassettte ptr 1 */
	struct rf_rb		*rf_rb2;	/* Cassettte ptr 2 */
};

/*
 *#define CYL(p)  (p * Rimi->dki_maxsect * (Rimi->dki_maxhead + 1))
 *		 Information for /dev/rrim16...
 */
#define CYL3450(p)	((daddr_t) ((p) * 23 * (4+1)))
#define CYL806(p)	((daddr_t) ((p) * 32 * (11+1)))

#define RIM44_ID    0x40
#define RIM45_ID    0x30
#define RIM45A_ID    0x20

