/*****************************************************************************
 *                                                                           *
 *                                                                           *
 *      File:           rf50.h (@(#)rf50.h	1.11 - 7/17/84 13:45:35)                               *
 *                                                                           *
 *      Description:    Header file for rf50.c (Ciprico Rimfire 50 SMD disk  *
 *                      controller driver)                                   *
 *                                                                           *
 *      Author:         Achut P. Reddy                                       *
 *                      Callan Data Systems, Inc.                            *
 *                      2645 Townsgate Road                                  *
 *                      Westlake Village, CA  91361                          *
 *                      (805) 497-6837                                       *
 *                                                                           *
 *      Date:           April 11, 1984                                       *
 *                                                                           *
 *    +-------------------------------------------------------------------+  *
 *    | Notice:         THIS IS PROPRIETARY INFORMATION OF Callan Data    |  *
 *    |                 Systems, Incorporated, AND THE USE, DUPLICATION   |  *
 *    |                 OR DISCLOSURE OF THIS SOURCE FILE AND INFORMATION |  *
 *    |                 CONTAINED HEREIN IS RESTRICTED TO Callan Data     |  *
 *    |                 Systems, Incorporated EMPLOYEES AND THOSE OTHERS  |  *
 *    |                 WHO HAVE EXPLICIT AND PRIOR WRITTEN AGREEMENTS TO |  *
 *    |                 USE THIS MATERIAL.                                |  *
 *    +-------------------------------------------------------------------+  *
 *                                                                           *
 *      (C) Copyright 1984 by Callan Data Systems, Inc.                      *
 *                                                                           *
 *****************************************************************************/


#define NUNITS		4	/* Maximum number of drives */
#define SECSIZE 	BSIZE   /* Number of bytes per sector (bsize = 512) */
#define MAXSCOUNT  	0xFFFF  /* maximum sector count transfer */
#define LOG_SS  	BSHIFT  /* Log (base 2) (SECSIZE) */
#define NRETRY  	0       /* Software retry count */
#define CRETRY  	3       /* Hardware retry count */

#define RFSMDADDR 	((struct device *) RF50CMDP_VA)

#define TRUE    1
#define FALSE   0


typedef unsigned char Uchar;

/* Minor device number is broken down as follows:
 *
 * bits 7-6 unit number (0-3)
 * bits 5-0 logical device (Up to 64 file system partitions -- see rf50map)
 */
#define logical(dev)	(minor(dev) & 0x3f)
#define physical(dev)	(minor(dev) >> 6)
#define vtop(virt)	((caddr_t)(((*vtopage(virt) & PBMASK) << PAGESHIFT) + ((long)virt & OFFMASK)))

/* Structure to hold disk-type specific information for each type */
struct rftype
{
    unsigned short d_sectors;		/* Sectors per track */
    unsigned short d_cyls;		/* Cylinders per drive */
    unsigned short d_heads;		/* Heads per drive */
    unsigned char d_interl;		/* Interleave */
    unsigned char d_class;		/* Drive class (used by CONFIG cmd) */
};
/* Mnemonics for disk types */
#define T_EAGLE		0		/* Fujitsu Eagle 360 Mb Disks */
#define T_CDC9715	1		/* CDC 9715 145 Mb Disks */

/*
 * SMDMAP parameters:
 *		STRK	=	Starting Track for logical unit
 *		ETRK	=	Ending Track for logical unit
 *		TYPE	=	Type of disk (index into rftype[] array)
 *		SPT	=	Sectors per track
 */
#define SMDMAP(STRK,ETRK,TYPE,SPT) {(STRK*SPT), ((ETRK-STRK+1)*SPT), TYPE}

/* Structure for file syatem maps.  Blocks here mean 512-byte blocks */
struct rf50map
{
	daddr_t rf50_baseb;      /* Base address in blocks */
	daddr_t rf50_nblk;       /* Number of blocks in logical device */
	char   rf50_type;	 /* Disk type */
};

/* Intel and Motorola have different opinions on byte addressing conventions.
 * All byte addresses from the 68000 to the MULTIBUS are byte reversed
 * as follows: take every byte address and invert its least significant bit.
 * Thus 2 becomes 3, 3 becomes 2, and so on.
 */

/* Command and status ports */
struct device
{
	char   rf50r1;  /* +1 Board Reset */
	char   rf50r0;  /* +0 Channel Attention */
	char   rf50r3;  /* +3 Clear Status Change Interrupt */
	char   rf50r2;  /* +2 Clear Command Interrupt */
	char   rf50r5;  /* +5 (msb0) iopb addr bits 8 - 15 (write only) */
	char   rf50r4;  /* +4 (lsb0) iopb addr bits 0 - 7 (write only) */
	char   rf50r7;  /* +7 (offset) not used for direct addressing (write only) */
	char   rf50r6;  /* +6 (msb1) iopb addr bits 16 - 23 (write only) */
	char   rf50r9;  /* +9 Reserved for debugger Inter */
	char   rf50r8;  /* +8 Interrupt Status register */
	char   rf50r11; /* +11 Reserved */
	char   rf50r10; /* +10 Reserved */
	char   rf50r13; /* +13 Reserved */
	char   rf50r12; /* +12 Reserved */
	char   rf50r15; /* +15 Reserved */
	char   rf50r14; /* +14 Reserved */
};

/* Command codes for writing in status/command register zero */
#define GO      0xff    /* word mode + starts the controller */
#define CLRINT  0xff    /* word mode + clear interrupt */

/* Useful bits for reading status/command register 8 */
#define DONE    0x01    /* if set, operation done, interrupt line asserted */
#define STCHNG  0x02    /* status change interrupt */
#define SCMSK	0x1C	/* Mask for status change field */
#define DRMSK	0xC0	/* Drive mask for status change condition */

#define E_SEEK 0x04
#define E_ILCMD 0x01

/* iopb is located in multibus memory. bytes reversed for Sun operation */
struct rf50_iopb
{
    ushort  rfsc_cmd;	    /* 0,+1 command */
    Uchar   rfsc_unit;	    /* +3 unit number */
    Uchar   rfsc_head;	    /* +2 head select */
    ushort  rfsc_ccntl;     /* +4,5 command control */
    ushort  rfsc_diskcntl;  /* +6,7 disk command control */
    ushort  rfsc_cylinder;  /* +8,9 starting cylinder */
    ushort  rfsc_sector;    /* +10,11 starting sector */
    ushort  rfsc_records;   /* +12,13 records */
    ushort  rfsc_lmem;	    /* +14,15 buffer memory addr bits 0 - 15 */
    ushort  rfsc_hmem;	    /* +16,17 buffer memory addr bits 16 - 31 */
    Uchar   rfsc_gate;	    /* +19 gate */
    Uchar   rfsc_error;	    /* +18 error code */
    ushort  rfsc_status;    /* +20,21 status */
    ushort  rfsc_lint;	    /* +22,23 interrupt/next iopb address, bits 0-15 */
    ushort  rfsc_hint;	    /* +24,25 interrupt/next iopb address, bits 24-31 */
    Uchar   rfsc_res0;	    /* +27 reserved */
    Uchar   rfsc_ehead;	    /* +26 extended head select */
    ushort  rfsc_ecyl;	    /* +28,29 entended cylinder, bits 0 - 15 */
    ushort  rfsc_esector;   /* +30,31 extended sector msb,bits 0 - 15 */
};

/* Command codes for controller */
#define CONFIG		0x00    /* Congigure */
#define CSTATUS		0x01    /* Disk status */
#define CREZERO		0x02    /* Rezero */
#define CSEEK		0x03    /* Seek */
#define CREADID		0x04    /* Read ID */
#define CREAD		0x05    /* Read */
#define CREAD_C		0x06    /* Read chained sectors */
#define CTRACK_READ	0x08    /* Track read */
#define CWRITE		0x09    /* Write sector */
#define CWRITE_C	0x0a    /* Write chained sectors */
#define CFORMAT		0x0b    /* Format */
#define CMAP_TRACK	0x0c    /* Map Track */
#define CMAP_SECTOR	0x0d    /* Map Sector */
#define CINTERROG	0x0e    /* Interrogate */
#define CREAD_L		0x0f    /* Read Long */
#define CWRITE_L	0x10    /* Write Long */
#define CDISK_DMP	0x11    /* Disk dump */
#define CDISK_RST	0x12    /* Disk restore */
#define CIDENTIFY	0x13    /* Identify */
#define CDIAG		0x20    /* Diagnostic */
#define COPT1		0x21    /* Option 1 */
#define COPT2		0x22    /* Option 2 */
#define CATTACH		0x23    /* Attach */
#define CPICKHOLD	0x25    /* Attach */

#define CMDMASK 0xff     /* mask to get low-nibble from command code */

/* Command Control bits (rfsc_ccntl) for IOPB */
#define BUS_LCK		0x01	/* Command control - bus lock */
#define LINK		0x02	/* Link of IOPB's */
#define INT_ENB		0x04	/* Interrupt enable */
#define MAIL_ENB	0x08	/* Mailbox interrupt enable */
#define BYTE_MD		0x10	/* Byte mode for multibus transfers */
#define ADDR_MD		0x20	/* Address mode offset */

#define CMDCTLNM	INT_ENB 	/* Normal mode */

/* Disk control Bits (rfsc_diskcntl) for IOPB */
#define RESRV_D		0x01	/* Reserve dual ported drive */
#define ECC_DISA	0x02	/* Disable error correction */
#define RET_DISA	0x04	/* Disable retries */
#define DATA_RTN	0x08	/* Data return enable */
#define PROT_EBL	0x10	/* Protected access enable */

/* Disk control Bits  for format control (subset of rfsc_diskcntl)*/
#define USER_ALT	0x1000	/* User supplies alternate address */
#define USER_ITL	0x2000	/* User supplies interleave table */
#define VERIFY		0x4000	/* Verify read - map track or format */
#define DISK_MD		0x8000	/* Disk mode for format: do whole disk */

#define DKCTLNM		0 	/* Normal mode for diskcntl */

/* status codes from rfsc_cmdgate of IOPB */
#define UNRECOV		0x08	/* Unrecoverable error */
#define REQ_CORC	0x10	/* Correction required */
#define REQ_RTRY	0x20	/* Retry required */
#define CMD_DONE	0x40	/* Command complete */
#define CMD_BUSY	0x80	/* Command entered */
#define NOTFLAGGED	0	/* cleared by rf50cmd controller updates */

/* status for rfsc_error */
#define OK		0x00	/* no error */

/* The 14-byte record used only for the Configure Disk command to initialize
 * each unit 
 */
struct  rf50_uinit
{
	char   rfi_interl;	/* +1 interleave factor */
	char   rfi_type;	/* +0 drive type */
	char   rfi_hds1;	/* +3 Heads per cylinder for unit one */
	char   rfi_hds0;	/* +2 Heads per cylinder for unit zero */
	short  rfi_spt;		/* +4,5 sectors per track high byte */
	short  rfi_cpd;		/* +6,7 cylinders per disk */
	short  rfi_bps;		/* +8,9 bytes per sector */
	char   rfi_res1;	/* +11 Reserved R1 */
	char   rfi_res0;	/* +10 Reserved R0 */
	char   rfi_res3;	/* +13 Reserved R3 */
	char   rfi_res2;	/* +12 Reserved R2 */
};

/* Drive classes (for use by controller) */
#define TYPE_CDC  0		/* CDC SMD, CMD or equivalent */
#define TYPE_FUJI 1		/* Fujitsu Eagle or equivalent */
#define TYPE_MEMX 2		/* Memorex 213/214 or equivalent */
#define DR_TYPE   TYPE_FUJI	/* Drive Type */

/* Parameter block for Option 1 command used to configure controller */
struct rfo1_iopb
{
    short rfo1_cmd;	/* +0, 1 command */
    short rfo1_1nu;	/* +2,3 not used */
    short rfo1_ccntl;	/* +4,5 cmd control */
    short rfo1_opcntl;	/* +6,7 option control */
    char  rfo1_2nu;	/* +9 not used */
    char  rfo1_imask;	/* +8 interrupt mask */
    char  rfo1_fmfil;	/* +11 format fill character */
    char  rfo1_rtcnt;	/* +10 retry count */
    short rfo1_dmacnt;	/* +12,13 DMA count */
    short rfo1_lsgate;	/* +14,15 low word system gate */
    short rfo1_hsgate;	/* +16,17 high word system gate */
    char  rfo1_gate;	/* +19 command gate */
    char  rfo1_error;	/* +18 error */
    short rfo1_1res;	/* +20,21 reserved */
    short rfo1_llnk;	/* +22,23 low link address */
    short rfo1_hlnk;	/* +24,25 high link address */
};

#define DMACNT	0x80	/* DMA count */

/* Option control (rfo1_opcntl) bits for controller init */
#define	STATSC_EN	0x0400	/* enable status scan */
#define	STATSC_DI	0x0800	/* disable status scan */
#define	STATCI_EN	0x0100	/* status change interrupt enable */
#define	STATCI_DI	0x0200	/* status change interrupt disable */
#define	PBPA_DIR	0x0040	/* Parameter block pointer address direct */
#define	PBPA_OPS	0x0080	/* Parameter block pointer address offset */
#define SYSGT_EN	0x0010	/* System gate enable  */
#define SYSGT_DI	0x0020	/* System gate disable */
#define	INTM_ST		0x0008	/* interrupt mask set */
#define	PRMTFL_ST	0x0004	/* Format fill set */
#define	DMACNT_ST	0x0002	/* dma count set */
#define	RTRCNT_ST	0x0001	/* retry count set */



/* In the past, drivers kept another copy of the buffer header around
 * (traditionally, struct iobuf *dp, defined in iobuf.h)
 * to keep track of the buffers on the queue (posted by strategy)
 * and used the remaining space in the iobuf.h structure to keep whatever
 * would fit.  Below we define a new structure that contains the necessary
 * entries to manage the io queue, and keep all the 'globals' as well.
 *
 * b_forw and b_back is a doubly-linked list, containing all the
 * buffers currently associated with this device.
 * d_actf and d_actl is a list used privately by the driver (us) to
 * keep a fast pointer to the head and tail of the above b_forw and b_back
 * list.
 */

struct rf50tab
{
    int b_flags;		/* see buf.h */
    struct buf *b_forw;		/* ptr to first buf header for this dev */
    struct buf *b_back;     	/* ptr to last buf header for this dev */
    struct buf *b_actf;     	/* ptr to head of I/O queue */
    struct buf *b_actl;     	/* tail of I/O queue */
    /* `private' vars for rf50 */
    char rf50_active;    	/* driver fsm state (active, busy, etc) */
    char rf50_errcnt;   	/* error count (for recovery) */
    char rf50_retry;     	/* retry phase; 0 = no retry 1 = retry */
    char rf50_rcmd;      	/* space to save old cmd during restore */
    daddr_t rf50_blkno;     	/* present block being transferred */
    caddr_t rf50_addr;      	/* present core address */
    unsigned rf50_bcount;   	/* present count */
    unsigned short rf50_seccnt; /* number of sectors being transfered */
    char rf50_cicsr;     	/* csr copy at last ci call */
    char rf50_unists[NUNITS];	/* UNit Initialization STatuS */
};

/* States for rf50_active */
#define IDLE            0
#define NORMALIO        1
#define INTR            2
#define RETRY           3

/* values for rf50_unists */
#define NOTCONFIGURED	0
#define CONFIGURED	1

/* Additional structure paired with rf50cbuf for commands internal to driver */
struct rf50_itcmd
{
    int b_command;
    int b_seccnt;
    int b_sector;
    int b_head;
    int b_cylinder;
    int b_status;
    int b_error;
    int b_cmdgate;
};

/* Structure for ioctl commands */
struct smdioctl
{
	int smd_op;
	int smd_head;
	int smd_cylinder;
	int smd_sector;
	int smd_ehead;
	int smd_ecylinder;
	int smd_esector;
	int smd_seccnt;
	int smd_status;
	int smd_error;
};

/* Some ioctl command mnemonics */
#ifdef UIOC				/* UIOC is defined in <sys/uioctl.h> */
#define UIOCDKOP	(UIOC|20)
#endif
