#define IDE_DRIVE_2 0x10
#define IDE_DRIVE_SELECT_1 (IDE_DRIVE_SELECT | IDE_DRIVE_1)
#define IDE_DRIVE_SELECT_2 (IDE_DRIVE_SELECT | IDE_DRIVE_2)
+#define IDE_DRIVE_MASK (IDE_DRIVE_SELECT_1 | IDE_DRIVE_SELECT_2)
#define IDE_USE_LBA 0x40
#define VIAPRQ 0x8000
#define VIASATA 0x10000
+#define CYRIX_OLD 0
+#define CYRIX_3x 1
+#define CYRIX_NEW 2
+#define CYRIX_35 3
+
#define ITE_33 0
#define ITE_133 1
#define ITE_133_NEW 2
PCI_DEV_HW_SPEC_BM( 7411, 1022, 0x00, ATA_UDMA5, "AMD 766" , 0 | AMDBUG ),
PCI_DEV_HW_SPEC_BM( 7441, 1022, 0x00, ATA_UDMA5, "AMD 768" , 0 ),
PCI_DEV_HW_SPEC_BM( 7469, 1022, 0x00, ATA_UDMA6, "AMD 8111" , 0 ),
+ PCI_DEV_HW_SPEC_BM( 208F, 1022, 0x00, ATA_UDMA4, "AMD CS5535" , CYRIX_35 ),
PCI_DEV_HW_SPEC_BM( 209a, 1022, 0x00, ATA_UDMA5, "AMD CS5536" , 0 ),
PCI_DEV_HW_SPEC_BM( 4349, 1002, 0x00, ATA_UDMA5, "ATI IXP200" , 0 ),
PCI_DEV_HW_SPEC_BM( 0d8f, 10de, 0x00, ATA_SA300, "nVidia nForce MCP89 AB", UNIATA_SATA | UNIATA_AHCI ),
PCI_DEV_HW_SPEC_BM( 0502, 100b, 0x00, ATA_UDMA2, "National Geode SC1100", 0 ),
+ PCI_DEV_HW_SPEC_BM( 002d, 100b, 0x00, ATA_UDMA4, "National Geode CS5535", CYRIX_35 ),
PCI_DEV_HW_SPEC_BM( 4d33, 105a, 0x00, ATA_UDMA2, "Promise PDC20246" , PROLD | 0x00 ),
PCI_DEV_HW_SPEC_BM( 4d38, 105a, 0x00, ATA_UDMA4, "Promise PDC20262" , PRNEW | 0x00 ),
*/
PCI_DEV_HW_SPEC_BM( 0001, 16ca, 0x00, ATA_WDMA2, "Cenatek Rocket Drive",0 ),
- PCI_DEV_HW_SPEC_BM( 0102, 1078, 0x00, ATA_UDMA2, "Cyrix 5530" , 0 ),
+ PCI_DEV_HW_SPEC_BM( 0000, 1078, 0x00, ATA_WDMA2, "Cyrix 5510" , CYRIX_OLD ),
+ PCI_DEV_HW_SPEC_BM( 0002, 1078, 0x00, ATA_WDMA2, "Cyrix 5520" , CYRIX_OLD ),
+ PCI_DEV_HW_SPEC_BM( 0102, 1078, 0x00, ATA_UDMA2, "Cyrix 5530" , CYRIX_3x ),
PCI_DEV_HW_SPEC_BM( 1000, 1042, 0x00, ATA_PIO4, "RZ 100x" , 0 ),
PCI_DEV_HW_SPEC_BM( 1001, 1042, 0x00, ATA_PIO4, "RZ 100x" , 0 ),
/*++
-Copyright (c) 2002-2014 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2015 Alexandr A. Telyatnikov (Alter)
Module Name:
id_ata.cpp
if (statusByte & IDE_STATUS_DRQ) {
// Suck out any remaining bytes and throw away.
AtapiReadPort2(chan, IDX_IO1_i_Data);
+ UniataNanoSleep(PIO0_TIMING);
} else {
break;
}
return statusByte;
} // AtapiSuckPort2()
+ULONG
+DDKFASTAPI
+AtapiSuckPortBuffer2(
+ IN PHW_CHANNEL chan,
+ IN PUSHORT Buffer,
+ IN ULONG Count
+ )
+{
+ UCHAR statusByte;
+ ULONG i;
+ USHORT data;
+ BOOLEAN retry = FALSE;
+
+ // Assume, proper drive is already seleted
+ WaitOnBusyLong(chan);
+ for (i = 0; i < Count; i++) {
+
+ GetStatus(chan, statusByte);
+ if (statusByte & IDE_STATUS_DRQ) {
+ // Suck out any remaining bytes and throw away.
+ data = AtapiReadPort2(chan, IDX_IO1_i_Data);
+ (*Buffer) = data;
+ Count--;
+ Buffer++;
+ UniataNanoSleep(PIO0_TIMING);
+ retry = FALSE;
+ } else {
+ if(i<Count && !retry) {
+ KdPrint2((PRINT_PREFIX " wait...\n"));
+ WaitForDrq(chan);
+ retry = TRUE;
+ }
+ break;
+ }
+ }
+ if(i) {
+ KdPrint2((PRINT_PREFIX "AtapiSuckPortBuffer2: %#x words\n", i ));
+ if(i==Count) {
+ AtapiSuckPort2(chan);
+ }
+ }
+ return i;
+} // AtapiSuckPortBuffer2()
+
UCHAR
DDKFASTAPI
WaitOnBusy(
#endif //UNIATA_CORE
-#if DBG
+#ifdef _DEBUG
VOID
NTAPI
UniataDumpATARegs(
if(use_ahci) {
statusByte = WaitOnBusyLong(chan);
-#if DBG
+#ifdef _DEBUG
if(!chan->AhciInternalAtaReq) {
KdPrint2((PRINT_PREFIX "!AhciInternalAtaReq\n"));
}
if (atapiDev || !(LunExt->DeviceFlags & DFLAGS_DWORDIO_ENABLED) /*!deviceExtension->DWordIO*/) {
KdPrint2((PRINT_PREFIX " use 16bit IO\n"));
+#ifdef _DEBUG
+ 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
- // spacifying manual delay in the way you see below.
+ // specifying manual delay in the way you see below.
ReadBuffer(chan, (PUSHORT)&deviceExtension->FullIdentifyData, 256, PIO0_TIMING);
// Work around for some IDE and one model Atapi that will present more than
LunExt->RwSwitchMCost = REORDER_MCOST_SWITCH_RW_CD;
LunExt->SeekBackMCost = REORDER_MCOST_SEEK_BACK_CD;
statusByte = WaitForDrq(chan);
+
} else {
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"));
}
//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));
PATA_REQ AtaReq = (PATA_REQ)(CurSrb->SrbExtension);
KdPrint2((PRINT_PREFIX "AtapiResetController: pending SRB %#x, chan %#x\n", CurSrb, chan));
+ if(CurSrb->Cdb[0] == SCSIOP_MECHANISM_STATUS) {
+ PHW_LU_EXTENSION LunExt;
+ KdPrint2((PRINT_PREFIX " was MechStatus\n"));
+
+ i = GET_CDEV(CurSrb);
+ KdPrint2((PRINT_PREFIX " Lun %x\n", i));
+ LunExt = chan->lun[i];
+
+ if(!(LunExt->DeviceFlags & DFLAGS_CHANGER_INITED)) {
+ LunExt->DeviceFlags |= DFLAGS_CHANGER_INITED;
+ KdPrint2((PRINT_PREFIX " set DFLAGS_CHANGER_INITED\n"));
+ }
+ }
// Check and see if we are processing an internal srb
if (AtaReq->OriginalSrb) {
KdPrint2((PRINT_PREFIX " restore original SRB %#x\n", AtaReq->OriginalSrb));
break; }
case ATA_SIS_ID:
case ATA_NVIDIA_ID: {
+ ULONG offs;
+ ULONG Channel = deviceExtension->Channel + j;
KdPrint2((PRINT_PREFIX " SIS/nVidia\n"));
- if(!(ChipFlags & UNIATA_SATA))
+ if(!(ChipFlags & UNIATA_SATA)) {
goto default_reset;
+ }
+ offs = (ChipFlags & NV4OFF) ? 0x0440 : 0x0010;
+
+ KdPrint2((PRINT_PREFIX " disable Phy intr, offs %#x, c %u\n", offs, Channel));
+ /* disable device and PHY state change interrupts */
+ if(ChipFlags & NVQ) {
+ KdPrint2((PRINT_PREFIX " NVQ, 32bits reg\n"));
+ AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
+ AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) & ((~(ULONG)0x0000000d) << (!Channel*16)) );
+ } else {
+ AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
+ AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) & ((~(UCHAR)0x0d) << (!Channel*4)) );
+ }
+ tmp16 = UniataSataPhyEnable(HwDeviceExtension, j, 0/* dev0*/, UNIATA_SATA_RESET_ENABLE);
+
+ KdPrint2((PRINT_PREFIX " enable Phy intr, offs %#x\n", offs));
+ /* enable device and PHY state change interrupts */
+ if(ChipFlags & NVQ) {
+ AtapiWritePortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4,
+ AtapiReadPortEx4(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+4) | (((ULONG)0x0000000d) << (!Channel*16)) );
+ } else {
+ AtapiWritePortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1,
+ AtapiReadPortEx1(NULL, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressSATA_0),offs+1) | (((UCHAR)0x0d) << (!Channel*4)) );
+ }
+
+ KdPrint2((PRINT_PREFIX " dev status %#x\n", tmp16));
+ if(tmp16 != IDE_STATUS_WRONG) {
+ goto default_reset;
+ }
break; }
case ATA_SILICON_IMAGE_ID: {
ULONG offset;
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,
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)) ) {
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) {
// 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
interruptReason,
srb));
+ if(!wordCount && atapiDev &&
+ !(statusByte & (IDE_STATUS_ERROR | IDE_STATUS_BUSY)) &&
+ (statusByte & IDE_STATUS_DRQ)) {
+ // this can be late Packet interrupt after packet sending
+ KdPrint2((PRINT_PREFIX " unreliable wordCount ?\n"));
+
+ wordCount = AtapiSuckPortBuffer2(chan,
+ AtaReq->DataBuffer,
+ AtaReq->WordsLeft);
+ KdPrint2((PRINT_PREFIX " transferred %#x\n", wordCount));
+ GetBaseStatus(chan, statusByte);
+ KdPrint2((PRINT_PREFIX " status %#x, statusByte\n"));
+ if(wordCount) {
+ interruptReason = ATAPI_IR_IO_toHost;
+#ifdef _DEBUG
+ UniataDumpATARegs(chan);
+#endif
+ }
+ if(wordCount && AtaReq->WordsLeft) {
+ goto continue_atapi_pio_read;
+ }
+ }
// 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.
status = SRB_STATUS_ERROR;
goto CompleteRequest;
}
-
+continue_atapi_pio_read:
// Advance data buffer pointer and bytes left.
AtaReq->DataBuffer += wordCount;
AtaReq->WordsLeft -= wordCount;
CHECK_INTR_IDLE);
AtaReq->ReqState = REQ_STATE_ATAPI_EXPECTING_DATA_INTR;
+ // clear interrupt
GetBaseStatus(chan, statusByte);
+#ifdef _DEBUG
+ 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);
}
} else {
RtlZeroMemory(modeData, sizeof(MODE_POWER_CONDITION_PAGE));
modeData->PageCode = MODE_PAGE_POWER_CONDITION;
- modeData->PageLength = sizeof(MODE_POWER_CONDITION_PAGE)-sizeof(MODE_PARAMETER_HEADER);
+ modeData->PageLength = sizeof(MODE_PAGE_POWER_CONDITION)-sizeof(MODE_PARAMETER_HEADER);
modeData->Byte3.Fields.Idle = LunExt->PowerState <= StartStop_Power_Idle;
modeData->Byte3.Fields.Standby = LunExt->PowerState == StartStop_Power_Standby;
Srb->DataTransferLength = sizeof(MODE_POWER_CONDITION_PAGE);
return status;
}
#endif // USE_REACTOS_DDK
- KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, KeNumberProcessors));
+ KdPrint(("UniATA Init: OS ver %x.%x (%d), %d CPU(s)\n", MajorVersion, MinorVersion, BuildNumber, *KeNumberProcessors));
KeQuerySystemTime(&t0);
do {
g_opt_WaitDrqDelay = 100;
g_opt_WaitBusyLongCount = 20000;
g_opt_MaxIsrWait = 200;
- g_opt_AtapiSendDisableIntr = 0;
+ g_opt_AtapiSendDisableIntr = FALSE;
g_opt_AtapiDmaRawRead = FALSE;
break;
}
g_opt_WaitDrqDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitDrqDelay", g_opt_WaitDrqDelay); // 10 vs 100
g_opt_WaitBusyLongCount = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongCount", g_opt_WaitBusyLongCount); // 2000 vs 20000
g_opt_WaitBusyLongDelay = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"WaitBusyLongDelay", g_opt_WaitBusyLongDelay); // 250 vs 250
- g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr); // 1 vs 0
- g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead); // 1 vs 0
+ g_opt_AtapiSendDisableIntr = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiSendDisableIntr", g_opt_AtapiSendDisableIntr) ? TRUE : FALSE; // 1 vs 0
+ g_opt_AtapiDmaRawRead = (BOOLEAN)AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"AtapiDmaRawRead", g_opt_AtapiDmaRawRead) ? TRUE : FALSE; // 1 vs 0
g_opt_MaxIsrWait = AtapiRegCheckDevValue(NULL, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"MaxIsrWait", g_opt_MaxIsrWait); // 40 vs xxx
}
/****************/
KdPrint2((PRINT_PREFIX "SATA Generic\n"));
+
if((udmamode >= 5) || (ChipFlags & UNIATA_AHCI) || ((udmamode >= 0) && (chan->MaxTransferMode >= ATA_SA150))) {
/* some drives report UDMA6, some UDMA5 */
/* ATAPI may not have SataCapabilities set in IDENTIFY DATA */
/*********/
/* Cyrix */
/*********/
- ULONG cyr_piotiming[] =
- { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 };
- ULONG cyr_wdmatiming[] = { 0x00077771, 0x00012121, 0x00002020 };
- ULONG cyr_udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 };
- ULONG mode_reg = 0x24+(dev << 3);
-
+dma_cs55xx:
if(apiomode >= 4)
apiomode = 4;
- for(i=udmamode; i>=0; i--) {
- if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
- AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_udmatiming[udmamode]);
+
+ if(ChipType == CYRIX_3x) {
+ ULONG cyr_piotiming[] =
+ { 0x00009172, 0x00012171, 0x00020080, 0x00032010, 0x00040010 };
+ ULONG cyr_wdmatiming[] = { 0x00077771, 0x00012121, 0x00002020 };
+ ULONG cyr_udmatiming[] = { 0x00921250, 0x00911140, 0x00911030 };
+ ULONG mode_reg = 0x24+(dev << 3);
+
+ for(i=udmamode; i>=0; i--) {
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
+ AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_udmatiming[udmamode]);
+ return;
+ }
+ }
+ for(i=wdmamode; i>=0; i--) {
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
+ AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_wdmatiming[wdmamode]);
+ return;
+ }
+ }
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
+ AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_piotiming[apiomode]);
return;
}
- }
- for(i=wdmamode; i>=0; i--) {
- if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
- AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_wdmatiming[wdmamode]);
+ } else
+ if(ChipType == CYRIX_OLD) {
+ UCHAR cyr_piotiming_old[] =
+ { 11, 6, 3, 2, 1 };
+ UCHAR timing;
+
+ for(i=wdmamode; i>=0; i--) {
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
+ return;
+ }
+ }
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
+ timing = (6-apiomode) | (cyr_piotiming_old[i]);
+ /* Channel command timing */
+ SetPciConfig1(0x62+Channel, timing);
+ /* Read command timing */
+ SetPciConfig1(0x64+Channel*4+dev, timing);
+ /* Write command timing */
+ SetPciConfig1(0x66+Channel*4+dev, timing);
+ return;
+ }
+ } else
+ if(ChipType == CYRIX_35) {
+/*
+ USHORT c35_pio_timings[5] = {
+ 0xF7F4, 0xF173, 0x8141, 0x5131, 0x1131
+ };
+ USHORT c35_pio_cmd_timings[5] = {
+ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131
+ };
+ ULONG c35_udma_timings[5] = {
+ 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061
+ };
+ ULONG c35_mwdma_timings[3] = {
+ 0x7F0FFFF3, 0x7F035352, 0x7F024241
+ };
+ ULONG mode_reg = 0x24+(dev << 3);
+*/
+ /* No MSR support yet, do not touch any regs */
+ for(i=udmamode; i>=0; i--) {
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
+ return;
+ }
+ }
+ for(i=wdmamode; i>=0; i--) {
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
+ return;
+ }
+ }
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
return;
}
- }
- if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
- AtapiWritePortEx4(chan, (ULONGIO_PTR)(&deviceExtension->BaseIoAddressBM_0), mode_reg, cyr_piotiming[apiomode]);
- return;
}
return;
/************/
/* National */
/************/
- ULONG nat_piotiming[] =
- { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010,
- 0x00803020, 0x20102010, 0x00100010,
- 0x00100010, 0x00100010, 0x00100010 };
- ULONG nat_dmatiming[] = { 0x80077771, 0x80012121, 0x80002020 };
- ULONG nat_udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 };
-
- if(apiomode >= 4)
- apiomode = 4;
- for(i=udmamode; i>=0; i--) {
- if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
- SetPciConfig4(0x44 + (dev * 8), nat_udmatiming[i]);
- SetPciConfig4(0x40 + (dev * 8), nat_piotiming[i+8]);
- return;
+ if(!ChipType) {
+ ULONG nat_piotiming[] =
+ { 0x9172d132, 0x21717121, 0x00803020, 0x20102010, 0x00100010,
+ 0x00803020, 0x20102010, 0x00100010,
+ 0x00100010, 0x00100010, 0x00100010 };
+ ULONG nat_dmatiming[] = { 0x80077771, 0x80012121, 0x80002020 };
+ ULONG nat_udmatiming[] = { 0x80921250, 0x80911140, 0x80911030 };
+
+ if(apiomode >= 4)
+ apiomode = 4;
+ for(i=udmamode; i>=0; i--) {
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_UDMA0 + i)) {
+ SetPciConfig4(0x44 + (dev * 8), nat_udmatiming[i]);
+ SetPciConfig4(0x40 + (dev * 8), nat_piotiming[i+8]);
+ return;
+ }
}
- }
- for(i=wdmamode; i>=0; i--) {
- if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
- SetPciConfig4(0x44 + (dev * 8), nat_dmatiming[i]);
- SetPciConfig4(0x40 + (dev * 8), nat_piotiming[i+5]);
+ for(i=wdmamode; i>=0; i--) {
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_WDMA0 + i)) {
+ SetPciConfig4(0x44 + (dev * 8), nat_dmatiming[i]);
+ SetPciConfig4(0x40 + (dev * 8), nat_piotiming[i+5]);
+ return;
+ }
+ }
+ if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
+ ChangePciConfig4(0x44 + (dev * 8), a | 0x80000000);
+ SetPciConfig4(0x40 + (dev * 8), nat_piotiming[apiomode]);
return;
}
- }
- if(AtaSetTransferMode(deviceExtension, DeviceNumber, lChannel, LunExt, ATA_PIO0 + apiomode)) {
- ChangePciConfig4(0x44 + (dev * 8), a | 0x80000000);
- SetPciConfig4(0x40 + (dev * 8), nat_piotiming[apiomode]);
- return;
+ } else {
+ goto dma_cs55xx;
}
/* Use GENERIC PIO */
break; }
KdPrint2((PRINT_PREFIX "New JMicron PATA 1 chan\n"));
}
break;
+ case ATA_CYRIX_ID:
+ if(ChipType == CYRIX_OLD) {
+ UCHAR tmp8;
+ ULONG slotNumber;
+ slotNumber = deviceExtension->slotNumber;
+ KdPrint2((PRINT_PREFIX "Cyrix slot %#x\n", slotNumber));
+ GetPciConfig1(0x60, tmp8);
+ if(tmp8 & (1 << BMList[deviceExtension->DevIndex].channel)) {
+ KdPrint2((PRINT_PREFIX "Old Cyrix chan %d ok\n", BMList[deviceExtension->DevIndex].channel));
+ } else {
+ KdPrint2((PRINT_PREFIX "Old Cyrix no chan %d\n", BMList[deviceExtension->DevIndex].channel));
+ return FALSE;
+ }
+ }
+ break;
} // end switch(VendorID)
i = AtapiRegCheckDevValue(deviceExtension, CHAN_NOT_SPECIFIED, DEVNUM_NOT_SPECIFIED, L"NumberChannels", n);
KdPrint2((PRINT_PREFIX "Intel SATA\n"));
if(ChipFlags & UNIATA_AHCI) {
KdPrint2((PRINT_PREFIX "Do nothing for AHCI\n"));
+ /* enable PCI interrupt */
+ ChangePciConfig2(offsetof(PCI_COMMON_CONFIG, Command), (a & ~0x0400));
break;
}
if(c == CHAN_NOT_SPECIFIED) {
if(ChipType == ITE_133_NEW) {
}
break;
+ case ATA_CYRIX_ID:
+ KdPrint2((PRINT_PREFIX "Cyrix\n"));
+ if(ChipType == CYRIX_OLD) {
+ if(c == CHAN_NOT_SPECIFIED) {
+ GetPciConfig1(0x60, tmp8);
+ if(!(tmp8 & 0x40)) {
+ KdPrint2((PRINT_PREFIX "Enable DMA\n"));
+ tmp8 |= 0x40;
+ SetPciConfig1(0x60, tmp8);
+ }
+ }
+ }
+ break;
default:
if(c != CHAN_NOT_SPECIFIED) {
// We don't know how to check for 80-pin cable on unknown controllers.
/*++
-Copyright (c) 2002-2012 Alexandr A. Telyatnikov (Alter)
+Copyright (c) 2002-2015 Alexandr A. Telyatnikov (Alter)
Module Name:
id_probe.cpp
ULONG MCACount = 0;
BOOLEAN FirstMasterOk = FALSE;
+// This is our own resource check,
+// ReactOS allows to allocate same I/O range for both PCI and ISA controllers
+BOOLEAN AtdiskPrimaryClaimed = FALSE;
+BOOLEAN AtdiskSecondaryClaimed = FALSE;
#ifndef UNIATA_CORE
chan->RegTranslation[IDX_SATA_IO].MemIo ? "mem" : "io"));
if(!(deviceExtension->HwFlags & UNIATA_AHCI)) {
-#if DBG
+#ifdef _DEBUG
UniataDumpATARegs(chan);
#endif
KdPrint2((PRINT_PREFIX "claim Compatible controller\n"));
if (channel == 0) {
KdPrint2((PRINT_PREFIX "claim Primary\n"));
+ AtdiskPrimaryClaimed =
ConfigInfo->AtdiskPrimaryClaimed = TRUE;
chan->PrimaryAddress = TRUE;
} else
if (channel == 1) {
KdPrint2((PRINT_PREFIX "claim Secondary\n"));
+ AtdiskSecondaryClaimed =
ConfigInfo->AtdiskSecondaryClaimed = TRUE;
FirstMasterOk = TRUE;
}
+ } else {
+ if(chan->RegTranslation[IDX_IO1].Addr == IO_WD1 &&
+ !chan->RegTranslation[IDX_IO1].MemIo) {
+ KdPrint2((PRINT_PREFIX "claim Primary (PCI over ISA range)\n"));
+ AtdiskPrimaryClaimed =
+ ConfigInfo->AtdiskPrimaryClaimed = TRUE;
+ }
+ if(chan->RegTranslation[IDX_IO1].Addr == IO_WD2 &&
+ !chan->RegTranslation[IDX_IO1].MemIo) {
+ KdPrint2((PRINT_PREFIX "claim Secondary (PCI over ISA range)\n"));
+ AtdiskSecondaryClaimed =
+ ConfigInfo->AtdiskSecondaryClaimed = TRUE;
+ }
}
AtapiDmaAlloc(HwDeviceExtension, ConfigInfo, c);
}
// check if Primary/Secondary Master IDE claimed
if((ioSpace == (PUCHAR)IO_WD1) &&
- (ConfigInfo->AtdiskPrimaryClaimed)) {
+ (ConfigInfo->AtdiskPrimaryClaimed || AtdiskPrimaryClaimed)) {
KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskPrimaryClaimed\n"));
goto not_found;
} else
if((ioSpace == (PUCHAR)IO_WD2) &&
- (ConfigInfo->AtdiskSecondaryClaimed)) {
+ (ConfigInfo->AtdiskSecondaryClaimed || AtdiskSecondaryClaimed)) {
KdPrint2((PRINT_PREFIX "AtapiFindController: AtdiskSecondaryClaimed\n"));
goto not_found;
}
UniataInitMapBase(chan, BaseIoAddress1, BaseIoAddress2);
UniataInitMapBM(deviceExtension, 0, FALSE);
-#if DBG
+#ifdef _DEBUG
UniataDumpATARegs(chan);
#endif
UCHAR statusByte;
ULONG RetVal=0;
ULONG waitCount = 10000;
+ ULONG at_home = 0;
KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x\n",
deviceNumber));
return 0;
}
if(deviceExtension->HwFlags & UNIATA_AHCI) {
- if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
+ if(!(at_home = UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber))) {
return 0;
}
}
LunExt->PowerState = 0;
}
+ if((deviceExtension->HwFlags & UNIATA_SATA) &&
+ !UniataIsSATARangeAvailable(deviceExtension, lChannel) &&
+ deviceNumber) {
+ KdPrint2((PRINT_PREFIX " SATA w/o i/o registers, check slave presence\n"));
+ SelectDrive(chan, deviceNumber & 0x01);
+ statusByte = AtapiReadPort1(chan, IDX_ATAPI_IO1_i_DriveSelect);
+ KdPrint2((PRINT_PREFIX " DriveSelect: %#x\n", statusByte));
+ if((statusByte & IDE_DRIVE_MASK) != IDE_DRIVE_SELECT_2) {
+ KdPrint2((PRINT_PREFIX "CheckDevice: (no dev)\n"));
+ UniataForgetDevice(LunExt);
+ return 0;
+ }
+ }
+
if(ResetDev && (deviceExtension->HwFlags & UNIATA_AHCI)) {
KdPrint2((PRINT_PREFIX "CheckDevice: reset AHCI dev\n"));
if(UniataAhciSoftReset(HwDeviceExtension, chan->lChannel, deviceNumber) == (ULONG)(-1)) {
// Reset device
AtapiSoftReset(chan, deviceNumber);
- if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
+ if(!(at_home = UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber))) {
//KdPrint2((PRINT_PREFIX "CheckDevice: nobody at home 1\n"));
return 0;
}
// Select the device.
SelectDrive(chan, deviceNumber);
- if(!UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
+ if(!(at_home = UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber))) {
//KdPrint2((PRINT_PREFIX "CheckDevice: nobody at home 2\n"));
return 0;
}
// ATAPI signature found.
// Issue the ATAPI identify command if this
// is not for the crash dump utility.
-
+try_atapi:
if (!deviceExtension->DriverMustPoll) {
// Issue ATAPI packet identify command.
}
} else {
-
+forget_device:
// Indicate no working device.
KdPrint2((PRINT_PREFIX "CheckDevice: Device %#x not responding\n",
deviceNumber));
RetVal = DFLAGS_DEVICE_PRESENT;
LunExt->DeviceFlags |= DFLAGS_DEVICE_PRESENT;
LunExt->DeviceFlags &= ~DFLAGS_ATAPI_DEVICE;
+ } else {
+ // This can be ATAPI on broken hardware
+ GetBaseStatus(chan, statusByte);
+ if(!at_home && UniataAnybodyHome(HwDeviceExtension, lChannel, deviceNumber)) {
+ KdPrint2((PRINT_PREFIX "CheckDevice: nobody at home post IDE\n"));
+ goto forget_device;
+ }
+ KdPrint2((PRINT_PREFIX "CheckDevice: try ATAPI %#x, status %#x\n",
+ deviceNumber, statusByte));
+ goto try_atapi;
}
GetBaseStatus(chan, statusByte);
}
}
/* re-enable AHCI mode */
+ /* Linux: Some controllers need AHCI_EN to be written multiple times.
+ * Try a few times before giving up.
+ */
GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
- if(!(GHC & AHCI_GHC_AE)) {
- KdPrint2((PRINT_PREFIX " re-enable AHCI mode, GHC %#x\n", GHC));
- UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
- GHC | AHCI_GHC_AE);
- GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
+ for(i=0; i<5; i++) {
+ if(!(GHC & AHCI_GHC_AE)) {
+ KdPrint2((PRINT_PREFIX " re-enable AHCI mode, GHC %#x\n", GHC));
+ UniataAhciWriteHostPort4(deviceExtension, IDX_AHCI_GHC,
+ GHC | AHCI_GHC_AE);
+ AtapiStallExecution(1000);
+ GHC = UniataAhciReadHostPort4(deviceExtension, IDX_AHCI_GHC);
+ } else {
+ break;
+ }
}
KdPrint2((PRINT_PREFIX " AHCI GHC %#x\n", GHC));
if(!(GHC & AHCI_GHC_AE)) {
CMD = UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD);
KdPrint2((" CMD %#x\n", CMD));
UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD | ATA_AHCI_P_CMD_FRE);
+ UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
return;
} // end UniataAhciStartFR()
CMD |
ATA_AHCI_P_CMD_ST |
((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0));
+ UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
return;
} // end UniataAhciStart()
if(CMD0 != CMD) {
KdPrint2((" send CMD %#x, entries %#x\n", CMD, AHCI_CL->prd_length));
UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, CMD);
+ UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
}
/* issue command to controller */
//UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_ACT, 0x01 << tag);
+ KdPrint2((" Set CI\n"));
UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CI, 0x01 << tag);
chan->AhciPrevCI |= 0x01 << tag;
+ KdPrint2((" Send CMD START\n"));
+ UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD,
+ CMD |
+ ATA_AHCI_P_CMD_ST |
+ ((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM) ? ATA_AHCI_P_CMD_PMA : 0));
+ UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
+
if(!ATAPI_DEVICE(chan, DeviceNumber)) {
- // TODO: check if we send ATA_RESET and wait for ready of so.
+ // TODO: check if we send ATAPI_RESET and wait for ready of so.
if(AtaReq->ahci.ahci_cmd_ptr->cfis[2] == IDE_COMMAND_ATAPI_RESET) {
ULONG TFD;
ULONG i;
(((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM)) ? ATA_AHCI_P_CMD_ALPE : 0) |
(((chan->ChannelCtrlFlags & CTRFLAGS_AHCI_PM2)) ? ATA_AHCI_P_CMD_ASP : 0 ))
);
+ UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
#ifdef DBG
//UniataDumpAhciPortRegs(chan);
UniataAhciStop(chan);
UniataAhciStopFR(chan);
UniataAhciWriteChannelPort4(chan, IDX_AHCI_P_CMD, 0);
+ UniataAhciReadChannelPort4(chan, IDX_AHCI_P_CMD); /* flush */
/* Allow everything including partial and slumber modes. */
UniataSataWritePort4(chan, IDX_SATA_SControl, 0, 0);
-#define UNIATA_VER_STR "45e"
-#define UNIATA_VER_DOT 0.45.5.0
+#define UNIATA_VER_STR "45h1"
+#define UNIATA_VER_DOT 0.45.8.1
#define UNIATA_VER_MJ 0
#define UNIATA_VER_MN 45
-#define UNIATA_VER_SUB_MJ 5
-#define UNIATA_VER_SUB_MN 0
-#define UNIATA_VER_DOT_COMMA 0,45,5,0
-#define UNIATA_VER_DOT_STR "0.45.5.0"
-#define UNIATA_VER_YEAR 2014
-#define UNIATA_VER_YEAR_STR "2014"
+#define UNIATA_VER_SUB_MJ 8
+#define UNIATA_VER_SUB_MN 1
+#define UNIATA_VER_DOT_COMMA 0,45,8,1
+#define UNIATA_VER_DOT_STR "0.45.8.1"
+#define UNIATA_VER_YEAR 2015
+#define UNIATA_VER_YEAR_STR "2015"