1 /* 2 * Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2002/03, Thomas Kurschel. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 /*! Emulation of SCSI commands that a device cannot handle. 9 10 Some SCSI devices don't support all SCSI commands, especially 11 those connected via ATAPI, USB or FireWire. These commands are 12 emulated here. 13 */ 14 15 16 #include "scsi_internal.h" 17 18 #include <vm/vm.h> 19 20 #include <string.h> 21 22 23 // move some function to end of file to avoid inlining 24 static void set_sense(scsi_ccb *request, int sense_key, int sense_asc); 25 static bool copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length, 26 void *buffer, int size, bool to_buffer); 27 static void get_emulation_buffer(scsi_ccb *request); 28 static void replace_request_data(scsi_ccb *request); 29 static void release_emulation_buffer(scsi_ccb *request); 30 static void restore_request_data(scsi_ccb *request); 31 32 33 /*! Free emulation buffer */ 34 void 35 scsi_free_emulation_buffer(scsi_device_info *device) 36 { 37 if (device->buffer_area) 38 delete_area(device->buffer_area); 39 40 device->buffer_area = 0; 41 device->buffer = NULL; 42 device->buffer_sg_list = NULL; 43 device->buffer_size = 0; 44 45 if (device->buffer_sem > 0) 46 delete_sem(device->buffer_sem); 47 } 48 49 50 /*! Setup buffer used to emulate unsupported SCSI commands 51 buffer_size must be power of two 52 */ 53 status_t 54 scsi_init_emulation_buffer(scsi_device_info *device, size_t buffer_size) 55 { 56 physical_entry map[1]; 57 size_t total_size; 58 59 SHOW_FLOW0(3, ""); 60 61 device->buffer_sem = create_sem(1, "SCSI emulation buffer"); 62 if (device->buffer_sem < 0) { 63 SHOW_ERROR(1, "cannot create DMA buffer semaphore (%s)", strerror(device->buffer_sem)); 64 return device->buffer_sem; 65 } 66 67 // we append S/G list to buffer as it must be locked as well 68 total_size = (buffer_size + sizeof(physical_entry) + B_PAGE_SIZE - 1) 69 & ~(B_PAGE_SIZE - 1); 70 71 void* address; 72 virtual_address_restrictions virtualRestrictions = {}; 73 virtualRestrictions.address_specification = B_ANY_KERNEL_ADDRESS; 74 physical_address_restrictions physicalRestrictions = {}; 75 physicalRestrictions.alignment = buffer_size; 76 device->buffer_area = create_area_etc(B_SYSTEM_TEAM, "ATAPI buffer", 77 total_size, B_32_BIT_CONTIGUOUS, 0, 0, 0, &virtualRestrictions, 78 &physicalRestrictions, &address); 79 // TODO: Use B_CONTIGUOUS, if possible! 80 81 if (device->buffer_area < 0) { 82 SHOW_ERROR( 1, "cannot create DMA buffer (%s)", strerror(device->buffer_area)); 83 84 delete_sem(device->buffer_sem); 85 return device->buffer_area; 86 } 87 88 get_memory_map(address, B_PAGE_SIZE, map, 1); 89 90 // get aligned part 91 phys_addr_t physicalAddress = map[0].address; 92 93 SHOW_FLOW(3, "physical = %#" B_PRIxPHYSADDR ", address = %p", 94 physicalAddress, address); 95 96 device->buffer = (char*)address; 97 device->buffer_size = buffer_size; 98 // s/g list is directly after buffer 99 device->buffer_sg_list = (physical_entry*)((char*)address + buffer_size); 100 device->buffer_sg_list[0].address = physicalAddress; 101 device->buffer_sg_list[0].size = buffer_size; 102 device->buffer_sg_count = 1; 103 104 return B_OK; 105 } 106 107 108 /*! Some ATAPI devices don't like 6 byte read/write commands, so 109 we translate them to their 10 byte counterparts; 110 USB devices usually don't like 10 bytes either 111 */ 112 static bool 113 scsi_read_write_6(scsi_ccb *request) 114 { 115 scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->orig_cdb; 116 scsi_cmd_rw_10 *cdb = (scsi_cmd_rw_10 *)request->cdb; 117 118 SHOW_FLOW0(3, "patching READ/WRITE(6) to READ/WRITE(10)"); 119 120 request->cdb_length = sizeof(*cdb); 121 memset(cdb, 0, sizeof(*cdb)); 122 123 cdb->opcode = cmd->opcode + (SCSI_OP_READ_10 - SCSI_OP_READ_6); 124 cdb->lun = cmd->lun; 125 cdb->lba = B_HOST_TO_BENDIAN_INT32((uint32)cmd->low_lba 126 | ((uint32)cmd->mid_lba << 8) | ((uint32)cmd->high_lba << 16)); 127 if (cmd->length == 0) 128 cdb->length = B_HOST_TO_BENDIAN_INT16(256); 129 else 130 cdb->length = B_HOST_TO_BENDIAN_INT16((uint16)cmd->length); 131 cdb->control = cmd->control; 132 133 #if 0 134 { 135 static uint32 lastLBA = 0; 136 static uint16 lastLength = 0; 137 static uint32 contigCount = 0; 138 static uint64 totalContig = 0; 139 140 uint32 currentLBA = B_BENDIAN_TO_HOST_INT32(cdb->lba); 141 uint16 currentLength = B_BENDIAN_TO_HOST_INT16(cdb->length); 142 143 if (lastLBA + lastLength == currentLBA) { 144 contigCount++; 145 totalContig++; 146 } else 147 contigCount = 0; 148 149 lastLBA = currentLBA; 150 lastLength = currentLength; 151 152 dprintf("scsi_read_write_6: %lld lba %ld; length: %d\n", totalContig, 153 B_BENDIAN_TO_HOST_INT32(cdb->lba), 154 B_BENDIAN_TO_HOST_INT16(cdb->length)); 155 } 156 #endif 157 158 return true; 159 } 160 161 162 /*! All ATAPI devices don't like 6 byte MODE SENSE, so we translate 163 that to 10 byte MODE SENSE 164 */ 165 static bool 166 scsi_start_mode_sense_6(scsi_ccb *request) 167 { 168 scsi_cmd_mode_sense_6 *cmd = (scsi_cmd_mode_sense_6 *)request->orig_cdb; 169 scsi_cmd_mode_sense_10 *cdb = (scsi_cmd_mode_sense_10 *)request->cdb; 170 171 SHOW_FLOW0(3, "patching MODE SENSE(6) to MODE SENSE(10)"); 172 173 request->cdb_length = sizeof(*cdb); 174 memset(cdb, 0, sizeof(*cdb)); 175 176 cdb->opcode = SCSI_OP_MODE_SENSE_10; 177 cdb->disable_block_desc = cmd->disable_block_desc; 178 cdb->lun = cmd->lun; 179 cdb->page_code = cmd->page_code; 180 cdb->page_control = cmd->page_control; 181 182 size_t allocationLength = cmd->allocation_length 183 - sizeof(scsi_cmd_mode_sense_6) + sizeof(scsi_cmd_mode_sense_10); 184 cdb->allocation_length = B_HOST_TO_BENDIAN_INT16(allocationLength); 185 186 SHOW_FLOW(3, "allocation_length=%" B_PRIuSIZE, allocationLength); 187 188 cdb->control = cmd->control; 189 190 // data header of 10 byte version is longer, so use internal buffer 191 // and copy it back once the command is finished 192 get_emulation_buffer(request); 193 replace_request_data(request); 194 195 // restrict data buffer len to length specified in cdb 196 request->data_length = allocationLength; 197 return true; 198 } 199 200 201 /*! All ATAPI devices don't like 6 byte MODE SELECT, so we translate 202 that to 10 byte MODE SELECT 203 */ 204 static bool 205 scsi_start_mode_select_6(scsi_ccb *request) 206 { 207 scsi_device_info *device = request->device; 208 scsi_cmd_mode_select_6 *cmd = (scsi_cmd_mode_select_6 *)request->orig_cdb; 209 scsi_cmd_mode_select_10 *cdb = (scsi_cmd_mode_select_10 *)request->cdb; 210 scsi_mode_param_header_6 header_6; 211 scsi_mode_param_header_10 *header_10 = (scsi_mode_param_header_10 *)device->buffer; 212 size_t param_list_length_6, param_list_length_10; 213 214 SHOW_FLOW0(3, "patching MODE SELECT(6) to MODE SELECT(10)"); 215 216 // calculate new data buffer size 217 param_list_length_6 = cmd->param_list_length; 218 param_list_length_10 = param_list_length_6 219 - sizeof(scsi_mode_param_header_6) + sizeof(scsi_mode_param_header_10); 220 221 // we need to replace data header, thus use internal buffer 222 get_emulation_buffer(request); 223 224 // make sure our buffer is large enough 225 if (param_list_length_10 > device->buffer_size) 226 goto err; 227 228 // construct new cdb 229 request->cdb_length = sizeof(*cdb); 230 memset(cdb, 0, sizeof(*cdb)); 231 232 cdb->opcode = SCSI_OP_MODE_SELECT_10; 233 cdb->save_pages = cmd->save_pages; 234 cdb->pf = cmd->pf; 235 cdb->lun = cmd->lun; 236 cdb->param_list_length = B_HOST_TO_BENDIAN_INT16(param_list_length_10); 237 238 SHOW_FLOW(3, "param_list_length=%ld", param_list_length_6); 239 240 cdb->control = cmd->control; 241 242 // copy and adapt header 243 if (!copy_sg_data(request, 0, param_list_length_6, &header_6, sizeof(header_6), true)) 244 goto err; 245 246 memset(header_10, 0, sizeof(*header_10)); 247 248 // mode_data_len is reserved for MODE SELECT 249 header_10->medium_type = header_6.medium_type; 250 header_10->dev_spec_parameter = header_6.dev_spec_parameter; 251 header_10->block_desc_length = B_HOST_TO_BENDIAN_INT16( 252 (uint16)header_6.block_desc_length); 253 254 // append actual mode select data 255 if (!copy_sg_data(request, sizeof(header_6), param_list_length_6, header_10 + 1, 256 param_list_length_10 - sizeof(*header_10), true)) 257 goto err; 258 259 replace_request_data(request); 260 261 // restrict buffer size to the one specified in cdb 262 request->data_length = param_list_length_10; 263 return true; 264 265 err: 266 release_emulation_buffer(request); 267 268 set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_PARAM_LIST_FIELD); 269 return false; 270 } 271 272 273 /*! Emulation procedure at start of command 274 returns false if command is to be finished without further execution 275 */ 276 bool 277 scsi_start_emulation(scsi_ccb *request) 278 { 279 //snooze( 1000000 ); 280 281 SHOW_FLOW(3, "command=%x", request->cdb[0]); 282 283 memcpy(request->orig_cdb, request->cdb, SCSI_MAX_CDB_SIZE); 284 request->orig_cdb_length = request->cdb_length; 285 286 switch (request->orig_cdb[0]) { 287 case SCSI_OP_READ_6: 288 case SCSI_OP_WRITE_6: 289 return scsi_read_write_6(request); 290 291 case SCSI_OP_MODE_SENSE_6: 292 return scsi_start_mode_sense_6(request); 293 294 case SCSI_OP_MODE_SELECT_6: 295 return scsi_start_mode_select_6(request); 296 } 297 298 return true; 299 } 300 301 302 /*! Back-translate MODE SENSE 10 to MODE SENSE 6 */ 303 static void 304 scsi_finish_mode_sense_10_6(scsi_ccb *request) 305 { 306 scsi_device_info *device = request->device; 307 scsi_mode_param_header_6 header_6; 308 scsi_mode_param_header_10 *header_10 = (scsi_mode_param_header_10 *)device->buffer; 309 int transfer_size_6, transfer_size_10; 310 311 if (request->subsys_status != SCSI_REQ_CMP 312 || request->device_status != SCSI_STATUS_GOOD) { 313 // on error, do nothing 314 restore_request_data(request); 315 release_emulation_buffer(request); 316 return; 317 } 318 319 // check how much data we got from device and thus will copy into 320 // request data 321 transfer_size_10 = request->data_length - request->data_resid; 322 transfer_size_6 = transfer_size_10 323 - sizeof(scsi_mode_param_header_10 *) + sizeof(scsi_mode_param_header_6 *); 324 325 SHOW_FLOW(0, "fixing MODE SENSE(6) (%d bytes)", transfer_size_6); 326 327 restore_request_data(request); 328 329 // adapt header 330 331 // convert total length 332 // (+1 is there because mode_data_len in 10 byte header ignores first 333 // two bytes, whereas in the 6 byte header it ignores only one byte) 334 header_6.mode_data_length = B_BENDIAN_TO_HOST_INT16(header_10->mode_data_length) 335 - sizeof(scsi_mode_param_header_10) + sizeof(scsi_mode_param_header_6) 336 + 1; 337 338 header_6.medium_type = header_10->medium_type; 339 header_6.dev_spec_parameter = header_10->dev_spec_parameter; 340 header_6.block_desc_length = B_BENDIAN_TO_HOST_INT16(header_10->block_desc_length); 341 342 // copy adapted header 343 copy_sg_data(request, 0, transfer_size_6, &header_6, sizeof(header_6), false); 344 345 // copy remaining data 346 copy_sg_data(request, sizeof(header_6), transfer_size_6, 347 header_10 + 1, transfer_size_10 - sizeof(*header_10), false); 348 349 request->data_resid = request->data_length - transfer_size_6; 350 351 release_emulation_buffer(request); 352 } 353 354 355 /*! Back-translate MODE SELECT 10 to MODE SELECT 6 */ 356 static void 357 scsi_finish_mode_select_10_6(scsi_ccb *request) 358 { 359 SHOW_FLOW0(3, "fixing MODE SELECT(6)"); 360 361 // adjust transmission length as we've used the longer 362 // mode select 10 data header 363 request->data_resid += sizeof(scsi_mode_param_header_6) 364 - sizeof(scsi_mode_param_header_10); 365 366 restore_request_data(request); 367 release_emulation_buffer(request); 368 } 369 370 371 /*! Fix inquiry data; some ATAPI devices return wrong version */ 372 static void 373 scsi_finish_inquiry(scsi_ccb *request) 374 { 375 int transferSize; 376 scsi_res_inquiry res; 377 378 SHOW_FLOW0(3, "fixing INQUIRY"); 379 380 if (request->subsys_status != SCSI_REQ_CMP 381 || request->device_status != SCSI_STATUS_GOOD) 382 return; 383 384 transferSize = request->data_length - request->data_resid; 385 386 copy_sg_data(request, 0, transferSize, &res, sizeof(res), true); 387 388 SHOW_FLOW(3, "ANSI version: %d, response data format: %d", 389 res.ansi_version, res.response_data_format); 390 391 res.ansi_version = 2; 392 res.response_data_format = 2; 393 394 copy_sg_data(request, 0, transferSize, &res, sizeof(res), false); 395 } 396 397 398 /*! Adjust result of emulated request */ 399 void 400 scsi_finish_emulation(scsi_ccb *request) 401 { 402 SHOW_FLOW0(3, ""); 403 404 switch ((((int)request->cdb[0]) << 8) | request->orig_cdb[0]) { 405 case (SCSI_OP_MODE_SENSE_10 << 8) | SCSI_OP_MODE_SENSE_6: 406 scsi_finish_mode_sense_10_6(request); 407 break; 408 409 case (SCSI_OP_MODE_SELECT_10 << 8) | SCSI_OP_MODE_SELECT_6: 410 scsi_finish_mode_select_10_6(request); 411 break; 412 413 case (SCSI_OP_INQUIRY << 8) | SCSI_OP_INQUIRY: 414 scsi_finish_inquiry(request); 415 break; 416 } 417 418 // restore cdb 419 memcpy(request->cdb, request->orig_cdb, SCSI_MAX_CDB_SIZE); 420 request->cdb_length = request->orig_cdb_length; 421 } 422 423 424 /*! Set sense of request */ 425 static void 426 set_sense(scsi_ccb *request, int sense_key, int sense_asc) 427 { 428 scsi_sense *sense = (scsi_sense *)request->sense; 429 430 SHOW_FLOW( 3, "sense_key=%d, sense_asc=%d", sense_key, sense_asc ); 431 432 request->subsys_status = SCSI_REQ_CMP; 433 request->device_status = SCSI_STATUS_CHECK_CONDITION; 434 435 // TBD: we can only handle requests with autosense 436 // without autosense, we had to manage virtual sense data, 437 // which is probably not worth the hazzle 438 if ((request->flags & SCSI_DIS_AUTOSENSE) != 0) 439 return; 440 441 memset(sense, 0, sizeof(*sense)); 442 443 sense->error_code = SCSIS_CURR_ERROR; 444 sense->sense_key = sense_key; 445 sense->add_sense_length = sizeof(*sense) - 7; 446 sense->asc = (sense_asc >> 8) & 0xff; 447 sense->ascq = sense_asc; 448 sense->sense_key_spec.raw.SKSV = 0; // no additional info 449 450 request->subsys_status |= SCSI_AUTOSNS_VALID; 451 } 452 453 454 /*! Copy data between request data and buffer 455 request - request to copy data from/to 456 offset - offset of data in request 457 allocation_length- limit of request's data buffer according to CDB 458 buffer - data to copy data from/to 459 size - number of bytes to copy 460 to_buffer - true: copy from request to buffer 461 false: copy from buffer to request 462 return: true, if data of request was large enough 463 */ 464 static bool 465 copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length, 466 void *buffer, int size, bool to_buffer) 467 { 468 const physical_entry *sg_list = request->sg_list; 469 int sg_count = request->sg_count; 470 int req_size; 471 472 SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_count=%d, %s buffer", 473 offset, allocation_length, size, sg_list, sg_count, to_buffer ? "to" : "from"); 474 475 // skip unused S/G entries 476 while (sg_count > 0 && offset >= sg_list->size) { 477 offset -= sg_list->size; 478 ++sg_list; 479 --sg_count; 480 } 481 482 if (sg_count == 0) 483 return 0; 484 485 // remaining bytes we are allowed to copy from/to request 486 req_size = min_c(allocation_length, request->data_length) - offset; 487 488 // copy one S/G entry at a time 489 for (; size > 0 && req_size > 0 && sg_count > 0; ++sg_list, --sg_count) { 490 size_t bytes; 491 492 bytes = min_c(size, req_size); 493 bytes = min_c(bytes, sg_list->size); 494 495 SHOW_FLOW(0, "buffer = %p, virt_addr = %#" B_PRIxPHYSADDR ", bytes = %" 496 B_PRIuSIZE ", to_buffer = %d", buffer, sg_list->address + offset, 497 bytes, to_buffer); 498 499 if (to_buffer) { 500 vm_memcpy_from_physical(buffer, sg_list->address + offset, bytes, 501 false); 502 } else { 503 vm_memcpy_to_physical(sg_list->address + offset, buffer, bytes, 504 false); 505 } 506 507 buffer = (char *)buffer + bytes; 508 size -= bytes; 509 offset = 0; 510 } 511 512 return size == 0; 513 } 514 515 516 /*! Allocate emulation buffer */ 517 static void 518 get_emulation_buffer(scsi_ccb *request) 519 { 520 scsi_device_info *device = request->device; 521 522 SHOW_FLOW0(3, ""); 523 524 acquire_sem(device->buffer_sem); 525 } 526 527 528 /*! Replace request data with emulation buffer, saving original pointer; 529 you must have called get_emulation_buffer() first 530 */ 531 static void 532 replace_request_data(scsi_ccb *request) 533 { 534 scsi_device_info *device = request->device; 535 536 SHOW_FLOW0(3, ""); 537 538 request->orig_sg_list = request->sg_list; 539 request->orig_sg_count = request->sg_count; 540 request->orig_data_length = request->data_length; 541 542 request->sg_list = device->buffer_sg_list; 543 request->sg_count = device->buffer_sg_count; 544 request->data_length = device->buffer_size; 545 } 546 547 548 /*! Release emulation buffer */ 549 static void 550 release_emulation_buffer(scsi_ccb *request) 551 { 552 SHOW_FLOW0(3, ""); 553 554 release_sem(request->device->buffer_sem); 555 } 556 557 558 /*! Restore original request data pointers */ 559 static void 560 restore_request_data(scsi_ccb *request) 561 { 562 SHOW_FLOW0(3, ""); 563 564 request->sg_list = request->orig_sg_list; 565 request->sg_count = request->orig_sg_count; 566 request->data_length = request->orig_data_length; 567 } 568