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=%" B_PRIx32
281 ", manual_auto_sense=%d", request
->subsys_status
,
282 request
->device_status
, request
->flags
, 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, "%" B_PRId64
, 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",
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]);
409 request
->subsys_status
= SCSI_REQ_INVALID
;
413 if (!request
->device
->valid
) {
414 SHOW_ERROR0( 3, "device got removed" );
416 // device got removed meanwhile
417 request
->subsys_status
= SCSI_DEV_NOT_THERE
;
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
;
429 request
->buffered
= request
->emulated
= 0;
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" );
438 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
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;
448 if (!scsi_start_emulation(request
)) {
449 SHOW_ERROR(3, "cannot emulate SCSI command 0x%02x", request
->cdb
[0]);
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
460 // currently, we always copy LUN into command packet as a safe bet
462 // abuse TUR to find proper spot in command packet for LUN
463 scsi_cmd_tur
*cmd
= (scsi_cmd_tur
*)request
->cdb
;
465 cmd
->lun
= request
->device
->target_lun
;
468 request
->ordered
= (request
->flags
& SCSI_ORDERED_QTAG
) != 0;
470 SHOW_FLOW(3, "ordered=%d", request
->ordered
);
472 // give SIM a well-defined first state
473 request
->sim_state
= 0;
475 // make sure device/bus is not blocked
476 if (!scsi_check_enqueue_request(request
))
481 request
->state
= SCSI_STATE_SENT
;
482 bus
->interface
->scsi_io(bus
->sim_cookie
, request
);
486 if (request
->buffered
)
487 scsi_release_dma_buffer(request
);
489 release_sem(request
->completion_sem
);
494 /** execute SCSI command synchronously */
497 scsi_sync_io(scsi_ccb
*request
)
501 // create scatter-gather list if required
502 if ((request
->flags
& SCSI_DIR_MASK
) != SCSI_DIR_NONE
503 && request
->sg_list
== NULL
&& request
->data_length
> 0) {
505 if (!create_temp_sg(request
)) {
506 SHOW_ERROR0( 3, "data is too much fragmented - you should use s/g list" );
508 // ToDo: this means too much (fragmented) data
509 request
->subsys_status
= SCSI_DATA_RUN_ERR
;
514 scsi_async_io(request
);
515 acquire_sem(request
->completion_sem
);
518 cleanup_tmp_sg(request
);
523 scsi_term_io(scsi_ccb
*ccb_to_terminate
)
525 scsi_bus_info
*bus
= ccb_to_terminate
->bus
;
527 return bus
->interface
->term_io(bus
->sim_cookie
, ccb_to_terminate
);
532 scsi_abort(scsi_ccb
*req_to_abort
)
534 scsi_bus_info
*bus
= req_to_abort
->bus
;
537 // checking the validity of the request to abort is a nightmare
538 // this is just a beginning
539 return SCSI_REQ_INVALID
;
542 ACQUIRE_BEN(&bus
->mutex
);
544 switch (req_to_abort
->state
) {
545 case SCSI_STATE_FINISHED
:
546 case SCSI_STATE_SENT
:
547 RELEASE_BEN(&bus
->mutex
);
550 case SCSI_STATE_QUEUED
: {
551 bool was_servicable
, start_retry
;
553 was_servicable
= scsi_can_service_bus(bus
);
555 // remove request from device queue
556 scsi_remove_queued_request(req_to_abort
);
558 start_retry
= scsi_can_service_bus(bus
) && !was_servicable
;
560 RELEASE_BEN(&bus
->mutex
);
562 req_to_abort
->subsys_status
= SCSI_REQ_ABORTED
;
565 if (req_to_abort
->emulated
)
566 scsi_finish_emulation(req_to_abort
);
568 // release DMA buffer
569 if (req_to_abort
->buffered
)
570 scsi_release_dma_buffer(req_to_abort
);
572 // tell peripheral driver about
573 release_sem_etc(req_to_abort
->completion_sem
, 1, 0/*B_DO_NOT_RESCHEDULE*/);
576 release_sem(bus
->start_service
);
586 /** submit pending request (at most one!) */
589 scsi_check_exec_service(scsi_bus_info
*bus
)
592 ACQUIRE_BEN(&bus
->mutex
);
594 if (scsi_can_service_bus(bus
)) {
596 scsi_device_info
*device
;
598 SHOW_FLOW0(3, "servicing bus");
602 // handle devices in round-robin-style
603 device
= bus
->waiting_devices
;
604 bus
->waiting_devices
= bus
->waiting_devices
->waiting_next
;
606 request
= device
->queued_reqs
;
607 scsi_remove_queued_request(request
);
609 // if bus is saturated, block it
610 if (--bus
->left_slots
== 0) {
611 SHOW_FLOW0(3, "bus is saturated, blocking further requests");
612 scsi_block_bus_nolock(bus
, false);
615 // if device saturated or blocking request, block device
616 if (--device
->left_slots
== 0 || request
->ordered
) {
617 SHOW_FLOW0(3, "device is saturated/blocked by requests, blocking further requests");
618 scsi_block_device_nolock(device
, false);
621 if (request
->sort
>= 0) {
622 device
->last_sort
= request
->sort
;
623 SHOW_FLOW(1, "%" B_PRId64
, device
->last_sort
);
626 RELEASE_BEN(&bus
->mutex
);
628 request
->state
= SCSI_STATE_SENT
;
629 bus
->interface
->scsi_io(bus
->sim_cookie
, request
);
634 RELEASE_BEN(&bus
->mutex
);