VirtualBox

Changeset 80058 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
Jul 30, 2019 8:17:49 AM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
132495
Message:

Virtio 1.0 capabilities are now showing up and some negotiation hurdles are being accomplished with the Linux guest driver counterpart. (See #9440, Comment #38)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp

    r79973 r80058  
    4444#include "VBoxDD.h"
    4545
    46 
    47 /*********************************************************************************************************************************
    48 *   Structures and Typedefs                                                                                                      *
    49 *********************************************************************************************************************************/
    50 #define VIRTIOSCSI_MAX_TARGETS  1
    51 
    52 /**
    53  * Device Instance Data.
     46#define VIRTIOSCSI_MAX_TARGETS                      1
     47#define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01
     48#define REQ_ALLOC_SIZE                              1024    /* TBD */
     49
     50#define PCI_VENDOR_ID_VIRTIO                        0x1AF4
     51#define PCI_DEVICE_ID_VIRTIOSCSI_HOST               0x1048
     52#define PCI_CLASS_BASE_MASS_STORAGE                 0x01
     53#define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER       0x00
     54#define PCI_CLASS_PROG_UNSPECIFIED                  0x00
     55#define VIRTIOSCSI_NAME_FMT                         "VIRTIOSCSI%d" /* "VSCSI" *might* be ambiguous with VBoxSCSI? */
     56#define VIRTIOSCSI_PCI_CLASS                        0x01     /* Base class Mass Storage? */
     57#define VIRTIOSCSI_N_QUEUES                         3        /* Control, Event, Request */
     58#define VIRTIOSCSI_REGION_MEM_IO                    0
     59#define VIRTIOSCSI_REGION_PORT_IO                   1
     60#define VIRTIOSCSI_REGION_PCI_CAP                   2
     61
     62/**
     63 * Definitions that follow are based on the VirtIO 1.0 specification.
     64 * Struct names are the same. The field names have been adapted to VirtualBox
     65 * data type + camel case annotation, with the original field name from the
     66 * VirtIO specification in the field's comment.
     67 */
     68
     69/** @name VirtIO 1.0 SCSI Host feature bits
     70 * @{  */
     71#define VIRTIOSCSI_F_INOUT                          RT_BIT_64(0)  /** Request is device readable AND writeable */
     72#define VIRTIOSCSI_F_HOTPLUG                        RT_BIT_64(1)  /** Host SHOULD allow hotplugging SCSI LUNs & targets */
     73#define VIRTIOSCSI_F_CHANGE                         RT_BIT_64(2)  /** Host reports LUN changes via VIRTIOSCSI_T_PARAM_CHANGE event */
     74#define VIRTIOSCSI_F_T10_PI                         RT_BIT_64(3)  /** Ext. flds for T10 prot info (DIF/DIX) in SCSI req hdr */
     75/** @} */
     76
     77/**
     78 * Features VirtIO 1.0 Host SCSI controller offers guest driver
     79 */
     80#define VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED         VIRTIOSCSI_F_INOUT   \
     81                                                    | VIRTIOSCSI_F_HOTPLUG \
     82                                                    | VIRTIOSCSI_F_CHANGE  \
     83                                                    | VIRTIOSCSI_F_T10_PI  \
     84
     85/**
     86 * State of a target attached to the VirtIO SCSI Host
    5487 */
    5588typedef struct VIRTIOSCSITARGET
    5689{
    57     /** Pointer to PCI device that owns this target instance. - R3 /pointer */
     90    /** Pointer to PCI device that owns this target instance. - R3 pointer */
    5891    R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiR3;
    59     /** Pointer to PCI device that owns this target instance. - R0 pointer */
    60     R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiR0;
    61     /** Pointer to PCI device that owns this target instance. - RC pointer */
    62     R3PTRTYPE(struct VIRTIOSCSI *)  pVirtioScsiRC;
    6392
    6493    /** Pointer to attached driver's base interface. */
    65     R3PTRTYPE(PPDMIBASE)            pUpstreamDrvBase;
    66 
    67     /** LUN of the device. */
     94    R3PTRTYPE(PPDMIBASE)            pDrvBase;
     95
     96    /** Target LUN */
    6897    RTUINT                          iLUN;
    6998
    70     /** Our base interface. */
     99    /** Target LUN Description */
     100    char *                          pszLunName;
     101
     102    /** Target base interface. */
    71103    PDMIBASE                        IBase;
    72104
     
    74106    bool                            fPresent;
    75107
     108
    76109    /** Media port interface. */
    77110    PDMIMEDIAPORT                   IMediaPort;
     111    /** Pointer to the attached driver's media interface. */
     112    R3PTRTYPE(PPDMIMEDIA)           pDrvMedia;
     113
    78114
    79115    /** Extended media port interface. */
    80116    PDMIMEDIAEXPORT                 IMediaExPort;
     117     /** Pointer to the attached driver's extended media interface. */
     118    R3PTRTYPE(PPDMIMEDIAEX)         pDrvMediaEx;
     119
     120
     121    /** Status LED interface */
     122    PDMILEDPORTS                    ILed;
     123    /** The status LED state for this device. */
     124    PDMLED                          led;
    81125
    82126    /** Number of outstanding tasks on the port. */
    83127    volatile uint32_t               cOutstandingRequests;
    84 
    85     /** LUN Description */
    86     char *                          pszLunName;
    87 
    88     /** Pointer to the attached driver's media interface. */
    89     R3PTRTYPE(PPDMIMEDIA)           pDrvMedia;
    90 
    91      /** Pointer to the attached driver's extended media interface. */
    92     R3PTRTYPE(PPDMIMEDIAEX)         pDrvMediaEx;
    93128
    94129    R3PTRTYPE(PVQUEUE)              pCtlQueue; // ? TBD
     
    100135
    101136/**
    102  * Main VirtIO SCSI device state.
     137 *  PDM instance data (state) for VirtIO Host SCSI device
    103138 *
    104139 * @extends     PDMPCIDEV
     
    112147    VIRTIOSCSITARGET                aTargetInstances[VIRTIOSCSI_MAX_TARGETS];
    113148
    114     PPDMDEVINSR3           pDevInsR3;              /**< Device instance - R3. */
    115     PPDMDEVINSR0           pDevInsR0;              /**< Device instance - R0. */
    116     PPDMDEVINSRC           pDevInsRC;              /**< Device instance - RC. */
     149    /** Device base interface. */
     150    PDMIBASE                        IBase;
     151
     152    /** Pointer to the device instance. - R3 ptr. */
     153    PPDMDEVINSR3                    pDevInsR3;
     154    /** Pointer to the device instance. - R0 ptr. */
     155    PPDMDEVINSR0                    pDevInsR0;
     156    /** Pointer to the device instance. - RC ptr. */
     157    PPDMDEVINSRC                    pDevInsRC;
     158
     159    /** Status LUN: LEDs port interface. */
     160    PDMILEDPORTS                    ILeds;
     161
     162    /** Status LUN: Partner of ILeds. */
     163    R3PTRTYPE(PPDMILEDCONNECTORS)   pLedsConnector;
    117164
    118165    /** Base address of the memory mapping. */
     
    133180    /** The event semaphore the processing thread waits on. */
    134181    SUPSEMEVENT                     hEvtProcess;
     182
     183    PVIRTIOCALLBACKS                pVirtioCallbacks;
    135184
    136185    /** Number of ports detected */
     
    168217
    169218
    170 #define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION        0x01
    171 
    172 #define PCI_VENDOR_ID_VIRTIO                        0x1AF4
    173 #define PCI_DEVICE_ID_VIRTIO_SCSI_HOST              0x1048
    174 #define PCI_CLASS_BASE_MASS_STORAGE                 0x01
    175 #define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER       0x00
    176 #define PCI_CLASS_PROG_UNSPECIFIED                  0x00
    177 #define VIRTIO_SCSI_NAME_FMT                        "VIRTIOSCSI%d" /* "VSCSI" *might* be ambiguous with VBoxSCSI? */
    178 #define VIRTIO_SCSI_PCI_CLASS                       0x01     /* Base class Mass Storage? */
    179 #define VIRTIO_SCSI_N_QUEUES                        3        /* Control, Event, Request */
    180 #define VIRTIO_SCSI_REGION_MEM_IO                   0
    181 #define VIRTIO_SCSI_REGION_PORT_IO                  1
    182 #define VIRTIO_SCSI_REGION_PCI_CAP                  2
    183 
    184 /**
    185  * Definitions that follow are based on the VirtIO 1.0 specification.
    186  * Struct names are the same. The field names have been adapted to VirtualBox
    187  * data type + camel case annotation, with the original field name from the
    188  * VirtIO specification in the field's comment.
    189  */
    190 
    191 /** @name VirtIO 1.0 SCSI Host feature bits
    192  * @{  */
    193 #define VIRTIO_SCSI_F_INOUT                         0      /** Request is device readable AND writeable */
    194 #define VIRTIO_SCSI_F_HOTPLUG                       1      /** Host SHOULD allow hotplugging SCSI LUNs & targets */
    195 #define VIRTIO_SCSI_F_CHANGE                        2      /** Host reports LUN changes via VIRTIO_SCSI_T_PARAM_CHANGE event */
    196 /** @} */
    197 
    198219#define CDB_SIZE                                    1      /* logic tbd */
    199220#define SENSE_SIZE                                  1      /* logic tbd */
     
    211232    uint8_t  uCdb[CDB_SIZE];                                /** cdb               */
    212233
    213     /** Following three fields only present if VIRTIO_SCSI_F_T10_PI negotiated */
     234    /** Following three fields only present if VIRTIOSCSI_F_T10_PI negotiated */
    214235
    215236    uint32_t uPiBytesOut;                                   /** pi_bytesout       */
     
    227248    uint8_t  uSense[SENSE_SIZE];                            /** sense             */
    228249
    229     /** Following two fields only present if VIRTIO_SCSI_F_T10_PI negotiated */
     250    /** Following two fields only present if VIRTIOSCSI_F_T10_PI negotiated */
    230251    uint8_t  uPiIn[PI_BYTES_IN];                            /** pi_in[]           */
    231252    uint8_t  uDataIn[];                                     /** detain;           */
     
    233254
    234255/** Command-specific response values */
    235 #define VIRTIO_SCSI_S_OK                            0       /* control, command   */
    236 #define VIRTIO_SCSI_S_OVERRUN                       1       /* control */
    237 #define VIRTIO_SCSI_S_ABORTED                       2       /* control */
    238 #define VIRTIO_SCSI_S_BAD_TARGET                    3       /* control, command */
    239 #define VIRTIO_SCSI_S_RESET                         4       /* control */
    240 #define VIRTIO_SCSI_S_BUSY                          5       /* control, command */
    241 #define VIRTIO_SCSI_S_TRANSPORT_FAILURE             6       /* control, command */
    242 #define VIRTIO_SCSI_S_TARGET_FAILURE                7       /* control, command */
    243 #define VIRTIO_SCSI_S_NEXUS_FAILURE                 8       /* control, command */
    244 #define VIRTIO_SCSI_S_FAILURE                       9       /* control, command */
    245 #define VIRTIO_SCSI_S_INCORRECT_LUN                12       /* command */
     256#define VIRTIOSCSI_S_OK                            0       /* control, command   */
     257#define VIRTIOSCSI_S_OVERRUN                       1       /* control */
     258#define VIRTIOSCSI_S_ABORTED                       2       /* control */
     259#define VIRTIOSCSI_S_BAD_TARGET                    3       /* control, command */
     260#define VIRTIOSCSI_S_RESET                         4       /* control */
     261#define VIRTIOSCSI_S_BUSY                          5       /* control, command */
     262#define VIRTIOSCSI_S_TRANSPORT_FAILURE             6       /* control, command */
     263#define VIRTIOSCSI_S_TARGET_FAILURE                7       /* control, command */
     264#define VIRTIOSCSI_S_NEXUS_FAILURE                 8       /* control, command */
     265#define VIRTIOSCSI_S_FAILURE                       9       /* control, command */
     266#define VIRTIOSCSI_S_INCORRECT_LUN                12       /* command */
    246267
    247268
    248269/** task_attr */
    249 #define VIRTIO_SCSI_S_SIMPLE                        0
    250 #define VIRTIO_SCSI_S_ORDERED                       1
    251 #define VIRTIO_SCSI_S_HEAD                          2
    252 #define VIRTIO_SCSI_S_ACA                           3
    253 
    254 #define VIRTIO_SCSI_T_TMF                           0
    255 #define VIRTIO_SCSI_T_TMF_ABORT_TASK                0
    256 #define VIRTIO_SCSI_T_TMF_ABORT_TASK_SET            1
    257 #define VIRTIO_SCSI_T_TMF_CLEAR_ACA                 2
    258 #define VIRTIO_SCSI_T_TMF_CLEAR_TASK_SET            3
    259 #define VIRTIO_SCSI_T_TMF_I_T_NEXUS_RESET           4
    260 #define VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET        5
    261 #define VIRTIO_SCSI_T_TMF_QUERY_TASK                6
    262 #define VIRTIO_SCSI_T_TMF_QUERY_TASK_SET            7
     270#define VIRTIOSCSI_S_SIMPLE                        0
     271#define VIRTIOSCSI_S_ORDERED                       1
     272#define VIRTIOSCSI_S_HEAD                          2
     273#define VIRTIOSCSI_S_ACA                           3
     274
     275#define VIRTIOSCSI_T_TMF                           0
     276#define VIRTIOSCSI_T_TMF_ABORT_TASK                0
     277#define VIRTIOSCSI_T_TMF_ABORT_TASK_SET            1
     278#define VIRTIOSCSI_T_TMF_CLEAR_ACA                 2
     279#define VIRTIOSCSI_T_TMF_CLEAR_TASK_SET            3
     280#define VIRTIOSCSI_T_TMF_I_T_NEXUS_RESET           4
     281#define VIRTIOSCSI_T_TMF_LOGICAL_UNIT_RESET        5
     282#define VIRTIOSCSI_T_TMF_QUERY_TASK                6
     283#define VIRTIOSCSI_T_TMF_QUERY_TASK_SET            7
    263284
    264285typedef struct virtio_scsi_ctrl_tmf
     
    275296/* command-specific response values */
    276297
    277 #define VIRTIO_SCSI_S_FUNCTION_COMPLETE            0
    278 #define VIRTIO_SCSI_S_FUNCTION_SUCCEEDED           10
    279 #define VIRTIO_SCSI_S_FUNCTION_REJECTED            11
    280 
    281 #define VIRTIO_SCSI_T_AN_QUERY                     1         /** Asynchronous notification query */
    282 #define VIRTIO_SCSI_T_AN_SUBSCRIBE                 2         /** Asynchronous notification subscription */
     298#define VIRTIOSCSI_S_FUNCTION_COMPLETE            0
     299#define VIRTIOSCSI_S_FUNCTION_SUCCEEDED           10
     300#define VIRTIOSCSI_S_FUNCTION_REJECTED            11
     301
     302#define VIRTIOSCSI_T_AN_QUERY                     1         /** Asynchronous notification query */
     303#define VIRTIOSCSI_T_AN_SUBSCRIBE                 2         /** Asynchronous notification subscription */
    283304
    284305typedef struct virtio_scsi_ctrl_an
     
    293314}  VIRTIOSCSICTRLAN, *PVIRTIOSCSICTRLAN;
    294315
    295 #define VIRTIO_SCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2
    296 #define VIRTIO_SCSI_EVT_ASYNC_POWER_MGMT          4
    297 #define VIRTIO_SCSI_EVT_ASYNC_EXTERNAL_REQUEST    8
    298 #define VIRTIO_SCSI_EVT_ASYNC_MEDIA_CHANGE        16
    299 #define VIRTIO_SCSI_EVT_ASYNC_MULTI_HOST          32
    300 #define VIRTIO_SCSI_EVT_ASYNC_DEVICE_BUSY         64
     316#define VIRTIOSCSI_EVT_ASYNC_OPERATIONAL_CHANGE  2
     317#define VIRTIOSCSI_EVT_ASYNC_POWER_MGMT          4
     318#define VIRTIOSCSI_EVT_ASYNC_EXTERNAL_REQUEST    8
     319#define VIRTIOSCSI_EVT_ASYNC_MEDIA_CHANGE        16
     320#define VIRTIOSCSI_EVT_ASYNC_MULTI_HOST          32
     321#define VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY         64
    301322
    302323/** Device operation: controlq */
     
    308329} VIRTIOSCSICTRL, *PVIRTIOSCSICTRL;
    309330
    310 #define VIRTIO_SCSI_T_NO_EVENT                   0
    311 
    312 #define VIRTIO_SCSI_T_TRANSPORT_RESET            1
    313 #define VIRTIO_SCSI_T_ASYNC_NOTIFY               2           /** Asynchronous notification */
    314 #define VIRTIO_SCSI_T_PARAM_CHANGE               3
    315 
    316 #define VIRTIO_SCSI_EVT_RESET_HARD               0
    317 #define VIRTIO_SCSI_EVT_RESET_RESCAN             1
    318 #define VIRTIO_SCSI_EVT_RESET_REMOVED            2
     331#define VIRTIOSCSI_T_NO_EVENT                   0
     332
     333#define VIRTIOSCSI_T_TRANSPORT_RESET            1
     334#define VIRTIOSCSI_T_ASYNC_NOTIFY               2           /** Asynchronous notification */
     335#define VIRTIOSCSI_T_PARAM_CHANGE               3
     336
     337#define VIRTIOSCSI_EVT_RESET_HARD               0
     338#define VIRTIOSCSI_EVT_RESET_RESCAN             1
     339#define VIRTIOSCSI_EVT_RESET_REMOVED            2
    319340
    320341/** Device operation: eventq */
    321342
    322 #define VIRTIO_SCSI_T_EVENTS_MISSED             0x80000000
     343#define VIRTIOSCSI_T_EVENTS_MISSED             0x80000000
    323344typedef struct virtio_scsi_event {
    324345    // Device-writable part
     
    352373}
    353374#endif
     375
     376/**
     377 * Turns on/off the write status LED.
     378 *
     379 * @returns VBox status code.
     380 * @param   pState          Pointer to the device state structure.
     381 * @param   fOn             New LED state.
     382 */
     383void virtioScsiSetWriteLed(PVIRTIOSCSITARGET pTarget, bool fOn)
     384{
     385    LogFlow(("%s virtioSetWriteLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
     386    if (fOn)
     387        pTarget->led.Asserted.s.fWriting = pTarget->led.Actual.s.fWriting = 1;
     388    else
     389        pTarget->led.Actual.s.fWriting = fOn;
     390}
     391
     392/**
     393 * Turns on/off the read status LED.
     394 *
     395 * @returns VBox status code.
     396 * @param   pState          Pointer to the device state structure.
     397 * @param   fOn             New LED state.
     398 */
     399void virtioScsiSetReadLed(PVIRTIOSCSITARGET pTarget, bool fOn)
     400{
     401    LogFlow(("%s virtioSetReadLed: %s\n", pTarget->pszLunName, fOn ? "on" : "off"));
     402    if (fOn)
     403        pTarget->led.Asserted.s.fReading = pTarget->led.Actual.s.fReading = 1;
     404    else
     405        pTarget->led.Actual.s.fReading = fOn;
     406}
    354407
    355408/**
     
    418471    return VINF_SUCCESS;
    419472}
    420 
    421 /**
    422  * Memory mapped I/O Handler for read operations.
    423  *
    424  * @returns VBox status code.
    425  *
    426  * @param   pDevIns     The device instance.
    427  * @param   pvUser      User argument.
    428  * @param   GCPhysAddr  Physical address (in GC) where the read starts.
    429  * @param   pv          Where to store the result.
    430  * @param   cb          Number of bytes read.
    431  */
    432 PDMBOTHCBDECL(int) virtioScsiMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    433 {
    434     RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
    435     LogFunc(("Read from MMIO area\n"));
    436     return VINF_SUCCESS;
    437 }
    438 
    439 /**
    440  * Memory mapped I/O Handler for write operations.
    441  *
    442  * @returns VBox status code.
    443  *
    444  * @param   pDevIns     The device instance.
    445  * @param   pvUser      User argument.
    446  * @param   GCPhysAddr  Physical address (in GC) where the read starts.
    447  * @param   pv          Where to fetch the result.
    448  * @param   cb          Number of bytes to write.
    449  */
    450 PDMBOTHCBDECL(int) virtioScsiMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    451 {
    452     RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
    453     LogFunc(("Write to MMIO area\n"));
    454     return VINF_SUCCESS;
    455 }
    456 
    457 /**
    458  * @callback_method_impl{FNPCIIOREGIONMAP}
    459  */
    460 static DECLCALLBACK(int) virtioScsiR3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
    461                                            RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
    462 {
    463     RT_NOREF(pPciDev, iRegion);
    464     PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    465     int rc = VINF_SUCCESS;
    466 
    467     Assert(cb >= 32);
    468 
    469     switch (iRegion)
    470     {
    471         case 0:
    472             LogFunc(("virtio-scsi controller MMIO mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
    473 
    474             /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
    475             rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    476                                    IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
    477                                    virtioScsiMMIOWrite, virtioScsiMMIORead,
    478                                    "virtio-scsi MMIO");
    479             pThis->GCPhysMMIOBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;
    480             return rc;
    481         case 1:
    482             /* VirtIO 1.0 doesn't uses Port I/O (Virtio 0.95 e.g. "legacy", does) */
    483             AssertMsgFailed(("virtio-scsi: Port I/O not supported by this Host SCSI device\n"));
    484         default:
    485             AssertMsgFailed(("Invalid enmType=%d\n", enmType));
    486     }
    487     return VERR_GENERAL_FAILURE; /* Should never get here */
    488 }
    489 
    490473
    491474/**
     
    654637
    655638    if (pThis->pMediaNotify)
    656         virtioSetWriteLed(&(pThis->virtioState), false);
    657 }
    658 
     639        virtioScsiSetWriteLed(pTarget, false);
     640}
    659641
    660642/**
     
    680662
    681663/**
     664 * Gets the pointer to the status LED of a unit.
     665 *
     666 * @returns VBox status code.
     667 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     668 * @param   iLUN            The unit which status LED we desire.
     669 * @param   ppLed           Where to store the LED pointer.
     670 */
     671static DECLCALLBACK(int) virtioScsiR3TargetQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
     672{
     673    PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, ILed);
     674    if (iLUN == 0)
     675    {
     676        *ppLed = &pTarget->led;
     677        Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
     678        return VINF_SUCCESS;
     679    }
     680    return VERR_PDM_LUN_NOT_FOUND;
     681  }
     682
     683
     684/**
     685 * Gets the pointer to the status LED of a unit.
     686 *
     687 * @returns VBox status code.
     688 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
     689 * @param   iLUN            The unit which status LED we desire.
     690 * @param   ppLed           Where to store the LED pointer.
     691 */
     692static DECLCALLBACK(int) virtioScsiR3DeviceQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
     693{
     694    PVIRTIOSCSI pThis = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, ILeds);
     695    if (iLUN < pThis->cTargets)
     696    {
     697        *ppLed = &pThis->aTargetInstances[iLUN].led;
     698        Assert((*ppLed)->u32Magic == PDMLED_MAGIC);
     699        return VINF_SUCCESS;
     700    }
     701    return VERR_PDM_LUN_NOT_FOUND;
     702}
     703
     704/**
     705 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
     706 */
     707static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     708{
     709     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
     710     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE,        &pTarget->IBase);
     711     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT,   &pTarget->IMediaPort);
     712     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);
     713     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS,    &pTarget->ILed);
     714     return NULL;
     715}
     716
     717/**
    682718 * virtio-scsi VirtIO Device-specific capabilities read callback
    683719 * (other VirtIO capabilities and features are handled in VirtIO implementation)
     
    691727{
    692728/*TBD*/
    693     LogFlowFunc(("Read from Device-Specific capabilities, callback to VirtIO client\n"));
     729    LogFunc(("Read from Device-Specific capabilities\n"));
    694730    RT_NOREF(pDevIns);
    695731    RT_NOREF(GCPhysAddr);
     
    712748{
    713749/*TBD*/
    714     LogFlowFunc(("Write to Device-Specific capabilities, callback to VirtIO client\n"));
     750    LogFunc(("Write to Device-Specific capabilities\n"));
    715751    RT_NOREF(pDevIns);
    716752    RT_NOREF(GCPhysAddr);
     
    721757}
    722758
     759
     760/**
     761 * Memory mapped I/O Handler for read operations.
     762 *
     763 * @returns VBox status code.
     764 *
     765 * @param   pDevIns     The device instance.
     766 * @param   pvUser      User argument.
     767 * @param   GCPhysAddr  Physical address (in GC) where the read starts.
     768 * @param   pv          Where to store the result.
     769 * @param   cb          Number of bytes read.
     770 */
     771PDMBOTHCBDECL(int) virtioScsiMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
     772{
     773    RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
     774    LogFunc(("Read from MMIO area\n"));
     775    return VINF_SUCCESS;
     776}
     777
     778/**
     779 * Memory mapped I/O Handler for write operations.
     780 *
     781 * @returns VBox status code.
     782 *
     783 * @param   pDevIns     The device instance.
     784 * @param   pvUser      User argument.
     785 * @param   GCPhysAddr  Physical address (in GC) where the read starts.
     786 * @param   pv          Where to fetch the result.
     787 * @param   cb          Number of bytes to write.
     788 */
     789PDMBOTHCBDECL(int) virtioScsiMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
     790{
     791    RT_NOREF_PV(pDevIns); RT_NOREF_PV(pvUser); RT_NOREF_PV(GCPhysAddr); RT_NOREF_PV(pv); RT_NOREF_PV(cb);
     792    LogFunc(("Write to MMIO area\n"));
     793    return VINF_SUCCESS;
     794}
     795
     796/**
     797 * @callback_method_impl{FNPCIIOREGIONMAP}
     798 */
     799static DECLCALLBACK(int) virtioScsiR3Map(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
     800                                           RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
     801{
     802    RT_NOREF(pPciDev, iRegion);
     803    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
     804    int rc = VINF_SUCCESS;
     805
     806    Assert(cb >= 32);
     807
     808    switch (iRegion)
     809    {
     810        case 0:
     811            LogFunc(("virtio-scsi MMIO mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
     812
     813            /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
     814            rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
     815                                   IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
     816                                   virtioScsiMMIOWrite, virtioScsiMMIORead,
     817                                   "virtio-scsi MMIO");
     818            pThis->GCPhysMMIOBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;
     819            return rc;
     820        case 1:
     821            /* VirtIO 1.0 doesn't uses Port I/O (Virtio 0.95 e.g. "legacy", does) */
     822            AssertMsgFailed(("virtio-scsi: Port I/O not supported by this Host SCSI device\n"));
     823        default:
     824            AssertMsgFailed(("Invalid enmType=%d\n", enmType));
     825    }
     826    return VERR_GENERAL_FAILURE; /* Should never get here */
     827}
     828
     829/**
     830 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
     831 */
     832static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
     833{
     834    PVIRTIOSCSI pVirtioScsi = RT_FROM_MEMBER(pInterface, VIRTIOSCSI, IBase);
     835
     836    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE,         &pVirtioScsi->IBase);
     837    PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS,     &pVirtioScsi->ILeds);
     838
     839    return NULL;
     840}
     841
     842
    723843/**
    724844 * Detach notification.
     
    737857    PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
    738858
    739     Log(("%s:\n", __FUNCTION__));
     859    LogFunc((""));
    740860
    741861    AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG,
     
    746866     */
    747867    pTarget->fPresent    = false;
    748     pTarget->pUpstreamDrvBase    = NULL;
    749 }
    750 
    751 
    752 /**
    753  * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    754  */
    755 static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    756 {
    757     PPDMDRVINS pDevIns = PDMIBASE_2_PDMDRV(pInterface);
    758     PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);
    759     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDevIns->IBase);
    760     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort);
    761     PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);
    762 
    763     /* This call back is necessary to get Status / LED support */
    764     return virtioQueryInterface(pInterface, pszIID);
    765 
    766     return NULL;
     868    pTarget->pDrvBase    = NULL;
    767869}
    768870
     
    792894
    793895    /* the usual paranoia */
    794     AssertRelease(!pTarget->pUpstreamDrvBase);
     896    AssertRelease(!pTarget->pDrvBase);
    795897    Assert(pTarget->iLUN == iLUN);
    796898
     
    800902     */
    801903    rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iLUN, &pDevIns->IBase,
    802                                &pTarget->pUpstreamDrvBase, (const char *)&pTarget->pszLunName);
     904                               &pTarget->pDrvBase, (const char *)&pTarget->pszLunName);
    803905    if (RT_SUCCESS(rc))
    804906        pTarget->fPresent = true;
     
    809911    {
    810912        pTarget->fPresent = false;
    811         pTarget->pUpstreamDrvBase = NULL;
     913        pTarget->pDrvBase = NULL;
    812914    }
    813915    return rc;
     
    823925}
    824926
    825 static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
    826 {
     927static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg){
    827928
    828929    PDMDEV_CHECK_VERSIONS_RETURN(pDevIns);
     930
    829931    PVIRTIOSCSI  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);
    830932    int  rc = VINF_SUCCESS;
    831933    bool fBootable = true;
     934
     935    pThis->pDevInsR3 = pDevIns;
     936    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     937    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
    832938
    833939    LogFunc(("PDM device instance: %d\n", iInstance));
     
    857963
    858964    VIRTIOPCIPARAMS virtioPciParams, *pVirtioPciParams = &virtioPciParams;
    859     pVirtioPciParams->uDeviceId      = PCI_DEVICE_ID_VIRTIO_SCSI_HOST;
     965    pVirtioPciParams->uDeviceId      = PCI_DEVICE_ID_VIRTIOSCSI_HOST;
    860966    pVirtioPciParams->uClassBase     = PCI_CLASS_BASE_MASS_STORAGE;
    861967    pVirtioPciParams->uClassSub      = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER;
    862968    pVirtioPciParams->uClassProg     = PCI_CLASS_PROG_UNSPECIFIED;
    863     pVirtioPciParams->uSubsystemId   = PCI_DEVICE_ID_VIRTIO_SCSI_HOST;  /* Virtio 1.0 spec allows PCI Device ID here */
     969    pVirtioPciParams->uSubsystemId   = PCI_DEVICE_ID_VIRTIOSCSI_HOST;  /* Virtio 1.0 spec allows PCI Device ID here */
    864970    pVirtioPciParams->uInterruptLine = 0x00;
    865971    pVirtioPciParams->uInterruptPin  = 0x01;
    866972
    867973    PVIRTIOSTATE pVirtio = &(pThis->virtioState);
    868     pDevIns->IBase.pfnQueryInterface = virtioScsiR3DeviceQueryInterface;
    869 
    870     rc = virtioConstruct(pDevIns, pVirtio, iInstance, pVirtioPciParams,
    871                          VIRTIO_SCSI_NAME_FMT, VIRTIO_SCSI_N_QUEUES, VIRTIO_SCSI_REGION_PCI_CAP,
    872                          virtioScsiR3DevCapRead, virtioScsiR3DevCapWrite, sizeof(VIRTIODEVCAP));
     974
     975    pThis->IBase.pfnQueryInterface = virtioScsiR3DeviceQueryInterface;
     976    rc = virtioConstruct(pDevIns, pVirtio, iInstance, pVirtioPciParams, &pThis->pVirtioCallbacks,
     977                         VIRTIOSCSI_NAME_FMT, VIRTIOSCSI_N_QUEUES, VIRTIOSCSI_REGION_PCI_CAP,
     978                         virtioScsiR3DevCapRead, virtioScsiR3DevCapWrite,
     979                        0 /* cbDevSpecificCap */,
     980                        0 /* uNotifyOffMultiplier */);
     981
     982
    873983    if (RT_FAILURE(rc))
    874984        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO"));
    875985
    876     rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIO_SCSI_REGION_MEM_IO, 32,
     986    pThis->pVirtioCallbacks->pfnSetHostFeatures(pVirtio, VIRTIOSCSI_HOST_SCSI_FEATURES_OFFERED);
     987
     988    rc = PDMDevHlpPCIIORegionRegister(pDevIns, VIRTIOSCSI_REGION_MEM_IO, 32,
    877989                                      PCI_ADDRESS_SPACE_MEM, virtioScsiR3Map);
    878990    if (RT_FAILURE(rc))
     
    9031015        PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN];
    9041016
    905         if (RTStrAPrintf(&pTarget->pszLunName, "VIRTIOSCSI%u", iLUN) < 0)
     1017        if (RTStrAPrintf(&pTarget->pszLunName, "vSCSI%u", iLUN) < 0)
    9061018            AssertLogRelFailedReturn(VERR_NO_MEMORY);
    9071019
     
    9091021        pTarget->iLUN = iLUN;
    9101022        pTarget->pVirtioScsiR3 = pThis;
     1023
     1024        pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
     1025
    9111026        /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */
    9121027        pTarget->IMediaPort.pfnQueryDeviceLocation       = virtioScsiR3QueryDeviceLocation;
     
    9181033        pTarget->IMediaExPort.pfnIoReqQueryBuf           = NULL;
    9191034        pTarget->IMediaExPort.pfnIoReqQueryDiscardRanges = NULL;
     1035        pTarget->IBase.pfnQueryInterface                 = virtioScsiR3TargetQueryInterface;
     1036        pTarget->ILed.pfnQueryStatusLed                  = virtioScsiR3TargetQueryStatusLed;
     1037        pThis->ILeds.pfnQueryStatusLed                   = virtioScsiR3DeviceQueryStatusLed;
     1038        pTarget->led.u32Magic                            = PDMLED_MAGIC;
    9201039
    9211040        LogFunc(("Attaching LUN: %s\n", pTarget->pszLunName));
     
    9231042        /* Attach this SCSI driver (upstream driver pre-determined statically outside this module) */
    9241043        AssertReturn(iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN);
    925         rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pDevIns->IBase, &pTarget->pUpstreamDrvBase, (const char *)&pTarget->pszLunName);
     1044        rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszLunName);
    9261045        if (RT_SUCCESS(rc))
    9271046        {
    9281047            pTarget->fPresent = true;
    9291048
    930             pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pUpstreamDrvBase, PDMIMEDIA);
     1049            pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA);
    9311050            AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia),
    9321051                         ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->iLUN),
    9331052                         VERR_PDM_MISSING_INTERFACE);
    9341053
    935              /* Get the extended media interface. */
    936              pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pUpstreamDrvBase, PDMIMEDIAEX);
    937              AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
     1054            /* Get the extended media interface. */
     1055            pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIAEX);
     1056            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
    9381057                         ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->iLUN),
    9391058                         VERR_PDM_MISSING_INTERFACE);
    9401059
    941 // pk: Not sure if this is needed here yet with VirtIO or DrvScsi, will investigate after basic VirtIO working.
    942 //            rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, sizeof(BUSLOGICREQ));
    943 //             AssertMsgRCReturn(rc, ("BusLogic configuration error: LUN#%u: Failed to set I/O request size!", pTarget->iLUN),
     1060            rc = pTarget->pDrvMediaEx->pfnIoReqAllocSizeSet(pTarget->pDrvMediaEx, REQ_ALLOC_SIZE /*TBD*/);
     1061            AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx),
     1062                         ("virtio-scsi configuration error: LUN#%u: Failed to set I/O request size!\n", pTarget->iLUN),
     1063                         rc);
    9441064
    9451065        }
     
    9471067        {
    9481068            pTarget->fPresent = false;
    949             pTarget->pUpstreamDrvBase = NULL;
     1069            pTarget->pDrvBase = NULL;
    9501070            rc = VINF_SUCCESS;
    9511071            Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszLunName));
     
    9641084    if (RT_FAILURE(rc))
    9651085        return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi cannot register save state handlers"));
     1086
     1087    /* Status driver */
     1088    PPDMIBASE pUpBase;
     1089    rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pThis->IBase, &pUpBase, "Status Port");
     1090    if (RT_FAILURE(rc))
     1091        return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the status LUN"));
     1092
    9661093    /*
    9671094     * Register the debugger info callback.
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