- Timestamp:
- May 29, 2007 9:23:13 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r2876 r2900 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 (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 } 3624 3709 } 3625 3710 … … 3921 4006 s->iIOBufferCur = iIOBufferCur; 3922 4007 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 4008 } 3977 4009 … … 4168 4200 ataSetIRQ(s); 4169 4201 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 } 4171 4220 } 4172 4221 else … … 4279 4328 ataSetIRQ(s); 4280 4329 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 } 4282 4348 } 4283 4349 else … … 4285 4351 /* Finish PIO transfer. */ 4286 4352 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) 4289 4356 { 4290 if (!s->fATAPITransfer && s->uTxDir != PDMBLOCKTXDIR_FROM_DEVICE)4291 4357 ataSetIRQ(s); 4292 4358 } 4359 pCtl->uAsyncIOState = ATA_AIO_NEW; 4293 4360 } 4294 4361 break;
Note:
See TracChangeset
for help on using the changeset viewer.