Index: drivers/storage/ide/uniata/atapi.h =================================================================== --- drivers/storage/ide/uniata/atapi.h (revision 58017) +++ drivers/storage/ide/uniata/atapi.h (working copy) @@ -533,9 +533,17 @@ // ATAPI interrupt reasons // +// for IDX_ATAPI_IO1_i_InterruptReason #define ATAPI_IR_COD 0x01 -#define ATAPI_IR_IO 0x02 +#define ATAPI_IR_COD_Data 0x0 +#define ATAPI_IR_COD_Cmd 0x1 +#define ATAPI_IR_IO 0x02 +#define ATAPI_IR_IO_toDev 0x00 +#define ATAPI_IR_IO_toHost 0x02 + +#define ATAPI_IR_Mask 0x03 + // // ATA Features // Index: drivers/storage/ide/uniata/id_ata.cpp =================================================================== --- drivers/storage/ide/uniata/id_ata.cpp (revision 58017) +++ drivers/storage/ide/uniata/id_ata.cpp (working copy) @@ -4492,7 +4492,7 @@ KdPrint2((PRINT_PREFIX " OurInterrupt = %d\n", OurInterrupt)); return OurInterrupt; } - interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3); + interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); KdPrint3((PRINT_PREFIX "AtapiCheckInterrupt__: ATAPI int reason %x\n", interruptReason)); return OurInterrupt; } @@ -4847,7 +4847,7 @@ if(deviceExtension->HwFlags & UNIATA_AHCI) { KdPrint3((PRINT_PREFIX " AHCI branch (ATAPI)\n")); } else { - interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3); + interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason)); } @@ -5016,7 +5016,7 @@ } } } else { - interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3); + interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason)); if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) && @@ -5086,7 +5086,7 @@ KdPrint2((PRINT_PREFIX "AtapiInterrupt: ATAPI branch\n")); // ATAPI branch - interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & 0x3); + interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); KdPrint3((PRINT_PREFIX "AtapiInterrupt: iReason %x\n", interruptReason)); if(DmaTransfer) { wordsThisInterrupt = DEV_BSIZE/2*512; @@ -5113,10 +5113,10 @@ if (srb->SrbFlags & SRB_FLAGS_DATA_IN) { - interruptReason = 0x2; + interruptReason = ATAPI_IR_IO_toHost; } else if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) { - interruptReason = 0x0; + interruptReason = ATAPI_IR_IO_toDev; } else { status = SRB_STATUS_ERROR; @@ -5164,13 +5164,13 @@ goto ReturnEnableIntr; } else { - interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? 0x2 : 0x0; + interruptReason = (srb->SrbFlags & SRB_FLAGS_DATA_IN) ? ATAPI_IR_IO_toHost : ATAPI_IR_IO_toDev; } } else { // Command complete - verify, write, or the SMART enable/disable. // Also get_media_status - interruptReason = 0x3; + interruptReason = ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd; } } } @@ -5196,7 +5196,7 @@ chan->ChannelCtrlFlags &= ~CTRFLAGS_DMA_OPERATION; goto CompleteRequest; } else - if (interruptReason == 0x1 && (statusByte & IDE_STATUS_DRQ)) { + if (interruptReason == ATAPI_IR_COD_Cmd && (statusByte & IDE_STATUS_DRQ)) { // Write the packet. KdPrint3((PRINT_PREFIX "AtapiInterrupt: Writing Atapi packet.\n")); // Send CDB to device. @@ -5212,7 +5212,7 @@ goto ReturnEnableIntr; - } else if (interruptReason == 0x0 && (statusByte & IDE_STATUS_DRQ)) { + } else if (interruptReason == ATAPI_IR_IO_toDev && (statusByte & IDE_STATUS_DRQ)) { // Write the data. if (atapiDev) { @@ -5319,7 +5319,7 @@ goto ReturnEnableIntr; - } else if (interruptReason == 0x2 && (statusByte & IDE_STATUS_DRQ)) { + } else if (interruptReason == ATAPI_IR_IO_toHost && (statusByte & IDE_STATUS_DRQ)) { if (atapiDev) { @@ -5515,7 +5515,7 @@ goto ReturnEnableIntr; - } else if (interruptReason == 0x3 && !(statusByte & IDE_STATUS_DRQ)) { + } else if (interruptReason == (ATAPI_IR_IO_toHost | ATAPI_IR_COD_Cmd) && !(statusByte & IDE_STATUS_DRQ)) { KdPrint2((PRINT_PREFIX "AtapiInterrupt: interruptReason = CompleteRequest\n")); // Command complete. @@ -5663,7 +5663,8 @@ AtaReq->OriginalSrb); } else { - // last request was illegal. No point trying again + // last request was illegal. No point trying again. + // Do-nothing call ? AtapiHwInitializeChanger (HwDeviceExtension, srb, (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL); @@ -5706,6 +5707,7 @@ if (AtaReq->OriginalSrb) { KdPrint2((PRINT_PREFIX "AtapiInterrupt: call AtapiHwInitializeChanger()\n")); + // Do-nothing call ? AtapiHwInitializeChanger (HwDeviceExtension, srb, (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL); @@ -6756,7 +6758,7 @@ //ULONG ldev = GET_LDEV(Srb); ULONG DeviceNumber = GET_CDEV(Srb); ULONG flags; - UCHAR statusByte,byteCountLow,byteCountHigh; + UCHAR statusByte,statusByte0,byteCountLow,byteCountHigh; BOOLEAN use_dma = FALSE; BOOLEAN dma_reinited = FALSE; BOOLEAN retried = FALSE; @@ -6901,9 +6903,27 @@ KdPrint2((PRINT_PREFIX "AtapiSendCommand: SRB_STATUS_PENDING (2)\n")); return srbStatus; } else { + + // failed! Get the sense key and maybe try again + AtaReq->Srb = BuildRequestSenseSrb ( HwDeviceExtension, + AtaReq->OriginalSrb); + + srbStatus = AtapiSendCommand(HwDeviceExtension, AtaReq->Srb, CMD_ACTION_ALL); + + KdPrint3((PRINT_PREFIX "AtapiSendCommand: chan->ExpectingInterrupt %d (1)\n", chan->ExpectingInterrupt)); + + if (srbStatus == SRB_STATUS_PENDING) { + KdPrint2((PRINT_PREFIX "AtapiSendCommand: send orig SRB_STATUS_PENDING (2.1)\n")); + return srbStatus; + } + + // failed again ? should not get here + AtaReq->Srb = AtaReq->OriginalSrb; AtaReq->OriginalSrb = NULL; + KdPrint2((PRINT_PREFIX "AtapiSendCommand: AtapiHwInitializeChanger()\n")); + // Do-nothing call ? AtapiHwInitializeChanger (HwDeviceExtension, Srb, (PMECHANICAL_STATUS_INFORMATION_HEADER) NULL); // fall out @@ -7395,6 +7415,8 @@ if(g_opt_AtapiSendDisableIntr) { AtapiDisableInterrupts(deviceExtension, lChannel); } + // remember status. Later we may check if error appeared after cmd packet + statusByte0 = statusByte; // Write ATAPI packet command. AtapiWritePort1(chan, IDX_IO1_o_Command, IDE_COMMAND_ATAPI_PACKET); @@ -7442,9 +7464,19 @@ GetStatus(chan, statusByte); KdPrint3((PRINT_PREFIX "AtapiSendCommand: cmd status (%#x)\n", statusByte)); + // When we operate in DMA mode, we should not start transfer when there is an error on entry + // Interrupt may never come in such case. if(statusByte & IDE_STATUS_ERROR) { + UCHAR interruptReason; + GetBaseStatus(chan, statusByte); KdPrint3((PRINT_PREFIX "AtapiSendCommand: Error on cmd: (%#x)\n", statusByte)); + + interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); + KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", interruptReason)); + + // TODO: we should check interruptReason and decide what to do now + // Read the error reg. to clear it and fail this request. AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; return MapError(deviceExtension, Srb);