VirtualBox

Changeset 24747 in vbox for trunk


Ignore:
Timestamp:
Nov 17, 2009 11:37:40 PM (15 years ago)
Author:
vboxsync
Message:

DevATA: Cleanup the waiting for idle stuff... only ataR3Construct needs wait no (annoying).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/DevATA.cpp

    r24745 r24747  
    415415    /** The position at which to get a new request for the AIO thread. */
    416416    uint8_t             AsyncIOReqTail;
    417     /** Whether to call RTThreadUserSignal when idle.
    418      * Before setting this, call RTThreadUserReset. */
     417    /** Whether to call PDMDevHlpAsyncNotificationCompleted when idle. */
    419418    bool volatile       fSignalIdle;
    420419    uint8_t             Alignment3[1]; /**< Explicit padding of the 1 byte gap. */
     
    670669
    671670
    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, };
     671static const ATARequest g_ataDMARequest = { ATA_AIO_DMA, };
     672static const ATARequest g_ataPIORequest = { ATA_AIO_PIO, };
     673static const ATARequest g_ataResetARequest = { ATA_AIO_RESET_ASSERTED, };
     674static const ATARequest g_ataResetCRequest = { ATA_AIO_RESET_CLEARED, };
    676675
    677676
     
    37393738}
    37403739
    3741 
    3742 /**
    3743  * Waits for a particular async I/O thread to complete whatever it
    3744  * 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 very
    3750  *                              accurate.
    3751  * @param   fLeaveSignallingOn  Leave the signalling on so that it will notifiy
    3752  *                              PDM about completion of the asynchronous
    3753  *                              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 the
    3798  * 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 notifiy
    3805  *                              PDM about completion of the asynchronous
    3806  *                              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_RTTHREAD
    3814             && !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 
    38243740#endif /* IN_RING3 */
    38253741
     
    41414057
    41424058        /* Issue the reset request now. */
    4143         ataAsyncIOPutRequest(pCtl, &ataResetARequest);
     4059        ataAsyncIOPutRequest(pCtl, &g_ataResetARequest);
    41444060#else /* !IN_RING3 */
    41454061        AssertMsgFailed(("RESET handling is too complicated for GC\n"));
     
    41584074            Log2(("%s: ignored setting HOB\n", __FUNCTION__));
    41594075        }
    4160         ataAsyncIOPutRequest(pCtl, &ataResetCRequest);
     4076        ataAsyncIOPutRequest(pCtl, &g_ataResetCRequest);
    41614077#else /* !IN_RING3 */
    41624078        AssertMsgFailed(("RESET handling is too complicated for GC\n"));
     
    42764192
    42774193        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);
    42794195    }
    42804196    else
     
    45624478
    45634479/**
    4564  * Signal ataWaitForAsyncIOIsIdle that we're idle (if we actually are).
     4480 * Signal PDM that we're idle (if we actually are).
    45654481 *
    45664482 * @param   pCtl        The controller.
    45674483 */
    4568 static void ataAsyncSignalIdle(PATACONTROLLER pCtl)
     4484static void ataR3AsyncSignalIdle(PATACONTROLLER pCtl)
    45694485{
    45704486    /*
    4571      * Take the mutex here and recheck the idle indicator as there might be
    4572      * 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.
    45734489     */
    45744490    int rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT); AssertRC(rc);
     
    45774493        &&  ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
    45784494    {
    4579         RTThreadUserSignal(pCtl->AsyncIOThread);
    45804495        PDMDevHlpAsyncNotificationCompleted(pCtl->pDevInsR3);
     4496        RTThreadUserSignal(pCtl->AsyncIOThread); /* for ataR3Construct/ataR3ResetCommon. */
    45814497    }
    45824498
     
    46054521        {
    46064522            if (pCtl->fSignalIdle)
    4607                 ataAsyncSignalIdle(pCtl);
     4523                ataR3AsyncSignalIdle(pCtl);
    46084524            rc = RTSemEventWait(pCtl->SuspendIOSem, RT_INDEFINITE_WAIT);
    46094525            /* Continue if we got a signal by RTThreadPoke().
     
    46224538        {
    46234539            if (pCtl->fSignalIdle)
    4624                 ataAsyncSignalIdle(pCtl);
     4540                ataR3AsyncSignalIdle(pCtl);
    46254541            rc = RTSemEventWait(pCtl->AsyncIOSem, RT_INDEFINITE_WAIT);
    46264542            /* Continue if we got a signal by RTThreadPoke().
     
    47654681                        {
    47664682                            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);
    47684684                        }
    47694685                    }
     
    48414757                {
    48424758                    LogRel(("PIIX3 ATA: Ctl#%d: redo DMA operation\n", ATACONTROLLER_IDX(pCtl)));
    4843                     ataAsyncIOPutRequest(pCtl, &ataDMARequest);
     4759                    ataAsyncIOPutRequest(pCtl, &g_ataDMARequest);
    48444760                    break;
    48454761                }
     
    48864802                    {
    48874803                        LogRel(("PIIX3 ATA: Ctl#%d: redo PIO operation\n", ATACONTROLLER_IDX(pCtl)));
    4888                         ataAsyncIOPutRequest(pCtl, &ataPIORequest);
     4804                        ataAsyncIOPutRequest(pCtl, &g_ataPIORequest);
    48894805                        ataSuspendRedo(pCtl);
    48904806                        break;
     
    50614977
    50624978    /* Signal the ultimate idleness. */
    5063     RTThreadUserSignal(ThreadSelf);
     4979    RTThreadUserSignal(pCtl->AsyncIOThread);
     4980    if (pCtl->fSignalIdle)
     4981        PDMDevHlpAsyncNotificationCompleted(pCtl->pDevInsR3);
    50644982
    50654983    /* Cleanup the state.  */
     
    51125030        {
    51135031            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);
    51155033        }
    51165034#else /* !IN_RING3 */
     
    52865204
    52875205
    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. This
    5332          * pretends that there is a BIOS that has set it up. Normal reset
    5333          * 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     else
    5362         PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncResetDone);
    5363 }
    5364 
    5365 
    53665206/* -=-=-=-=-=- PCIATAState::IBase  -=-=-=-=-=- */
    53675207
     
    56705510#ifdef IN_RING3
    56715511
    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 1
    5690     if (!ataWaitForAllAsyncIOIsIdle(pDevIns, 0, true /*fLeaveSignallingOn*/))
    5691         PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncSuspendOrPowerOffDone);
    5692 #else
    5693     if (!ataWaitForAllAsyncIOIsIdle(pDevIns, 20000))
    5694         AssertMsgFailed(("Async I/O didn't stop in ~40 seconds!\n"));
    5695 #endif
    5696 }
    5697 
    56985512
    56995513DECLINLINE(void) ataRelocBuffer(PPDMDEVINS pDevIns, ATADevState *s)
     
    57075521 * @copydoc FNPDMDEVRELOCATE
    57085522 */
    5709 static DECLCALLBACK(void) ataRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
     5523static DECLCALLBACK(void) ataR3Relocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
    57105524{
    57115525    PCIATAState *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
     
    57325546 * @param   pDevIns     The device instance data.
    57335547 */
    5734 static DECLCALLBACK(int) ataDestruct(PPDMDEVINS pDevIns)
     5548static DECLCALLBACK(int) ataR3Destruct(PPDMDEVINS pDevIns)
    57355549{
    57365550    PCIATAState    *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
    57375551    int             rc;
    57385552
    5739     Log(("ataDestruct\n"));
     5553    Log(("ataR3Destruct\n"));
    57405554
    57415555    /*
     
    58155629 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    58165630 */
    5817 static DECLCALLBACK(void) ataDetach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     5631static DECLCALLBACK(void) ataR3Detach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    58185632{
    58195633    PCIATAState    *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
     
    59925806 * @param   fFlags      Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
    59935807 */
    5994 static DECLCALLBACK(int)  ataAttach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
     5808static DECLCALLBACK(int)  ataR3Attach(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags)
    59955809{
    59965810    PCIATAState    *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
     
    60475861
    60485862/**
    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 /**
    60625863 * Resume notification.
    60635864 *
     
    60655866 * @param   pDevIns     The device instance data.
    60665867 */
    6067 static DECLCALLBACK(void) ataResume(PPDMDEVINS pDevIns)
     5868static DECLCALLBACK(void) ataR3Resume(PPDMDEVINS pDevIns)
    60685869{
    60695870    PCIATAState    *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
     
    60805881    }
    60815882    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 */
     5893static 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 */
     5930static DECLCALLBACK(bool) ataR3IsAsyncSuspendOrPowerOffDone(PPDMDEVINS pDevIns)
     5931{
     5932    return ataR3AllAsyncIOIsIdle(pDevIns);
     5933}
     5934
     5935
     5936/**
     5937 * Common worker for ataSuspend and ataR3PowerOff.
     5938 */
     5939static void ataR3SuspendOrPowerOff(PPDMDEVINS pDevIns)
     5940{
     5941    if (!ataR3AllAsyncIOIsIdle(pDevIns))
     5942        PDMDevHlpSetAsyncNotification(pDevIns, ataR3IsAsyncSuspendOrPowerOffDone);
    60825943}
    60835944
     
    60895950 * @param   pDevIns     The device instance data.
    60905951 */
    6091 static DECLCALLBACK(void) ataPowerOff(PPDMDEVINS pDevIns)
     5952static DECLCALLBACK(void) ataR3PowerOff(PPDMDEVINS pDevIns)
    60925953{
    60935954    Log(("%s:\n", __FUNCTION__));
    60945955    ataR3SuspendOrPowerOff(pDevIns);
     5956}
     5957
     5958
     5959/**
     5960 * Suspend notification.
     5961 *
     5962 * @returns VBox status.
     5963 * @param   pDevIns     The device instance data.
     5964 */
     5965static 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 */
     5978static 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 */
     6003static 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 */
     6094static DECLCALLBACK(void)  ataR3Reset(PPDMDEVINS pDevIns)
     6095{
     6096    ataR3ResetCommon(pDevIns, false /*fConstruct*/);
    60956097}
    60966098
     
    64846486 *                      iInstance it's expected to be used a bit in this function.
    64856487 */
    6486 static DECLCALLBACK(int)   ataConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
     6488static DECLCALLBACK(int)   ataR3Construct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfgHandle)
    64876489{
    64886490    PCIATAState    *pThis = PDMINS_2_DATA(pDevIns, PCIATAState *);
     
    69516953     * Initialize the device state.
    69526954     */
    6953     ataReset(pDevIns);
    6954 
    6955     return VINF_SUCCESS;
     6955    return ataR3ResetCommon(pDevIns, true /*fConstruct*/);
    69566956}
    69576957
     
    69876987    sizeof(PCIATAState),
    69886988    /* pfnConstruct */
    6989     ataConstruct,
     6989    ataR3Construct,
    69906990    /* pfnDestruct */
    6991     ataDestruct,
     6991    ataR3Destruct,
    69926992    /* pfnRelocate */
    6993     ataRelocate,
     6993    ataR3Relocate,
    69946994    /* pfnIOCtl */
    69956995    NULL,
     
    69976997    NULL,
    69986998    /* pfnReset */
    6999     ataReset,
     6999    ataR3Reset,
    70007000    /* pfnSuspend */
    7001     ataSuspend,
     7001    ataR3Suspend,
    70027002    /* pfnResume */
    7003     ataResume,
     7003    ataR3Resume,
    70047004    /* pfnAttach */
    7005     ataAttach,
     7005    ataR3Attach,
    70067006    /* pfnDetach */
    7007     ataDetach,
     7007    ataR3Detach,
    70087008    /* pfnQueryInterface. */
    70097009    NULL,
     
    70117011    NULL,
    70127012    /* pfnPowerOff */
    7013     ataPowerOff,
     7013    ataR3PowerOff,
    70147014    /* pfnSoftReset */
    70157015    NULL,
Note: See TracChangeset for help on using the changeset viewer.

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