2 * Copyright 2013, Jérôme Duval, korli@users.berlios.de.
3 * Distributed under the terms of the MIT License.
7 #include "VirtioSCSIPrivate.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
31 set_scsi_bus(scsi_sim_cookie cookie
, scsi_bus bus
)
33 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
39 scsi_io(scsi_sim_cookie cookie
, scsi_ccb
*request
)
42 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
43 if (sim
->ExecuteRequest(request
) == B_BUSY
)
44 gSCSI
->requeue(request
, true);
49 abort_io(scsi_sim_cookie cookie
, scsi_ccb
*request
)
52 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
53 return sim
->AbortRequest(request
);
58 reset_device(scsi_sim_cookie cookie
, uchar targetID
, uchar targetLUN
)
61 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
62 return sim
->ResetDevice(targetID
, targetLUN
);
67 terminate_io(scsi_sim_cookie cookie
, scsi_ccb
*request
)
70 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
71 return sim
->TerminateRequest(request
);
76 path_inquiry(scsi_sim_cookie cookie
, scsi_path_inquiry
*info
)
80 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
81 if (sim
->Bus() == NULL
)
84 sim
->PathInquiry(info
);
89 //! this is called immediately before the SCSI bus manager scans the bus
91 scan_bus(scsi_sim_cookie cookie
)
100 reset_bus(scsi_sim_cookie cookie
)
108 /*! Get restrictions of one device
109 (used for non-SCSI transport protocols and bug fixes)
112 get_restrictions(scsi_sim_cookie cookie
, uchar targetID
, bool *isATAPI
,
113 bool *noAutoSense
, uint32
*maxBlocks
)
116 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
117 sim
->GetRestrictions(targetID
, isATAPI
, noAutoSense
, maxBlocks
);
122 ioctl(scsi_sim_cookie cookie
, uint8 targetID
, uint32 op
, void *buffer
,
126 VirtioSCSIController
*sim
= (VirtioSCSIController
*)cookie
;
127 return sim
->Control(targetID
, op
, buffer
, length
);
135 sim_init_bus(device_node
*node
, void **_cookie
)
139 VirtioSCSIController
*controller
= new(std::nothrow
)
140 VirtioSCSIController(node
);
141 if (controller
== NULL
)
143 status_t status
= controller
->InitCheck();
149 *_cookie
= controller
;
155 sim_uninit_bus(void *cookie
)
158 VirtioSCSIController
*controller
= (VirtioSCSIController
*)cookie
;
168 virtio_scsi_supports_device(device_node
*parent
)
173 // make sure parent is really the Virtio bus manager
174 if (gDeviceManager
->get_attr_string(parent
, B_DEVICE_BUS
, &bus
, false))
177 if (strcmp(bus
, "virtio"))
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
)
185 TRACE("Virtio SCSI device found!\n");
192 virtio_scsi_register_device(device_node
*parent
)
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
));
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
,
218 { B_DEVICE_PRETTY_NAME
, B_STRING_TYPE
,
219 { string
: VIRTIO_SCSI_BRIDGE_PRETTY_NAME
}},
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
}},
228 return gDeviceManager
->register_node(parent
, VIRTIO_SCSI_DEVICE_MODULE_NAME
,
234 virtio_scsi_init_driver(device_node
*node
, void **_cookie
)
243 virtio_scsi_register_child_devices(void *cookie
)
246 device_node
*node
= (device_node
*)cookie
;
248 int32 id
= gDeviceManager
->create_id(VIRTIO_SCSI_ID_GENERATOR
);
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
}},
264 status_t status
= gDeviceManager
->register_node(node
,
265 VIRTIO_SCSI_SIM_MODULE_NAME
, attrs
, NULL
, NULL
);
267 gDeviceManager
->free_id(VIRTIO_SCSI_ID_GENERATOR
, id
);
274 std_ops(int32 op
, ...)
278 case B_MODULE_UNINIT
:
287 static scsi_sim_interface sVirtioSCSISimInterface
= {
290 VIRTIO_SCSI_SIM_MODULE_NAME
,
294 NULL
, // supported devices
295 NULL
, // register node
298 NULL
, // register child devices
315 static driver_module_info sVirtioSCSIDevice
= {
317 VIRTIO_SCSI_DEVICE_MODULE_NAME
,
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
,
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
,