BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / bus_managers / ide / ide_sim.c
blob0f400db5f52815ebdaba42ac81dfe7675af8da9c
1 /*
2 * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Copyright 2002/03, Thomas Kurschel. All rights reserved.
5 * Distributed under the terms of the MIT License.
6 */
8 /*
9 Part of Open IDE bus manager
11 Interface between ide bus manager and scsi bus manager.
13 The IDE bus manager has a bit unusual structure as it
14 consists of a single level only. In fact it is no bus manager
15 in terms of the PnP structure at all but a driver that maps
16 one SCSI bus onto one IDE controller.
18 This structure does not allow us to publish IDE devices
19 as they can be accessed via the SCSI bus node only. Therefore
20 we do a full bus scan every time the IDE bus node is loaded.
21 The drawback is that a bus rescan must be done indirectly via a
22 SCSI bus scan.
25 #include "ide_internal.h"
26 #include "ide_sim.h"
28 #include <scsi_cmds.h>
29 #include <safemode.h>
31 #include <string.h>
32 #include <malloc.h>
33 #include <stdio.h>
35 scsi_for_sim_interface *scsi;
38 static void disconnect_worker(ide_bus_info *bus, void *arg);
39 static void set_check_condition(ide_qrequest *qrequest);
42 /** check whether this request can be within device */
44 static inline bool
45 is_queuable(ide_device_info *device, scsi_ccb *request)
47 int opcode = request->cdb[0];
49 // XXX disable queuing
50 if (!device->CQ_enabled)
51 return false;
53 // make sure the caller allows queuing
54 if ((request->flags & SCSI_ORDERED_QTAG) != 0)
55 return false;
57 // for atapi, all commands could be queued, but all
58 // atapi devices I know don't support queuing anyway
59 return opcode == SCSI_OP_READ_6 || opcode == SCSI_OP_WRITE_6
60 || opcode == SCSI_OP_READ_10 || opcode == SCSI_OP_WRITE_10;
64 static void
65 scan_device(ide_bus_info *bus, int device)
67 SHOW_FLOW0(4, "");
69 // currently, the SCSI bus manager doesn't block the
70 // bus when a bus or device scan is issued, so we
71 // have to use a SPC for that to be sure no one else
72 // is accessing the device or bus concurrently
73 schedule_synced_pc(bus, &bus->scan_bus_syncinfo, (void *)device);
75 acquire_sem(bus->scan_device_sem);
79 static uchar
80 sim_scan_bus(ide_bus_info *bus)
82 int i;
84 SHOW_FLOW0(4, "");
86 if (bus->disconnected)
87 return SCSI_NO_HBA;
89 for (i = 0; i < bus->max_devices; ++i) {
90 scan_device(bus, i);
93 return SCSI_REQ_CMP;
97 static void
98 sim_set_scsi_bus(ide_bus_info *bus, scsi_bus scsi)
100 bus->scsi_cookie = scsi;
102 // detect devices
103 sim_scan_bus(bus);
107 static void
108 sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
110 ide_device_info *device;
111 bool queuable;
112 ide_qrequest *qrequest;
114 SHOW_FLOW(3, "%d:%d", request->target_id, request->target_lun);
116 if (bus->disconnected)
117 goto err_disconnected;
119 // make sure, device is valid
120 // I've read that there are ATAPI devices with more then one LUN,
121 // but it seems that most (all?) devices ignore LUN, so we have
122 // to restrict to LUN 0 to avoid mirror devices
123 if (request->target_id >= 2)
124 goto err_inv_device;
126 device = bus->devices[request->target_id];
127 if (device == NULL)
128 goto err_inv_device;
130 if (request->target_lun > device->last_lun)
131 goto err_inv_device;
133 queuable = is_queuable(device, request);
135 // grab the bus
136 ACQUIRE_BEN(&bus->status_report_ben);
137 IDE_LOCK(bus);
139 if (bus->state != ide_state_idle)
140 goto err_bus_busy;
142 // bail out if device can't accept further requests
143 if (device->free_qrequests == NULL
144 || (device->num_running_reqs > 0 && !queuable))
145 goto err_device_busy;
147 bus->state = ide_state_accessing;
149 IDE_UNLOCK(bus);
150 RELEASE_BEN(&bus->status_report_ben);
152 // as we own the bus, noone can bother us
153 qrequest = device->free_qrequests;
154 device->free_qrequests = qrequest->next;
156 qrequest->request = request;
157 qrequest->queuable = queuable;
158 qrequest->running = true;
159 qrequest->uses_dma = false;
161 ++device->num_running_reqs;
162 ++bus->num_running_reqs;
163 bus->active_qrequest = qrequest;
165 device->exec_io(device, qrequest);
167 return;
169 err_inv_device:
170 SHOW_ERROR(3, "Invalid device %d:%d",
171 request->target_id, request->target_lun);
173 request->subsys_status = SCSI_SEL_TIMEOUT;
174 scsi->finished(request, 1);
175 return;
177 err_bus_busy:
178 SHOW_FLOW0(3, "Bus busy");
180 IDE_UNLOCK(bus);
181 scsi->requeue(request, true);
182 RELEASE_BEN(&bus->status_report_ben);
183 return;
185 err_device_busy:
186 SHOW_FLOW0(3, "Device busy");
188 IDE_UNLOCK(bus);
189 scsi->requeue(request, false);
190 RELEASE_BEN(&bus->status_report_ben);
191 return;
193 err_disconnected:
194 SHOW_ERROR0(3, "No controller anymore");
195 request->subsys_status = SCSI_NO_HBA;
196 scsi->finished(request, 1);
197 return;
201 static uchar
202 sim_path_inquiry(ide_bus_info *bus, scsi_path_inquiry *info)
204 const char *controller_name;
206 SHOW_FLOW0(4, "");
208 if (bus->disconnected)
209 return SCSI_NO_HBA;
211 info->hba_inquiry = SCSI_PI_TAG_ABLE | SCSI_PI_WIDE_16;
213 info->hba_misc = 0;
215 memset(info->vuhba_flags, 0, sizeof(info->vuhba_flags));
216 // we don't need any of the private data
217 info->sim_priv = 0;
219 // there is no initiator for IDE, but SCSI needs it for scanning
220 info->initiator_id = 2;
221 // there's no controller limit, so set it higher then the maximum
222 // number of queued requests, which is 32 per device * 2 devices
223 info->hba_queue_size = 65;
225 strncpy(info->sim_vid, "Haiku", SCSI_SIM_ID);
227 if (pnp->get_attr_string(bus->node, SCSI_DESCRIPTION_CONTROLLER_NAME,
228 &controller_name, true) == B_OK) {
229 strlcpy(info->hba_vid, controller_name, SCSI_HBA_ID);
230 } else
231 strlcpy(info->hba_vid, "", SCSI_HBA_ID);
233 strlcpy(info->controller_family, "IDE", SCSI_FAM_ID);
234 strlcpy(info->controller_type, "IDE", SCSI_TYPE_ID);
236 SHOW_FLOW0(4, "done");
238 return SCSI_REQ_CMP;
242 static uchar
243 sim_abort(ide_bus_info *bus, scsi_ccb *ccb_to_abort)
245 // we cannot abort specific commands, so just ignore
246 if (bus->disconnected)
247 return SCSI_NO_HBA;
249 return SCSI_REQ_CMP;
253 static uchar
254 sim_term_io(ide_bus_info *bus, scsi_ccb *ccb_to_abort)
256 // we cannot terminate commands, so just ignore
257 if (bus->disconnected)
258 return SCSI_NO_HBA;
260 return SCSI_REQ_CMP;
264 static uchar
265 sim_reset_bus(ide_bus_info *bus)
267 // no, we don't do that
268 if (bus->disconnected)
269 return SCSI_NO_HBA;
271 return SCSI_REQ_INVALID;
275 static uchar
276 sim_reset_device(ide_bus_info *bus, uchar target_id, uchar target_lun)
278 // xxx to do
279 if (bus->disconnected)
280 return SCSI_NO_HBA;
282 return SCSI_REQ_INVALID;
286 /** fill sense buffer according to device sense */
288 void
289 create_sense(ide_device_info *device, scsi_sense *sense)
291 memset(sense, 0, sizeof(*sense));
293 sense->error_code = SCSIS_CURR_ERROR;
294 sense->sense_key = decode_sense_key(device->combined_sense);
295 sense->add_sense_length = sizeof(*sense) - 7;
296 sense->asc = decode_sense_asc(device->combined_sense);
297 sense->ascq = decode_sense_ascq(device->combined_sense);
298 sense->sense_key_spec.raw.SKSV = 0; // no additional info
302 /** finish command, updating sense of device and request, and release bus */
304 void
305 finish_checksense(ide_qrequest *qrequest)
307 SHOW_FLOW(3, "%p, subsys_status=%d, sense=%x",
308 qrequest->request,
309 qrequest->request->subsys_status,
310 (int)qrequest->device->new_combined_sense);
312 qrequest->request->subsys_status = qrequest->device->subsys_status;
314 if (qrequest->request->subsys_status == SCSI_REQ_CMP) {
315 // device or emulation code completed command
316 qrequest->device->combined_sense = qrequest->device->new_combined_sense;
318 // if emulation code detected error, set CHECK CONDITION
319 if (qrequest->device->combined_sense)
320 set_check_condition(qrequest);
323 finish_request(qrequest, false);
327 /** finish request and release bus
328 * resubmit - true, if request should be resubmitted by XPT
331 void
332 finish_request(ide_qrequest *qrequest, bool resubmit)
334 ide_device_info *device = qrequest->device;
335 ide_bus_info *bus = device->bus;
336 scsi_ccb *request;
337 uint num_running;
339 SHOW_FLOW0(3, "");
341 // save request first, as qrequest can be reused as soon as
342 // access_finished is called!
343 request = qrequest->request;
345 qrequest->running = false;
346 qrequest->next = device->free_qrequests;
347 device->free_qrequests = qrequest;
349 // num_running is not really correct as the XPT is interested
350 // in the number of concurrent requests when it was *started* !
351 num_running = device->num_running_reqs--;
352 --bus->num_running_reqs;
354 // paranoia
355 bus->active_qrequest = NULL;
357 // release bus, handling service requests;
358 // TBD:
359 // if we really handle a service request, the finished command
360 // is delayed unnecessarily, but if we tell the XPT about the finished
361 // command first, it will instantly try to pass us another
362 // request to handle, which we will refuse as the bus is still
363 // locked; this really has to be improved
364 access_finished(bus, device);
366 ACQUIRE_BEN(&bus->status_report_ben);
368 if (resubmit)
369 scsi->resubmit(request);
370 else
371 scsi->finished(request, num_running);
373 RELEASE_BEN(&bus->status_report_ben);
377 /** set CHECK CONDITION of device and perform auto-sense if requested.
378 * (don't move it before finish_request - we don't want to inline
379 * it as it's on the rarely used error path)
382 static void
383 set_check_condition(ide_qrequest *qrequest)
385 scsi_ccb *request = qrequest->request;
386 ide_device_info *device = qrequest->device;
388 SHOW_FLOW0(3, "");
390 request->subsys_status = SCSI_REQ_CMP_ERR;
391 request->device_status = SCSI_STATUS_CHECK_CONDITION;
393 // copy sense only if caller requested it
394 if ((request->flags & SCSI_DIS_AUTOSENSE) == 0) {
395 scsi_sense sense;
396 int sense_len;
398 SHOW_FLOW0(3, "autosense");
400 // we cannot copy sense directly as sense buffer may be too small
401 create_sense(device, &sense);
403 sense_len = min(SCSI_MAX_SENSE_SIZE, sizeof(sense));
405 memcpy(request->sense, &sense, sense_len);
406 request->sense_resid = SCSI_MAX_SENSE_SIZE - sense_len;
407 request->subsys_status |= SCSI_AUTOSNS_VALID;
409 // device sense gets reset once it's read
410 device->combined_sense = 0;
415 void
416 finish_retry(ide_qrequest *qrequest)
418 qrequest->device->combined_sense = 0;
419 finish_request(qrequest, true);
423 /** finish request and abort pending requests of the device
424 * (to be called when the request failed and thus messed up the queue)
427 void
428 finish_reset_queue(ide_qrequest *qrequest)
430 ide_bus_info *bus = qrequest->device->bus;
432 // don't remove block_bus!!!
433 // during finish_checksense, the bus is released, so
434 // the SCSI bus manager could send us further commands
435 scsi->block_bus(bus->scsi_cookie);
437 finish_checksense(qrequest);
438 send_abort_queue(qrequest->device);
440 scsi->unblock_bus(bus->scsi_cookie);
444 /** finish request, but don't release bus
445 * if resubmit is true, the request will be resubmitted
448 static void
449 finish_norelease(ide_qrequest *qrequest, bool resubmit)
451 ide_device_info *device = qrequest->device;
452 ide_bus_info *bus = device->bus;
453 uint num_requests;
455 qrequest->running = false;
456 qrequest->next = device->free_qrequests;
457 device->free_qrequests = qrequest;
459 num_requests = device->num_running_reqs++;
460 --bus->num_running_reqs;
462 if (bus->active_qrequest == qrequest)
463 bus->active_qrequest = NULL;
465 ACQUIRE_BEN(&bus->status_report_ben);
467 if (resubmit)
468 scsi->resubmit(qrequest->request);
469 else
470 scsi->finished(qrequest->request, num_requests);
472 RELEASE_BEN(&bus->status_report_ben);
476 /** finish all queued requests but <ignore> of the device;
477 * set resubmit, if requests are to be resubmitted by xpt
480 void
481 finish_all_requests(ide_device_info *device, ide_qrequest *ignore,
482 int subsys_status, bool resubmit)
484 int i;
486 if (device == NULL)
487 return;
489 // we only have to block the device, but for CD changers we
490 // have to block all LUNS of the device (and we neither know
491 // their device handle nor which exist at all), so block
492 // the entire bus instead (it won't take that long anyway)
493 scsi->block_bus(device->bus->scsi_cookie);
495 for (i = 0; i < device->queue_depth; ++i) {
496 ide_qrequest *qrequest = &device->qreq_array[i];
498 if (qrequest->running && qrequest != ignore) {
499 qrequest->request->subsys_status = subsys_status;
500 finish_norelease(qrequest, resubmit);
504 scsi->unblock_bus(device->bus->scsi_cookie);
508 static status_t
509 ide_sim_init_bus(device_node *node, void **cookie)
511 ide_bus_info *bus;
512 bool dmaDisabled = false;
513 status_t status;
515 SHOW_FLOW0(3, "");
517 // first prepare the info structure
518 bus = (ide_bus_info *)malloc(sizeof(*bus));
519 if (bus == NULL)
520 return B_NO_MEMORY;
522 memset(bus, 0, sizeof(*bus));
523 bus->node = node;
524 B_INITIALIZE_SPINLOCK(&bus->lock);
525 bus->num_running_reqs = 0;
526 bus->active_qrequest = NULL;
527 bus->disconnected = false;
530 int32 channel_id = -1;
532 pnp->get_attr_uint32(node, IDE_CHANNEL_ID_ITEM, (uint32 *)&channel_id, true);
534 sprintf(bus->name, "ide_bus %d", (int)channel_id);
537 init_synced_pc(&bus->scan_bus_syncinfo, scan_device_worker);
538 init_synced_pc(&bus->disconnect_syncinfo, disconnect_worker);
540 bus->state = ide_state_idle;
541 bus->timer.bus = bus;
542 bus->synced_pc_list = NULL;
544 if ((status = scsi->alloc_dpc(&bus->irq_dpc)) < B_OK)
545 goto err1;
547 bus->active_device = NULL;
548 bus->sync_wait_sem = create_sem(0, "ide_sync_wait");
549 if (bus->sync_wait_sem < 0) {
550 status = bus->sync_wait_sem;
551 goto err2;
554 bus->devices[0] = bus->devices[1] = NULL;
556 bus->scan_device_sem = create_sem(0, "ide_scan_finished");
557 if (bus->scan_device_sem < 0) {
558 status = bus->scan_device_sem;
559 goto err3;
562 status = INIT_BEN(&bus->status_report_ben, "ide_status_report");
563 if (status < B_OK)
564 goto err4;
567 // check if safemode settings disable DMA
568 void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
569 if (settings != NULL) {
570 dmaDisabled = get_driver_boolean_parameter(settings, B_SAFEMODE_DISABLE_IDE_DMA,
571 false, false);
572 unload_driver_settings(settings);
576 bus->first_device = NULL;
578 // read restrictions of controller
580 if (pnp->get_attr_uint8(node, IDE_CONTROLLER_MAX_DEVICES_ITEM,
581 &bus->max_devices, true) != B_OK) {
582 // per default, 2 devices are supported per node
583 bus->max_devices = 2;
586 bus->max_devices = min(bus->max_devices, 2);
588 if (dmaDisabled
589 || pnp->get_attr_uint8(node, IDE_CONTROLLER_CAN_DMA_ITEM, &bus->can_DMA, true) != B_OK) {
590 // per default, no dma support
591 bus->can_DMA = false;
594 SHOW_FLOW(2, "can_dma: %d", bus->can_DMA);
596 if (bus->can_DMA) {
597 if (pnp->get_attr_uint8(node, IDE_CONTROLLER_CAN_CQ_ITEM, &bus->can_CQ, true) != B_OK) {
598 // per default, command queuing is supported unless the driver
599 // reports problems (queuing should be transparent to
600 // controller, but for sure there is some buggy, over-optimizing
601 // controller out there)
602 bus->can_CQ = true;
604 } else {
605 // I am not sure if it's a problem of the driver or the drive (probably the
606 // former), but we're generally disabling command queueing in case of PIO
607 // transfers. Since those should be rare on a real system (as is CQ support
608 // in the drive), it's not really worth investigating, though.
609 bus->can_CQ = false;
613 device_node *parent = pnp->get_parent_node(node);
614 pnp->get_driver(parent, (driver_module_info **)&bus->controller,
615 (void **)&bus->channel_cookie);
617 bus->controller->set_channel(bus->channel_cookie, bus);
618 pnp->put_node(parent);
621 *cookie = bus;
622 return B_OK;
624 err4:
625 delete_sem(bus->scan_device_sem);
626 err3:
627 delete_sem(bus->sync_wait_sem);
628 err2:
629 scsi->free_dpc(bus->irq_dpc);
630 err1:
631 uninit_synced_pc(&bus->scan_bus_syncinfo);
632 uninit_synced_pc(&bus->disconnect_syncinfo);
633 free(bus);
635 return status;
639 static status_t
640 ide_sim_uninit_bus(ide_bus_info *bus)
642 DELETE_BEN(&bus->status_report_ben);
643 delete_sem(bus->scan_device_sem);
644 delete_sem(bus->sync_wait_sem);
645 scsi->free_dpc(bus->irq_dpc);
646 uninit_synced_pc(&bus->scan_bus_syncinfo);
647 uninit_synced_pc(&bus->disconnect_syncinfo);
649 free(bus);
651 return B_OK;
655 // abort all running requests with SCSI_NO_HBA; finally, unblock bus
656 static void
657 disconnect_worker(ide_bus_info *bus, void *arg)
659 int i;
661 for (i = 0; i < bus->max_devices; ++i) {
662 if (bus->devices[i])
663 // is this the proper error code?
664 finish_all_requests(bus->devices[i], NULL, SCSI_NO_HBA, false);
667 scsi->unblock_bus(bus->scsi_cookie);
671 static void
672 ide_sim_bus_removed(ide_bus_info *bus)
674 // XPT must not issue further commands
675 scsi->block_bus(bus->scsi_cookie);
676 // make sure, we refuse all new commands
677 bus->disconnected = true;
678 // abort all running commands with SCSI_NO_HBA
679 // (the scheduled function also unblocks the bus when finished)
680 schedule_synced_pc(bus, &bus->disconnect_syncinfo, NULL);
684 static void
685 ide_sim_get_restrictions(ide_bus_info *bus, uchar target_id,
686 bool *is_atapi, bool *no_autosense, uint32 *max_blocks)
688 ide_device_info *device = bus->devices[target_id];
690 // we declare even ATA devices as ATAPI so we have to emulate fewer
691 // commands
692 *is_atapi = true;
694 // we emulate autosense for ATA devices
695 *no_autosense = false;
697 if (device != NULL && device->is_atapi) {
698 // we don't support native autosense for ATAPI devices
699 *no_autosense = true;
702 *max_blocks = 255;
704 if (device->is_atapi) {
705 if (strncmp(device->infoblock.model_number, "IOMEGA ZIP 100 ATAPI",
706 strlen("IOMEGA ZIP 100 ATAPI")) == 0
707 || strncmp( device->infoblock.model_number, "IOMEGA Clik!",
708 strlen( "IOMEGA Clik!")) == 0) {
709 SHOW_ERROR0(2, "Found buggy ZIP/Clik! drive - restricting transmission size");
710 *max_blocks = 64;
716 static status_t
717 ide_sim_ioctl(ide_bus_info *bus, uint8 targetID, uint32 op, void *buffer, size_t length)
719 ide_device_info *device = bus->devices[targetID];
721 // We currently only support IDE_GET_INFO_BLOCK
722 switch (op) {
723 case IDE_GET_INFO_BLOCK:
724 // we already have the info block, just copy it
725 memcpy(buffer, &device->infoblock,
726 min(sizeof(device->infoblock), length));
727 return B_OK;
729 case IDE_GET_STATUS:
731 // TODO: have our own structure and fill it with some useful stuff
732 ide_status status;
733 if (device->DMA_enabled)
734 status.dma_status = 1;
735 else if (device->DMA_supported) {
736 if (device->DMA_failures > 0)
737 status.dma_status = 6;
738 else if (device->bus->can_DMA)
739 status.dma_status = 2;
740 else
741 status.dma_status = 4;
742 } else
743 status.dma_status = 2;
745 status.pio_mode = 0;
746 status.dma_mode = get_device_dma_mode(device);
748 memcpy(buffer, &status, min(sizeof(status), length));
749 return B_OK;
753 return B_DEV_INVALID_IOCTL;
757 static status_t
758 std_ops(int32 op, ...)
760 switch (op) {
761 case B_MODULE_INIT:
762 case B_MODULE_UNINIT:
763 return B_OK;
765 default:
766 return B_ERROR;
771 module_dependency module_dependencies[] = {
772 { SCSI_FOR_SIM_MODULE_NAME, (module_info **)&scsi },
773 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
778 scsi_sim_interface ide_sim_module = {
781 IDE_SIM_MODULE_NAME,
783 std_ops,
786 NULL, // supported devices
787 NULL, // register node
788 (status_t (*)(device_node *, void **)) ide_sim_init_bus,
789 (void (*)(void *)) ide_sim_uninit_bus,
790 NULL, // register child devices
791 NULL, // rescan
792 (void (*)(void *)) ide_sim_bus_removed,
793 NULL, // suspend
794 NULL // resume
797 (void (*)(scsi_sim_cookie, scsi_bus)) sim_set_scsi_bus,
798 (void (*)(scsi_sim_cookie, scsi_ccb *)) sim_scsi_io,
799 (uchar (*)(scsi_sim_cookie, scsi_ccb *)) sim_abort,
800 (uchar (*)(scsi_sim_cookie, uchar, uchar)) sim_reset_device,
801 (uchar (*)(scsi_sim_cookie, scsi_ccb *)) sim_term_io,
803 (uchar (*)(scsi_sim_cookie, scsi_path_inquiry *))sim_path_inquiry,
804 (uchar (*)(scsi_sim_cookie)) sim_scan_bus,
805 (uchar (*)(scsi_sim_cookie)) sim_reset_bus,
807 (void (*)(scsi_sim_cookie, uchar,
808 bool*, bool *, uint32 *)) ide_sim_get_restrictions,
810 (status_t (*)(scsi_sim_cookie, uint8, uint32, void *, size_t))ide_sim_ioctl,