00001
00041 #ifndef SCSI_CDB_H_INCLUDED
00042 #define SCSI_CDB_H_INCLUDED
00043
00044 #include <assert.h>
00045 #include <types.h>
00046
00047 #include <scsi/spc_protocol.h>
00048
00049 static inline uint16_t scsi_cdb_get_u16(const uint8_t *cdb, unsigned int offset)
00050 {
00051
00052 return (cdb[offset] << 8) | cdb[offset + 1];
00053 }
00054
00055 static inline uint32_t scsi_cdb_get_u32(const uint8_t *cdb, unsigned int offset)
00056 {
00057
00058 return ((cdb[offset] << 24)
00059 | (cdb[offset + 1] << 16)
00060 | (cdb[offset + 2] << 8)
00061 | cdb[offset + 3]);
00062 }
00063
00064 static inline uint8_t scsi_cdb_get_opcode(const uint8_t *cdb)
00065 {
00066 return cdb[0];
00067 }
00068
00069 static inline uint8_t scsi_cdb_get_group_code(const uint8_t *cdb)
00070 {
00071 return scsi_cdb_get_opcode(cdb) >> 5;
00072 }
00073
00074 extern void scsi_cdb_bad_opcode(void);
00075
00076 static inline uint32_t scsi_cdb_get_lba(const uint8_t *cdb,
00077 unsigned int cdb_len)
00078 {
00079 uint32_t lba;
00080
00081 switch (cdb_len) {
00082 case 6:
00083 assert(scsi_cdb_get_group_code(cdb) == 0);
00084 lba = (cdb[1] & 0x1f) << 16;
00085 lba |= cdb[2] << 8;
00086 lba |= cdb[3];
00087 break;
00088
00089 case 10:
00090 assert(scsi_cdb_get_group_code(cdb) == 1
00091 || scsi_cdb_get_group_code(cdb) == 2);
00092 lba = cdb[2] << 24;
00093 lba |= cdb[3] << 16;
00094 lba |= cdb[4] << 8;
00095 lba |= cdb[5];
00096 break;
00097 }
00098
00099 return lba;
00100 }
00101
00102 static inline uint32_t scsi_cdb_get_xfer_len(const uint8_t *cdb,
00103 unsigned int cdb_len)
00104 {
00105 uint32_t len;
00106
00107
00108
00109
00110 switch (cdb_len) {
00111 case 6:
00112 assert(scsi_cdb_get_group_code(cdb) == 0);
00113 len = cdb[4];
00114 if (!len)
00115 len = 256;
00116 break;
00117
00118 case 10:
00119 assert(scsi_cdb_get_group_code(cdb) == 1
00120 || scsi_cdb_get_group_code(cdb) == 2);
00121 len = cdb[7] << 8;
00122 len |= cdb[8];
00123 break;
00124 }
00125
00126 return len;
00127 }
00128
00129 static inline uint32_t scsi_cdb_get_alloc_len(const uint8_t *cdb,
00130 uint8_t opcode)
00131 {
00132 uint32_t len;
00133
00134 switch (opcode) {
00135 case SCSI_CMD_REQUEST_SENSE:
00136 case SCSI_CMD_MODE_SENSE6:
00137 len = cdb[4];
00138 break;
00139 case SCSI_CMD_MODE_SENSE10:
00140 len = scsi_cdb_get_u16(cdb, 7);
00141 break;
00142 }
00143
00144 return len;
00145 }
00146
00147 static inline bool scsi_cdb_bytchk_is_set(const uint8_t *cdb,
00148 unsigned int cdb_len)
00149 {
00150 switch (cdb_len) {
00151 case 10:
00152 return cdb[1] & (1 << 1);
00153 default:
00154 unhandled_case(cdb_len);
00155 return false;
00156 }
00157 }
00158
00159 #endif