1/*
2 * Copyright 2004-2006, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
3 * Copyright 2002/03, Thomas Kurschel. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8/*
9	Part of Open IDE bus manager
10
11	Interface between ide bus manager and scsi bus manager.
12
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.
17
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.
23*/
24
25#include "ide_internal.h"
26#include "ide_sim.h"
27
28#include <scsi_cmds.h>
29#include <safemode.h>
30
31#include <string.h>
32#include <malloc.h>
33#include <stdio.h>
34
35scsi_for_sim_interface *scsi;
36
37
38static void disconnect_worker(ide_bus_info *bus, void *arg);
39static void set_check_condition(ide_qrequest *qrequest);
40
41
42/** check whether this request can be within device */
43
44static inline bool
45is_queuable(ide_device_info *device, scsi_ccb *request)
46{
47	int opcode = request->cdb[0];
48
49	// XXX disable queuing
50	if (!device->CQ_enabled)
51		return false;
52
53	// make sure the caller allows queuing
54	if ((request->flags & SCSI_ORDERED_QTAG) != 0)
55		return false;
56
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;
61}
62
63
64static void
65scan_device(ide_bus_info *bus, int device)
66{
67	SHOW_FLOW0(4, "");
68
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);
74
75	acquire_sem(bus->scan_device_sem);
76}
77
78
79static uchar
80sim_scan_bus(ide_bus_info *bus)
81{
82	int i;
83
84	SHOW_FLOW0(4, "");
85
86	if (bus->disconnected)
87		return SCSI_NO_HBA;
88
89	for (i = 0; i < bus->max_devices; ++i) {
90		scan_device(bus, i);
91	}
92
93	return SCSI_REQ_CMP;
94}
95
96
97static void
98sim_set_scsi_bus(ide_bus_info *bus, scsi_bus scsi)
99{
100	bus->scsi_cookie = scsi;
101
102	// detect devices
103	sim_scan_bus(bus);
104}
105
106
107static void
108sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
109{
110	ide_device_info *device;
111	bool queuable;
112	ide_qrequest *qrequest;
113
114	SHOW_FLOW(3, "%d:%d", request->target_id, request->target_lun);
115
116	if (bus->disconnected)
117		goto err_disconnected;
118
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;
125
126	device = bus->devices[request->target_id];
127	if (device == NULL)
128		goto err_inv_device;
129
130	if (request->target_lun > device->last_lun)
131		goto err_inv_device;
132
133	queuable = is_queuable(device, request);
134
135	// grab the bus
136	ACQUIRE_BEN(&bus->status_report_ben);
137	IDE_LOCK(bus);
138
139	if (bus->state != ide_state_idle)
140		goto err_bus_busy;
141
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;
146
147	bus->state = ide_state_accessing;
148
149	IDE_UNLOCK(bus);
150	RELEASE_BEN(&bus->status_report_ben);
151
152	// as we own the bus, noone can bother us
153	qrequest = device->free_qrequests;
154	device->free_qrequests = qrequest->next;
155
156	qrequest->request = request;
157	qrequest->queuable = queuable;
158	qrequest->running = true;
159	qrequest->uses_dma = false;
160
161	++device->num_running_reqs;
162	++bus->num_running_reqs;
163	bus->active_qrequest = qrequest;
164
165	device->exec_io(device, qrequest);
166
167	return;
168
169err_inv_device:
170	SHOW_ERROR(3, "Invalid device %d:%d",
171		request->target_id, request->target_lun);
172
173	request->subsys_status = SCSI_SEL_TIMEOUT;
174	scsi->finished(request, 1);
175	return;
176
177err_bus_busy:
178	SHOW_FLOW0(3, "Bus busy");
179
180	IDE_UNLOCK(bus);
181	scsi->requeue(request, true);
182	RELEASE_BEN(&bus->status_report_ben);
183	return;
184
185err_device_busy:
186	SHOW_FLOW0(3, "Device busy");
187
188	IDE_UNLOCK(bus);
189	scsi->requeue(request, false);
190	RELEASE_BEN(&bus->status_report_ben);
191	return;
192
193err_disconnected:
194	SHOW_ERROR0(3, "No controller anymore");
195	request->subsys_status = SCSI_NO_HBA;
196	scsi->finished(request, 1);
197	return;
198}
199
200
201static uchar
202sim_path_inquiry(ide_bus_info *bus, scsi_path_inquiry *info)
203{
204	const char *controller_name;
205
206	SHOW_FLOW0(4, "");
207
208	if (bus->disconnected)
209		return SCSI_NO_HBA;
210
211	info->hba_inquiry = SCSI_PI_TAG_ABLE | SCSI_PI_WIDE_16;
212
213	info->hba_misc = 0;
214
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;
218
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;
224
225	strncpy(info->sim_vid, "Haiku", SCSI_SIM_ID);
226
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);
232
233	strlcpy(info->controller_family, "IDE", SCSI_FAM_ID);
234	strlcpy(info->controller_type, "IDE", SCSI_TYPE_ID);
235
236	SHOW_FLOW0(4, "done");
237
238	return SCSI_REQ_CMP;
239}
240
241
242static uchar
243sim_abort(ide_bus_info *bus, scsi_ccb *ccb_to_abort)
244{
245	// we cannot abort specific commands, so just ignore
246	if (bus->disconnected)
247		return SCSI_NO_HBA;
248
249	return SCSI_REQ_CMP;
250}
251
252
253static uchar
254sim_term_io(ide_bus_info *bus, scsi_ccb *ccb_to_abort)
255{
256	// we cannot terminate commands, so just ignore
257	if (bus->disconnected)
258		return SCSI_NO_HBA;
259
260	return SCSI_REQ_CMP;
261}
262
263
264static uchar
265sim_reset_bus(ide_bus_info *bus)
266{
267	// no, we don't do that
268	if (bus->disconnected)
269		return SCSI_NO_HBA;
270
271	return SCSI_REQ_INVALID;
272}
273
274
275static uchar
276sim_reset_device(ide_bus_info *bus, uchar target_id, uchar target_lun)
277{
278	// xxx to do
279	if (bus->disconnected)
280		return SCSI_NO_HBA;
281
282	return SCSI_REQ_INVALID;
283}
284
285
286/** fill sense buffer according to device sense */
287
288void
289create_sense(ide_device_info *device, scsi_sense *sense)
290{
291	memset(sense, 0, sizeof(*sense));
292
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
299}
300
301
302/** finish command, updating sense of device and request, and release bus */
303
304void
305finish_checksense(ide_qrequest *qrequest)
306{
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);
311
312	qrequest->request->subsys_status = qrequest->device->subsys_status;
313
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;
317
318		// if emulation code detected error, set CHECK CONDITION
319		if (qrequest->device->combined_sense)
320			set_check_condition(qrequest);
321	}
322
323	finish_request(qrequest, false);
324}
325
326
327/**	finish request and release bus
328 *	resubmit - true, if request should be resubmitted by XPT
329 */
330
331void
332finish_request(ide_qrequest *qrequest, bool resubmit)
333{
334	ide_device_info *device = qrequest->device;
335	ide_bus_info *bus = device->bus;
336	scsi_ccb *request;
337	uint num_running;
338
339	SHOW_FLOW0(3, "");
340
341	// save request first, as qrequest can be reused as soon as
342	// access_finished is called!
343	request = qrequest->request;
344
345	qrequest->running = false;
346	qrequest->next = device->free_qrequests;
347	device->free_qrequests = qrequest;
348
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;
353
354	// paranoia
355	bus->active_qrequest = NULL;
356
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);
365
366	ACQUIRE_BEN(&bus->status_report_ben);
367
368	if (resubmit)
369		scsi->resubmit(request);
370	else
371		scsi->finished(request, num_running);
372
373	RELEASE_BEN(&bus->status_report_ben);
374}
375
376
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)
380 */
381
382static void
383set_check_condition(ide_qrequest *qrequest)
384{
385	scsi_ccb *request = qrequest->request;
386	ide_device_info *device = qrequest->device;
387
388	SHOW_FLOW0(3, "");
389
390	request->subsys_status = SCSI_REQ_CMP_ERR;
391	request->device_status = SCSI_STATUS_CHECK_CONDITION;
392
393	// copy sense only if caller requested it
394	if ((request->flags & SCSI_DIS_AUTOSENSE) == 0) {
395		scsi_sense sense;
396		int sense_len;
397
398		SHOW_FLOW0(3, "autosense");
399
400		// we cannot copy sense directly as sense buffer may be too small
401		create_sense(device, &sense);
402
403		sense_len = min(SCSI_MAX_SENSE_SIZE, sizeof(sense));
404
405		memcpy(request->sense, &sense, sense_len);
406		request->sense_resid = SCSI_MAX_SENSE_SIZE - sense_len;
407		request->subsys_status |= SCSI_AUTOSNS_VALID;
408
409		// device sense gets reset once it's read
410		device->combined_sense = 0;
411	}
412}
413
414
415void
416finish_retry(ide_qrequest *qrequest)
417{
418	qrequest->device->combined_sense = 0;
419	finish_request(qrequest, true);
420}
421
422
423/**	finish request and abort pending requests of the device
424 *	(to be called when the request failed and thus messed up the queue)
425 */
426
427void
428finish_reset_queue(ide_qrequest *qrequest)
429{
430	ide_bus_info *bus = qrequest->device->bus;
431
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);
436
437	finish_checksense(qrequest);
438	send_abort_queue(qrequest->device);
439
440	scsi->unblock_bus(bus->scsi_cookie);
441}
442
443
444/**	finish request, but don't release bus
445 *	if resubmit is true, the request will be resubmitted
446 */
447
448static void
449finish_norelease(ide_qrequest *qrequest, bool resubmit)
450{
451	ide_device_info *device = qrequest->device;
452	ide_bus_info *bus = device->bus;
453	uint num_requests;
454
455	qrequest->running = false;
456	qrequest->next = device->free_qrequests;
457	device->free_qrequests = qrequest;
458
459	num_requests = device->num_running_reqs++;
460	--bus->num_running_reqs;
461
462	if (bus->active_qrequest == qrequest)
463		bus->active_qrequest = NULL;
464
465	ACQUIRE_BEN(&bus->status_report_ben);
466
467	if (resubmit)
468		scsi->resubmit(qrequest->request);
469	else
470		scsi->finished(qrequest->request, num_requests);
471
472	RELEASE_BEN(&bus->status_report_ben);
473}
474
475
476/**	finish all queued requests but <ignore> of the device;
477 *	set resubmit, if requests are to be resubmitted by xpt
478 */
479
480void
481finish_all_requests(ide_device_info *device, ide_qrequest *ignore,
482	int subsys_status, bool resubmit)
483{
484	int i;
485
486	if (device == NULL)
487		return;
488
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);
494
495	for (i = 0; i < device->queue_depth; ++i) {
496		ide_qrequest *qrequest = &device->qreq_array[i];
497
498		if (qrequest->running && qrequest != ignore) {
499			qrequest->request->subsys_status = subsys_status;
500			finish_norelease(qrequest, resubmit);
501		}
502	}
503
504	scsi->unblock_bus(device->bus->scsi_cookie);
505}
506
507
508static status_t
509ide_sim_init_bus(device_node *node, void **cookie)
510{
511	ide_bus_info *bus;
512	bool dmaDisabled = false;
513	status_t status;
514
515	SHOW_FLOW0(3, "");
516
517	// first prepare the info structure
518	bus = (ide_bus_info *)malloc(sizeof(*bus));
519	if (bus == NULL)
520		return B_NO_MEMORY;
521
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;
528
529	{
530		int32 channel_id = -1;
531
532		pnp->get_attr_uint32(node, IDE_CHANNEL_ID_ITEM, (uint32 *)&channel_id, true);
533
534		sprintf(bus->name, "ide_bus %d", (int)channel_id);
535	}
536
537	init_synced_pc(&bus->scan_bus_syncinfo, scan_device_worker);
538	init_synced_pc(&bus->disconnect_syncinfo, disconnect_worker);
539
540	bus->state = ide_state_idle;
541	bus->timer.bus = bus;
542	bus->synced_pc_list = NULL;
543
544	if ((status = scsi->alloc_dpc(&bus->irq_dpc)) < B_OK)
545		goto err1;
546
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;
552	}
553
554	bus->devices[0] = bus->devices[1] = NULL;
555
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;
560	}
561
562	status = INIT_BEN(&bus->status_report_ben, "ide_status_report");
563	if (status < B_OK)
564		goto err4;
565
566	{
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);
573		}
574	}
575
576	bus->first_device = NULL;
577
578	// read restrictions of controller
579
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;
584	}
585
586	bus->max_devices = min(bus->max_devices, 2);
587
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;
592	}
593
594	SHOW_FLOW(2, "can_dma: %d", bus->can_DMA);
595
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;
603		}
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;
610	}
611
612	{
613		device_node *parent = pnp->get_parent_node(node);
614		pnp->get_driver(parent, (driver_module_info **)&bus->controller,
615			(void **)&bus->channel_cookie);
616
617		bus->controller->set_channel(bus->channel_cookie, bus);
618		pnp->put_node(parent);
619	}
620
621	*cookie = bus;
622	return B_OK;
623
624err4:
625	delete_sem(bus->scan_device_sem);
626err3:
627	delete_sem(bus->sync_wait_sem);
628err2:
629	scsi->free_dpc(bus->irq_dpc);
630err1:
631	uninit_synced_pc(&bus->scan_bus_syncinfo);
632	uninit_synced_pc(&bus->disconnect_syncinfo);
633	free(bus);
634
635	return status;
636}
637
638
639static status_t
640ide_sim_uninit_bus(ide_bus_info *bus)
641{
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);
648
649	free(bus);
650
651	return B_OK;
652}
653
654
655// abort all running requests with SCSI_NO_HBA; finally, unblock bus
656static void
657disconnect_worker(ide_bus_info *bus, void *arg)
658{
659	int i;
660
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);
665	}
666
667	scsi->unblock_bus(bus->scsi_cookie);
668}
669
670
671static void
672ide_sim_bus_removed(ide_bus_info *bus)
673{
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);
681}
682
683
684static void
685ide_sim_get_restrictions(ide_bus_info *bus, uchar target_id,
686	bool *is_atapi, bool *no_autosense, uint32 *max_blocks)
687{
688	ide_device_info *device = bus->devices[target_id];
689
690	// we declare even ATA devices as ATAPI so we have to emulate fewer
691	// commands
692	*is_atapi = true;
693
694	// we emulate autosense for ATA devices
695	*no_autosense = false;
696
697	if (device != NULL && device->is_atapi) {
698		// we don't support native autosense for ATAPI devices
699		*no_autosense = true;
700	}
701
702	*max_blocks = 255;
703
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;
711		}
712	}
713}
714
715
716static status_t
717ide_sim_ioctl(ide_bus_info *bus, uint8 targetID, uint32 op, void *buffer, size_t length)
718{
719	ide_device_info *device = bus->devices[targetID];
720
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;
728
729		case IDE_GET_STATUS:
730		{
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;
744
745			status.pio_mode = 0;
746			status.dma_mode = get_device_dma_mode(device);
747
748			memcpy(buffer, &status, min(sizeof(status), length));
749			return B_OK;
750		}
751	}
752
753	return B_DEV_INVALID_IOCTL;
754}
755
756
757static status_t
758std_ops(int32 op, ...)
759{
760	switch (op) {
761		case B_MODULE_INIT:
762		case B_MODULE_UNINIT:
763			return B_OK;
764
765		default:
766			return B_ERROR;
767	}
768}
769
770
771module_dependency module_dependencies[] = {
772	{ SCSI_FOR_SIM_MODULE_NAME, (module_info **)&scsi },
773	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
774	{}
775};
776
777
778scsi_sim_interface ide_sim_module = {
779	{
780		{
781			IDE_SIM_MODULE_NAME,
782			0,
783			std_ops,
784		},
785
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
795	},
796
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,
802
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,
806
807	(void (*)(scsi_sim_cookie, uchar,
808		bool*, bool *, uint32 *))					ide_sim_get_restrictions,
809
810	(status_t (*)(scsi_sim_cookie, uint8, uint32, void *, size_t))ide_sim_ioctl,
811};
812