1 /* 2 * SCSI commands related implementation 3 */ 4 5 #include <minix/blockdriver.h> /* SECTOR_SIZE */ 6 7 #include <assert.h> 8 #include <string.h> /* strncpy */ 9 10 #include "common.h" 11 #include "scsi.h" 12 13 /*---------------------------* 14 * declared functions * 15 *---------------------------*/ 16 /* To work correctly cbw->CBWCB must be zeroed before calling these: */ 17 static int create_inquiry_scsi_cmd(mass_storage_cbw *); 18 static int create_test_scsi_cmd(mass_storage_cbw *); 19 static int create_read_capacity_scsi_cmd(mass_storage_cbw *); 20 static int create_write_scsi_cmd(mass_storage_cbw *, scsi_transfer *); 21 static int create_read_scsi_cmd(mass_storage_cbw *, scsi_transfer *); 22 static int create_mode_sense_scsi_cmd(mass_storage_cbw *); 23 static int create_request_sense_scsi_cmd(mass_storage_cbw *); 24 25 /*---------------------------* 26 * defined functions * 27 *---------------------------*/ 28 /*===========================================================================* 29 * create_scsi_cmd * 30 *===========================================================================*/ 31 int 32 create_scsi_cmd(mass_storage_cbw * cbw, int cmd, scsi_transfer * info) 33 { 34 MASS_DEBUG_DUMP; 35 36 assert(NULL != cbw); 37 38 switch (cmd) { 39 case SCSI_INQUIRY: 40 return create_inquiry_scsi_cmd(cbw); 41 case SCSI_TEST_UNIT_READY: 42 return create_test_scsi_cmd(cbw); 43 case SCSI_READ_CAPACITY: 44 return create_read_capacity_scsi_cmd(cbw); 45 case SCSI_WRITE: 46 return create_write_scsi_cmd(cbw, info); 47 case SCSI_READ: 48 return create_read_scsi_cmd(cbw, info); 49 case SCSI_MODE_SENSE: 50 return create_mode_sense_scsi_cmd(cbw); 51 case SCSI_REQUEST_SENSE: 52 return create_request_sense_scsi_cmd(cbw); 53 default: 54 MASS_MSG("Invalid SCSI command!"); 55 return EXIT_FAILURE; 56 } 57 } 58 59 60 /*===========================================================================* 61 * create_inquiry_scsi_cmd * 62 *===========================================================================*/ 63 static int 64 create_inquiry_scsi_cmd(mass_storage_cbw * cbw) 65 { 66 MASS_DEBUG_DUMP; 67 68 cbw->dCBWDataTransferLength = SCSI_INQUIRY_DATA_LEN; 69 cbw->bCBWFlags = CBW_FLAGS_IN; 70 cbw->bCDBLength = SCSI_INQUIRY_CMD_LEN; 71 72 SCSI_SET_INQUIRY_OP_CODE(cbw->CBWCB); 73 SCSI_SET_INQUIRY_PAGE_CODE(cbw->CBWCB, 0); 74 SCSI_SET_INQUIRY_ALLOC_LEN(cbw->CBWCB, SCSI_INQUIRY_DATA_LEN); 75 76 return EXIT_SUCCESS; 77 } 78 79 80 /*===========================================================================* 81 * create_test_scsi_cmd * 82 *===========================================================================*/ 83 static int 84 create_test_scsi_cmd(mass_storage_cbw * cbw) 85 { 86 MASS_DEBUG_DUMP; 87 88 cbw->bCDBLength = SCSI_TEST_CMD_LEN; 89 90 SCSI_SET_TEST_OP_CODE(cbw->CBWCB); 91 92 return EXIT_SUCCESS; 93 } 94 95 96 /*===========================================================================* 97 * create_read_capacity_scsi_cmd * 98 *===========================================================================*/ 99 static int 100 create_read_capacity_scsi_cmd(mass_storage_cbw * cbw) 101 { 102 MASS_DEBUG_DUMP; 103 104 cbw->dCBWDataTransferLength = SCSI_READ_CAPACITY_DATA_LEN; 105 cbw->bCBWFlags = CBW_FLAGS_IN; 106 cbw->bCDBLength = SCSI_READ_CAPACITY_CMD_LEN; 107 108 SCSI_SET_READ_CAPACITY_OP_CODE(cbw->CBWCB); 109 SCSI_SET_READ_CAPACITY_LBA(cbw->CBWCB, 0x00); 110 111 return EXIT_SUCCESS; 112 } 113 114 115 /*===========================================================================* 116 * create_write_scsi_cmd * 117 *===========================================================================*/ 118 static int 119 create_write_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info) 120 { 121 MASS_DEBUG_DUMP; 122 123 assert(NULL != info); 124 assert(0 == (info->length % SECTOR_SIZE)); 125 126 cbw->dCBWDataTransferLength = info->length; 127 cbw->bCBWFlags = CBW_FLAGS_OUT; 128 cbw->bCDBLength = SCSI_WRITE_CMD_LEN; 129 130 SCSI_SET_WRITE_OP_CODE(cbw->CBWCB); 131 SCSI_SET_WRITE_LBA(cbw->CBWCB, info->lba); 132 SCSI_SET_WRITE_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE); 133 134 return EXIT_SUCCESS; 135 } 136 137 138 /*===========================================================================* 139 * create_read_scsi_cmd * 140 *===========================================================================*/ 141 static int 142 create_read_scsi_cmd(mass_storage_cbw * cbw, scsi_transfer * info) 143 { 144 MASS_DEBUG_DUMP; 145 146 assert(NULL != info); 147 assert(0 == (info->length % SECTOR_SIZE)); 148 149 cbw->dCBWDataTransferLength = info->length; 150 cbw->bCBWFlags = CBW_FLAGS_IN; 151 cbw->bCDBLength = SCSI_READ_CMD_LEN; 152 153 SCSI_SET_READ_OP_CODE(cbw->CBWCB); 154 SCSI_SET_READ_LBA(cbw->CBWCB, info->lba); 155 SCSI_SET_READ_BLEN(cbw->CBWCB, info->length / SECTOR_SIZE); 156 157 return EXIT_SUCCESS; 158 } 159 160 161 /*===========================================================================* 162 * create_mode_sense_scsi_cmd * 163 *===========================================================================*/ 164 static int 165 create_mode_sense_scsi_cmd(mass_storage_cbw * cbw) 166 { 167 MASS_DEBUG_DUMP; 168 169 cbw->dCBWDataTransferLength = SCSI_MODE_SENSE_FLEX_DATA_LEN; 170 cbw->bCBWFlags = CBW_FLAGS_IN; 171 cbw->bCDBLength = SCSI_MODE_SENSE_CMD_LEN; 172 173 SCSI_SET_MODE_SENSE_OP_CODE(cbw->CBWCB); 174 SCSI_SET_MODE_SENSE_PAGE_CODE(cbw->CBWCB, 175 SCSI_MODE_SENSE_FLEXIBLE_DISK_PAGE); 176 177 return EXIT_SUCCESS; 178 } 179 180 181 /*===========================================================================* 182 * create_request_sense_scsi_cmd * 183 *===========================================================================*/ 184 static int 185 create_request_sense_scsi_cmd(mass_storage_cbw * cbw) 186 { 187 MASS_DEBUG_DUMP; 188 189 cbw->dCBWDataTransferLength = SCSI_REQUEST_SENSE_DATA_LEN; 190 cbw->bCBWFlags = CBW_FLAGS_IN; 191 cbw->bCDBLength = SCSI_REQUEST_SENSE_CMD_LEN; 192 193 SCSI_SET_REQUEST_SENSE_OP_CODE(cbw->CBWCB); 194 SCSI_SET_REQUEST_SENSE_ALLOC(cbw->CBWCB, SCSI_REQUEST_SENSE_DATA_LEN); 195 196 return EXIT_SUCCESS; 197 } 198 199 200 /*===========================================================================* 201 * check_inquiry_reply * 202 *===========================================================================*/ 203 int 204 check_inquiry_reply(uint8_t * scsi_reply) 205 { 206 char vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN + 1]; 207 char product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN + 1]; 208 209 MASS_DEBUG_DUMP; 210 211 /* Stop condition for printing as strncpy() does not add it */ 212 vendor_name[SCSI_INQUIRY_VENDOR_NAME_LEN] = '\0'; 213 product_name[SCSI_INQUIRY_PRODUCT_NAME_LEN] = '\0'; 214 215 if (SCSI_GET_INQUIRY_PERIPH_QUALIF(scsi_reply)) { 216 MASS_MSG("Device not connected"); 217 return EXIT_FAILURE; 218 } 219 220 strncpy(vendor_name, SCSI_GET_INQUIRY_VENDOR_NAME(scsi_reply), 221 SCSI_INQUIRY_VENDOR_NAME_LEN); 222 strncpy(product_name, SCSI_GET_INQUIRY_PRODUCT_NAME(scsi_reply), 223 SCSI_INQUIRY_PRODUCT_NAME_LEN); 224 225 MASS_DEBUG_MSG("Vendor name: %s", vendor_name); 226 MASS_DEBUG_MSG("Product name %s", product_name); 227 228 return EXIT_SUCCESS; 229 } 230 231 232 /*===========================================================================* 233 * check_read_capacity_reply * 234 *===========================================================================*/ 235 int 236 check_read_capacity_reply(uint8_t * scsi_reply, uint32_t * lba, uint32_t * blen) 237 { 238 MASS_DEBUG_DUMP; 239 240 *lba = SCSI_GET_READ_CAPACITY_LBA(scsi_reply); 241 *blen = SCSI_GET_READ_CAPACITY_BLEN(scsi_reply); 242 243 return EXIT_SUCCESS; 244 } 245 246 247 /*===========================================================================* 248 * check_mode_sense_reply * 249 *===========================================================================*/ 250 int 251 check_mode_sense_reply(uint8_t * scsi_reply, unsigned * cyl, 252 unsigned * head, unsigned * sect) 253 { 254 MASS_DEBUG_DUMP; 255 256 *cyl = SCSI_GET_MODE_SENSE_CYLINDERS(scsi_reply); 257 *head = SCSI_GET_MODE_SENSE_HEADS(scsi_reply); 258 *sect = SCSI_GET_MODE_SENSE_SECTORS(scsi_reply); 259 260 return EXIT_SUCCESS; 261 } 262 263 264 /*===========================================================================* 265 * check_csw * 266 *===========================================================================*/ 267 int 268 check_csw(mass_storage_csw * csw, unsigned int tag) 269 { 270 MASS_DEBUG_DUMP; 271 272 if (csw->dCSWTag != tag) { 273 MASS_MSG("CSW tag mismatch!"); 274 return EXIT_FAILURE; 275 } 276 277 if (CSW_SIGNATURE != csw->dCSWSignature) { 278 MASS_MSG("CSW signature mismatch!"); 279 return EXIT_FAILURE; 280 } 281 282 if (CSW_STATUS_GOOD != csw->bCSWStatus) { 283 MASS_MSG("CSW status error (0x%02X)!", csw->bCSWStatus); 284 return EXIT_FAILURE; 285 } 286 287 return EXIT_SUCCESS; 288 } 289