[haiku-commits] haiku: hrev45816 - src/add-ons/kernel/busses/scsi/virtio

  • From: korli@xxxxxxxxxxxxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Tue, 2 Jul 2013 22:46:06 +0200 (CEST)

hrev45816 adds 3 changesets to branch 'master'
old head: f0c63f83d2cfb8bbf5f7ad1079bd8aa6c3c6ec49
new head: e19769d2967f21c79ea8485e3b245d65fe1b1f1a
overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=e19769d+%5Ef0c63f8

----------------------------------------------------------------------------

46bfab0: virtio: free fDescriptors on VirtioQueue destruction.

82fda49: Virtio: added a driver with basic support for SCSI devices.
  
  * Here is the Qemu command line option for Virtio SCSI devices:
  -drive if=none,id=hd,file=haiku.image -device virtio-scsi-pci,id=scsi -device 
scsi-hd,drive=hd
  * virtio_scsi.h is copied unchanged from FreeBSD, except for the _PACKED 
directive.

e19769d: virtio_block: replaced __packed with _PACKED

                                   [ Jérôme Duval <jerome.duval@xxxxxxxxx> ]

----------------------------------------------------------------------------

10 files changed, 1224 insertions(+), 1 deletion(-)
.../kernel/bus_managers/virtio/VirtioQueue.cpp   |   1 +
src/add-ons/kernel/busses/scsi/Jamfile           |   1 +
src/add-ons/kernel/busses/scsi/virtio/Jamfile    |  11 +
.../busses/scsi/virtio/VirtioSCSIController.cpp  | 264 +++++++++++++++
.../busses/scsi/virtio/VirtioSCSIHelper.cpp      |  79 +++++
.../busses/scsi/virtio/VirtioSCSIPrivate.h       | 148 ++++++++
.../busses/scsi/virtio/VirtioSCSIRequest.cpp     | 228 +++++++++++++
.../kernel/busses/scsi/virtio/virtio_scsi.cpp    | 339 +++++++++++++++++++
.../kernel/busses/scsi/virtio/virtio_scsi.h      | 152 +++++++++
.../disk/virtual/virtio_block/virtio_blk.h       |   2 +-

############################################################################

Commit:      46bfab031f9094fef5c0f187b28ba243e2ebd2ec
URL:         http://cgit.haiku-os.org/haiku/commit/?id=46bfab0
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Tue Jul  2 20:30:18 2013 UTC

virtio: free fDescriptors on VirtioQueue destruction.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp 
b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp
index 6cff71d..5133348 100644
--- a/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp
+++ b/src/add-ons/kernel/bus_managers/virtio/VirtioQueue.cpp
@@ -134,6 +134,7 @@ VirtioQueue::VirtioQueue(VirtioDevice* device, uint16 
queueNumber,
 VirtioQueue::~VirtioQueue()
 {
        delete_area(fArea);
+       delete[] fDescriptors;
 }
 
 

############################################################################

Commit:      82fda49e52a6d4fe217de033c350fee60ce56bff
URL:         http://cgit.haiku-os.org/haiku/commit/?id=82fda49
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Tue Jul  2 20:33:30 2013 UTC

Virtio: added a driver with basic support for SCSI devices.

* Here is the Qemu command line option for Virtio SCSI devices:
-drive if=none,id=hd,file=haiku.image -device virtio-scsi-pci,id=scsi -device 
scsi-hd,drive=hd
* virtio_scsi.h is copied unchanged from FreeBSD, except for the _PACKED 
directive.

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/busses/scsi/Jamfile 
b/src/add-ons/kernel/busses/scsi/Jamfile
index 8d80bbc..3b1f30f 100644
--- a/src/add-ons/kernel/busses/scsi/Jamfile
+++ b/src/add-ons/kernel/busses/scsi/Jamfile
@@ -4,3 +4,4 @@ SubInclude HAIKU_TOP src add-ons kernel busses scsi ahci ;
 SubInclude HAIKU_TOP src add-ons kernel busses scsi 53c8xx ;
 SubInclude HAIKU_TOP src add-ons kernel busses scsi buslogic ;
 SubInclude HAIKU_TOP src add-ons kernel busses scsi usb ;
+SubInclude HAIKU_TOP src add-ons kernel busses scsi virtio ;
diff --git a/src/add-ons/kernel/busses/scsi/virtio/Jamfile 
b/src/add-ons/kernel/busses/scsi/virtio/Jamfile
new file mode 100644
index 0000000..eba2d24
--- /dev/null
+++ b/src/add-ons/kernel/busses/scsi/virtio/Jamfile
@@ -0,0 +1,11 @@
+SubDir HAIKU_TOP src add-ons kernel busses scsi virtio ;
+
+UsePrivateHeaders drivers virtio ;
+UsePrivateKernelHeaders ;
+
+KernelAddon virtio_scsi :
+       virtio_scsi.cpp
+       VirtioSCSIController.cpp
+       VirtioSCSIHelper.cpp
+       VirtioSCSIRequest.cpp
+;
diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp 
b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp
new file mode 100644
index 0000000..dcde6c8
--- /dev/null
+++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIController.cpp
@@ -0,0 +1,264 @@
+/*
+ * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "VirtioSCSIPrivate.h"
+
+#include <new>
+#include <stdlib.h>
+#include <string.h>
+
+#include <util/AutoLock.h>
+
+
+const char *
+get_feature_name(uint32 feature)
+{
+       switch (feature) {
+               case VIRTIO_SCSI_F_INOUT:
+                       return "in out";
+               case VIRTIO_SCSI_F_HOTPLUG:
+                       return "hotplug";
+       }
+       return NULL;
+}
+
+
+VirtioSCSIController::VirtioSCSIController(device_node *node)
+       :
+       fNode(node),
+       fVirtio(NULL),
+       fVirtioDevice(NULL),
+       fStatus(B_NO_INIT),
+       fRequest(NULL)
+{
+       CALLED();
+
+       B_INITIALIZE_SPINLOCK(&fInterruptLock);
+       fInterruptCondition.Init(this, "virtio scsi transfer");
+       
+       // get the Virtio device from our parent's parent
+       device_node *parent = gDeviceManager->get_parent_node(node);
+       device_node *virtioParent = gDeviceManager->get_parent_node(parent);
+       gDeviceManager->put_node(parent);
+
+       gDeviceManager->get_driver(virtioParent, (driver_module_info 
**)&fVirtio,
+               (void **)&fVirtioDevice);
+       gDeviceManager->put_node(virtioParent);
+
+       fVirtio->negociate_features(fVirtioDevice,
+               0 /*VIRTIO_SCSI_F_HOTPLUG*/,
+               &fFeatures, &get_feature_name);
+
+       fStatus = fVirtio->read_device_config(fVirtioDevice, 0, &fConfig,
+               sizeof(struct virtio_scsi_config));
+       if (fStatus != B_OK)
+               return;
+
+       fConfig.sense_size = VIRTIO_SCSI_SENSE_SIZE;
+       fConfig.cdb_size = VIRTIO_SCSI_CDB_SIZE;
+
+       fVirtio->write_device_config(fVirtioDevice,
+               offsetof(struct virtio_scsi_config, sense_size), 
&fConfig.sense_size,
+               sizeof(fConfig.sense_size));
+       fVirtio->write_device_config(fVirtioDevice,
+               offsetof(struct virtio_scsi_config, cdb_size), 
&fConfig.sense_size,
+               sizeof(fConfig.cdb_size));
+
+       fRequest = new(std::nothrow) VirtioSCSIRequest(true);
+       if (fRequest == NULL) {
+               fStatus = B_NO_MEMORY;
+               return;
+       }
+
+       ::virtio_queue virtioQueues[3];
+       fStatus = fVirtio->alloc_queues(fVirtioDevice, 3, virtioQueues);
+       if (fStatus != B_OK) {
+               ERROR("queue allocation failed (%s)\n", strerror(fStatus));
+               return;
+       }
+
+       fControlVirtioQueue = virtioQueues[0];
+       fEventVirtioQueue = virtioQueues[1];
+       fRequestVirtioQueue = virtioQueues[2];
+       
+       fStatus = fVirtio->setup_interrupt(fVirtioDevice, NULL, NULL);
+       if (fStatus != B_OK) {
+               ERROR("interrupt setup failed (%s)\n", strerror(fStatus));
+               return;
+       }
+
+       
+}
+
+
+VirtioSCSIController::~VirtioSCSIController()
+{
+       CALLED();
+       delete fRequest;
+}
+
+
+status_t
+VirtioSCSIController::InitCheck()
+{
+       return fStatus;
+}
+
+
+void
+VirtioSCSIController::SetBus(scsi_bus bus)
+{
+       fBus = bus;
+}
+
+
+void
+VirtioSCSIController::PathInquiry(scsi_path_inquiry *info)
+{
+       info->hba_inquiry = SCSI_PI_TAG_ABLE;
+       info->hba_misc = 0;
+       info->sim_priv = 0;
+       info->initiator_id = VIRTIO_SCSI_INITIATOR_ID;
+       info->hba_queue_size = fConfig.cmd_per_lun != 0 ? fConfig.cmd_per_lun : 
1;
+       memset(info->vuhba_flags, 0, sizeof(info->vuhba_flags));
+
+       strlcpy(info->sim_vid, "Haiku", SCSI_SIM_ID);
+       strlcpy(info->hba_vid, "VirtIO", SCSI_HBA_ID);
+
+       strlcpy(info->sim_version, "1.0", SCSI_VERS);
+       strlcpy(info->hba_version, "1.0", SCSI_VERS);
+       strlcpy(info->controller_family, "Virtio", SCSI_FAM_ID);
+       strlcpy(info->controller_type, "Virtio", SCSI_TYPE_ID);
+}
+
+
+void
+VirtioSCSIController::GetRestrictions(uint8 targetID, bool *isATAPI,
+       bool *noAutoSense, uint32 *maxBlocks)
+{
+       *isATAPI = false;
+       *noAutoSense = true;    
+       *maxBlocks = fConfig.cmd_per_lun;
+}
+
+
+uchar
+VirtioSCSIController::ResetDevice(uchar targetID, uchar targetLUN)
+{
+       return SCSI_REQ_CMP;
+}
+
+
+status_t
+VirtioSCSIController::ExecuteRequest(scsi_ccb *ccb)
+{
+       status_t result = fRequest->Start(ccb);
+       if (result != B_OK)
+               return result;
+
+       if (ccb->cdb[0] == SCSI_OP_REQUEST_SENSE && fRequest->HasSense()) {
+               TRACE("request sense\n");
+               fRequest->RequestSense();
+               fRequest->Finish(false);
+               return B_OK;
+       }
+
+       if (ccb->target_id > fConfig.max_target) {
+               ERROR("invalid target device\n");
+               fRequest->SetStatus(SCSI_TID_INVALID);
+               fRequest->Finish(false);
+               return B_BAD_INDEX;
+       }
+
+       if (ccb->target_lun > fConfig.max_lun) {
+               ERROR("invalid lun device\n");
+               fRequest->SetStatus(SCSI_LUN_INVALID);
+               fRequest->Finish(false);
+               return B_BAD_INDEX;
+       }
+
+       if (ccb->cdb_length > VIRTIO_SCSI_CDB_SIZE) {
+               fRequest->SetStatus(SCSI_REQ_INVALID);
+               fRequest->Finish(false);
+               return B_BAD_VALUE;
+       }
+
+       bool isOut = (ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT;
+       bool isIn = (ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_IN;
+
+       // TODO check feature inout if request is bidirectional
+
+       fRequest->SetTimeout(ccb->timeout > 0 ? ccb->timeout * 1000 * 1000
+               : VIRTIO_SCSI_STANDARD_TIMEOUT);
+
+       uint32 inCount = (isIn ? ccb->sg_count : 0) + 1;
+       uint32 outCount = (isOut ? ccb->sg_count : 0) + 1;
+       physical_entry entries[inCount + outCount];
+       fRequest->FillRequest(inCount, outCount, entries);
+
+       {
+               InterruptsSpinLocker locker(fInterruptLock);
+               fExpectsInterrupt = true;
+               fInterruptCondition.Add(&fInterruptConditionEntry);
+       }
+
+       fVirtio->queue_request_v(fRequestVirtioQueue, entries,
+               outCount, inCount, VirtioSCSIController::RequestCallback, this);
+
+       result = fInterruptConditionEntry.Wait(B_RELATIVE_TIMEOUT,
+               fRequest->Timeout());
+       
+       {
+               InterruptsSpinLocker locker(fInterruptLock);
+               fExpectsInterrupt = false;
+       }
+
+       if (result != B_OK)
+               return result;
+
+       return fRequest->Finish(false);
+}
+
+
+uchar
+VirtioSCSIController::AbortRequest(scsi_ccb *request)                  
+{
+       return SCSI_REQ_CMP;
+}
+
+
+uchar
+VirtioSCSIController::TerminateRequest(scsi_ccb *request)
+{
+       return SCSI_REQ_CMP;
+}
+
+
+status_t
+VirtioSCSIController::Control(uint8 targetID, uint32 op, void *buffer,
+       size_t length)
+{
+       CALLED();       
+       return B_DEV_INVALID_IOCTL;
+}
+
+
+void
+VirtioSCSIController::RequestCallback(void* cookie)
+{
+       CALLED();
+       VirtioSCSIController* controller = (VirtioSCSIController*)cookie;
+       controller->_Interrupt();
+}
+
+
+void
+VirtioSCSIController::_Interrupt()
+{
+       SpinLocker locker(fInterruptLock);
+       fInterruptCondition.NotifyAll();
+}
+
diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIHelper.cpp 
b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIHelper.cpp
new file mode 100644
index 0000000..a5ece2a
--- /dev/null
+++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIHelper.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2009, Michael Lotz, mmlr@xxxxxxxx.
+ * Copyright 2004-2007, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx.
+ * Copyright 2002/03, Thomas Kurschel. All rights reserved.
+ *
+ * Distributed under the terms of the MIT License.
+ */
+
+#include "VirtioSCSIPrivate.h"
+
+#include <string.h>
+
+#include <vm/vm.h>
+
+
+/*!    Copy data between ccb data and buffer
+       ccb                     - ccb to copy data from/to
+       offset                  - offset of data in ccb
+       allocation_length- limit of ccb's data buffer according to CDB
+       buffer                  - data to copy data from/to
+       size                    - number of bytes to copy
+       to_buffer               - true: copy from ccb to buffer
+                                         false: copy from buffer to ccb
+       return: true, if data of ccb was large enough
+*/
+bool
+copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength,
+       void *buffer, int size, bool toBuffer)
+{
+       const physical_entry *sgList = ccb->sg_list;
+       int sgCount = ccb->sg_count;
+
+       // skip unused S/G entries
+       while (sgCount > 0 && offset >= sgList->size) {
+               offset -= sgList->size;
+               ++sgList;
+               --sgCount;
+       }
+
+       if (sgCount == 0)
+               return false;
+
+       // remaining bytes we are allowed to copy from/to ccb
+       int requestSize = MIN(allocationLength, ccb->data_length) - offset;
+
+       // copy one S/G entry at a time
+       for (; size > 0 && requestSize > 0 && sgCount > 0; ++sgList, --sgCount) 
{
+               size_t bytes;
+
+               bytes = MIN(size, requestSize);
+               bytes = MIN(bytes, sgList->size);
+
+               if (toBuffer) {
+                       vm_memcpy_from_physical(buffer, sgList->address + 
offset, bytes,
+                               false);
+               } else {
+                       vm_memcpy_to_physical(sgList->address + offset, buffer, 
bytes,
+                               false);
+               }
+
+               buffer = (char *)buffer + bytes;
+               size -= bytes;
+               offset = 0;
+       }
+
+       return size == 0;
+}
+
+
+void
+swap_words(void *data, size_t size)
+{
+       uint16 *word = (uint16 *)data;
+       size_t count = size / 2;
+       while (count--) {
+               *word = B_BENDIAN_TO_HOST_INT16(*word);
+               word++;
+       }
+}
diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h 
b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h
new file mode 100644
index 0000000..0dddad1
--- /dev/null
+++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIPrivate.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef VIRTIO_SCSI_PRIVATE_H
+#define VIRTIO_SCSI_PRIVATE_H
+
+
+#include <bus/SCSI.h>
+#include <condition_variable.h>
+#include <lock.h>
+#include <scsi_cmds.h>
+#include <virtio.h>
+
+#include "virtio_scsi.h"
+
+
+//#define TRACE_VIRTIO_SCSI
+#ifdef TRACE_VIRTIO_SCSI
+#      define TRACE(x...) dprintf("virtio_scsi: " x)
+#else
+#      define TRACE(x...) ;
+#endif
+#define ERROR(x...)                    dprintf("\33[33mvirtio_scsi:\33[0m " x)
+#define CALLED()                       TRACE("CALLED %s\n", 
__PRETTY_FUNCTION__)
+
+extern device_manager_info* gDeviceManager;
+extern scsi_for_sim_interface *gSCSI;
+
+bool copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength,
+       void *buffer, int size, bool toBuffer);
+void swap_words(void *data, size_t size);
+
+
+#define VIRTIO_SCSI_STANDARD_TIMEOUT           10 * 1000 * 1000
+#define VIRTIO_SCSI_INITIATOR_ID       7
+
+
+class VirtioSCSIRequest;
+
+
+class VirtioSCSIController {
+public:
+                                                               
VirtioSCSIController(device_node* node);
+                                                               
~VirtioSCSIController();
+
+                       status_t                        InitCheck();
+
+                       void                            SetBus(scsi_bus bus);
+                       scsi_bus                        Bus() const { return 
fBus; }
+
+                       void                            
PathInquiry(scsi_path_inquiry* info);
+                       void                            GetRestrictions(uint8 
targetID, bool* isATAPI,
+                                                                       bool* 
noAutoSense, uint32* maxBlocks);
+                       uchar                           ResetDevice(uchar 
targetID, uchar targetLUN);
+                       status_t                        
ExecuteRequest(scsi_ccb* request);
+                       uchar                           AbortRequest(scsi_ccb* 
request);
+                       uchar                           
TerminateRequest(scsi_ccb* request);
+                       status_t                        Control(uint8 targetID, 
uint32 op,
+                                                                       void* 
buffer, size_t length);
+                       
+private:
+       static  void                            RequestCallback(void *cookie);
+                       void                            _Interrupt();
+
+                       device_node*            fNode;
+                       scsi_bus                        fBus;
+
+                       virtio_device_interface* fVirtio;
+                       virtio_device*          fVirtioDevice;
+
+                       status_t                        fStatus;
+                       struct virtio_scsi_config       fConfig;
+                       uint32                          fFeatures;
+                       ::virtio_queue          fControlVirtioQueue;
+                       ::virtio_queue          fEventVirtioQueue;
+                       ::virtio_queue          fRequestVirtioQueue;
+
+                       area_id                         fArea;
+                       struct virtio_scsi_event*       fEvents;
+
+                       VirtioSCSIRequest*      fRequest;
+
+                       spinlock                        fInterruptLock;
+                       ConditionVariable       fInterruptCondition;
+                       ConditionVariableEntry fInterruptConditionEntry;
+                       bool                            fExpectsInterrupt;
+
+};
+
+
+class VirtioSCSIRequest {
+public:
+                                                               
VirtioSCSIRequest(bool hasLock);
+                                                               
~VirtioSCSIRequest();
+
+                       void                            SetStatus(uint8 status);
+                       uint8                           Status() const { return 
fStatus; }
+
+                       void                            SetTimeout(bigtime_t 
timeout);
+                       bigtime_t                       Timeout() const { 
return fTimeout; }
+
+                       bool                            HasSense() {
+                                                                       return 
(fResponse->sense_len > 0); }
+
+                       void                            SetIsWrite(bool 
isWrite);
+                       bool                            IsWrite() const { 
return fIsWrite; }
+
+                       void                            SetBytesLeft(uint32 
bytesLeft);
+                       size_t*                         BytesLeft() { return 
&fBytesLeft; }
+
+                       bool                            HasData() const
+                                                                       { 
return fCCB->data_length > 0; }
+
+                       status_t                        Finish(bool resubmit);
+
+                       // SCSI stuff
+                       status_t                        Start(scsi_ccb *ccb);
+                       scsi_ccb*                       CCB() { return fCCB; }
+
+                       void                            RequestSense();
+
+                       void                            FillRequest(uint32 
inCount, uint32 outCount,
+                                                                       
physical_entry *entries);
+
+private:
+                       void                            _FillSense(scsi_sense 
*sense);
+                       uchar                           _ResponseStatus();
+
+                       mutex                           fLock;
+                       bool                            fHasLock;
+
+                       uint8                           fStatus;
+                       
+                       bigtime_t                       fTimeout;
+                       size_t                          fBytesLeft;
+                       bool                            fIsWrite;
+                       scsi_ccb*                       fCCB;
+
+                       // virtio scsi
+                       void*                           fBuffer;
+                       struct virtio_scsi_cmd_req *fRequest;
+                       struct virtio_scsi_cmd_resp *fResponse;
+};
+
+
+#endif // VIRTIO_SCSI_PRIVATE_H
+
diff --git a/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIRequest.cpp 
b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIRequest.cpp
new file mode 100644
index 0000000..ab93b17
--- /dev/null
+++ b/src/add-ons/kernel/busses/scsi/virtio/VirtioSCSIRequest.cpp
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Copyright 2009, Michael Lotz, mmlr@xxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "VirtioSCSIPrivate.h"
+
+#include <string.h>
+
+
+VirtioSCSIRequest::VirtioSCSIRequest(bool hasLock)
+       :
+       fHasLock(hasLock),
+       fTimeout(0),
+       fBytesLeft(0),
+       fIsWrite(false),
+       fCCB(NULL)
+{
+       if (hasLock)
+               mutex_init(&fLock, "virtio scsi request");
+
+       fBuffer = malloc(sizeof(struct virtio_scsi_cmd_req)
+               + sizeof(struct virtio_scsi_cmd_resp));
+       bzero(fBuffer, sizeof(struct virtio_scsi_cmd_req)
+               + sizeof(struct virtio_scsi_cmd_resp));
+
+       fRequest = (struct virtio_scsi_cmd_req *)fBuffer;
+       fResponse = (struct virtio_scsi_cmd_resp *)
+               ((addr_t)fBuffer + sizeof(struct virtio_scsi_cmd_req));
+
+       fResponse->sense_len = 0;
+}
+
+
+VirtioSCSIRequest::~VirtioSCSIRequest()
+{
+       if (fHasLock)
+               mutex_destroy(&fLock);
+
+       free(fBuffer);
+}
+
+
+void
+VirtioSCSIRequest::SetStatus(uint8 status)
+{
+       fStatus = status;
+}
+
+
+void
+VirtioSCSIRequest::SetTimeout(bigtime_t timeout)
+{
+       fTimeout = timeout;
+}
+
+
+void
+VirtioSCSIRequest::SetIsWrite(bool isWrite)
+{
+       fIsWrite = isWrite;
+}
+
+
+void
+VirtioSCSIRequest::SetBytesLeft(uint32 bytesLeft)
+{
+       fBytesLeft = bytesLeft;
+}
+
+
+status_t
+VirtioSCSIRequest::Start(scsi_ccb *ccb)
+{
+       CALLED();
+       if (mutex_trylock(&fLock) != B_OK)
+               return B_BUSY;
+
+       fCCB = ccb;
+       fStatus = SCSI_REQ_CMP;
+       fCCB->device_status = SCSI_STATUS_GOOD;
+       fIsWrite = false;
+       bzero(fResponse, sizeof(struct virtio_scsi_cmd_resp));
+
+       TRACE("VirtioSCSIRequest::Start() opcode %x tid %x lun %x\n", 
ccb->cdb[0],
+               ccb->target_id, ccb->target_lun);
+
+       return B_OK;
+}
+
+
+status_t
+VirtioSCSIRequest::Finish(bool resubmit)
+{
+       CALLED();
+       fStatus = _ResponseStatus();
+       fCCB->data_resid = fResponse->resid;
+       fCCB->subsys_status = fStatus;
+
+       TRACE("VirtioSCSIRequest::Finish() status 0x%x response 0x%x resid:0x%x"
+               " sense_len:%x\n", fResponse->status, fResponse->response,
+               fResponse->resid, fResponse->sense_len);
+
+       if (fCCB->cdb[0] == SCSI_OP_INQUIRY) {
+               // when the request is an inquiry, don't do anything
+       } else if (fStatus == SCSI_REQ_CMP && fResponse->status != 0
+               && HasSense()) {
+               // when the request completed and has set sense
+       // data, report this to the scsi stack by setting
+       // CHECK CONDITION status
+               TRACE("setting check condition\n");
+
+               fCCB->subsys_status = SCSI_REQ_CMP_ERR;
+               fCCB->device_status = SCSI_STATUS_CHECK_CONDITION;
+
+               // copy sense data if caller requested it
+               if ((fCCB->flags & SCSI_DIS_AUTOSENSE) == 0) {
+                       size_t senseLength = min_c(sizeof(fCCB->sense),
+                               fResponse->sense_len);
+                       memcpy(fCCB->sense, fResponse->sense, senseLength);
+                       fCCB->sense_resid = sizeof(fCCB->sense) - senseLength;
+                       fCCB->subsys_status |= SCSI_AUTOSNS_VALID;
+               }
+       }
+
+       mutex_unlock(&fLock);
+
+       if (resubmit)
+               gSCSI->resubmit(fCCB);
+       else
+               gSCSI->finished(fCCB, 1);
+
+       TRACE("VirtioSCSIRequest::Finish() done\n");
+
+       return B_OK;
+}
+
+
+void
+VirtioSCSIRequest::RequestSense()
+{
+       CALLED();
+       // Copy sense data from last request into data buffer of current 
request.
+       // The sense data of last request is still present in the current 
request,
+       // as it isn't cleared on SCSI_OP_REQUEST_SENSE.
+       scsi_cmd_request_sense *command = (scsi_cmd_request_sense *)fCCB->cdb;
+       copy_sg_data(fCCB, 0, command->allocation_length, fResponse->sense,
+               fResponse->sense_len, false);
+
+       fCCB->data_resid = fCCB->data_length - min_c(min_c(fResponse->sense_len,
+               command->allocation_length), fCCB->data_length);
+       fResponse->sense_len = 0;
+}
+
+
+void
+VirtioSCSIRequest::FillRequest(uint32 inCount, uint32 outCount,
+       physical_entry *entries)
+{
+       CALLED();
+       fRequest->task_attr = VIRTIO_SCSI_S_SIMPLE;
+       fRequest->tag = (addr_t)fCCB;
+       fRequest->lun[0] = 1;
+       fRequest->lun[1] = fCCB->target_id;
+       fRequest->lun[2] = 0x40 | ((fCCB->target_lun >> 8) & 0x3f);
+       fRequest->lun[3] = (fCCB->target_lun >> 8) & 0xff;
+
+       memcpy(fRequest->cdb, fCCB->cdb, min_c(fCCB->cdb_length,
+               sizeof(fRequest->cdb)));
+
+       get_memory_map(fBuffer, sizeof(struct virtio_scsi_cmd_req)
+               + sizeof(struct virtio_scsi_cmd_resp), &entries[0], 1);
+       entries[0].size = sizeof(struct virtio_scsi_cmd_req);
+       if (outCount > 1) {
+               memcpy(entries + 1, fCCB->sg_list, fCCB->sg_count
+                       * sizeof(physical_entry));
+       }
+
+       entries[outCount].address = entries[0].address
+               + sizeof(struct virtio_scsi_cmd_req);
+       entries[outCount].size = sizeof(struct virtio_scsi_cmd_resp);
+       
+       if (inCount > 1) {
+               memcpy(entries + outCount + 1, fCCB->sg_list, fCCB->sg_count
+                       * sizeof(physical_entry));
+       }
+}
+
+
+uchar
+VirtioSCSIRequest::_ResponseStatus()
+{
+       uchar status;
+
+       switch (fResponse->response) {
+               case VIRTIO_SCSI_S_OK:
+                       status = SCSI_REQ_CMP;
+                       break;
+               case VIRTIO_SCSI_S_OVERRUN:
+                       status = SCSI_DATA_RUN_ERR;
+                       break;
+               case VIRTIO_SCSI_S_ABORTED:
+                       status = SCSI_REQ_ABORTED;
+                       break;
+               case VIRTIO_SCSI_S_BAD_TARGET:
+                       status = SCSI_TID_INVALID;
+                       break;
+               case VIRTIO_SCSI_S_RESET:
+                       status = SCSI_SCSI_BUS_RESET;
+                       break;
+               case VIRTIO_SCSI_S_BUSY:
+                       status = SCSI_SCSI_BUSY;
+                       break;
+               case VIRTIO_SCSI_S_TRANSPORT_FAILURE:
+               case VIRTIO_SCSI_S_TARGET_FAILURE:
+               case VIRTIO_SCSI_S_NEXUS_FAILURE:
+                       status = SCSI_NO_NEXUS;
+                       break;
+               default: /* VIRTIO_SCSI_S_FAILURE */
+                       status = SCSI_REQ_CMP_ERR;
+                       break;
+       }
+
+       return status;
+}
+
diff --git a/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.cpp 
b/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.cpp
new file mode 100644
index 0000000..c1b6391
--- /dev/null
+++ b/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.cpp
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2013, Jérôme Duval, korli@xxxxxxxxxxxxxxxx.
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "VirtioSCSIPrivate.h"
+
+#include <new>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define VIRTIO_SCSI_ID_GENERATOR "virtio_scsi/id"
+#define VIRTIO_SCSI_ID_ITEM "virtio_scsi/id"
+#define VIRTIO_SCSI_BRIDGE_PRETTY_NAME "Virtio SCSI Bridge"
+#define VIRTIO_SCSI_CONTROLLER_PRETTY_NAME "Virtio SCSI Controller"
+
+#define VIRTIO_SCSI_DEVICE_MODULE_NAME "busses/scsi/virtio_scsi/driver_v1"
+#define VIRTIO_SCSI_SIM_MODULE_NAME "busses/scsi/virtio_scsi/sim/driver_v1"
+
+
+device_manager_info *gDeviceManager;
+scsi_for_sim_interface *gSCSI;
+
+
+//     #pragma mark - SIM module interface
+
+
+static void
+set_scsi_bus(scsi_sim_cookie cookie, scsi_bus bus)
+{
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       sim->SetBus(bus);
+}
+
+
+static void
+scsi_io(scsi_sim_cookie cookie, scsi_ccb *request)
+{
+       CALLED();
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       if (sim->ExecuteRequest(request) == B_BUSY)
+               gSCSI->requeue(request, true);
+}
+
+
+static uchar
+abort_io(scsi_sim_cookie cookie, scsi_ccb *request)
+{
+       CALLED();
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       return sim->AbortRequest(request);
+}
+
+
+static uchar
+reset_device(scsi_sim_cookie cookie, uchar targetID, uchar targetLUN)
+{
+       CALLED();
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       return sim->ResetDevice(targetID, targetLUN);
+}
+
+
+static uchar
+terminate_io(scsi_sim_cookie cookie, scsi_ccb *request)
+{
+       CALLED();
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       return sim->TerminateRequest(request);
+}
+
+
+static uchar
+path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info)
+{
+       CALLED();
+
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       if (sim->Bus() == NULL)
+               return SCSI_NO_HBA;
+
+       sim->PathInquiry(info);
+       return SCSI_REQ_CMP;
+}
+
+
+//! this is called immediately before the SCSI bus manager scans the bus
+static uchar
+scan_bus(scsi_sim_cookie cookie)
+{
+       CALLED();
+
+       return SCSI_REQ_CMP;
+}
+
+
+static uchar
+reset_bus(scsi_sim_cookie cookie)
+{
+       CALLED();
+
+       return SCSI_REQ_CMP;
+}
+
+
+/*!    Get restrictions of one device
+       (used for non-SCSI transport protocols and bug fixes)
+*/
+static void
+get_restrictions(scsi_sim_cookie cookie, uchar targetID, bool *isATAPI,
+       bool *noAutoSense, uint32 *maxBlocks)
+{
+       CALLED();
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       sim->GetRestrictions(targetID, isATAPI, noAutoSense, maxBlocks);
+}
+
+
+static status_t
+ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer,
+       size_t length)
+{
+       CALLED();
+       VirtioSCSIController *sim = (VirtioSCSIController *)cookie;
+       return sim->Control(targetID, op, buffer, length);
+}
+
+
+//     #pragma mark -
+
+
+static status_t
+sim_init_bus(device_node *node, void **_cookie)
+{
+       CALLED();
+
+       VirtioSCSIController *controller =  new(std::nothrow)
+               VirtioSCSIController(node);
+       if (controller == NULL)
+               return B_NO_MEMORY;
+       status_t status = controller->InitCheck();
+       if (status < B_OK) {
+               delete controller;
+               return status;
+       }
+
+       *_cookie = controller;
+       return B_OK;
+}
+
+
+static void
+sim_uninit_bus(void *cookie)
+{
+       CALLED();
+       VirtioSCSIController *controller = (VirtioSCSIController*)cookie;
+
+       delete controller;
+}
+
+
+//     #pragma mark -
+
+
+static float
+virtio_scsi_supports_device(device_node *parent)
+{
+       const char *bus;
+       uint16 deviceType;
+
+       // make sure parent is really the Virtio bus manager
+       if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
+               return -1;
+
+       if (strcmp(bus, "virtio"))
+               return 0.0;
+
+       // check whether it's really a Virtio SCSI Device
+       if (gDeviceManager->get_attr_uint16(parent, VIRTIO_DEVICE_TYPE_ITEM,
+                       &deviceType, true) != B_OK || deviceType != 
VIRTIO_DEVICE_ID_SCSI)
+               return 0.0;
+
+       TRACE("Virtio SCSI device found!\n");
+
+       return 0.6f;
+}
+
+
+static status_t
+virtio_scsi_register_device(device_node *parent)
+{
+       CALLED();
+       virtio_device_interface* virtio = NULL;
+       virtio_device* virtioDevice = NULL;
+       struct virtio_scsi_config config;
+
+       gDeviceManager->get_driver(parent, (driver_module_info **)&virtio,
+               (void **)&virtioDevice);
+       
+       status_t status = virtio->read_device_config(virtioDevice, 0, &config,
+               sizeof(struct virtio_scsi_config));
+       if (status != B_OK)
+               return status;
+
+       uint32 max_targets = config.max_target + 1;
+       uint32 max_blocks = 0x10000;
+       if (config.max_sectors != 0)
+               max_blocks = config.max_sectors;
+
+       device_attr attrs[] = {
+               { SCSI_DEVICE_MAX_TARGET_COUNT, B_UINT32_TYPE,
+                       { ui32: max_targets }},
+               { B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
+                       { string: VIRTIO_SCSI_BRIDGE_PRETTY_NAME }},
+
+               // DMA properties
+               { B_DMA_MAX_SEGMENT_BLOCKS, B_UINT32_TYPE, { ui32: max_blocks 
}},
+               { B_DMA_MAX_SEGMENT_COUNT, B_UINT32_TYPE,
+                       { ui32: config.seg_max }},
+               { NULL }
+       };
+       
+       return gDeviceManager->register_node(parent, 
VIRTIO_SCSI_DEVICE_MODULE_NAME,
+               attrs, NULL, NULL);
+}
+
+
+static status_t
+virtio_scsi_init_driver(device_node *node, void **_cookie)
+{
+       CALLED();
+       *_cookie = node;
+       return B_OK;
+}
+
+
+static status_t
+virtio_scsi_register_child_devices(void *cookie)
+{
+       CALLED();
+       device_node *node = (device_node *)cookie;
+
+       int32 id = gDeviceManager->create_id(VIRTIO_SCSI_ID_GENERATOR);
+       if (id < 0)
+               return id;
+
+       device_attr attrs[] = {
+               { B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
+                       { string: SCSI_FOR_SIM_MODULE_NAME }},
+               { B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
+                       { string: VIRTIO_SCSI_CONTROLLER_PRETTY_NAME }},
+               { SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE,
+                       { string: VIRTIO_SCSI_DEVICE_MODULE_NAME }},
+               { B_DMA_MAX_TRANSFER_BLOCKS, B_UINT32_TYPE, { ui32: 255 }},
+               { VIRTIO_SCSI_ID_ITEM, B_UINT32_TYPE, { ui32: (uint32)id }},
+                       { NULL }
+       };
+
+       status_t status = gDeviceManager->register_node(node,
+               VIRTIO_SCSI_SIM_MODULE_NAME, attrs, NULL, NULL);
+       if (status < B_OK)
+               gDeviceManager->free_id(VIRTIO_SCSI_ID_GENERATOR, id);
+
+       return status;
+}
+
+
+static status_t
+std_ops(int32 op, ...)
+{
+       switch (op) {
+               case B_MODULE_INIT:
+               case B_MODULE_UNINIT:
+                       return B_OK;
+
+               default:
+                       return B_ERROR;
+       }
+}
+
+
+static scsi_sim_interface sVirtioSCSISimInterface = {
+       {
+               {
+                       VIRTIO_SCSI_SIM_MODULE_NAME,
+                       0,
+                       std_ops
+               },
+               NULL,   // supported devices
+               NULL,   // register node
+               sim_init_bus,
+               sim_uninit_bus,
+               NULL,   // register child devices
+               NULL,   // rescan
+               NULL    // bus_removed
+       },
+       set_scsi_bus,
+       scsi_io,
+       abort_io,
+       reset_device,
+       terminate_io,
+       path_inquiry,
+       scan_bus,
+       reset_bus,
+       get_restrictions,
+       ioctl
+};
+
+
+static driver_module_info sVirtioSCSIDevice = {
+       {
+               VIRTIO_SCSI_DEVICE_MODULE_NAME,
+               0,
+               std_ops
+       },
+       virtio_scsi_supports_device,
+       virtio_scsi_register_device,
+       virtio_scsi_init_driver,
+       NULL,   // uninit_driver,
+       virtio_scsi_register_child_devices,
+       NULL,   // rescan
+       NULL,   // device_removed
+};
+
+
+module_dependency module_dependencies[] = {
+       { B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
+       { SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSI },
+       {}
+};
+
+
+module_info *modules[] = {
+       (module_info *)&sVirtioSCSIDevice,
+       (module_info *)&sVirtioSCSISimInterface,
+       NULL
+};
diff --git a/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.h 
b/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.h
new file mode 100644
index 0000000..b781839
--- /dev/null
+++ b/src/add-ons/kernel/busses/scsi/virtio/virtio_scsi.h
@@ -0,0 +1,152 @@
+/*-
+ * This header is BSD licensed so anyone can use the definitions to implement
+ * compatible drivers/servers.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _VIRTIO_SCSI_H
+#define _VIRTIO_SCSI_H
+
+/* Feature bits */
+#define VIRTIO_SCSI_F_INOUT    0x0001  /* Single request can contain both
+                                        * read and write buffers */
+#define VIRTIO_SCSI_F_HOTPLUG  0x0002  /* Host should enable hot plug/unplug
+                                        * of new LUNs and targets.
+                                        */
+
+#define VIRTIO_SCSI_CDB_SIZE   32
+#define VIRTIO_SCSI_SENSE_SIZE 96
+
+/* SCSI command request, followed by data-out */
+struct virtio_scsi_cmd_req {
+       uint8_t lun[8];         /* Logical Unit Number */
+       uint64_t tag;           /* Command identifier */
+       uint8_t task_attr;      /* Task attribute */
+       uint8_t prio;
+       uint8_t crn;
+       uint8_t cdb[VIRTIO_SCSI_CDB_SIZE];
+} _PACKED;
+
+/* Response, followed by sense data and data-in */
+struct virtio_scsi_cmd_resp {
+       uint32_t sense_len;             /* Sense data length */
+       uint32_t resid;                 /* Residual bytes in data buffer */
+       uint16_t status_qualifier;      /* Status qualifier */
+       uint8_t status;                 /* Command completion status */
+       uint8_t response;               /* Response values */
+       uint8_t sense[VIRTIO_SCSI_SENSE_SIZE];
+} _PACKED;
+
+/* Task Management Request */
+struct virtio_scsi_ctrl_tmf_req {
+       uint32_t type;
+       uint32_t subtype;
+       uint8_t lun[8];
+       uint64_t tag;
+} _PACKED;
+
+struct virtio_scsi_ctrl_tmf_resp {
+       uint8_t response;
+} _PACKED;
+
+/* Asynchronous notification query/subscription */
+struct virtio_scsi_ctrl_an_req {
+       uint32_t type;
+       uint8_t lun[8];
+       uint32_t event_requested;
+} _PACKED;
+
+struct virtio_scsi_ctrl_an_resp {
+       uint32_t event_actual;
+       uint8_t response;
+} _PACKED;
+
+struct virtio_scsi_event {
+       uint32_t event;
+       uint8_t lun[8];
+       uint32_t reason;
+} _PACKED;
+
+struct virtio_scsi_config {
+       uint32_t num_queues;
+       uint32_t seg_max;
+       uint32_t max_sectors;
+       uint32_t cmd_per_lun;
+       uint32_t event_info_size;
+       uint32_t sense_size;
+       uint32_t cdb_size;
+       uint16_t max_channel;
+       uint16_t max_target;
+       uint32_t max_lun;
+} _PACKED;
+
+/* Response codes */
+#define VIRTIO_SCSI_S_OK                       0
+#define VIRTIO_SCSI_S_FUNCTION_COMPLETE        0
+#define VIRTIO_SCSI_S_OVERRUN                  1
+#define VIRTIO_SCSI_S_ABORTED                  2
+#define VIRTIO_SCSI_S_BAD_TARGET               3
+#define VIRTIO_SCSI_S_RESET                    4
+#define VIRTIO_SCSI_S_BUSY                     5
+#define VIRTIO_SCSI_S_TRANSPORT_FAILURE        6
+#define VIRTIO_SCSI_S_TARGET_FAILURE           7
+#define VIRTIO_SCSI_S_NEXUS_FAILURE            8
+#define VIRTIO_SCSI_S_FAILURE                  9
+#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED       10
+#define VIRTIO_SCSI_S_FUNCTION_REJECTED        11
+#define VIRTIO_SCSI_S_INCORRECT_LUN            12
+
+/* Controlq type codes.  */
+#define VIRTIO_SCSI_T_TMF                      0
+#define VIRTIO_SCSI_T_AN_QUERY                 1
+#define VIRTIO_SCSI_T_AN_SUBSCRIBE             2
+
+/* Valid TMF subtypes.  */
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK           0
+#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET       1
+#define VIRTIO_SCSI_T_TMF_CLEAR_ACA            2
+#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET       3
+#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET      4
+#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET   5
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK           6
+#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET       7
+
+/* Events.  */
+#define VIRTIO_SCSI_T_EVENTS_MISSED            0x80000000
+#define VIRTIO_SCSI_T_NO_EVENT                 0
+#define VIRTIO_SCSI_T_TRANSPORT_RESET          1
+#define VIRTIO_SCSI_T_ASYNC_NOTIFY             2
+
+/* Reasons of transport reset event */
+#define VIRTIO_SCSI_EVT_RESET_HARD             0
+#define VIRTIO_SCSI_EVT_RESET_RESCAN           1
+#define VIRTIO_SCSI_EVT_RESET_REMOVED          2
+
+#define VIRTIO_SCSI_S_SIMPLE                   0
+#define VIRTIO_SCSI_S_ORDERED                  1
+#define VIRTIO_SCSI_S_HEAD                     2
+#define VIRTIO_SCSI_S_ACA                      3
+
+#endif /* _VIRTIO_SCSI_H */

############################################################################

Revision:    hrev45816
Commit:      e19769d2967f21c79ea8485e3b245d65fe1b1f1a
URL:         http://cgit.haiku-os.org/haiku/commit/?id=e19769d
Author:      Jérôme Duval <jerome.duval@xxxxxxxxx>
Date:        Tue Jul  2 20:41:04 2013 UTC

virtio_block: replaced __packed with _PACKED

----------------------------------------------------------------------------

diff --git a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_blk.h 
b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_blk.h
index fdac9e5..35acaea 100644
--- a/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_blk.h
+++ b/src/add-ons/kernel/drivers/disk/virtual/virtio_block/virtio_blk.h
@@ -60,7 +60,7 @@ struct virtio_blk_config {
 
        /* block size of device (if VIRTIO_BLK_F_BLK_SIZE) */
        uint32_t blk_size;
-} __packed;
+} _PACKED;
 
 /*
  * Command types


Other related posts:

  • » [haiku-commits] haiku: hrev45816 - src/add-ons/kernel/busses/scsi/virtio - korli