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

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

struct scsidevice {
	u_char	scsi_config;	/* Configuration register */
	u_char	scsi_fill1[5];
	u_short	scsi_ext;	/* Additional status info, status extension */
#define scsi_parm scsi_ext	/* Paramater Stack to pass SCSI commands */
	u_char	scsi_fill2[1];
	u_char	scsi_dma_mode;	/* DMA Mode Register (Burst length) */
	u_short	scsi_aux;	/* Additional status information (Auxiliary) */
	u_short	scsi_status;	/* Status register for cmd complition info */
#define scsi_cmd scsi_status	/* Commands to SCSI adapter about parm stack */
};

/* Status register defintions (Read Only, 16 bits) scsi_status */

/*	This register is use for command completion status and should be
 * read after an interrupt occurs and before sending a new command.
 * An 8 bit read of this register clears the interrupt and allows subsequent
 * interrupts to occur.
 */
#define SCSI_ST_CCSM		0xFF00	/* Command Completion Status Mask */
#define SCSI_ST_AR		0x0F00	/* Adapter Ready after reset(BAT's ok)*/
#define SCSI_ST_FC		0x8000	/* Adapter detected Fault Condition */
#define SCSI_ST_CR		0x2000	/* Command Rejected */
#define SCSI_ST_CEF		0x4000	/* Command Exec Fault */
#define SCSI_ST_INFO		0xA000	/* Informational */
#define SCSI_ST_BAT_FAIL	0xC000	/* BATs Failed */
#define SCSI_ST_WRAP_FAIL	0xE000	/* Wraps Failed */

#define SCSI_ST_CTM		0x001F	/* Command Tag number Mask */
#define SCSI_ST_CCS_VALID	0x0020	/* Command Comp. Status is valid */
#define SCSI_ST_VALID		0x0040	/* Status Byte is now valid */
#define SCSI_ST_BUSY		0x0080	/* Adapter busy processing command or */
					/* emptying the param stack */

#define SCSI_ST_BITS "\20\6COMMAND-COMPLETE\7STATUS-VALID\10BUSY"

/* SCSI_ST_INFO descriptions */
#define SCSI_INFO_INTER		0xA100	/* Intermediate xfer interrupt */
#define SCSI_INFO_PARERR	0xA300	/* Intermediate xfer w/ parity err */

/* Command Register (Write Only, 16 bits) scsi_cmd */
/*
 *	This register is used for altering the adapter after the parameter
 * stack has been filled (If applicable).  It will contain the operation
 * code for the adapter and the other following paramter information.
 */
#define SCSI_CMD_CTM		0x001F	/* Command Tag number Mask */
#define SCSI_CMD_NBPM		0x0F00	/* Number Bytes of Param MASK */
#define SCSI_CMD_OCM		0xF000	/* Operation Code Mask */

/* Operation Codes */
#define SCSI_CMD_SEND		0x0000	/* Send SCSI Command */
#define SCSI_CMD_RW		0x1000	/* Read/Write Adapter Buffer */
#define SCSI_CMD_RBAT		0x4000	/* Run Basic Assurance Tests */
#define SCSI_CMD_RWRAP		0x5000	/* Run Wrap Tests */
#define SCSI_CMD_CLRT		0x6000	/* Clear Tag */
#define SCSI_CMD_CONT		0x7000	/* Continue SCSI Data Xfr. */
#define SCSI_CMD_MISC		0x8000	/* Miscellaneous adapter info */

/* DMA Mode Register (8 bits, Write Only) scsi_dma_mode
 * defines the burst length to be used during DMA data transfers.
 */
#define SCSI_BURST_LEN4		0x01
#define SCSI_BURST_LEN8		0x03
#define SCSI_BURST_LEN16	0x05
#define SCSI_BURST_LEN32	0x07
#define SCSI_BURST_LEN64	0x09
#define SCSI_BURST_LEN128	0x0B
#define SCSI_BURST_LEN256	0x0D
#define SCSI_BURST_LEN512	0x0F


/* Configuration register flags, scsi_config
 * (16 bits, Read/Write, 8 bits write, 4 bits read only)
 */
#define SCSI_CF_INT11	0x00	/* Use interrupt level 11 */
#define SCSI_CF_INT12	0x01	/* Use interrupt level 12 */
#define SCSI_CF_IEN	0x02	/* Interrupt Enable */
#define SCSI_CF_DMAEN	0x10	/* DMA Enable */
#define SCSI_CF_DMASM	0xE0	/* DMA Channel Select Mask */
#define SCSI_CF_DMASFT	5	/* DMA Select Shift value (For placing chan) */
#define SCSI_CF_ECM	0x0F00	/* EC Mask (TBD) referenced as a short */

/* Magic Reset Code to be placed in Auxiliary register after a power on reset */
#define SCSI_AUX_RESET	0x4400

/*
 * SCSI commands placed in parameter stack and sent by the SCSI_CMD_SEND cmd.
 * These are command passed to the peripheral SCSI device.
 * The top three bits of command is the group, the bottom 5 is the cmd.
 */
/* GROUP 0 */
#define CMD_TUR		0x00	/* Test for Unit Ready */
#define CMD_RZU		0x01	/* Rezero Unit (Not supported on IBM9332) */
#define CMD_RS		0x03	/* Request Sense */
#define CMD_FU		0x04	/* Format Unit */
#define CMD_RSA		0x05	/* Read Slave Area */
#define CMD_WSA		0x06	/* Write Slave Area */
#define CMD_RB		0x07	/* Reassign Blocks */
#define CMD_READ	0x08	/* Read */
#define CMD_WRITE	0x0A	/* Write */
#define CMD_SEEK	0x0B	/* Seek (Not supported on IBM9332) */
#define CMD_INQUIRY	0x12	/* Inquiry */
#define CMD_MODE_SEL	0x15	/* Mode Select */
#define CMD_RES		0x16	/* Reserve */
#define CMD_REL		0x17	/* Release for Unit Ready */
#define CMD_COPY	0x18	/* Copy (Not supported on IBM9332) */
#define CMD_MS		0x1A	/* Mode Sense */
#define CMD_SSU		0x1B	/* Start/Stop Unit (Not supported on IBM9332) */
#define CMD_RDR		0x1C	/* Receive Diagnostic Results (Not on IBM9332) */
#define CMD_SD		0x1D	/* Send Diagnostic */
#define CMD_MR		0x1E	/* Prevent/Allow Medium Removal (Not IBM9332) */

/* GROUP 1 */
#define CMD_RCAP	0x25	/* Read Capacity */
#define CMD_REXT	0x28	/* Read Extended */
#define CMD_WEXT	0x2A	/* Write Extended */
#define CMD_SEXT	0x2B	/* Seek Extended (Not on IBM9332) */
#define CMD_WV		0x2E	/* Write and Verify */
#define CMD_VERIFY	0x2F	/* Verify */

/* ALL these are optional and are not supported by the IBM9332 */
#define CMD_SDH		0x30	/* Search Data High */
#define CMD_SDE		0x31	/* Search Data Equal */
#define CMD_SDL		0x32	/* Search Data Low */
#define CMD_SETL	0x33	/* Set Limits */
#define CMD_CMP		0x39	/* Compare */
#define CMD_CV		0x3A	/* Copy And Verify */

/* Command groups allowd by this SCSI Adapter */
#define SCSI_CMD_GROUP0	0x0
#define SCSI_CMD_GROUP1	0x1
#define SCSI_CMD_GROUP5	0x5

/* Sizes of the different command groups parameter stacks */
#define SCSI_GROUP0_SIZE	(6)
#define SCSI_GROUP1_SIZE	(10)
#define SCSI_GROUP2_5_SIZE	(12)

/* SCSI opcode field */
typedef union {
	struct {
		u_char	group:3;	/* Group code */
		u_char	command:5;	/* Command code */
	} opcode;
	u_char charcode;
} scsi_opcode;

/* Control Byte definition */
typedef union {
	struct {
		u_char	vu:2;		/* Vendor Unique */
		u_char	rsvd:4;		/* Reserved */
		u_char	flag:1;		/* Flag bit */
		u_char	link:1;		/* Link bit */
	} ctrl;
	u_char charctrl;
} scsi_control;

/* Typical Command Descriptor Block for Six-Byte Commands */
typedef struct {
	u_char		opcode;		/* Command Operation Code (See above) */
	u_int		lun:3;		/* Logical Unit Number */
	u_int		lba:21;		/* Logical Block Address */
	u_char		tlen;		/* Transfer Length */
	u_char		ctrl;		/* Control Byte (See above) */
} scsi_cdb6;

/* Typical Command Descriptor Block for Ten-Byte Commands */
typedef struct {
	u_char		opcode;		/* Command Operation Code */
	u_int		lun:3;		/* Logical Unit Number */
	u_int		rsvd1:4;	/* Reserved */
	u_int		reladr:1;	/* Relative address bit */
	u_char		lba[4];		/* Logical Block Address */
	u_char		rsvd2;		/* Reserved */
	u_char		tlen[2];	/* Transfer Length */
	u_char		ctrl;		/* Control Byte */
} scsi_cdb10;

/* Typical Command Descriptor Block for Twelve-Byte Commands */
typedef struct {
	u_char		opcode;		/* Command Operation Code */
	u_int		lun:3;		/* Logical Unit Number */
	u_int		rsvd1:4;	/* Reserved */
	u_int		reladr:1;	/* Relative address bit */
	u_char		lba[4];		/* Logical Block Address */
	u_char		rsvd2[3];	/* Reserved */
	u_char		tlen[2];	/* Transfer Length */
	u_char		ctrl;		/* Control Byte */
} scsi_cdb12;

/* Typical Command Descriptor Block for Six-Byte Commands */
typedef struct {
	u_char		opcode;		/* Command Operation Code (See above) */
	u_char		lun:3;		/* Logical Unit Number */
	u_char		level:5;	/* Format Level */
	u_char		rsvd1;
	u_char		rsvd2;
	u_char		interleave;	/* Interleave Factor */
	u_char		ctrl;		/* Control Byte (See above) */
} scsi_frmt;

/* Struct defines stack for SCSI commands sent to the adapter */
typedef struct {
	u_int		rsvd1:2;
	u_int		stopxfr:1;	/* Stop data transfer at intermediate */
	u_int		dataxfr:1;	/* Data transfer control bit */
	u_int		dir:1;		/* Data direction (0 - out, 1 - in ) */
	u_int		id:3;		/* Target SCSI device ID */
	u_char		bufnum;		/* Starting buffer block number */
	u_char		rsvd2;
	u_char		gran;		/* Interrupt granularity */
	/* SCSI command descriptor block depending on command group type */
	union		{
		scsi_cdb6	cdb6;
		scsi_cdb10	cdb10;
		scsi_cdb12	cdb12;
		scsi_frmt	frmt;
	} cdb;
} scsi_cmdstack;

/* Direction for data in SCSI command (scsi_cmdstack.dir flag) */
#define SCSI_OUT	0
#define SCSI_IN		1


/* SCSI Adapter implementation specific information */

/* Structure defines stack for Read/Write adapter data buffer DMA transfers */
typedef struct {
	u_char	flag;		/* Direction and count type of data transfer */
	/* 24 DMA address, high 8 bits of 32 ignored */
	u_char	dma_resid;	/* Dma address residual byte */
	u_char	dma_hb;		/* Dma address high byte */
	u_char	dma_mb;		/* Dma address middle byte */
	u_char	dma_lb;		/* Dma address low byte */
	u_char	bufnum;		/* Which adapter buffer to start at */
	u_char	bcount;		/* How many Blocks/Bytes to xfer (See below) */
} scsi_rwdmastack;

#define SCSI_DMAST_SIZE	7	/* Size of the DMA parameter stack */

#define SCSI_DMADIR_RD	0x08	/* Read adapter buffer direction flag */
#define SCSI_DMADIR_WR	0x00	/* Write adapter buffer direction flag */
#define SCSI_DMABLKCNT	0x00	/* bcount is in 512 byte blocks - 1 */
#define SCSI_DMABYTCNT	0x04	/* bcount is in bytes/2 */

/* DMA and TCW struct and defines used to build DMA address needed above */
/* All these defines deal with DMA with an Alternate Master in Page Mode */
/* typedef union {
/* 	struct {
/* 		u_int	resid:8;	/* Residual byte */
/* 		u_int	hbits:7;	/* High bits allways set */
/* 		u_int	tcw:6;		/* TCW select */
/* 		u_int	disp:11;	/* Displacement */
/* 	} dma_addr;
/* 	u_char char_dma_addr[4];
/* } scsi_dmaaddr;
*/
	
/*  Tag and buffer allocation for SCSI adapter */
#define SCSI_NTAGS	16	/* Number of cmds simultaneously active */
#define SCSI_NBUFS	64	/* 64 512 bytes sections to make 32K Kbytes */

/* Number of buffers reserved for sense commands */
#define SCSI_SNBUFS	8	/* One for every legal unit */
/* Number of buffers reserved for r/w commands */
#define SCSI_NCMDBUFS	(SCSI_NBUFS - SCSI_SNBUFS)

#define SENSE_BUFNUM(unit) (SCSI_NCMDBUFS+unit)

/* Number of command Tags for doing adapter control commands */
#define SCSI_NCTAGS	2

/* Number of SCSI command Tags */
#ifdef SINGLETHREADED
#define SCSI_NSTAGS	1
#else !SINGLETHREADED
#define SCSI_NSTAGS	(SCSI_NTAGS - SCSI_NCTAGS)
#endif !SINGLETHREADED

/* Starting Tag number for SCSI commands */
#define SCSI_STAGS_ST	0

/* Specially reserved Command tags */
#define SCSI_CMD_TAG	14
#define SCSI_SENSE_TAG	15


#define SCSI_NOBUFS	0xff	/* No buffers available right now */


/* Special Interrupt Clear registers, act as semaphores for shared ints */
/* The interrupt routine should do a byte write to clear semaphore on int */
#define SCSI_INT11_SEMA	(*(char *)0xF00006f3)
#define SCSI_INT12_SEMA	(*(char *)0xF00006f4)


/* Defines and structures for sense data */
typedef struct SCSI_ERR_REC {
	u_char	detect_id;		/* See IBM 9332 SCSI document */
	u_char	err_number;		/* See IBM 9332 SCSI document */
	u_char	lba[4];
	u_char	phys[4];
	u_char	rec_res;		/* See IBM 9332 SCSI document */
	u_char	rec_act;		/* See IBM 9332 SCSI document */
} scsi_err_rec;

typedef struct SCSI_SENSE {
	u_char	adval:1;	/* Address valid? */
	u_char	Err_class:3;	/* Error Class (ibm9332 always is 7) */
	u_char	Err_code:4;	/* Error  Code (ibm9332 always is 0) */
	u_char	rsvd1[1];
	u_char	key;		/* Sense Key */
	u_char	info_by[4];	/* Info bytes (valid address if adval) */
	u_char	add_len;	/* Additional length */
	u_char	rsvd2[4];
	u_char	add_code;	/* Additional Sense Code */
	u_char	rsvd3[1];
	u_char	fru;
	u_char	iri[3];		/* Illegal Request Info (Not supported) */
	u_char	rsvd4[1];
	u_char	hac;		/* Host Action Code */
	u_char	surc[2];	/* Summary Unit Refence Code */
	u_char	rsvd5[2];
	scsi_err_rec err_rec[8];/* Max number of error records */
} scsi_sense;

#define SCSI_SENSESZ	((short)sizeof(struct SCSI_SENSE))
#define SCSI_ERRRECSZ	((short)sizeof(struct SCSI_ERR_REC))

/* Defines for Sense 'key' element of SCSI_SENSE structure */
#define SCSI_SENSE_NO	0x00	/* NO SENSE INFORMATION */
#define SCSI_SENSE_RE	0x01	/* Recovered Error */
#define SCSI_SENSE_NR	0x02	/* LUN is Not Ready */
#define SCSI_SENSE_ME	0x03	/* Medium Error */
#define SCSI_SENSE_HE	0x04	/* Hardware Error */
#define SCSI_SENSE_IR	0x05	/* Illegal Request */
#define SCSI_SENSE_UA	0x06	/* Unit Attention (A reset has occured) */
#define SCSI_SENSE_AC	0x0B	/* Aborted Command */

/* Defines for Sense 'add_code' element of SCSI_SENSE structure */
#define SCSI_ADSEN_NO	0x00	/* NO Additional SENSE INFORMATION */
#define SCSI_ADSEN_RUT	0x29	/* Reset Caused the UNIT ATTENTION */
#define SCSI_ADSEN_MUT	0x2A	/* Change of Mode Param caused UNIT ATTENTION */

/* Defines for 'detect_id' element of SCSI_ERR_REC structure */
#define SCSI_DI_IP	0x08	/* Interface Processor Error Code */
#define SCSI_DI_FP0	0x10	/* File Processor Error Code */
#define SCSI_DI_FP1	0x11	/* File Processor Error Code */
#define SCSI_DI_SP0	0x20	/* Servo Processor Error Code */
#define SCSI_DI_SP1	0x40	/* Servo Processor Error Code */

/*
 * The following structure is returned on a Mode Sense (CMD_MS) command
 * and passed on a Mode Select (CMD_MODE_SEL) command
 */
struct mode_sense_header {
	char sdl;		/* Sense Data Length on (CMD_MS) */
	char medium_type;	/* Allways 0 */
	char rsvd2;
	char bdl;		/* Block Descriptor Length */
};

struct block_descriptor {
	char Density_code;	/* Allways 0 */
	char nblocks[3];	/* Number of Disk Blocks */
	char rsvd1;
	char blen[3];		/* Disk Block Length */
};

/* Defines for ibm9332 for nblocks field */
#define SCSI_NBLOCKS_HALF	782364
#define SCSI_NBLOCKS_FULL	391182

/* Defines for ibm9332 for blen field */
#define SCSI_BLEN_HALF	256
#define SCSI_BLEN_FULL	512

/* Defines for munging dma addresses */
#define SCSI_HI_SHIFT	(16+1)
#define SCSI_MID_SHIFT	(8+1)
#define SCSI_LOW_SHIFT	(1)
#define SCSI_BYTE_MASK	0xff

struct vendor_unique_params {
	char page_code;
	char page_len;
	char drl;		/* Data Recovery Level */
	char drf;		/* Data Recovery Flags */
	short int_factor;	/* Interleave Factor (RO) */
};

/* Defines for Data Recovery Flags (drf) */
#define SCSI_ARRE	0x40	/* Automatic reassign defective data blocks*/
#define SCSI_PER	0x04	/* Report soft data errors */

struct mode_sense {
	struct mode_sense_header	msh;
	struct block_descriptor		bd;
	struct vendor_unique_params	vup;
};

#define MODE_SENLEN	18
