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, &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 size_t allocationLength; 171 172 SHOW_FLOW0(3, "patching MODE SENSE(6) to MODE SENSE(10)"); 173 174 request->cdb_length = sizeof(*cdb); 175 memset(cdb, 0, sizeof(*cdb)); 176 177 cdb->opcode = SCSI_OP_MODE_SENSE_10; 178 cdb->disable_block_desc = cmd->disable_block_desc; 179 cdb->lun = cmd->lun; 180 cdb->page_code = cmd->page_code; 181 cdb->page_control = cmd->page_control; 182 183 allocationLength = cmd->allocation_length 184 - sizeof(scsi_cmd_mode_sense_6) + sizeof(scsi_cmd_mode_sense_10); 185 cdb->allocation_length = B_HOST_TO_BENDIAN_INT16(allocationLength); 186 187 SHOW_FLOW(3, "allocation_length=%ld", allocationLength); 188 189 cdb->control = cmd->control; 190 191 // data header of 10 byte version is longer, so use internal buffer 192 // and copy it back once the command is finished 193 get_emulation_buffer(request); 194 replace_request_data(request); 195 196 // restrict data buffer len to length specified in cdb 197 request->data_length = allocationLength; 198 return true; 199 } 200 201 202 /*! All ATAPI devices don't like 6 byte MODE SELECT, so we translate 203 that to 10 byte MODE SELECT 204 */ 205 static bool 206 scsi_start_mode_select_6(scsi_ccb *request) 207 { 208 scsi_device_info *device = request->device; 209 scsi_cmd_mode_select_6 *cmd = (scsi_cmd_mode_select_6 *)request->orig_cdb; 210 scsi_cmd_mode_select_10 *cdb = (scsi_cmd_mode_select_10 *)request->cdb; 211 scsi_mode_param_header_6 header_6; 212 scsi_mode_param_header_10 *header_10 = (scsi_mode_param_header_10 *)device->buffer; 213 size_t param_list_length_6, param_list_length_10; 214 215 SHOW_FLOW0(3, "patching MODE SELECT(6) to MODE SELECT(10)"); 216 217 // calculate new data buffer size 218 param_list_length_6 = cmd->param_list_length; 219 param_list_length_10 = param_list_length_6 220 - sizeof(scsi_mode_param_header_6) + sizeof(scsi_mode_param_header_10); 221 222 // we need to replace data header, thus use internal buffer 223 get_emulation_buffer(request); 224 225 // make sure our buffer is large enough 226 if (param_list_length_10 > device->buffer_size) 227 goto err; 228 229 // construct new cdb 230 request->cdb_length = sizeof(*cdb); 231 memset(cdb, 0, sizeof(*cdb)); 232 233 cdb->opcode = SCSI_OP_MODE_SELECT_10; 234 cdb->save_pages = cmd->save_pages; 235 cdb->pf = cmd->pf; 236 cdb->lun = cmd->lun; 237 cdb->param_list_length = B_HOST_TO_BENDIAN_INT16(param_list_length_10); 238 239 SHOW_FLOW(3, "param_list_length=%ld", param_list_length_6); 240 241 cdb->control = cmd->control; 242 243 // copy and adapt header 244 if (!copy_sg_data(request, 0, param_list_length_6, &header_6, sizeof(header_6), true)) 245 goto err; 246 247 memset(header_10, 0, sizeof(*header_10)); 248 249 // mode_data_len is reserved for MODE SELECT 250 header_10->medium_type = header_6.medium_type; 251 header_10->dev_spec_parameter = header_6.dev_spec_parameter; 252 header_10->block_desc_length = B_HOST_TO_BENDIAN_INT16( 253 (uint16)header_6.block_desc_length); 254 255 // append actual mode select data 256 if (!copy_sg_data(request, sizeof(header_6), param_list_length_6, header_10 + 1, 257 param_list_length_10 - sizeof(*header_10), true)) 258 goto err; 259 260 replace_request_data(request); 261 262 // restrict buffer size to the one specified in cdb 263 request->data_length = param_list_length_10; 264 return true; 265 266 err: 267 release_emulation_buffer(request); 268 269 set_sense(request, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_PARAM_LIST_FIELD); 270 return false; 271 } 272 273 274 /*! Emulation procedure at start of command 275 returns false if command is to be finished without further execution 276 */ 277 bool 278 scsi_start_emulation(scsi_ccb *request) 279 { 280 //snooze( 1000000 ); 281 282 SHOW_FLOW(3, "command=%x", request->cdb[0]); 283 284 memcpy(request->orig_cdb, request->cdb, SCSI_MAX_CDB_SIZE); 285 request->orig_cdb_length = request->cdb_length; 286 287 switch (request->orig_cdb[0]) { 288 case SCSI_OP_READ_6: 289 case SCSI_OP_WRITE_6: 290 return scsi_read_write_6(request); 291 292 case SCSI_OP_MODE_SENSE_6: 293 return scsi_start_mode_sense_6(request); 294 295 case SCSI_OP_MODE_SELECT_6: 296 return scsi_start_mode_select_6(request); 297 } 298 299 return true; 300 } 301 302 303 /*! Back-translate MODE SENSE 10 to MODE SENSE 6 */ 304 static void 305 scsi_finish_mode_sense_10_6(scsi_ccb *request) 306 { 307 scsi_device_info *device = request->device; 308 scsi_mode_param_header_6 header_6; 309 scsi_mode_param_header_10 *header_10 = (scsi_mode_param_header_10 *)device->buffer; 310 int transfer_size_6, transfer_size_10; 311 312 if (request->subsys_status != SCSI_REQ_CMP 313 || request->device_status != SCSI_STATUS_GOOD) { 314 // on error, do nothing 315 restore_request_data(request); 316 release_emulation_buffer(request); 317 return; 318 } 319 320 // check how much data we got from device and thus will copy into 321 // request data 322 transfer_size_10 = request->data_length - request->data_resid; 323 transfer_size_6 = transfer_size_10 324 - sizeof(scsi_mode_param_header_10 *) + sizeof(scsi_mode_param_header_6 *); 325 326 SHOW_FLOW(0, "fixing MODE SENSE(6) (%d bytes)", transfer_size_6); 327 328 restore_request_data(request); 329 330 // adapt header 331 332 // convert total length 333 // (+1 is there because mode_data_len in 10 byte header ignores first 334 // two bytes, whereas in the 6 byte header it ignores only one byte) 335 header_6.mode_data_length = B_BENDIAN_TO_HOST_INT16(header_10->mode_data_length) 336 - sizeof(scsi_mode_param_header_10) + sizeof(scsi_mode_param_header_6) 337 + 1; 338 339 header_6.medium_type = header_10->medium_type; 340 header_6.dev_spec_parameter = header_10->dev_spec_parameter; 341 header_6.block_desc_length = B_BENDIAN_TO_HOST_INT16(header_10->block_desc_length); 342 343 // copy adapted header 344 copy_sg_data(request, 0, transfer_size_6, &header_6, sizeof(header_6), false); 345 346 // copy remaining data 347 copy_sg_data(request, sizeof(header_6), transfer_size_6, 348 header_10 + 1, transfer_size_10 - sizeof(*header_10), false); 349 350 request->data_resid = request->data_length - transfer_size_6; 351 352 release_emulation_buffer(request); 353 } 354 355 356 /*! Back-translate MODE SELECT 10 to MODE SELECT 6 */ 357 static void 358 scsi_finish_mode_select_10_6(scsi_ccb *request) 359 { 360 SHOW_FLOW0(3, "fixing MODE SELECT(6)"); 361 362 // adjust transmission length as we've used the longer 363 // mode select 10 data header 364 request->data_resid += sizeof(scsi_mode_param_header_6) 365 - sizeof(scsi_mode_param_header_10); 366 367 restore_request_data(request); 368 release_emulation_buffer(request); 369 } 370 371 372 /*! Fix inquiry data; some ATAPI devices return wrong version */ 373 static void 374 scsi_finish_inquiry(scsi_ccb *request) 375 { 376 int transferSize; 377 scsi_res_inquiry res; 378 379 SHOW_FLOW0(3, "fixing INQUIRY"); 380 381 if (request->subsys_status != SCSI_REQ_CMP 382 || request->device_status != SCSI_STATUS_GOOD) 383 return; 384 385 transferSize = request->data_length - request->data_resid; 386 387 copy_sg_data(request, 0, transferSize, &res, sizeof(res), true); 388 389 SHOW_FLOW(3, "ANSI version: %d, response data format: %d", 390 res.ansi_version, res.response_data_format); 391 392 res.ansi_version = 2; 393 res.response_data_format = 2; 394 395 copy_sg_data(request, 0, transferSize, &res, sizeof(res), false); 396 } 397 398 399 /*! Adjust result of emulated request */ 400 void 401 scsi_finish_emulation(scsi_ccb *request) 402 { 403 SHOW_FLOW0(3, ""); 404 405 switch ((((int)request->cdb[0]) << 8) | request->orig_cdb[0]) { 406 case (SCSI_OP_MODE_SENSE_10 << 8) | SCSI_OP_MODE_SENSE_6: 407 scsi_finish_mode_sense_10_6(request); 408 break; 409 410 case (SCSI_OP_MODE_SELECT_10 << 8) | SCSI_OP_MODE_SELECT_6: 411 scsi_finish_mode_select_10_6(request); 412 break; 413 414 case (SCSI_OP_INQUIRY << 8) | SCSI_OP_INQUIRY: 415 scsi_finish_inquiry(request); 416 break; 417 } 418 419 // restore cdb 420 memcpy(request->cdb, request->orig_cdb, SCSI_MAX_CDB_SIZE); 421 request->cdb_length = request->orig_cdb_length; 422 } 423 424 425 /*! Set sense of request */ 426 static void 427 set_sense(scsi_ccb *request, int sense_key, int sense_asc) 428 { 429 scsi_sense *sense = (scsi_sense *)request->sense; 430 431 SHOW_FLOW( 3, "sense_key=%d, sense_asc=%d", sense_key, sense_asc ); 432 433 request->subsys_status = SCSI_REQ_CMP; 434 request->device_status = SCSI_STATUS_CHECK_CONDITION; 435 436 // TBD: we can only handle requests with autosense 437 // without autosense, we had to manage virtual sense data, 438 // which is probably not worth the hazzle 439 if ((request->flags & SCSI_DIS_AUTOSENSE) != 0) 440 return; 441 442 memset(sense, 0, sizeof(*sense)); 443 444 sense->error_code = SCSIS_CURR_ERROR; 445 sense->sense_key = sense_key; 446 sense->add_sense_length = sizeof(*sense) - 7; 447 sense->asc = (sense_asc >> 8) & 0xff; 448 sense->ascq = sense_asc; 449 sense->sense_key_spec.raw.SKSV = 0; // no additional info 450 451 request->subsys_status |= SCSI_AUTOSNS_VALID; 452 } 453 454 455 /*! Copy data between request data and buffer 456 request - request to copy data from/to 457 offset - offset of data in request 458 allocation_length- limit of request's data buffer according to CDB 459 buffer - data to copy data from/to 460 size - number of bytes to copy 461 to_buffer - true: copy from request to buffer 462 false: copy from buffer to request 463 return: true, if data of request was large enough 464 */ 465 static bool 466 copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length, 467 void *buffer, int size, bool to_buffer) 468 { 469 const physical_entry *sg_list = request->sg_list; 470 int sg_count = request->sg_count; 471 int req_size; 472 473 SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_count=%d, %s buffer", 474 offset, allocation_length, size, sg_list, sg_count, to_buffer ? "to" : "from"); 475 476 // skip unused S/G entries 477 while (sg_count > 0 && offset >= sg_list->size) { 478 offset -= sg_list->size; 479 ++sg_list; 480 --sg_count; 481 } 482 483 if (sg_count == 0) 484 return 0; 485 486 // remaining bytes we are allowed to copy from/to request 487 req_size = min_c(allocation_length, request->data_length) - offset; 488 489 // copy one S/G entry at a time 490 for (; size > 0 && req_size > 0 && sg_count > 0; ++sg_list, --sg_count) { 491 size_t bytes; 492 493 bytes = min_c(size, req_size); 494 bytes = min_c(bytes, sg_list->size); 495 496 SHOW_FLOW(0, "buffer = %p, virt_addr = %#" B_PRIxPHYSADDR ", bytes = %" 497 B_PRIuSIZE ", to_buffer = %d", buffer, sg_list->address + offset, 498 bytes, to_buffer); 499 500 if (to_buffer) { 501 vm_memcpy_from_physical(buffer, sg_list->address + offset, bytes, 502 false); 503 } else { 504 vm_memcpy_to_physical(sg_list->address + offset, buffer, bytes, 505 false); 506 } 507 508 buffer = (char *)buffer + bytes; 509 size -= bytes; 510 offset = 0; 511 } 512 513 return size == 0; 514 } 515 516 517 /*! Allocate emulation buffer */ 518 static void 519 get_emulation_buffer(scsi_ccb *request) 520 { 521 scsi_device_info *device = request->device; 522 523 SHOW_FLOW0(3, ""); 524 525 acquire_sem(device->buffer_sem); 526 } 527 528 529 /*! Replace request data with emulation buffer, saving original pointer; 530 you must have called get_emulation_buffer() first 531 */ 532 static void 533 replace_request_data(scsi_ccb *request) 534 { 535 scsi_device_info *device = request->device; 536 537 SHOW_FLOW0(3, ""); 538 539 request->orig_sg_list = request->sg_list; 540 request->orig_sg_count = request->sg_count; 541 request->orig_data_length = request->data_length; 542 543 request->sg_list = device->buffer_sg_list; 544 request->sg_count = device->buffer_sg_count; 545 request->data_length = device->buffer_size; 546 } 547 548 549 /*! Release emulation buffer */ 550 static void 551 release_emulation_buffer(scsi_ccb *request) 552 { 553 SHOW_FLOW0(3, ""); 554 555 release_sem(request->device->buffer_sem); 556 } 557 558 559 /*! Restore original request data pointers */ 560 static void 561 restore_request_data(scsi_ccb *request) 562 { 563 SHOW_FLOW0(3, ""); 564 565 request->sg_list = request->orig_sg_list; 566 request->sg_count = request->orig_sg_count; 567 request->data_length = request->orig_data_length; 568 } 569