/* @(#)stcreg.h       2.4 88/09/01 Copyr 1987 Sun Micro */

/*
 * SCSI command codes
 */
#define STC_TEST_UNIT_READY	0x0
#define STC_REWIND		0x1
#define STC_REQUEST_SENSE	0x3
#define STC_READ_BLOCK_LIMITS	0x5
#define STC_LOAD_DISPLAY	0x6
#define STC_READ		0x8
#define STC_WRITE		0xA
#define STC_READ_REVERSE	0xF
#define STC_WRITE_FILEMARKS	0x10
#define STC_SPACE		0x11	      
#define STC_INQUIRY		0x12
#define STC_RECOVER_BUFFERED_DATA	0x14
#define STC_MODE_SELECT		0x15
#define STC_RESERVE_UNIT	0x16
#define STC_RELEASE_UNIT	0x17
#define STC_ERASE		0x19
#define STC_MODE_SENSE		0x1A
#define STC_LOAD		0x1B
#define STC_RECIEVE_DIAG_RESULTS	0x1C	
#define STC_SEND_DIAGNOSTIC	0x1D
#define STC_LOCATE		0x2B
#define STC_READ_POSITION	0x34
#define STC_UNLOAD		0x80		/* phony - for int use only */
#define STC_SPACE_FILE		0x81		/* phony - for int use only */
#define STC_SPACE_RECORD	0x82		/* phony - for int use only */

/*
 * Error classifications
 */
#define NO_ERROR		0
#define MORE_PROCESSING      	1       /* Recoverable error */
#define REAL_ERROR           	2       /* Hard error */
#define PSEUDO_ERROR         	3       /* What looked like error is OK */

/*
 * Timeouts (in seconds)
 */
#define	NO_TIMEOUT		0	/* Turn off timeouts */
#define REQUEST_SENSE_TIMEOUT	10
#define DEFAULT_TIMEOUT		30
#define MODE_TIMEOUT		30
#define INQUIRY_TIMEOUT		30
#define TEST_UNIT_READY_TIMEOUT	30
#define READ_WRITE_TIMEOUT	120
#define REWIND_TIMEOUT		120
#define SELFTEST_TIMEOUT	180

/*
 * Special codes.
 */
#define SC_SENDDIAG		0x1D    /* send diagnostic */
#define SELF_TEST		0x04	/* self test bit */
/*
 * Special tape codes.
 */
#define SC_REWIND		0x01	/* special tape operation code */
#define FIXED_LENGTH_IO		0x01	/* special tape tag code */
#define T_NOREWIND              0x04

/*
 * Default type for opening.
 */
#define STC_TYPE_INVALID	0x00
#define STC_TYPE_DEFAULT	0x01	/* Who knows ? */
#define STC_TYPE_4980		0x02	/* StorageTek 4980 */
#define STC_TYPE_4980_SK	0x03	/* StorageTek 4980 with stacker */
#define STC_TYPE_2980           0x04    /* StorageTek 2980 */

#define IS_DEFAULT(dsi)		(dstc->un_ctype == STC_TYPE_DEFAULT)

#define SAVED_SENSE_LEN 86

/*
 * Mode select parameters
 */
struct stc_mode_params {
    u_char mode_res1;
    u_char mode_res2;
    u_char wp			:1;	/* Write protect */
    u_char mode_buffered	:3;
    u_char mode_speed		:4;
    u_char mode_desc_len;
};

struct stc_mode_blk_desc {
    u_char	density;
    u_char	nblks_high;
    u_char	nblks_mid;
    u_char	nblks_low;
    u_char	rsvd;
    u_char	blk_len_high;
    u_char	blk_len_mid;
    u_char	blk_len_low;
    u_char mode_icrc;
};



/*
 * Mode sense data
 */
struct stc_mode_sense_data {
    u_char	sense_data_len;
    u_char	media_type;
    u_char	write_protect	:1;
    u_char	buffered_mode	:3;
    u_char	transport_speed	:4;
    u_char	desc_len;
    struct	stc_mode_blk_desc desc;
    u_char	loader_status;
};

/*
 * SCSI stc driver structure. Warning, must be even-byte aligned.
 */
struct scsi_stc {
	u_int   un_sense;               /* ptr to request sense buffer */
	int	un_senselen;		/* size of above */
	int     un_bufcnt;              /* number of buffers in use */
	u_int   un_timeout;             /* timeout time  */
	int     un_err_blkno;           /* block where error occurred */
	int     un_err_resid;           /* resid from last error */
	int	un_fileno;		/* current file number */
	int	un_position;		/* current position (bytes) */
	int	un_bsize;		/* Current blocksize */
	short   un_status;              /* status from last sense */
	short   un_retries;             /* retry count */
	u_short un_openf;               /* tape open state */
	u_short un_flags;               /* special global unit flags,      */
					/*   disables disconnect/reconnect */
	int 	un_misc;		/* Misc flags */
	u_char  un_ctype;               /* controller type */
	u_char  un_last_cmd;            /* last scsi command issued */
	u_char	un_err_sense[SAVED_SENSE_LEN];	/* Sense data from last ran_sense */
	short	un_err_sense_len;	/* How much we got */
	struct  stc_mode_sense_data un_mdata;
	u_char  un_eof;			/* eof mark pending */
	u_char	un_eot;			/* eot = 0, not found */
					/*     = 1, eot hit */
					/*     = 2, eot pending */
	struct proc	*stc_wsel;	/* user proc structure for select */
	int		stc_state;	/* select state flag */
	int	un_has_icrc;		/* drive has icrc installed/enabled */
	int	un_icrc_on;		/* drive is in ICRC mode */
	short		p_pgrp;		/* user process group leader */
};

/*
 * defines for stc_state (select and asynch I/O)
 */
#define STC_WCOLL	0x01
#define STC_ASYNC	0x02
#define	STC_DEVDONE	0x04	/* Got device done interrupt */

/*
 * Define for ICRC mode
 */
#define	STC_ICRC	0x01

/*
 * Used for generic commands
 */
struct stc_cmd {
        u_short stc_cmd;                /* command to be executed */
        u_int   stc_buflen;             /* size of user's buffer */
        daddr_t stc_blkno;              /* address for command */
        caddr_t stc_bufaddr;            /* user's buffer address */
};

/*
 * ioctls
 */
/*
 * Grot.  We have to define our own versions of these
 * since Ultrix and SunOS are no longer compatable.
 * Use the version from Ultrix, which is independant of C compiler
 * oddities, and is the smaller of the two.
 */
#define _CMIOCPARM_MASK   0x7f            /* Parameters are < 128 bytes   */
#define _CMIOC_VOID       (int)0x20000000 /* No parameters                */
#define _CMIOC_OUT        (int)0x40000000 /* Copy out parameters          */
#define _CMIOC_IN         (int)0x80000000 /* Copy in parameters           */
#define _CMIOC_INOUT      (int)(_CMIOC_IN|_CMIOC_OUT)
#define _CMIO(x,y)        (int)(_CMIOC_VOID|(x<<8)|y)
#define _CMIOR(x,y,t)     (int)(_CMIOC_OUT|((sizeof(t)&_CMIOCPARM_MASK)<<16)|(x<<8)|y)
#define _CMIOW(x,y,t)     (int)(_CMIOC_IN|((sizeof(t)&_CMIOCPARM_MASK)<<16)|(x<<8)|y)
#define _CMIOWR(x,y,t)    (int)(_CMIOC_INOUT|((sizeof(t)&_CMIOCPARM_MASK)<<16)|(x<<8)|y)

#define STCIOC_REZERO   _CMIO('f', 0)   /* Issue REZERO for error recovery */
#define STCIOC_SELFTEST _CMIO('f', 1)   /* Issue self test command to stc */
#define STCIOC_GETERRC  _CMIOR('f', 2, struct scsi_ext_sense)
                                        /* Get detailed STC error code */
#define STCIOC_INQUIRY  _CMIOR('f', 3, struct scsi_inquiry_data)
                                        /* get INQUIRY data */
#define STCIOC_LOAD_DISPLAY	_CMIOW('f', 4, struct stc_display_params)
#define STCIOC_SET_BLKSIZE	_CMIOW('f', 5, int)
#define STCIOC_GET_BLKSIZE	_CMIOR('f', 6, int)
#define	STCIOC_SET_ASYNC	_CMIO('f', 7)	/* Set async notification */
#define STCIOC_CANCEL_ASYNC	_CMIO('f', 8)	/* Cancel async notification */
#define STCIOC_CLEAR_EOT	_CMIO('f', 9)	/* Allow writes past EOT */
#define STCIOC_READ_DEVDONE	_CMIO('f', 10)	/* Read device done flag */
#define STCIOC_SET_ICRC		_CMIO('f', 11)  /* Turn compression on */
#define STCIOC_CLEAR_ICRC	_CMIO('f', 12)  /* Turn compression off */
#define STCIOC_GET_ICRC		_CMIO('f', 13)  /* Inquire about compression */

/*
 * Macros for getting information from the sense data returned
 * by the various SCSI controllers.  Note, this uses byte 2 of the
 * extended sense descriptor block to mimimize SCSI controller dependencies.
 */

#define STC_CORRECTABLE(dstc, sense) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_RECOVERABLE_ERROR))

#define STC_NOT_READY(dstc, sense) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_NOT_READY))

#define STC_MEDIA_ERROR(dstc, sense ) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_MEDIUM_ERROR))

#define STC_ILLEGAL(dstc, sense) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_ILLEGAL_REQUEST))

#define STC_HARDWARE(dstc, sense) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_HARDWARE_ERROR))

#define STC_RESET(dstc, sense) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_UNIT_ATTENTION))

#define STC_WRITE_PROT(dstc, sense) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_WRITE_PROTECT))

#define STC_BLANK_CHECK(dstc, sense) \
	(dstc->un_ctype != 0  && \
	 (((struct scsi_ext_sense *)sense)->key == SC_BLANK_CHECK))

#define STC_FILE_MARK(dstc, sense) \
        (dstc->un_ctype != 0  && \
         (((struct scsi_ext_sense *)sense)->fil_mk) ? 1 : 0)

#define STC_END_OF_TAPE(dstc, sense) \
        (dstc->un_ctype != 0  && \
         (((struct scsi_ext_sense *)sense)->eom) ? 1 : 0)

#define STC_LENGTH(dstc, sense) \
        (dstc->un_ctype != 0  && \
         (((struct scsi_ext_sense *)sense)->ili) ? 1 : 0)

#define STC_VOLUME_OVERFLOW(dstc, sense) \
        (dstc->un_ctype != 0  && \
         (((struct scsi_ext_sense *)sense)->key == SC_VOLUME_OVERFLOW))

#ifdef KERNEL
static char *stc_key_error_str[] = SENSE_KEY_INFO;
#define MAX_KEY_ERROR_STR \
	(sizeof(stc_key_error_str)/sizeof(stc_key_error_str[0]))
#endif

/* SUPPRESS 592 -- some includers don't use this variable */
static char *stc_cmds[] = {
	"test unit ready",		/* 0x00 */
	"rewind",			/* 0x01 */
	"<bad cmd>",			/* 0x02 */
	"request sense",		/* 0x03 */
	"<bad cmd>",			/* 0x04 */
	"read block limits",		/* 0x05 */
	"load display",			/* 0x06 */
	"<bad cmd>",			/* 0x07 */
	"read",				/* 0x08 */
	"<bad cmd>",			/* 0x09 */
	"write",			/* 0x0a */
	"<bad cmd>",			/* 0x0b */
	"<bad cmd>",			/* 0x0c */
	"<bad cmd>",			/* 0x0d */
	"<bad cmd>",			/* 0x0e */
	"read reverse",			/* 0x0f */
	"write filemarks",		/* 0x10 */
	"space",			/* 0x11 */
	"inquiry",			/* 0x12 */
	"<bad cmd>",			/* 0x13 */
	"recover buffered data",	/* 0x14 */
	"mode select",			/* 0x15 */
	"reserve",			/* 0x16 */
	"release",			/* 0x17 */
	"<bad cmd>",			/* 0x18 */
	"erase",			/* 0x19 */
	"mode sense",			/* 0x1a */
	"load/unload",			/* 0x1b */
	"receive diag results",		/* 0x1c */
	"send diag",			/* 0x1d */
	"<bad cmd>",			/* 0x1f */
	"<bad cmd>",			/* 0x20 */
	"<bad cmd>",			/* 0x21 */
	"<bad cmd>",			/* 0x22 */
	"<bad cmd>",			/* 0x23 */
	"<bad cmd>",			/* 0x24 */
	"<bad cmd>",			/* 0x25 */
	"<bad cmd>",			/* 0x26 */
	"<bad cmd>",			/* 0x27 */
	"<bad cmd>",			/* 0x28 */
	"<bad cmd>",			/* 0x29 */
	"<bad cmd>",			/* 0x2a */
	"locate",			/* 0x2b */
	"<bad cmd>",			/* 0x2c */
	"<bad cmd>",			/* 0x2d */
	"<bad cmd>",			/* 0x2e */
	"<bad cmd>",			/* 0x2f */
	"<bad cmd>",			/* 0x30 */
	"<bad cmd>",			/* 0x31 */
	"<bad cmd>",			/* 0x32 */
	"<bad cmd>",			/* 0x33 */
	"read position",		/* 0x34 */
};
#define MAX_STC_CMDS \
	(sizeof(stc_cmds)/sizeof(stc_cmds[0]))

/* SUPPRESS 592 -- some includers don't use this variable */
static char *stc_int_cmds[] = {
  "stc_unload",			/* 0x80 */
  "stc_space_file",		/* 0x81 */
  "stc_space_record",		/* 0x82 */
};
#define MAX_STC_INT_CMDS (sizeof(stc_int_cmds)/sizeof(stc_int_cmds[0]))

/*
 * Inquiry data description
 */

#define SCSI_TAPELOADER		0x81

/*
 * Result of the read block limits command
 */
struct stc_rbl_result {
    u_char	rbl_reserved;
    u_char 	rbl_max1;
    u_char	rbl_max2;
    u_char	rbl_max3;
    u_char	rbl_min1;
    u_char	rbl_min2;
};

/*
 * Load display parameter list
 */
struct stc_display_params {
    u_char	display_flags;
    char	display_message1[8];
    char	display_message2[8];
};

#define NEW_MESSAGE_OVERLAY 0xe0
#define DISPLAY_ALTERNATE   0x10
#define DISPLAY_BLINK	    0x8
#define DISPLAY_MSG2	    0x4


/*
 * Diagnostic results
 */
struct stc_diag_results {
    u_char     	last_test_high;
    u_char	last_test_low;
    u_char	fsc_high;
    u_char	fsc_low;
    u_char	diag_fsc_high;
    u_char	diag_fsc_low;
    u_char	drive_status_high;
    u_char	drive_status_low;
    u_char	lun_tested;
    u_char	physical_address;
    u_char	last_block_sector;
    u_char	last_block_high;
    u_char	last_block_mid;
    u_char	last_block_low;
};

struct stc_diag_params {
    u_char	diag_func_num;
    u_char	start_test[2];
    u_char	end_test[2];
};

/* 
 * Read position data format
 */
struct stc_position {
    u_char 	bop	:1;
    u_char	eop	:1;
    u_char		:3;
    u_char	bpu	:1;
    u_char		:2;
    u_char	partition;
    u_char	rsvd2;
    u_char	rsvd3;
    u_char	first_block[4];
    u_char	last_block[4];
    u_char	rsvd12;
    u_char	blks_in_buffer[3];
    u_char	bytes_in_buffer[4];
};
    

/*
 * Code field for SPACE command
 */

#define SPACE_BLOCKS 0
#define SPACE_FILEMARKS 1
#define SPACE_SEQ_FILEMARKS 2


/*
 * Full extended sense structure for STC 4980
 */
struct stc_ext_sense {
    /* byte 0 */
    u_char	valid	: 1;	/* sense data is valid */
    u_char	err_class : 3;
    u_char 	err_code : 4;
    /* byte 1 */
    u_char	seg_num;	/* segment number, applies to copy cmd only */
    /* byte 2 */
    u_char	fil_mk	: 1;	/* file mark on device */
    u_char	eom	: 1;	/* end of media */
    u_char	ili	: 1;	/* incorrect length indicator */
    u_char		: 1;	/* reserved */
    u_char	key	: 4;	/* sense key, see below */
    /* bytes 3 through 7 */
    u_char	info_1;		/* information byte 1 */
    u_char	info_2;		/* information byte 2 */
    u_char	info_3;		/* information byte 3 */
    u_char	info_4;		/* information byte 4 */
    u_char	add_len;	/* number of additional bytes */
    /* bytes 8-11 */
    u_char	vu_8;
    u_char	vu_9;
    u_char	vu_10;
    u_char	vu_11;
    u_char	sec_sense_code;
    u_char	sec_sense_qual;
    /* bytes 14-17 */
    u_char	vu_14;
    u_char	vu_15;
    u_char 	vu_16;
    u_char	vu_17;
    /* Bytes 18-23 */
    u_char	fsc_1_high;
    u_char	fsc_1_low;
    u_char	fsc_2_high;
    u_char	fsc_2_low;
    u_char	fsc_last_high;
    u_char	fsc_last_low;
    u_char	initiator;	/* byte 24 */
    u_char	cur_lun;
    /* bytes 26-37 */
    u_char	msp[4];
    u_char	msb[8];
    /* byte 38 - 49 */
    u_char	ext_error[12];
    /* bytes 50-85 */
    u_char	ext_stats[36];
};

/*
 * Extensions to scsi.h
 */
#define SCSI_BIG_DMA_OK   0x1000	/* Ctlr flag */
#define SC_UNF_BIG_DMA	  0x1000


