VirtualBox

Changeset 79928 in vbox


Ignore:
Timestamp:
Jul 23, 2019 11:47:38 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132346
Message:

See #9440 Comment #36

Location:
trunk/src/VBox
Files:
2 added
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Makefile.kmk

    r79891 r79928  
    532532  VBoxDD_DEFS           += VBOX_WITH_VIRTIO_SCSI
    533533  VBoxDD_SOURCES        += \
     534    Virtio/Virtio_1_0.cpp \
    534535        Storage/DevVirtioSCSI.cpp
    535536 endif
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r79535 r79928  
    3939# include <iprt/uuid.h>
    4040#endif
     41#include "../VirtIO/Virtio_1_0.h"
     42
    4143#include "VBoxSCSI.h"
    4244#include "VBoxDD.h"
     
    5355typedef struct VIRTIOSCSITARGET
    5456{
     57
     58
    5559    /** Pointer to the owning virtioScsi device instance. - R3 pointer */
    5660    R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiR3;
    57 
     61    /** Pointer to the owning virtioScsi device instance. - R0 pointer */
     62    R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiR0;
    5863    /** Pointer to the owning virtioScsi device instance. - RC pointer */
    59     RCPTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiRC;
    60 
    61     /** Pointer to the attached driver's base interface. */
    62     R3PTRTYPE(PPDMIBASE)          pDrvBase;
     64    R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiRC;
     65
     66    /** Pointer to attached driver's base interface. */
     67    R3PTRTYPE(PPDMIBASE)            pUpstreamDrvBase;
     68
     69    /** LUN of the device. */
     70    RTUINT                          iLUN;
    6371
    6472    /** Our base interface. */
    65     PDMIBASE                      IBase;
    66 
    67     /** LUN of the device. */
    68     RTUINT                        iLUN;
     73    PDMIBASE                        IBase;
    6974
    7075    /** Flag whether device is present. */
    71     bool                          fPresent;
     76    bool                            fPresent;
    7277
    7378    /** Media port interface. */
    74     PDMIMEDIAPORT                 IMediaPort;
     79    PDMIMEDIAPORT                   IMediaPort;
     80
    7581    /** Extended media port interface. */
    76     PDMIMEDIAEXPORT               IMediaExPort;
    77     /** Led interface. */
    78     PDMILEDPORTS                  ILed;
    79 
    80     /** The status LED state for this device. */
    81     PDMLED                        Led;
     82    PDMIMEDIAEXPORT                 IMediaExPort;
    8283
    8384    /** Number of outstanding tasks on the port. */
    84     volatile uint32_t             cOutstandingRequests;
    85 
    86 } VIRTIOSCSITARGET;
    87 typedef VIRTIOSCSITARGET *PVIRTIOSCSITARGET;
     85    volatile uint32_t               cOutstandingRequests;
     86
     87    /** LUN Description */
     88    char *                          pszLunName;
     89
     90    /** Pointer to the attached driver's media interface. */
     91    R3PTRTYPE(PPDMIMEDIA)           pDrvMedia;
     92
     93     /** Pointer to the attached driver's extended media interface. */
     94    R3PTRTYPE(PPDMIMEDIAEX)         pDrvMediaEx;
     95
     96    R3PTRTYPE(PVQUEUE)              pCtlQueue; // ? TBD
     97    R3PTRTYPE(PVQUEUE)              pEvtQueue; // ? TBD
     98    R3PTRTYPE(PVQUEUE)              pReqQueue; // ? TBD
     99
     100} VIRTIOSCSITARGET, *PVIRTIOSCSITARGET;
    88101
    89102
     
    92105 *
    93106 * @extends     PDMPCIDEV
    94  * @implements  PDMILEDPORTS
    95107 */
    96108typedef struct VIRTIOSCSI
    97109{
    98110
    99     VIRTIOSCSITARGET                  aTargetInstances[VIRTIOSCSI_MAX_TARGETS];
    100 
    101     /** The PCI device structure. */
    102     PDMPCIDEV                       dev;
    103     /** Pointer to the device instance - HC ptr */
    104     PPDMDEVINSR3                    pDevInsR3;
    105     /** Pointer to the device instance - R0 ptr */
    106     PPDMDEVINSR0                    pDevInsR0;
    107     /** Pointer to the device instance - RC ptr. */
    108     PPDMDEVINSRC                    pDevInsRC;
     111    PPDMDEVINSR3           pDevInsR3;              /**< Device instance - R3. */
     112    PPDMDEVINSR0           pDevInsR0;              /**< Device instance - R0. */
     113    PPDMDEVINSRC           pDevInsRC;              /**< Device instance - RC. */
     114
     115    /* virtioState must be first member */
     116    VIRTIOSTATE                     virtioState;
     117
     118    /* SCSI target instances data */
     119    VIRTIOSCSITARGET                aTargetInstances[VIRTIOSCSI_MAX_TARGETS];
     120
     121    /** Base address of the I/O ports. */
     122    RTIOPORT                        IOPortBase;
     123
     124    /** Base address of the memory mapping. */
     125    RTGCPHYS                        GCPhysMMIOBase;
     126
     127    /** IMediaExPort: Media ejection notification */
     128    R3PTRTYPE(PPDMIMEDIANOTIFY)     pMediaNotify;
    109129
    110130    /** Queue to send tasks to R3. - HC ptr */
    111131    R3PTRTYPE(PPDMQUEUE)            pNotifierQueueR3;
    112     /** Queue to send tasks to R3. - HC ptr */
    113     R0PTRTYPE(PPDMQUEUE)            pNotifierQueueR0;
    114     /** Queue to send tasks to R3. - RC ptr */
    115     RCPTRTYPE(PPDMQUEUE)            pNotifierQueueRC;
    116132
    117133    /** The support driver session handle. */
    118134    R3R0PTRTYPE(PSUPDRVSESSION)     pSupDrvSession;
     135
    119136    /** Worker thread. */
    120137    R3PTRTYPE(PPDMTHREAD)           pThreadWrk;
     138
    121139    /** The event semaphore the processing thread waits on. */
    122140    SUPSEMEVENT                     hEvtProcess;
    123141
    124     /** The base interface.
    125      * @todo use PDMDEVINS::IBase  */
    126     PDMIBASE                        IBase;
    127 
    128     /** Whether R0 is enabled. */
    129     bool                            fR0Enabled;
    130     /** Whether RC is enabled. */
    131     bool                            fGCEnabled;
    132142    /** Number of ports detected */
    133143    uint64_t                        cTargets;
    134144
    135     /** Base address of the I/O ports. */
    136     RTIOPORT                        IOPortBase;
    137 
    138     /** Base address of the memory mapping. */
    139     RTGCPHYS                        MMIOBase;
    140 
    141     /** Status LUN: Media Notifys. */
    142     R3PTRTYPE(PPDMIMEDIANOTIFY)     pMediaNotify;
    143 
    144     /** Partner of ILeds. */
    145     R3PTRTYPE(PPDMILEDCONNECTORS)   pLedsConnector;
    146 
    147     /** Indicates that PDMDevHlpAsyncNotificationCompleted should be called when
    148      * a port is entering the idle state. */
     145    /** True if PDMDevHlpAsyncNotificationCompleted should be called when port goes idle */
    149146    bool volatile                   fSignalIdle;
    150147
     
    152149
    153150
     151
     152//pk: Needed for virtioIO (e.g. to talk to devSCSI? TBD ??
    154153/**
    155154 * Task state for a CCB request.
     
    174173typedef struct VIRTIOSCSIREQ *PVIRTIOSCSIREQ;
    175174
     175
    176176#define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01
     177
     178#define PCI_VENDOR_ID_VIRTIO                        0x1AF4
     179#define PCI_DEVICE_ID_VIRTIO_SCSI_HOST              0x1048
     180#define PCI_CLASS_BASE_MASS_STORAGE                 0x01
     181#define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER       0x00
     182#define PCI_CLASS_PROG_UNSPECIFIED                  0x00
     183#define VIRTIO_SCSI_NAME_FMT                        "VIRTIOSCSI%d" /* "VSCSI" *might* be ambiguous with VBoxSCSI? */
     184#define VIRTIO_SCSI_PCI_CLASS                       0x01     /* Base class Mass Storage? */
     185#define VIRTIO_SCSI_N_QUEUES                        3        /* Control, Event, Request */
     186#define VIRTIO_SCSI_REGION_MEM_IO                   0
     187#define VIRTIO_SCSI_REGION_PORT_IO                  1
     188#define VIRTIO_SCSI_REGION_PCI_CAP                  2
     189
     190/**
     191 * Definitions that follow are based on the VirtIO 1.0 specification.
     192 * Struct names are the same. The field names have been adapted to VirtualBox
     193 * data type + camel case annotation, with the original field name from the
     194 * VirtIO specification in the field's comment.
     195 */
     196
     197/** @name VirtIO 1.0 SCSI Host feature bits
     198 * @{  */
     199#define VIRTIO_SCSI_F_INOUT                         0      /** Request is device readable AND writeable */
     200#define VIRTIO_SCSI_F_HOTPLUG                       1      /** Host SHOULD allow hotplugging SCSI LUNs & targets */
     201#define VIRTIO_SCSI_F_CHANGE                        2      /** Host reports LUN changes via VIRTIO_SCSI_T_PARAM_CHANGE event */
     202/** @} */
     203
     204#define CDB_SIZE                                    1      /* logic tbd */
     205#define SENSE_SIZE                                  1      /* logic tbd */
     206#define PI_BYTES_OUT                                1      /* logic tbd */
     207#define PI_BYTES_IN                                 1      /* logic tbd */
     208#define DATA_OUT                                    1      /* logic tbd */
     209typedef struct virtio_scsi_req_cmd
     210{
     211    /* Device-readable part */
     212    uint8_t  uLUN[8];                                       /** lun               */
     213    uint64_t uId;                                           /** id                */
     214    uint8_t  uTaskAttr;                                     /** task_attr         */
     215    uint8_t  uPrio;                                         /** prio              */
     216    uint8_t  uCrn;                                          /** crn               */
     217    uint8_t  uCdb[CDB_SIZE];                                /** cdb               */
     218
     219    /** Following three fields only present if VIRTIO_SCSI_F_T10_PI negotiated */
     220
     221    uint32_t uPiBytesOut;                                   /** pi_bytesout       */
     222    uint32_t uPiBytesIn;                                    /** pi_bytesin        */
     223    uint8_t  uPiOut[PI_BYTES_OUT];                          /** pi_out[]          */
     224
     225    uint8_t  uDataOut[DATA_OUT];                            /** dataout           */
     226
     227    /* Device-writable part */
     228    uint32_t uSenseLen;                                     /** sense_len         */
     229    uint32_t uResidual;                                     /** residual          */
     230    uint16_t uStatusQualifier;                              /** status_qualifier  */
     231    uint8_t  uStatus;                                       /** status            */
     232    uint8_t  uResponse;                                     /** response          */
     233    uint8_t  uSense[SENSE_SIZE];                            /** sense             */
     234
     235    /** Following two fields only present if VIRTIO_SCSI_F_T10_PI negotiated */
     236    uint8_t  uPiIn[PI_BYTES_IN];                            /** pi_in[]           */
     237    uint8_t  uDataIn[];                                     /** detain;           */
     238} VIRTIOSCSIREQCMD, *PVIRTIOSCSIREQCMD;
     239
     240/** Command-specific response values */
     241#define VIRTIO_SCSI_S_OK                            0       /* control, command   */
     242#define VIRTIO_SCSI_S_OVERRUN                       1       /* control */
     243#define VIRTIO_SCSI_S_ABORTED                       2       /* control */
     244#define VIRTIO_SCSI_S_BAD_TARGET                    3       /* control, command */
     245#define VIRTIO_SCSI_S_RESET                         4       /* control */
     246#define VIRTIO_SCSI_S_BUSY                          5       /* control, command */
     247#define VIRTIO_SCSI_S_TRANSPORT_FAILURE             6       /* control, command */
     248#define VIRTIO_SCSI_S_TARGET_FAILURE                7       /* control, command */
     249#define VIRTIO_SCSI_S_NEXUS_FAILURE                 8       /* control, command */
     250#define VIRTIO_SCSI_S_FAILURE                       9       /* control, command */
     251#define VIRTIO_SCSI_S_INCORRECT_LUN                12       /* command */
     252
     253
     254/** task_attr */
     255#define VIRTIO_SCSI_S_SIMPLE                        0
     256#define VIRTIO_SCSI_S_ORDERED                       1
     257#define VIRTIO_SCSI_S_HEAD                          2
     258#define VIRTIO_SCSI_S_ACA                           3
     259
     260#define VIRTIO_SCSI_T_TMF                           0
     261#define VIRTIO_SCSI_T_TMF_ABORT_TASK                0
     262#define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET            1
     263#define VIRTIO_SCSI_T_TMF_CLEAR_ACA                 2
     264#define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET            3
     265#define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET           4
     266#define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET        5
     267#define VIRTIO_SCSI_T_TMF_QUERY_TASK                6
     268#define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET            7
     269
     270typedef struct virtio_scsi_ctrl_tmf
     271{
     272     // Device-readable part
     273    uint32_t uType;                                          /** type           */
     274    uint32_t uSubtype;                                       /** subtype        */
     275    uint8_t  uLUN[8];                                        /** lun            */
     276    uint64_t uId;                                            /** id             */
     277    // Device-writable part
     278    uint8_t  uResponse;                                      /** response       */
     279} VIRTIOSCSICTRLBUF, *PVIRTIOSCSICTRLBUF;
     280
     281/* command-specific response values */
     282
     283#define VIRTIO_SCSI_S_FUNCTION_COMPLETE            0
     284#define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED           10
     285#define VIRTIO_SCSI_S_FUNCTION_REJECTED            11
     286
     287#define VIRTIO_SCSI_T_AN_QUERY                     1         /** Asynchronous notification query */
     288#define VIRTIO_SCSI_T_AN_SUBSCRIBE                 2         /** Asynchronous notification subscription */
     289
     290typedef struct virtio_scsi_ctrl_an
     291{
     292    // Device-readable part
     293    uint32_t  uType;                                         /** type            */
     294    uint8_t   uLUN[8];                                       /** lun             */
     295    uint32_t  uEventRequested;                               /** event_requested */
     296    // Device-writable part
     297    uint32_t  uEventActual;                                  /** event_actual    */
     298    uint8_t   uResponse;                                     /** response        */
     299}  VIRTIOSCSICTRLAN, *PVIRTIOSCSICTRLAN;
     300
     301#define VIRTIO_SCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2
     302#define VIRTIO_SCSI_EVT_ASYNC_POWER_MGMT          4
     303#define VIRTIO_SCSI_EVT_ASYNC_EXTERNAL_REQUEST    8
     304#define VIRTIO_SCSI_EVT_ASYNC_MEDIA_CHANGE        16
     305#define VIRTIO_SCSI_EVT_ASYNC_MULTI_HOST          32
     306#define VIRTIO_SCSI_EVT_ASYNC_DEVICE_BUSY         64
     307
     308/** Device operation: controlq */
     309
     310typedef struct virtio_scsi_ctrl
     311{
     312    uint32_t type;                                           /** type            */
     313    uint8_t  response;                                       /** response        */
     314} VIRTIOSCSICTRL, *PVIRTIOSCSICTRL;
     315
     316#define VIRTIO_SCSI_T_NO_EVENT                   0
     317
     318#define VIRTIO_SCSI_T_TRANSPORT_RESET            1
     319#define VIRTIO_SCSI_T_ASYNC_NOTIFY               2           /** Asynchronous notification */
     320#define VIRTIO_SCSI_T_PARAM_CHANGE               3
     321
     322#define VIRTIO_SCSI_EVT_RESET_HARD               0
     323#define VIRTIO_SCSI_EVT_RESET_RESCAN             1
     324#define VIRTIO_SCSI_EVT_RESET_REMOVED            2
     325
     326/** Device operation: eventq */
     327
     328#define VIRTIO_SCSI_T_EVENTS_MISSED             0x80000000
     329typedef struct virtio_scsi_event {
     330    // Device-writable part
     331    uint32_t uEvent;                                         /** event:          */
     332    uint8_t  uLUN[8];                                        /** lun             */
     333    uint32_t uReason;                                        /** reason          */
     334} VIRTIOSCSIEVENT, *PVIRTIOSCSIEVENT;
     335
     336
    177337/*********************************************************************************************************************************/
     338
     339#ifdef BOOTABLE_SUPPORT_TBD
     340/** @callback_method_impl{FNIOMIOPORTIN} */
     341static DECLCALLBACK(int) virtioScsiR3BiosIoPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
     342                                                    uint32_t *pcTransfers, unsigned cb);
     343{
     344}
     345/** @callback_method_impl{FNIOMIOPORTOUT} */
     346static DECLCALLBACK(int) virtioScsiR3BiosIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb);
     347{
     348}
     349/** @callback_method_impl{FNIOMIOPORTOUTSTRING} */
     350static DECLCALLBACK(int) virtioScsiR3BiosIoPortWriteStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, const uint8_t *pbSrc,
     351                                                        uint32_t *pcTransfers, unsigned cb);
     352{
     353}
     354/** @callback_method_impl{FNIOMIOPORTINSTRING} */
     355static DECLCALLBACK(int) virtioScsiR3BiosIoPortReadStr(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint8_t *pbDst,
     356                                                       uint32_t *pcTransfers, unsigned cb);
     357{
     358}
     359#endif
    178360
    179361/**
     
    186368static DECLCALLBACK(void) virtioScsiR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
    187369{
    188     PVIRTIOSCSI   pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    189     bool        fVerbose = false;
     370    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     371    bool fVerbose = false;
    190372
    191373    /* Parse arguments. */
     
    197379                    pDevIns->pReg->szName,
    198380                    pDevIns->iInstance);
    199     pHlp->pfnPrintf(pHlp, "GC=%RTbool R0=%RTbool\n",
    200                     !!pThis->fGCEnabled, !!pThis->fR0Enabled);
     381    pHlp->pfnPrintf(pHlp, "numTargets=%lu", pThis->cTargets);
    201382}
    202383
     
    204385static DECLCALLBACK(int) virtioScsiR3LiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
    205386{
     387    LogFunc(("callback"));
     388    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     389    RT_NOREF(pThis);
    206390    RT_NOREF(uPass);
    207     NOREF(pSSM);
    208     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    209     LogFunc(("callback"));
    210     NOREF(pThis);
     391    RT_NOREF(pSSM);
    211392    return VINF_SSM_DONT_CALL_AGAIN;
    212393}
     
    215396static DECLCALLBACK(int) virtioScsiR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
    216397{
     398    LogFunc(("callback"));
     399    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     400    RT_NOREF(pThis);
    217401    RT_NOREF(uPass);
    218     NOREF(pSSM);
    219     NOREF(uVersion);
    220     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    221     LogFunc(("callback"));
    222     NOREF(pThis);
     402    RT_NOREF(pSSM);
     403    RT_NOREF(uVersion);
    223404    return VINF_SSM_DONT_CALL_AGAIN;
    224405}
     
    227408static DECLCALLBACK(int) virtioScsiR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    228409{
     410    LogFunc(("callback"));
     411    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     412    RT_NOREF(pThis);
    229413    RT_NOREF(pSSM);
    230     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    231     LogFunc(("callback"));
    232     NOREF(pThis);
    233414    return VINF_SUCCESS;
    234415}
     
    237418static DECLCALLBACK(int) virtioScsiR3LoadDone(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
    238419{
     420    LogFunc(("callback"));
     421    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     422    RT_NOREF(pThis);
    239423    RT_NOREF(pSSM);
    240     PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    241     LogFunc(("callback"));
    242     NOREF(pThis);
    243424    return VINF_SUCCESS;
    244425}
     
    258439{
    259440    RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
    260 
    261     /* the linux driver does not make use of the MMIO area. */
    262     AssertMsgFailed(("MMIO Read\n"));
     441    LogFunc(("Read from MMIO area\n"));
    263442    return VINF_SUCCESS;
    264443}
    265 
    266444
    267445/**
     
    279457{
    280458    RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
    281 
    282     /* the linux driver does not make use of the MMIO area. */
    283     AssertMsgFailed(("MMIO Write\n"));
     459    LogFunc(("Write to MMIO area\n"));
    284460    return VINF_SUCCESS;
    285461}
    286462
    287463/**
    288  * Port I/O Handler for IN operations.
    289  *
    290  * @returns VBox status code.
    291  *
    292  * @param   pDevIns     The device instance.
    293  * @param   pvUser      User argument.
    294  * @param   uPort       Port number used for the IN operation.
    295  * @param   pu32        Where to store the result.
    296  * @param   cb          Number of bytes read.
    297  */
    298 PDMBOTHCBDECL(int) virtioScsiIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t *pu32, unsigned cb)
    299 {
    300 //    PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    301     unsigned iRegister = uPort % 4;
    302     NOREF(iRegister);
    303     NOREF(pDevIns);
    304     NOREF(pu32);
    305     RT_NOREF_PV(pvUser); RT_NOREF_PV(cb);
    306 
    307     Assert(cb == 1);
    308 
    309 //    return buslogicRegisterRead(pVirtioScsi, iRegister, pu32);
    310     return 0;
    311 }
    312 
    313 
    314 /**
    315  * Port I/O Handler for OUT operations.
    316  *
    317  * @returns VBox status code.
    318  *
    319  * @param   pDevIns     The device instance.
    320  * @param   pvUser      User argument.
    321  * @param   uPort       Port number used for the IN operation.
    322  * @param   u32         The value to output.
    323  * @param   cb          The value size in bytes.
    324  */
    325 PDMBOTHCBDECL(int) virtioScsiIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT uPort, uint32_t u32, unsigned cb)
    326 {
    327 //    PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    328     unsigned iRegister = uPort % 4;
    329     uint8_t uVal = (uint8_t)u32;
    330     NOREF(uVal);
    331     NOREF(iRegister);
    332     RT_NOREF2(pvUser, cb);
    333     NOREF(u32);
    334 
    335     Assert(cb == 1);
    336 
    337 //    int rc = buslogicRegisterWrite(pVirtioScsi, iRegister, (uint8_t)uVal);
    338     int rc = 0;
    339     Log2(("#%d %s: pvUser=%#p cb=%d u32=%#x uPort=%#x rc=%Rrc\n",
    340           pDevIns->iInstance, __FUNCTION__, pvUser, cb, u32, uPort, rc));
    341 
    342     return rc;
    343 }
    344 
    345 /**
    346464 * @callback_method_impl{FNPCIIOREGIONMAP}
    347465 */
    348 static DECLCALLBACK(int) virtioScsiR3MmioMap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
     466static DECLCALLBACK(int) virtioScsiR3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
    349467                                           RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
    350468{
    351469    RT_NOREF(pPciDev, iRegion);
    352470    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    353     int   rc = VINF_SUCCESS;
    354 
    355     LogFunc(("Register MMIO area at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
     471    int rc = VINF_SUCCESS;
    356472
    357473    Assert(cb >= 32);
    358474
    359     if (enmType == PCI_ADDRESS_SPACE_MEM)
     475    switch (iRegion)
    360476    {
    361         /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
    362         rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
     477        case 0:
     478            LogFunc(("virtio-scsi controller MMIO mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
     479
     480            /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
     481            rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    363482                                   IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
    364                                    virtioScsiMMIOWrite, virtioScsiMMIORead, "virtio-scsi MMIO");
    365         if (RT_FAILURE(rc))
     483                                   virtioScsiMMIOWrite, virtioScsiMMIORead,
     484                                   "virtio-scsi MMIO");
     485            pThis->GCPhysMMIOBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;
    366486            return rc;
    367 
    368         if (pThis->fGCEnabled)
    369         {
    370             rc = PDMDevHlpMMIORegisterRC(pDevIns, GCPhysAddress, cb, NIL_RTRCPTR /*pvUser*/,
    371                                          "virtioScsiMMIOWrite", "virtioScsiMMIORead");
    372             if (RT_FAILURE(rc))
    373                 return rc;
    374         }
    375 
    376         pThis->MMIOBase = GCPhysAddress;
     487        case 1:
     488            /* VirtIO 1.0 doesn't uses Port I/O (Virtio 0.95 e.g. "legacy", does) */
     489            AssertMsgFailed(("virtio-scsi: Port I/O not supported by this Host SCSI device\n"));
     490        default:
     491            AssertMsgFailed(("Invalid enmType=%d\n", enmType));
    377492    }
    378     else if (enmType == PCI_ADDRESS_SPACE_IO)
    379     {
    380         rc = PDMDevHlpIOPortRegister(pDevIns, (RTIOPORT)GCPhysAddress, 32,
    381                                      NULL, virtioScsiIOPortWrite, virtioScsiIOPortRead, NULL, NULL, "virtio-scsi PCI");
    382         if (RT_FAILURE(rc))
    383             return rc;
    384 
    385         if (pThis->fGCEnabled)
    386         {
    387             rc = PDMDevHlpIOPortRegisterRC(pDevIns, (RTIOPORT)GCPhysAddress, 32,
    388                                            0, "virtioScsiIOPortWrite", "virtioScsiIOPortRead", NULL, NULL, "virtio-scsi PCI");
    389             if (RT_FAILURE(rc))
    390                 return rc;
    391         }
    392 
    393         pThis->IOPortBase = (RTIOPORT)GCPhysAddress;
    394     }
    395     else
    396         AssertMsgFailed(("Invalid enmType=%d\n", enmType));
    397 
    398     return rc;
     493    return VERR_GENERAL_FAILURE; /* Should never get here */
    399494}
    400495
     
    419514static DECLCALLBACK(void) virtioScsiR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    420515{
    421 LogFunc(("Relocating virtio-scsci"));
     516    LogFunc(("Relocating virtio-scsi"));
    422517    RT_NOREF(offDelta);
    423518    PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    424519
    425520    pThis->pDevInsR3 = pDevIns;
    426 //    pThis->pNotifierQueueRC = PDMQueueRCPtr(pThis->pNotifierQueueR3);
    427521
    428522    for (uint32_t i = 0; i < VIRTIOSCSI_MAX_TARGETS; i++)
     
    458552                                                    size_t cbCopy)
    459553{
    460 NOREF(pInterface);
    461 NOREF(pvIoReqAlloc);
    462 NOREF(offDst);
    463 NOREF(pSgBuf);
    464 
    465     RT_NOREF1(hIoReq);
    466 //    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    467 //    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    468 
     554    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     555    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    469556    size_t cbCopied = 0;
     557    RT_NOREF(pTarget);
     558    RT_NOREF(pReq);
     559    RT_NOREF(pInterface);
     560    RT_NOREF(pvIoReqAlloc);
     561    RT_NOREF(offDst);
     562    RT_NOREF(pSgBuf);
     563    RT_NOREF(hIoReq);
     564    RT_NOREF(cbCopy);
     565    RT_NOREF(cbCopied);
     566
    470567/*
    471568    if (RT_UNLIKELY(pReq->fBIOS))
     
    473570    else
    474571        cbCopied = virtioScsiR3CopySgBufToGuest(pTarget->CTX_SUFF(pVirtioScsi), pReq, pSgBuf, offDst, cbCopy);
     572    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
    475573*/
    476     return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_OVERFLOW;
     574    return 0; /* placeholder */
    477575}
    478576
     
    484582                                                  size_t cbCopy)
    485583{
    486 NOREF(pInterface);
    487 NOREF(pvIoReqAlloc);
    488 NOREF(offSrc);
    489 NOREF(pSgBuf);
    490 
    491     RT_NOREF1(hIoReq);
    492 //    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    493 //    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    494 
     584    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     585    PVIRTIOSCSIREQ pReq = (PVIRTIOSCSIREQ)pvIoReqAlloc;
    495586    size_t cbCopied = 0;
     587    RT_NOREF(pTarget);
     588    RT_NOREF(pReq);
     589    RT_NOREF(pInterface);
     590    RT_NOREF(pvIoReqAlloc);
     591    RT_NOREF(offSrc);
     592    RT_NOREF(pSgBuf);
     593    RT_NOREF(hIoReq);
     594    RT_NOREF(cbCopy);
     595    RT_NOREF(cbCopied);
     596
    496597/*
    497598    if (RT_UNLIKELY(pReq->fBIOS))
     
    499600    else
    500601        cbCopied = vboxscsiR3CopySgBufFromGuest(pTarget->CTX_SUFF(pVirtioScsi), pReq, pSgBuf, offSrc, cbCopy);
     602    return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
    501603*/
    502     return cbCopied == cbCopy ? VINF_SUCCESS : VERR_PDM_MEDIAEX_IOBUF_UNDERRUN;
     604    return 0; /* placeholder */
     605
    503606}
    504607
     
    509612                                                       void *pvIoReqAlloc, int rcReq)
    510613{
    511 NOREF(pInterface);
    512 NOREF(pvIoReqAlloc);
    513 NOREF(rcReq);
     614    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
     615    RT_NOREF(pTarget);
     616    RT_NOREF(pInterface);
     617    RT_NOREF(pvIoReqAlloc);
     618    RT_NOREF(rcReq);
    514619    RT_NOREF(hIoReq);
    515 //    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    516620//    virtioScsiR3ReqComplete(pTarget->CTX_SUFF(pVirtioScsi), (VIRTIOSCSIREQ)pvIoReqAlloc, rcReq);
    517621    return VINF_SUCCESS;
     
    525629{
    526630
    527 NOREF(pInterface);
    528 NOREF(hIoReq);
    529 NOREF(enmState);
    530     RT_NOREF3(hIoReq, pvIoReqAlloc, enmState);
     631    RT_NOREF4(pInterface, hIoReq, pvIoReqAlloc, enmState);
    531632    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);
    532633
     
    551652
    552653/**
    553  * Gets the pointer to the status LED of a device - called from the SCSI driver.
    554  *
    555  * @returns VBox status code.
    556  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    557  * @param   iLUN            The unit which status LED we desire. Always 0 here as the driver
    558  *                          doesn't know about other LUN's.
    559  * @param   ppLed           Where to store the LED pointer.
    560  */
    561 static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
    562 {
    563     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
    564     if (iLUN == 0)
    565     {
    566         *ppLed = &pTarget->Led;
    567         Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
    568         return VINF_SUCCESS;
    569     }
    570     return VERR_PDM_LUN_NOT_FOUND;
    571 }
    572 
    573 /**
    574654 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}
    575655 */
     
    580660
    581661    if (pThis->pMediaNotify)
    582     {
    583         int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pThis->CTX_SUFF(pDevIns)), VMCPUID_ANY,
    584                                    (PFNRT)pThis->pMediaNotify->pfnEjected, 2,
    585                                    pThis->pMediaNotify, pTarget->iLUN);
    586         AssertRC(rc);
    587     }
    588 }
    589 
    590 
    591 /**
    592  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    593  */
    594 static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    595 {
    596     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
    597     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pTarget->IBase);
    598     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort);
    599     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);
    600     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pTarget->ILed);
    601     return NULL;
    602 }
     662        virtioSetWriteLed(&(pThis->virtioState), false);
     663}
     664
    603665
    604666/**
     
    622684}
    623685
     686
     687/**
     688 * virtio-scsi VirtIO Device-specific capabilities read callback
     689 * (other VirtIO capabilities and features are handled in VirtIO implementation)
     690 *
     691 * @param   pDevIns     The device instance.
     692 * @param   GCPhysAddr  Guest driver physical address to read
     693 * @param   pvBuf       Buffer in which to save read data
     694 * @param   cbRead      Number of bytes to read
     695 */
     696static DECLCALLBACK(int) virtioScsiR3DevCapRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhysAddr, const void *pvBuf, size_t cbRead)
     697{
     698/*TBD*/
     699    LogFlowFunc(("Read from Device-Specific capabilities, callback to VirtIO client\n"));
     700    RT_NOREF(pDevIns);
     701    RT_NOREF(GCPhysAddr);
     702    RT_NOREF(pvBuf);
     703    RT_NOREF(cbRead);
     704    int rv = VINF_SUCCESS;
     705    return rv;
     706}
     707
     708/**
     709 * virtio-scsi VirtIO Device-specific capabilities read callback
     710 * (other VirtIO capabilities and features are handled in VirtIO implementation)
     711 *
     712 * @param   pDevIns     The device instance.
     713 * @param   GCPhysAddr  Guest driver physical address to write
     714 * @param   pvBuf       Buffer in which to save read data
     715 * @param   cbRead      Number of bytes to write
     716 */
     717static DECLCALLBACK(int) virtioScsiR3DevCapWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhysAddr, const void *pvBuf, size_t cbWrite)
     718{
     719/*TBD*/
     720    LogFlowFunc(("Write to Device-Specific capabilities, callback to VirtIO client\n"));
     721    RT_NOREF(pDevIns);
     722    RT_NOREF(GCPhysAddr);
     723    RT_NOREF(pvBuf);
     724    RT_NOREF(cbWrite);
     725    int rv = VINF_SUCCESS;
     726    return rv;
     727}
     728
     729/**
     730 * Detach notification.
     731 *
     732 * One harddisk at one port has been unplugged.
     733 * The VM is suspended at this point.
     734 *
     735 * @param   pDevIns     The device instance.
     736 * @param   iLUN        The logical unit which is being detached.
     737 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
     738 */
     739static DECLCALLBACK(void) virtioScsiR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     740{
     741    RT_NOREF(fFlags);
     742    PVIRTIOSCSI       pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     743    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
     744
     745    Log(("%s:\n", __FUNCTION__));
     746
     747    AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
     748              ("virtio-scsi: Device does not support hotplugging\n"));
     749
     750    /*
     751     * Zero some important members.
     752     */
     753    pTarget->fPresent    = false;
     754    pTarget->pUpstreamDrvBase    = NULL;
     755}
     756
     757
     758/**
     759 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
     760 */
     761static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     762{
     763    PPDMDRVINS pDevIns = PDMIBASE_2_PDMDRV(pInterface);
     764    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
     765    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevIns->IBase);
     766    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort);
     767    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);
     768    return NULL;
     769}
     770
     771/**
     772 * Attach command.
     773 *
     774 * This is called when we change block driver.
     775 *
     776 * @returns VBox status code.
     777 * @param   pDevIns     The device instance.
     778 * @param   iLUN        The logical unit which is being detached.
     779 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
     780 */
     781static DECLCALLBACK(int)  virtioScsiR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     782{
     783    PVIRTIOSCSI       pThis   = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     784    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
     785    int rc;
     786
     787    pThis->pDevInsR3    = pDevIns;
     788    pThis->pDevInsR0    = PDMDEVINS_2_R0PTR(pDevIns);
     789    pThis->pDevInsRC    = PDMDEVINS_2_RCPTR(pDevIns);
     790
     791    AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
     792                    ("virtio-scsi: Device does not support hotplugging\n"),
     793                    VERR_INVALID_PARAMETER);
     794
     795    /* the usual paranoia */
     796    AssertRelease(!pTarget->pUpstreamDrvBase);
     797    Assert(pTarget->iLUN == iLUN);
     798
     799    /*
     800     * Try attach the SCSI driver and get the interfaces,
     801     * required as well as optional.
     802     */
     803    rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iLUN, &pDevIns->IBase,
     804                               &pTarget->pUpstreamDrvBase, (const char *)&pTarget->pszLunName);
     805    if (RT_SUCCESS(rc))
     806        pTarget->fPresent = true;
     807    else
     808        AssertMsgFailed(("Failed to attach %s. rc=%Rrc\n", pTarget->pszLunName, rc));
     809
     810    if (RT_FAILURE(rc))
     811    {
     812        pTarget->fPresent = false;
     813        pTarget->pUpstreamDrvBase = NULL;
     814    }
     815    return rc;
     816}
     817
    624818static DECLCALLBACK(int) virtioScsiDestruct(PPDMDEVINS pDevIns)
    625819{
     
    628822     */
    629823    PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns);
    630 
    631824    return VINF_SUCCESS;
    632825}
     
    635828{
    636829
     830    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    637831    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    638     int        rc = VINF_SUCCESS;
    639     bool       fBootable = true;
    640     PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
    641 
    642     NOREF(fBootable);
    643     NOREF(iInstance);
    644 
    645     /*
    646      * Init instance data (do early because of constructor).
    647      */
    648     pThis->pDevInsR3 = pDevIns;
    649     pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    650     pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    651 
    652     PCIDevSetVendorId         (&pThis->dev, 0x1AF4); /* VirtIO */
    653     PCIDevSetDeviceId         (&pThis->dev, 0x1048); /* SCSI Host */
    654     PCIDevSetCommand          (&pThis->dev, PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS);
    655     PCIDevSetRevisionId       (&pThis->dev, 0x01);
    656     PCIDevSetClassProg        (&pThis->dev, 0x00); /* SCSI */
    657     PCIDevSetClassSub         (&pThis->dev, 0x00); /* SCSI */
    658     PCIDevSetClassBase        (&pThis->dev, 0x01); /* Mass storage */
    659     PCIDevSetBaseAddress      (&pThis->dev, 0, true  /*IO*/, false /*Pref*/, false /*64-bit*/, 0x00000000);
    660     PCIDevSetBaseAddress      (&pThis->dev, 1, false /*IO*/, false /*Pref*/, false /*64-bit*/, 0x00000000);
    661     PCIDevSetSubSystemVendorId(&pThis->dev, 0x104b);
    662     PCIDevSetSubSystemId      (&pThis->dev, 0x1040);
    663     PCIDevSetInterruptLine    (&pThis->dev, 0x00);
    664     PCIDevSetInterruptPin     (&pThis->dev, 0x01);
     832    int  rc = VINF_SUCCESS;
     833    bool fBootable = true;
     834
     835    LogFunc(("PDM device instance: %d\n", iInstance));
    665836
    666837    /*
    667838     * Validate and read configuration.
    668839     */
    669     if (!CFGMR3AreValuesValid(pCfg,
    670                               "GCEnabled\0"
    671                               "R0Enabled\0"
    672                               "NumTargets\0"))
    673         return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
     840    if (!CFGMR3AreValuesValid(pCfg,"NumTargets\0"
     841                                   "Bootable\0"
     842                                /* "GCEnabled\0"    TBD */
     843                                /* "R0Enabled\0"    TBD */
     844    ))
     845    return PDMDEV_SET_ERROR(pDevIns, VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES,
    674846                                N_("virtio-scsi configuration error: unknown option specified"));
    675 
    676     rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &pThis->fGCEnabled, true);
    677     if (RT_FAILURE(rc))
    678         return PDMDEV_SET_ERROR(pDevIns, rc,
    679                                 N_("virtio-scsi configuration error: failed to read GCEnabled as boolean"));
    680     LogFunc(("fGCEnabled=%d\n", pThis->fGCEnabled));
    681 
    682     rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &pThis->fR0Enabled, true);
    683     if (RT_FAILURE(rc))
    684         return PDMDEV_SET_ERROR(pDevIns, rc,
    685                                 N_("virtio-scsi configuration error: failed to read R0Enabled as boolean"));
    686     LogFunc(("R0Enabled=%d\n", pThis->fGCEnabled));
    687847
    688848    rc = CFGMR3QueryIntegerDef(pCfg, "NumTargets", &pThis->cTargets, true);
     
    690850        return PDMDEV_SET_ERROR(pDevIns, rc,
    691851                                N_("virtio-scsi configuration error: failed to read NumTargets as integer"));
    692     LogFunc(("NumTargets=%d\n", pThis->fGCEnabled));
    693 
    694 
    695 LogFunc(("Register PCI device and map mmio and ports\n"));
    696     rc = PDMDevHlpPCIRegister(pDevIns, &pThis->dev);
     852    LogFunc(("NumTargets=%d\n", pThis->cTargets));
     853
     854    rc = CFGMR3QueryBoolDef(pCfg, "Bootable", &fBootable, true);
    697855    if (RT_FAILURE(rc))
    698         return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi cannot register with PCI bus"));
    699 
    700 LogFunc(("Register io region\n"));
    701     rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0, 32, PCI_ADDRESS_SPACE_IO, virtioScsiR3MmioMap);
     856         return PDMDEV_SET_ERROR(pDevIns, rc,
     857                                N_("virtio-scsi configuration error: failed to read Bootable as boolean"));
     858    LogFunc(("Bootable=%RTbool (unimplemented)\n", fBootable));
     859
     860    VIRTIOPCIPARAMS virtioPciParams, *pVirtioPciParams = &virtioPciParams;
     861    pVirtioPciParams->uDeviceId      = PCI_DEVICE_ID_VIRTIO_SCSI_HOST;
     862    pVirtioPciParams->uClassBase     = PCI_CLASS_BASE_MASS_STORAGE;
     863    pVirtioPciParams->uClassSub      = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER;
     864    pVirtioPciParams->uClassProg     = PCI_CLASS_PROG_UNSPECIFIED;
     865    pVirtioPciParams->uSubsystemId   = PCI_DEVICE_ID_VIRTIO_SCSI_HOST;  /* Virtio 1.0 spec allows PCI Device ID here */
     866    pVirtioPciParams->uInterruptLine = 0x00;
     867    pVirtioPciParams->uInterruptPin  = 0x01;
     868
     869
     870    PVIRTIOSTATE pVirtioScsi = &(pThis->virtioState);
     871    rc = virtioConstruct(pDevIns, pVirtioScsi, iInstance, pVirtioPciParams,
     872                         VIRTIO_SCSI_NAME_FMT, VIRTIO_SCSI_N_QUEUES, VIRTIO_SCSI_REGION_PCI_CAP,
     873                         virtioScsiR3DevCapRead, virtioScsiR3DevCapWrite, sizeof(VIRTIODEVCFG));
    702874    if (RT_FAILURE(rc))
    703         return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi cannot register PCI I/O address space"));
    704 LogFunc(("Register mmio region\n"));
    705     rc = PDMDevHlpPCIIORegionRegister(pDevIns, 1, 32, PCI_ADDRESS_SPACE_MEM, virtioScsiR3MmioMap);
     875        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO"));
     876
     877    rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIO_SCSI_REGION_PORT_IO, 32,
     878                                      PCI_ADDRESS_SPACE_MEM, virtioScsiR3Map);
    706879    if (RT_FAILURE(rc))
    707         return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi cannot register PCI mmio address space"));
    708 #if 0
     880        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: cannot register PCI mmio address space"));
     881
     882#ifdef BOOTABLE_SUPPORT_TBD
    709883    if (fBootable)
    710884    {
     
    718892    }
    719893#endif
     894
    720895    /* Initialize task queue. */
    721896    rc = PDMDevHlpQueueCreate(pDevIns, sizeof(PDMQUEUEITEMCORE), 5, 0,
     
    724899        return rc;
    725900
    726     pThis->pNotifierQueueR0 = PDMQueueR0Ptr(pThis->pNotifierQueueR3);
    727     pThis->pNotifierQueueRC = PDMQueueRCPtr(pThis->pNotifierQueueR3);
    728 
    729901    /* Initialize per device instance. */
    730     for (unsigned i = 0; i < VIRTIOSCSI_MAX_TARGETS; i++)
     902    for (RTUINT iLUN = 0; iLUN < VIRTIOSCSI_MAX_TARGETS; iLUN++)
    731903    {
    732         PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[i];
    733         char *pszName;
    734 
    735         if (RTStrAPrintf(&pszName, "Device%u", i) < 0)
     904        PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
     905
     906        if (RTStrAPrintf(&pTarget->pszLunName, "VSCSI%u", iLUN) < 0)
    736907            AssertLogRelFailedReturn(VERR_NO_MEMORY);
    737908
    738909        /* Initialize static parts of the device. */
    739         pTarget->iLUN = i;
     910        pTarget->iLUN = iLUN;
    740911        pTarget->pVirtioScsiR3 = pThis;
    741         pTarget->pVirtioScsiRC = PDMINS_2_DATA_RCPTR(pDevIns);
    742         pTarget->Led.u32Magic = PDMLED_MAGIC;
    743         pTarget->IBase.pfnQueryInterface                 = virtioScsiR3DeviceQueryInterface;
     912        /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */
    744913        pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiR3QueryDeviceLocation;
    745914        pTarget->IMediaExPort.pfnIoReqCompleteNotify     = virtioScsiR3IoReqCompleteNotify;
    746915        pTarget->IMediaExPort.pfnIoReqCopyFromBuf        = virtioScsiR3IoReqCopyFromBuf;
    747916        pTarget->IMediaExPort.pfnIoReqCopyToBuf          = virtioScsiR3IoReqCopyToBuf;
     917        pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiR3IoReqStateChanged;
     918        pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiR3MediumEjected;
    748919        pTarget->IMediaExPort.pfnIoReqQueryBuf           = NULL;
    749920        pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
    750         pTarget->IMediaExPort.pfnIoReqStateChanged       = virtioScsiR3IoReqStateChanged;
    751         pTarget->IMediaExPort.pfnMediumEjected           = virtioScsiR3MediumEjected;
    752         pTarget->ILed.pfnQueryStatusLed                  = virtioScsiR3DeviceQueryStatusLed;
    753 
    754         LogFunc(("Attaching: Lun=%d, pszName=%s\n",  pTarget->iLUN, pszName));
    755         /* Attach SCSI driver. */
    756         AssertReturn(pTarget->iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);
    757         rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iLUN, &pTarget->IBase, &pTarget->pDrvBase, pszName);
     921        pDevIns->IBase.pfnQueryInterface                 = virtioScsiR3DeviceQueryInterface;
     922
     923        LogFunc(("Attaching LUN: %s\n", pTarget->pszLunName));
     924
     925        /* Attach this SCSI driver (upstream driver pre-determined statically outside this module) */
     926        AssertReturn(iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);
     927        rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pDevIns->IBase, &pTarget->pUpstreamDrvBase, (const char *)&pTarget->pszLunName);
    758928        if (RT_SUCCESS(rc))
     929        {
    759930            pTarget->fPresent = true;
     931
     932            pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pUpstreamDrvBase, PDMIMEDIA);
     933            AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia),
     934                         ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->iLUN),
     935                         VERR_PDM_MISSING_INTERFACE);
     936
     937             /* Get the extended media interface. */
     938             pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pUpstreamDrvBase, PDMIMEDIAEX);
     939             AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
     940                         ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->iLUN),
     941                         VERR_PDM_MISSING_INTERFACE);
     942
     943// pk: Not sure if this is needed here yet with VirtIO or DrvScsi, will investigate after basic VirtIO working.
     944//            rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(BUSLOGICREQ));
     945//             AssertMsgRCReturn(rc, ("BusLogic configuration error: LUN#%u: Failed to set I/O request size!", pTarget->iLUN),
     946
     947        }
    760948        else if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
    761949        {
    762             pTarget->fPresent    = false;
    763             pTarget->pDrvBase    = NULL;
     950            pTarget->fPresent = false;
     951            pTarget->pUpstreamDrvBase = NULL;
    764952            rc = VINF_SUCCESS;
    765             Log(("virtio-scsi: no driver attached to device %s\n", pszName));
     953            Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszLunName));
    766954        }
    767955        else
    768956        {
    769             AssertLogRelMsgFailed(("virtio-scsi: Failed to attach %s\n", pszName));
     957            AssertLogRelMsgFailed(("virtio-scsi: Failed to attach %s\n", pTarget->pszLunName));
    770958            return rc;
    771959        }
    772960    }
    773961
    774     /*
    775      * Attach status driver (optional).
    776      */
    777 /*
    778     PPDMIBASE pBase;
    779     rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThis->IBase, &pBase, "Status Port");
    780     if (RT_SUCCESS(rc))
    781         pThis->pLedsConnector = PDMIBASE_QUERY_INTERFACE(pBase, PDMILEDCONNECTORS);
    782     else if (rc != VERR_PDM_NO_ATTACHED_DRIVER)
    783     {
    784         AssertMsgFailed(("Failed to attach to status driver. rc=%Rrc\n", rc));
    785         return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi cannot attach to status driver"));
    786     }
    787 */
    788962    rc = PDMDevHlpSSMRegisterEx(pDevIns, VIRTIOSCSI_SAVED_STATE_MINOR_VERSION, sizeof(*pThis), NULL,
    789963                                NULL, virtioScsiR3LiveExec, NULL,
     
    797971    char szTmp[128];
    798972    RTStrPrintf(szTmp, sizeof(szTmp), "%s%d", pDevIns->pReg->szName, pDevIns->iInstance);
    799     PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi HBA info", virtioScsiR3Info);
     973    PDMDevHlpDBGFInfoRegister(pDevIns, szTmp, "virtio-scsi info", virtioScsiR3Info);
    800974
    801975    return rc;
    802976}
    803 
    804 
    805 /**
    806  * Detach notification.
    807  *
    808  * One harddisk at one port has been unplugged.
    809  * The VM is suspended at this point.
    810  *
    811  * @param   pDevIns     The device instance.
    812  * @param   iLUN        The logical unit which is being detached.
    813  * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    814  */
    815 static DECLCALLBACK(void) virtioScsiR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    816 {
    817     RT_NOREF(fFlags);
    818     PVIRTIOSCSI       pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    819     PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
    820 
    821     Log(("%s:\n", __FUNCTION__));
    822 
    823     AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
    824               ("virtio-scsi: Device does not support hotplugging\n"));
    825 
    826     /*
    827      * Zero some important members.
    828      */
    829     pTarget->fPresent    = false;
    830     pTarget->pDrvBase    = NULL;
    831 }
    832 
    833 
    834 /**
    835  * Attach command.
    836  *
    837  * This is called when we change block driver.
    838  *
    839  * @returns VBox status code.
    840  * @param   pDevIns     The device instance.
    841  * @param   iLUN        The logical unit which is being detached.
    842  * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    843  */
    844 static DECLCALLBACK(int)  virtioScsiR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    845 {
    846     PVIRTIOSCSI       pThis   = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    847     PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
    848     int rc;
    849 
    850 LogFlowFunc(("iLun=%d"));
    851 
    852     AssertMsgReturn(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
    853                     ("virtio-scsi: Device does not support hotplugging\n"),
    854                     VERR_INVALID_PARAMETER);
    855 
    856     /* the usual paranoia */
    857     AssertRelease(!pTarget->pDrvBase);
    858     Assert(pTarget->iLUN == iLUN);
    859 
    860     /*
    861      * Try attach the SCSI driver and get the interfaces,
    862      * required as well as optional.
    863      */
    864     rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iLUN, &pTarget->IBase, &pTarget->pDrvBase, NULL);
    865     if (RT_SUCCESS(rc))
    866         pTarget->fPresent = true;
    867     else
    868         AssertMsgFailed(("Failed to attach LUN#%d. rc=%Rrc\n", pTarget->iLUN, rc));
    869 
    870     if (RT_FAILURE(rc))
    871     {
    872         pTarget->fPresent    = false;
    873         pTarget->pDrvBase    = NULL;
    874     }
    875     return rc;
    876 }
    877 
    878977
    879978/**
     
    887986    "virtio-scsi",
    888987    /* szRCMod */
    889     "VBoxDDRC.rc",
     988    "",
    890989    /* szR0Mod */
    891     "VBoxDDR0.r0",
     990    "",
    892991    /* pszDescription */
    893     "Virtio SCSI Device.",
     992    "Virtio SCSI.\n",
    894993    /* fFlags */
     994#ifdef VIRTIOSCSI_GC_SUPPORT
     995    PDM_DEVREG_FLAGS_DEFAULT_BITS | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
     996#else
    895997    PDM_DEVREG_FLAGS_DEFAULT_BITS,
     998#endif
    896999    /* fClass */
    8971000    PDM_DEVREG_CLASS_MISC,
  • trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp

    r79551 r79928  
    24132413                    hrc = ctrls[i]->COMGETTER(PortCount)(&cPorts);                          H();
    24142414                    InsertConfigInteger(pCfg, "NumTargets", cPorts);
     2415                    InsertConfigInteger(pCfg, "Bootable",   fBootable);
    24152416
    24162417                    /* Attach the status driver */
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette