VirtualBox

Changeset 2900 in vbox for trunk/src


Ignore:
Timestamp:
May 29, 2007 9:23:13 AM (18 years ago)
Author:
vboxsync
Message:

Fixed fixed fix for Linux PIO reads. Tested Windows installs, worked
fine.

File:
1 edited

Legend:

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

    r2876 r2900  
    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 (though maybe a couple of chunks need to be
     3686         * transferred, but all without source/sink callback). */
     3687
     3688        /* Continue a previously started transfer. */
     3689        ataUnsetStatus(s, ATA_STAT_DRQ);
     3690        ataSetStatus(s, ATA_STAT_READY);
     3691
     3692        if (s->cbTotalTransfer)
     3693        {
     3694            /* There is more to transfer, happens usually for large ATAPI
     3695             * reads - the protocol limits the chunk size to 65534 bytes. */
     3696            ataPIOTransfer(pCtl);
     3697            ataSetIRQ(s);
     3698        }
     3699        else
     3700        {
     3701            Log2(("%s: Ctl#%d: skipping message to async I/O thread, ending PIO transfer\n", __FUNCTION__, ATACONTROLLER_IDX(pCtl)));
     3702            /* Finish PIO transfer. */
     3703            ataPIOTransfer(pCtl);
     3704            Assert(!pCtl->fRedo);
     3705            if (!s->fATAPITransfer)
     3706                ataSetIRQ(s);
     3707        }
     3708    }
    36243709}
    36253710
     
    39214006    s->iIOBufferCur = iIOBufferCur;
    39224007    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);
    39764008}
    39774009
     
    41684200                            ataSetIRQ(s);
    41694201
    4170                         pCtl->uAsyncIOState = ATA_AIO_PIO;
     4202                        if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
     4203                        {
     4204                            /* Write operations and not yet finished transfers
     4205                             * must be completed in the async I/O thread. */
     4206                            pCtl->uAsyncIOState = ATA_AIO_PIO;
     4207                        }
     4208                        else
     4209                        {
     4210                            /* Finished read operation can be handled inline
     4211                             * in the end of PIO transfer handling code. Linux
     4212                             * depends on this, as it waits only briefly for
     4213                             * devices to become ready after incoming data
     4214                             * transfer. Cannot find anything in the ATA spec
     4215                             * that backs this assumption, but as all kernels
     4216                             * are affected (though most of the time it does
     4217                             * not cause any harm) this must work. */
     4218                            pCtl->uAsyncIOState = ATA_AIO_NEW;
     4219                        }
    41714220                    }
    41724221                    else
     
    42794328                    ataSetIRQ(s);
    42804329
    4281                     pCtl->uAsyncIOState = ATA_AIO_PIO;
     4330                    if (s->uTxDir == PDMBLOCKTXDIR_TO_DEVICE || s->iSourceSink != ATAFN_SS_NULL)
     4331                    {
     4332                        /* Write operations and not yet finished transfers
     4333                         * must be completed in the async I/O thread. */
     4334                        pCtl->uAsyncIOState = ATA_AIO_PIO;
     4335                    }
     4336                    else
     4337                    {
     4338                        /* Finished read operation can be handled inline
     4339                         * in the end of PIO transfer handling code. Linux
     4340                         * depends on this, as it waits only briefly for
     4341                         * devices to become ready after incoming data
     4342                         * transfer. Cannot find anything in the ATA spec
     4343                         * that backs this assumption, but as all kernels
     4344                         * are affected (though most of the time it does
     4345                         * not cause any harm) this must work. */
     4346                        pCtl->uAsyncIOState = ATA_AIO_NEW;
     4347                    }
    42824348                }
    42834349                else
     
    42854351                    /* Finish PIO transfer. */
    42864352                    ataPIOTransfer(pCtl);
    4287                     pCtl->uAsyncIOState = ATA_AIO_NEW;
    4288                     if (!pCtl->fChainedTransfer)
     4353                    if (    !pCtl->fChainedTransfer
     4354                        &&  !s->fATAPITransfer
     4355                        &&  s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)
    42894356                    {
    4290                         if (!s->fATAPITransfer && s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)
    42914357                            ataSetIRQ(s);
    42924358                    }
     4359                    pCtl->uAsyncIOState = ATA_AIO_NEW;
    42934360                }
    42944361                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