- Timestamp:
- Nov 19, 2019 5:43:11 AM (5 years ago)
- Location:
- trunk/src/VBox/Devices
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevVirtioSCSI.cpp
r81935 r81973 1 /* $Id$ $Revision$ $Date$ $Author$ */1 /* $Id$ $Revision$ $Date$ $Author$ */ 2 2 /** @file 3 3 * VBox storage devices - Virtio SCSI Driver … … 127 127 * VirtIO SCSI Host Device device-specific configuration (see VirtIO 1.0, section 5.6.4) 128 128 * VBox VirtIO framework issues callback to this client (device) to handle MMIO accesses 129 * to the device-specific configuration parameters. 129 * to the device-specific configuration parameters. uNumQueues is constant, readonly, 130 * but maintained in this struct due to the design of local MMIO and logging handling. 131 * The named constant will be used instead to wherever feasible. 130 132 */ 131 133 typedef struct virtio_scsi_config … … 332 334 | VIRTIOSCSI_EVT_ASYNC_DEVICE_BUSY ) 333 335 336 typedef struct VIRTIOSCSI_REQ_REDO 337 { 338 struct VIRTIOSCSI_REQ_REDO *next; /**< link to next in chain */ 339 uint16_t uHeadIdx; /**< desc chain head idx */ 340 } VIRTIOSCSI_REQ_REDO, *PVIRTIOSCSI_REQ_REDO; 341 334 342 /** 335 343 * Worker thread context, shared state. … … 350 358 bool volatile fSleeping; /**< Flags whether worker thread is sleeping or not */ 351 359 bool volatile fNotified; /**< Flags whether worker thread notified */ 360 PVIRTIOSCSI_REQ_REDO pReqRedoQueue; /**< Singly-linked listhead for suspended reqs to redo */ 352 361 } VIRTIOSCSIWORKERR3; 353 362 /** Pointer to a VirtIO SCSI worker. */ 354 363 typedef VIRTIOSCSIWORKERR3 *PVIRTIOSCSIWORKERR3; 355 356 364 357 365 /** … … 379 387 /** Flag whether device is present. */ 380 388 bool fPresent; 381 382 389 /** Media port interface. */ 383 390 PDMIMEDIAPORT IMediaPort; … … 401 408 402 409 } VIRTIOSCSITARGET, *PVIRTIOSCSITARGET; 403 404 405 /** Why we're quiescing. */406 typedef enum VIRTIOSCSIQUIESCINGFOR407 {408 kvirtIoScsiQuiescingForInvalid = 0,409 kvirtIoScsiQuiescingForReset,410 kvirtIoScsiQuiescingForSuspend,411 kvirtIoScsiQuiescingForPowerOff,412 kvirtIoScsiQuiescingFor32BitHack = 0x7fffffff413 } VIRTIOSCSIQUIESCINGFOR;414 415 410 416 411 /** … … 520 515 /** True if in the process of quiescing I/O */ 521 516 uint32_t fQuiescing; 517 522 518 /** For which purpose we're quiescing. */ 523 VIRTIO SCSIQUIESCINGFORenmQuiescingFor;519 VIRTIOVMSTATECHANGED enmQuiescingFor; 524 520 525 521 } VIRTIOSCSIR3; … … 566 562 typedef struct VIRTIOSCSIREQ 567 563 { 564 struct VIRTIOSCSIREQ *next; /**< When linked into redo queue */ 568 565 PDMMEDIAEXIOREQ hIoReq; /**< Handle of I/O request */ 569 566 PVIRTIOSCSITARGET pTarget; /**< Target */ … … 666 663 static int virtioScsiR3SendEvent(PPDMDEVINS pDevIns, PVIRTIOSCSI pThis, uint16_t uTarget, uint32_t uEventType, uint32_t uReason) 667 664 { 668 669 670 665 VIRTIOSCSI_EVENT_T event; 671 666 event.uEvent = uEventType; … … 727 722 virtioCoreR3QueueGet(pDevIns, &pThis->Virtio, EVENTQ_IDX, &pDescChain, true); 728 723 729 RTSGBUF reqSegBuf; 730 RTSGSEG aReqSegs[] = { { &event, sizeof(event) } }; 731 RTSgBufInit(&reqSegBuf, aReqSegs, RT_ELEMENTS(aReqSegs)); 732 733 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, EVENTQ_IDX, &reqSegBuf, pDescChain, true); 724 PRTSGBUF pReqSegBuf = (PRTSGBUF)RTMemAllocZ(sizeof(RTSGBUF)); 725 AssertReturn(pReqSegBuf, VERR_NO_MEMORY); 726 727 PRTSGSEG paReqSegs = (PRTSGSEG)RTMemAllocZ(sizeof(RTSGSEG) * 2); 728 AssertReturn(paReqSegs, VERR_NO_MEMORY); 729 730 paReqSegs[0].pvSeg = &event; 731 paReqSegs[0].cbSeg = sizeof(sizeof(event)); 732 733 RTSgBufInit(pReqSegBuf, paReqSegs, 1); 734 735 virtioCoreR3QueuePut(pDevIns, &pThis->Virtio, EVENTQ_IDX, pReqSegBuf, pDescChain, true); 734 736 virtioCoreQueueSync(pDevIns, &pThis->Virtio, EVENTQ_IDX); 737 738 RTMemFree(paReqSegs); 739 RTMemFree(pReqSegBuf); 735 740 736 741 return VINF_SUCCESS; … … 1041 1046 uint64_t srcSgCur = (uint64_t)pSgPhysSend->pGcSegCur; 1042 1047 cbCopied = RT_MIN((uint64_t)pSgBuf->cbSegLeft, srcSgLen - (srcSgCur - srcSgStart)); 1043 PDMDevHlpP hysRead(pDevIns,1048 PDMDevHlpPCIPhysRead(pDevIns, 1044 1049 (RTGCPHYS)pSgPhysSend->pGcSegCur, pSgBuf->pvSegCur, cbCopied); 1045 1050 RTSgBufAdvance(pSgBuf, cbCopied); … … 1054 1059 } 1055 1060 1056 /**1057 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected}1058 */1059 static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface)1060 {1061 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);1062 PPDMDEVINS pDevIns = pTarget->pDevIns;1063 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);1064 1065 LogFunc(("LUN %d Ejected!\n", pTarget->iTarget));1066 if (pThisCC->pMediaNotify)1067 {1068 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY,1069 (PFNRT)pThisCC->pMediaNotify->pfnEjected, 2,1070 pThisCC->pMediaNotify, pTarget->iTarget);1071 AssertRC(rc);1072 }1073 }1074 1075 /**1076 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged}1077 */1078 static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq,1079 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState)1080 {1081 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort);1082 PPDMDEVINS pDevIns = pTarget->pDevIns;1083 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI);1084 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);1085 RT_NOREF(hIoReq, pvIoReqAlloc);1086 1087 switch (enmState)1088 {1089 case PDMMEDIAEXIOREQSTATE_SUSPENDED:1090 {1091 /* Stop considering this request active */1092 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThisCC->fQuiescing)1093 PDMDevHlpAsyncNotificationCompleted(pDevIns);1094 break;1095 }1096 case PDMMEDIAEXIOREQSTATE_ACTIVE:1097 ASMAtomicIncU32(&pThis->cActiveReqs);1098 break;1099 default:1100 AssertMsgFailed(("Invalid request state given %u\n", enmState));1101 }1102 }1103 1104 1105 1061 /********************************************************************************************************************************* 1106 1062 * Worker Thread * … … 1132 1088 size_t cbSeg = cb; 1133 1089 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg); 1134 PDMDevHlpP hysRead(pDevIns, GCPhys, pb, cbSeg);1090 PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg); 1135 1091 pb += cbSeg; 1136 1092 cb -= cbSeg; … … 1344 1300 size_t cbSeg = cb; 1345 1301 RTGCPHYS GCPhys = virtioCoreSgBufGetNextSegment(pDescChain->pSgPhysSend, &cbSeg); 1346 PDMDevHlpP hysRead(pDevIns, GCPhys, pb, cbSeg);1302 PDMDevHlpPCIPhysRead(pDevIns, GCPhys, pb, cbSeg); 1347 1303 pb += cbSeg; 1348 1304 cb -= cbSeg; … … 1551 1507 while (pThread->enmState == PDMTHREADSTATE_RUNNING) 1552 1508 { 1553 if ( virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, qIdx))1509 if (!pWorkerR3->pReqRedoQueue && virtioCoreQueueIsEmpty(pDevIns, &pThis->Virtio, qIdx)) 1554 1510 { 1555 1511 /* Atomic interlocks avoid missing alarm while going to sleep & notifier waking the awoken */ … … 1577 1533 if (!pThisCC->fQuiescing) 1578 1534 { 1535 /* Process any reqs that were suspended saved to the redo queue in save exec. */ 1536 PVIRTIOSCSI_REQ_REDO pReqRedo = pWorkerR3->pReqRedoQueue; 1537 for (; pReqRedo; pReqRedo = pReqRedo->next) 1538 { 1539 PVIRTIO_DESC_CHAIN_T pDescChain; 1540 int rc = virtioCoreR3DescChainGet(pDevIns, &pThis->Virtio, qIdx, 1541 pReqRedo->uHeadIdx, &pDescChain); 1542 if (RT_FAILURE(rc)) 1543 LogRel(("Error fetching desc chain to redo, %Rrc", rc)); 1544 1545 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, qIdx, pDescChain); 1546 if (RT_FAILURE(rc)) 1547 LogRel(("Error submitting req packet, resetting %Rrc", rc)); 1548 } 1549 pWorkerR3->pReqRedoQueue = NULL; 1550 1579 1551 Log6Func(("fetching next descriptor chain from %s\n", QUEUENAME(qIdx))); 1580 1552 PVIRTIO_DESC_CHAIN_T pDescChain; … … 1593 1565 rc = virtioScsiR3ReqSubmit(pDevIns, pThis, pThisCC, qIdx, pDescChain); 1594 1566 if (RT_FAILURE(rc)) 1595 { 1596 LogRel(("Error submitting req packet, resetting %Rrc", rc)); 1597 } 1567 LogRel(("Error submitting req packet, resetting %Rrc", rc)); 1598 1568 } 1599 1569 } … … 2009 1979 pHlp->pfnSSMGetU32(pSSM, &pThis->virtioScsiConfig.uMaxLun); 2010 1980 pHlp->pfnSSMGetU32(pSSM, &pThis->fAsyncEvtsEnabled); 2011 pHlp->pfnSSMGetU32V(pSSM, &pThis->cActiveReqs); 2012 pHlp->pfnSSMGetBool(pSSM, &pThis->fEventsMissed); 1981 pHlp->pfnSSMGetU32(pSSM, (uint32_t *)&pThis->cActiveReqs); 2013 1982 pHlp->pfnSSMGetU32(pSSM, &pThis->fVirtioReady); 2014 1983 pHlp->pfnSSMGetU32(pSSM, &pThis->fHasT10pi); … … 2017 1986 pHlp->pfnSSMGetU32(pSSM, &pThis->fHasLunChange); 2018 1987 pHlp->pfnSSMGetU32(pSSM, &pThis->fResetting); 1988 pHlp->pfnSSMGetBool(pSSM, &pThis->fEventsMissed); 1989 1990 // int rc = vboxscsiR3LoadExec(pHlp, &pThisCC->VBoxSCSI, pSSM); 2019 1991 2020 1992 /* 2021 1993 * Call the virtio core to let it load its state. 2022 1994 */ 2023 return virtioCoreR3LoadExec(&pThis->Virtio, pDevIns->pHlpR3, pSSM); 1995 int rc = virtioCoreR3LoadExec(&pThis->Virtio, pDevIns->pHlpR3, pSSM); 1996 1997 /* 1998 * Nudge request queue workers 1999 */ 2000 for (int qIdx = VIRTQ_REQ_BASE; qIdx < VIRTIOSCSI_QUEUE_CNT; qIdx++) 2001 { 2002 if (pThis->afQueueAttached[qIdx]) 2003 { 2004 LogFunc(("Waking %s worker.\n", QUEUENAME(qIdx))); 2005 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->aWorkers[qIdx].hEvtProcess); 2006 AssertRCReturn(rc, rc); 2007 } 2008 } 2009 return rc; 2024 2010 } 2025 2011 … … 2030 2016 { 2031 2017 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2032 //PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC);2018 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC); 2033 2019 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3; 2034 2020 LogFunc(("SAVE EXEC!!\n")); 2035 2021 2022 /* Every device first. */ 2023 // lsilogicR3LiveExec(pDevIns, pSSM, SSM_PASS_FINAL); 2024 for (unsigned i = 0; i < pThis->cTargets; i++) 2025 { 2026 PVIRTIOSCSITARGET pTarget = &pThisCC->paTargetInstances[i]; 2027 2028 AssertMsg(!pThis->cActiveReqs, ("There are still outstanding requests on this device\n")); 2029 pHlp->pfnSSMPutU32(pSSM, pThis->cTargets); 2030 2031 /* Query all suspended requests and store them in the request queue. */ 2032 if (pTarget->pDrvMediaEx) 2033 { 2034 uint32_t cReqsRedo = pTarget->pDrvMediaEx->pfnIoReqGetSuspendedCount(pTarget->pDrvMediaEx); 2035 if (cReqsRedo) 2036 { 2037 PDMMEDIAEXIOREQ hIoReq; 2038 PVIRTIOSCSIREQ pReq; 2039 int rc = pTarget->pDrvMediaEx->pfnIoReqQuerySuspendedStart(pTarget->pDrvMediaEx, &hIoReq, 2040 (void **)&pReq); 2041 AssertRCBreak(rc); 2042 2043 /* todo: BIOS? */ 2044 for (; cReqsRedo; --cReqsRedo) 2045 { 2046 2047 /* Add the head virtio desc idx of this request to the redo queue */ 2048 PVIRTIOSCSI_REQ_REDO pReqRedo = (PVIRTIOSCSI_REQ_REDO)RTMemAllocZ(sizeof(VIRTIOSCSI_REQ_REDO)); 2049 AssertReturn(pReqRedo, VERR_NO_MEMORY); 2050 pReqRedo->uHeadIdx = pReq->pDescChain->uHeadIdx; 2051 PVIRTIOSCSIWORKERR3 pWorkerR3 = &pThisCC->aWorkers[pReq->qIdx]; 2052 PVIRTIOSCSI_REQ_REDO *pReqRedoSlot = &pWorkerR3->pReqRedoQueue; 2053 2054 while(*pReqRedoSlot) 2055 pReqRedoSlot = &((*pReqRedoSlot)->next); 2056 2057 *pReqRedoSlot = pReqRedo; 2058 rc = pTarget->pDrvMediaEx->pfnIoReqQuerySuspendedNext(pTarget->pDrvMediaEx, hIoReq, 2059 &hIoReq, (void **)&pReq); 2060 AssertRCBreak(rc); 2061 } 2062 } 2063 } 2064 // int rc = vboxscsiR3SaveExec(pHlp, &pThisCC->VBoxSCSI, pSSM); 2065 } 2036 2066 pHlp->pfnSSMPutU32(pSSM, pThis->virtioScsiConfig.uNumQueues); 2037 2067 pHlp->pfnSSMPutU32(pSSM, pThis->virtioScsiConfig.uSegMax); … … 2163 2193 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2164 2194 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC); 2165 LogFunc(("Device I/O activity quiesced: enmQuiescingFor=%d\n", pThisCC->enmQuiescingFor)); 2166 2167 if (pThisCC->enmQuiescingFor == kvirtIoScsiQuiescingForReset) 2168 virtioCoreR3PropagateResetNotification(pDevIns, &pThis->Virtio); 2169 /** @todo r=bird: Do we need other notifications here for suspend and/or poweroff? */ 2170 2171 // pThisCC->enmQuiescingFor = kvirtIoScsiQuiescingForInvalid; 2195 2196 if (ASMAtomicReadU32(&pThis->cActiveReqs)) 2197 return false; 2198 2199 LogFunc(("Device I/O activity quiesced: enmQuiescingFor=%s\n", 2200 virtioCoreGetStateChangeText(pThisCC->enmQuiescingFor))); 2201 2202 virtioCoreR3VmStateChanged(pDevIns, &pThis->Virtio, pThisCC->enmQuiescingFor); 2203 2204 pThis->fResetting = false; 2172 2205 pThisCC->fQuiescing = false; 2206 2173 2207 return true; 2174 2208 } … … 2177 2211 * Worker for virtioScsiR3Reset() and virtioScsiR3SuspendOrPowerOff(). 2178 2212 */ 2179 static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns, VIRTIO SCSIQUIESCINGFORenmQuiscingFor)2213 static void virtioScsiR3QuiesceDevice(PPDMDEVINS pDevIns, VIRTIOVMSTATECHANGED enmQuiscingFor) 2180 2214 { 2181 2215 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); … … 2194 2228 2195 2229 /** 2196 * Common worker for suspend and power off. 2197 */ 2198 static void virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns, VIRTIOSCSIQUIESCINGFOR enmQuiscingFor) 2199 { 2230 * @interface_method_impl{PDMDEVREGR3,pfnReset} 2231 */ 2232 static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns) 2233 { 2234 LogFunc(("\n")); 2235 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2236 pThis->fResetting = true; 2237 virtioScsiR3QuiesceDevice(pDevIns, kvirtIoVmStateChangedReset); 2238 } 2239 2240 /** 2241 * @interface_method_impl{PDMDEVREGR3,pfnPowerOff} 2242 */ 2243 static DECLCALLBACK(void) virtioScsiR3SuspendOrPowerOff(PPDMDEVINS pDevIns, VIRTIOVMSTATECHANGED enmType) 2244 { 2245 LogFunc(("\n")); 2246 2200 2247 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2201 2248 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC); 2202 2249 2203 virtioScsiR3QuiesceDevice(pDevIns, enmQuiscingFor); 2204 2250 virtioScsiR3QuiesceDevice(pDevIns, enmType); 2205 2251 2206 2252 /* VM is halted, thus no new I/O being dumped into queues by the guest. … … 2219 2265 2220 2266 /** 2221 * @interface_method_impl{PDMDEVREGR3,pfn PowerOff}2267 * @interface_method_impl{PDMDEVREGR3,pfnSuspend} 2222 2268 */ 2223 2269 static DECLCALLBACK(void) virtioScsiR3PowerOff(PPDMDEVINS pDevIns) 2224 2270 { 2225 2271 LogFunc(("\n")); 2226 virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIo ScsiQuiescingForPowerOff);2272 virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedPowerOff); 2227 2273 } 2228 2274 … … 2233 2279 { 2234 2280 LogFunc(("\n")); 2235 virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIo ScsiQuiescingForSuspend);2281 virtioScsiR3SuspendOrPowerOff(pDevIns, kvirtIoVmStateChangedSuspend); 2236 2282 } 2237 2283 … … 2262 2308 2263 2309 /* Ensure guest is working the queues too. */ 2264 virtioCoreR3PropagateResumeNotification(pDevIns, &pThis->Virtio); 2265 } 2266 2267 /** 2268 * @interface_method_impl{PDMDEVREGR3,pfnReset} 2269 */ 2270 static DECLCALLBACK(void) virtioScsiR3Reset(PPDMDEVINS pDevIns) 2271 { 2272 LogFunc(("\n")); 2273 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2274 pThis->fResetting = true; 2275 virtioScsiR3QuiesceDevice(pDevIns, kvirtIoScsiQuiescingForReset); 2276 PDMDevHlpVMReset(pDevIns, 0); 2310 virtioCoreR3VmStateChanged(pDevIns, &pThis->Virtio, kvirtIoVmStateChangedResume); 2311 } 2312 2313 /** 2314 * @interface_method_impl{PDMIMEDIAEXPORT,pfnMediumEjected} 2315 */ 2316 static DECLCALLBACK(void) virtioScsiR3MediumEjected(PPDMIMEDIAEXPORT pInterface) 2317 { 2318 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 2319 PPDMDEVINS pDevIns = pTarget->pDevIns; 2320 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC); 2321 2322 LogFunc(("LUN %d Ejected!\n", pTarget->iTarget)); 2323 if (pThisCC->pMediaNotify) 2324 { 2325 int rc = VMR3ReqCallNoWait(PDMDevHlpGetVM(pDevIns), VMCPUID_ANY, 2326 (PFNRT)pThisCC->pMediaNotify->pfnEjected, 2, 2327 pThisCC->pMediaNotify, pTarget->iTarget); 2328 AssertRC(rc); 2329 } 2330 } 2331 2332 /** 2333 * @interface_method_impl{PDMIMEDIAEXPORT,pfnIoReqStateChanged} 2334 */ 2335 static DECLCALLBACK(void) virtioScsiR3IoReqStateChanged(PPDMIMEDIAEXPORT pInterface, PDMMEDIAEXIOREQ hIoReq, 2336 void *pvIoReqAlloc, PDMMEDIAEXIOREQSTATE enmState) 2337 { 2338 PVIRTIOSCSITARGET pTarget = RT_FROM_MEMBER(pInterface, VIRTIOSCSITARGET, IMediaExPort); 2339 PPDMDEVINS pDevIns = pTarget->pDevIns; 2340 PVIRTIOSCSI pThis = PDMDEVINS_2_DATA(pDevIns, PVIRTIOSCSI); 2341 PVIRTIOSCSICC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVIRTIOSCSICC); 2342 RT_NOREF(hIoReq, pvIoReqAlloc); 2343 2344 switch (enmState) 2345 { 2346 case PDMMEDIAEXIOREQSTATE_SUSPENDED: 2347 { 2348 /* Stop considering this request active */ 2349 if (!ASMAtomicDecU32(&pThis->cActiveReqs) && pThisCC->fQuiescing) 2350 PDMDevHlpAsyncNotificationCompleted(pDevIns); 2351 break; 2352 } 2353 case PDMMEDIAEXIOREQSTATE_ACTIVE: 2354 ASMAtomicIncU32(&pThis->cActiveReqs); 2355 break; 2356 default: 2357 AssertMsgFailed(("Invalid request state given %u\n", enmState)); 2358 } 2277 2359 } 2278 2360 … … 2354 2436 pThis->virtioScsiConfig.uMaxSectors = VIRTIOSCSI_MAX_SECTORS_HINT; 2355 2437 pThis->virtioScsiConfig.uCmdPerLun = VIRTIOSCSI_MAX_COMMANDS_PER_LUN; 2356 pThis->virtioScsiConfig.uEventInfoSize = sizeof(VIRTIOSCSI_EVENT_T); /* Spec says at least this size! */2438 pThis->virtioScsiConfig.uEventInfoSize = sizeof(VIRTIOSCSI_EVENT_T); /*VirtIO 1.0 Spec says at least this size! */ 2357 2439 pThis->virtioScsiConfig.uSenseSize = VIRTIOSCSI_SENSE_SIZE_DEFAULT; 2358 2440 pThis->virtioScsiConfig.uCdbSize = VIRTIOSCSI_CDB_SIZE_DEFAULT; … … 2368 2450 2369 2451 VIRTIOPCIPARAMS VirtioPciParams; 2370 VirtioPciParams.uDeviceId = PCI_DEVICE_ID_VIRTIOSCSI_HOST;2371 VirtioPciParams.uClassBase = PCI_CLASS_BASE_MASS_STORAGE;2372 VirtioPciParams.uClassSub = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER;2373 VirtioPciParams.uClassProg = PCI_CLASS_PROG_UNSPECIFIED;2374 VirtioPciParams.uSubsystemId = PCI_DEVICE_ID_VIRTIOSCSI_HOST; /* Virtio1.0 spec allows PCI Device ID here */2375 VirtioPciParams.uInterruptLine = 0x00;2376 VirtioPciParams.uInterruptPin = 0x01;2452 VirtioPciParams.uDeviceId = PCI_DEVICE_ID_VIRTIOSCSI_HOST; 2453 VirtioPciParams.uClassBase = PCI_CLASS_BASE_MASS_STORAGE; 2454 VirtioPciParams.uClassSub = PCI_CLASS_SUB_SCSI_STORAGE_CONTROLLER; 2455 VirtioPciParams.uClassProg = PCI_CLASS_PROG_UNSPECIFIED; 2456 VirtioPciParams.uSubsystemId = PCI_DEVICE_ID_VIRTIOSCSI_HOST; /* VirtIO 1.0 spec allows PCI Device ID here */ 2457 VirtioPciParams.uInterruptLine = 0x00; 2458 VirtioPciParams.uInterruptPin = 0x01; 2377 2459 2378 2460 rc = virtioCoreR3Init(pDevIns, &pThis->Virtio, &pThisCC->Virtio, &VirtioPciParams, pThis->szInstance, -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.cpp
r81838 r81973 103 103 104 104 105 const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState) 106 { 107 switch (enmState) 108 { 109 case kvirtIoVmStateChangedReset: return "<VM RESET>"; 110 case kvirtIoVmStateChangedSuspend: return "<VM SUSPEND>"; 111 case kvirtIoVmStateChangedPowerOff: return "<VM POWEROFF>"; 112 case kvirtIoVmStateChangedResume: return "<VM RESUME>"; 113 default: return "<BAD ENUM>"; 114 } 115 } 116 105 117 /********************************************************************************************************************************* 106 118 * Internal Functions * … … 128 140 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 129 141 uint16_t const cQueueItems = RT_MAX(pVirtio->uQueueSize[idxQueue], 1); /* Make sure to avoid div-by-zero. */ 130 PDMDevHlpP hysRead(pDevIns, /** @todo r=bird: PDMDevHlpPhysRead or PDMDevHlpPCIPhysRead ?!? (ditto rest of file + writes) */142 PDMDevHlpPCIPhysRead(pDevIns, 131 143 pVirtio->aGCPhysQueueDesc[idxQueue] + sizeof(VIRTQ_DESC_T) * (idxDesc % cQueueItems), 132 144 pDesc, sizeof(VIRTQ_DESC_T)); … … 141 153 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 142 154 uint16_t const cQueueItems = RT_MAX(pVirtio->uQueueSize[idxQueue], 1); /* Make sure to avoid div-by-zero. */ 143 PDMDevHlpP hysRead(pDevIns,155 PDMDevHlpPCIPhysRead(pDevIns, 144 156 pVirtio->aGCPhysQueueAvail[idxQueue] 145 157 + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[availIdx % cQueueItems]), … … 152 164 uint16_t uIdx = 0; 153 165 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 154 PDMDevHlpP hysRead(pDevIns,166 PDMDevHlpPCIPhysRead(pDevIns, 155 167 pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, uIdx), 156 168 &uIdx, sizeof(uIdx)); … … 168 180 uint16_t fFlags; 169 181 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 170 PDMDevHlpP hysRead(pDevIns,182 PDMDevHlpPCIPhysRead(pDevIns, 171 183 pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF(VIRTQ_AVAIL_T, fFlags), 172 184 &fFlags, sizeof(fFlags)); … … 180 192 /* VirtIO 1.0 uUsedEventIdx (used_event) immediately follows ring */ 181 193 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 182 PDMDevHlpP hysRead(pDevIns,194 PDMDevHlpPCIPhysRead(pDevIns, 183 195 pVirtio->aGCPhysQueueAvail[idxQueue] + RT_UOFFSETOF_DYN(VIRTQ_AVAIL_T, auRing[pVirtio->uQueueSize[idxQueue]]), 184 196 &uUsedEventIdx, sizeof(uUsedEventIdx)); … … 214 226 uint16_t uIdx = 0; 215 227 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 216 PDMDevHlpP hysRead(pDevIns,228 PDMDevHlpPCIPhysRead(pDevIns, 217 229 pVirtio->aGCPhysQueueUsed[idxQueue] + RT_UOFFSETOF(VIRTQ_USED_T, uIdx), 218 230 &uIdx, sizeof(uIdx)); … … 225 237 uint16_t fFlags = 0; 226 238 AssertMsg(pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK, ("Called with guest driver not ready\n")); 227 PDMDevHlpP hysRead(pDevIns,239 PDMDevHlpPCIPhysRead(pDevIns, 228 240 pVirtio->aGCPhysQueueUsed[idxQueue] + RT_UOFFSETOF(VIRTQ_USED_T, fFlags), 229 241 &fFlags, sizeof(fFlags)); … … 516 528 #endif /* IN_RING3 */ 517 529 518 #if 0 /** @todo r=bird: no prototype or docs for this one */519 530 /** 520 531 * See API comments in header file for description … … 528 539 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 529 540 530 if (virtioCoreQueueIsEmpty(pVirtio , idxQueue))541 if (virtioCoreQueueIsEmpty(pVirtio->pDevIns, pVirtio, idxQueue)) 531 542 return VERR_NOT_AVAILABLE; 532 543 … … 536 547 return VINF_SUCCESS; 537 548 } 538 #endif539 549 540 550 /** … … 557 567 #ifdef IN_RING3 558 568 559 /** 560 * Removes descriptor chain from avail ring of indicated queue and converts the descriptor 561 * chain into its OUT (to device) and IN to guest components. 562 * 563 * Additionally it converts the OUT desc chain data to a contiguous virtual 564 * memory buffer for easy consumption by the caller. The caller must return the 565 * descriptor chain pointer via virtioCoreR3QueuePut() and then call virtioCoreQueueSync() 566 * at some point to return the data to the guest and complete the transaction. 567 * 568 * @param pDevIns The device instance. 569 * @param pVirtio Pointer to the shared virtio state. 570 * @param idxQueue Queue number 571 * @param fRemove flags whether to remove desc chain from queue (false = peek) 572 * @param ppDescChain Address to store pointer to descriptor chain that contains the 573 * pre-processed transaction information pulled from the virtq. 574 * 575 * @returns VBox status code: 576 * @retval VINF_SUCCESS Success 577 * @retval VERR_INVALID_STATE VirtIO not in ready state (asserted). 578 * @retval VERR_NOT_AVAILABLE If the queue is empty. 579 */ 580 int virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, 581 PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove) 569 570 int virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, 571 uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain) 582 572 { 583 573 AssertReturn(ppDescChain, VERR_INVALID_PARAMETER); … … 595 585 ("Guest driver not in ready state.\n"), VERR_INVALID_STATE); 596 586 597 if (virtqIsEmpty(pDevIns, pVirtio, idxQueue))598 return VERR_NOT_AVAILABLE;599 600 uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdx);601 587 uint16_t uDescIdx = uHeadIdx; 602 588 603 Log3Func(("%s DESC CHAIN: (head) desc_idx=%u [avail_idx=%u]\n", pVirtq->szVirtqName, uHeadIdx, pVirtq->uAvailIdx)); 604 605 if (fRemove) 606 pVirtq->uAvailIdx++; 589 Log3Func(("%s DESC CHAIN: (head) desc_idx=%u\n", pVirtq->szVirtqName, uHeadIdx)); 607 590 608 591 VIRTQ_DESC_T desc; … … 682 665 683 666 /** 667 * Fetches descriptor chain using avail ring of indicated queue and converts the descriptor 668 * chain into its OUT (to device) and IN to guest components. 669 * 670 * Additionally it converts the OUT desc chain data to a contiguous virtual 671 * memory buffer for easy consumption by the caller. The caller must return the 672 * descriptor chain pointer via virtioCoreR3QueuePut() and then call virtioCoreQueueSync() 673 * at some point to return the data to the guest and complete the transaction. 674 * 675 * @param pDevIns The device instance. 676 * @param pVirtio Pointer to the shared virtio state. 677 * @param idxQueue Queue number 678 * @param fRemove flags whether to remove desc chain from queue (false = peek) 679 * @param ppDescChain Address to store pointer to descriptor chain that contains the 680 * pre-processed transaction information pulled from the virtq. 681 * 682 * @returns VBox status code: 683 * @retval VINF_SUCCESS Success 684 * @retval VERR_INVALID_STATE VirtIO not in ready state (asserted). 685 * @retval VERR_NOT_AVAILABLE If the queue is empty. 686 */ 687 int virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, 688 PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove) 689 { 690 PVIRTQSTATE pVirtq = &pVirtio->virtqState[idxQueue]; 691 692 if (virtqIsEmpty(pDevIns, pVirtio, idxQueue)) 693 return VERR_NOT_AVAILABLE; 694 695 uint16_t uHeadIdx = virtioReadAvailDescIdx(pDevIns, pVirtio, idxQueue, pVirtq->uAvailIdx); 696 697 if (fRemove) 698 pVirtq->uAvailIdx++; 699 700 int rc = virtioCoreR3DescChainGet(pDevIns, pVirtio, idxQueue, uHeadIdx, ppDescChain); 701 return rc; 702 } 703 704 /** 684 705 * Returns data to the guest to complete a transaction initiated by virtQueueGet(). 685 706 * … … 895 916 static int virtioKick(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint8_t uCause, uint16_t uMsixVector, bool fForce) 896 917 { 897 if (fForce)898 Log6Func(("reason: resumed after suspend\n"));899 else900 if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT)901 Log6Func(("reason: buffer added to 'used' ring.\n"));902 else903 if (uCause == VIRTIO_ISR_DEVICE_CONFIG)918 if (fForce) 919 Log6Func(("reason: resumed after suspend\n")); 920 else 921 if (uCause == VIRTIO_ISR_VIRTQ_INTERRUPT) 922 Log6Func(("reason: buffer added to 'used' ring.\n")); 923 else 924 if (uCause == VIRTIO_ISR_DEVICE_CONFIG) 904 925 Log6Func(("reason: device config change\n")); 905 926 … … 910 931 } 911 932 else if (uMsixVector != VIRTIO_MSI_NO_VECTOR) 912 {913 Log6Func(("MSI-X enabled, calling PDMDevHlpPCISetIrq with vector: 0x%x\n", uMsixVector));914 933 PDMDevHlpPCISetIrq(pDevIns, uMsixVector, 1); 915 }916 934 return VINF_SUCCESS; 917 935 } … … 922 940 * @param pDevIns The device instance. 923 941 */ 924 static void virtioLowerInterrupt(PPDMDEVINS pDevIns) 925 { 926 /** @todo r=bird: MSI? */ 927 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW); 942 static void virtioLowerInterrupt(PPDMDEVINS pDevIns, uint16_t uMsixVector) 943 { 944 PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); 945 if (!pVirtio->fMsiSupport) 946 PDMDevHlpPCISetIrq(pDevIns, 0, PDM_IRQ_LEVEL_LOW); 947 else if (uMsixVector != VIRTIO_MSI_NO_VECTOR) 948 PDMDevHlpPCISetIrq(pDevIns, pVirtio->uMsixConfig, PDM_IRQ_LEVEL_LOW); 928 949 } 929 950 … … 952 973 pVirtio->uISR = 0; 953 974 954 virtioLowerInterrupt(pDevIns); 975 if (!pVirtio->fMsiSupport) 976 virtioLowerInterrupt(pDevIns, 0); 977 else 978 { 979 virtioLowerInterrupt(pDevIns, pVirtio->uMsixConfig); 980 for (int i = 0; i < VIRTQ_MAX_CNT; i++) 981 { 982 virtioLowerInterrupt(pDevIns, pVirtio->uQueueMsixVector[i]); 983 pVirtio->uQueueMsixVector[i]; 984 } 985 } 955 986 956 987 if (!pVirtio->fMsiSupport) /* VirtIO 1.0, 4.1.4.3 and 4.1.5.1.2 */ 957 988 pVirtio->uMsixConfig = VIRTIO_MSI_NO_VECTOR; 958 989 959 pVirtio->uNumQueues = VIRTQ_MAX_CNT; 960 for (uint16_t idxQueue = 0; idxQueue < pVirtio->uNumQueues; idxQueue++) 990 for (uint16_t idxQueue = 0; idxQueue < VIRTQ_MAX_CNT; idxQueue++) 961 991 virtioResetQueue(pVirtio, idxQueue); 962 992 } 963 993 964 #if 0 /** @todo r=bird: Probably not needed. */ 965 /** 966 * Enable or disable queue 967 * 968 * @param pVirtio Pointer to the shared virtio state. 969 * @param idxQueue Queue number 970 * @param fEnabled Flag indicating whether to enable queue or not 971 */ 972 void virtioCoreQueueEnable(PVIRTIOCORE pVirtio, uint16_t idxQueue, bool fEnabled) 973 { 974 if (fEnabled) 975 pVirtio->uQueueSize[idxQueue] = VIRTQ_MAX_SIZE; 976 else 977 pVirtio->uQueueSize[idxQueue] = 0; 978 } 979 #endif 980 981 #if 0 /** @todo r=bird: This isn't invoked by anyone. Why? 982 For this and the previous I was just trying to provide flexibility 983 for other devices that might use this code r=paul */ 984 /** 985 * Initiate orderly reset procedure. 994 /** 995 * Initiate orderly reset procedure. This is an exposed API for clients that might need it. 986 996 * Invoked by client to reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2) 987 997 */ 988 998 void virtioCoreResetAll(PVIRTIOCORE pVirtio) 989 999 { 990 LogFunc((" VIRTIO RESET REQUESTED!!!\n"));1000 LogFunc(("\n")); 991 1001 pVirtio->uDeviceStatus |= VIRTIO_STATUS_DEVICE_NEEDS_RESET; 992 1002 if (pVirtio->uDeviceStatus & VIRTIO_STATUS_DRIVER_OK) 993 1003 { 994 1004 pVirtio->fGenUpdatePending = true; 995 virtioKick(pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */); 996 } 997 } 998 #endif 1005 virtioKick(pVirtio->pDevIns, pVirtio, VIRTIO_ISR_DEVICE_CONFIG, pVirtio->uMsixConfig, false /* fForce */); 1006 } 1007 } 999 1008 1000 1009 #ifdef IN_RING3 … … 1233 1242 { 1234 1243 Log6Func(("Guest read uDeviceStatus ................ (")); 1235 *(uint 32_t *)pv = pVirtio->uDeviceStatus; /** @todo r=bird: Why 32-bit write here, the field is 8-bit? */1244 *(uint8_t *)pv = pVirtio->uDeviceStatus; 1236 1245 virtioLogDeviceStatus(pVirtio->uDeviceStatus); 1237 1246 Log6((")\n")); … … 1341 1350 pVirtio->fGenUpdatePending = false; 1342 1351 } 1352 1353 if (pVirtio->fMsiSupport) 1354 PDMDevHlpPCISetIrq(pDevIns, pVirtio->uMsixConfig, PDM_IRQ_LEVEL_LOW); 1355 1343 1356 return rcStrict; 1344 1357 #else … … 1355 1368 Log6Func(("Read and clear ISR\n")); 1356 1369 pVirtio->uISR = 0; /* VirtIO specification requires reads of ISR to clear it */ 1357 virtioLowerInterrupt(pDevIns );1370 virtioLowerInterrupt(pDevIns, 0); 1358 1371 return VINF_SUCCESS; 1359 1372 } … … 1516 1529 int virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM) 1517 1530 { 1531 LogFunc(("\n")); 1518 1532 pHlp->pfnSSMPutU64(pSSM, VIRTIO_SAVEDSTATE_MARKER); 1519 1533 pHlp->pfnSSMPutU32(pSSM, VIRTIO_SAVEDSTATE_VERSION); … … 1528 1542 pHlp->pfnSSMPutU32(pSSM, pVirtio->uDriverFeaturesSelect); 1529 1543 pHlp->pfnSSMPutU64(pSSM, pVirtio->uDriverFeatures); 1530 Assert(pVirtio->uNumQueues == VIRTQ_MAX_CNT); /** @todo r=bird: See todo in struct & virtioCoreR3LoadExec. */ 1531 pHlp->pfnSSMPutU32(pSSM, pVirtio->uNumQueues); 1532 1533 for (uint32_t i = 0; i < pVirtio->uNumQueues; i++) 1544 1545 for (uint32_t i = 0; i < VIRTQ_MAX_CNT; i++) 1534 1546 { 1535 1547 pHlp->pfnSSMPutGCPhys64(pSSM, pVirtio->aGCPhysQueueDesc[i]); … … 1559 1571 int virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM) 1560 1572 { 1573 LogFunc(("\n")); 1561 1574 /* 1562 1575 * Check the marker and (embedded) version number. … … 1575 1588 return pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 1576 1589 N_("Unsupported virtio version: %u"), uVersion); 1577 1578 1590 /* 1579 1591 * Load the state. … … 1589 1601 pHlp->pfnSSMGetU64(pSSM, &pVirtio->uDriverFeatures); 1590 1602 1591 /* Make sure the queue count is within expectations. */ 1592 /** @todo r=bird: Turns out the expectations are exactly VIRTQ_MAX_CNT, bug? */ 1593 rc = pHlp->pfnSSMGetU32(pSSM, &pVirtio->uNumQueues); 1594 AssertRCReturn(rc, rc); 1595 AssertReturn(pVirtio->uNumQueues == VIRTQ_MAX_CNT, 1596 pHlp->pfnSSMSetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 1597 N_("Saved queue count %u, expected %u"), uVersion, VIRTQ_MAX_CNT)); 1598 AssertCompile(RT_ELEMENTS(pVirtio->virtqState) == VIRTQ_MAX_CNT); 1599 AssertCompile(RT_ELEMENTS(pVirtio->aGCPhysQueueDesc) == VIRTQ_MAX_CNT); 1600 1601 for (uint32_t idxQueue = 0; idxQueue < pVirtio->uNumQueues; idxQueue++) 1603 for (uint32_t idxQueue = 0; idxQueue < VIRTQ_MAX_CNT; idxQueue++) 1602 1604 { 1603 1605 pHlp->pfnSSMGetGCPhys64(pSSM, &pVirtio->aGCPhysQueueDesc[idxQueue]); … … 1629 1631 * @param pVirtio Pointer to the shared virtio state. 1630 1632 */ 1631 void virtioCoreR3PropagateResetNotification(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio) 1632 { 1633 /** @todo r=bird: You probably need to do something here. See 1634 * virtioScsiR3Reset. */ 1633 void virtioCoreR3VmStateChanged(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, VIRTIOVMSTATECHANGED enmState) 1634 { 1635 1636 LogFunc(("State changing to %s: ***FUNCTIONALITY TBD***\n", 1637 virtioCoreGetStateChangeText(enmState))); 1638 1639 switch(enmState) 1640 { 1641 case kvirtIoVmStateChangedReset: 1642 virtioCoreResetAll(pVirtio); 1643 break; 1644 case kvirtIoVmStateChangedSuspend: 1645 break; 1646 case kvirtIoVmStateChangedPowerOff: 1647 break; 1648 case kvirtIoVmStateChangedResume: 1649 break; 1650 default: 1651 LogRelFunc(("Bad enum value")); 1652 return; 1653 } 1635 1654 RT_NOREF(pDevIns, pVirtio); 1636 1655 } … … 1698 1717 AssertLogRelReturn(pVirtio == PDMINS_2_DATA(pDevIns, PVIRTIOCORE), VERR_STATE_CHANGED); 1699 1718 AssertLogRelReturn(pVirtioCC == PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC), VERR_STATE_CHANGED); 1719 1720 pVirtio->pDevIns = pDevIns; 1700 1721 1701 1722 /* -
trunk/src/VBox/Devices/VirtIO/Virtio_1_0.h
r81818 r81973 36 36 typedef CTX_SUFF(PVIRTIOCORE) PVIRTIOCORECC; 37 37 38 typedef enum VIRTIOVMSTATECHANGED 39 { 40 kvirtIoVmStateChangedInvalid = 0, 41 kvirtIoVmStateChangedReset, 42 kvirtIoVmStateChangedSuspend, 43 kvirtIoVmStateChangedPowerOff, 44 kvirtIoVmStateChangedResume, 45 kvirtIoVmStateChangedFor32BitHack = 0x7fffffff 46 } VIRTIOVMSTATECHANGED; 38 47 39 48 /** … … 159 168 typedef struct VIRTQSTATE 160 169 { 161 char 162 uint16_t 163 uint16_t 164 bool 170 char szVirtqName[32]; /**< Dev-specific name of queue */ 171 uint16_t uAvailIdx; /**< Consumer's position in avail ring */ 172 uint16_t uUsedIdx; /**< Consumer's position in used ring */ 173 bool fEventThresholdReached; /**< Don't lose track while queueing ahead */ 165 174 } VIRTQSTATE, *PVIRTQSTATE; 166 175 … … 222 231 { 223 232 char szInstance[16]; /**< Instance name, e.g. "VIRTIOSCSI0" */ 224 233 PPDMDEVINS pDevIns; /**< Client device instance */ 225 234 RTGCPHYS aGCPhysQueueDesc[VIRTQ_MAX_CNT]; /**< (MMIO) PhysAdr per-Q desc structs GUEST */ 226 235 RTGCPHYS aGCPhysQueueAvail[VIRTQ_MAX_CNT]; /**< (MMIO) PhysAdr per-Q avail structs GUEST */ … … 237 246 uint32_t uDriverFeaturesSelect; /**< (MMIO) hi/lo select uDriverFeatures GUEST */ 238 247 uint32_t uMsixConfig; /**< (MMIO) MSI-X vector GUEST */ 239 uint32_t uNumQueues; /**< (MMIO) Actual number of queues GUEST240 * @todo r=bird: This value is always VIRTQ_MAX_CNT241 * and only used in for loops. Guest always see242 * VIRTQ_MAX_CNT regardless of this value, so243 * what's the point of having this? */244 248 uint8_t uDeviceStatus; /**< (MMIO) Device Status GUEST */ 245 249 uint8_t uPrevDeviceStatus; /**< (MMIO) Prev Device Status GUEST */ … … 261 265 uint8_t uISR; /**< Interrupt Status Register. */ 262 266 uint8_t fMsiSupport; 263 264 267 265 268 /** The MMIO handle for the PCI capability region (\#2). */ … … 369 372 * @{ */ 370 373 371 int virtioCoreR3QueueAttach(PVIRTIOCORE pVirtio, uint16_t idxQueue, const char *pcszName); 372 #if 0 /* no such function */ 373 /** 374 * Detaches from queue and release resources 375 * 376 * @param hVirtio Handle for VirtIO framework 377 * @param idxQueue Queue number 378 */ 379 int virtioCoreR3QueueDetach(PVIRTIOCORE pVirtio, uint16_t idxQueue); 380 #endif 374 int virtioCoreR3QueueAttach(PVIRTIOCORE pVirtio, uint16_t idxQueue, const char *pcszName); 375 376 int virtioCoreR3DescChainGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, 377 uint16_t uHeadIdx, PPVIRTIO_DESC_CHAIN_T ppDescChain); 378 381 379 int virtioCoreR3QueueGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16_t idxQueue, 382 380 PPVIRTIO_DESC_CHAIN_T ppDescChain, bool fRemove); … … 388 386 389 387 /** 388 * Skip the next entry in the specified queue 389 * 390 * @param pVirtio Pointer to the virtio state. 391 * @param idxQueue Index of queue 392 * 393 */ 394 int virtioQueueSkip(PVIRTIOCORE pVirtio, uint16_t idxQueue); 395 396 /** 390 397 * Reset the device and driver (see VirtIO 1.0 section 2.1.1/2.1.2) 391 398 * … … 469 476 int virtioCoreR3SaveExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM); 470 477 int virtioCoreR3LoadExec(PVIRTIOCORE pVirtio, PCPDMDEVHLPR3 pHlp, PSSMHANDLE pSSM); 471 void virtioCoreR3PropagateResetNotification(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio); 472 void virtioCoreR3PropagateResumeNotification(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio); 478 void virtioCoreR3VmStateChanged(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, VIRTIOVMSTATECHANGED enmState); 473 479 void virtioCoreR3Term(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC); 474 480 int virtioCoreR3Init(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC, PVIRTIOPCIPARAMS pPciParams, 475 481 const char *pcszInstance, uint64_t fDevSpecificFeatures, void *pvDevSpecificCfg, uint16_t cbDevSpecificCfg); 476 482 int virtioCoreRZInit(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, PVIRTIOCORECC pVirtioCC); 483 const char *virtioCoreGetStateChangeText(VIRTIOVMSTATECHANGED enmState); 484 477 485 /** @} */ 478 486
Note:
See TracChangeset
for help on using the changeset viewer.