[haiku-commits] haiku: hrev45865 - src/add-ons/kernel/busses/scsi/virtio src/add-ons/kernel/bus_managers/virtio src/add-ons/kernel/bus_managers/scsi src/add-ons/kernel/drivers/disk/scsi/scsi_disk headers/private/virtio

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 17 Jul 2013 18:00:13 +0200 (CEST)

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];
 };
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev45865 - src/add-ons/kernel/busses/scsi/virtio src/add-ons/kernel/bus_managers/virtio src/add-ons/kernel/bus_managers/scsi src/add-ons/kernel/drivers/disk/scsi/scsi_disk headers/private/virtio - korli