1 /* 2 * Copyright 2004-2007, Haiku, Inc. All RightsReserved. 3 * Copyright 2002-2004, Thomas Kurschel. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 //! Part of Open SCSI bus manager 9 10 11 #include "scsi_internal.h" 12 #include "queuing.h" 13 14 #include <string.h> 15 16 #include <algorithm> 17 18 19 /** put request back in queue because of device/bus overflow */ 20 21 void 22 scsi_requeue_request(scsi_ccb *request, bool bus_overflow) 23 { 24 scsi_bus_info *bus = request->bus; 25 scsi_device_info *device = request->device; 26 bool was_servicable, start_retry; 27 28 SHOW_FLOW0(3, ""); 29 30 if (request->state != SCSI_STATE_SENT) { 31 panic("Unsent ccb was request to requeue\n"); 32 return; 33 } 34 35 request->state = SCSI_STATE_QUEUED; 36 37 mutex_lock(&bus->mutex); 38 39 was_servicable = scsi_can_service_bus(bus); 40 41 if (bus->left_slots++ == 0) 42 scsi_unblock_bus_noresume(bus, false); 43 44 if (device->left_slots++ == 0 || request->ordered) 45 scsi_unblock_device_noresume(device, false); 46 47 // make sure it's the next request for this device 48 scsi_add_req_queue_first(request); 49 50 if (bus_overflow) { 51 // bus has overflown 52 scsi_set_bus_overflow(bus); 53 // add device to queue as last - other devices may be waiting already 54 scsi_add_device_queue_last(device); 55 // don't change device overflow condition as the device has never seen 56 // this request 57 } else { 58 // device has overflown 59 scsi_set_device_overflow(device); 60 scsi_remove_device_queue(device); 61 // either, the device has refused the request, i.e. it was transmitted 62 // over the bus - in this case, the bus cannot be overloaded anymore; 63 // or, the driver detected that the device can not be able to process 64 // further requests, because the driver knows its maximum queue depth 65 // or something - in this case, the bus state hasn't changed, but the 66 // driver will tell us about any overflow when we submit the next 67 // request, so the overflow state will be fixed automatically 68 scsi_clear_bus_overflow(bus); 69 } 70 71 start_retry = !was_servicable && scsi_can_service_bus(bus); 72 73 mutex_unlock(&bus->mutex); 74 75 // submit requests to other devices in case bus was overloaded 76 if (start_retry) 77 release_sem_etc(bus->start_service, 1, 0/*B_DO_NOT_RESCHEDULE*/); 78 } 79 80 81 /** restart request ASAP because something went wrong */ 82 83 void 84 scsi_resubmit_request(scsi_ccb *request) 85 { 86 scsi_bus_info *bus = request->bus; 87 scsi_device_info *device = request->device; 88 bool was_servicable, start_retry; 89 90 SHOW_FLOW0(3, ""); 91 92 if (request->state != SCSI_STATE_SENT) { 93 panic("Unsent ccb was asked to get resubmitted\n"); 94 return; 95 } 96 97 request->state = SCSI_STATE_QUEUED; 98 99 mutex_lock(&bus->mutex); 100 101 was_servicable = scsi_can_service_bus(bus); 102 103 if (bus->left_slots++ == 0) 104 scsi_unblock_bus_noresume(bus, false); 105 106 if (device->left_slots++ == 0 || request->ordered) 107 scsi_unblock_device_noresume(device, false); 108 109 // if SIM reported overflow of device/bus, this should (hopefully) be over now 110 scsi_clear_device_overflow(device); 111 scsi_clear_bus_overflow(bus); 112 113 // we don't want to let anyone overtake this request 114 request->ordered = true; 115 116 // make it the next request submitted to SIM for this device 117 scsi_add_req_queue_first(request); 118 119 // if device is not blocked (anymore) add it to waiting list of bus 120 if (device->lock_count == 0) { 121 scsi_add_device_queue_first(device); 122 // as previous line does nothing if already queued, we force device 123 // to be the next one to get handled 124 bus->waiting_devices = device; 125 } 126 127 start_retry = !was_servicable && scsi_can_service_bus(bus); 128 129 mutex_unlock(&bus->mutex); 130 131 // let the service thread do the resubmit 132 if (start_retry) 133 release_sem_etc(bus->start_service, 1, 0/*B_DO_NOT_RESCHEDULE*/); 134 } 135 136 137 /** submit autosense for request */ 138 139 static void 140 submit_autosense(scsi_ccb *request) 141 { 142 scsi_device_info *device = request->device; 143 144 //snooze(1000000); 145 146 SHOW_FLOW0(3, "sending autosense"); 147 // we cannot use scsi_scsi_io but must insert it brute-force 148 149 // give SIM a well-defined first state 150 // WARNING: this is a short version of scsi_async_io, so if 151 // you change something there, do it here as well! 152 153 // no DMA buffer (we made sure that the data buffer fulfills all 154 // limitations) 155 device->auto_sense_request->buffered = false; 156 // don't let any request bypass us 157 device->auto_sense_request->ordered = true; 158 // request is not emulated 159 device->auto_sense_request->emulated = false; 160 161 device->auto_sense_originator = request; 162 163 // make it next request to process 164 scsi_add_queued_request_first(device->auto_sense_request); 165 } 166 167 168 /** finish special auto-sense request */ 169 170 static void 171 finish_autosense(scsi_device_info *device) 172 { 173 scsi_ccb *orig_request = device->auto_sense_originator; 174 scsi_ccb *request = device->auto_sense_request; 175 176 SHOW_FLOW0(3, ""); 177 178 if (request->subsys_status == SCSI_REQ_CMP) { 179 int sense_len; 180 181 // we got sense data -> copy it to sense buffer 182 sense_len = std::min((uint32)SCSI_MAX_SENSE_SIZE, 183 request->data_length - request->data_resid); 184 185 SHOW_FLOW(3, "Got sense: %d bytes", sense_len); 186 187 memcpy(orig_request->sense, request->data, sense_len); 188 189 orig_request->sense_resid = SCSI_MAX_SENSE_SIZE - sense_len; 190 orig_request->subsys_status |= SCSI_AUTOSNS_VALID; 191 } else { 192 // failed to get sense 193 orig_request->subsys_status = SCSI_AUTOSENSE_FAIL; 194 } 195 196 // inform peripheral driver 197 orig_request->completion_cond.NotifyAll(); 198 } 199 200 201 /** device refused request because command queue is full */ 202 203 static void 204 scsi_device_queue_overflow(scsi_ccb *request, uint num_requests) 205 { 206 scsi_bus_info *bus = request->bus; 207 scsi_device_info *device = request->device; 208 int diff_max_slots; 209 210 // set maximum number of concurrent requests to number of 211 // requests running when QUEUE FULL condition occurred - 1 212 // (the "1" is the refused request) 213 --num_requests; 214 215 // at least one request at once must be possible 216 if (num_requests < 1) 217 num_requests = 1; 218 219 SHOW_INFO(2, "Restricting device queue to %d requests", num_requests); 220 221 // update slot count 222 mutex_lock(&bus->mutex); 223 224 diff_max_slots = device->total_slots - num_requests; 225 device->total_slots = num_requests; 226 device->left_slots -= diff_max_slots; 227 228 mutex_unlock(&bus->mutex); 229 230 // requeue request, blocking further device requests 231 scsi_requeue_request(request, false); 232 } 233 234 235 /** finish scsi request */ 236 237 void 238 scsi_request_finished(scsi_ccb *request, uint num_requests) 239 { 240 scsi_device_info *device = request->device; 241 scsi_bus_info *bus = request->bus; 242 bool was_servicable, start_service, do_autosense; 243 244 SHOW_FLOW(3, "%p", request); 245 246 if (request->state != SCSI_STATE_SENT) { 247 panic("Unsent ccb %p was reported as done\n", request); 248 return; 249 } 250 251 if (request->subsys_status == SCSI_REQ_INPROG) { 252 panic("ccb %p with status \"Request in Progress\" was reported as done\n", 253 request); 254 return; 255 } 256 257 // check for queue overflow reported by device 258 if (request->subsys_status == SCSI_REQ_CMP_ERR 259 && request->device_status == SCSI_STATUS_QUEUE_FULL) { 260 scsi_device_queue_overflow(request, num_requests); 261 return; 262 } 263 264 request->state = SCSI_STATE_FINISHED; 265 266 mutex_lock(&bus->mutex); 267 268 was_servicable = scsi_can_service_bus(bus); 269 270 // do pseudo-autosense if device doesn't support it and 271 // device reported a check condition state and auto-sense haven't 272 // been retrieved by SIM 273 // (last test is implicit as SIM adds SCSI_AUTOSNS_VALID to subsys_status) 274 do_autosense = device->manual_autosense 275 && (request->flags & SCSI_DIS_AUTOSENSE) == 0 276 && request->subsys_status == SCSI_REQ_CMP_ERR 277 && request->device_status == SCSI_STATUS_CHECK_CONDITION; 278 279 if (request->subsys_status != SCSI_REQ_CMP) { 280 SHOW_FLOW(3, "subsys=%x, device=%x, flags=%" B_PRIx32 281 ", manual_auto_sense=%d", request->subsys_status, 282 request->device_status, request->flags, device->manual_autosense); 283 } 284 285 if (do_autosense) { 286 // queue auto-sense request after checking was_servicable but before 287 // releasing locks so no other request overtakes auto-sense 288 submit_autosense(request); 289 } 290 291 if (bus->left_slots++ == 0) 292 scsi_unblock_bus_noresume(bus, false); 293 294 if (device->left_slots++ == 0 || request->ordered) 295 scsi_unblock_device_noresume(device, false); 296 297 // if SIM reported overflow of device/bus, this should (hopefully) be over now 298 scsi_clear_device_overflow(device); 299 scsi_clear_bus_overflow(bus); 300 301 // if device is not blocked (anymore) and has pending requests, 302 // add it to waiting list of bus 303 if (device->lock_count == 0 && device->queued_reqs != NULL) 304 scsi_add_device_queue_last(device); 305 306 start_service = !was_servicable && scsi_can_service_bus(bus); 307 308 mutex_unlock(&bus->mutex); 309 310 // tell service thread to submit new requests to SIM 311 // (do this ASAP to keep bus/device busy) 312 if (start_service) 313 release_sem_etc(bus->start_service, 1, 0/*B_DO_NOT_RESCHEDULE*/); 314 315 if (request->emulated) 316 scsi_finish_emulation(request); 317 318 // copy data from buffer and release it 319 if (request->buffered) 320 scsi_release_dma_buffer(request); 321 322 // special treatment for finished auto-sense 323 if (request == device->auto_sense_request) 324 finish_autosense(device); 325 else { 326 // tell peripheral driver about completion 327 if (!do_autosense) 328 request->completion_cond.NotifyAll(); 329 } 330 } 331 332 333 /** check whether request can be executed right now, enqueuing it if not, 334 * return: true if request can be executed 335 * side effect: updates device->last_sort 336 */ 337 338 static inline bool 339 scsi_check_enqueue_request(scsi_ccb *request) 340 { 341 scsi_bus_info *bus = request->bus; 342 scsi_device_info *device = request->device; 343 bool execute; 344 345 mutex_lock(&bus->mutex); 346 347 // if device/bus is locked, or there are waiting requests 348 // or waiting devices (last condition makes sure we don't overtake 349 // requests that got queued because bus was full) 350 if (device->lock_count > 0 || device->queued_reqs != NULL 351 || bus->lock_count > 0 || bus->waiting_devices != NULL) { 352 SHOW_FLOW0(3, "bus/device is currently locked"); 353 scsi_add_queued_request(request); 354 execute = false; 355 } else { 356 // if bus is saturated, block it 357 if (--bus->left_slots == 0) { 358 SHOW_FLOW0(3, "bus is saturated, blocking further requests"); 359 scsi_block_bus_nolock(bus, false); 360 } 361 362 // if device saturated or blocking request, block device 363 if (--device->left_slots == 0 || request->ordered) { 364 SHOW_FLOW0( 3, "device is saturated/blocked by requests, blocking further requests" ); 365 scsi_block_device_nolock(device, false); 366 } 367 368 if (request->sort >= 0) { 369 device->last_sort = request->sort; 370 SHOW_FLOW(1, "%" B_PRId64, device->last_sort); 371 } 372 373 execute = true; 374 } 375 376 mutex_unlock(&bus->mutex); 377 378 return execute; 379 } 380 381 382 // size of SCSI command according to function group 383 int func_group_len[8] = { 384 6, 10, 10, 0, 16, 12, 0, 0 385 }; 386 387 388 /** execute scsi command asynchronously */ 389 390 void 391 scsi_async_io(scsi_ccb *request) 392 { 393 scsi_bus_info *bus = request->bus; 394 395 //SHOW_FLOW( 0, "path_id=%d", bus->path_id ); 396 397 //snooze( 1000000 ); 398 399 // do some sanity tests first 400 if (request->state != SCSI_STATE_FINISHED) { 401 panic("Passed ccb to scsi_action that isn't ready (state = %d)\n", 402 request->state); 403 } 404 405 if (request->cdb_length < func_group_len[request->cdb[0] >> 5]) { 406 SHOW_ERROR(3, "invalid command len (%d instead of %d)", 407 request->cdb_length, func_group_len[request->cdb[0] >> 5]); 408 409 request->subsys_status = SCSI_REQ_INVALID; 410 goto err; 411 } 412 413 if (!request->device->valid) { 414 SHOW_ERROR0( 3, "device got removed" ); 415 416 // device got removed meanwhile 417 request->subsys_status = SCSI_DEV_NOT_THERE; 418 goto err; 419 } 420 421 if ((request->flags & SCSI_DIR_MASK) != SCSI_DIR_NONE 422 && request->sg_list == NULL && request->data_length > 0) { 423 SHOW_ERROR( 3, "Asynchronous SCSI I/O requires S/G list (data is %" 424 B_PRIu32 " bytes)", request->data_length ); 425 request->subsys_status = SCSI_DATA_RUN_ERR; 426 goto err; 427 } 428 429 request->buffered = request->emulated = 0; 430 431 // make data DMA safe 432 // (S/G list must be created first to be able to verify DMA restrictions) 433 if ((request->flags & SCSI_DMA_SAFE) == 0 && request->data_length > 0) { 434 request->buffered = true; 435 if (!scsi_get_dma_buffer(request)) { 436 SHOW_ERROR0( 3, "cannot create DMA buffer for request - reduce data volume" ); 437 438 request->subsys_status = SCSI_DATA_RUN_ERR; 439 goto err; 440 } 441 } 442 443 // emulate command if not supported 444 if ((request->device->emulation_map[request->cdb[0] >> 3] 445 & (1 << (request->cdb[0] & 7))) != 0) { 446 request->emulated = true; 447 448 if (!scsi_start_emulation(request)) { 449 SHOW_ERROR(3, "cannot emulate SCSI command 0x%02x", request->cdb[0]); 450 goto err2; 451 } 452 } 453 454 // SCSI-1 uses 3 bits of command packet for LUN 455 // SCSI-2 uses identify message, but still needs LUN in command packet 456 // (though it won't fit, as LUNs can be 4 bits wide) 457 // SCSI-3 doesn't use command packet for LUN anymore 458 // ATAPI uses 3 bits of command packet for LUN 459 460 // currently, we always copy LUN into command packet as a safe bet 461 { 462 // abuse TUR to find proper spot in command packet for LUN 463 scsi_cmd_tur *cmd = (scsi_cmd_tur *)request->cdb; 464 465 cmd->lun = request->device->target_lun; 466 } 467 468 request->ordered = (request->flags & SCSI_ORDERED_QTAG) != 0; 469 470 SHOW_FLOW(3, "ordered=%d", request->ordered); 471 472 // make sure device/bus is not blocked 473 if (!scsi_check_enqueue_request(request)) 474 return; 475 476 bus = request->bus; 477 478 request->state = SCSI_STATE_SENT; 479 bus->interface->scsi_io(bus->sim_cookie, request); 480 return; 481 482 err2: 483 if (request->buffered) 484 scsi_release_dma_buffer(request); 485 err: 486 request->completion_cond.NotifyAll(B_ERROR); 487 return; 488 } 489 490 491 /** execute SCSI command synchronously */ 492 493 void 494 scsi_sync_io(scsi_ccb *request) 495 { 496 bool tmp_sg = false; 497 498 // create scatter-gather list if required 499 if ((request->flags & SCSI_DIR_MASK) != SCSI_DIR_NONE 500 && request->sg_list == NULL && request->data_length > 0) { 501 tmp_sg = true; 502 if (!create_temp_sg(request)) { 503 SHOW_ERROR0( 3, "data is too much fragmented - you should use s/g list" ); 504 505 // ToDo: this means too much (fragmented) data 506 request->subsys_status = SCSI_DATA_RUN_ERR; 507 return; 508 } 509 } 510 511 ConditionVariableEntry entry; 512 request->completion_cond.Add(&entry); 513 514 scsi_async_io(request); 515 516 entry.Wait(); 517 518 if (tmp_sg) 519 cleanup_temp_sg(request); 520 } 521 522 523 uchar 524 scsi_term_io(scsi_ccb *ccb_to_terminate) 525 { 526 scsi_bus_info *bus = ccb_to_terminate->bus; 527 528 return bus->interface->term_io(bus->sim_cookie, ccb_to_terminate); 529 } 530 531 532 uchar 533 scsi_abort(scsi_ccb *req_to_abort) 534 { 535 scsi_bus_info *bus = req_to_abort->bus; 536 537 if (bus == NULL) { 538 // checking the validity of the request to abort is a nightmare 539 // this is just a beginning 540 return SCSI_REQ_INVALID; 541 } 542 543 mutex_lock(&bus->mutex); 544 545 switch (req_to_abort->state) { 546 case SCSI_STATE_FINISHED: 547 case SCSI_STATE_SENT: 548 mutex_unlock(&bus->mutex); 549 break; 550 551 case SCSI_STATE_QUEUED: { 552 bool was_servicable, start_retry; 553 554 was_servicable = scsi_can_service_bus(bus); 555 556 // remove request from device queue 557 scsi_remove_queued_request(req_to_abort); 558 559 start_retry = scsi_can_service_bus(bus) && !was_servicable; 560 561 mutex_unlock(&bus->mutex); 562 563 req_to_abort->subsys_status = SCSI_REQ_ABORTED; 564 565 // finish emulation 566 if (req_to_abort->emulated) 567 scsi_finish_emulation(req_to_abort); 568 569 // release DMA buffer 570 if (req_to_abort->buffered) 571 scsi_release_dma_buffer(req_to_abort); 572 573 // tell peripheral driver about 574 req_to_abort->completion_cond.NotifyAll(B_CANCELED); 575 576 if (start_retry) 577 release_sem(bus->start_service); 578 579 break; 580 } 581 } 582 583 return SCSI_REQ_CMP; 584 } 585 586 587 /** submit pending request (at most one!) */ 588 589 bool 590 scsi_check_exec_service(scsi_bus_info *bus) 591 { 592 SHOW_FLOW0(3, ""); 593 mutex_lock(&bus->mutex); 594 595 if (scsi_can_service_bus(bus)) { 596 scsi_ccb *request; 597 scsi_device_info *device; 598 599 SHOW_FLOW0(3, "servicing bus"); 600 601 //snooze( 1000000 ); 602 603 // handle devices in round-robin-style 604 device = bus->waiting_devices; 605 bus->waiting_devices = bus->waiting_devices->waiting_next; 606 607 request = device->queued_reqs; 608 scsi_remove_queued_request(request); 609 610 // if bus is saturated, block it 611 if (--bus->left_slots == 0) { 612 SHOW_FLOW0(3, "bus is saturated, blocking further requests"); 613 scsi_block_bus_nolock(bus, false); 614 } 615 616 // if device saturated or blocking request, block device 617 if (--device->left_slots == 0 || request->ordered) { 618 SHOW_FLOW0(3, "device is saturated/blocked by requests, blocking further requests"); 619 scsi_block_device_nolock(device, false); 620 } 621 622 if (request->sort >= 0) { 623 device->last_sort = request->sort; 624 SHOW_FLOW(1, "%" B_PRId64, device->last_sort); 625 } 626 627 mutex_unlock(&bus->mutex); 628 629 request->state = SCSI_STATE_SENT; 630 bus->interface->scsi_io(bus->sim_cookie, request); 631 632 return true; 633 } 634 635 mutex_unlock(&bus->mutex); 636 637 return false; 638 } 639