Changeset 80058 in vbox
- Timestamp:
- Jul 30, 2019 8:17:49 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r79973 r80058 44 44 #include "VBoxDD.h" 45 45 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 54 87 */ 55 88 typedef struct VIRTIOSCSITARGET 56 89 { 57 /** Pointer to PCI device that owns this target instance. - R3 /pointer */90 /** Pointer to PCI device that owns this target instance. - R3 pointer */ 58 91 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;63 92 64 93 /** Pointer to attached driver's base interface. */ 65 R3PTRTYPE(PPDMIBASE) p UpstreamDrvBase;66 67 /** LUN of the device.*/94 R3PTRTYPE(PPDMIBASE) pDrvBase; 95 96 /** Target LUN */ 68 97 RTUINT iLUN; 69 98 70 /** Our base interface. */ 99 /** Target LUN Description */ 100 char * pszLunName; 101 102 /** Target base interface. */ 71 103 PDMIBASE IBase; 72 104 … … 74 106 bool fPresent; 75 107 108 76 109 /** Media port interface. */ 77 110 PDMIMEDIAPORT IMediaPort; 111 /** Pointer to the attached driver's media interface. */ 112 R3PTRTYPE(PPDMIMEDIA) pDrvMedia; 113 78 114 79 115 /** Extended media port interface. */ 80 116 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; 81 125 82 126 /** Number of outstanding tasks on the port. */ 83 127 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;93 128 94 129 R3PTRTYPE(PVQUEUE) pCtlQueue; // ? TBD … … 100 135 101 136 /** 102 * Main VirtIO SCSI device state.137 * PDM instance data (state) for VirtIO Host SCSI device 103 138 * 104 139 * @extends PDMPCIDEV … … 112 147 VIRTIOSCSITARGET aTargetInstances[VIRTIOSCSI_MAX_TARGETS]; 113 148 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; 117 164 118 165 /** Base address of the memory mapping. */ … … 133 180 /** The event semaphore the processing thread waits on. */ 134 181 SUPSEMEVENT hEvtProcess; 182 183 PVIRTIOCALLBACKS pVirtioCallbacks; 135 184 136 185 /** Number of ports detected */ … … 168 217 169 218 170 #define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION 0x01171 172 #define PCI_VENDOR_ID_VIRTIO 0x1AF4173 #define PCI_DEVICE_ID_VIRTIO_SCSI_HOST 0x1048174 #define PCI_CLASS_BASE_MASS_STORAGE 0x01175 #define PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER 0x00176 #define PCI_CLASS_PROG_UNSPECIFIED 0x00177 #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 0181 #define VIRTIO_SCSI_REGION_PORT_IO 1182 #define VIRTIO_SCSI_REGION_PCI_CAP 2183 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 VirtualBox187 * data type + camel case annotation, with the original field name from the188 * VirtIO specification in the field's comment.189 */190 191 /** @name VirtIO 1.0 SCSI Host feature bits192 * @{ */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 198 219 #define CDB_SIZE 1 /* logic tbd */ 199 220 #define SENSE_SIZE 1 /* logic tbd */ … … 211 232 uint8_t uCdb[CDB_SIZE]; /** cdb */ 212 233 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 */ 214 235 215 236 uint32_t uPiBytesOut; /** pi_bytesout */ … … 227 248 uint8_t uSense[SENSE_SIZE]; /** sense */ 228 249 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 */ 230 251 uint8_t uPiIn[PI_BYTES_IN]; /** pi_in[] */ 231 252 uint8_t uDataIn[]; /** detain; */ … … 233 254 234 255 /** 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 */ 246 267 247 268 248 269 /** task_attr */ 249 #define VIRTIO _SCSI_S_SIMPLE 0250 #define VIRTIO _SCSI_S_ORDERED 1251 #define VIRTIO _SCSI_S_HEAD 2252 #define VIRTIO _SCSI_S_ACA 3253 254 #define VIRTIO _SCSI_T_TMF 0255 #define VIRTIO _SCSI_T_TMF_ABORT_TASK 0256 #define VIRTIO _SCSI_T_TMF_ABORT_TASK_SET 1257 #define VIRTIO _SCSI_T_TMF_CLEAR_ACA 2258 #define VIRTIO _SCSI_T_TMF_CLEAR_TASK_SET 3259 #define VIRTIO _SCSI_T_TMF_I_T_NEXUS_RESET 4260 #define VIRTIO _SCSI_T_TMF_LOGICAL_UNIT_RESET 5261 #define VIRTIO _SCSI_T_TMF_QUERY_TASK 6262 #define VIRTIO _SCSI_T_TMF_QUERY_TASK_SET 7270 #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 263 284 264 285 typedef struct virtio_scsi_ctrl_tmf … … 275 296 /* command-specific response values */ 276 297 277 #define VIRTIO _SCSI_S_FUNCTION_COMPLETE 0278 #define VIRTIO _SCSI_S_FUNCTION_SUCCEEDED 10279 #define VIRTIO _SCSI_S_FUNCTION_REJECTED 11280 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 */ 283 304 284 305 typedef struct virtio_scsi_ctrl_an … … 293 314 } VIRTIOSCSICTRLAN, *PVIRTIOSCSICTRLAN; 294 315 295 #define VIRTIO _SCSI_EVT_ASYNC_OPERATIONAL_CHANGE 2296 #define VIRTIO _SCSI_EVT_ASYNC_POWER_MGMT 4297 #define VIRTIO _SCSI_EVT_ASYNC_EXTERNAL_REQUEST 8298 #define VIRTIO _SCSI_EVT_ASYNC_MEDIA_CHANGE 16299 #define VIRTIO _SCSI_EVT_ASYNC_MULTI_HOST 32300 #define VIRTIO _SCSI_EVT_ASYNC_DEVICE_BUSY 64316 #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 301 322 302 323 /** Device operation: controlq */ … … 308 329 } VIRTIOSCSICTRL, *PVIRTIOSCSICTRL; 309 330 310 #define VIRTIO _SCSI_T_NO_EVENT 0311 312 #define VIRTIO _SCSI_T_TRANSPORT_RESET 1313 #define VIRTIO _SCSI_T_ASYNC_NOTIFY 2 /** Asynchronous notification */314 #define VIRTIO _SCSI_T_PARAM_CHANGE 3315 316 #define VIRTIO _SCSI_EVT_RESET_HARD 0317 #define VIRTIO _SCSI_EVT_RESET_RESCAN 1318 #define VIRTIO _SCSI_EVT_RESET_REMOVED 2331 #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 319 340 320 341 /** Device operation: eventq */ 321 342 322 #define VIRTIO _SCSI_T_EVENTS_MISSED 0x80000000343 #define VIRTIOSCSI_T_EVENTS_MISSED 0x80000000 323 344 typedef struct virtio_scsi_event { 324 345 // Device-writable part … … 352 373 } 353 374 #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 */ 383 void 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 */ 399 void 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 } 354 407 355 408 /** … … 418 471 return VINF_SUCCESS; 419 472 } 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 490 473 491 474 /** … … 654 637 655 638 if (pThis->pMediaNotify) 656 virtioSetWriteLed(&(pThis->virtioState), false); 657 } 658 639 virtioScsiSetWriteLed(pTarget, false); 640 } 659 641 660 642 /** … … 680 662 681 663 /** 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 */ 671 static 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 */ 692 static 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 */ 707 static 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 /** 682 718 * virtio-scsi VirtIO Device-specific capabilities read callback 683 719 * (other VirtIO capabilities and features are handled in VirtIO implementation) … … 691 727 { 692 728 /*TBD*/ 693 LogF lowFunc(("Read from Device-Specific capabilities, callback to VirtIO client\n"));729 LogFunc(("Read from Device-Specific capabilities\n")); 694 730 RT_NOREF(pDevIns); 695 731 RT_NOREF(GCPhysAddr); … … 712 748 { 713 749 /*TBD*/ 714 LogF lowFunc(("Write to Device-Specific capabilities, callback to VirtIO client\n"));750 LogFunc(("Write to Device-Specific capabilities\n")); 715 751 RT_NOREF(pDevIns); 716 752 RT_NOREF(GCPhysAddr); … … 721 757 } 722 758 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 */ 771 PDMBOTHCBDECL(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 */ 789 PDMBOTHCBDECL(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 */ 799 static 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 */ 832 static 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 723 843 /** 724 844 * Detach notification. … … 737 857 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN]; 738 858 739 Log (("%s:\n", __FUNCTION__));859 LogFunc(("")); 740 860 741 861 AssertMsg(fFlags & PDM_TACH_FLAGS_NOT_HOT_PLUG, … … 746 866 */ 747 867 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; 767 869 } 768 870 … … 792 894 793 895 /* the usual paranoia */ 794 AssertRelease(!pTarget->p UpstreamDrvBase);896 AssertRelease(!pTarget->pDrvBase); 795 897 Assert(pTarget->iLUN == iLUN); 796 898 … … 800 902 */ 801 903 rc = PDMDevHlpDriverAttach(pDevIns, pTarget->iLUN, &pDevIns->IBase, 802 &pTarget->p UpstreamDrvBase, (const char *)&pTarget->pszLunName);904 &pTarget->pDrvBase, (const char *)&pTarget->pszLunName); 803 905 if (RT_SUCCESS(rc)) 804 906 pTarget->fPresent = true; … … 809 911 { 810 912 pTarget->fPresent = false; 811 pTarget->p UpstreamDrvBase = NULL;913 pTarget->pDrvBase = NULL; 812 914 } 813 915 return rc; … … 823 925 } 824 926 825 static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg) 826 { 927 static DECLCALLBACK(int) virtioScsiConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg){ 827 928 828 929 PDMDEV_CHECK_VERSIONS_RETURN(pDevIns); 930 829 931 PVIRTIOSCSI pThis = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 830 932 int rc = VINF_SUCCESS; 831 933 bool fBootable = true; 934 935 pThis->pDevInsR3 = pDevIns; 936 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 937 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 832 938 833 939 LogFunc(("PDM device instance: %d\n", iInstance)); … … 857 963 858 964 VIRTIOPCIPARAMS virtioPciParams, *pVirtioPciParams = &virtioPciParams; 859 pVirtioPciParams->uDeviceId = PCI_DEVICE_ID_VIRTIO _SCSI_HOST;965 pVirtioPciParams->uDeviceId = PCI_DEVICE_ID_VIRTIOSCSI_HOST; 860 966 pVirtioPciParams->uClassBase = PCI_CLASS_BASE_MASS_STORAGE; 861 967 pVirtioPciParams->uClassSub = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER; 862 968 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 */ 864 970 pVirtioPciParams->uInterruptLine = 0x00; 865 971 pVirtioPciParams->uInterruptPin = 0x01; 866 972 867 973 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 873 983 if (RT_FAILURE(rc)) 874 984 return PDMDEV_SET_ERROR(pDevIns, rc, N_("virtio-scsi: failed to initialize VirtIO")); 875 985 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, 877 989 PCI_ADDRESS_SPACE_MEM, virtioScsiR3Map); 878 990 if (RT_FAILURE(rc)) … … 903 1015 PVIRTIOSCSITARGET pTarget = &pThis->aTargetInstances[iLUN]; 904 1016 905 if (RTStrAPrintf(&pTarget->pszLunName, " VIRTIOSCSI%u", iLUN) < 0)1017 if (RTStrAPrintf(&pTarget->pszLunName, "vSCSI%u", iLUN) < 0) 906 1018 AssertLogRelFailedReturn(VERR_NO_MEMORY); 907 1019 … … 909 1021 pTarget->iLUN = iLUN; 910 1022 pTarget->pVirtioScsiR3 = pThis; 1023 1024 pTarget->IBase.pfnQueryInterface = virtioScsiR3TargetQueryInterface; 1025 911 1026 /* IMediaPort and IMediaExPort interfaces provide callbacks for VD media and downstream driver access */ 912 1027 pTarget->IMediaPort.pfnQueryDeviceLocation = virtioScsiR3QueryDeviceLocation; … … 918 1033 pTarget->IMediaExPort.pfnIoReqQueryBuf = NULL; 919 1034 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; 920 1039 921 1040 LogFunc(("Attaching LUN: %s\n", pTarget->pszLunName)); … … 923 1042 /* Attach this SCSI driver (upstream driver pre-determined statically outside this module) */ 924 1043 AssertReturn(iLUN < RT_ELEMENTS(pThis->aTargetInstances), VERR_PDM_NO_SUCH_LUN); 925 rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &p DevIns->IBase, &pTarget->pUpstreamDrvBase, (const char *)&pTarget->pszLunName);1044 rc = PDMDevHlpDriverAttach(pDevIns, iLUN, &pTarget->IBase, &pTarget->pDrvBase, (const char *)&pTarget->pszLunName); 926 1045 if (RT_SUCCESS(rc)) 927 1046 { 928 1047 pTarget->fPresent = true; 929 1048 930 pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->p UpstreamDrvBase, PDMIMEDIA);1049 pTarget->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIA); 931 1050 AssertMsgReturn(VALID_PTR(pTarget->pDrvMedia), 932 1051 ("virtio-scsi configuration error: LUN#%d missing basic media interface!\n", pTarget->iLUN), 933 1052 VERR_PDM_MISSING_INTERFACE); 934 1053 935 936 pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pUpstreamDrvBase, PDMIMEDIAEX);937 1054 /* Get the extended media interface. */ 1055 pTarget->pDrvMediaEx = PDMIBASE_QUERY_INTERFACE(pTarget->pDrvBase, PDMIMEDIAEX); 1056 AssertMsgReturn(VALID_PTR(pTarget->pDrvMediaEx), 938 1057 ("virtio-scsi configuration error: LUN#%d missing extended media interface!\n", pTarget->iLUN), 939 1058 VERR_PDM_MISSING_INTERFACE); 940 1059 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); 944 1064 945 1065 } … … 947 1067 { 948 1068 pTarget->fPresent = false; 949 pTarget->p UpstreamDrvBase = NULL;1069 pTarget->pDrvBase = NULL; 950 1070 rc = VINF_SUCCESS; 951 1071 Log(("virtio-scsi: no driver attached to device %s\n", pTarget->pszLunName)); … … 964 1084 if (RT_FAILURE(rc)) 965 1085 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 966 1093 /* 967 1094 * Register the debugger info callback. -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r79973 r80058 35 35 # define QUEUENAME(s, q) (q->pcszName) 36 36 #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 37 129 38 130 #ifdef VBOX_DEVICE_STRUCT_TESTCASE … … 316 408 } 317 409 318 void virtioReset(PVIRTIOSTATE pState) 319 { 320 321 RT_NOREF(pState); 322 /* PK TODO Adapt to VirtIO 1.0 410 int virtioReset(PVIRTIOSTATE pVirtio) 411 { 412 RT_NOREF(pVirtio); 413 /* PK TODO Adapt to VirtIO 1.09 323 414 pState->uGuestFeatures = 0; 324 415 pState->uQueueSelector = 0; … … 329 420 virtQueueReset(&pState->Queues[i]); 330 421 */ 422 virtioNotify(pVirtio); 423 return VINF_SUCCESS; 331 424 } 332 425 … … 374 467 375 468 #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 EMT385 */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 else412 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 else428 pState->led.Actual.s.fReading = fOn;429 }430 469 431 470 … … 575 614 } 576 615 616 void virtioNotify(PVIRTIOSTATE pVirtio) 617 { 618 RT_NOREF(pVirtio); 619 } 620 621 static 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 */ 638 int 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 } 577 780 578 781 /** … … 587 790 * @param cb Number of bytes read. 588 791 */ 589 PDMBOTHCBDECL(int) virtioPciCapMemRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 590 { 591 /* PK New feature! */ 592 792 PDMBOTHCBDECL(int) virtioR3MmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb) 793 { 593 794 RT_NOREF(pvUser); 795 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 594 796 int rc = VINF_SUCCESS; 595 797 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 601 823 return rc; 602 824 } 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 */ 839 static 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 */ 870 static 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 605 883 /** 606 884 * Memory mapped I/O Handler for PCI Capabilities write operations. … … 614 892 * @param cb Number of bytes to write. 615 893 */ 616 PDMBOTHCBDECL(int) virtioPciCapMemWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 617 { 618 619 /* PK New feature! */ 894 PDMBOTHCBDECL(int) virtioR3MmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb) 895 { 896 620 897 RT_NOREF(pvUser); 898 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 621 899 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")); 627 927 628 928 return rc; 629 929 } 930 630 931 631 932 /** … … 636 937 { 637 938 RT_NOREF3(pPciDev, iRegion, enmType); 638 PVIRTIOSTATE p This= PDMINS_2_DATA(pDevIns, PVIRTIOSTATE);939 PVIRTIOSTATE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOSTATE); 639 940 int rc = VINF_SUCCESS; 640 941 641 942 Assert(cb >= 32); 642 643 LogFunc(("virtIO controller PCI Capabilities mapped at GCPhysAddr=%RGp cb=%RGp\n", GCPhysAddress, cb));644 943 645 944 /* We use the assigned size here, because we currently only support page aligned MMIO ranges. */ 646 945 rc = PDMDevHlpMMIORegister(pDevIns, GCPhysAddress, cb, NULL /*pvUser*/, 647 946 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU, 648 virtio PciCapMemWrite, virtioPciCapMemRead,947 virtioR3MmioWrite, virtioR3MmioRead, 649 948 "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 } 651 963 return rc; 652 964 } … … 656 968 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 657 969 */ 658 void *virtioQueryInterface( struct PDMIBASE *pInterface, const char *pszIID)970 void *virtioQueryInterface(PPDMIBASE pInterface, const char *pszIID) 659 971 { 660 972 VIRTIOSTATE *pThis = IFACE_TO_STATE(pInterface, IBase); … … 662 974 663 975 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pThis->IBase); 664 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pThis->ILeds);665 976 return NULL; 666 977 } 667 978 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 988 static 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 1003 static int virtioSetHostFeatures(PVIRTIOSTATE pVirtio, uint64_t uFeaturesOffered) 1004 { 1005 pVirtio->uFeaturesOffered = VIRTIO_F_VERSION_1 | uFeaturesOffered; 1006 return VINF_SUCCESS; 1007 } 668 1008 669 1009 /** … … 678 1018 { 679 1019 Log(("%s Destroying PCI instance\n", INSTANCE(pState))); 680 681 1020 return VINF_SUCCESS; 682 1021 } … … 712 1051 * @param devCapWriteCallback Client function to call back to handle device specific capabilities 713 1052 * @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 1056 int virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams, 1057 PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion, 718 1058 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; 722 1063 723 1064 /* Init handles and log related stuff. */ 724 1065 RTStrPrintf(pVirtio->szInstance, sizeof(pVirtio->szInstance), pcszNameFmt, iInstance); 725 1066 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; 731 1077 pVirtio->pfnVirtioDevCapRead = devCapReadCallback; 732 1078 pVirtio->pfnVirtioDevCapWrite = devCapWriteCallback; … … 753 1099 pVirtio->IBase = pDevIns->IBase; 754 1100 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 763 1106 uint8_t fMsiSupport = false; 764 #if 0 && defined(VBOX_WITH_MSI_DEVICES) /* T.B.D. */765 fMsiSupport = true;766 1107 #endif 1108 767 1109 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; 770 1121 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); 772 1135 pCfg->uCfgType = VIRTIO_PCI_CAP_COMMON_CFG; 773 1136 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; 779 1144 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); 781 1147 pCfg->uCfgType = VIRTIO_PCI_CAP_NOTIFY_CFG; 782 1148 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]; 788 1156 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); 790 1159 pCfg->uCfgType = VIRTIO_PCI_CAP_ISR_CFG; 791 1160 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]; 797 1168 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; 800 1172 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 815 1177 816 1178 /* Set offset to first capability and enable PCI dev capabilities */ … … 821 1183 { 822 1184 PDMMSIREG aMsiReg; 823 824 1185 RT_ZERO(aMsiReg); 825 1186 aMsiReg.iMsixCapOffset = uCfgCapOffset; … … 829 1190 rc = PDMDevHlpPCIRegisterMsi(pDevIns, &aMsiReg); /* see MsixR3init() */ 830 1191 if (RT_FAILURE (rc)) 831 {832 1192 /* PK TODO: The following is moot, we need to flag no MSI-X support */ 833 1193 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); 841 1202 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")); 844 1205 845 1206 return rc; 846 1207 } 847 1208 848 849 850 1209 #endif /* IN_RING3 */ 851 1210 -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r79973 r80058 34 34 /** @} */ 35 35 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 36 44 /** Mandatory for Virtio PCI device identification, per spec */ 37 45 #define DEVICE_PCI_VENDOR_ID_VIRTIO 0x1AF4 … … 69 77 typedef DECLCALLBACK(uint32_t) FNGETHOSTFEATURES(void *pvState); 70 78 typedef FNGETHOSTFEATURES *PFNGETHOSTFEATURES; 71 72 /** @name VirtIO port I/O callbacks.73 * @{ */74 typedef struct VIRTIOIOCALLBACKS75 {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 /** @} */87 79 88 80 … … 140 132 uint32_t uOffset; /** Offset within bar. (L.E.) */ 141 133 uint32_t uLength; /** Length of struct, in bytes. (L.E.) */ 142 } VIRTIO PCICAP, *PVIRTIOPCICAP;134 } VIRTIO_PCI_CAP_T, *PVIRTIO_PCI_CAP_T; 143 135 144 136 typedef struct virtio_pci_common_cfg /* VirtIO 1.0 specification name of this struct */ … … 165 157 uint16_t uQueueMsixVector; /** RW (driver selects MSI-X queue vector) */ 166 158 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) */ 168 160 uint64_t uQueueDesc; /** RW (driver writes desc table phys addr) */ 169 161 uint64_t uQueueAvail; /** RW (driver writes avail ring phys addr) */ 170 162 uint64_t uQueueUsed; /** RW (driver writes used ring phys addr) */ 171 } VIRTIO COMMONCFG, *PVIRTIOCOMMONCFG;163 } VIRTIO_PCI_COMMON_CFG_T, *PVIRTIO_PCI_COMMON_CFG_T; 172 164 173 165 typedef struct virtio_pci_notify_cap 174 166 { 175 struct virtio_pci_cap cap;167 struct virtio_pci_cap pciCap; 176 168 uint32_t uNotifyOffMultiplier; /* notify_off_multiplier */ 177 } VIRTIO NOTIFYCAP, *PVIRTIONOTIFYCAP;178 179 typedef uint8_t VIRTIO ISRCAP, *PVIRTIOISRCAP;180 181 /* Device-specific configuration (if any) ... T.B.D. (if and when neeed), provide an182 * 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 capabilities184 * 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 171 typedef 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 178 typedef struct virtio_pci_dev_cfg VIRTIO_PCI_DEVICE_CAP_T, *PVIRTIO_PCI_DEVICE_CAP_T; 179 #endif 188 180 189 181 typedef struct virtio_pci_cfg_cap { 190 struct virtio_pci_cap cap;191 uint8_t pci_cfg_data[4]; /* Data for BAR access. */192 } VIRTIO PCICFGCAP, *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; 193 185 194 186 typedef struct virtq_desc /* VirtIO 1.0 specification formal name of this struct */ … … 306 298 /** Status LUN: Base interface. */ 307 299 PDMIBASE IBase; 300 308 301 /** 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; 337 303 338 304 /* Read/write part, protected with critical section. */ … … 340 306 PDMLED led; 341 307 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. */ 346 339 347 340 #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 359 385 } VIRTIOSTATE, *PVIRTIOSTATE; 386 387 /** @name VirtIO port I/O callbacks. 388 * @{ */ 389 typedef 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 /** @} */ 360 400 361 401 void virtioRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta); 362 402 void *virtioQueryInterface(struct PDMIBASE *pInterface, const char *pszIID); 363 403 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, 404 int virtioConstruct(PPDMDEVINS pDevIns, PVIRTIOSTATE pVirtio, int iInstance, PVIRTIOPCIPARAMS pPciParams, 405 PPVIRTIOCALLBACKS ppVirtioCallbacks, const char *pcszNameFmt, uint32_t nQueues, uint32_t uVirtioRegion, 373 406 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 409 int virtioDestruct(PVIRTIOSTATE pVirtio); 410 int virtioReset(PVIRTIOSTATE pVirtio); 411 int virtioSaveExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM); 412 int virtioLoadExec(PVIRTIOSTATE pVirtio, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass, uint32_t nQueues); 413 void virtioSetReadLed(PVIRTIOSTATE pVirtio, bool fOn); 414 void virtioSetWriteLed(PVIRTIOSTATE pVirtio, bool fOn); 415 int virtioRaiseInterrupt(PVIRTIOSTATE pVirtio, int rcBusy, uint8_t uint8_tIntCause); 416 void virtioNotify(PVIRTIOSTATE pVirtio); 417 418 PVQUEUE virtioAddQueue(PVIRTIOSTATE pVirtio, unsigned uSize, PFNVIRTIOQUEUECALLBACK pfnCallback, const char *pcszName); 419 bool virtQueueSkip(PVIRTIOSTATE pVirtio, PVQUEUE pQueue); 420 bool virtQueueGet(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, bool fRemove = true); 421 void virtQueuePut(PVIRTIOSTATE pVirtio, PVQUEUE pQueue, PVQUEUEELEM pElem, uint32_t len, uint32_t uReserved = 0); 422 void virtQueueNotify(PVIRTIOSTATE pVirtio, PVQUEUE pQueue); 423 void virtQueueSync(PVIRTIOSTATE pVirtio, PVQUEUE pQueue); 424 void vringSetNotification( PVIRTIOSTATE pVirtio, PVIRTQUEUE pVirtQueue, bool fEnabled); 425 426 DECLINLINE(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 395 446 static inline int virtq_need_event(uint16_t event_idx, uint16_t new_idx, uint16_t old_idx) 396 447 return (uint16_t)(new_idx - event_idx - 1) < (uint16_t)(new_idx - old_idx); … … 435 486 } 436 487 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 448 488 #endif /* !VBOX_INCLUDED_SRC_VirtIO_Virtio_1_0_h */
Note:
See TracChangeset
for help on using the changeset viewer.