hrev45865 adds 6 changesets to branch 'master' old head: 71fec49e6725dd1ce645fb42504d1264044a3137 new head: e598dee7522bba2b525730cb6e888c5a69c8aead overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=e598dee+%5E71fec49 ---------------------------------------------------------------------------- a6ffcfb: scsi_disk: added a hook for rescanning devices * a call indicates the media was changed. f08e2e6: scsi: propagates the rescan to our child device ... when registering finds an existing device with a registered child node. ea2fa87: scsi_cmds.h: added SCSIS_ASC_CAPACITY_DATA_HAS_CHANGED * indicates the device data capacity has changed.. b3a0911: virtio_scsi: added configuration change definitions. * supported by at least QEmu 1.4 ed4a8e4: virtio: changed a bit the driver API by adding a driverCookie. * the processing of requests in drivers is eased a bit with this change, but this could be improved for instance by enabling a driver to dequeue items in a service thread instead of the interrupt handler. * made a few methods const. e598dee: virtio_scsi: now handles events like capacity data changed. * push event requests on the event queue, handles them. * activate feature VIRTIO_SCSI_F_CHANGE. * when a capacity data changed event is received, schedule a rescan of the scsi device node on the scsi dpc queue. we find out unique child node and call the rescan_node() hook. * Haiku only handles media changed events on removable devices, so the feature only actually works when the device is defined as such, aka for QEMU the following option: -device scsi-hd,drive=hd,removable=true [ Jérôme Duval <jerome.duval@xxxxxxxxx> ] ---------------------------------------------------------------------------- 12 files changed, 171 insertions(+), 36 deletions(-) headers/private/drivers/scsi_cmds.h | 1 + headers/private/virtio/virtio.h | 4 +- .../kernel/bus_managers/scsi/device_scan.cpp | 16 ++- .../kernel/bus_managers/virtio/VirtioDevice.cpp | 12 ++- .../kernel/bus_managers/virtio/VirtioModule.cpp | 4 +- .../kernel/bus_managers/virtio/VirtioPrivate.h | 19 ++-- .../kernel/bus_managers/virtio/VirtioQueue.cpp | 15 +-- .../busses/scsi/virtio/VirtioSCSIController.cpp | 103 +++++++++++++++++-- .../busses/scsi/virtio/VirtioSCSIPrivate.h | 14 ++- .../kernel/busses/scsi/virtio/virtio_scsi.h | 2 + .../drivers/disk/scsi/scsi_disk/scsi_disk.cpp | 15 ++- .../disk/virtual/virtio_block/virtio_block.cpp | 2 +- ############################################################################ Commit: a6ffcfb320d376c85353582a030ee710396a0f28 URL: http://cgit.haiku-os.org/haiku/commit/?id=a6ffcfb Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Tue Jul 16 16:24:01 2013 UTC scsi_disk: added a hook for rescanning devices * a call indicates the media was changed. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp index a50a149..d3d13af 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_disk/scsi_disk.cpp @@ -595,6 +595,19 @@ das_register_child_devices(void* _cookie) } +static status_t +das_rescan_child_devices(void* _cookie) +{ + das_driver_info* info = (das_driver_info*)_cookie; + uint64 capacity = info->capacity; + update_capacity(info); + if (info->capacity != capacity) + sSCSIPeripheral->media_changed(info->scsi_periph_device); + return B_OK; +} + + + module_dependency module_dependencies[] = { {SCSI_PERIPH_MODULE_NAME, (module_info**)&sSCSIPeripheral}, {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager}, @@ -636,7 +649,7 @@ struct driver_module_info sSCSIDiskDriver = { das_init_driver, das_uninit_driver, das_register_child_devices, - NULL, // rescan + das_rescan_child_devices, NULL, // removed }; ############################################################################ Commit: f08e2e6b2ae7ba5a0719d1bed5b3e567957ff487 URL: http://cgit.haiku-os.org/haiku/commit/?id=f08e2e6 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Tue Jul 16 16:26:30 2013 UTC scsi: propagates the rescan to our child device ... when registering finds an existing device with a registered child node. ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/bus_managers/scsi/device_scan.cpp b/src/add-ons/kernel/bus_managers/scsi/device_scan.cpp index e6a41fd..97d77d7 100644 --- a/src/add-ons/kernel/bus_managers/scsi/device_scan.cpp +++ b/src/add-ons/kernel/bus_managers/scsi/device_scan.cpp @@ -223,8 +223,20 @@ scsi_scan_lun(scsi_bus_info *bus, uchar target_id, uchar target_lun) // solution 2: device drivers must scan devices before first use // disadvantage: it takes time and driver must perform a task that // the bus_manager should really take care of - scsi_register_device(bus, target_id, target_lun, &new_inquiry_data); - + res = scsi_register_device(bus, target_id, target_lun, &new_inquiry_data); + if (res == B_NAME_IN_USE) { + SHOW_FLOW0(3, "name in use"); + if (scsi_force_get_device(bus, target_id, target_lun, &device) != B_OK) + return B_OK; + // the device was already registered, let's tell our child to rescan it + device_node *childNode = NULL; + const device_attr attrs[] = { { NULL } }; + if (pnp->get_next_child_node(bus->node, attrs, &childNode) == B_OK) { + pnp->rescan_node(childNode); + pnp->put_node(childNode); + } + scsi_put_forced_device(device); + } return B_OK; err3: ############################################################################ Commit: ea2fa8721995774afc60047e747a9f010f2d8317 URL: http://cgit.haiku-os.org/haiku/commit/?id=ea2fa87 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Tue Jul 16 16:30:03 2013 UTC scsi_cmds.h: added SCSIS_ASC_CAPACITY_DATA_HAS_CHANGED * indicates the device data capacity has changed.. ---------------------------------------------------------------------------- diff --git a/headers/private/drivers/scsi_cmds.h b/headers/private/drivers/scsi_cmds.h index 1e1a47c..ea45233 100644 --- a/headers/private/drivers/scsi_cmds.h +++ b/headers/private/drivers/scsi_cmds.h @@ -146,6 +146,7 @@ #define SCSIS_ASC_WAS_RESET 0x2900 // reset by power-on/bus reset/device reset #define SCSIS_ASC_PARAMS_CHANGED 0x2a00 +#define SCSIS_ASC_CAPACITY_DATA_HAS_CHANGED 0x2a09 #define SCSIS_ASC_MEDIUM_FORMAT_CORRUPTED 0x3100 #define SCSIS_ASC_ROUNDED_PARAM 0x3700 // parameter got rounded #define SCSIS_ASC_NO_MEDIUM 0x3a00 // medium not present ############################################################################ Commit: b3a0911eb73c4f2c38663e4016b0b862cbf919da URL: http://cgit.haiku-os.org/haiku/commit/?id=b3a0911 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Tue Jul 16 16:31:45 2013 UTC virtio_scsi: added configuration change definitions. * supported by at least QEmu 1.4 ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.h b/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.h index b781839..2c8a7d6 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.h +++ b/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.h @@ -35,6 +35,7 @@ #define VIRTIO_SCSI_F_HOTPLUG 0x0002 /* Host should enable hot plug/unplug * of new LUNs and targets. */ +#define VIRTIO_SCSI_F_CHANGE 0x0004 /* Host can change the config */ #define VIRTIO_SCSI_CDB_SIZE 32 #define VIRTIO_SCSI_SENSE_SIZE 96 @@ -138,6 +139,7 @@ struct virtio_scsi_config { #define VIRTIO_SCSI_T_NO_EVENT 0 #define VIRTIO_SCSI_T_TRANSPORT_RESET 1 #define VIRTIO_SCSI_T_ASYNC_NOTIFY 2 +#define VIRTIO_SCSI_T_PARAM_CHANGE 3 /* Reasons of transport reset event */ #define VIRTIO_SCSI_EVT_RESET_HARD 0 ############################################################################ Commit: ed4a8e4d11d7972d6fb6f025c108915ad06c73af URL: http://cgit.haiku-os.org/haiku/commit/?id=ed4a8e4 Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Wed Jul 17 15:30:18 2013 UTC virtio: changed a bit the driver API by adding a driverCookie. * the processing of requests in drivers is eased a bit with this change, but this could be improved for instance by enabling a driver to dequeue items in a service thread instead of the interrupt handler. * made a few methods const. ---------------------------------------------------------------------------- diff --git a/headers/private/virtio/virtio.h b/headers/private/virtio/virtio.h index 94642c9..fffe0d7 100644 --- a/headers/private/virtio/virtio.h +++ b/headers/private/virtio/virtio.h @@ -53,7 +53,7 @@ typedef void* virtio_device; // queue cookie, issued by virtio bus manager typedef void* virtio_queue; // callback function for requests -typedef void (*virtio_callback_func)(void *cookie); +typedef void (*virtio_callback_func)(void* driverCookie, void *cookie); // callback function for interrupts typedef void (*virtio_intr_func)(void *cookie); @@ -105,7 +105,7 @@ typedef struct { virtio_queue *queues); status_t (*setup_interrupt)(virtio_device cookie, - virtio_intr_func config_handler, void* configCookie); + virtio_intr_func config_handler, void* driverCookie); status_t (*queue_request)(virtio_queue queue, const physical_entry *readEntry, diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp index 03c514a..d2a12f0 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioDevice.cpp @@ -58,7 +58,10 @@ VirtioDevice::VirtioDevice(device_node *node) fCookie(NULL), fStatus(B_NO_INIT), fQueues(NULL), - fFeatures(0) + fFeatures(0), + fAlignment(0), + fConfigHandler(NULL), + fDriverCookie(NULL) { device_node *parent = gDeviceManager->get_parent_node(node); fStatus = gDeviceManager->get_driver(parent, @@ -172,11 +175,10 @@ err: status_t -VirtioDevice::SetupInterrupt(virtio_intr_func configHandler, - void* configCookie) +VirtioDevice::SetupInterrupt(virtio_intr_func configHandler, void *driverCookie) { fConfigHandler = configHandler; - fConfigCookie = configCookie; + fDriverCookie = driverCookie; status_t status = fController->setup_interrupt(fCookie, fQueueCount); if (status != B_OK) return status; @@ -228,7 +230,7 @@ status_t VirtioDevice::ConfigInterrupt() { if (fConfigHandler != NULL) - fConfigHandler(fConfigCookie); + fConfigHandler(fDriverCookie); return B_OK; } diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp index 8229fc7..de6328e 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioModule.cpp @@ -96,11 +96,11 @@ virtio_alloc_queues(virtio_device cookie, size_t count, virtio_queue *queues) status_t virtio_setup_interrupt(virtio_device cookie, virtio_intr_func config_handler, - void* configCookie) + void *driverCookie) { CALLED(); VirtioDevice *device = (VirtioDevice *)cookie; - return device->SetupInterrupt(config_handler, configCookie); + return device->SetupInterrupt(config_handler, driverCookie); } diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h index 1b31201..4097bdd 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioPrivate.h @@ -23,7 +23,8 @@ #else # define TRACE(x...) #endif -#define ERROR(x...) dprintf("\33[33mvirtio:\33[0m " x) +#define TRACE_ALWAYS(x...) dprintf("\33[33mvirtio:\33[0m " x) +#define ERROR(x...) TRACE_ALWAYS(x) #define CALLED() TRACE("CALLED %s\n", __PRETTY_FUNCTION__) @@ -56,10 +57,12 @@ public: status_t AllocateQueues(size_t count, virtio_queue *queues); status_t SetupInterrupt(virtio_intr_func config_handler, - void* configCookie); + void *driverCookie); - uint16 Alignment() { return fAlignment; } - uint32 Features() { return fFeatures; } + uint16 Alignment() const { return fAlignment; } + uint32 Features() const { return fFeatures; } + + void* DriverCookie() { return fDriverCookie; } status_t SetupQueue(uint16 queueNumber, phys_addr_t physAddr); @@ -85,7 +88,7 @@ private: uint16 fAlignment; virtio_intr_func fConfigHandler; - void* fConfigCookie; + void* fDriverCookie; }; @@ -102,8 +105,10 @@ public: void NotifyHost(); status_t Interrupt(); - bool IsFull() { return fRingFree == 0; } - bool IsEmpty() { return fRingFree == fRingSize; } + bool IsFull() const { return fRingFree == 0; } + bool IsEmpty() const { return fRingFree == fRingSize; } + + VirtioDevice* Device() { return fDevice; } status_t QueueRequest(const physical_entry* vector, size_t readVectorCount, diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp index 5133348..6f8acf3 100644 --- a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp +++ b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp @@ -50,7 +50,8 @@ alloc_mem(void **virt, phys_addr_t *phy, size_t size, uint32 protection, class TransferDescriptor { public: - TransferDescriptor(uint16 size, + TransferDescriptor(VirtioQueue* queue, + uint16 size, virtio_callback_func callback, void *callbackCookie); ~TransferDescriptor(); @@ -58,6 +59,7 @@ public: void Callback(); uint16 Size() { return fDescriptorCount; } private: + VirtioQueue* fQueue; void* fCookie; virtio_callback_func fCallback; struct vring_desc* fIndirect; @@ -67,9 +69,10 @@ private: }; -TransferDescriptor::TransferDescriptor(uint16 size, +TransferDescriptor::TransferDescriptor(VirtioQueue* queue, uint16 size, virtio_callback_func callback, void *callbackCookie) - : fCookie(callbackCookie), + : fQueue(queue), + fCookie(callbackCookie), fCallback(callback), fDescriptorCount(size) { @@ -85,7 +88,7 @@ void TransferDescriptor::Callback() { if (fCallback != NULL) - fCallback(fCookie); + fCallback(fQueue->Device()->DriverCookie(), fCookie); } @@ -226,8 +229,8 @@ VirtioQueue::QueueRequest(const physical_entry* vector, size_t readVectorCount, return B_BUSY; uint16 insertIndex = fRingHeadIndex; - fDescriptors[insertIndex] = new(std::nothrow) TransferDescriptor(count, - callback, callbackCookie); + fDescriptors[insertIndex] = new(std::nothrow) TransferDescriptor(this, + count, callback, callbackCookie); if (fDescriptors[insertIndex] == NULL) return B_NO_MEMORY; diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp index dcde6c8..d66d2ce 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp +++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp @@ -84,7 +84,7 @@ VirtioSCSIController::VirtioSCSIController(device_node *node) fEventVirtioQueue = virtioQueues[1]; fRequestVirtioQueue = virtioQueues[2]; - fStatus = fVirtio->setup_interrupt(fVirtioDevice, NULL, NULL); + fStatus = fVirtio->setup_interrupt(fVirtioDevice, NULL, this); if (fStatus != B_OK) { ERROR("interrupt setup failed (%s)\n", strerror(fStatus)); return; @@ -206,7 +206,7 @@ VirtioSCSIController::ExecuteRequest(scsi_ccb *ccb) } fVirtio->queue_request_v(fRequestVirtioQueue, entries, - outCount, inCount, VirtioSCSIController::RequestCallback, this); + outCount, inCount, VirtioSCSIController::_RequestCallback, NULL); result = fInterruptConditionEntry.Wait(B_RELATIVE_TIMEOUT, fRequest->Timeout()); @@ -247,16 +247,16 @@ VirtioSCSIController::Control(uint8 targetID, uint32 op, void *buffer, void -VirtioSCSIController::RequestCallback(void* cookie) +VirtioSCSIController::_RequestCallback(void* driverCookie, void* cookie) { CALLED(); - VirtioSCSIController* controller = (VirtioSCSIController*)cookie; - controller->_Interrupt(); + VirtioSCSIController* controller = (VirtioSCSIController*)driverCookie; + controller->_RequestInterrupt(); } void -VirtioSCSIController::_Interrupt() +VirtioSCSIController::_RequestInterrupt() { SpinLocker locker(fInterruptLock); fInterruptCondition.NotifyAll(); diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h index 0dddad1..8e48c01 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h +++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h @@ -60,8 +60,9 @@ public: void* buffer, size_t length); private: - static void RequestCallback(void *cookie); - void _Interrupt(); + static void _RequestCallback(void* driverCookie, + void *cookie); + void _RequestInterrupt(); device_node* fNode; scsi_bus fBus; diff --git a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp index 0fa462d..131b527 100644 --- a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp +++ b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_block.cpp @@ -160,7 +160,7 @@ log2(uint32 x) static void -virtio_block_callback(void* cookie) +virtio_block_callback(void* driverCookie, void* cookie) { virtio_block_driver_info* info = (virtio_block_driver_info*)cookie; ############################################################################ Revision: hrev45865 Commit: e598dee7522bba2b525730cb6e888c5a69c8aead URL: http://cgit.haiku-os.org/haiku/commit/?id=e598dee Author: Jérôme Duval <jerome.duval@xxxxxxxxx> Date: Wed Jul 17 15:48:33 2013 UTC virtio_scsi: now handles events like capacity data changed. * push event requests on the event queue, handles them. * activate feature VIRTIO_SCSI_F_CHANGE. * when a capacity data changed event is received, schedule a rescan of the scsi device node on the scsi dpc queue. we find out unique child node and call the rescan_node() hook. * Haiku only handles media changed events on removable devices, so the feature only actually works when the device is defined as such, aka for QEMU the following option: -device scsi-hd,drive=hd,removable=true ---------------------------------------------------------------------------- diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp index d66d2ce..308835d 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp +++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp @@ -32,12 +32,16 @@ VirtioSCSIController::VirtioSCSIController(device_node *node) fVirtio(NULL), fVirtioDevice(NULL), fStatus(B_NO_INIT), - fRequest(NULL) + fRequest(NULL), + fEventDPC(NULL) { CALLED(); B_INITIALIZE_SPINLOCK(&fInterruptLock); fInterruptCondition.Init(this, "virtio scsi transfer"); + + if (gSCSI->alloc_dpc(&fEventDPC) != B_OK) + return; // get the Virtio device from our parent's parent device_node *parent = gDeviceManager->get_parent_node(node); @@ -49,7 +53,7 @@ VirtioSCSIController::VirtioSCSIController(device_node *node) gDeviceManager->put_node(virtioParent); fVirtio->negociate_features(fVirtioDevice, - 0 /*VIRTIO_SCSI_F_HOTPLUG*/, + VIRTIO_SCSI_F_CHANGE /*VIRTIO_SCSI_F_HOTPLUG*/, &fFeatures, &get_feature_name); fStatus = fVirtio->read_device_config(fVirtioDevice, 0, &fConfig, @@ -83,6 +87,9 @@ VirtioSCSIController::VirtioSCSIController(device_node *node) fControlVirtioQueue = virtioQueues[0]; fEventVirtioQueue = virtioQueues[1]; fRequestVirtioQueue = virtioQueues[2]; + + for (uint32 i = 0; i < VIRTIO_SCSI_NUM_EVENTS; i++) + _SubmitEvent(i); fStatus = fVirtio->setup_interrupt(fVirtioDevice, NULL, this); if (fStatus != B_OK) { @@ -98,6 +105,8 @@ VirtioSCSIController::~VirtioSCSIController() { CALLED(); delete fRequest; + + gSCSI->free_dpc(fEventDPC); } @@ -262,3 +271,81 @@ VirtioSCSIController::_RequestInterrupt() fInterruptCondition.NotifyAll(); } + + +void +VirtioSCSIController::_EventCallback(void* driverCookie, void* cookie) +{ + CALLED(); + VirtioSCSIController* controller = (VirtioSCSIController*)driverCookie; + struct virtio_scsi_event* event = (struct virtio_scsi_event*)cookie; + controller->_EventInterrupt(event); +} + + +void +VirtioSCSIController::_EventInterrupt(struct virtio_scsi_event* event) +{ + CALLED(); + TRACE("events %#x\n", event->event); + if ((event->event & VIRTIO_SCSI_T_EVENTS_MISSED) != 0) { + ERROR("events missed\n"); + } else switch (event->event) { + case VIRTIO_SCSI_T_TRANSPORT_RESET: + ERROR("transport reset\n"); + break; + case VIRTIO_SCSI_T_ASYNC_NOTIFY: + ERROR("async notify\n"); + break; + case VIRTIO_SCSI_T_PARAM_CHANGE: + { + uint16 sense = (event->reason >> 8) + | ((event->reason & 0xff) << 8); + if (sense == SCSIS_ASC_CAPACITY_DATA_HAS_CHANGED) { + ERROR("capacity data has changed for %x:%x\n", event->lun[1], + event->lun[2] << 8 | event->lun[3]); + gSCSI->schedule_dpc(fBus, fEventDPC, _RescanChildBus, this); + } else + ERROR("param change, unknown reason\n"); + break; + } + default: + ERROR("unknown event %#x\n", event->event); + break; + } +} + + +void +VirtioSCSIController::_SubmitEvent(uint32 eventNumber) +{ + CALLED(); + struct virtio_scsi_event* event = &fEventBuffers[eventNumber]; + bzero(event, sizeof(struct virtio_scsi_event)); + + physical_entry entry; + get_memory_map(event, sizeof(struct virtio_scsi_event), &entry, 1); + + fVirtio->queue_request_v(fEventVirtioQueue, &entry, + 0, 1, VirtioSCSIController::_EventCallback, event); +} + + +void +VirtioSCSIController::_RescanChildBus(void *cookie) +{ + CALLED(); + VirtioSCSIController* controller = (VirtioSCSIController*)cookie; + device_node *childNode = NULL; + const device_attr attrs[] = { { NULL } }; + if (gDeviceManager->get_next_child_node(controller->fNode, attrs, + &childNode) != B_OK) { + ERROR("couldn't find the child node for %p\n", controller->fNode); + return; + } + + gDeviceManager->rescan_node(childNode); + TRACE("rescan done %p\n", childNode); + gDeviceManager->put_node(childNode); +} + diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h index 8e48c01..ca810de 100644 --- a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h +++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h @@ -35,6 +35,8 @@ void swap_words(void *data, size_t size); #define VIRTIO_SCSI_STANDARD_TIMEOUT 10 * 1000 * 1000 #define VIRTIO_SCSI_INITIATOR_ID 7 +#define VIRTIO_SCSI_NUM_EVENTS 4 + class VirtioSCSIRequest; @@ -63,6 +65,11 @@ private: static void _RequestCallback(void* driverCookie, void *cookie); void _RequestInterrupt(); + static void _EventCallback(void *driverCookie, void *cookie); + void _EventInterrupt(struct virtio_scsi_event* event); + static void _RescanChildBus(void *cookie); + + void _SubmitEvent(uint32 event); device_node* fNode; scsi_bus fBus; @@ -87,6 +94,8 @@ private: ConditionVariableEntry fInterruptConditionEntry; bool fExpectsInterrupt; + scsi_dpc_cookie fEventDPC; + struct virtio_scsi_event fEventBuffers[VIRTIO_SCSI_NUM_EVENTS]; };