Changeset 2872 in vbox for trunk/src/VBox/Devices/Storage
- Timestamp:
- May 25, 2007 1:52:35 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r2862 r2872 3607 3607 #ifdef IN_RING3 3608 3608 3609 static 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 3609 3662 DECLINLINE(void) ataPIOTransferFinish(PATACONTROLLER pCtl, ATADevState *s) 3610 3663 { … … 3617 3670 } 3618 3671 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 } 3624 3694 } 3625 3695 … … 3921 3991 s->iIOBufferCur = iIOBufferCur; 3922 3992 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 it3938 * very similarly by not continuing with the current instruction3939 * 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 else3975 ataPIOTransferStop(s);3976 3993 } 3977 3994 … … 4168 4185 ataSetIRQ(s); 4169 4186 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 } 4171 4205 } 4172 4206 else … … 4279 4313 ataSetIRQ(s); 4280 4314 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 } 4282 4333 } 4283 4334 else … … 4285 4336 /* Finish PIO transfer. */ 4286 4337 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) 4289 4341 { 4290 if (!s->fATAPITransfer && s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)4291 4342 ataSetIRQ(s); 4292 4343 } 4344 pCtl->uAsyncIOState = ATA_AIO_NEW; 4293 4345 } 4294 4346 break;
Note:
See TracChangeset
for help on using the changeset viewer.