VirtualBox

Changeset 2872 in vbox for trunk/src/VBox/Devices/Storage


Ignore:
Timestamp:
May 25, 2007 1:52:35 PM (18 years ago)
Author:
vboxsync
Message:

Fixed the Linux PIO read fix. Now it shouldn't hang Windows installs
from CD.

File:
1 edited

Legend:

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

    r2862 r2872  
    36073607#ifdef IN_RING3
    36083608
     3609static void ataPIOTransfer(PATACONTROLLER pCtl)
     3610{
     3611    ATADevState *s;
     3612
     3613    s = &pCtl->aIfs[pCtl->iAIOIf];
     3614    Log3(("%s: if=%p\n", __FUNCTION__, s));
     3615
     3616    if (s->cbTotalTransfer && s->iIOBufferCur > s->iIOBufferEnd)
     3617    {
     3618        LogRel(("PIIX3 ATA: LUN#%d: %s data in the middle of a PIO transfer - VERY SLOW\n", s->iLUN, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "storing" : "loading"));
     3619        /* Any guest OS that triggers this case has a pathetic ATA driver.
     3620         * In a real system it would block the CPU via IORDY, here we do it
     3621         * very similarly by not continuing with the current instruction
     3622         * until the transfer to/from the storage medium is completed. */
     3623        if (s->iSourceSink != ATAFN_SS_NULL)
     3624        {
     3625            bool fRedo;
     3626            uint8_t status = s->uATARegStatus;
     3627            ataSetStatusValue(s, ATA_STAT_BUSY);
     3628            Log2(("%s: calling source/sink function\n", __FUNCTION__));
     3629            fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
     3630            pCtl->fRedo = fRedo;
     3631            if (RT_UNLIKELY(fRedo))
     3632                return;
     3633            ataSetStatusValue(s, status);
     3634            s->iIOBufferCur = 0;
     3635            s->iIOBufferEnd = s->cbElementaryTransfer;
     3636        }
     3637    }
     3638    if (s->cbTotalTransfer)
     3639    {
     3640        if (s->fATAPITransfer)
     3641            ataPIOTransferLimitATAPI(s);
     3642
     3643        if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
     3644            s->cbElementaryTransfer = s->cbTotalTransfer;
     3645
     3646        Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
     3647             __FUNCTION__, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T",
     3648             s->cbTotalTransfer, s->cbElementaryTransfer,
     3649             s->iIOBufferCur, s->iIOBufferEnd));
     3650        ataPIOTransferStart(s, s->iIOBufferCur, s->cbElementaryTransfer);
     3651        s->cbTotalTransfer -= s->cbElementaryTransfer;
     3652        s->iIOBufferCur += s->cbElementaryTransfer;
     3653
     3654        if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
     3655            s->cbElementaryTransfer = s->cbTotalTransfer;
     3656    }
     3657    else
     3658        ataPIOTransferStop(s);
     3659}
     3660
     3661
    36093662DECLINLINE(void) ataPIOTransferFinish(PATACONTROLLER pCtl, ATADevState *s)
    36103663{
     
    36173670    }
    36183671
    3619     ataUnsetStatus(s, ATA_STAT_READY | ATA_STAT_DRQ);
    3620     ataSetStatus(s, ATA_STAT_BUSY);
    3621 
    3622     Log2(("%s: Ctl#%d: message to async I/O thread, continuing PIO transfer\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl)));
    3623     ataAsyncIOPutRequest(pCtl, &ataPIORequest);
     3672    if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
     3673    {
     3674        /* Need to continue the transfer in the async I/O thread. This is
     3675         * the case for write operations or generally for not yet finished
     3676         * transfers (some data might need to be read). */
     3677        ataUnsetStatus(s, ATA_STAT_READY | ATA_STAT_DRQ);
     3678        ataSetStatus(s, ATA_STAT_BUSY);
     3679
     3680        Log2(("%s: Ctl#%d: message to async I/O thread, continuing PIO transfer\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl)));
     3681        ataAsyncIOPutRequest(pCtl, &ataPIORequest);
     3682    }
     3683    else
     3684    {
     3685        /* Everything finished, mark device as ready. */
     3686        ataUnsetStatus(s, ATA_STAT_DRQ);
     3687
     3688        Log2(("%s: Ctl#%d: skipping message to async I/O thread, ending PIO transfer\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl)));
     3689        ataPIOTransfer(pCtl);
     3690        Assert(!pCtl->fRedo);
     3691        if (!s->fATAPITransfer)
     3692            ataSetIRQ(s);
     3693    }
    36243694}
    36253695
     
    39213991    s->iIOBufferCur = iIOBufferCur;
    39223992    s->iIOBufferEnd = iIOBufferEnd;
    3923 }
    3924 
    3925 
    3926 static void ataPIOTransfer(PATACONTROLLER pCtl)
    3927 {
    3928     ATADevState *s;
    3929 
    3930     s = &pCtl->aIfs[pCtl->iAIOIf];
    3931     Log3(("%s: if=%p\n", __FUNCTION__, s));
    3932 
    3933     if (s->cbTotalTransfer && s->iIOBufferCur > s->iIOBufferEnd)
    3934     {
    3935         LogRel(("PIIX3 ATA: LUN#%d: %s data in the middle of a PIO transfer - VERY SLOW\n", s->iLUN, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "storing" : "loading"));
    3936         /* Any guest OS that triggers this case has a pathetic ATA driver.
    3937          * In a real system it would block the CPU via IORDY, here we do it
    3938          * very similarly by not continuing with the current instruction
    3939          * until the transfer to/from the storage medium is completed. */
    3940         if (s->iSourceSink != ATAFN_SS_NULL)
    3941         {
    3942             bool fRedo;
    3943             uint8_t status = s->uATARegStatus;
    3944             ataSetStatusValue(s, ATA_STAT_BUSY);
    3945             Log2(("%s: calling source/sink function\n", __FUNCTION__));
    3946             fRedo = g_apfnSourceSinkFuncs[s->iSourceSink](s);
    3947             pCtl->fRedo = fRedo;
    3948             if (RT_UNLIKELY(fRedo))
    3949                 return;
    3950             ataSetStatusValue(s, status);
    3951             s->iIOBufferCur = 0;
    3952             s->iIOBufferEnd = s->cbElementaryTransfer;
    3953         }
    3954     }
    3955     if (s->cbTotalTransfer)
    3956     {
    3957         if (s->fATAPITransfer)
    3958             ataPIOTransferLimitATAPI(s);
    3959 
    3960         if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
    3961             s->cbElementaryTransfer = s->cbTotalTransfer;
    3962 
    3963         Log2(("%s: %s tx_size=%d elem_tx_size=%d index=%d end=%d\n",
    3964              __FUNCTION__, s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE ? "T2I" : "I2T",
    3965              s->cbTotalTransfer, s->cbElementaryTransfer,
    3966              s->iIOBufferCur, s->iIOBufferEnd));
    3967         ataPIOTransferStart(s, s->iIOBufferCur, s->cbElementaryTransfer);
    3968         s->cbTotalTransfer -= s->cbElementaryTransfer;
    3969         s->iIOBufferCur += s->cbElementaryTransfer;
    3970 
    3971         if (s->uTxDir == PDMBLOCKTXDIR_FROM_DEVICE && s->cbElementaryTransfer > s->cbTotalTransfer)
    3972             s->cbElementaryTransfer = s->cbTotalTransfer;
    3973     }
    3974     else
    3975         ataPIOTransferStop(s);
    39763993}
    39773994
     
    41684185                            ataSetIRQ(s);
    41694186
    4170                         pCtl->uAsyncIOState = ATA_AIO_PIO;
     4187                        if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
     4188                        {
     4189                            /* Write operations and not yet finished transfers
     4190                             * must be completed in the async I/O thread. */
     4191                            pCtl->uAsyncIOState = ATA_AIO_PIO;
     4192                        }
     4193                        else
     4194                        {
     4195                            /* Finished read operation can be handled inline
     4196                             * in the end of PIO transfer handling code. Linux
     4197                             * depends on this, as it waits only briefly for
     4198                             * devices to become ready after incoming data
     4199                             * transfer. Cannot find anything in the ATA spec
     4200                             * that backs this assumption, but as all kernels
     4201                             * are affected (though most of the time it does
     4202                             * not cause any harm) this must work. */
     4203                            pCtl->uAsyncIOState = ATA_AIO_NEW;
     4204                        }
    41714205                    }
    41724206                    else
     
    42794313                    ataSetIRQ(s);
    42804314
    4281                     pCtl->uAsyncIOState = ATA_AIO_PIO;
     4315                    if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
     4316                    {
     4317                        /* Write operations and not yet finished transfers
     4318                         * must be completed in the async I/O thread. */
     4319                        pCtl->uAsyncIOState = ATA_AIO_PIO;
     4320                    }
     4321                    else
     4322                    {
     4323                        /* Finished read operation can be handled inline
     4324                         * in the end of PIO transfer handling code. Linux
     4325                         * depends on this, as it waits only briefly for
     4326                         * devices to become ready after incoming data
     4327                         * transfer. Cannot find anything in the ATA spec
     4328                         * that backs this assumption, but as all kernels
     4329                         * are affected (though most of the time it does
     4330                         * not cause any harm) this must work. */
     4331                        pCtl->uAsyncIOState = ATA_AIO_NEW;
     4332                    }
    42824333                }
    42834334                else
     
    42854336                    /* Finish PIO transfer. */
    42864337                    ataPIOTransfer(pCtl);
    4287                     pCtl->uAsyncIOState = ATA_AIO_NEW;
    4288                     if (!pCtl->fChainedTransfer)
     4338                    if (    !pCtl->fChainedTransfer
     4339                        &&  !s->fATAPITransfer
     4340                        &&  s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)
    42894341                    {
    4290                         if (!s->fATAPITransfer && s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)
    42914342                            ataSetIRQ(s);
    42924343                    }
     4344                    pCtl->uAsyncIOState = ATA_AIO_NEW;
    42934345                }
    42944346                break;
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