iPXE
scsi.h
Go to the documentation of this file.
00001 #ifndef _IPXE_SCSI_H
00002 #define _IPXE_SCSI_H
00003 
00004 #include <stdint.h>
00005 #include <ipxe/uaccess.h>
00006 #include <ipxe/interface.h>
00007 
00008 /** @file
00009  *
00010  * SCSI devices
00011  *
00012  */
00013 
00014 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00015 
00016 /** Maximum block for READ/WRITE (10) commands */
00017 #define SCSI_MAX_BLOCK_10 0xffffffffULL
00018 
00019 /**
00020  * @defgroup scsiops SCSI operation codes
00021  * @{
00022  */
00023 
00024 #define SCSI_OPCODE_READ_10             0x28    /**< READ (10) */
00025 #define SCSI_OPCODE_READ_16             0x88    /**< READ (16) */
00026 #define SCSI_OPCODE_WRITE_10            0x2a    /**< WRITE (10) */
00027 #define SCSI_OPCODE_WRITE_16            0x8a    /**< WRITE (16) */
00028 #define SCSI_OPCODE_READ_CAPACITY_10    0x25    /**< READ CAPACITY (10) */
00029 #define SCSI_OPCODE_SERVICE_ACTION_IN   0x9e    /**< SERVICE ACTION IN */
00030 #define SCSI_SERVICE_ACTION_READ_CAPACITY_16 0x10 /**< READ CAPACITY (16) */
00031 #define SCSI_OPCODE_TEST_UNIT_READY     0x00    /**< TEST UNIT READY */
00032 
00033 /** @} */
00034 
00035 /**
00036  * @defgroup scsiflags SCSI flags
00037  * @{
00038  */
00039 
00040 #define SCSI_FL_FUA_NV          0x02    /**< Force unit access to NVS */
00041 #define SCSI_FL_FUA             0x08    /**< Force unit access */
00042 #define SCSI_FL_DPO             0x10    /**< Disable cache page out */
00043 
00044 /** @} */
00045 
00046 /**
00047  * @defgroup scsicdbs SCSI command data blocks
00048  * @{
00049  */
00050 
00051 /** A SCSI "READ (10)" CDB */
00052 struct scsi_cdb_read_10 {
00053         /** Opcode (0x28) */
00054         uint8_t opcode;
00055         /** Flags */
00056         uint8_t flags;
00057         /** Start address
00058          *
00059          * This is a logical block number, in big-endian order.
00060          */
00061         uint32_t lba;
00062         /** Group number */
00063         uint8_t group;
00064         /** Transfer length
00065          *
00066          * This is a logical block count, in big-endian order.
00067          */
00068         uint16_t len;
00069         /** Control byte */
00070         uint8_t control;
00071 } __attribute__ (( packed ));
00072 
00073 /** A SCSI "READ (16)" CDB */
00074 struct scsi_cdb_read_16 {
00075         /** Opcode (0x88) */
00076         uint8_t opcode;
00077         /** Flags */
00078         uint8_t flags;
00079         /** Start address
00080          *
00081          * This is a logical block number, in big-endian order.
00082          */
00083         uint64_t lba;
00084         /** Transfer length
00085          *
00086          * This is a logical block count, in big-endian order.
00087          */
00088         uint32_t len;
00089         /** Group number */
00090         uint8_t group;
00091         /** Control byte */
00092         uint8_t control;
00093 } __attribute__ (( packed ));
00094 
00095 /** A SCSI "WRITE (10)" CDB */
00096 struct scsi_cdb_write_10 {
00097         /** Opcode (0x2a) */
00098         uint8_t opcode;
00099         /** Flags */
00100         uint8_t flags;
00101         /** Start address
00102          *
00103          * This is a logical block number, in big-endian order.
00104          */
00105         uint32_t lba;
00106         /** Group number */
00107         uint8_t group;
00108         /** Transfer length
00109          *
00110          * This is a logical block count, in big-endian order.
00111          */
00112         uint16_t len;
00113         /** Control byte */
00114         uint8_t control;
00115 } __attribute__ (( packed ));
00116 
00117 /** A SCSI "WRITE (16)" CDB */
00118 struct scsi_cdb_write_16 {
00119         /** Opcode (0x8a) */
00120         uint8_t opcode;
00121         /** Flags */
00122         uint8_t flags;
00123         /** Start address
00124          *
00125          * This is a logical block number, in big-endian order.
00126          */
00127         uint64_t lba;
00128         /** Transfer length
00129          *
00130          * This is a logical block count, in big-endian order.
00131          */
00132         uint32_t len;
00133         /** Group number */
00134         uint8_t group;
00135         /** Control byte */
00136         uint8_t control;
00137 } __attribute__ (( packed ));
00138 
00139 /** A SCSI "READ CAPACITY (10)" CDB */
00140 struct scsi_cdb_read_capacity_10 {
00141         /** Opcode (0x25) */
00142         uint8_t opcode;
00143         /** Reserved */
00144         uint8_t reserved_a;
00145         /** Logical block address
00146          *
00147          * Applicable only if the PMI bit is set.
00148          */
00149         uint32_t lba;
00150         /** Reserved */
00151         uint8_t reserved_b[3];
00152         /** Control byte */
00153         uint8_t control;        
00154 } __attribute__ (( packed ));
00155 
00156 /** SCSI "READ CAPACITY (10)" parameter data */
00157 struct scsi_capacity_10 {
00158         /** Maximum logical block number */
00159         uint32_t lba;
00160         /** Block length in bytes */
00161         uint32_t blksize;
00162 } __attribute__ (( packed ));
00163 
00164 /** A SCSI "READ CAPACITY (16)" CDB */
00165 struct scsi_cdb_read_capacity_16 {
00166         /** Opcode (0x9e) */
00167         uint8_t opcode;
00168         /** Service action */
00169         uint8_t service_action;
00170         /** Logical block address
00171          *
00172          * Applicable only if the PMI bit is set.
00173          */
00174         uint64_t lba;
00175         /** Transfer length
00176          *
00177          * This is the size of the data-in buffer, in bytes.
00178          */
00179         uint32_t len;
00180         /** Reserved */
00181         uint8_t reserved;
00182         /** Control byte */
00183         uint8_t control;
00184 } __attribute__ (( packed ));
00185 
00186 /** SCSI "READ CAPACITY (16)" parameter data */
00187 struct scsi_capacity_16 {
00188         /** Maximum logical block number */
00189         uint64_t lba;
00190         /** Block length in bytes */
00191         uint32_t blksize;
00192         /** Reserved */
00193         uint8_t reserved[20];
00194 } __attribute__ (( packed ));
00195 
00196 /** A SCSI "TEST UNIT READY" CDB */
00197 struct scsi_cdb_test_unit_ready {
00198         /** Opcode (0x00) */
00199         uint8_t opcode;
00200         /** Reserved */
00201         uint8_t reserved[4];
00202         /** Control byte */
00203         uint8_t control;
00204 } __attribute__ (( packed ));
00205 
00206 /** A SCSI Command Data Block */
00207 union scsi_cdb {
00208         struct scsi_cdb_read_10 read10;
00209         struct scsi_cdb_read_16 read16;
00210         struct scsi_cdb_write_10 write10;
00211         struct scsi_cdb_write_16 write16;
00212         struct scsi_cdb_read_capacity_10 readcap10;
00213         struct scsi_cdb_read_capacity_16 readcap16;
00214         struct scsi_cdb_test_unit_ready testready;
00215         unsigned char bytes[16];
00216 };
00217 
00218 /** printf() format for dumping a scsi_cdb */
00219 #define SCSI_CDB_FORMAT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \
00220                         "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
00221 
00222 /** printf() parameters for dumping a scsi_cdb */
00223 #define SCSI_CDB_DATA(cdb)                                                \
00224         (cdb).bytes[0], (cdb).bytes[1], (cdb).bytes[2], (cdb).bytes[3],   \
00225         (cdb).bytes[4], (cdb).bytes[5], (cdb).bytes[6], (cdb).bytes[7],   \
00226         (cdb).bytes[8], (cdb).bytes[9], (cdb).bytes[10], (cdb).bytes[11], \
00227         (cdb).bytes[12], (cdb).bytes[13], (cdb).bytes[14], (cdb).bytes[15]
00228 
00229 /** @} */
00230 
00231 /** A SCSI LUN
00232  *
00233  * This is a four-level LUN as specified by SAM-2, in big-endian
00234  * order.
00235  */
00236 struct scsi_lun {
00237         uint16_t u16[4];
00238 }  __attribute__ (( packed ));
00239 
00240 /** printf() format for dumping a scsi_lun */
00241 #define SCSI_LUN_FORMAT "%04x-%04x-%04x-%04x"
00242 
00243 /** printf() parameters for dumping a scsi_lun */
00244 #define SCSI_LUN_DATA(lun)                                                \
00245         ntohs ( (lun).u16[0] ), ntohs ( (lun).u16[1] ),                   \
00246         ntohs ( (lun).u16[2] ), ntohs ( (lun).u16[3] )
00247 
00248 /** A SCSI command information unit */
00249 struct scsi_cmd {
00250         /** LUN */
00251         struct scsi_lun lun;
00252         /** CDB for this command */
00253         union scsi_cdb cdb;
00254         /** Data-out buffer (may be NULL) */
00255         userptr_t data_out;
00256         /** Data-out buffer length
00257          *
00258          * Must be zero if @c data_out is NULL
00259          */
00260         size_t data_out_len;
00261         /** Data-in buffer (may be NULL) */
00262         userptr_t data_in;
00263         /** Data-in buffer length
00264          *
00265          * Must be zero if @c data_in is NULL
00266          */
00267         size_t data_in_len;
00268 };
00269 
00270 /** SCSI fixed-format sense data */
00271 struct scsi_sns_fixed {
00272         /** Response code */
00273         uint8_t code;
00274         /** Reserved */
00275         uint8_t reserved;
00276         /** Sense key */
00277         uint8_t key;
00278         /** Information */
00279         uint32_t info;
00280         /** Additional sense length */
00281         uint8_t len;
00282         /** Command-specific information */
00283         uint32_t cs_info;
00284         /** Additional sense code and qualifier */
00285         uint16_t additional;
00286 } __attribute__ (( packed ));
00287 
00288 /** SCSI descriptor-format sense data */
00289 struct scsi_sns_descriptor {
00290         /** Response code */
00291         uint8_t code;
00292         /** Sense key */
00293         uint8_t key;
00294         /** Additional sense code and qualifier */
00295         uint16_t additional;
00296 } __attribute__ (( packed ));
00297 
00298 /** SCSI sense data */
00299 union scsi_sns {
00300         /** Response code */
00301         uint8_t code;
00302         /** Fixed-format sense data */
00303         struct scsi_sns_fixed fixed;
00304         /** Descriptor-format sense data */
00305         struct scsi_sns_descriptor desc;
00306 };
00307 
00308 /** SCSI sense response code mask */
00309 #define SCSI_SENSE_CODE_MASK 0x7f
00310 
00311 /** Test if SCSI sense data is in fixed format
00312  *
00313  * @v code              Response code
00314  * @ret is_fixed        Sense data is in fixed format
00315  */
00316 #define SCSI_SENSE_FIXED( code ) ( ( (code) & 0x7e ) == 0x70 )
00317 
00318 /** SCSI sense key mask */
00319 #define SCSI_SENSE_KEY_MASK 0x0f
00320 
00321 /** A SCSI response information unit */
00322 struct scsi_rsp {
00323         /** SCSI status code */
00324         uint8_t status;
00325         /** Data overrun (or negative underrun) */
00326         ssize_t overrun;
00327         /** Autosense data (if any)
00328          *
00329          * To minimise code size, this is stored as the first four
00330          * bytes of a descriptor-format sense data block (even if the
00331          * response code indicates fixed-format sense data).
00332          */
00333         struct scsi_sns_descriptor sense;
00334 };
00335 
00336 extern int scsi_parse_lun ( const char *lun_string, struct scsi_lun *lun );
00337 extern void scsi_parse_sense ( const void *data, size_t len,
00338                                struct scsi_sns_descriptor *sense );
00339 
00340 extern int scsi_command ( struct interface *control, struct interface *data,
00341                           struct scsi_cmd *command );
00342 #define scsi_command_TYPE( object_type )                                \
00343         typeof ( int ( object_type, struct interface *data,             \
00344                        struct scsi_cmd *command ) )
00345 
00346 extern void scsi_response ( struct interface *intf, struct scsi_rsp *response );
00347 #define scsi_response_TYPE( object_type ) \
00348         typeof ( void ( object_type, struct scsi_rsp *response ) )
00349 
00350 extern int scsi_open ( struct interface *block, struct interface *scsi,
00351                        struct scsi_lun *lun );
00352 
00353 #endif /* _IPXE_SCSI_H */