2 * Copyright 2004-2007, Haiku, Inc. All RightsReserved.
3 * Copyright 2002-2004, Thomas Kurschel. All rights reserved.
5 * Distributed under the terms of the MIT License.
8 //! Part of Open SCSI bus manager
11 #include "scsi_internal.h"
19 /** put request back in queue because of device/bus overflow */
22 scsi_requeue_request(scsi_ccb
*request
, bool bus_overflow
)
24 scsi_bus_info
*bus
= request
->bus
;
25 scsi_device_info
*device
= request
->device
;
26 bool was_servicable
, start_retry
;
30 if (request
->state
!= SCSI_STATE_SENT
) {
31 panic("Unsent ccb was request to requeue\n");
35 request
->state
= SCSI_STATE_QUEUED
;
37 ACQUIRE_BEN(&bus
->mutex
);
39 was_servicable
= scsi_can_service_bus(bus
);
41 if (bus
->left_slots
++ == 0)
42 scsi_unblock_bus_noresume(bus
, false);
44 if (device
->left_slots
++ == 0 || request
->ordered
)
45 scsi_unblock_device_noresume(device
, false);
47 // make sure it's the next request for this device
48 scsi_add_req_queue_first(request
);
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
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
);
71 start_retry
= !was_servicable
&& scsi_can_service_bus(bus
);
73 RELEASE_BEN(&bus
->mutex
);
75 // submit requests to other devices in case bus was overloaded
77 release_sem_etc(bus
->start_service
, 1, 0/*B_DO_NOT_RESCHEDULE*/);
81 /** restart request ASAP because something went wrong */
84 scsi_resubmit_request(scsi_ccb
*request
)
86 scsi_bus_info
*bus
= request
->bus
;
87 scsi_device_info
*device
= request
->device
;
88 bool was_servicable
, start_retry
;
92 if (request
->state
!= SCSI_STATE_SENT
) {
93 panic("Unsent ccb was asked to get resubmitted\n");
97 request
->state
= SCSI_STATE_QUEUED
;
99 ACQUIRE_BEN(&bus
->mutex
);
101 was_servicable
= scsi_can_service_bus(bus
);
103 if (bus
->left_slots
++ == 0)
104 scsi_unblock_bus_noresume(bus
, false);
106 if (device
->left_slots
++ == 0 || request
->ordered
)
107 scsi_unblock_device_noresume(device
, false);
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
);
113 // we don't want to let anyone overtake this request
114 request
->ordered
= true;
116 // make it the next request submitted to SIM for this device
117 scsi_add_req_queue_first(request
);
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
;
127 start_retry
= !was_servicable
&& scsi_can_service_bus(bus
);
129 RELEASE_BEN(&bus
->mutex
);
131 // let the service thread do the resubmit
133 release_sem_etc(bus
->start_service
, 1, 0/*B_DO_NOT_RESCHEDULE*/);
137 /** submit autosense for request */
140 submit_autosense(scsi_ccb
*request
)
142 scsi_device_info
*device
= request
->device
;
146 SHOW_FLOW0(3, "sending autosense");
147 // we cannot use scsi_scsi_io but must insert it brute-force
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!
153 // no DMA buffer (we made sure that the data buffer fulfills all
155 request
->buffered
= false;
156 // don't let any request bypass us
157 request
->ordered
= true;
158 // initial SIM state for this request
159 request
->sim_state
= 0;
161 device
->auto_sense_originator
= request
;
163 // make it next request to process
164 scsi_add_queued_request_first(device
->auto_sense_request
);
168 /** finish special auto-sense request */
171 finish_autosense(scsi_device_info
*device
)
173 scsi_ccb
*orig_request
= device
->auto_sense_originator
;
174 scsi_ccb
*request
= device
->auto_sense_request
;
178 if (request
->subsys_status
== SCSI_REQ_CMP
) {
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
);
185 SHOW_FLOW(3, "Got sense: %d bytes", sense_len
);
187 memcpy(orig_request
->sense
, request
->data
, sense_len
);
189 orig_request
->sense_resid
= SCSI_MAX_SENSE_SIZE
- sense_len
;
190 orig_request
->subsys_status
|= SCSI_AUTOSNS_VALID
;
192 // failed to get sense
193 orig_request
->subsys_status
= SCSI_AUTOSENSE_FAIL
;
196 // inform peripheral driver
197 release_sem_etc(orig_request
->completion_sem
, 1, 0/*B_DO_NOT_RESCHEDULE*/);
201 /** device refused request because command queue is full */
204 scsi_device_queue_overflow(scsi_ccb
*request
, uint num_requests
)
206 scsi_bus_info
*bus
= request
->bus
;
207 scsi_device_info
*device
= request
->device
;
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)
215 // at least one request at once must be possible
216 if (num_requests
< 1)
219 SHOW_INFO(2, "Restricting device queue to %d requests", num_requests
);
222 ACQUIRE_BEN(&bus
->mutex
);
224 diff_max_slots
= device
->total_slots
- num_requests
;
225 device
->total_slots
= num_requests
;
226 device
->left_slots
-= diff_max_slots
;
228 RELEASE_BEN(&bus
->mutex
);
230 // requeue request, blocking further device requests
231 scsi_requeue_request(request
, false);
235 /** finish scsi request */
238 scsi_request_finished(scsi_ccb
*request
, uint num_requests
)
240 scsi_device_info
*device
= request
->device
;
241 scsi_bus_info
*bus
= request
->bus
;
242 bool was_servicable
, start_service
, do_autosense
;
244 SHOW_FLOW(3, "%p", request
);
246 if (request
->state
!= SCSI_STATE_SENT
) {
247 panic("Unsent ccb %p was reported as done\n", request
);
251 if (request
->subsys_status
== SCSI_REQ_INPROG
) {
252 panic("ccb %p with status \"Request in Progress\" was reported as done\n",
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
);
264 request
->state
= SCSI_STATE_FINISHED
;
266 ACQUIRE_BEN(&bus
->mutex
);
268 was_servicable
= scsi_can_service_bus(bus
);
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
;
279 if (request
->subsys_status
!= SCSI_REQ_CMP
) {
280 SHOW_FLOW(3, "subsys=%x, device=%x, flags=%x, manual_auto_sense=%d",
281 request
->subsys_status
, request
->device_status
, (int)request
->flags
,
282 device
->manual_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
);
291 if (bus
->left_slots
++ == 0)
292 scsi_unblock_bus_noresume(bus
, false);
294 if (device
->left_slots
++ == 0 || request
->ordered
)
295 scsi_unblock_device_noresume(device
, false);
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
);
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
);
306 start_service
= !was_servicable
&& scsi_can_service_bus(bus
);
308 RELEASE_BEN(&bus
->mutex
);
310 // tell service thread to submit new requests to SIM
311 // (do this ASAP to keep bus/device busy)
313 release_sem_etc(bus
->start_service
, 1, 0/*B_DO_NOT_RESCHEDULE*/);
315 if (request
->emulated
)
316 scsi_finish_emulation(request
);
318 // copy data from buffer and release it
319 if (request
->buffered
)
320 scsi_release_dma_buffer(request
);
322 // special treatment for finished auto-sense
323 if (request
== device
->auto_sense_request
)
324 finish_autosense(device
);
326 // tell peripheral driver about completion
328 release_sem_etc(request
->completion_sem
, 1, 0/*B_DO_NOT_RESCHEDULE*/);
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
339 scsi_check_enqueue_request(scsi_ccb
*request
)
341 scsi_bus_info
*bus
= request
->bus
;
342 scsi_device_info
*device
= request
->device
;
345 ACQUIRE_BEN(&bus
->mutex
);
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
);
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);
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);
368 if (request
->sort
>= 0) {
369 device
->last_sort
= request
->sort
;
370 SHOW_FLOW(1, "%Ld", device
->last_sort
);
376 RELEASE_BEN(&bus
->mutex
);
382 // size of SCSI command according to function group
383 int func_group_len
[8] = {
384 6, 10, 10, 0, 16, 12, 0, 0
388 /** execute scsi command asynchronously */
391 scsi_async_io(scsi_ccb
*request
)
393 scsi_bus_info
*bus
= request
->bus
;
395 //SHOW_FLOW( 0, "path_id=%d", bus->path_id );
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", request
->state
);
403 if (request
->cdb_length
< func_group_len
[request
->cdb
[0] >> 5]) {
404 SHOW_ERROR(3, "invalid command len (%d instead of %d)",
405 request
->cdb_length
, func_group_len
[request
->cdb
[0] >> 5]);
407 request
->subsys_status
= SCSI_REQ_INVALID
;
411 if (!request
->device
->valid
) {
412 SHOW_ERROR0( 3, "device got removed" );
414 // device got removed meanwhile
415 request
->subsys_status
= SCSI_DEV_NOT_THERE
;
419 if ((request
->flags
& SCSI_DIR_MASK
) != SCSI_DIR_NONE
420 && request
->sg_list
== NULL
&& request
->data_length
> 0) {
421 SHOW_ERROR( 3, "Asynchronous SCSI I/O requires S/G list (data is %d bytes)",
422 (int)request
->data_length
);
423 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
427 request
->buffered
= request
->emulated
= 0;
429 // make data DMA safe
430 // (S/G list must be created first to be able to verify DMA restrictions)
431 if ((request
->flags
& SCSI_DMA_SAFE
) == 0 && request
->data_length
> 0) {
432 request
->buffered
= true;
433 if (!scsi_get_dma_buffer(request
)) {
434 SHOW_ERROR0( 3, "cannot create DMA buffer for request - reduce data volume" );
436 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
441 // emulate command if not supported
442 if ((request
->device
->emulation_map
[request
->cdb
[0] >> 3]
443 & (1 << (request
->cdb
[0] & 7))) != 0) {
444 request
->emulated
= true;
446 if (!scsi_start_emulation(request
)) {
447 SHOW_ERROR(3, "cannot emulate SCSI command 0x%02x", request
->cdb
[0]);
452 // SCSI-1 uses 3 bits of command packet for LUN
453 // SCSI-2 uses identify message, but still needs LUN in command packet
454 // (though it won't fit, as LUNs can be 4 bits wide)
455 // SCSI-3 doesn't use command packet for LUN anymore
456 // ATAPI uses 3 bits of command packet for LUN
458 // currently, we always copy LUN into command packet as a safe bet
460 // abuse TUR to find proper spot in command packet for LUN
461 scsi_cmd_tur
*cmd
= (scsi_cmd_tur
*)request
->cdb
;
463 cmd
->lun
= request
->device
->target_lun
;
466 request
->ordered
= (request
->flags
& SCSI_ORDERED_QTAG
) != 0;
468 SHOW_FLOW(3, "ordered=%d", request
->ordered
);
470 // give SIM a well-defined first state
471 request
->sim_state
= 0;
473 // make sure device/bus is not blocked
474 if (!scsi_check_enqueue_request(request
))
479 request
->state
= SCSI_STATE_SENT
;
480 bus
->interface
->scsi_io(bus
->sim_cookie
, request
);
484 if (request
->buffered
)
485 scsi_release_dma_buffer(request
);
487 release_sem(request
->completion_sem
);
492 /** execute SCSI command synchronously */
495 scsi_sync_io(scsi_ccb
*request
)
499 // create scatter-gather list if required
500 if ((request
->flags
& SCSI_DIR_MASK
) != SCSI_DIR_NONE
501 && request
->sg_list
== NULL
&& request
->data_length
> 0) {
503 if (!create_temp_sg(request
)) {
504 SHOW_ERROR0( 3, "data is too much fragmented - you should use s/g list" );
506 // ToDo: this means too much (fragmented) data
507 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
512 scsi_async_io(request
);
513 acquire_sem(request
->completion_sem
);
516 cleanup_tmp_sg(request
);
521 scsi_term_io(scsi_ccb
*ccb_to_terminate
)
523 scsi_bus_info
*bus
= ccb_to_terminate
->bus
;
525 return bus
->interface
->term_io(bus
->sim_cookie
, ccb_to_terminate
);
530 scsi_abort(scsi_ccb
*req_to_abort
)
532 scsi_bus_info
*bus
= req_to_abort
->bus
;
535 // checking the validity of the request to abort is a nightmare
536 // this is just a beginning
537 return SCSI_REQ_INVALID
;
540 ACQUIRE_BEN(&bus
->mutex
);
542 switch (req_to_abort
->state
) {
543 case SCSI_STATE_FINISHED
:
544 case SCSI_STATE_SENT
:
545 RELEASE_BEN(&bus
->mutex
);
548 case SCSI_STATE_QUEUED
: {
549 bool was_servicable
, start_retry
;
551 was_servicable
= scsi_can_service_bus(bus
);
553 // remove request from device queue
554 scsi_remove_queued_request(req_to_abort
);
556 start_retry
= scsi_can_service_bus(bus
) && !was_servicable
;
558 RELEASE_BEN(&bus
->mutex
);
560 req_to_abort
->subsys_status
= SCSI_REQ_ABORTED
;
563 if (req_to_abort
->emulated
)
564 scsi_finish_emulation(req_to_abort
);
566 // release DMA buffer
567 if (req_to_abort
->buffered
)
568 scsi_release_dma_buffer(req_to_abort
);
570 // tell peripheral driver about
571 release_sem_etc(req_to_abort
->completion_sem
, 1, 0/*B_DO_NOT_RESCHEDULE*/);
574 release_sem(bus
->start_service
);
584 /** submit pending request (at most one!) */
587 scsi_check_exec_service(scsi_bus_info
*bus
)
590 ACQUIRE_BEN(&bus
->mutex
);
592 if (scsi_can_service_bus(bus
)) {
594 scsi_device_info
*device
;
596 SHOW_FLOW0(3, "servicing bus");
600 // handle devices in round-robin-style
601 device
= bus
->waiting_devices
;
602 bus
->waiting_devices
= bus
->waiting_devices
->waiting_next
;
604 request
= device
->queued_reqs
;
605 scsi_remove_queued_request(request
);
607 // if bus is saturated, block it
608 if (--bus
->left_slots
== 0) {
609 SHOW_FLOW0(3, "bus is saturated, blocking further requests");
610 scsi_block_bus_nolock(bus
, false);
613 // if device saturated or blocking request, block device
614 if (--device
->left_slots
== 0 || request
->ordered
) {
615 SHOW_FLOW0(3, "device is saturated/blocked by requests, blocking further requests");
616 scsi_block_device_nolock(device
, false);
619 if (request
->sort
>= 0) {
620 device
->last_sort
= request
->sort
;
621 SHOW_FLOW(1, "%Ld", device
->last_sort
);
624 RELEASE_BEN(&bus
->mutex
);
626 request
->state
= SCSI_STATE_SENT
;
627 bus
->interface
->scsi_io(bus
->sim_cookie
, request
);
632 RELEASE_BEN(&bus
->mutex
);