Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

875 lines
26 KiB

//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: timing.c
//
//--------------------------------------------------------------------------
#include "intel.h"
//
// PiixTiming[Master Timing Mode][Slave Timing Mode]
//
PIIX_SPECIAL_TIMING_REGISTER PiixSpecialTiming[PiixMode_MaxMode] =
{
{
PIIX_TIMING_DMA_TIMING_ENABLE(0) |
PIIX_TIMING_PREFETCH_AND_POSTING_ENABLE(0) |
PIIX_TIMING_IOREADY_SAMPLE_POINT_ENABLE(0) |
PIIX_TIMING_FAST_TIMING_BANK_ENABLE(0)
}, // not present
{
PIIX_TIMING_DMA_TIMING_ENABLE(0) |
PIIX_TIMING_PREFETCH_AND_POSTING_ENABLE(0) |
PIIX_TIMING_IOREADY_SAMPLE_POINT_ENABLE(0) |
PIIX_TIMING_FAST_TIMING_BANK_ENABLE(0)
}, // piix timing mode 0
{
PIIX_TIMING_DMA_TIMING_ENABLE(0) |
PIIX_TIMING_PREFETCH_AND_POSTING_ENABLE(0) |
PIIX_TIMING_IOREADY_SAMPLE_POINT_ENABLE(0) |
PIIX_TIMING_FAST_TIMING_BANK_ENABLE(1)
}, // piix timing mode 2
{
PIIX_TIMING_DMA_TIMING_ENABLE(0) |
PIIX_TIMING_PREFETCH_AND_POSTING_ENABLE(0) |
PIIX_TIMING_IOREADY_SAMPLE_POINT_ENABLE(1) |
PIIX_TIMING_FAST_TIMING_BANK_ENABLE(1)
}, // piix timing mode 3
{
PIIX_TIMING_DMA_TIMING_ENABLE(0) |
PIIX_TIMING_PREFETCH_AND_POSTING_ENABLE(0) |
PIIX_TIMING_IOREADY_SAMPLE_POINT_ENABLE(1) |
PIIX_TIMING_FAST_TIMING_BANK_ENABLE(1)
} // piix timing mode 4
};
UCHAR PiixIoReadySamplePointClockSetting[PiixMode_MaxMode] =
{
0,
0,
1,
2,
2
};
UCHAR PiixRecoveryTimeClockSetting[PiixMode_MaxMode] =
{
0,
0,
0,
1,
3
};
NTSTATUS
PiixIdeUdmaModesSupported (
IN IDENTIFY_DATA IdentifyData,
IN OUT PULONG BestXferMode,
IN OUT PULONG CurrentMode
)
{
ULONG bestXferMode =0;
ULONG currentMode = 0;
if (IdentifyData.TranslationFieldsValid & (1 << 2)) {
if (IdentifyData.UltraDMASupport) {
GetHighestTransferMode( IdentifyData.UltraDMASupport,
bestXferMode);
*BestXferMode = bestXferMode;
}
if (IdentifyData.UltraDMAActive) {
GetHighestTransferMode( IdentifyData.UltraDMAActive,
currentMode);
*CurrentMode = currentMode;
}
}
return STATUS_SUCCESS;
}
NTSTATUS
PiixIdeTransferModeSelect (
IN PDEVICE_EXTENSION DeviceExtension,
IN OUT PPCIIDE_TRANSFER_MODE_SELECT TransferModeSelect
)
{
NTSTATUS status;
ULONG driveBestXferMode[MAX_IDE_DEVICE];
PIIX_TIMING_REGISTER piixTimingReg;
PIIX3_SLAVE_TIMING_REGISTER piixSlaveTimingReg;
PIIX4_UDMA_CONTROL_REGISTER piix4UdmaControlReg;
PIIX4_UDMA_TIMING_REGISTER piix4UdmaTimingReg;
ICH_IO_CONFIG_REGISTER ioConfigReg;
USHORT dataMask;
ULONG i;
//
// Store the identify data for later use.
//
for (i=0;i<MAX_IDE_DEVICE;i++) {
DeviceExtension->IdentifyData[i]=TransferModeSelect->IdentifyData[i];
}
status = PiixIdepTransferModeSelect (
DeviceExtension,
TransferModeSelect,
driveBestXferMode,
&piixTimingReg,
&piixSlaveTimingReg,
&piix4UdmaControlReg,
&piix4UdmaTimingReg,
&ioConfigReg
);
if (NT_SUCCESS(status)) {
#if DBG
{
PIIX_TIMING_REGISTER piixOldTimingReg[2];
PIIX3_SLAVE_TIMING_REGISTER piixOldSlaveTimingReg;
PIIX4_UDMA_CONTROL_REGISTER piix4OldUdmaControlReg;
PIIX4_UDMA_TIMING_REGISTER piix4OldUdmaTimingReg;
ICH_IO_CONFIG_REGISTER oldIoConfigReg;
ULONG channel;
#define BitSet(Data, Mask, NewData) Data = ((Data & ~Mask) | (Mask & NewData));
piixOldSlaveTimingReg.AsUChar = 0;
piix4OldUdmaControlReg.AsUChar = 0;
piix4OldUdmaTimingReg.AsUChar = 0;
channel = TransferModeSelect->Channel;
PciIdeXGetBusData (
DeviceExtension,
piixOldTimingReg,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, Timing),
sizeof (piixOldTimingReg)
);
PciIdeXDebugPrint ((1,
"Old PIIX Timing Register Value (IDETIM = 0x%x",
piixOldTimingReg[channel].AsUShort));
if (!IS_PIIX(DeviceExtension->DeviceId)) {
PciIdeXGetBusData (
DeviceExtension,
&piixOldSlaveTimingReg,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, SlaveTiming),
sizeof (piixOldSlaveTimingReg)
);
PciIdeXDebugPrint ((1,
" SIDETIM (0x%x)",
piixOldSlaveTimingReg.AsUChar));
}
if (IS_UDMA_CONTROLLER(DeviceExtension->DeviceId)) {
PciIdeXGetBusData (
DeviceExtension,
&piix4OldUdmaControlReg,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, UdmaControl),
sizeof (piix4OldUdmaControlReg)
);
PciIdeXDebugPrint ((1,
" SDMACTL (0x%x)",
piix4OldUdmaControlReg.AsUChar));
PciIdeXGetBusData (
DeviceExtension,
&piix4OldUdmaTimingReg,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, UdmaTiming[channel]),
sizeof (piix4OldUdmaTimingReg)
);
PciIdeXDebugPrint ((1,
" SDMATIM (0x%x)",
piix4OldUdmaTimingReg.AsUChar));
}
if (IS_ICH_(DeviceExtension->DeviceId) ||
IS_ICH0(DeviceExtension->DeviceId)) {
PciIdeXGetBusData (
DeviceExtension,
&oldIoConfigReg,
FIELD_OFFSET(ICH_PCI_CONFIG_DATA, IoConfig),
sizeof (oldIoConfigReg)
);
PciIdeXDebugPrint ((1,
" I/O Control (0x%x)",
oldIoConfigReg.AsUShort));
}
PciIdeXDebugPrint ((1, "\n"));
if (channel == 0) {
BitSet (piixOldSlaveTimingReg.AsUChar, 0x0f, piixSlaveTimingReg.AsUChar);
BitSet (piix4OldUdmaControlReg.AsUChar, 0x03, piix4UdmaControlReg.AsUChar);
} else {
BitSet (piixOldSlaveTimingReg.AsUChar, 0xf0, piixSlaveTimingReg.AsUChar);
BitSet (piix4OldUdmaControlReg.AsUChar, 0x0c, piix4UdmaControlReg.AsUChar);
}
BitSet (oldIoConfigReg.AsUShort, 0x0f, ioConfigReg.AsUShort);
PciIdeXDebugPrint ((1,
"New PIIX/ICH Timing Register Value (IDETIM = 0x%x, SIDETIM (0x%x), SDMACTL (0x%x), SDMATIM (0x%x), IOCTRL (0x%x)\n",
piixTimingReg.AsUShort,
piixOldSlaveTimingReg.AsUChar,
piix4OldUdmaControlReg.AsUChar,
piix4UdmaTimingReg.AsUChar,
oldIoConfigReg.AsUShort
));
}
#endif // DBG
#ifndef PIIX_TIMING_REGISTER_SUPPORT
status = STATUS_UNSUCCESSFUL;
goto GetOut;
#endif
dataMask = 0xffff;
status = PciIdeXSetBusData (
DeviceExtension,
&piixTimingReg,
&dataMask,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, Timing) +
sizeof(piixTimingReg) *
TransferModeSelect->Channel,
sizeof (piixTimingReg)
);
if (!NT_SUCCESS(status)) {
goto GetOut;
}
if (!IS_PIIX(DeviceExtension->DeviceId)) {
dataMask = TransferModeSelect->Channel == 0 ? 0x0f : 0xf0;
status = PciIdeXSetBusData (
DeviceExtension,
&piixSlaveTimingReg,
&dataMask,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, SlaveTiming),
sizeof (piixSlaveTimingReg)
);
if (!NT_SUCCESS(status)) {
ASSERT(!"Unable to set pci config data\n");
goto GetOut;
}
}
if (IS_UDMA_CONTROLLER(DeviceExtension->DeviceId)) {
//
// UDMA Control Register
//
dataMask = TransferModeSelect->Channel == 0 ? 0x03 : 0x0c;
status = PciIdeXSetBusData (
DeviceExtension,
&piix4UdmaControlReg,
&dataMask,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, UdmaControl),
sizeof (piix4UdmaControlReg)
);
if (!NT_SUCCESS(status)) {
ASSERT(!"Unable to set pci config data\n");
goto GetOut;
}
//
// UDMA Timing Register
//
dataMask = 0xff;
status = PciIdeXSetBusData (
DeviceExtension,
&piix4UdmaTimingReg,
&dataMask,
FIELD_OFFSET(PIIX4_PCI_CONFIG_DATA, UdmaTiming) +
sizeof(piix4UdmaTimingReg) *
TransferModeSelect->Channel,
sizeof (piix4UdmaTimingReg)
);
if (!NT_SUCCESS(status)) {
ASSERT(!"Unable to set pci config data\n");
goto GetOut;
}
}
if (IS_ICH_(DeviceExtension->DeviceId) ||
IS_ICH0(DeviceExtension->DeviceId) ||
IS_ICH2(DeviceExtension->DeviceId)) {
//
// UDMA Control Register
//
dataMask = TransferModeSelect->Channel == 0 ? 0x0403 : 0x040c;
status = PciIdeXSetBusData (
DeviceExtension,
&ioConfigReg,
&dataMask,
FIELD_OFFSET(ICH_PCI_CONFIG_DATA, IoConfig),
sizeof (ioConfigReg)
);
if (!NT_SUCCESS(status)) {
ASSERT(!"Unable to set pci config data\n");
goto GetOut;
}
}
}
GetOut:
if (NT_SUCCESS(status)) {
for (i = 0; i < MAX_IDE_DEVICE; i++) {
TransferModeSelect->DeviceTransferModeSelected[i] =
driveBestXferMode[i];
}
}
return status;
}
NTSTATUS
PiixIdepTransferModeSelect (
IN PDEVICE_EXTENSION DeviceExtension,
IN PPCIIDE_TRANSFER_MODE_SELECT TransferModeSelect,
OUT ULONG DriveBestXferMode[MAX_IDE_DEVICE],
OUT PPIIX_TIMING_REGISTER PiixTimingReg,
OUT PPIIX3_SLAVE_TIMING_REGISTER PiixSlaveTimingReg,
OUT PPIIX4_UDMA_CONTROL_REGISTER Piix4UdmaControlReg,
OUT PPIIX4_UDMA_TIMING_REGISTER Piix4UdmaTimingReg,
OUT PICH_IO_CONFIG_REGISTER IoConfigReg
)
{
ULONG i;
ULONG xferMode;
ULONG channel;
NTSTATUS status;
UCHAR ispClockSetting;
UCHAR recoveryClockSetting;
PIIX_TIMING_MODE piixTimingMode;
PIIX_SPECIAL_TIMING_REGISTER piixSpecialTiming;
ULONG driveBestXferMode[MAX_IDE_DEVICE];
PIIX_TIMING_REGISTER piixTimingReg;
PIIX3_SLAVE_TIMING_REGISTER piixSlaveTimingReg;
PIIX4_UDMA_CONTROL_REGISTER piix4UdmaControlReg;
PIIX4_UDMA_TIMING_REGISTER piix4UdmaTimingReg;
ICH_IO_CONFIG_REGISTER ioConfigReg;
ULONG transferModeSupported;
PULONG transferModeTimingTable;
channel = TransferModeSelect->Channel;
piixTimingReg.AsUShort = 0;
piixSlaveTimingReg.AsUChar = 0;
transferModeTimingTable=TransferModeSelect->TransferModeTimingTable;
ASSERT(transferModeTimingTable);
for (i = 0; i < MAX_IDE_DEVICE; i++) {
ULONG enableUdma66 = TransferModeSelect->EnableUDMA66;
driveBestXferMode[i] = 0;
if (TransferModeSelect->DevicePresent[i] == FALSE) {
continue;
}
#if 1
//
// UDMA transfer mode
//
transferModeSupported=TransferModeSelect->DeviceTransferModeSupported[i];
//
// only upto udma 5 is supported
//
transferModeSupported &= 0x1ffff;
//
// translate drive reported udma settings to drive's best udma mode
// UDMA_MASK masks out udma mode >2 if cableReady or enableUdma is not set for a
// controller that supports modes > udma2. enableUdma flag is ignored for Udma100
// controllers
//
UDMA_MASK(DeviceExtension->UdmaController, DeviceExtension->CableReady[channel][i],
enableUdma66, transferModeSupported);
GetHighestDMATransferMode(transferModeSupported, xferMode);
if (xferMode >= UDMA0) {
driveBestXferMode[i] = 1 << xferMode;
}
//
// DMA transfer mode
//
//
// Get the highest DMA mode (exclude UDMA)
//
transferModeSupported = TransferModeSelect->
DeviceTransferModeSupported[i] & (MWDMA_SUPPORT | SWDMA_SUPPORT);
GetHighestDMATransferMode(transferModeSupported, xferMode);
//
// if xfermode is mwdma2 or 1, select mwdma2 , 1 or swdma2 depending on the cycle time
//
if (xferMode >= MWDMA1) {
while (xferMode >= SWDMA2) {
//
// MWDMA0 is not supported
//
if (xferMode == MWDMA0) {
xferMode--;
continue;
}
if (TransferModeSelect->BestMwDmaCycleTime[i] <= transferModeTimingTable[xferMode]) {
driveBestXferMode[i] |= (1 << xferMode);
break;
}
xferMode--;
}
} else if (xferMode == SWDMA2) {
if (TransferModeSelect->BestSwDmaCycleTime[i] <= transferModeTimingTable[xferMode]) {
driveBestXferMode[i] |= SWDMA_MODE2;
} //else use PIO
}
//
// Don't use SWDMA0 and SWDMA1
//
//
// PIO transfer mode
//
transferModeSupported=TransferModeSelect->DeviceTransferModeSupported[i];
GetHighestPIOTransferMode(transferModeSupported, xferMode);
//
// if PIO2 is the highest PIO mode supported, don't check the
// bestPIOTiming reported by the device.
//
if (xferMode == PIO2) {
driveBestXferMode[i] |= (1 << xferMode);
} else {
//
// PIO1 is not supported
//
while (xferMode > PIO1) {
if (TransferModeSelect->BestPioCycleTime[i] <= transferModeTimingTable[xferMode]) {
driveBestXferMode[i] |= (1 << xferMode);
break;
}
xferMode--;
}
//
// default to PIO0
//
if (xferMode <= PIO1) {
driveBestXferMode[i] |= (1 << PIO0);
}
}
#endif
}
//
// use the slower mode if we have a old piix and two devices on the channel
//
if (IS_PIIX(DeviceExtension->DeviceId)) {
if (TransferModeSelect->DevicePresent[0] && TransferModeSelect->DevicePresent[1]) {
ULONG mode;
if ((driveBestXferMode[0] & PIO_SUPPORT) <=
(driveBestXferMode[1] & PIO_SUPPORT)) {
mode = driveBestXferMode[0] & PIO_SUPPORT;
} else {
mode = driveBestXferMode[1] & PIO_SUPPORT;
}
if ((driveBestXferMode[0] & SWDMA_SUPPORT) <=
(driveBestXferMode[1] & SWDMA_SUPPORT)) {
mode |= driveBestXferMode[0] & SWDMA_SUPPORT;
} else {
mode |= driveBestXferMode[1] & SWDMA_SUPPORT;
}
if ((driveBestXferMode[0] & MWDMA_SUPPORT) <=
(driveBestXferMode[1] & MWDMA_SUPPORT)) {
mode |= driveBestXferMode[0] & MWDMA_SUPPORT;
} else {
mode |= driveBestXferMode[1] & MWDMA_SUPPORT;
}
if ((driveBestXferMode[0] & UDMA_SUPPORT) <=
(driveBestXferMode[1] & UDMA_SUPPORT)) {
mode |= driveBestXferMode[0] & UDMA_SUPPORT;
} else {
mode |= driveBestXferMode[1] & UDMA_SUPPORT;
}
driveBestXferMode[0] = driveBestXferMode[1] = mode;
}
}
//
// translate device ATA timing mode to piix timing mode
//
for (i = 0; i < MAX_IDE_DEVICE; i++) {
piixSpecialTiming.AsUChar = 0;
if (TransferModeSelect->DevicePresent[i] == FALSE) {
piixTimingMode = PiixMode_NotPresent;
} else {
//
// default
//
piixTimingMode = PiixMode_Mode0;
if (!(driveBestXferMode[i] & DMA_SUPPORT)) {
//
// pio only device
//
if (driveBestXferMode[i] & PIO_MODE0) {
piixTimingMode = PiixMode_Mode0;
} else if (driveBestXferMode[i] & PIO_MODE2) {
piixTimingMode = PiixMode_Mode2;
if (TransferModeSelect->IoReadySupported[i]) {
piixSpecialTiming.AsUChar |= PIIX_TIMING_IOREADY_SAMPLE_POINT_ENABLE(1);
}
} else if (driveBestXferMode[i] & PIO_MODE3) {
piixTimingMode = PiixMode_Mode3;
} else if (driveBestXferMode[i] & PIO_MODE4) {
piixTimingMode = PiixMode_Mode4;
} else {
ASSERT(FALSE);
}
} else if (driveBestXferMode[i] & SWDMA_MODE2) {
piixTimingMode = PiixMode_Mode2;
if (driveBestXferMode[i] & PIO_MODE0) {
piixSpecialTiming.AsUChar |= PIIX_TIMING_DMA_TIMING_ENABLE(1);
}
if (TransferModeSelect->IoReadySupported[i]) {
piixSpecialTiming.AsUChar |= PIIX_TIMING_IOREADY_SAMPLE_POINT_ENABLE(1);
}
} else if (driveBestXferMode[i] & MWDMA_MODE1) {
piixTimingMode = PiixMode_Mode3;
if (driveBestXferMode[i] & (PIO_MODE0 | PIO_MODE2)) {
piixSpecialTiming.AsUChar |= PIIX_TIMING_DMA_TIMING_ENABLE(1);
}
} else if (driveBestXferMode[i] & MWDMA_MODE2) {
if (driveBestXferMode[i] & PIO_MODE3) {
piixTimingMode = PiixMode_Mode3;
} else {
piixTimingMode = PiixMode_Mode4;
}
if (driveBestXferMode[i] & (PIO_MODE0 | PIO_MODE2)) {
piixSpecialTiming.AsUChar |= PIIX_TIMING_DMA_TIMING_ENABLE(1);
}
}
if (TransferModeSelect->FixedDisk[i]) {
piixSpecialTiming.AsUChar |= PIIX_TIMING_PREFETCH_AND_POSTING_ENABLE(1);
}
}
piixSpecialTiming.AsUChar |= PiixSpecialTiming[piixTimingMode].AsUChar;
if (i == 0) {
//
// master device
//
piixTimingReg.b.IoReadySamplePoint = PiixIoReadySamplePointClockSetting[piixTimingMode];
piixTimingReg.b.RecoveryTime = PiixRecoveryTimeClockSetting[piixTimingMode];
piixTimingReg.b.n.Device0SpecialTiming = piixSpecialTiming.AsUChar & 0xf;
} else {
//
// slave device
//
if (channel == 0) {
piixSlaveTimingReg.b.Channel0IoReadySamplePoint = PiixIoReadySamplePointClockSetting[piixTimingMode];
piixSlaveTimingReg.b.Channel0RecoveryTime = PiixRecoveryTimeClockSetting[piixTimingMode];
} else {
piixSlaveTimingReg.b.Channel1IoReadySamplePoint = PiixIoReadySamplePointClockSetting[piixTimingMode];
piixSlaveTimingReg.b.Channel1RecoveryTime = PiixRecoveryTimeClockSetting[piixTimingMode];
}
piixTimingReg.b.n.Device1SpecialTiming = piixSpecialTiming.AsUChar & 0xf;
}
}
if (!IS_PIIX(DeviceExtension->DeviceId)) {
//
// enable the timing setting for the slave
//
piixTimingReg.b.SlaveTimingEnable = 1;
} else {
piixSlaveTimingReg.AsUChar = 0;
}
//
// make sure the channel is enabled
//
piixTimingReg.b.ChannelEnable = 1;
//
// setup up udma
//
piix4UdmaControlReg.AsUChar = 0;
piix4UdmaTimingReg.AsUChar = 0;
ioConfigReg.AsUShort = 0;
ioConfigReg.b.WriteBufferPingPongEnable = 1;
for (i = 0; i < MAX_IDE_DEVICE; i++) {
if (driveBestXferMode[i] & UDMA_SUPPORT) {
UCHAR udmaTiming;
if (driveBestXferMode[i] & UDMA_MODE5) {
udmaTiming = ICH2_UDMA_MODE5_TIMING;
} else if (driveBestXferMode[i] & UDMA_MODE4) {
udmaTiming = ICH_UDMA_MODE4_TIMING;
} else if (driveBestXferMode[i] & UDMA_MODE3) {
udmaTiming = ICH_UDMA_MODE3_TIMING;
} else if (driveBestXferMode[i] & UDMA_MODE2) {
udmaTiming = PIIX4_UDMA_MODE2_TIMING;
} else if (driveBestXferMode[i] & UDMA_MODE1) {
udmaTiming = PIIX4_UDMA_MODE1_TIMING;
} else if (driveBestXferMode[i] & UDMA_MODE0) {
udmaTiming = PIIX4_UDMA_MODE0_TIMING;
} else {
ASSERT (!"intelide: Unknown UDMA MODE\n");
//
// we will use udma mode 5
//
udmaTiming = ICH2_UDMA_MODE5_TIMING;
}
if (i == 0) {
if (channel == 0) {
//
// primary master
//
piix4UdmaControlReg.b.Channel0Drive0UdmaEnable = 1;
if (driveBestXferMode[i] & UDMA66_SUPPORT) {
ioConfigReg.b.PrimaryMasterBaseClock = 1;
}
if (driveBestXferMode[i] & UDMA100_SUPPORT) {
ioConfigReg.b.FastPrimaryMasterBaseClock = 1;
}
} else {
//
// secondary master
//
piix4UdmaControlReg.b.Channel1Drive0UdmaEnable = 1;
if (driveBestXferMode[i] & UDMA66_SUPPORT) {
ioConfigReg.b.SecondaryMasterBaseClock = 1;
}
if (driveBestXferMode[i] & UDMA100_SUPPORT) {
ioConfigReg.b.FastSecondaryMasterBaseClock = 1;
}
}
piix4UdmaTimingReg.b.Drive0CycleTime = udmaTiming;
} else {
ASSERT(i==1);
if (channel == 0) {
//
// primary slave
//
piix4UdmaControlReg.b.Channel0Drive1UdmaEnable = 1;
if (driveBestXferMode[i] & UDMA66_SUPPORT) {
ioConfigReg.b.PrimarySlaveBaseClock = 1;
}
if (driveBestXferMode[i] & UDMA100_SUPPORT) {
ioConfigReg.b.FastPrimarySlaveBaseClock = 1;
}
} else {
//
// secondary slave
//
piix4UdmaControlReg.b.Channel1Drive1UdmaEnable = 1;
if (driveBestXferMode[i] & UDMA66_SUPPORT) {
ioConfigReg.b.SecondarySlaveBaseClock = 1;
}
if (driveBestXferMode[i] & UDMA100_SUPPORT) {
ioConfigReg.b.FastSecondarySlaveBaseClock = 1;
}
}
piix4UdmaTimingReg.b.Drive1CycleTime = udmaTiming;
}
//
// if the drive support UDMA, use UDMA
// turn off other DMA mode
//
driveBestXferMode[i] &= ~(MWDMA_SUPPORT | SWDMA_SUPPORT);
}
}
//
// setup the return data
//
for (i = 0; i < MAX_IDE_DEVICE; i++) {
DriveBestXferMode[i] = driveBestXferMode[i];
}
*PiixTimingReg = piixTimingReg;
*PiixSlaveTimingReg = piixSlaveTimingReg;
*Piix4UdmaControlReg = piix4UdmaControlReg;
*Piix4UdmaTimingReg = piix4UdmaTimingReg;
*IoConfigReg = ioConfigReg;
return STATUS_SUCCESS;
}