VirtualBox

Changeset 80058 in vbox


Ignore:
Timestamp:
Jul 30, 2019 8:17:49 AM (5 years ago)
Author:
vboxsync
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)

Location:
trunk/src/VBox/Devices
Files:
3 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.
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp

    r79973 r80058  
    3535# define QUEUENAME(s, q) (q->pcszName)
    3636#endif
     37
     38/* These ACCESSOR macros handle the most basic kinds of MMIO accesses to fields
     39 * virtio 1.0 spec's virtio_pci_common_cfg  avoiding a lot of visual bloat.
     40 */
     41
     42 /**
     43  * If the physical address and access length is within the mapped capability struct
     44  * the ptrByType will be set to the mapped capability start. Otherwise ptrByType will be NULL.
     45  *
     46  * Implied parameters:
     47  *     GPhysAddr   - Physical address accessed (via MMIO callback)
     48  *     cb          - Number of bytes to access
     49  *
     50  * Actual Parameters:
     51  *     [IN]  pCapStruct - Pointer to MMIO mapped capability struct
     52  *     [IN]  type       - Capability struct type
     53  *     [OUT] result     - A pointer of type capType that will be set to a mapped capability
     54  *                       if phys. addr / access len is within it's span.
     55  *     [OUT] offset     - The offset of the physical address into the capability if applicable.
     56  */
     57
     58#define MATCH_VIRTIO_CAP_STRUCT(pCapStruct, type, result, offset) \
     59        type *result = NULL; \
     60        if (   GCPhysAddr >= (RTGCPHYS)pCapStruct \
     61            && GCPhysAddr < ((RTGCPHYS)pCapStruct + sizeof(type)) \
     62            && cb <= sizeof(type)) \
     63        { \
     64            offset = GCPhysAddr - (RTGCPHYS)pCapStruct; \
     65            result = (type *)pCapStruct; \
     66        }
     67
     68#define LOG_ACCESSOR(member, type) \
     69        LogFunc(("Guest %s 0x%x %s %s\n", fWrite ? "wrote" : "read ", \
     70                 *(type *)pv, fWrite ? "  to" : "from", #member));
     71
     72#define LOG_INDEXED_ACCESSOR(member, type, idx) \
     73        LogFunc(("Guest %s 0x%x %s %s[%d]\n", fWrite ? "wrote" : "read ", \
     74                 *(type *)pv, fWrite ? "  to" : "from", #member, idx));
     75
     76#define ACCESSOR(member, type) \
     77    { \
     78        if (fWrite) \
     79        { \
     80            pVirtio->member = *(type *)pv; \
     81        } \
     82        else \
     83        { \
     84            *(type *)pv = pVirtio->member; \
     85        } \
     86        LOG_ACCESSOR(member, type); \
     87    }
     88#define ACCESSOR_WITH_IDX(member, type, idx) \
     89    { \
     90        if (fWrite) \
     91        { \
     92            pVirtio->member[idx] = *(type *)pv; \
     93        } \
     94        else \
     95        { \
     96            *(type *)pv = pVirtio->member[idx]; \
     97        } \
     98        LOG_INDEXED_ACCESSOR(member, type, idx); \
     99    }
     100
     101#define ACCESSOR_READONLY(member, type) \
     102    { \
     103        if (fWrite) \
     104        { \
     105            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s\n", #member)); \
     106            AssertMsgFailed(("bad access\n")); \
     107        } \
     108        else \
     109        { \
     110            *(type *)pv = pVirtio->member; \
     111            LOG_ACCESSOR(member, type); \
     112        } \
     113    }
     114
     115#define ACCESSOR_READONLY_WITH_IDX(member, type, idx) \
     116    { \
     117        if (fWrite) \
     118        { \
     119            LogFunc(("Guest attempted to write readonly virtio_pci_common_cfg.%s[%d]\n", #member, idx)); \
     120            AssertMsgFailed(("bad access\n")); \
     121        } \
     122        else \
     123        { \
     124            *(type *)pv = pVirtio->member[idx]; \
     125            LOG_INDEXED_ACCESSOR(member, type, idx); \
     126        } \
     127    }
     128
    37129
    38130#ifdef VBOX_DEVICE_STRUCT_TESTCASE
     
    316408}
    317409
    318 void virtioReset(PVIRTIOSTATE pState)
    319 {
    320 
    321     RT_NOREF(pState);
    322 /* PK TODO Adapt to VirtIO 1.0
     410int virtioReset(PVIRTIOSTATE pVirtio)
     411{
     412    RT_NOREF(pVirtio);
     413/* PK TODO Adapt to VirtIO 1.09
    323414    pState->uGuestFeatures = 0;
    324415    pState->uQueueSelector = 0;
     
    329420        virtQueueReset(&pState->Queues[i]);
    330421*/
     422    virtioNotify(pVirtio);
     423    return VINF_SUCCESS;
    331424}
    332425
     
    374467
    375468#ifdef IN_RING3
    376 
    377 /**
    378  * Gets the pointer to the status LED of a unit.
    379  *
    380  * @returns VBox status code.
    381  * @param   pInterface      Pointer to the interface structure.
    382  * @param   iLUN            The unit which status LED we desire.
    383  * @param   ppLed           Where to store the LED pointer.
    384  * @thread  EMT
    385  */
    386 static DECLCALLBACK(int) virtioQueryStatusLed(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed)
    387 {
    388     VIRTIOSTATE *pState = IFACE_TO_STATE(pInterface, ILeds);
    389     int rc = VERR_PDM_LUN_NOT_FOUND;
    390 
    391     if (iLUN == 0)
    392     {
    393         *ppLed = &pState->led;
    394         rc     = VINF_SUCCESS;
    395     }
    396     return rc;
    397 }
    398 
    399 /**
    400  * Turns on/off the write status LED.
    401  *
    402  * @returns VBox status code.
    403  * @param   pState          Pointer to the device state structure.
    404  * @param   fOn             New LED state.
    405  */
    406 void virtioSetWriteLed(PVIRTIOSTATE pState, bool fOn)
    407 {
    408     LogFlow(("%s virtioSetWriteLed: %s\n", INSTANCE(pState), fOn ? "on" : "off"));
    409     if (fOn)
    410         pState->led.Asserted.s.fWriting = pState->led.Actual.s.fWriting = 1;
    411     else
    412         pState->led.Actual.s.fWriting = fOn;
    413 }
    414 
    415 /**
    416  * Turns on/off the read status LED.
    417  *
    418  * @returns VBox status code.
    419  * @param   pState          Pointer to the device state structure.
    420  * @param   fOn             New LED state.
    421  */
    422 void virtioSetReadLed(PVIRTIOSTATE pState, bool fOn)
    423 {
    424     LogFlow(("%s virtioSetReadLed: %s\n", INSTANCE(pState), fOn ? "on" : "off"));
    425     if (fOn)
    426         pState->led.Asserted.s.fReading = pState->led.Actual.s.fReading = 1;
    427     else
    428         pState->led.Actual.s.fReading = fOn;
    429 }
    430469
    431470
     
    575614}
    576615
     616void virtioNotify(PVIRTIOSTATE pVirtio)
     617{
     618    RT_NOREF(pVirtio);
     619}
     620
     621static void virtioResetDevice(PVIRTIOSTATE pVirtio)
     622{
     623    RT_NOREF(pVirtio);
     624    LogFunc((""));
     625    pVirtio->uDeviceStatus = 0;
     626}
     627
     628/**
     629 * Handle accesses to Common Configuration capability
     630 *
     631 * @returns VBox status code
     632 *
     633 * @param   pVirtio     Virtio instance state
     634 * @param   fWrite      If write access (otherwise read access)
     635 * @param   pv          Pointer to location to write to or read from
     636 * @param   cb          Number of bytes to read or write
     637 */
     638int virtioCommonCfgAccessed(PVIRTIOSTATE pVirtio, int fWrite, off_t uoff, void const *pv)
     639{
     640    int rv = VINF_SUCCESS;
     641    if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeature))
     642    {
     643        if (fWrite) /* Guest WRITE pCommonCfg->uDeviceFeature */
     644        {
     645            AssertMsgFailed(("Guest attempted to write readonly virtio_pci_common_cfg.device_feature\n"));
     646        }
     647        else /* Guest WRITE pCommonCfg->uDeviceFeature */
     648        {
     649            switch(pVirtio->uFeaturesOfferedSelect)
     650            {
     651                case 0:
     652                    pVirtio->uFeaturesOffered = *(uint32_t *)pv;
     653                    LOG_ACCESSOR(uFeaturesOffered, uint32_t);
     654                    break;
     655                case 1:
     656                    pVirtio->uFeaturesOffered = (uint64_t)(*(uint32_t *)pv) << 32;
     657                    LOG_ACCESSOR(uFeaturesOffered, uint32_t);
     658                    break;
     659                default:
     660                    Log(("Guest selected out of range pVirtio->uDeviceFeature (%d), returning 0\n",
     661                        pVirtio->uFeaturesOfferedSelect));
     662            }
     663        }
     664    }
     665    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeature))
     666    {
     667        if (fWrite) /* Guest WRITE pCommonCfg->uDriverFeature */
     668        {
     669            switch(pVirtio->uFeaturesOfferedSelect)
     670            {
     671                case 0:
     672                    pVirtio->uFeaturesAccepted = *(uint32_t *)pv;
     673                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     674                    break;
     675                case 1:
     676                    pVirtio->uFeaturesAccepted = (uint64_t)(*(uint32_t *)pv) << 32;
     677                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     678                    break;
     679            }
     680        }
     681        else /* Guest READ pCommonCfg->uDriverFeature */
     682        {
     683            switch(pVirtio->uFeaturesOfferedSelect)
     684            {
     685                case 0:
     686                    *(uint32_t *)pv = pVirtio->uFeaturesAccepted & 0xffffffff;
     687                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     688                    break;
     689                case 1:
     690                    *(uint32_t *)pv = (pVirtio->uFeaturesAccepted >> 32) & 0xffffffff;
     691                    LOG_ACCESSOR(uFeaturesAccepted, uint32_t);
     692                    break;
     693            }
     694        }
     695    }
     696    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uNumQueues))
     697    {
     698        if (fWrite)
     699        {
     700            AssertMsgFailed(("Guest attempted to write readonly virtio_pci_common_cfg.num_queues\n"));
     701        }
     702        else
     703        {
     704            *(uint16_t *)pv = MAX_QUEUES;
     705            Log(("Guest read 0x%x from pVirtio->uNumQueues\n", MAX_QUEUES));
     706        }
     707    }
     708    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceStatus))
     709    {
     710        if (fWrite) /* Guest WRITE pCommonCfg->uDeviceStatus */
     711        {
     712            pVirtio->uDeviceStatus = *(uint8_t *)pv;
     713            LogFunc(("Driver wrote uDeviceStatus:\n"));
     714            showDeviceStatus(pVirtio->uDeviceStatus);
     715            if (pVirtio->uDeviceStatus == 0)
     716                virtioResetDevice(pVirtio);
     717        }
     718        else /* Guest READ pCommonCfg->uDeviceStatus */
     719        {
     720            LogFunc(("Driver read uDeviceStatus:\n"));
     721            *(uint32_t *)pv = pVirtio->uDeviceStatus;
     722            showDeviceStatus(pVirtio->uDeviceStatus);
     723        }
     724    }
     725    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uMsixConfig))
     726    {
     727        ACCESSOR(uMsixConfig, uint32_t);
     728    }
     729    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDeviceFeatureSelect))
     730    {
     731        ACCESSOR(uFeaturesOfferedSelect, uint32_t);
     732    }
     733    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uDriverFeatureSelect))
     734    {
     735        ACCESSOR(uFeaturesAcceptedSelect, uint32_t);
     736    }
     737    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uConfigGeneration))
     738    {
     739        ACCESSOR_READONLY(uConfigGeneration, uint8_t);
     740    }
     741    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueSelect))
     742    {
     743        ACCESSOR(uQueueSelect, uint16_t);
     744    }
     745    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueSize))
     746    {
     747        ACCESSOR_WITH_IDX(uQueueSize, uint16_t, pVirtio->uQueueSelect);
     748    }
     749    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueMsixVector))
     750    {
     751        ACCESSOR_WITH_IDX(uQueueMsixVector, uint16_t, pVirtio->uQueueSelect);
     752    }
     753    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueEnable))
     754    {
     755        ACCESSOR_WITH_IDX(uQueueEnable, uint16_t, pVirtio->uQueueSelect);
     756    }
     757    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueNotifyOff))
     758    {
     759        ACCESSOR_READONLY_WITH_IDX(uQueueNotifyOff, uint16_t, pVirtio->uQueueSelect);
     760    }
     761    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueDesc))
     762    {
     763        ACCESSOR_WITH_IDX(uQueueDesc, uint64_t, pVirtio->uQueueSelect);
     764    }
     765    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueAvail))
     766    {
     767        ACCESSOR_WITH_IDX(uQueueAvail, uint64_t, pVirtio->uQueueSelect);
     768    }
     769    else if (uoff == RT_OFFSETOF(VIRTIO_PCI_COMMON_CFG_T, uQueueUsed))
     770    {
     771        ACCESSOR_WITH_IDX(uQueueUsed, uint64_t, pVirtio->uQueueSelect);
     772    }
     773    else
     774    {
     775
     776        AssertMsgFailed(("virtio: Bad common cfg offset   \n"));
     777    }
     778    return rv;
     779}
    577780
    578781/**
     
    587790 * @param   cb          Number of bytes read.
    588791 */
    589 PDMBOTHCBDECL(int) virtioPciCapMemRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
    590 {
    591 /* PK New feature! */
    592 
     792PDMBOTHCBDECL(int) virtioR3MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
     793{
    593794    RT_NOREF(pvUser);
     795    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    594796    int rc = VINF_SUCCESS;
    595797
    596     LogFunc(("Read (MMIO) VirtIO capabilities\n"));
    597     PVIRTIOSTATE pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    598 
    599     /* TBD: This should be called only if VIRTIO_PCI_CAP_DEVICE_CFG capability is being accessed */
    600     rc = pThis->pfnVirtioDevCapRead(pDevIns, GCPhysAddr, pv, cb);
     798//#ifdef LOG_ENABLED
     799//    LogFlowFunc(("pVirtio=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pVirtio, GCPhysAddr, pv, cb, pv, cb));
     800//#endif
     801    off_t uoff = 0;
     802    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysCommonCfg, VIRTIO_PCI_COMMON_CFG_T, pCommonCfg,  uoff);
     803    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysIsrCap,    VIRTIO_PCI_ISR_CAP_T,    pIsrCap,     uoff);
     804#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     805    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysDeviceCap, VIRTIO_PCI_DEVICE_CAP_T, pDeviceCap,  uoff);
     806#endif
     807    /* Note: The notify capability is handled differently as per VirtIO 1.0 spec 4.1.4.4 */
     808
     809    if (pCommonCfg)
     810        virtioCommonCfgAccessed(pVirtio, 0 /* fWrite */, uoff, pv);
     811    else if (pIsrCap)
     812    {
     813        *(uint8_t *)pv = pVirtio->fQueueInterrupt | pVirtio->fDeviceConfigInterrupt << 1;
     814        LogFunc(("Read 0x%s from pIsrCap\n", *(uint8_t *)pv));
     815    }
     816#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     817    else if (pDeviceCap)
     818        rc = pThis->pfnVirtioDevCapRead(pDevIns, GCPhysAddr, pv, cb);
     819#endif
     820    else
     821        AssertMsgFailed(("virtio: Write outside of capabilities region\n"));
     822
    601823    return rc;
    602824}
    603 
    604 
     825#if TBD
     826/**
     827  * Callback function for reading from the PCI configuration space.
     828  *
     829  * @returns The register value.
     830  * @param   pDevIns         Pointer to the device instance the PCI device
     831  *                          belongs to.
     832  * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
     833  * @param   uAddress        The configuration space register address. [0..4096]
     834  * @param   cb              The register size. [1,2,4]
     835  *
     836  * @remarks Called with the PDM lock held.  The device lock is NOT take because
     837  *          that is very likely be a lock order violation.
     838  */
     839static DECLCALLBACK(uint32_t) virtioPciConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
     840                                       uint32_t uAddress, unsigned cb)
     841{
     842    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
     843    int rc = VINF_SUCCESS;
     844
     845    LogFunc(("uAddress: %d, uPciConfigDataOffset: %d\n", uAddress, pVirtio->uPciConfigDataOffset));
     846
     847    if (uAddress == pVirtio->uPciConfigDataOffset)
     848        Log(("Read uPciConfigDataOffset\n"));
     849    rc = pVirtio->pfnPciConfigReadOld(pDevIns, pPciDev, uAddress, cb);
     850    return rc;
     851
     852}
     853
     854/**
     855 * Callback function for writing to the PCI configuration space.
     856 *
     857 * @returns VINF_SUCCESS or PDMDevHlpDBGFStop status.
     858 *
     859 * @param   pDevIns         Pointer to the device instance the PCI device
     860 *                          belongs to.
     861 * @param   pPciDev         Pointer to PCI device. Use pPciDev->pDevIns to get the device instance.
     862 * @param   uAddress        The configuration space register address. [0..4096]
     863 * @param   u32Value        The value that's being written. The number of bits actually used from
     864 *                          this value is determined by the cb parameter.
     865 * @param   cb              The register size. [1,2,4]
     866 *
     867 * @remarks Called with the PDM lock held.  The device lock is NOT take because
     868 *          that is very likely be a lock order violation.
     869 */
     870static DECLCALLBACK(VBOXSTRICTRC) virtioPciConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
     871                                        uint32_t uAddress, uint32_t u32Value, unsigned cb)
     872{
     873    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
     874    VBOXSTRICTRC strictRc;
     875
     876    LogFunc(("uAddress: %d, uPciConfigDataOffset: %d\n", uAddress, pVirtio->uPciConfigDataOffset));
     877    if (uAddress == pVirtio->uPciConfigDataOffset)
     878        Log(("Wrote uPciConfigDataOffset\n"));
     879    strictRc = pVirtio->pfnPciConfigWriteOld(pDevIns, pPciDev, uAddress, u32Value, cb);
     880    return strictRc;
     881}
     882#endif
    605883/**
    606884 * Memory mapped I/O Handler for PCI Capabilities write operations.
     
    614892 * @param   cb          Number of bytes to write.
    615893 */
    616 PDMBOTHCBDECL(int) virtioPciCapMemWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
    617 {
    618 
    619 /* PK New feature! */
     894PDMBOTHCBDECL(int) virtioR3MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
     895{
     896
    620897    RT_NOREF(pvUser);
     898    PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    621899    int rc = VINF_SUCCESS;
    622     LogFunc(("Write (MMIO) Virtio capabilities\n"));
    623     PVIRTIOSTATE pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    624 
    625     /* TBD: This should be called only if VIRTIO_PCI_CAP_DEVICE_CFG capability is being accessed */
    626     rc = pThis->pfnVirtioDevCapWrite(pDevIns, GCPhysAddr, pv,cb);
     900
     901#ifdef LOG_ENABLED
     902//    LogFunc(("pVirtio=%#p GCPhysAddr=%RGp pv=%#p{%.*Rhxs} cb=%u\n", pVirtio, GCPhysAddr, pv, cb, pv, cb));
     903#endif
     904    off_t uoff = 0;
     905
     906    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysCommonCfg, VIRTIO_PCI_COMMON_CFG_T, pCommonCfg,  uoff);
     907    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysIsrCap,    VIRTIO_PCI_ISR_CAP_T,    pIsrCap,     uoff);
     908#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     909    MATCH_VIRTIO_CAP_STRUCT(pVirtio->pGcPhysDeviceCap, VIRTIO_PCI_DEVICE_CAP_T, pDeviceCap,  uoff);
     910#endif
     911
     912    if (pCommonCfg)
     913        virtioCommonCfgAccessed(pVirtio, 1 /* fWrite */, uoff, pv);
     914    else if (pIsrCap)
     915    {
     916        pVirtio->fQueueInterrupt = (*(uint8_t *)pv) & 1;
     917        pVirtio->fDeviceConfigInterrupt = !!(*((uint8_t *)pv) & 2);
     918        Log(("pIsrCap... setting fQueueInterrupt=%d fDeviceConfigInterrupt=%d\n",
     919              pVirtio->fQueueInterrupt, pVirtio->fDeviceConfigInterrupt));
     920    }
     921#if HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     922    else if (pDeviceCap)
     923        rc = pThis->pfnVirtioDevCapWrite(pDevIns, GCPhysAddr, pv, cb);
     924#endif
     925    else
     926        AssertMsgFailed(("virtio: Write outside of capabilities region\n"));
    627927
    628928    return rc;
    629929}
     930
    630931
    631932/**
     
    636937{
    637938    RT_NOREF3(pPciDev, iRegion, enmType);
    638     PVIRTIOSTATE  pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
     939    PVIRTIOSTATE  pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);
    639940    int rc = VINF_SUCCESS;
    640941
    641942    Assert(cb >= 32);
    642 
    643     LogFunc(("virtIO controller PCI Capabilities mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));
    644943
    645944    /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */
    646945    rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/,
    647946                           IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
    648                            virtioPciCapMemWrite, virtioPciCapMemRead,
     947                           virtioR3MmioWrite, virtioR3MmioRead,
    649948                           "virtio-scsi MMIO");
    650     pThis->GCPhysPciCapBase = RT_SUCCESS(rc) ? GCPhysAddress : 0;
     949
     950    LogFunc(("virtio: PCI Capabilities mapped at GCPhysAddr=%RGp cb=%RGp, region=%d\n", GCPhysAddress, cb, iRegion));
     951
     952    if (RT_SUCCESS(rc))
     953    {
     954        pVirtio->GCPhysPciCapBase = GCPhysAddress;
     955        pVirtio->pGcPhysCommonCfg = (PVIRTIO_PCI_COMMON_CFG_T)(GCPhysAddress + pVirtio->uCommonCfgOffset);
     956        pVirtio->pGcPhysNotifyCap = (PVIRTIO_PCI_NOTIFY_CAP_T)(GCPhysAddress + pVirtio->uNotifyCapOffset);
     957        pVirtio->pGcPhysIsrCap    = (PVIRTIO_PCI_ISR_CAP_T)(GCPhysAddress + pVirtio->uIsrCapOffset);
     958        pVirtio->pGcPhysPciCfgCap = (PVIRTIO_PCI_CFG_CAP_T)(GCPhysAddress + pVirtio->uPciCfgCapOffset);
     959#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     960        pVirtio->pGcPhysDeviceCap = (PVIRTIO_PCI_DEVICE_CAP_T)(GCPhysAddress + pVirtio->uuDeviceCapOffset);
     961#endif
     962    }
    651963    return rc;
    652964}
     
    656968 * @interface_method_impl{PDMIBASE,pfnQueryInterface}
    657969 */
    658 void *virtioQueryInterface(struct PDMIBASE *pInterface, const char *pszIID)
     970void *virtioQueryInterface(PPDMIBASE pInterface, const char *pszIID)
    659971{
    660972    VIRTIOSTATE *pThis = IFACE_TO_STATE(pInterface, IBase);
     
    662974
    663975    PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase);
    664     PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);
    665976    return NULL;
    666977}
    667978
     979/**
     980 * Get VirtIO available host-side features
     981 *
     982 * @returns feature bits selected or 0 if selector out of range.
     983 *
     984 * @param   pState          Virtio state
     985 * @param   uSelect         Selects which 32-bit set of feature information to return
     986 */
     987
     988static uint64_t virtioGetHostFeatures(PVIRTIOSTATE pVirtio)
     989{
     990    return pVirtio->uFeaturesOffered;
     991}
     992
     993/**
     994 *
     995 * Set VirtIO available host-side features
     996 *
     997 * @returns VBox status code
     998 *
     999 * @param   pState              Virtio state
     1000 * @param   uFeaturesOffered    Feature bits (0-63) to set
     1001 */
     1002
     1003static int virtioSetHostFeatures(PVIRTIOSTATE pVirtio, uint64_t uFeaturesOffered)
     1004{
     1005    pVirtio->uFeaturesOffered = VIRTIO_F_VERSION_1 | uFeaturesOffered;
     1006    return VINF_SUCCESS;
     1007}
    6681008
    6691009/**
     
    6781018{
    6791019    Log(("%s Destroying PCI instance\n", INSTANCE(pState)));
    680 
    6811020    return VINF_SUCCESS;
    6821021}
     
    7121051 * @param   devCapWriteCallback   Client function to call back to handle device specific capabilities
    7131052 * @param   cbDevSpecificCap      Size of device specific struct
    714  */
    715 int   virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance,
    716                     PVIRTIOPCIPARAMS pPciParams, const char *pcszNameFmt,
    717                     uint32_t nQueues, uint32_t uVirtioRegion,
     1053 * @param   uNotifyOffMultiplier  See VirtIO 1.0 spec 4.1.4.4 re: virtio_pci_notify_cap
     1054 */
     1055
     1056int   virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams,
     1057                    PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion,
    7181058                    PFNVIRTIODEVCAPREAD devCapReadCallback, PFNVIRTIODEVCAPWRITE devCapWriteCallback,
    719                     uint16_t cbDevSpecificCap)
    720 {
    721     RT_NOREF(nQueues);
     1059                    uint16_t cbDevSpecificCap, uint32_t uNotifyOffMultiplier)
     1060{
     1061    pVirtio->nQueues = nQueues;
     1062    pVirtio->uNotifyOffMultiplier = uNotifyOffMultiplier;
    7221063
    7231064    /* Init handles and log related stuff. */
    7241065    RTStrPrintf(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszNameFmt, iInstance);
    7251066
    726     pVirtio->pDevInsR3    = pDevIns;
    727     pVirtio->pDevInsR0    = PDMDEVINS_2_R0PTR(pDevIns);
    728     pVirtio->pDevInsRC    = PDMDEVINS_2_RCPTR(pDevIns);
    729     pVirtio->led.u32Magic = PDMLED_MAGIC;
    730     pVirtio->ILeds.pfnQueryStatusLed = virtioQueryStatusLed;
     1067    VIRTIOCALLBACKS virtioCallbacks;
     1068    virtioCallbacks.pfnSetHostFeatures = virtioSetHostFeatures;
     1069    virtioCallbacks.pfnGetHostFeatures = virtioGetHostFeatures;
     1070    virtioCallbacks.pfnReset = virtioReset;
     1071    *ppVirtioCallbacks = &virtioCallbacks;
     1072
     1073    pVirtio->pDevInsR3 = pDevIns;
     1074    pVirtio->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
     1075    pVirtio->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     1076    pVirtio->uDeviceStatus = 0;
    7311077    pVirtio->pfnVirtioDevCapRead     = devCapReadCallback;
    7321078    pVirtio->pfnVirtioDevCapWrite    = devCapWriteCallback;
     
    7531099    pVirtio->IBase = pDevIns->IBase;
    7541100
    755     rc = PDMDevHlpPCIIORegionRegister(pDevIns, uVirtioRegion, 32, PCI_ADDRESS_SPACE_MEM, virtioR3Map);
    756     if (RT_FAILURE(rc))
    757         return PDMDEV_SET_ERROR(pDevIns, rc,
    758             N_("virtio: cannot register PCI Capabilities address space")); /* can we put params in this error? */
    759 
    760     /** Build PCI vendor-specific capabilities list for exchanging
    761      *  VirtIO device capabilities with driver */
    762 
     1101    /** Construct & map PCI vendor-specific capabilities for virtio host negotiation with guest driver */
     1102
     1103#if 0 && defined(VBOX_WITH_MSI_DEVICES)  /* T.B.D. */
     1104    uint8_t fMsiSupport = true;
     1105#else
    7631106    uint8_t fMsiSupport = false;
    764 #if 0 && defined(VBOX_WITH_MSI_DEVICES)  /* T.B.D. */
    765         fMsiSupport = true;
    7661107#endif
     1108
    7671109    uint8_t uCfgCapOffset = 0x40;
    768     /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_common_cfg (VIRTIOCOMMONCFG)*/
    769     PVIRTIOPCICAP pCfg = pVirtio->pCommonCfg = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1110    PVIRTIO_PCI_NOTIFY_CAP_T pNotifyCap;
     1111    PVIRTIO_PCI_CAP_T pCommonCfg, pIsrCap;
     1112#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     1113    PVIRTIO_PCI_CAP_T pDeviceCap;
     1114#endif
     1115    uint32_t cbVirtioCaps = 0;
     1116
     1117    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIO_PCI_CAP_T) */
     1118    pVirtio->pPciCfgCap = (PVIRTIO_PCI_CFG_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
     1119    pVirtio->uPciConfigDataOffset = 0x40 + sizeof(VIRTIO_PCI_CAP_T);
     1120    PVIRTIO_PCI_CAP_T pCfg = (PVIRTIO_PCI_CAP_T)pVirtio->pPciCfgCap;
    7701121    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    771     pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP);
     1122    pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_CFG_CAP_T);
     1123    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CFG_CAP_T);
     1124    pCfg->uCfgType = VIRTIO_PCI_CAP_PCI_CFG;
     1125    pCfg->uBar     = uVirtioRegion;
     1126    pCfg->uOffset  = pVirtio->uPciCfgCapOffset = 0;
     1127    pCfg->uLength  = sizeof(VIRTIO_PCI_CFG_CAP_T);
     1128    cbVirtioCaps  += pCfg->uLength;
     1129
     1130    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_common_cfg (VIRTIO_PCI_COMMON_CFG_T)*/
     1131    pCfg = pCommonCfg = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
     1132    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
     1133    pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_CAP_T);
     1134    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
    7721135    pCfg->uCfgType = VIRTIO_PCI_CAP_COMMON_CFG;
    7731136    pCfg->uBar     = uVirtioRegion;
    774     pCfg->uOffset  = 0;
    775     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    776 
    777     /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_notify_cap (VIRTIONOTIFYCAP)*/
    778     pCfg = pVirtio->pNotifyCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1137    pCfg->uOffset  = pVirtio->uCommonCfgOffset = pVirtio->pPciCfgCap->pciCap.uOffset + sizeof(VIRTIO_PCI_CFG_CAP_T);
     1138    pCfg->uLength  = sizeof(VIRTIO_PCI_COMMON_CFG_T);
     1139    cbVirtioCaps  += pCfg->uLength;
     1140
     1141    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_notify_cap (VIRTIO_PCI_NOTIFY_CAP_T)*/
     1142    pNotifyCap = (PVIRTIO_PCI_NOTIFY_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
     1143    pCfg = (PVIRTIO_PCI_CAP_T)pNotifyCap;
    7791144    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    780     pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP);
     1145    pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
     1146    pCfg->uCapLen  = sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
    7811147    pCfg->uCfgType = VIRTIO_PCI_CAP_NOTIFY_CFG;
    7821148    pCfg->uBar     = uVirtioRegion;
    783     pCfg->uOffset  = pVirtio->pCommonCfg->uOffset + sizeof(VIRTIOCOMMONCFG);
    784     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    785 
    786     /* Capability will be mapped via VirtIO 1.0: uint8_t (VIRTIOISRCAP)  */
    787     pCfg = pVirtio->pISRCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1149    pCfg->uOffset  = pVirtio->uNotifyCapOffset = pCommonCfg->uOffset + sizeof(VIRTIO_PCI_COMMON_CFG_T);
     1150    pCfg->uLength  = sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
     1151    pNotifyCap->uNotifyOffMultiplier = uNotifyOffMultiplier;
     1152    cbVirtioCaps  += pCfg->uLength;
     1153
     1154    /* Capability will be mapped via VirtIO 1.0: uint8_t (VIRTIO_PCI_ISR_CAP_T)  */
     1155    pCfg = pIsrCap = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
    7881156    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    789     pCfg->uCapNext = uCfgCapOffset += sizeof(VIRTIOPCICAP);
     1157    pCfg->uCapNext = (uint8_t)(fMsiSupport || cbDevSpecificCap ? (uCfgCapOffset += sizeof(VIRTIO_PCI_ISR_CAP_T)) : 0);
     1158    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
    7901159    pCfg->uCfgType = VIRTIO_PCI_CAP_ISR_CFG;
    7911160    pCfg->uBar     = uVirtioRegion;
    792     pCfg->uOffset  = pVirtio->pNotifyCap->uOffset + sizeof(VIRTIONOTIFYCAP);
    793     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    794 
    795     /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_cfg_cap (VIRTIOPCICAP) */
    796     pCfg = pVirtio->pPCICfgCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
     1161    pCfg->uOffset  = pVirtio->uIsrCapOffset = pNotifyCap->pciCap.uOffset + sizeof(VIRTIO_PCI_NOTIFY_CAP_T);
     1162    pCfg->uLength  = sizeof(VIRTIO_PCI_ISR_CAP_T);
     1163    cbVirtioCaps  += pCfg->uLength;
     1164
     1165#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     1166    /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_dev_cap (VIRTIODEVCAP)*/
     1167    pCfg = pDeviceCap = (PVIRTIO_PCI_CAP_T)&pVirtio->dev.abConfig[uCfgCapOffset];
    7971168    pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    798     pCfg->uCapNext = (uint8_t)(fMsiSupport || cbDevSpecificCap ? (uCfgCapOffset += sizeof(VIRTIOPCICAP)): 0);
    799     pCfg->uCfgType = VIRTIO_PCI_CAP_PCI_CFG;
     1169    pCfg->uCapNext = (uint8_t)(fMsiSupport ? (uCfgCapOffset += sizeof(VIRTIO_PCI_CAP_T)) : 0);
     1170    pCfg->uCapLen  = sizeof(VIRTIO_PCI_CAP_T);
     1171    pCfg->uCfgType = VIRTIO_PCI_CAP_DEVICE_CFG;
    8001172    pCfg->uBar     = uVirtioRegion;
    801     pCfg->uOffset  = pVirtio->pISRCap->uOffset + sizeof(VIRTIOISRCAP);
    802     pCfg->uLength  = sizeof(VIRTIOPCICAP);
    803 
    804     if (cbDevSpecificCap)
    805     {
    806      /* Capability will be mapped via VirtIO 1.0: struct virtio_pci_dev_cap (VIRTIODEVCAP)*/
    807         pCfg = pVirtio->pDeviceCap = (PVIRTIOPCICAP)&pVirtio->dev.abConfig[uCfgCapOffset];
    808         pCfg->uCapVndr = VIRTIO_PCI_CAP_ID_VENDOR;
    809         pCfg->uCapNext = (uint8_t)(fMsiSupport ? (uCfgCapOffset += sizeof(VIRTIOPCICAP)) : 0);
    810         pCfg->uCfgType = VIRTIO_PCI_CAP_DEVICE_CFG;
    811         pCfg->uBar     = uVirtioRegion;
    812         pCfg->uOffset  = pVirtio->pPCICfgCap->uOffset + sizeof(VIRTIOPCICAP);
    813         pCfg->uLength  = sizeof(VIRTIOPCICAP);
    814     }
     1173    pCfg->uOffset  = uDeviceCapOffset->uOffset + sizeof(VIRTIO_PCI_ISR_CAP_T);
     1174    pCfg->uLength  = cbDevSpecificCap;
     1175    cbVirtioCaps  += pCfg->uLength;
     1176#endif
    8151177
    8161178    /* Set offset to first capability and enable PCI dev capabilities */
     
    8211183    {
    8221184        PDMMSIREG aMsiReg;
    823 
    8241185        RT_ZERO(aMsiReg);
    8251186        aMsiReg.iMsixCapOffset  = uCfgCapOffset;
     
    8291190        rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg); /* see MsixR3init() */
    8301191        if (RT_FAILURE (rc))
    831         {
    8321192            /* PK TODO: The following is moot, we need to flag no MSI-X support */
    8331193            PCIDevSetCapabilityList(&pVirtio->dev, 0x40);
    834         }
    835     }
    836 
    837     /* Status driver */
    838     PPDMIBASE pUpstreamBase;
    839 
    840     rc = PDMDevHlpDriverAttach(pDevIns, PDM_STATUS_LUN, &pVirtio->IBase, &pUpstreamBase, "Status Port");
     1194    }
     1195/*
     1196    PDMDevHlpPCISetConfigCallbacks(pDevIns, &pVirtio->dev,
     1197                virtioPciConfigRead,  &pVirtio->pfnPciConfigReadOld,
     1198                virtioPciConfigWrite, &pVirtio->pfnPciConfigWriteOld);
     1199*/
     1200    rc = PDMDevHlpPCIIORegionRegister(pDevIns, uVirtioRegion, cbVirtioCaps,
     1201                                      PCI_ADDRESS_SPACE_MEM, virtioR3Map);
    8411202    if (RT_FAILURE(rc))
    842         return PDMDEV_SET_ERROR(pDevIns, rc, N_("Failed to attach the status LUN"));
    843     pVirtio->pLedsConnector = PDMIBASE_QUERY_INTERFACE(&pVirtio->IBase, PDMILEDCONNECTORS);
     1203        return PDMDEV_SET_ERROR(pDevIns, rc,
     1204            N_("virtio: cannot register PCI Capabilities address space"));
    8441205
    8451206    return rc;
    8461207}
    8471208
    848 
    849 
    8501209#endif /* IN_RING3 */
    8511210
  • trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h

    r79973 r80058  
    3434/** @} */
    3535
     36
     37/** Reserved Feature Bits */
     38#define VIRTIO_F_RING_INDIRECT_DESC         RT_BIT_64(28)
     39#define VIRTIO_F_RING_IDX                   RT_BIT_64(29)
     40#define VIRTIO_F_VERSION_1                  RT_BIT_64(32)
     41
     42#define MAX_QUEUES                          5       /** Maximum number of queues we support     */
     43
    3644/** Mandatory for Virtio PCI device identification, per spec */
    3745#define DEVICE_PCI_VENDOR_ID_VIRTIO         0x1AF4
     
    6977typedef DECLCALLBACK(uint32_t) FNGETHOSTFEATURES(void *pvState);
    7078typedef FNGETHOSTFEATURES *PFNGETHOSTFEATURES;
    71 
    72 /** @name VirtIO port I/O callbacks.
    73  * @{ */
    74 typedef struct VIRTIOIOCALLBACKS
    75 {
    76      DECLCALLBACKMEMBER(uint32_t, pfnGetHostFeatures)(void *pvState);
    77      DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState);
    78      DECLCALLBACKMEMBER(void,     pfnSetHostFeatures)(void *pvState, uint32_t fFeatures);
    79      DECLCALLBACKMEMBER(int,      pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
    80      DECLCALLBACKMEMBER(int,      pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData);
    81      DECLCALLBACKMEMBER(int,      pfnReset)(void *pvState);
    82      DECLCALLBACKMEMBER(void,     pfnReady)(void *pvState);
    83 } VIRTIOIOCALLBACKS;
    84 /** Pointer to a const VirtIO port I/O callback structure. */
    85 typedef const VIRTIOIOCALLBACKS *PCVIRTIOIOCALLBACKS;
    86 /** @} */
    8779
    8880
     
    140132    uint32_t  uOffset;                /** Offset within bar.  (L.E.)                  */
    141133    uint32_t  uLength;                /** Length of struct, in bytes. (L.E.)          */
    142 }  VIRTIOPCICAP, *PVIRTIOPCICAP;
     134}  VIRTIO_PCI_CAP_T, *PVIRTIO_PCI_CAP_T;
    143135
    144136typedef struct virtio_pci_common_cfg /* VirtIO 1.0 specification name of this struct  */
     
    165157    uint16_t  uQueueMsixVector;       /** RW (driver selects MSI-X queue vector)      */
    166158    uint16_t  uQueueEnable;           /** RW (driver controls usability of queue)     */
    167     uint16_t  uQueueNotifyOff;        /** RO (offset to virtqueue; see spec)          */
     159    uint16_t  uQueueNotifyOff;        /** RO (offset uto virtqueue; see spec)          */
    168160    uint64_t  uQueueDesc;             /** RW (driver writes desc table phys addr)     */
    169161    uint64_t  uQueueAvail;            /** RW (driver writes avail ring phys addr)     */
    170162    uint64_t  uQueueUsed;             /** RW (driver writes used ring  phys addr)     */
    171 } VIRTIOCOMMONCFG, *PVIRTIOCOMMONCFG;
     163} VIRTIO_PCI_COMMON_CFG_T, *PVIRTIO_PCI_COMMON_CFG_T;
    172164
    173165typedef struct virtio_pci_notify_cap
    174166{
    175         struct virtio_pci_cap cap;
     167        struct virtio_pci_cap pciCap;
    176168        uint32_t uNotifyOffMultiplier; /* notify_off_multiplier                        */
    177 } VIRTIONOTIFYCAP, *PVIRTIONOTIFYCAP;
    178 
    179 typedef uint8_t VIRTIOISRCAP, *PVIRTIOISRCAP;
    180 
    181 /* Device-specific configuration (if any) ... T.B.D. (if and when neeed), provide an
    182  * interface/callback that lets the client of this code manage it, if and when needed.
    183  * probably just passing in a struct length and a callback from our capabilities
    184  * region handler */
    185 typedef struct virtio_pci_dev_cfg
    186 {
    187 } VIRTIODEVCAP, *PVIRTIODEVCAP;
     169} VIRTIO_PCI_NOTIFY_CAP_T, *PVIRTIO_PCI_NOTIFY_CAP_T;
     170
     171typedef uint8_t VIRTIO_PCI_ISR_CAP_T, *PVIRTIO_PCI_ISR_CAP_T;
     172
     173/*
     174 * If the client of this library has any device-specific capabilities, it must define
     175 * and implement this struct and the macro
     176 */
     177#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     178typedef struct virtio_pci_dev_cfg     VIRTIO_PCI_DEVICE_CAP_T, *PVIRTIO_PCI_DEVICE_CAP_T;
     179#endif
    188180
    189181typedef struct virtio_pci_cfg_cap {
    190         struct virtio_pci_cap cap;
    191         uint8_t pci_cfg_data[4]; /* Data for BAR access. */
    192 } VIRTIOPCICFGCAP, *PVIRTIOPCICFGCAP;
     182        struct virtio_pci_cap pciCap;
     183        uint8_t uPciCfgData[4]; /* Data for BAR access. */
     184} VIRTIO_PCI_CFG_CAP_T, *PVIRTIO_PCI_CFG_CAP_T;
    193185
    194186typedef struct virtq_desc  /* VirtIO 1.0 specification formal name of this struct     */
     
    306298    /** Status LUN: Base interface. */
    307299    PDMIBASE               IBase;
     300
    308301    /** Status LUN: LED port interface. */
    309     PDMILEDPORTS           ILeds;
    310     /** Status LUN: LED connector (peer). */
    311     R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
    312 
    313     PPDMDEVINSR3           pDevInsR3;              /**< Device instance - R3. */
    314     PPDMDEVINSR0           pDevInsR0;              /**< Device instance - R0. */
    315     PPDMDEVINSRC           pDevInsRC;              /**< Device instance - RC. */
    316 
    317     /** Base address of PCI capabilities */
    318     RTGCPHYS               GCPhysPciCapBase;
    319 
    320     VIRTIOCOMMONCFG        pGcPhysVirtioCommonCfg;
    321     VIRTIONOTIFYCAP        pGcPhysVirtioNotifyCap;
    322     VIRTIOISRCAP           pGcPhysVirtioIsrCap;
    323     VIRTIODEVCAP           pGcPhysVirtioDevCap;
    324     VIRTIOPCICFGCAP        pGcPhysVirtioPciCap;
    325 
    326     /** Callbacks when guest driver reads or writes VirtIO device-specific capabilities(s) */
    327 
    328     PFNVIRTIODEVCAPWRITE   pfnVirtioDevCapWrite;
    329     PFNVIRTIODEVCAPREAD    pfnVirtioDevCapRead;
    330 
    331 #if HC_ARCH_BITS == 64
    332     uint32_t               padding2;
    333 #endif
    334 
    335     /** Base port of I/O space region. */
    336     RTIOPORT               IOPortBase;
     302    PDMILEDPORTS           ILed;
    337303
    338304    /* Read/write part, protected with critical section. */
     
    340306    PDMLED                 led;
    341307
    342     uint32_t               uGuestFeatures;
    343     uint16_t               uQueueSelector;         /**< An index in aQueues array. */
    344     uint8_t                uStatus;                /**< Device Status (bits are device-specific). */
    345     uint8_t                uISR;                   /**< Interrupt Status Register. */
     308
     309    /** Status LUN: LED connector (peer). */
     310    R3PTRTYPE(PPDMILEDCONNECTORS) pLedsConnector;
     311
     312    PPDMDEVINSR3                pDevInsR3;              /**< Device instance - R3. */
     313    PPDMDEVINSR0                pDevInsR0;              /**< Device instance - R0. */
     314    PPDMDEVINSRC                pDevInsRC;              /**< Device instance - RC. */
     315
     316    /** Base address of PCI capabilities */
     317    RTGCPHYS                    GCPhysPciCapBase;
     318
     319
     320    /** Callbacks when guest driver reads or writes VirtIO device-specific capabilities(s) */
     321
     322    PFNVIRTIODEVCAPWRITE         pfnVirtioDevCapWrite;
     323    PFNVIRTIODEVCAPREAD          pfnVirtioDevCapRead;
     324    PFNPCICONFIGREAD             pfnPciConfigReadOld;
     325    PFNPCICONFIGWRITE            pfnPciConfigWriteOld;
     326
     327    uint8_t                      uPciConfigDataOffset;
     328#if HC_ARCH_BITS == 64
     329    uint32_t                     padding2;
     330#endif
     331
     332    /** Base port of I/O space region. */
     333    RTIOPORT                     IOPortBase;
     334
     335    uint32_t                     uGuestFeatures;
     336    uint16_t                     uQueueSelector;             /** An index in aQueues array. */
     337    uint8_t                      uStatus;                    /** Device Status (bits are device-specific). */
     338    uint8_t                      uISR;                       /** Interrupt Status Register. */
    346339
    347340#if HC_ARCH_BITS != 64
    348     uint32_t               padding3;
    349 #endif
    350 
    351     uint32_t               nQueues;       /**< Actual number of queues used. */
    352     VQUEUE                 Queues[VIRTIO_MAX_NQUEUES];
    353 
    354     PVIRTIOPCICAP pCommonCfg;
    355     PVIRTIOPCICAP pNotifyCap;
    356     PVIRTIOPCICAP pISRCap;
    357     PVIRTIOPCICAP pPCICfgCap;
    358     PVIRTIOPCICAP pDeviceCap;
     341    uint32_t                     padding3;
     342#endif
     343
     344    uint32_t                     nQueues;                    /** Actual number of queues used. */
     345    VQUEUE                       Queues[VIRTIO_MAX_NQUEUES];
     346
     347    uint32_t                     uFeaturesOfferedSelect;     /** Select hi/lo 32-bit uFeaturesOffered to r/w */
     348    uint64_t                     uFeaturesOffered;           /** Host features offered */
     349    uint32_t                     uFeaturesAcceptedSelect;    /** Selects hi/lo 32-bit uFeaturesAccepted to r/w*/
     350    uint64_t                     uFeaturesAccepted;          /** Host features accepted by guest */
     351
     352    uint32_t                     uMsixConfig;
     353    uint8_t                      uDeviceStatus;
     354    uint8_t                      uConfigGeneration;
     355    uint32_t                     uNotifyOffMultiplier;       /* Multiplier for uQueueNotifyOff[idx] */
     356
     357    uint16_t                     uQueueSelect;
     358    uint16_t                     uQueueSize[MAX_QUEUES];
     359    uint16_t                     uQueueMsixVector[MAX_QUEUES];
     360    uint16_t                     uQueueEnable[MAX_QUEUES];
     361    uint16_t                     uQueueNotifyOff[MAX_QUEUES];
     362    uint64_t                     uQueueDesc[MAX_QUEUES];
     363    uint64_t                     uQueueAvail[MAX_QUEUES];
     364    uint64_t                     uQueueUsed[MAX_QUEUES];
     365
     366    uint32_t                     uNotifyCapOffset;
     367    uint32_t                     uIsrCapOffset;
     368    uint32_t                     uPciCfgCapOffset;
     369    uint32_t                     uDeviceCapOffset;
     370    uint32_t                     uCommonCfgOffset;
     371
     372    PVIRTIO_PCI_CFG_CAP_T        pPciCfgCap;            /** Pointer to struct in configuration area */
     373
     374    PVIRTIO_PCI_COMMON_CFG_T     pGcPhysCommonCfg;      /** Pointer to MMIO mapped struct */
     375    PVIRTIO_PCI_NOTIFY_CAP_T     pGcPhysNotifyCap;      /** Pointer to MMIO mapped struct */
     376    PVIRTIO_PCI_ISR_CAP_T        pGcPhysIsrCap;         /** Pointer to MMIO mapped struct */
     377    PVIRTIO_PCI_CFG_CAP_T        pGcPhysPciCfgCap;      /** Pointer to MMIO mapped struct */
     378#ifdef HAVE_VIRTIO_DEVICE_SPECIFIC_CAP
     379    PVIRTIO_PCI_DEVICE_CAP_T     pGcPhysDeviceCap;      /** Pointer to MMIO mapped struct */
     380#endif
     381
     382    bool fDeviceConfigInterrupt;
     383    bool fQueueInterrupt;
     384
    359385} VIRTIOSTATE, *PVIRTIOSTATE;
     386
     387/** @name VirtIO port I/O callbacks.
     388 * @{ */
     389typedef struct VIRTIOIOCALLBACKS
     390{
     391     DECLCALLBACKMEMBER(uint64_t, pfnGetHostFeatures)(PVIRTIOSTATE pVirtio);
     392     DECLCALLBACKMEMBER(int,      pfnSetHostFeatures)(PVIRTIOSTATE pVirtio, uint64_t uFeaturesOffered);
     393     DECLCALLBACKMEMBER(int,      pfnReset)(PVIRTIOSTATE pVirtio);
     394/*   DECLCALLBACKMEMBER(uint32_t, pfnGetHostMinimalFeatures)(void *pvState); */
     395/*   DECLCALLBACKMEMBER(int,      pfnGetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData); */
     396/*   DECLCALLBACKMEMBER(int,      pfnSetConfig)(void *pvState, uint32_t offCfg, uint32_t cb, void *pvData); */
     397/*   DECLCALLBACKMEMBER(void,     pfnReady)(void *pvState); */
     398} VIRTIOCALLBACKS, *PVIRTIOCALLBACKS, **PPVIRTIOCALLBACKS;
     399/** @} */
    360400
    361401void    virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
    362402void   *virtioQueryInterface(struct PDMIBASE *pInterface, const char *pszIID);
    363403
    364 int     virtioIOPortIn(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT port,
    365                         uint32_t *pu32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks);
    366 
    367 int     virtioIOPortOut(PPDMDEVINS pDevIns, void  *pvUser, RTIOPORT port,
    368                         uint32_t u32, unsigned cb, PCVIRTIOIOCALLBACKS pCallbacks);
    369 
    370 int     virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance,
    371                     PVIRTIOPCIPARAMS pPciParams, const char *pcszNameFmt,
    372                     uint32_t nQueues, uint32_t uVirtioRegion,
     404int     virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams,
     405                    PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion,
    373406                    PFNVIRTIODEVCAPREAD devCapReadCallback, PFNVIRTIODEVCAPWRITE devCapWriteCallback,
    374                     uint16_t cbDevSpecificCap);
    375 
    376 
    377 int     virtioDestruct(       PVIRTIOSTATE pState);
    378 void    virtioReset(          PVIRTIOSTATE pState);
    379 int     virtioSaveExec(       PVIRTIOSTATE pState, PSSMHANDLE pSSM);
    380 int     virtioLoadExec(       PVIRTIOSTATE pState, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues);
    381 void    virtioSetReadLed(     PVIRTIOSTATE pState, bool fOn);
    382 void    virtioSetWriteLed(    PVIRTIOSTATE pState, bool fOn);
    383 int     virtioRaiseInterrupt( PVIRTIOSTATE pState, int rcBusy, uint8_t uint8_tIntCause);
    384 
    385 PVQUEUE virtioAddQueue(       PVIRTIOSTATE pState, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName);
    386 bool    virtQueueSkip(        PVIRTIOSTATE pState, PVQUEUE pQueue);
    387 bool    virtQueueGet(         PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
    388 void    virtQueuePut(         PVIRTIOSTATE pState, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0);
    389 void    virtQueueNotify(      PVIRTIOSTATE pState, PVQUEUE pQueue);
    390 void    virtQueueSync(        PVIRTIOSTATE pState, PVQUEUE pQueue);
    391 void    vringSetNotification( PVIRTIOSTATE pState, PVIRTQUEUE pVirtQueue, bool fEnabled);
    392 
    393 
    394 /*
     407                    uint16_t cbDevSpecificCap, uint32_t uNotifyOffMultiplier);
     408
     409int     virtioDestruct(PVIRTIOSTATE pVirtio);
     410int     virtioReset(PVIRTIOSTATE pVirtio);
     411int     virtioSaveExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM);
     412int     virtioLoadExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues);
     413void    virtioSetReadLed(PVIRTIOSTATE pVirtio, bool fOn);
     414void    virtioSetWriteLed(PVIRTIOSTATE pVirtio, bool fOn);
     415int     virtioRaiseInterrupt(PVIRTIOSTATE pVirtio, int rcBusy, uint8_t uint8_tIntCause);
     416void    virtioNotify(PVIRTIOSTATE pVirtio);
     417
     418PVQUEUE virtioAddQueue(PVIRTIOSTATE pVirtio, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName);
     419bool    virtQueueSkip(PVIRTIOSTATE pVirtio, PVQUEUE pQueue);
     420bool    virtQueueGet(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true);
     421void    virtQueuePut(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0);
     422void    virtQueueNotify(PVIRTIOSTATE pVirtio, PVQUEUE pQueue);
     423void    virtQueueSync(PVIRTIOSTATE pVirtio, PVQUEUE pQueue);
     424void    vringSetNotification( PVIRTIOSTATE pVirtio, PVIRTQUEUE pVirtQueue, bool fEnabled);
     425
     426DECLINLINE(void) showDeviceStatus(uint8_t status)
     427{
     428    if (status & VIRTIO_STATUS_ACKNOWLEDGE)
     429        Log(("                        ACKNOWLEDGE\n"));
     430    if (status & VIRTIO_STATUS_DRIVER)
     431        Log(("                        DRIVER\n"));
     432    if (status & VIRTIO_STATUS_DRIVER_OK)
     433        Log(("                        DRIVER_OK\n"));
     434    if (status & VIRTIO_STATUS_FEATURES_OK)
     435        Log(("                        FEATURES_OK\n"));
     436    if (status & VIRTIO_STATUS_FAILED)
     437        Log(("                        FAILED\n"));
     438    if (status & VIRTIO_STATUS_DEVICE_NEEDS_RESET)
     439        Log(("                        ACKNOWLEDGE\n"));
     440    if (status == 0)
     441        Log(("                        RESET\n"));
     442    Log(("\n"));
     443}
     444
     445/*  FROM Virtio 1.0 SPEC, NYI
    395446      static inline int virtq_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old_idx)
    396447            return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old_idx);
     
    435486}
    436487
    437 DECLINLINE(int) virtioLock(VIRTIOSTATE *pState, int rcBusy)
    438 {
    439     int rc = PDMCritSectEnter(&pState->cs, rcBusy);
    440     return rc;
    441 }
    442 
    443 DECLINLINE(void) virtioUnlock(VIRTIOSTATE *pState)
    444 {
    445     PDMCritSectLeave(&pState->cs);
    446 }
    447 
    448488#endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h */
Note: See TracChangeset for help on using the changeset viewer.

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