xref: /haiku/src/add-ons/kernel/busses/scsi/ahci/ahci_sim.cpp (revision 1c09002cbee8e797a0f8bbfc5678dfadd39ee1a7)
1 /*
2  * Copyright 2007-2009, Marcus Overhagen. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 #include "ahci_controller.h"
7 
8 #include <KernelExport.h>
9 #include <string.h>
10 #include <new>
11 
12 #define TRACE(a...) dprintf("ahci: " a)
13 //#define FLOW(a...)	dprintf("ahci: " a)
14 #define FLOW(a...)
15 
16 
17 //	#pragma mark - SIM module interface
18 
19 
20 static void
21 ahci_set_scsi_bus(scsi_sim_cookie cookie, scsi_bus bus)
22 {
23 }
24 
25 
26 //! execute request
27 static void
28 ahci_scsi_io(scsi_sim_cookie cookie, scsi_ccb *request)
29 {
30 	FLOW("ahci_scsi_io, cookie %p, path_id %u, target_id %u, target_lun %u\n",
31 		cookie, request->path_id, request->target_id, request->target_lun);
32 	static_cast<AHCIController *>(cookie)->ExecuteRequest(request);
33 }
34 
35 
36 //! abort request
37 static uchar
38 ahci_abort_io(scsi_sim_cookie cookie, scsi_ccb *request)
39 {
40 	TRACE("ahci_abort_io, cookie %p\n", cookie);
41 	return static_cast<AHCIController *>(cookie)->AbortRequest(request);
42 }
43 
44 
45 static uchar
46 ahci_reset_device(scsi_sim_cookie cookie, uchar targetID, uchar targetLUN)
47 {
48 	TRACE("ahci_reset_device, cookie %p\n", cookie);
49 	return static_cast<AHCIController *>(cookie)->ResetDevice(targetID, targetLUN);
50 }
51 
52 
53 //! terminate request
54 static uchar
55 ahci_terminate_io(scsi_sim_cookie cookie, scsi_ccb *request)
56 {
57 	TRACE("ahci_terminate_io, cookie %p\n", cookie);
58 	return static_cast<AHCIController *>(cookie)->TerminateRequest(request);
59 }
60 
61 
62 //! get information about bus
63 static uchar
64 ahci_path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info)
65 {
66 	TRACE("ahci_path_inquiry, cookie %p\n", cookie);
67 
68 	memset(info, 0, sizeof(*info));
69 	info->version_num = 1;
70 	// supports tagged requests and soft reset
71 	info->hba_inquiry = 0; // SCSI_PI_TAG_ABLE | SCSI_PI_SOFT_RST;
72 	// controller is 32, devices are 0 to 31
73 	info->initiator_id = 32;
74 	// adapter command queue size
75 	info->hba_queue_size = 1;
76 
77 	return SCSI_REQ_CMP;
78 }
79 
80 
81 //! this is called immediately before the SCSI bus manager scans the bus
82 static uchar
83 ahci_scan_bus(scsi_sim_cookie cookie)
84 {
85 	TRACE("ahci_scan_bus, cookie %p\n", cookie);
86 
87 	return SCSI_REQ_CMP;
88 }
89 
90 
91 static uchar
92 ahci_reset_bus(scsi_sim_cookie cookie)
93 {
94 	TRACE("ahci_reset_bus, cookie %p\n", cookie);
95 
96 	return SCSI_REQ_CMP;
97 }
98 
99 
100 /*!	Get restrictions of one device
101 	(used for non-SCSI transport protocols and bug fixes)
102 */
103 static void
104 ahci_get_restrictions(scsi_sim_cookie cookie, uchar targetID, bool *isATAPI,
105 	bool *noAutoSense, uint32 *maxBlocks)
106 {
107 	TRACE("ahci_get_restrictions, cookie %p\n", cookie);
108 
109 	static_cast<AHCIController *>(cookie)->GetRestrictions(targetID, isATAPI, noAutoSense, maxBlocks);
110 }
111 
112 
113 static status_t
114 ahci_ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer,
115 	size_t length)
116 {
117 	TRACE("ahci_ioctl, cookie %p\n", cookie);
118 	return B_DEV_INVALID_IOCTL;
119 }
120 
121 
122 //	#pragma mark -
123 
124 
125 static status_t
126 ahci_sim_init_bus(device_node *node, void **_cookie)
127 {
128 	TRACE("ahci_sim_init_bus\n");
129 
130 	// get the PCI device from our parent's parent
131 	device_node *parent = gDeviceManager->get_parent_node(node);
132 	device_node *pciParent = gDeviceManager->get_parent_node(parent);
133 	gDeviceManager->put_node(parent);
134 
135 	pci_device_module_info *pci;
136 	pci_device *pciDevice;
137 	gDeviceManager->get_driver(pciParent, (driver_module_info **)&pci,
138 		(void **)&pciDevice);
139 	gDeviceManager->put_node(pciParent);
140 
141 	TRACE("ahci_sim_init_bus: pciDevice %p\n", pciDevice);
142 
143 	AHCIController *controller =  new(std::nothrow) AHCIController(node, pci,
144 		pciDevice);
145 	if (!controller)
146 		return B_NO_MEMORY;
147 	status_t status = controller->Init();
148 	if (status < B_OK) {
149 		delete controller;
150 		return status;
151 	}
152 
153 	*_cookie = controller;
154 	TRACE("cookie = %p\n", *_cookie);
155 	return B_OK;
156 }
157 
158 
159 static void
160 ahci_sim_uninit_bus(void *cookie)
161 {
162 	TRACE("ahci_sim_uninit_bus, cookie %p\n", cookie);
163 	AHCIController *controller = static_cast<AHCIController *>(cookie);
164 
165 	controller->Uninit();
166 	delete controller;
167 }
168 
169 
170 static void
171 ahci_sim_bus_removed(void *cookie)
172 {
173 	TRACE("ahci_sim_bus_removed, cookie %p\n", cookie);
174 }
175 
176 
177 static status_t
178 std_ops(int32 op, ...)
179 {
180 	switch (op) {
181 		case B_MODULE_INIT:
182 		case B_MODULE_UNINIT:
183 			return B_OK;
184 
185 		default:
186 			return B_ERROR;
187 	}
188 }
189 
190 
191 scsi_sim_interface gAHCISimInterface = {
192 	{
193 		{
194 			AHCI_SIM_MODULE_NAME,
195 			0,
196 			std_ops
197 		},
198 		NULL,	// supported devices
199 		NULL,	// register node
200 		ahci_sim_init_bus,
201 		ahci_sim_uninit_bus,
202 		NULL,	// register child devices
203 		NULL,	// rescan
204 		ahci_sim_bus_removed
205 	},
206 	ahci_set_scsi_bus,
207 	ahci_scsi_io,
208 	ahci_abort_io,
209 	ahci_reset_device,
210 	ahci_terminate_io,
211 	ahci_path_inquiry,
212 	ahci_scan_bus,
213 	ahci_reset_bus,
214 	ahci_get_restrictions,
215 	ahci_ioctl
216 };
217