--- M:\work\UniATA\etc\v45e\driver\id_ata.cpp Mon Oct 20 18:19:54 2014 +++ M:\work\UniATA\BusMaster\driver\id_ata.cpp Sun Feb 08 16:01:43 2015 @@ -1,6 +1,6 @@ /*++ -Copyright (c) 2002-2014 Alexandr A. Telyatnikov (Alter) +Copyright (c) 2002-2015 Alexandr A. Telyatnikov (Alter) Module Name: id_ata.cpp @@ -1594,7 +1594,20 @@ if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) { KdPrint2((PRINT_PREFIX " use 16bit IO\n")); +#if DBG + if(atapiDev) { + j = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); + KdPrint3((PRINT_PREFIX "IssueIdentify: iReason %x\n", j)); + + j = + AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountLow); + j |= + (USHORT)AtapiReadPort1(chan, IDX_ATAPI_IO1_i_ByteCountHigh) << 8; + KdPrint3((PRINT_PREFIX "IssueIdentify: wCount %x\n", j)); + + } +#endif //DBG // ATI/SII chipsets with memory-mapped IO hangs when // I call ReadBuffer(), probably due to PCI burst/prefetch enabled // Unfortunately, I don't know yet how to workaround it except @@ -2007,6 +2020,7 @@ KdPrint2((PRINT_PREFIX "IssueIdentify: ATAPI drive type %#x.\n", LunExt->IdentifyData.DeviceType)); } + KdPrint2((PRINT_PREFIX "IssueIdentify: AtapiCmdSize %#x\n", deviceExtension->FullIdentifyData.AtapiCmdSize)); } else { KdPrint2((PRINT_PREFIX "IssueIdentify: hard drive.\n")); } @@ -2142,7 +2156,7 @@ //ULONG RevID = deviceExtension->RevID; ULONG ChipFlags = deviceExtension->HwFlags & CHIPFLAG_MASK; //UCHAR tmp8; - UCHAR tmp16; + USHORT tmp16; KdPrint2((PRINT_PREFIX "AtapiResetController: Reset IDE %#x/%#x @ %#x\n", VendorID, DeviceID, slotNumber)); KdPrint2((PRINT_PREFIX "simplexOnly %d\n", deviceExtension->simplexOnly)); @@ -2458,6 +2472,22 @@ GetStatus(chan, statusByte); + if(statusByte != IDE_STATUS_SUCCESS) { + ULONG k; + k = UniataAnybodyHome(deviceExtension, j, i); + if(k == ATA_AT_HOME_HDD) { + // device reset in progress, perform additional wait + KdPrint2((PRINT_PREFIX " long reset, wait up to 4.5 s\n")); + k = 30 * 1000; + while ((AtapiReadPort1(chan, IDX_IO1_i_Status) & IDE_STATUS_BUSY) && + k--) + { + AtapiStallExecution(150); + } + KdPrint2((PRINT_PREFIX " exit after %u loops\n", k)); + GetStatus(chan, statusByte); + } + } if(statusByte == IDE_STATUS_SUCCESS) { IssueIdentify(HwDeviceExtension, @@ -5356,24 +5386,24 @@ // Ensure that this is a write command. if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) { - KdPrint2((PRINT_PREFIX - "AtapiInterrupt: Write interrupt\n")); + KdPrint2((PRINT_PREFIX + "AtapiInterrupt: Write interrupt\n")); - statusByte = WaitOnBusy(chan); + statusByte = WaitOnBusy(chan); - if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) { + if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) { - WriteBuffer(chan, - AtaReq->DataBuffer, - wordCount, - UniataGetPioTiming(LunExt)); - } else { + WriteBuffer(chan, + AtaReq->DataBuffer, + wordCount, + UniataGetPioTiming(LunExt)); + } else { - WriteBuffer2(chan, - (PULONG)(AtaReq->DataBuffer), - wordCount / 2, - UniataGetPioTiming(LunExt)); - } + WriteBuffer2(chan, + (PULONG)(AtaReq->DataBuffer), + wordCount / 2, + UniataGetPioTiming(LunExt)); + } } else { KdPrint3((PRINT_PREFIX @@ -5383,6 +5413,17 @@ // Fail this request. status = SRB_STATUS_ERROR; + if(!wordCount && atapiDev && (srb->Cdb[0] != SCSIOP_REQUEST_SENSE)) { + // some devices feel bad after incorrect commands and may need reset + KdPrint2((PRINT_PREFIX + "AtapiInterrupt: Try ATAPI reset\n")); + AtapiDisableInterrupts(deviceExtension, lChannel); + AtapiSoftReset(chan, DeviceNumber); + AtapiEnableInterrupts(deviceExtension, lChannel); + status = SRB_STATUS_BUS_RESET; + AtaReq->ReqState = REQ_STATE_TRANSFER_COMPLETE; + //goto IntrPrepareResetController; + } goto CompleteRequest; } // Advance data buffer pointer and bytes left. @@ -7555,6 +7596,11 @@ AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR; GetBaseStatus(chan, statusByte); + +#if DBG + statusByte = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); + KdPrint3((PRINT_PREFIX "AtapiSendCommand: iReason %x\n", statusByte)); +#endif //DBG if(g_opt_AtapiSendDisableIntr) { AtapiEnableInterrupts(deviceExtension, lChannel);