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