Changeset 80306 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- Aug 15, 2019 6:45:06 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 132764
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r80240 r80306 44 44 #include "VBoxDD.h" 45 45 46 #define VIRTIOSCSI_MAX_TARGETS 1 /**< Can probably determined from higher layers */47 46 48 47 /** … … 62 61 */ 63 62 #define VIRTIOSCSI_REQ_QUEUE_CNT 1 /**< Number of req queues exposed by dev. */ 63 #define VIRTIOSCSI_MAX_TARGETS 1 /**< Can probably determined from higher layers */ 64 #define VIRTIOSCSI_MAX_LUN 16383 /* < VirtIO specification, section 5.6.4 */ 65 #define VIRTIOSCSI_MAX_COMMANDS_PER_LUN 64 /* < T.B.D. What is a good value for this? */ 66 #define VIRTIOSCSI_MAX_SEG_COUNT 1024 /* < T.B.D. What is a good value for this? */ 67 #define VIRTIOSCSI_MAX_SECTORS_HINT 0x10000 /* < VirtIO specification, section 5.6.4 */ 68 #define VIRTIOSCSI_MAX_CHANNEL_HINT 0 /* < VirtIO specification, section 5.6.4 */ 64 69 #define VIRTIOSCSI_SAVED_STATE_MINOR_VERSION 0x01 /**< SSM version # */ 70 65 71 #define PCI_DEVICE_ID_VIRTIOSCSI_HOST 0x1048 /**< Informs guest driver of type of VirtIO device */ 66 72 #define PCI_CLASS_BASE_MASS_STORAGE 0x01 /**< PCI Mass Storage device class */ … … 106 112 typedef struct virtio_scsi_ctrl 107 113 { 108 uint32_t type; /**< type*/109 uint8_t response; /**< response*/114 uint32_t type; /**< type */ 115 uint8_t response; /**< response */ 110 116 } VIRTIO_SCSI_CTRL_T, *PVIRTIO_SCSI_CTRL_T; 111 117 … … 113 119 * @name VirtIO 1.0 SCSI Host Device device specific control types 114 120 * @{ */ 115 #define VIRTIOSCSI_T_NO_EVENT 0116 #define VIRTIOSCSI_T_TRANSPORT_RESET 1117 #define VIRTIOSCSI_T_ASYNC_NOTIFY 2 /**< Asynchronous notification*/118 #define VIRTIOSCSI_T_PARAM_CHANGE 3121 #define VIRTIOSCSI_T_NO_EVENT 0 122 #define VIRTIOSCSI_T_TRANSPORT_RESET 1 123 #define VIRTIOSCSI_T_ASYNC_NOTIFY 2 /**< Asynchronous notification */ 124 #define VIRTIOSCSI_T_PARAM_CHANGE 3 119 125 /** @} */ 120 126 … … 125 131 typedef struct virtio_scsi_event { 126 132 // Device-writable part 127 uint32_t uEvent; /**< event:*/128 uint8_t uLUN[8]; /**< lun*/129 uint32_t uReason; /**< reason*/133 uint32_t uEvent; /**< event: */ 134 uint8_t uLUN[8]; /**< lun */ 135 uint32_t uReason; /**< reason */ 130 136 } VIRTIO_SCSI_EVENT_T, *PVIRTIO_SCSI_EVENT_T; 131 137 … … 133 139 * @name VirtIO 1.0 SCSI Host Device device specific event types 134 140 * @{ */ 135 #define VIRTIOSCSI_EVT_RESET_HARD 0 /**<*/136 #define VIRTIOSCSI_EVT_RESET_RESCAN 1 /**<*/137 #define VIRTIOSCSI_EVT_RESET_REMOVED 2 /**<*/141 #define VIRTIOSCSI_EVT_RESET_HARD 0 /**< */ 142 #define VIRTIOSCSI_EVT_RESET_RESCAN 1 /**< */ 143 #define VIRTIOSCSI_EVT_RESET_REMOVED 2 /**< */ 138 144 /** @} */ 139 145 … … 143 149 * The following struct is described in VirtIO 1.0 Specification, section 5.6.6.1 144 150 */ 145 #define CDB_SIZE 32 /**< Mandated by VirtIO 1.0 spec section 5.6.6.1*/146 #define SENSE_SIZE 96 /**< See section VirtIO 1.0, section 5.6.4*/147 #define PI_BYTES_IN 1/**< Value TBD (see section 5.6.6.1) */148 #define PI_BYTES_OUT 1/**< Value TBD (see section 5.6.6.1) */149 #define DATA_OUT 512/**< Value TBD (see section 5.6.6.1) */151 #define VIRTIOSCSI_SENSE_SIZE_DEFAULT 96 /**< VirtIO 1.0: 96 on reset, guest can change */ 152 #define VIRTIOSCSI_CDB_SIZE_DEFAULT 32 /**< VirtIO 1.0: 32 on reset, guest can change */ 153 #define VIRTIOSCSI_PI_BYTES_IN 1 /**< Value TBD (see section 5.6.6.1) */ 154 #define VIRTIOSCSI_PI_BYTES_OUT 1 /**< Value TBD (see section 5.6.6.1) */ 155 #define VIRTIOSCSI_DATA_OUT 512 /**< Value TBD (see section 5.6.6.1) */ 150 156 151 157 typedef struct virtio_scsi_req_cmd … … 157 163 uint8_t uPrio; /**< prio */ 158 164 uint8_t uCrn; /**< crn */ 159 uint8_t uCdb[ CDB_SIZE];/**< cdb VirtIO 1.0 mandates 32-bytes */165 uint8_t uCdb[VIRTIOSCSI_CDB_SIZE_DEFAULT]; /**< cdb VirtIO 1.0 mandates 32-bytes */ 160 166 161 167 /** Following three fields only present if VIRTIOSCSI_F_T10_PI negotiated */ … … 163 169 uint32_t uPiBytesOut; /**< pi_bytesout */ 164 170 uint32_t uPiBytesIn; /**< pi_bytesin */ 165 uint8_t uPiOut[ PI_BYTES_OUT];/**< pi_out[] TBD */166 167 uint8_t uDataOut[ DATA_OUT];/**< dataout */171 uint8_t uPiOut[VIRTIOSCSI_PI_BYTES_OUT]; /**< pi_out[] TBD */ 172 173 uint8_t uDataOut[VIRTIOSCSI_DATA_OUT]; /**< dataout */ 168 174 169 175 /* Device-writable part */ … … 173 179 uint8_t uStatus; /**< status */ 174 180 uint8_t uResponse; /**< response */ 175 uint8_t uSense[ SENSE_SIZE];/**< sense */181 uint8_t uSense[VIRTIOSCSI_SENSE_SIZE_DEFAULT]; /**< sense */ 176 182 177 183 /** Following two fields only present if VIRTIOSCSI_F_T10_PI negotiated */ 178 uint8_t uPiIn[ PI_BYTES_IN];/**< pi_in[] */184 uint8_t uPiIn[VIRTIOSCSI_PI_BYTES_IN]; /**< pi_in[] */ 179 185 uint8_t uDataIn[]; /**< detain; */ 180 186 } VIRTIO_SCSI_REQ_CMD_T, *PVIRTIO_SCSI_REQ_CMD_T; … … 183 189 * @name VirtIO 1.0 SCSI Host Device Req command-specific response values 184 190 * @{ */ 185 #define VIRTIOSCSI_S_OK 0/**< control, command */186 #define VIRTIOSCSI_S_OVERRUN 1/**< control */187 #define VIRTIOSCSI_S_ABORTED 2/**< control */188 #define VIRTIOSCSI_S_BAD_TARGET 3/**< control, command */189 #define VIRTIOSCSI_S_RESET 4/**< control */190 #define VIRTIOSCSI_S_BUSY 5/**< control, command */191 #define VIRTIOSCSI_S_TRANSPORT_FAILURE 6/**< control, command */192 #define VIRTIOSCSI_S_TARGET_FAILURE 7/**< control, command */193 #define VIRTIOSCSI_S_NEXUS_FAILURE 8/**< control, command */194 #define VIRTIOSCSI_S_FAILURE 9/**< control, command */195 #define VIRTIOSCSI_S_INCORRECT_LUN 12/**< command */191 #define VIRTIOSCSI_S_OK 0 /**< control, command */ 192 #define VIRTIOSCSI_S_OVERRUN 1 /**< control */ 193 #define VIRTIOSCSI_S_ABORTED 2 /**< control */ 194 #define VIRTIOSCSI_S_BAD_TARGET 3 /**< control, command */ 195 #define VIRTIOSCSI_S_RESET 4 /**< control */ 196 #define VIRTIOSCSI_S_BUSY 5 /**< control, command */ 197 #define VIRTIOSCSI_S_TRANSPORT_FAILURE 6 /**< control, command */ 198 #define VIRTIOSCSI_S_TARGET_FAILURE 7 /**< control, command */ 199 #define VIRTIOSCSI_S_NEXUS_FAILURE 8 /**< control, command */ 200 #define VIRTIOSCSI_S_FAILURE 9 /**< control, command */ 201 #define VIRTIOSCSI_S_INCORRECT_LUN 12 /**< command */ 196 202 /** @} */ 197 203 … … 461 467 462 468 /** 469 * Implementation invokes this to reset the VirtIO device 470 */ 471 static void virtioScsiDeviceReset(PVIRTIOSCSI pVirtioScsi) 472 { 473 pVirtioScsi->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT; 474 pVirtioScsi->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT; 475 virtioResetAll(pVirtioScsi->hVirtio); 476 477 } 478 479 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pVirtioScsi, uint32_t uOffset, 480 const void *pv, size_t cb, uint8_t fWrite) 481 { 482 int rc = VINF_SUCCESS; 483 if (MATCH_SCSI_CONFIG(uNumQueues)) 484 { 485 SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues); 486 } 487 else 488 if (MATCH_SCSI_CONFIG(uSegMax)) 489 { 490 SCSI_CONFIG_ACCESSOR_READONLY(uSegMax); 491 } 492 else 493 if (MATCH_SCSI_CONFIG(uMaxSectors)) 494 { 495 SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors); 496 } 497 else 498 if (MATCH_SCSI_CONFIG(uCmdPerLun)) 499 { 500 SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun); 501 } 502 else 503 if (MATCH_SCSI_CONFIG(uEventInfoSize)) 504 { 505 SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize); 506 } 507 else 508 if (MATCH_SCSI_CONFIG(uSenseSize)) 509 { 510 SCSI_CONFIG_ACCESSOR(uSenseSize); 511 } 512 else 513 if (MATCH_SCSI_CONFIG(uCdbSize)) 514 { 515 SCSI_CONFIG_ACCESSOR(uCdbSize); 516 } 517 else 518 if (MATCH_SCSI_CONFIG(uMaxChannel)) 519 { 520 SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel); 521 } 522 else 523 if (MATCH_SCSI_CONFIG(uMaxTarget)) 524 { 525 SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget); 526 } 527 else 528 if (MATCH_SCSI_CONFIG(uMaxLun)) 529 { 530 SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun); 531 } 532 else 533 { 534 LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb)); 535 rc = VERR_ACCESS_DENIED; 536 } 537 return rc; 538 } 539 540 541 /** 542 * Get this callback from the virtio framework when the driver is ready so we know 543 * the request for the number of queues is valid (for now presuming the driver(s) aren't 544 * dynamically adding req queues but create them all while initializing 545 * based on config information on host). 546 */ 547 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, bool fVirtioReady) 548 { 549 #define MAX_QUEUENAME_SIZE 20 550 Log2Func(("\n")); 551 char pszQueueName[MAX_QUEUENAME_SIZE]; 552 if (fVirtioReady) 553 { 554 Log2Func(("VirtIO reports ready... Initializing queues\n")); 555 virtioQueueAttach(hVirtio, VIRTIOSCSI_VIRTQ_CONTROLQ, "controlq"); 556 virtioQueueAttach(hVirtio, VIRTIOSCSI_VIRTQ_EVENTQ, "eventq"); 557 for (uint16_t qIdx = VIRTIOSCSI_VIRTQ_REQ_BASE; 558 qIdx < VIRTIOSCSI_VIRTQ_REQ_BASE + VIRTIOSCSI_REQ_QUEUE_CNT; 559 qIdx++) 560 { 561 RTStrPrintf(pszQueueName, sizeof(pszQueueName), "requestq_%d", qIdx - 2); 562 bool fEnabled = virtioQueueAttach(hVirtio, qIdx, (const char *)pszQueueName); 563 if (!fEnabled) 564 break; 565 } 566 } else 567 Log2Func(("VirtIO is resetting\n")); 568 } 569 570 /** 463 571 * Turns on/off the write status LED. 464 572 * … … 559 667 * @copydoc FNPDMDEVRESET 560 668 */ 561 static DECLCALLBACK(void) virtioScsiR3 Reset(PPDMDEVINS pDevIns)562 { 563 PVIRTIOSCSI p This= PDMINS_2_DATA(pDevIns, PVIRTIOSCSI);564 NOREF(pThis);669 static DECLCALLBACK(void) virtioScsiR3PDMReset(PPDMDEVINS pDevIns) 670 { 671 PVIRTIOSCSI pVirtioScsi = PDMINS_2_DATA(pDevIns, PVIRTIOSCSI); 672 virtioScsiDeviceReset(pVirtioScsi); 565 673 566 674 // ASMAtomicWriteBool(&pThis->fSignalIdle, true); … … 571 679 // ASMAtomicWriteBool(&pThis->fSignalIdle, false); 572 680 // } 681 573 682 } 574 683 … … 807 916 } 808 917 809 /**810 * @interface_method_impl{PDMIBASE,pfnQueryInterface}811 */812 static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID)813 {814 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase);815 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pTarget->IBase);816 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort);817 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort);818 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pTarget->ILed);819 return NULL;820 }821 822 static int virtioScsiR3CfgAccessed(PVIRTIOSCSI pVirtioScsi, uint32_t uOffset,823 const void *pv, size_t cb, uint8_t fWrite)824 {825 int rc = VINF_SUCCESS;826 if (MATCH_SCSI_CONFIG(uNumQueues))827 {828 SCSI_CONFIG_ACCESSOR_READONLY(uNumQueues);829 }830 else831 if (MATCH_SCSI_CONFIG(uSegMax))832 {833 SCSI_CONFIG_ACCESSOR_READONLY(uSegMax);834 }835 else836 if (MATCH_SCSI_CONFIG(uMaxSectors))837 {838 SCSI_CONFIG_ACCESSOR_READONLY(uMaxSectors);839 }840 else841 if (MATCH_SCSI_CONFIG(uCmdPerLun))842 {843 SCSI_CONFIG_ACCESSOR_READONLY(uCmdPerLun);844 }845 else846 if (MATCH_SCSI_CONFIG(uEventInfoSize))847 {848 SCSI_CONFIG_ACCESSOR_READONLY(uEventInfoSize);849 }850 else851 if (MATCH_SCSI_CONFIG(uSenseSize))852 {853 SCSI_CONFIG_ACCESSOR(uSenseSize);854 }855 else856 if (MATCH_SCSI_CONFIG(uCdbSize))857 {858 SCSI_CONFIG_ACCESSOR(uCdbSize);859 }860 else861 if (MATCH_SCSI_CONFIG(uMaxChannel))862 {863 SCSI_CONFIG_ACCESSOR_READONLY(uMaxChannel);864 }865 else866 if (MATCH_SCSI_CONFIG(uMaxTarget))867 {868 SCSI_CONFIG_ACCESSOR_READONLY(uMaxTarget);869 }870 else871 if (MATCH_SCSI_CONFIG(uMaxLun))872 {873 SCSI_CONFIG_ACCESSOR_READONLY(uMaxLun);874 }875 else876 {877 LogFunc(("Bad access by guest to virtio_scsi_config: uoff=%d, cb=%d\n", uOffset, cb));878 rc = VERR_ACCESS_DENIED;879 }880 return rc;881 }882 883 884 /**885 * Get this callback from the virtio framework when the driver is ready so we know886 * the request for the number of queues is valid (for now presuming the driver(s) aren't887 * dynamically adding req queues but create them all while initializing888 * based on config information on host).889 */890 static DECLCALLBACK(void) virtioScsiStatusChanged(VIRTIOHANDLE hVirtio, bool fVirtioReady)891 {892 #define MAX_QUEUENAME_SIZE 20893 Log2Func(("\n"));894 char pszQueueName[MAX_QUEUENAME_SIZE];895 if (fVirtioReady)896 {897 Log2Func(("VirtIO reports ready... Initializing queues\n"));898 virtioQueueInit(hVirtio, VIRTIOSCSI_VIRTQ_CONTROLQ, "controlq");899 virtioQueueInit(hVirtio, VIRTIOSCSI_VIRTQ_EVENTQ, "eventq");900 for (uint16_t qIdx = VIRTIOSCSI_VIRTQ_REQ_BASE; qIdx < virtioGetNumQueues(hVirtio); qIdx++)901 {902 RTStrPrintf(pszQueueName, sizeof(pszQueueName), "requestq_%d", qIdx - 2);903 bool fEnabled = virtioQueueInit(hVirtio, qIdx, (const char *)pszQueueName);904 if (!fEnabled)905 break;906 }907 } else908 Log2Func(("VirtIO not ready\n"));909 }910 918 911 919 static DECLCALLBACK(void) virtioScsiQueueNotified(VIRTIOHANDLE hVirtio, uint16_t qIdx) … … 1031 1039 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 1032 1040 */ 1041 static DECLCALLBACK(void *) virtioScsiR3TargetQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1042 { 1043 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IBase); 1044 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pTarget->IBase); 1045 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAPORT, &pTarget->IMediaPort); 1046 PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIAEXPORT, &pTarget->IMediaExPort); 1047 PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDPORTS, &pTarget->ILed); 1048 return NULL; 1049 } 1050 1051 /** 1052 * @interface_method_impl{PDMIBASE,pfnQueryInterface} 1053 */ 1033 1054 static DECLCALLBACK(void *) virtioScsiR3DeviceQueryInterface(PPDMIBASE pInterface, const char *pszIID) 1034 1055 { … … 1176 1197 /* Configure virtio_scsi_config that transacts via VirtIO implementation's Dev. Specific Cap callbacks */ 1177 1198 pThis->virtioScsiConfig.uNumQueues = VIRTIOSCSI_REQ_QUEUE_CNT; 1178 pThis->virtioScsiConfig.uSegMax = 1024; /* initial guess */1179 pThis->virtioScsiConfig.uMaxSectors = 0x10000;1180 pThis->virtioScsiConfig.uCmdPerLun = 64; /* initial guess */1181 pThis->virtioScsiConfig.uEventInfoSize = 100; /* VirtIO 1.0 spec says this should based on # of negotiated features*/1182 pThis->virtioScsiConfig.uSenseSize = 96; /* from VirtIO 1.0 spec, must restore this on reset */1183 pThis->virtioScsiConfig.uCdbSize = 32; /* from VirtIO 1.0 spec, must restore this on reset */1184 pThis->virtioScsiConfig.uMaxChannel = 0; /* from VirtIO 1.0 spec */1199 pThis->virtioScsiConfig.uSegMax = VIRTIOSCSI_MAX_SEG_COUNT; 1200 pThis->virtioScsiConfig.uMaxSectors = VIRTIOSCSI_MAX_SECTORS_HINT; 1201 pThis->virtioScsiConfig.uCmdPerLun = VIRTIOSCSI_MAX_COMMANDS_PER_LUN; 1202 pThis->virtioScsiConfig.uEventInfoSize = sizeof(VIRTIO_SCSI_EVENT_T); /* Spec says at least this size! */ 1203 pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT; 1204 pThis->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT; 1205 pThis->virtioScsiConfig.uMaxChannel = VIRTIOSCSI_MAX_CHANNEL_HINT; 1185 1206 pThis->virtioScsiConfig.uMaxTarget = pThis->cTargets; 1186 pThis->virtioScsiConfig.uMaxLun = 16383; /* from VirtIO 1.0 spec */1207 pThis->virtioScsiConfig.uMaxLun = VIRTIOSCSI_MAX_LUN; 1187 1208 1188 1209 rc = virtioConstruct(pDevIns, &pThis->hVirtio, pVirtioPciParams, pThis->szInstance, … … 1357 1378 NULL, 1358 1379 /* pfnReset */ 1359 virtioScsiR3 Reset,1380 virtioScsiR3PDMReset, 1360 1381 /* pfnSuspend */ 1361 1382 NULL,
Note:
See TracChangeset
for help on using the changeset viewer.