/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* bos720 src/bos/usr/samples/cdrom/cdromdd.h 1.4                         */
/*                                                                        */
/* Licensed Materials - Property of IBM                                   */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 1992,1997              */
/* All Rights Reserved                                                    */
/*                                                                        */
/* US Government Users Restricted Rights - Use, duplication or            */
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.      */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
/* @(#)48     1.4  src/bos/usr/samples/cdrom/cdromdd.h, cdrmsamp, bos720 5/19/97 00:03:06 */
/*
	    NOTICE TO USERS OF THE SOURCE CODE EXAMPLES

 THE SOURCE CODE EXAMPLES PROVIDED BY IBM ARE ONLY INTENDED TO ASSIST IN THE
 DEVELOPMENT OF A WORKING SOFTWARE PROGRAM.  THE SOURCE CODE EXAMPLES DO NOT
 FUNCTION AS WRITTEN:  ADDITIONAL CODE IS REQUIRED.  IN ADDITION, THE SOURCE
 CODE EXAMPLES MAY NOT COMPILE AND/OR BIND SUCCESSFULLY AS WRITTEN.
 
 INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THE SOURCE CODE
 EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS, "AS IS" WITHOUT
 WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
 LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
 OF THE SOURCE CODE EXAMPLES, BOTH INDIVIDUALLY AND AS ONE OR MORE GROUPS,
 IS WITH YOU.  SHOULD ANY PART OF THE SOURCE CODE EXAMPLES PROVE
 DEFECTIVE, YOU (AND NOT IBM OR AN AUTHORIZED RISC System/6000* WORKSTATION
 DEALER) ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING, REPAIR OR
 CORRECTION.

 IBM does not warrant that the contents of the source code examples, whether
 individually or as one or more groups, will meet your requirements or that
 the source code examples are error-free.

 IBM may make improvements and/or changes in the source code examples at
 any time.

 Changes may be made periodically to the information in the source code
 examples; these changes may be reported, for the sample device drivers
 included herein, in new editions of the examples.

 References in the source code examples to IBM products, programs, or
 services do not imply that IBM intends to make these available in all
 countries in which IBM operates.  Any reference to an IBM licensed
 program in the source code examples is not intended to state or imply
 that only IBM's licensed program may be used.  Any functionally equivalent
 program may be used.

 * RISC System/6000 is a trademark of International Business Machines 
   Corporation.
*/
#ifndef  _H_CDROMDD
#define _H_CDROMDD
/*
 * COMPONENT_NAME: SCSI CD-ROM Device Driver Include File
 *
 * FUNCTIONS:	NONE
 * 
 * ORIGINS: 27
 * 
 */

/*********************************************************************/
/* cdromdd.h header dependencies				     */
/*********************************************************************/
#include <sys/buf.h>
#include <sys/scsi.h>
#include <sys/types.h>
#include <sys/watchdog.h>
#include <sys/iostat.h>

/************************************************************************/
/* Sense key values                                                     */
/************************************************************************/
#define CD_NO_SENSE             0x00
#define CD_RECOVERED_ERROR      0x01
#define CD_NOT_READY            0x02
#define CD_MEDIUM_ERROR         0x03
#define CD_ILLEGAL_REQUEST      0x05
#define CD_HARDWARE_ERROR       0x04
#define CD_UNIT_ATTENTION       0x06
#define CD_ABORTED_COMMAND      0x0B

/************************************************************************/
/* Other misc. defines                                                  */
/************************************************************************/
#define CD_MAX_RETRY            0x01    /* # of retries to attempt      */
#define CD_MAX_RESET_RETRY      0x03    /* # resets to attempt          */
#define CD_NO_RETRY             0x7F    /* don't retry (> CD_MAX_RETRY) */
#define CD_WAIT                 0xFD    /* cd_error rtn val = wait      */
#define CD_RETRY                0xFE    /* cd_error rtn val = retry cmd */
#define CD_RESET                0xFF    /* cd_error rtn val = reset dev */
#define CD_TIMEOUT              0x1E    /* command timeout value (secs) */
#define CD_WATCHDOG             0x05    /* watchdog timeout value (secs)*/
#define CD_PAGE_CODE            0xBF    /* page code for MODE_SENSE     */
#define CD_MODE_SELECT_SIZE      32     /* size of MODE_SELECT data      */
#define CD_MEDIUM_CHANGED       0x28    /* additional sense key         */
#define CD_START_UNIT           0x01    /* flag for start/stop unit cmd */
#define CD_STOP_UNIT            0x00    /* flag for start/stop unit cmd */
#define CD_PASS_THRU            0xEF    /* cmd state for pass-thru ioctl*/
#define CD_ORIGINAL_REQUEST     0x01    /* flag for cd_start routine    */
#define CD_CONTINUED_REQUEST    0x02    /* flag for cd_start routine    */
#define CD_HASHSIZE		0x0F

/* For debug purposes only */

#define CDROM_LOCK_CLASS         900

/************************************************************************/
/* Initialization information on individual disks                       */
/************************************************************************/
struct cdrom_dds_df  {
        dev_t           adapter_devno;  /* adapter major/minor number   */
					/* This value is the size of an */
					/* int.  The major number is    */
					/* held in the 2 high bytes     */
					/* while the 2 low bytes holds  */
					/* the minor number.            */
        uchar           scsi_id;        /* SCSI ID for this controller  */
					/* This is the ID for the       */
					/* initiator controlling this   */
					/* device.                      */
        uchar           lun_id;         /* logical unit ID for this dev */
	char		resource_name[8];
					/* The name of device.  This is */
					/* used primarily in the error  */
					/* recovery routines 		*/
        uchar		mode_select_data[256]; 
					/* mode select data.  This data */
					/* is used with the initial 	*/
					/* MODE_SELECT command sent down*/
					/* to the adapter to configure 	*/
					/* information such as the data */
					/* transfer rate and so on. Note*/
					/* that care must be taken in 	*/
					/* the transfer of the data in  */
					/* this array to the structure  */
					/* used in the MODE_SELECT 	*/	
					/* command.  The data in this 	*/
					/* array is referenced in terms	*/
					/* of bytes, whereas the data	*/
					/* in the MODE_SELECT structure	*/
					/* is referenced in terms of 	*/	
					/* words (4 bytes)		*/
        uchar		mode_default_data[256]; 
					/* this is the mode default data*/
					/* used to specify what parms   */
					/* if any should be forced to   */
					/* the default values           */
	int		mode_data_length;
					/* This is used to tell how many*/
					/* BYTES of data are held in the*/
					/* mode_select_data array	*/
	int		mode_default_length;
					/* This is used to tell how many*/
					/* BYTES of data are held in the*/
					/* mode_default_data array      */	
	int		reserve_lock;	/* flag to lock target from other*/
					/* initiators. Default is FALSE	*/
					/* When the value is FALSE, a 	*/
					/* TEST_UNIT_READY command is 	*/
					/* sent instead of a RESERVE 	*/
					/* command.  TEST_UNIT_READY is */
					/* used until such time that the*/
					/* SCSI NOP command is recognized*/
};

/************************************************************************/
/* Device capacity data block                                           */
/************************************************************************/
struct cd_capacity {
        int     lba;                    /* last logical block address-1 */
        int     len;                    /* block length in bytes        */
};

/************************************************************************/
/* Request Sense Data Block                                             */
/************************************************************************/
struct cd_req_sense_info  {
       uchar           err_code;        /* error class and code         */
       uchar           rsvd0;
       uchar           sense_key;
       uchar           addr_byte0;
       uchar           addr_byte1;
       uchar           addr_byte2;
       uchar           addr_byte3;
       uchar           add_sense_length;
       uchar           add_sense_byte0;
       uchar           add_sense_byte1;
       uchar           add_sense_byte2;
       uchar           add_sense_byte3;
       uchar           add_sense_key;
       uchar           rsvd1;
       uchar           fru;
       uchar           flag_byte;
       uchar           field_ptrM;
       uchar           field_ptrL;
};

/************************************************************************/
/* Buffer block definition (includes sc_buf)                            */
/************************************************************************/

struct cd_buf_block {
        struct sc_buf         scsi_buf;
        uint                  retry_count;
	uchar		      intrpt;          /* used to wait for      */
					       /* resources             */
        struct cd_disk_df     *disk_ptr;
};

/* 
 * This macro sets the lun for the corresponding cd_buf (struct
 * cd_buf_block). NOTE: It assumes that scsi_cmd.lun has not yet been
 * set (i.e. it zeroes out the lower 5 bits.).
 */
#define CD_SET_CMD_LUN(cd_buf,lun_id) 		         		\
{									\
									\
	(cd_buf)->scsi_buf.lun = (lun_id) & 0xff;			\
									\
	if ((lun_id) > 7 ) {						\
		/*							\
		 * If lun is greater than 7 then zero out		\
		 * the 3 bits in the SCSI CDB used for lun in 		\
		 * SCSI-1 & SCSI 2.					\
		 */							\
		(cd_buf)->scsi_buf.scsi_command.scsi_cmd.lun = 0x0;	\
									\
	}								\
	else {								\
		/*							\
		 * If lun is less then or equal to 7 then set		\
		 * the 3 bits in the SCSI CDB used for lun in 		\
		 * SCSI-1 & SCSI 2 to the lun value as well.		\
		 */							\
									\
		(cd_buf)->scsi_buf.scsi_command.scsi_cmd.lun = 		\
			((lun_id) & 0xff) << 5;				\
									\
	}								\
}


/* 
 * This macro determines if the caller is a 32-bit/64-bit process
 * and does the appropriate copyout call.  The 1st argument, 
 * caller_64bit indicates whether the caller is a 64-bit process or not.
 * The second argument dk_rdwrt is the 32-bit version of the sc_rdwrt 
 * structure and the third argument dk_rdwrt64 is the 64-bit version
 * of sc_rdwrt (sc_rdwrt64).
 */
#define CD_RDWRT_COPYOUT(caller_64bit,arg,dk_rdwrt,dk_rdwrt64)         	\
{									\
							                \      
        if (caller_64bit) {					        \
		 /*							\
		  * 64-bit caller					\
		  */							\
			  						\
                 dk_rdwrt64.status_validity = dk_rdwrt.status_validity; \
	         dk_rdwrt64.scsi_bus_status = dk_rdwrt.scsi_bus_status; \
	         dk_rdwrt64.adapter_status = dk_rdwrt.adapter_status;   \
	         dk_rdwrt64.adap_q_status = dk_rdwrt.adap_q_status;     \
			  						\      
		  copyout(&dk_rdwrt64, (caddr_t)arg,			\
			    sizeof(struct sc_rdwrt64));			\
				    					\     
        } else {							\
									\      
	          /*							\
		   * 32-bit caller					\
		   */							\
		   copyout(&dk_rdwrt, (caddr_t)arg, 			\
			     sizeof(struct sc_rdwrt));			\
	}								\
									\
}

/* 
 * This macro determines if the caller is a 32-bit/64-bit process
 * and does the appropriate copyout call.  The 1st argument, 
 * caller_64bit indicates whether the caller is a 64-bit process or not.
 * The second argument iocmd is the 32-bit version of the sc_iocmd 
 * structure and the third argument iocmd64 is the 64-bit version
 * of sc_iocmd (sc_iocmd64).
 */
#define CD_IOCMD_COPYOUT(caller_64bit,arg,iocmd,iocmd64)    	        \
{									\
							                \      
        if (caller_64bit) {					        \
		 /*							\
		  * 64-bit caller					\
		  */							\
			  						\
                 iocmd64.status_validity = iocmd.status_validity;       \
	         iocmd64.scsi_bus_status = iocmd.scsi_bus_status;       \
	         iocmd64.adapter_status = iocmd.adapter_status;         \
	         iocmd64.adap_q_status = iocmd.adap_q_status;           \
			  						\     
		  copyout(&iocmd64, (caddr_t)arg, 			\
			    sizeof(struct sc_iocmd64));			\
				    					\     
        } else {							\
									\     
	          /*							\
		   * 32-bit caller					\
		   */							\
		   copyout(&iocmd, (caddr_t)arg, 			\
			     sizeof(struct sc_iocmd));			\
	}								\
									\
}

/************************************************************************/
/* Structure used for transfering request sense info on an ioctl.       */
/************************************************************************/
struct cd_ioctl_req_sense {
        struct xmem     xmemd;
        char            *buffer;
        int             count;
};

/************************************************************************/
/* Information on individual disks                                      */
/************************************************************************/
struct cd_disk_df {
        struct watchdog  watchdog_timer;     /* Stucture used for timer      */
        struct cd_buf_block norm_buf;        /* Ptr to scsi buf, etc.        */
        struct cd_buf_block reset_buf;       /* buf block to use for a reset */
        struct cd_buf_block rs_buf;          /* buf block to use for req.sens*/
        struct cd_buf_block ioctl_buf;       /* buf block to use for ioctl's */
        struct sc_error_log_df log_struct;   /* error log structure          */
        struct cd_disk_df *next_defined;     /* Ptr to next defined disk_df  */
        struct cd_disk_df *next_opened;      /* Ptr to next opened disk_df   */
        dev_t            devno;              /* What device number           */
        struct buf       *head;              /* Next buf struct in queue     */
        struct buf       *tail;              /* Last item in queue           */
        struct file      *fp;                /* File pointer for dev-- calls */
        struct buf       rdse_buf_struct;    /* used for CDIORDSE ioctl      */
        struct cd_capacity disk_nblks;       /* Number of blocks on disk     */
        struct cdrom_dds_df disk_ddi;        /* ddi info assoc. with device  */
        struct cd_req_sense_info req_sense_data;/* storage for r.s. data     */
        struct cd_ioctl_req_sense ioctl_req_sense;/* req sense info for ioctl*/
	struct dkstat	 cd_dkstat;	     /* for io statistics measure    */
        int              lock_word;          /* lock structure for this dev  */
        int              reset_count;        /* number of resets tried       */
	uchar		 disk_intrpt;        /* used to wait for resources   */
	uint		 open_event;	     /* open/close event word        */
        uchar            cmd_state;          /* current command              */
        uchar            old_cmd_state;      /* previous command             */
        uchar            reset_state;        /* previous command during reset*/
        uchar            busy;               /* a command is in progress     */
        uchar            open_pending;       /* cd_open started the reset op.*/
        uchar            ioctl_pending;      /* the cmd came from an ioctl   */
        uchar            ioctl_rqst;         /* a CDIORDSE ioctl is waiting  */
        uchar            reset_pending;      /* a device reset is in progress*/
        uchar            error_pending;      /* set if recovering from error */
        uchar            cmd_pending;        /* cmd pending in strategy      */
        uchar            diag_mode;          /* device is open in diag mode  */
        uchar            reset_failed;       /* the device is dead           */
        uchar            failed_errno;       /* errno for the dead device    */
        uchar            opened;             /* the device has been opened   */
        uchar            retain_reservation; /* no release on close          */
	uchar		 card_scsi_id;	     /* SCSI ID of the adapter	     */
	int		 max_transfer;	     /* max transfer size allowed    */
	int		 reserve_lock;	     /* Lock target from other inits */
	int 		 intr_pri;	     /* Interrupt priority prior to  */
					     /* disable_lock.		     */
	Simple_lock	 spin_lock;	     /* CD-ROM Thread-Interrupt Spin */
                                             /* Lock.		             */
};

/************************************************************************/
/* Disk Structure Hash Table Definition                                 */
/************************************************************************/

struct cd_hash_table_df {
        struct cd_disk_df       *defined_head;
        struct cd_disk_df       *opened_head;
};

#ifndef _NO_PROTO
int    cd_config( dev_t devno, int op, struct uio *uiop );
int    cd_open( dev_t devno, int devflag, int chan, int ext );
int    cd_close( dev_t devno, int chan, int ext);
int    cd_read( dev_t devno, struct uio *uiop, int chan, int ext );
int    cd_ioctl( dev_t devno, int op, int arg, ulong dev_flag );
char   cd_open_support( struct cd_disk_df *disk_ptr, int ext,
	char disk_offset );
int    cd_mincnt( struct buf bp, void *minparms );
void   cd_release( struct cd_disk_df *disk_ptr );
void   cd_pass_thru( struct cd_disk_df *disk_ptr, struct sc_iocmd *sc_iocmd_ptr,
 struct xmem *xmem_desc_ptr );
void   cd_device_reset( struct cd_disk_df *disk_ptr );
void   cd_mode_select( struct cd_disk_df *disk_ptr );
void   cd_read_capacity( struct cd_disk_df *disk_ptr );
void   cd_reserve( struct cd_disk_df *disk_ptr );
void   cd_start_stop( struct cd_disk_df *disk_ptr, struct sc_buf *scsi_buf_ptr,
 uchar start_stop_flag );
void   cd_start( struct cd_disk_df *disk_ptr, uchar flag );
uchar  cd_busy( struct cd_disk_df *disk_ptr );
void   cd_watchdog( struct watchdog *watchdog_timer );
int    cd_strategy( struct buf *buf_ptr );
uchar  cd_scsi_error( struct cd_disk_df *disk_ptr );
uchar  cd_adapter_error( struct cd_buf_block *buf_ptr,
 struct cd_disk_df *disk_ptr );
void   cd_iodone( struct buf *bp );

#else

int    cd_config();
int    cd_open();
int    cd_close();
int    cd_read();
char   cd_open_support();
int    cd_ioctl();
int    cd_mincnt();
void   cd_release();
void   cd_pass_thru();
void   cd_device_reset();
void   cd_mode_select();
void   cd_read_capacity();
void   cd_reserve();
void   cd_start_stop();
void   cd_start();
uchar  cd_busy();
void   cd_watchdog();
int    cd_strategy();
uchar  cd_scsi_error();
uchar  cd_adapter_error();
void   cd_iodone();

#endif /* _NO_PROTO */
#endif /* ! _H_CDROMDD */
