btrfs: Attempt to fix GCC2 build.
[haiku.git] / src / add-ons / kernel / busses / scsi / virtio / virtio_scsi.cpp
blobcd092a9c12f150b6c2a9e2b40a4f5dfc0f294570
1 /*
2 * Copyright 2013, Jérôme Duval, korli@users.berlios.de.
3 * Distributed under the terms of the MIT License.
4 */
7 #include "VirtioSCSIPrivate.h"
9 #include <new>
10 #include <stdlib.h>
11 #include <string.h>
14 #define VIRTIO_SCSI_ID_GENERATOR "virtio_scsi/id"
15 #define VIRTIO_SCSI_ID_ITEM "virtio_scsi/id"
16 #define VIRTIO_SCSI_BRIDGE_PRETTY_NAME "Virtio SCSI Bridge"
17 #define VIRTIO_SCSI_CONTROLLER_PRETTY_NAME "Virtio SCSI Controller"
19 #define VIRTIO_SCSI_DEVICE_MODULE_NAME "busses/scsi/virtio_scsi/driver_v1"
20 #define VIRTIO_SCSI_SIM_MODULE_NAME "busses/scsi/virtio_scsi/sim/driver_v1"
23 device_manager_info *gDeviceManager;
24 scsi_for_sim_interface *gSCSI;
27 // #pragma mark - SIM module interface
30 static void
31 set_scsi_bus(scsi_sim_cookie cookie, scsi_bus bus)
33 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
34 sim->SetBus(bus);
38 static void
39 scsi_io(scsi_sim_cookie cookie, scsi_ccb *request)
41 CALLED();
42 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
43 if (sim->ExecuteRequest(request) == B_BUSY)
44 gSCSI->requeue(request, true);
48 static uchar
49 abort_io(scsi_sim_cookie cookie, scsi_ccb *request)
51 CALLED();
52 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
53 return sim->AbortRequest(request);
57 static uchar
58 reset_device(scsi_sim_cookie cookie, uchar targetID, uchar targetLUN)
60 CALLED();
61 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
62 return sim->ResetDevice(targetID, targetLUN);
66 static uchar
67 terminate_io(scsi_sim_cookie cookie, scsi_ccb *request)
69 CALLED();
70 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
71 return sim->TerminateRequest(request);
75 static uchar
76 path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info)
78 CALLED();
80 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
81 if (sim->Bus() == NULL)
82 return SCSI_NO_HBA;
84 sim->PathInquiry(info);
85 return SCSI_REQ_CMP;
89 //! this is called immediately before the SCSI bus manager scans the bus
90 static uchar
91 scan_bus(scsi_sim_cookie cookie)
93 CALLED();
95 return SCSI_REQ_CMP;
99 static uchar
100 reset_bus(scsi_sim_cookie cookie)
102 CALLED();
104 return SCSI_REQ_CMP;
108 /*! Get restrictions of one device
109 (used for non-SCSI transport protocols and bug fixes)
111 static void
112 get_restrictions(scsi_sim_cookie cookie, uchar targetID, bool *isATAPI,
113 bool *noAutoSense, uint32 *maxBlocks)
115 CALLED();
116 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
117 sim->GetRestrictions(targetID, isATAPI, noAutoSense, maxBlocks);
121 static status_t
122 ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer,
123 size_t length)
125 CALLED();
126 VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
127 return sim->Control(targetID, op, buffer, length);
131 // #pragma mark -
134 static status_t
135 sim_init_bus(device_node *node, void **_cookie)
137 CALLED();
139 VirtioSCSIController *controller = new(std::nothrow)
140 VirtioSCSIController(node);
141 if (controller == NULL)
142 return B_NO_MEMORY;
143 status_t status = controller->InitCheck();
144 if (status < B_OK) {
145 delete controller;
146 return status;
149 *_cookie = controller;
150 return B_OK;
154 static void
155 sim_uninit_bus(void *cookie)
157 CALLED();
158 VirtioSCSIController *controller = (VirtioSCSIController*)cookie;
160 delete controller;
164 // #pragma mark -
167 static float
168 virtio_scsi_supports_device(device_node *parent)
170 const char *bus;
171 uint16 deviceType;
173 // make sure parent is really the Virtio bus manager
174 if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
175 return -1;
177 if (strcmp(bus, "virtio"))
178 return 0.0;
180 // check whether it's really a Virtio SCSI Device
181 if (gDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM,
182 &deviceType, true) != B_OK || deviceType != VIRTIO_DEVICE_ID_SCSI)
183 return 0.0;
185 TRACE("Virtio SCSI device found!\n");
187 return 0.6f;
191 static status_t
192 virtio_scsi_register_device(device_node *parent)
194 CALLED();
195 virtio_device_interface* virtio = NULL;
196 virtio_device* virtioDevice = NULL;
197 struct virtio_scsi_config config;
199 gDeviceManager->get_driver(parent, (driver_module_info **)&virtio,
200 (void **)&virtioDevice);
202 status_t status = virtio->read_device_config(virtioDevice, 0, &config,
203 sizeof(struct virtio_scsi_config));
204 if (status != B_OK)
205 return status;
207 uint32 max_targets = config.max_target + 1;
208 uint32 max_luns = config.max_lun + 1;
209 uint32 max_blocks = 0x10000;
210 if (config.max_sectors != 0)
211 max_blocks = config.max_sectors;
213 device_attr attrs[] = {
214 { SCSI_DEVICE_MAX_TARGET_COUNT, B_UINT32_TYPE,
215 { ui32: max_targets }},
216 { SCSI_DEVICE_MAX_LUN_COUNT, B_UINT32_TYPE,
217 { ui32: max_luns }},
218 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
219 { string: VIRTIO_SCSI_BRIDGE_PRETTY_NAME }},
221 // DMA properties
222 { B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { ui32: max_blocks }},
223 { B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE,
224 { ui32: config.seg_max }},
225 { NULL }
228 return gDeviceManager->register_node(parent, VIRTIO_SCSI_DEVICE_MODULE_NAME,
229 attrs, NULL, NULL);
233 static status_t
234 virtio_scsi_init_driver(device_node *node, void **_cookie)
236 CALLED();
237 *_cookie = node;
238 return B_OK;
242 static status_t
243 virtio_scsi_register_child_devices(void *cookie)
245 CALLED();
246 device_node *node = (device_node *)cookie;
248 int32 id = gDeviceManager->create_id(VIRTIO_SCSI_ID_GENERATOR);
249 if (id < 0)
250 return id;
252 device_attr attrs[] = {
253 { B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
254 { string: SCSI_FOR_SIM_MODULE_NAME }},
255 { B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
256 { string: VIRTIO_SCSI_CONTROLLER_PRETTY_NAME }},
257 { SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE,
258 { string: VIRTIO_SCSI_DEVICE_MODULE_NAME }},
259 { B_DMA_MAX_TRANSFER_BLOCKS, B_UINT32_TYPE, { ui32: 255 }},
260 { VIRTIO_SCSI_ID_ITEM, B_UINT32_TYPE, { ui32: (uint32)id }},
261 { NULL }
264 status_t status = gDeviceManager->register_node(node,
265 VIRTIO_SCSI_SIM_MODULE_NAME, attrs, NULL, NULL);
266 if (status < B_OK)
267 gDeviceManager->free_id(VIRTIO_SCSI_ID_GENERATOR, id);
269 return status;
273 static status_t
274 std_ops(int32 op, ...)
276 switch (op) {
277 case B_MODULE_INIT:
278 case B_MODULE_UNINIT:
279 return B_OK;
281 default:
282 return B_ERROR;
287 static scsi_sim_interface sVirtioSCSISimInterface = {
290 VIRTIO_SCSI_SIM_MODULE_NAME,
292 std_ops
294 NULL, // supported devices
295 NULL, // register node
296 sim_init_bus,
297 sim_uninit_bus,
298 NULL, // register child devices
299 NULL, // rescan
300 NULL // bus_removed
302 set_scsi_bus,
303 scsi_io,
304 abort_io,
305 reset_device,
306 terminate_io,
307 path_inquiry,
308 scan_bus,
309 reset_bus,
310 get_restrictions,
311 ioctl
315 static driver_module_info sVirtioSCSIDevice = {
317 VIRTIO_SCSI_DEVICE_MODULE_NAME,
319 std_ops
321 virtio_scsi_supports_device,
322 virtio_scsi_register_device,
323 virtio_scsi_init_driver,
324 NULL, // uninit_driver,
325 virtio_scsi_register_child_devices,
326 NULL, // rescan
327 NULL, // device_removed
331 module_dependency module_dependencies[] = {
332 { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
333 { SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSI },
338 module_info *modules[] = {
339 (module_info *)&sVirtioSCSIDevice,
340 (module_info *)&sVirtioSCSISimInterface,
341 NULL