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