Changeset 2876 in vbox for trunk/src/VBox
- Timestamp:
- May 25, 2007 2:45:47 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r2875 r2876 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 it3621 * very similarly by not continuing with the current instruction3622 * 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 else3658 ataPIOTransferStop(s);3659 }3660 3661 3662 3609 DECLINLINE(void) ataPIOTransferFinish(PATACONTROLLER pCtl, ATADevState *s) 3663 3610 { … … 3670 3617 } 3671 3618 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 } 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); 3694 3624 } 3695 3625 … … 3991 3921 s->iIOBufferCur = iIOBufferCur; 3992 3922 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); 3993 3976 } 3994 3977 … … 4185 4168 ataSetIRQ(s); 4186 4169 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 } 4170 pCtl->uAsyncIOState = ATA_AIO_PIO; 4205 4171 } 4206 4172 else … … 4313 4279 ataSetIRQ(s); 4314 4280 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 } 4281 pCtl->uAsyncIOState = ATA_AIO_PIO; 4333 4282 } 4334 4283 else … … 4336 4285 /* Finish PIO transfer. */ 4337 4286 ataPIOTransfer(pCtl); 4338 if ( !pCtl->fChainedTransfer 4339 && !s->fATAPITransfer 4340 && s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE) 4287 pCtl->uAsyncIOState = ATA_AIO_NEW; 4288 if (!pCtl->fChainedTransfer) 4341 4289 { 4290 if (!s->fATAPITransfer && s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE) 4342 4291 ataSetIRQ(s); 4343 4292 } 4344 pCtl->uAsyncIOState = ATA_AIO_NEW;4345 4293 } 4346 4294 break;
Note:
See TracChangeset
for help on using the changeset viewer.