--- 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 19:53:29 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)); @@ -2327,6 +2341,9 @@ KdPrint2((PRINT_PREFIX " SIS/nVidia\n")); if(!(ChipFlags & UNIATA_SATA)) goto default_reset; + if(UniataSataClearErr(HwDeviceExtension, j, UNIATA_SATA_IGNORE_CONNECT, 0)) { + goto default_reset; + } break; } case ATA_SILICON_IMAGE_ID: { ULONG offset; @@ -2458,6 +2475,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, @@ -4261,7 +4294,7 @@ pr_status = AtapiReadPortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs); AtapiWritePortEx1(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs, (0x0f << shift)); } - KdPrint2((PRINT_PREFIX " pr_status %x\n", pr_status)); + KdPrint2((PRINT_PREFIX " pr_status %x, shift %x\n", pr_status, shift)); /* check for and handle connect events */ if(((pr_status & (0x0cUL << shift)) == (0x04UL << shift)) ) { @@ -5094,6 +5127,15 @@ interruptReason = (AtapiReadPort1(chan, IDX_ATAPI_IO1_i_InterruptReason) & ATAPI_IR_Mask); KdPrint3((PRINT_PREFIX "AtapiInterrupt: ATAPI Error, int reason %x\n", interruptReason)); + if(UniataIsSATARangeAvailable(deviceExtension, lChannel)) { + if(deviceExtension->HwFlags & UNIATA_AHCI) { + // Do nothing here + } else + if(deviceExtension->HwFlags & UNIATA_SATA) { + UniataSataClearErr(HwDeviceExtension, lChannel, UNIATA_SATA_IGNORE_CONNECT, 0); + } + } + if(DmaTransfer && (chan->lun[DeviceNumber]->TransferMode > ATA_UDMA2) && ((error >> 4) == SCSI_SENSE_HARDWARE_ERROR)) { if(AtaReq->retry < MAX_RETRIES) { @@ -5356,24 +5398,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 +5425,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 +7608,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);