--- M:\work\UniATA\BusMaster\driver\etc\v41d7\id_ata.cpp Thu Jul 12 17:14:56 2012 +++ M:\work\UniATA\BusMaster\driver\id_ata.cpp Fri Jul 13 11:03:48 2012 @@ -3831,9 +3831,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")); @@ -4068,6 +4070,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)); @@ -4077,6 +4080,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; } @@ -4098,8 +4109,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 { @@ -4168,7 +4181,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); @@ -4176,9 +4189,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; } } } @@ -4321,6 +4338,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")); @@ -4857,13 +4875,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) { @@ -4896,7 +4926,6 @@ status = SRB_STATUS_ERROR; goto CompleteRequest; } - // Advance data buffer pointer and bytes left. AtaReq->DataBuffer += wordCount; AtaReq->WordsLeft -= wordCount; @@ -4946,7 +4975,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; --- M:\work\UniATA\BusMaster\driver\etc\v41d7\bsmaster.h Tue Jul 10 23:10:14 2012 +++ M:\work\UniATA\BusMaster\driver\bsmaster.h Fri Jul 13 10:33:13 2012 @@ -786,7 +786,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