Index: drivers/storage/ide/uniata/bsmaster.h =================================================================== --- drivers/storage/ide/uniata/bsmaster.h (revision 56880) +++ drivers/storage/ide/uniata/bsmaster.h (working copy) @@ -781,7 +781,8 @@ #define REQ_STATE_EXPECTING_INTR 0x40 #define REQ_STATE_ATAPI_EXPECTING_CMD_INTR 0x41 #define REQ_STATE_ATAPI_EXPECTING_DATA_INTR 0x42 -#define REQ_STATE_ATAPI_DO_NOTHING_INTR 0x43 +#define REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 0x43 +#define REQ_STATE_ATAPI_DO_NOTHING_INTR 0x44 #define REQ_STATE_EARLY_INTR 0x48 Index: drivers/storage/ide/uniata/id_ata.cpp =================================================================== --- drivers/storage/ide/uniata/id_ata.cpp (revision 56880) +++ drivers/storage/ide/uniata/id_ata.cpp (working copy) @@ -3750,9 +3750,11 @@ UCHAR lChannel; BOOLEAN DmaTransfer = FALSE; BOOLEAN OurInterrupt = FALSE; + BOOLEAN StatusValid = FALSE; // ULONG k; UCHAR interruptReason; BOOLEAN EarlyIntr = FALSE; + BOOLEAN SingleBlockIntr = FALSE; KdPrint2((PRINT_PREFIX "AtapiCheckInterrupt__:\n")); @@ -3985,6 +3987,7 @@ } else { KdPrint2((PRINT_PREFIX " getting status...\n")); GetStatus(chan, statusByte); + StatusValid = 1; KdPrint2((PRINT_PREFIX " status %#x\n", statusByte)); if(statusByte & IDE_STATUS_ERROR) { KdPrint2((PRINT_PREFIX " IDE_STATUS_ERROR -> our\n", statusByte)); @@ -3994,6 +3997,14 @@ (LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) && (dma_status == BM_STATUS_ACTIVE)) { KdPrint2((PRINT_PREFIX " special case DMA + ATAPI + IDE_STATUS_DSC -> our\n", statusByte)); + // some devices interrupts on each block transfer even in DMA mode + if(LunExt->TransferMode >= ATA_SDMA && LunExt->TransferMode <= ATA_WDMA2) { + KdPrint2((PRINT_PREFIX " wait for completion\n")); + ///* clear interrupt and get status */ + //GetBaseStatus(chan, statusByte); + //return INTERRUPT_REASON_IGNORE; + SingleBlockIntr = TRUE; + } } else { return INTERRUPT_REASON_IGNORE; } @@ -4015,8 +4026,10 @@ /* if drive is busy it didn't interrupt */ /* the exception is DCS + BSY state of ATAPI devices */ - KdPrint2((PRINT_PREFIX " getting status...\n")); - GetStatus(chan, statusByte); + if(!StatusValid) { + KdPrint2((PRINT_PREFIX " getting status...\n")); + GetStatus(chan, statusByte); + } if(LunExt->DeviceFlags & DFLAGS_ATAPI_DEVICE) { KdPrint3((PRINT_PREFIX " ATAPI status %#x\n", statusByte)); } else { @@ -4085,7 +4098,7 @@ #ifndef UNIATA_PIO_ONLY if(DmaTransfer) { - if(!EarlyIntr || g_WaitBusyInISR) { + if(!SingleBlockIntr && (!EarlyIntr || g_WaitBusyInISR)) { dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/); } else { PSCSI_REQUEST_BLOCK srb = UniataGetCurRequest(chan); @@ -4093,9 +4106,13 @@ //ASSERT(AtaReq); - KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n")); + if(SingleBlockIntr) { + KdPrint2((PRINT_PREFIX " set REQ_STATE_ATAPI_EXPECTING_DATA_INTR2.\n")); + } else { + KdPrint2((PRINT_PREFIX " set REQ_STATE_EARLY_INTR.\n")); + } if(AtaReq) { - AtaReq->ReqState = REQ_STATE_EARLY_INTR; + AtaReq->ReqState = SingleBlockIntr ? REQ_STATE_ATAPI_EXPECTING_DATA_INTR2 : REQ_STATE_EARLY_INTR; } } } @@ -4238,6 +4255,7 @@ case REQ_STATE_ATAPI_EXPECTING_CMD_INTR: KdPrint3((PRINT_PREFIX " EXPECTING_CMD_INTR\n")); case REQ_STATE_ATAPI_EXPECTING_DATA_INTR: + case REQ_STATE_ATAPI_EXPECTING_DATA_INTR2: case REQ_STATE_DPC_WAIT_BUSY0: case REQ_STATE_DPC_WAIT_BUSY1: KdPrint2((PRINT_PREFIX " continue service interrupt\n")); @@ -4774,13 +4792,25 @@ } } - if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) { + if (DmaTransfer && + (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) { //ASSERT(AtaReq->WordsLeft == wordCount); + if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) { + KdPrint2((PRINT_PREFIX + "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount)); + if(AtaReq->WordsLeft > wordCount) { + AtaReq->WordsLeft -= wordCount; + AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; + goto ReturnEnableIntr; + } + dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/); + } AtaReq->WordsLeft = 0; status = SRB_STATUS_SUCCESS; chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; goto CompleteRequest; } + // Ensure that this is a write command. if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) { @@ -4813,7 +4843,6 @@ status = SRB_STATUS_ERROR; goto CompleteRequest; } - // Advance data buffer pointer and bytes left. AtaReq->DataBuffer += wordCount; AtaReq->WordsLeft -= wordCount; @@ -4863,7 +4892,18 @@ } } - if (DmaTransfer && (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) { + if(DmaTransfer && + (chan->ChannelCtrlFlags & CTRFLAGS_DMA_OPERATION)) { + if(AtaReq->ReqState == REQ_STATE_ATAPI_EXPECTING_DATA_INTR2) { + KdPrint2((PRINT_PREFIX + "IdeIntr: DMA tmp INTR %#x vs %#x\n", AtaReq->WordsLeft, wordCount)); + if(AtaReq->WordsLeft > wordCount) { + AtaReq->WordsLeft -= wordCount; + AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; + goto ReturnEnableIntr; + } + dma_status = AtapiDmaDone(HwDeviceExtension, DEVNUM_NOT_SPECIFIED, lChannel, NULL/*srb*/); + } //ASSERT(AtaReq->WordsLeft == wordCount); AtaReq->WordsLeft = 0; status = SRB_STATUS_SUCCESS;