- Timestamp:
- Nov 17, 2009 11:37:40 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r24745 r24747 415 415 /** The position at which to get a new request for the AIO thread. */ 416 416 uint8_t AsyncIOReqTail; 417 /** Whether to call RTThreadUserSignal when idle. 418 * Before setting this, call RTThreadUserReset. */ 417 /** Whether to call PDMDevHlpAsyncNotificationCompleted when idle. */ 419 418 bool volatile fSignalIdle; 420 419 uint8_t Alignment3[1]; /**< Explicit padding of the 1 byte gap. */ … … 670 669 671 670 672 static const ATARequest ataDMARequest = { ATA_AIO_DMA, };673 static const ATARequest ataPIORequest = { ATA_AIO_PIO, };674 static const ATARequest ataResetARequest = { ATA_AIO_RESET_ASSERTED, };675 static const ATARequest ataResetCRequest = { ATA_AIO_RESET_CLEARED, };671 static const ATARequest g_ataDMARequest = { ATA_AIO_DMA, }; 672 static const ATARequest g_ataPIORequest = { ATA_AIO_PIO, }; 673 static const ATARequest g_ataResetARequest = { ATA_AIO_RESET_ASSERTED, }; 674 static const ATARequest g_ataResetCRequest = { ATA_AIO_RESET_CLEARED, }; 676 675 677 676 … … 3739 3738 } 3740 3739 3741 3742 /**3743 * Waits for a particular async I/O thread to complete whatever it3744 * is doing at the moment.3745 *3746 * @returns true on success.3747 * @returns false when the thread is still processing.3748 * @param pThis Pointer to the controller data.3749 * @param cMillies How long to wait (total). This isn't very3750 * accurate.3751 * @param fLeaveSignallingOn Leave the signalling on so that it will notifiy3752 * PDM about completion of the asynchronous3753 * notification.3754 */3755 static bool ataWaitForAsyncIOIsIdle(PATACONTROLLER pCtl, unsigned cMillies, bool fLeaveSignallingOn)3756 {3757 uint64_t u64Start;3758 bool fRc;3759 3760 /* Hope for the simple way out... */3761 if (ataAsyncIOIsIdle(pCtl, false /*fStrict*/))3762 return true;3763 3764 /*3765 * Have to wait. Do the setup while owning the mutex to avoid races.3766 */3767 RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);3768 3769 RTThreadUserReset(pCtl->AsyncIOThread);3770 ASMAtomicWriteBool(&pCtl->fSignalIdle, true);3771 3772 RTSemMutexRelease(pCtl->AsyncIORequestMutex);3773 3774 u64Start = RTTimeMilliTS();3775 for (;;)3776 {3777 fRc = ataAsyncIOIsIdle(pCtl, false /*fStrict*/);3778 if (fRc)3779 break;3780 3781 if (RTTimeMilliTS() - u64Start >= cMillies)3782 break;3783 3784 int rc = RTThreadUserWait(pCtl->AsyncIOThread, 100 /*ms*/);3785 AssertMsg( ( RT_SUCCESS(rc)3786 && ataAsyncIOIsIdle(pCtl, false /*fStrict*/))3787 || rc == VERR_TIMEOUT,3788 ("rc=%Rrc i=%u\n", rc, ATACONTROLLER_IDX(pCtl)));3789 }3790 3791 if (fRc || !fLeaveSignallingOn)3792 ASMAtomicWriteBool(&pCtl->fSignalIdle, false);3793 return fRc;3794 }3795 3796 /**3797 * Waits for all async I/O threads to complete whatever they are doing at the3798 * moment.3799 *3800 * @returns true on success.3801 * @returns false when one or more threads is still processing.3802 * @param pThis Pointer to the instance data.3803 * @param cMillies How long to wait per controller.3804 * @param fLeaveSignallingOn Leave the signalling on so that it will notifiy3805 * PDM about completion of the asynchronous3806 * notification.3807 */3808 static bool ataWaitForAllAsyncIOIsIdle(PPDMDEVINS pDevIns, uint32_t cMillies, bool fLeaveSignallingOn)3809 {3810 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);3811 3812 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)3813 if ( pThis->aCts[i].AsyncIOThread != NIL_RTTHREAD3814 && !ataWaitForAsyncIOIsIdle(&pThis->aCts[i], cMillies, fLeaveSignallingOn))3815 {3816 LogRel(("PIIX3 ATA: Ctl#%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n",3817 i, pThis->aCts[i].iSelectedIf, pThis->aCts[i].iAIOIf,3818 pThis->aCts[i].aIfs[0].uATARegCommand, pThis->aCts[i].aIfs[1].uATARegCommand));3819 return false;3820 }3821 return true;3822 }3823 3824 3740 #endif /* IN_RING3 */ 3825 3741 … … 4141 4057 4142 4058 /* Issue the reset request now. */ 4143 ataAsyncIOPutRequest(pCtl, & ataResetARequest);4059 ataAsyncIOPutRequest(pCtl, &g_ataResetARequest); 4144 4060 #else /* !IN_RING3 */ 4145 4061 AssertMsgFailed(("RESET handling is too complicated for GC\n")); … … 4158 4074 Log2(("%s: ignored setting HOB\n", __FUNCTION__)); 4159 4075 } 4160 ataAsyncIOPutRequest(pCtl, & ataResetCRequest);4076 ataAsyncIOPutRequest(pCtl, &g_ataResetCRequest); 4161 4077 #else /* !IN_RING3 */ 4162 4078 AssertMsgFailed(("RESET handling is too complicated for GC\n")); … … 4276 4192 4277 4193 Log2(("%s: Ctl#%d: message to async I/O thread, continuing PIO transfer\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl))); 4278 ataAsyncIOPutRequest(pCtl, & ataPIORequest);4194 ataAsyncIOPutRequest(pCtl, &g_ataPIORequest); 4279 4195 } 4280 4196 else … … 4562 4478 4563 4479 /** 4564 * Signal ataWaitForAsyncIOIsIdlethat we're idle (if we actually are).4480 * Signal PDM that we're idle (if we actually are). 4565 4481 * 4566 4482 * @param pCtl The controller. 4567 4483 */ 4568 static void ata AsyncSignalIdle(PATACONTROLLER pCtl)4484 static void ataR3AsyncSignalIdle(PATACONTROLLER pCtl) 4569 4485 { 4570 4486 /* 4571 * Take the mutex here and recheck the idle indicator as there might be4572 * interesting races, like in the ataReset code.4487 * Take the mutex here and recheck the idle indicator to avoid 4488 * unnecessary work and racing ataR3WaitForAsyncIOIsIdle. 4573 4489 */ 4574 4490 int rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT); AssertRC(rc); … … 4577 4493 && ataAsyncIOIsIdle(pCtl, false /*fStrict*/)) 4578 4494 { 4579 RTThreadUserSignal(pCtl->AsyncIOThread);4580 4495 PDMDevHlpAsyncNotificationCompleted(pCtl->pDevInsR3); 4496 RTThreadUserSignal(pCtl->AsyncIOThread); /* for ataR3Construct/ataR3ResetCommon. */ 4581 4497 } 4582 4498 … … 4605 4521 { 4606 4522 if (pCtl->fSignalIdle) 4607 ata AsyncSignalIdle(pCtl);4523 ataR3AsyncSignalIdle(pCtl); 4608 4524 rc = RTSemEventWait(pCtl->SuspendIOSem, RT_INDEFINITE_WAIT); 4609 4525 /* Continue if we got a signal by RTThreadPoke(). … … 4622 4538 { 4623 4539 if (pCtl->fSignalIdle) 4624 ata AsyncSignalIdle(pCtl);4540 ataR3AsyncSignalIdle(pCtl); 4625 4541 rc = RTSemEventWait(pCtl->AsyncIOSem, RT_INDEFINITE_WAIT); 4626 4542 /* Continue if we got a signal by RTThreadPoke(). … … 4765 4681 { 4766 4682 Log2(("%s: Ctl#%d: message to async I/O thread, continuing DMA transfer immediately\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl))); 4767 ataAsyncIOPutRequest(pCtl, & ataDMARequest);4683 ataAsyncIOPutRequest(pCtl, &g_ataDMARequest); 4768 4684 } 4769 4685 } … … 4841 4757 { 4842 4758 LogRel(("PIIX3 ATA: Ctl#%d: redo DMA operation\n", ATACONTROLLER_IDX(pCtl))); 4843 ataAsyncIOPutRequest(pCtl, & ataDMARequest);4759 ataAsyncIOPutRequest(pCtl, &g_ataDMARequest); 4844 4760 break; 4845 4761 } … … 4886 4802 { 4887 4803 LogRel(("PIIX3 ATA: Ctl#%d: redo PIO operation\n", ATACONTROLLER_IDX(pCtl))); 4888 ataAsyncIOPutRequest(pCtl, & ataPIORequest);4804 ataAsyncIOPutRequest(pCtl, &g_ataPIORequest); 4889 4805 ataSuspendRedo(pCtl); 4890 4806 break; … … 5061 4977 5062 4978 /* Signal the ultimate idleness. */ 5063 RTThreadUserSignal(ThreadSelf); 4979 RTThreadUserSignal(pCtl->AsyncIOThread); 4980 if (pCtl->fSignalIdle) 4981 PDMDevHlpAsyncNotificationCompleted(pCtl->pDevInsR3); 5064 4982 5065 4983 /* Cleanup the state. */ … … 5112 5030 { 5113 5031 Log2(("%s: Ctl#%d: message to async I/O thread, continuing DMA transfer\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl))); 5114 ataAsyncIOPutRequest(pCtl, & ataDMARequest);5032 ataAsyncIOPutRequest(pCtl, &g_ataDMARequest); 5115 5033 } 5116 5034 #else /* !IN_RING3 */ … … 5286 5204 5287 5205 5288 /**5289 * Callback employed by ataSuspend and ataPowerOff.5290 *5291 * @returns true if we've quiesced, false if we're still working.5292 * @param pDevIns The device instance.5293 */5294 static DECLCALLBACK(bool) ataR3IsAsyncResetDone(PPDMDEVINS pDevIns)5295 {5296 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);5297 5298 if ( !ataWaitForAsyncIOIsIdle(&pThis->aCts[0], 1, true /*fLeaveSignallingOn*/)5299 || !ataWaitForAsyncIOIsIdle(&pThis->aCts[1], 1, true /*fLeaveSignallingOn*/))5300 return false;5301 5302 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)5303 {5304 PDMCritSectEnter(&pThis->aCts[i].lock, VERR_INTERNAL_ERROR);5305 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)5306 ataResetDevice(&pThis->aCts[i].aIfs[j]);5307 PDMCritSectLeave(&pThis->aCts[i].lock);5308 }5309 PDMDevHlpAsyncNotificationCompleted(pDevIns);5310 return true;5311 }5312 5313 5314 /**5315 * Reset notification.5316 *5317 * @returns VBox status.5318 * @param pDevIns The device instance data.5319 */5320 static DECLCALLBACK(void) ataReset(PPDMDEVINS pDevIns)5321 {5322 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);5323 5324 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)5325 {5326 PDMCritSectEnter(&pThis->aCts[i].lock, VERR_INTERNAL_ERROR);5327 5328 pThis->aCts[i].iSelectedIf = 0;5329 pThis->aCts[i].iAIOIf = 0;5330 pThis->aCts[i].BmDma.u8Cmd = 0;5331 /* Report that both drives present on the bus are in DMA mode. This5332 * pretends that there is a BIOS that has set it up. Normal reset5333 * default is 0x00. */5334 pThis->aCts[i].BmDma.u8Status = (pThis->aCts[i].aIfs[0].pDrvBase != NULL ? BM_STATUS_D0DMA : 0)5335 | (pThis->aCts[i].aIfs[1].pDrvBase != NULL ? BM_STATUS_D1DMA : 0);5336 pThis->aCts[i].BmDma.pvAddr = 0;5337 5338 pThis->aCts[i].fReset = true;5339 pThis->aCts[i].fRedo = false;5340 pThis->aCts[i].fRedoIdle = false;5341 ataAsyncIOClearRequests(&pThis->aCts[i]);5342 Log2(("%s: Ctl#%d: message to async I/O thread, reset controller\n", __FUNCTION__, i));5343 ataAsyncIOPutRequest(&pThis->aCts[i], &ataResetARequest);5344 ataAsyncIOPutRequest(&pThis->aCts[i], &ataResetCRequest);5345 5346 PDMCritSectLeave(&pThis->aCts[i].lock);5347 }5348 5349 /*5350 * Only reset the devices when both threads have quiesced.5351 */5352 if ( ataWaitForAsyncIOIsIdle(&pThis->aCts[0], 2, true /*fLeaveSignallingOn*/)5353 && ataWaitForAsyncIOIsIdle(&pThis->aCts[1], 2, true /*fLeaveSignallingOn*/))5354 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++)5355 {5356 PDMCritSectEnter(&pThis->aCts[i].lock, VERR_INTERNAL_ERROR);5357 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++)5358 ataResetDevice(&pThis->aCts[i].aIfs[j]);5359 PDMCritSectLeave(&pThis->aCts[i].lock);5360 }5361 else5362 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncResetDone);5363 }5364 5365 5366 5206 /* -=-=-=-=-=- PCIATAState::IBase -=-=-=-=-=- */ 5367 5207 … … 5670 5510 #ifdef IN_RING3 5671 5511 5672 /**5673 * Callback employed by ataSuspend and ataPowerOff.5674 *5675 * @returns true if we've quiesced, false if we're still working.5676 * @param pDevIns The device instance.5677 */5678 static DECLCALLBACK(bool) ataR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)5679 {5680 return ataWaitForAllAsyncIOIsIdle(pDevIns, 0, true /*fLeaveSignallingOn*/);5681 }5682 5683 5684 /**5685 * Common worker for ataSuspend and ataPowerOff.5686 */5687 static void ataR3SuspendOrPowerOff(PPDMDEVINS pDevIns)5688 {5689 #if 15690 if (!ataWaitForAllAsyncIOIsIdle(pDevIns, 0, true /*fLeaveSignallingOn*/))5691 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncSuspendOrPowerOffDone);5692 #else5693 if (!ataWaitForAllAsyncIOIsIdle(pDevIns, 20000))5694 AssertMsgFailed(("Async I/O didn't stop in ~40 seconds!\n"));5695 #endif5696 }5697 5698 5512 5699 5513 DECLINLINE(void) ataRelocBuffer(PPDMDEVINS pDevIns, ATADevState *s) … … 5707 5521 * @copydoc FNPDMDEVRELOCATE 5708 5522 */ 5709 static DECLCALLBACK(void) ataR elocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)5523 static DECLCALLBACK(void) ataR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta) 5710 5524 { 5711 5525 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); … … 5732 5546 * @param pDevIns The device instance data. 5733 5547 */ 5734 static DECLCALLBACK(int) ata Destruct(PPDMDEVINS pDevIns)5548 static DECLCALLBACK(int) ataR3Destruct(PPDMDEVINS pDevIns) 5735 5549 { 5736 5550 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 5737 5551 int rc; 5738 5552 5739 Log(("ata Destruct\n"));5553 Log(("ataR3Destruct\n")); 5740 5554 5741 5555 /* … … 5815 5629 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 5816 5630 */ 5817 static DECLCALLBACK(void) ata Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)5631 static DECLCALLBACK(void) ataR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 5818 5632 { 5819 5633 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); … … 5992 5806 * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines. 5993 5807 */ 5994 static DECLCALLBACK(int) ata Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)5808 static DECLCALLBACK(int) ataR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags) 5995 5809 { 5996 5810 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); … … 6047 5861 6048 5862 /** 6049 * Suspend notification.6050 *6051 * @returns VBox status.6052 * @param pDevIns The device instance data.6053 */6054 static DECLCALLBACK(void) ataSuspend(PPDMDEVINS pDevIns)6055 {6056 Log(("%s:\n", __FUNCTION__));6057 ataR3SuspendOrPowerOff(pDevIns);6058 }6059 6060 6061 /**6062 5863 * Resume notification. 6063 5864 * … … 6065 5866 * @param pDevIns The device instance data. 6066 5867 */ 6067 static DECLCALLBACK(void) ataR esume(PPDMDEVINS pDevIns)5868 static DECLCALLBACK(void) ataR3Resume(PPDMDEVINS pDevIns) 6068 5869 { 6069 5870 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); … … 6080 5881 } 6081 5882 return; 5883 } 5884 5885 5886 /** 5887 * Checks if all (both) the async I/O threads have quiesced. 5888 * 5889 * @returns true on success. 5890 * @returns false when one or more threads is still processing. 5891 * @param pThis Pointer to the instance data. 5892 */ 5893 static bool ataR3AllAsyncIOIsIdle(PPDMDEVINS pDevIns) 5894 { 5895 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 5896 5897 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++) 5898 if (pThis->aCts[i].AsyncIOThread != NIL_RTTHREAD) 5899 { 5900 bool fRc = ataAsyncIOIsIdle(&pThis->aCts[i], false /*fStrict*/); 5901 if (!fRc) 5902 { 5903 /* Make it signal PDM & itself when its done */ 5904 RTSemMutexRequest(pThis->aCts[i].AsyncIORequestMutex, RT_INDEFINITE_WAIT); 5905 ASMAtomicWriteBool(&pThis->aCts[i].fSignalIdle, true); 5906 RTSemMutexRelease(pThis->aCts[i].AsyncIORequestMutex); 5907 fRc = ataAsyncIOIsIdle(&pThis->aCts[i], false /*fStrict*/); 5908 if (!fRc) 5909 { 5910 #if 0 /** @todo Need to do some time tracking here... */ 5911 LogRel(("PIIX3 ATA: Ctl#%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x\n", 5912 i, pThis->aCts[i].iSelectedIf, pThis->aCts[i].iAIOIf, 5913 pThis->aCts[i].aIfs[0].uATARegCommand, pThis->aCts[i].aIfs[1].uATARegCommand)); 5914 #endif 5915 return false; 5916 } 5917 } 5918 ASMAtomicWriteBool(&pThis->aCts[i].fSignalIdle, false); 5919 } 5920 return true; 5921 } 5922 5923 5924 /** 5925 * Callback employed by ataSuspend and ataR3PowerOff. 5926 * 5927 * @returns true if we've quiesced, false if we're still working. 5928 * @param pDevIns The device instance. 5929 */ 5930 static DECLCALLBACK(bool) ataR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns) 5931 { 5932 return ataR3AllAsyncIOIsIdle(pDevIns); 5933 } 5934 5935 5936 /** 5937 * Common worker for ataSuspend and ataR3PowerOff. 5938 */ 5939 static void ataR3SuspendOrPowerOff(PPDMDEVINS pDevIns) 5940 { 5941 if (!ataR3AllAsyncIOIsIdle(pDevIns)) 5942 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncSuspendOrPowerOffDone); 6082 5943 } 6083 5944 … … 6089 5950 * @param pDevIns The device instance data. 6090 5951 */ 6091 static DECLCALLBACK(void) ata PowerOff(PPDMDEVINS pDevIns)5952 static DECLCALLBACK(void) ataR3PowerOff(PPDMDEVINS pDevIns) 6092 5953 { 6093 5954 Log(("%s:\n", __FUNCTION__)); 6094 5955 ataR3SuspendOrPowerOff(pDevIns); 5956 } 5957 5958 5959 /** 5960 * Suspend notification. 5961 * 5962 * @returns VBox status. 5963 * @param pDevIns The device instance data. 5964 */ 5965 static DECLCALLBACK(void) ataR3Suspend(PPDMDEVINS pDevIns) 5966 { 5967 Log(("%s:\n", __FUNCTION__)); 5968 ataR3SuspendOrPowerOff(pDevIns); 5969 } 5970 5971 5972 /** 5973 * Callback employed by ataR3Reset. 5974 * 5975 * @returns true if we've quiesced, false if we're still working. 5976 * @param pDevIns The device instance. 5977 */ 5978 static DECLCALLBACK(bool) ataR3IsAsyncResetDone(PPDMDEVINS pDevIns) 5979 { 5980 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 5981 5982 if (!ataR3AllAsyncIOIsIdle(pDevIns)) 5983 return false; 5984 5985 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++) 5986 { 5987 PDMCritSectEnter(&pThis->aCts[i].lock, VERR_INTERNAL_ERROR); 5988 for (uint32_t j = 0; j < RT_ELEMENTS(pThis->aCts[i].aIfs); j++) 5989 ataResetDevice(&pThis->aCts[i].aIfs[j]); 5990 PDMCritSectLeave(&pThis->aCts[i].lock); 5991 } 5992 return true; 5993 } 5994 5995 5996 /** 5997 * Common reset worker for ataR3Reset and ataR3Construct. 5998 * 5999 * @returns VBox status. 6000 * @param pDevIns The device instance data. 6001 * @param fConstruct Indicates who is calling. 6002 */ 6003 static int ataR3ResetCommon(PPDMDEVINS pDevIns, bool fConstruct) 6004 { 6005 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); 6006 6007 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++) 6008 { 6009 PDMCritSectEnter(&pThis->aCts[i].lock, VERR_INTERNAL_ERROR); 6010 6011 pThis->aCts[i].iSelectedIf = 0; 6012 pThis->aCts[i].iAIOIf = 0; 6013 pThis->aCts[i].BmDma.u8Cmd = 0; 6014 /* Report that both drives present on the bus are in DMA mode. This 6015 * pretends that there is a BIOS that has set it up. Normal reset 6016 * default is 0x00. */ 6017 pThis->aCts[i].BmDma.u8Status = (pThis->aCts[i].aIfs[0].pDrvBase != NULL ? BM_STATUS_D0DMA : 0) 6018 | (pThis->aCts[i].aIfs[1].pDrvBase != NULL ? BM_STATUS_D1DMA : 0); 6019 pThis->aCts[i].BmDma.pvAddr = 0; 6020 6021 pThis->aCts[i].fReset = true; 6022 pThis->aCts[i].fRedo = false; 6023 pThis->aCts[i].fRedoIdle = false; 6024 ataAsyncIOClearRequests(&pThis->aCts[i]); 6025 Log2(("%s: Ctl#%d: message to async I/O thread, reset controller\n", __FUNCTION__, i)); 6026 ataAsyncIOPutRequest(&pThis->aCts[i], &g_ataResetARequest); 6027 ataAsyncIOPutRequest(&pThis->aCts[i], &g_ataResetCRequest); 6028 6029 PDMCritSectLeave(&pThis->aCts[i].lock); 6030 } 6031 6032 int rcRet = VINF_SUCCESS; 6033 if (!fConstruct) 6034 { 6035 /* 6036 * Setup asynchronous notification compmletion if the requests haven't 6037 * completed yet. 6038 */ 6039 if (!ataR3IsAsyncResetDone(pDevIns)) 6040 PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncResetDone); 6041 } 6042 else 6043 { 6044 /* 6045 * Wait for the requests for complete. 6046 * 6047 * Would be real nice if we could do it all from EMT(0) and not 6048 * involve the worker threads, then we could dispense with all the 6049 * waiting and semaphore ping-pong here... 6050 */ 6051 for (uint32_t i = 0; i < RT_ELEMENTS(pThis->aCts); i++) 6052 { 6053 if (pThis->aCts[i].AsyncIOThread != NIL_RTTHREAD) 6054 { 6055 int rc = RTSemMutexRequest(pThis->aCts[i].AsyncIORequestMutex, RT_INDEFINITE_WAIT); 6056 AssertRC(rc); 6057 6058 ASMAtomicWriteBool(&pThis->aCts[i].fSignalIdle, true); 6059 rc = RTThreadUserReset(pThis->aCts[i].AsyncIOThread); 6060 AssertRC(rc); 6061 6062 rc = RTSemMutexRelease(pThis->aCts[i].AsyncIORequestMutex); 6063 AssertRC(rc); 6064 6065 if (!ataAsyncIOIsIdle(&pThis->aCts[i], false /*fStrict*/)) 6066 { 6067 rc = RTThreadUserWait(pThis->aCts[i].AsyncIOThread, 30*1000 /*ms*/); 6068 if (RT_FAILURE(rc)) 6069 rc = RTThreadUserWait(pThis->aCts[i].AsyncIOThread, 1000 /*ms*/); 6070 if (RT_FAILURE(rc)) 6071 { 6072 AssertRC(rc); 6073 rcRet = rc; 6074 } 6075 } 6076 } 6077 ASMAtomicWriteBool(&pThis->aCts[i].fSignalIdle, false); 6078 } 6079 if (RT_SUCCESS(rcRet)) 6080 { 6081 rcRet = ataR3IsAsyncResetDone(pDevIns) ? VINF_SUCCESS : VERR_INTERNAL_ERROR; 6082 AssertRC(rcRet); 6083 } 6084 } 6085 return rcRet; 6086 } 6087 6088 6089 /** 6090 * Reset notification. 6091 * 6092 * @param pDevIns The device instance data. 6093 */ 6094 static DECLCALLBACK(void) ataR3Reset(PPDMDEVINS pDevIns) 6095 { 6096 ataR3ResetCommon(pDevIns, false /*fConstruct*/); 6095 6097 } 6096 6098 … … 6484 6486 * iInstance it's expected to be used a bit in this function. 6485 6487 */ 6486 static DECLCALLBACK(int) ata Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)6488 static DECLCALLBACK(int) ataR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle) 6487 6489 { 6488 6490 PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *); … … 6951 6953 * Initialize the device state. 6952 6954 */ 6953 ataReset(pDevIns); 6954 6955 return VINF_SUCCESS; 6955 return ataR3ResetCommon(pDevIns, true /*fConstruct*/); 6956 6956 } 6957 6957 … … 6987 6987 sizeof(PCIATAState), 6988 6988 /* pfnConstruct */ 6989 ata Construct,6989 ataR3Construct, 6990 6990 /* pfnDestruct */ 6991 ata Destruct,6991 ataR3Destruct, 6992 6992 /* pfnRelocate */ 6993 ataR elocate,6993 ataR3Relocate, 6994 6994 /* pfnIOCtl */ 6995 6995 NULL, … … 6997 6997 NULL, 6998 6998 /* pfnReset */ 6999 ataR eset,6999 ataR3Reset, 7000 7000 /* pfnSuspend */ 7001 ata Suspend,7001 ataR3Suspend, 7002 7002 /* pfnResume */ 7003 ataR esume,7003 ataR3Resume, 7004 7004 /* pfnAttach */ 7005 ata Attach,7005 ataR3Attach, 7006 7006 /* pfnDetach */ 7007 ata Detach,7007 ataR3Detach, 7008 7008 /* pfnQueryInterface. */ 7009 7009 NULL, … … 7011 7011 NULL, 7012 7012 /* pfnPowerOff */ 7013 ata PowerOff,7013 ataR3PowerOff, 7014 7014 /* pfnSoftReset */ 7015 7015 NULL,
Note:
See TracChangeset
for help on using the changeset viewer.