*/
#define ENABLE_PCI
+#define ENABLE_NATIVE_PCI
#define ENABLE_ISA
// -------------------------------------------------------------------------
IDE_DRIVE_IDENTIFY DeviceParams[2];
BOOLEAN DevicePresent[2];
BOOLEAN DeviceAtapi[2];
+ ULONG TransferSize[2];
+ BOOLEAN MultiSectorCommand[2];
+ BOOLEAN DWordIo[2];
+
ULONG CommandPortBase;
ULONG ControlPortBase;
BOOLEAN ExpectingInterrupt;
PSCSI_REQUEST_BLOCK CurrentSrb;
- PUSHORT DataBuffer;
+
+ PUCHAR DataBuffer;
+ ULONG DataTransferLength;
} ATAPI_MINIPORT_EXTENSION, *PATAPI_MINIPORT_EXTENSION;
ULONG Dummy;
} UNIT_EXTENSION, *PUNIT_EXTENSION;
+PCI_SLOT_NUMBER LastSlotNumber;
+
+#ifdef ENABLE_NATIVE_PCI
+typedef struct _PCI_NATIVE_CONTROLLER
+{
+ USHORT VendorID;
+ USHORT DeviceID;
+}
+PCI_NATIVE_CONTROLLER, *PPCI_NATIVE_CONTROLLER;
+
+PCI_NATIVE_CONTROLLER const PciNativeController[] =
+{
+ {
+ 0x105A, // Promise
+ 0x4D68, // PDC20268, Ultra100TX2
+ },
+ {
+ 0x105A, // Promise
+ 0x4D30, // PDC20267, Ultra100
+ }
+};
+#endif
+
// ----------------------------------------------- Discardable Declarations
AtapiReadWrite(IN PATAPI_MINIPORT_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb);
+static ULONG
+AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb);
static UCHAR
AtapiErrorToScsi(PVOID DeviceExtension,
InitData.MapBuffers = TRUE;
+
/* Search the PCI bus for compatibility mode ide controllers */
#ifdef ENABLE_PCI
InitData.HwFindAdapter = AtapiFindCompatiblePciController;
// statusToReturn = newStatus;
#endif
- /* Search the ISA bus for ide controllers */
-#ifdef ENABLE_ISA
- InitData.HwFindAdapter = AtapiFindIsaBusController;
- InitData.NumberOfAccessRanges = 2;
- InitData.AdapterInterfaceType = Isa;
+ /* Search the PCI bus for all ide controllers */
+#ifdef ENABLE_NATIVE_PCI
- InitData.VendorId = NULL;
+ InitData.HwFindAdapter = AtapiFindNativePciController;
+ InitData.NumberOfAccessRanges = 3;
+ InitData.AdapterInterfaceType = PCIBus;
+
+ InitData.VendorId = 0;
InitData.VendorIdLength = 0;
- InitData.DeviceId = NULL;
+ InitData.DeviceId = 0;
InitData.DeviceIdLength = 0;
+ LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
+
Status = ScsiPortInitialize(DriverObject,
RegistryPath,
&InitData,
NULL);
-// if (newStatus < statusToReturn)
-// statusToReturn = newStatus;
+// if (newStatus < statusToReturn)
+// statusToReturn = newStatus;
#endif
- /* Search the PCI bus for native mode ide controllers */
-#if 0
- InitData.HwFindAdapter = AtapiFindNativePciController;
+ /* Search the ISA bus for ide controllers */
+#ifdef ENABLE_ISA
+ InitData.HwFindAdapter = AtapiFindIsaBusController;
InitData.NumberOfAccessRanges = 2;
- InitData.AdapterInterfaceType = PCIBus;
+ InitData.AdapterInterfaceType = Isa;
InitData.VendorId = NULL;
InitData.VendorIdLength = 0;
Status = ScsiPortInitialize(DriverObject,
RegistryPath,
&InitData,
- (PVOID)i);
-// if (newStatus < statusToReturn)
-// statusToReturn = newStatus;
+ NULL);
+// if (newStatus < statusToReturn)
+// statusToReturn = newStatus;
#endif
DPRINT("Returning from DriverEntry\n");
}
+BOOLEAN
+AtapiClaimHwResources(PATAPI_MINIPORT_EXTENSION DevExt,
+ PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+ INTERFACE_TYPE InterfaceType,
+ ULONG CommandPortBase,
+ ULONG ControlPortBase,
+ ULONG BusMasterPortBase,
+ ULONG InterruptVector)
+{
+ SCSI_PHYSICAL_ADDRESS IoAddress;
+ PVOID IoBase;
+
+ IoAddress = ScsiPortConvertUlongToPhysicalAddress(CommandPortBase);
+ IoBase = ScsiPortGetDeviceBase((PVOID)DevExt,
+ InterfaceType,
+ ConfigInfo->SystemIoBusNumber,
+ IoAddress,
+ 8,
+ TRUE);
+ if (IoBase == NULL)
+ {
+ return FALSE;
+ }
+ DevExt->CommandPortBase = (ULONG)IoBase;
+ ConfigInfo->AccessRanges[0].RangeStart = IoAddress;
+ ConfigInfo->AccessRanges[0].RangeLength = 8;
+ ConfigInfo->AccessRanges[0].RangeInMemory = FALSE;
+
+ if (ControlPortBase)
+ {
+ IoAddress = ScsiPortConvertUlongToPhysicalAddress(ControlPortBase + 2);
+ IoBase = ScsiPortGetDeviceBase((PVOID)DevExt,
+ InterfaceType,
+ ConfigInfo->SystemIoBusNumber,
+ IoAddress,
+ 1,
+ TRUE);
+ if (IoBase == NULL)
+ {
+ ScsiPortFreeDeviceBase((PVOID)DevExt,
+ (PVOID)DevExt->CommandPortBase);
+ return FALSE;
+ }
+ DevExt->ControlPortBase = (ULONG)IoBase;
+ ConfigInfo->AccessRanges[1].RangeStart = IoAddress;
+ ConfigInfo->AccessRanges[1].RangeLength = 1;
+ ConfigInfo->AccessRanges[1].RangeInMemory = FALSE;
+ }
+ if (BusMasterPortBase)
+ {
+ IoAddress = ScsiPortConvertUlongToPhysicalAddress(BusMasterPortBase);
+ IoBase = ScsiPortGetDeviceBase((PVOID)DevExt,
+ InterfaceType,
+ ConfigInfo->SystemIoBusNumber,
+ IoAddress,
+ 8,
+ TRUE);
+ if (IoBase == NULL)
+ {
+ ScsiPortFreeDeviceBase((PVOID)DevExt, (PVOID)DevExt->CommandPortBase);
+ ScsiPortFreeDeviceBase((PVOID)DevExt, (PVOID)DevExt->ControlPortBase);
+ return FALSE;
+ }
+ ConfigInfo->AccessRanges[2].RangeStart = IoAddress;
+ ConfigInfo->AccessRanges[2].RangeLength = 8;
+ ConfigInfo->AccessRanges[2].RangeInMemory = FALSE;
+ }
+ ConfigInfo->BusInterruptLevel = InterruptVector;
+ ConfigInfo->BusInterruptVector = InterruptVector;
+ ConfigInfo->InterruptMode = (InterfaceType == Isa) ? Latched : LevelSensitive;
+
+ if ((CommandPortBase == 0x1F0 || ControlPortBase == 0x3F4) && !ConfigInfo->AtdiskPrimaryClaimed)
+ {
+ ConfigInfo->AtdiskPrimaryClaimed = TRUE;
+ }
+ if ((CommandPortBase == 0x170 || ControlPortBase == 0x374) && !ConfigInfo->AtdiskSecondaryClaimed)
+ {
+ ConfigInfo->AtdiskSecondaryClaimed = TRUE;
+ }
+ return TRUE;
+}
+
+
+#ifdef ENABLE_PCI
static ULONG STDCALL
AtapiFindCompatiblePciController(PVOID DeviceExtension,
PVOID HwContext,
PCI_SLOT_NUMBER SlotNumber;
PCI_COMMON_CONFIG PciConfig;
ULONG DataSize;
+ ULONG StartDeviceNumber;
+ ULONG DeviceNumber;
+ ULONG StartFunctionNumber;
ULONG FunctionNumber;
BOOLEAN ChannelFound;
BOOLEAN DeviceFound;
+ ULONG BusMasterBasePort = 0;
DPRINT("AtapiFindCompatiblePciController() Bus: %lu Slot: %lu\n",
ConfigInfo->SystemIoBusNumber,
ConfigInfo->AtdiskSecondaryClaimed == TRUE)
return(SP_RETURN_NOT_FOUND);
-
- SlotNumber.u.AsULONG = 0;
- for (FunctionNumber = 0 /*ConfigInfo->SlotNumber*/; FunctionNumber < 256; FunctionNumber++)
- {
- SlotNumber.u.AsULONG = FunctionNumber;
-
- ChannelFound = FALSE;
- DeviceFound = FALSE;
-
- DataSize = ScsiPortGetBusData(DeviceExtension,
- PCIConfiguration,
- 0,
- SlotNumber.u.AsULONG,
- &PciConfig,
- sizeof(PCI_COMMON_CONFIG));
-// if (DataSize != sizeof(PCI_COMMON_CONFIG) ||
-// PciConfig.VendorID == PCI_INVALID_VENDORID)
- if (DataSize == 0)
+ SlotNumber.u.AsULONG = ConfigInfo->SlotNumber;
+ StartDeviceNumber = SlotNumber.u.bits.DeviceNumber;
+ StartFunctionNumber = SlotNumber.u.bits.FunctionNumber;
+ for (DeviceNumber = StartDeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
+ {
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+ for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+ {
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+ ChannelFound = FALSE;
+ DeviceFound = FALSE;
+
+ DataSize = ScsiPortGetBusData(DeviceExtension,
+ PCIConfiguration,
+ ConfigInfo->SystemIoBusNumber,
+ SlotNumber.u.AsULONG,
+ &PciConfig,
+ PCI_COMMON_HDR_LENGTH);
+ if (DataSize != PCI_COMMON_HDR_LENGTH)
{
-// if ((SlotNumber.u.AsULONG & 0x07) == 0)
-// return(SP_RETURN_ERROR); /* No bus found */
-
- continue;
-// return(SP_RETURN_ERROR);
+ if (FunctionNumber == 0)
+ {
+ break;
+ }
+ else
+ {
+ continue;
+ }
}
-
- if (PciConfig.BaseClass == 0x01 &&
- PciConfig.SubClass == 0x01) // &&
-// (PciConfig.ProgIf & 0x05) == 0)
+
+ DPRINT("%x %x\n", PciConfig.BaseClass, PciConfig.SubClass);
+ if (PciConfig.BaseClass == 0x01 &&
+ PciConfig.SubClass == 0x01) // &&
+// (PciConfig.ProgIf & 0x05) == 0)
{
- /* both channels are in compatibility mode */
- DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
- ConfigInfo->SystemIoBusNumber,
- SlotNumber.u.bits.DeviceNumber,
- SlotNumber.u.bits.FunctionNumber,
- PciConfig.VendorID,
- PciConfig.DeviceID);
- DPRINT("ProgIF 0x%02hx\n", PciConfig.ProgIf);
-
- DPRINT("Found IDE controller in compatibility mode!\n");
-
- ConfigInfo->NumberOfBuses = 1;
- ConfigInfo->MaximumNumberOfTargets = 2;
- ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */
-
- if (PciConfig.ProgIf & 0x80)
- {
+ /* both channels are in compatibility mode */
+ DPRINT("Bus %1lu Device %2lu Func %1lu VenID 0x%04hx DevID 0x%04hx\n",
+ ConfigInfo->SystemIoBusNumber,
+ SlotNumber.u.bits.DeviceNumber,
+ SlotNumber.u.bits.FunctionNumber,
+ PciConfig.VendorID,
+ PciConfig.DeviceID);
+ DPRINT("ProgIF 0x%02hx\n", PciConfig.ProgIf);
+
+ DPRINT("Found IDE controller in compatibility mode!\n");
+
+ ConfigInfo->NumberOfBuses = 1;
+ ConfigInfo->MaximumNumberOfTargets = 2;
+ ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */
+
+ if (PciConfig.ProgIf & 0x80)
+ {
DPRINT("Found IDE Bus Master controller!\n");
- if (PciConfig.u.type0.BaseAddresses[4] & 0x00000001)
- {
- DPRINT(" IDE Bus Master Registers at IO %lx\n",
- PciConfig.u.type0.BaseAddresses[4] & ~0x00000003);
- }
- }
-
- if (ConfigInfo->AtdiskPrimaryClaimed == FALSE)
- {
+ if (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE)
+ {
+ BusMasterBasePort = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
+ DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort);
+ }
+ }
+ if (ConfigInfo->AtdiskPrimaryClaimed == FALSE)
+ {
/* Both channels unclaimed: Claim primary channel */
DPRINT("Primary channel!\n");
-
- DevExt->CommandPortBase = 0x01F0;
- DevExt->ControlPortBase = 0x03F6;
-
- ConfigInfo->BusInterruptLevel = 14;
- ConfigInfo->BusInterruptVector = 14;
- ConfigInfo->InterruptMode = LevelSensitive;
-
- ConfigInfo->AccessRanges[0].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(0x01F0);
- ConfigInfo->AccessRanges[0].RangeLength = 8;
- ConfigInfo->AccessRanges[0].RangeInMemory = FALSE;
-
- ConfigInfo->AccessRanges[1].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(0x03F6);
- ConfigInfo->AccessRanges[1].RangeLength = 1;
- ConfigInfo->AccessRanges[1].RangeInMemory = FALSE;
-
- /* Claim bus master registers */
- if (PciConfig.ProgIf & 0x80)
- {
- DevExt->BusMasterRegisterBase =
- PciConfig.u.type0.BaseAddresses[4] & ~0x00000003;
-
- ConfigInfo->AccessRanges[2].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(DevExt->BusMasterRegisterBase);
- ConfigInfo->AccessRanges[2].RangeLength = 8;
- ConfigInfo->AccessRanges[2].RangeInMemory = FALSE;
- }
-
- ConfigInfo->AtdiskPrimaryClaimed = TRUE;
- ChannelFound = TRUE;
- *Again = TRUE;
- }
- else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE)
- {
+ ChannelFound = AtapiClaimHwResources(DevExt,
+ ConfigInfo,
+ PCIBus,
+ 0x1F0,
+ 0x3F4,
+ BusMasterBasePort,
+ 14);
+ *Again = TRUE;
+ }
+ else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE)
+ {
/* Primary channel already claimed: claim secondary channel */
DPRINT("Secondary channel!\n");
- DevExt->CommandPortBase = 0x0170;
- DevExt->ControlPortBase = 0x0376;
-
- ConfigInfo->BusInterruptLevel = 15;
- ConfigInfo->BusInterruptVector = 15;
- ConfigInfo->InterruptMode = LevelSensitive;
-
- ConfigInfo->AccessRanges[0].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(0x0170);
- ConfigInfo->AccessRanges[0].RangeLength = 8;
- ConfigInfo->AccessRanges[0].RangeInMemory = FALSE;
-
- ConfigInfo->AccessRanges[1].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(0x0376);
- ConfigInfo->AccessRanges[1].RangeLength = 1;
- ConfigInfo->AccessRanges[1].RangeInMemory = FALSE;
-
- /* Claim bus master registers */
- if (PciConfig.ProgIf & 0x80)
- {
- DevExt->BusMasterRegisterBase =
- (PciConfig.u.type0.BaseAddresses[4] & ~0x00000003) + 8;
-
- ConfigInfo->AccessRanges[2].RangeStart =
- ScsiPortConvertUlongToPhysicalAddress(DevExt->BusMasterRegisterBase);
- ConfigInfo->AccessRanges[2].RangeLength = 8;
- ConfigInfo->AccessRanges[2].RangeInMemory = FALSE;
- }
-
- ConfigInfo->AtdiskSecondaryClaimed = TRUE;
- ChannelFound = TRUE;
+ ChannelFound = AtapiClaimHwResources(DevExt,
+ ConfigInfo,
+ PCIBus,
+ 0x170,
+ 0x374,
+ BusMasterBasePort ? BusMasterBasePort + 8 : 0,
+ 15);
*Again = FALSE;
- }
-
- /* Find attached devices */
- if (ChannelFound == TRUE)
- {
- DeviceFound = AtapiFindDevices(DevExt,
- ConfigInfo);
- }
- DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_FOUND\n");
- return(SP_RETURN_FOUND);
- }
- }
-
+ }
+ /* Find attached devices */
+ if (ChannelFound)
+ {
+ DeviceFound = AtapiFindDevices(DevExt, ConfigInfo);
+ ConfigInfo->SlotNumber = SlotNumber.u.AsULONG;
+ DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_FOUND\n");
+ return(SP_RETURN_FOUND);
+ }
+ }
+ if (FunctionNumber == 0 && !(PciConfig.HeaderType & PCI_MULTIFUNCTION))
+ {
+ break;
+ }
+ }
+ StartFunctionNumber = 0;
+ }
DPRINT("AtapiFindCompatiblePciController() returns: SP_RETURN_NOT_FOUND\n");
return(SP_RETURN_NOT_FOUND);
}
+#endif
+#ifdef ENABLE_ISA
static ULONG STDCALL
AtapiFindIsaBusController(PVOID DeviceExtension,
PVOID HwContext,
/* Both channels unclaimed: Claim primary channel */
DPRINT("Primary channel!\n");
- DevExt->CommandPortBase = 0x01F0;
- DevExt->ControlPortBase = 0x03F6;
-
- ConfigInfo->BusInterruptLevel = 14;
- ConfigInfo->BusInterruptVector = 14;
- ConfigInfo->InterruptMode = LevelSensitive;
-
- ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x01F0);
- ConfigInfo->AccessRanges[0].RangeLength = 8;
- ConfigInfo->AccessRanges[0].RangeInMemory = FALSE;
-
- ConfigInfo->AccessRanges[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x03F6);
- ConfigInfo->AccessRanges[1].RangeLength = 1;
- ConfigInfo->AccessRanges[1].RangeInMemory = FALSE;
-
- ConfigInfo->AtdiskPrimaryClaimed = TRUE;
- ChannelFound = TRUE;
- *Again = FALSE/*TRUE*/;
+ ChannelFound = AtapiClaimHwResources(DevExt,
+ ConfigInfo,
+ Isa,
+ 0x1F0,
+ 0x3F4,
+ 0,
+ 14);
+ *Again = TRUE;
}
else if (ConfigInfo->AtdiskSecondaryClaimed == FALSE)
{
/* Primary channel already claimed: claim secondary channel */
DPRINT("Secondary channel!\n");
- DevExt->CommandPortBase = 0x0170;
- DevExt->ControlPortBase = 0x0376;
-
- ConfigInfo->BusInterruptLevel = 15;
- ConfigInfo->BusInterruptVector = 15;
- ConfigInfo->InterruptMode = LevelSensitive;
-
- ConfigInfo->AccessRanges[0].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x0170);
- ConfigInfo->AccessRanges[0].RangeLength = 8;
- ConfigInfo->AccessRanges[0].RangeInMemory = FALSE;
-
- ConfigInfo->AccessRanges[1].RangeStart = ScsiPortConvertUlongToPhysicalAddress(0x0376);
- ConfigInfo->AccessRanges[1].RangeLength = 1;
- ConfigInfo->AccessRanges[1].RangeInMemory = FALSE;
-
- ConfigInfo->AtdiskSecondaryClaimed = TRUE;
- ChannelFound = TRUE;
+ ChannelFound = AtapiClaimHwResources(DevExt,
+ ConfigInfo,
+ Isa,
+ 0x170,
+ 0x374,
+ 0,
+ 15);
*Again = FALSE;
}
else
{
DeviceFound = AtapiFindDevices(DevExt,
ConfigInfo);
+ DPRINT("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n");
+ return(SP_RETURN_FOUND);
}
-
- DPRINT("AtapiFindIsaBusController() returns: SP_RETURN_FOUND\n");
- return(SP_RETURN_FOUND);
+ *Again = FALSE;
+ return SP_RETURN_NOT_FOUND;
}
+#endif
+#ifdef ENABLE_NATIVE_PCI
static ULONG STDCALL
AtapiFindNativePciController(PVOID DeviceExtension,
PVOID HwContext,
PBOOLEAN Again)
{
PATAPI_MINIPORT_EXTENSION DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
+ PCI_COMMON_CONFIG PciConfig;
+ PCI_SLOT_NUMBER SlotNumber;
+ ULONG DataSize;
+ ULONG DeviceNumber;
+ ULONG StartDeviceNumber;
+ ULONG FunctionNumber;
+ ULONG StartFunctionNumber;
+ ULONG BusMasterBasePort;
+ ULONG Count;
+ BOOLEAN ChannelFound;
DPRINT("AtapiFindNativePciController() called!\n");
+ SlotNumber.u.AsULONG = ConfigInfo->SlotNumber;
+ StartDeviceNumber = SlotNumber.u.bits.DeviceNumber;
+ StartFunctionNumber = SlotNumber.u.bits.FunctionNumber;
+ for (DeviceNumber = StartDeviceNumber; DeviceNumber < PCI_MAX_DEVICES; DeviceNumber++)
+ {
+ SlotNumber.u.bits.DeviceNumber = DeviceNumber;
+ for (FunctionNumber = StartFunctionNumber; FunctionNumber < PCI_MAX_FUNCTION; FunctionNumber++)
+ {
+ SlotNumber.u.bits.FunctionNumber = FunctionNumber;
+ DataSize = ScsiPortGetBusData(DeviceExtension,
+ PCIConfiguration,
+ ConfigInfo->SystemIoBusNumber,
+ SlotNumber.u.AsULONG,
+ &PciConfig,
+ PCI_COMMON_HDR_LENGTH);
+ if (DataSize != PCI_COMMON_HDR_LENGTH)
+ {
+ break;
+ }
+ for (Count = 0; Count < sizeof(PciNativeController)/sizeof(PCI_NATIVE_CONTROLLER); Count++)
+ {
+ if (PciConfig.VendorID == PciNativeController[Count].VendorID &&
+ PciConfig.DeviceID == PciNativeController[Count].DeviceID)
+ {
+ break;
+ }
+ }
+ if (Count < sizeof(PciNativeController)/sizeof(PCI_NATIVE_CONTROLLER))
+ {
+ /* We have found a known native pci ide controller */
+ if ((PciConfig.ProgIf & 0x80) && (PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_SPACE))
+ {
+ DPRINT("Found IDE Bus Master controller!\n");
+ BusMasterBasePort = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
+ DPRINT(" IDE Bus Master Registers at IO %lx\n", BusMasterBasePort);
+ }
+ else
+ {
+ BusMasterBasePort = 0;
+ }
+
+ DPRINT("VendorID: %04x, DeviceID: %04x\n", PciConfig.VendorID, PciConfig.DeviceID);
+ ConfigInfo->NumberOfBuses = 1;
+ ConfigInfo->MaximumNumberOfTargets = 2;
+ ConfigInfo->MaximumTransferLength = 0x10000; /* max 64Kbyte */
+
+ /* FIXME:
+ We must not store and use the last tested slot number. If there is a recall
+ to the some device and we will claim the primary channel again than the call
+ to ScsiPortGetDeviceBase in AtapiClaimHwResource will fail and we can try to
+ claim the secondary channel.
+ */
+ ChannelFound = FALSE;
+ if (LastSlotNumber.u.AsULONG != SlotNumber.u.AsULONG)
+ {
+ /* try to claim primary channel */
+ if ((PciConfig.u.type0.BaseAddresses[0] & PCI_ADDRESS_IO_SPACE) &&
+ (PciConfig.u.type0.BaseAddresses[1] & PCI_ADDRESS_IO_SPACE))
+ {
+ /* primary channel is enabled */
+ ChannelFound = AtapiClaimHwResources(DevExt,
+ ConfigInfo,
+ PCIBus,
+ PciConfig.u.type0.BaseAddresses[0] & PCI_ADDRESS_IO_ADDRESS_MASK,
+ PciConfig.u.type0.BaseAddresses[1] & PCI_ADDRESS_IO_ADDRESS_MASK,
+ BusMasterBasePort,
+ PciConfig.u.type0.InterruptLine);
+ if (ChannelFound)
+ {
+ AtapiFindDevices(DevExt, ConfigInfo);
+ *Again = TRUE;
+ ConfigInfo->SlotNumber = LastSlotNumber.u.AsULONG = SlotNumber.u.AsULONG;
+ return SP_RETURN_FOUND;
+ }
+ }
+ }
+ if (!ChannelFound)
+ {
+ /* try to claim secondary channel */
+ if ((PciConfig.u.type0.BaseAddresses[2] & PCI_ADDRESS_IO_SPACE) &&
+ (PciConfig.u.type0.BaseAddresses[3] & PCI_ADDRESS_IO_SPACE))
+ {
+ /* secondary channel is enabled */
+ ChannelFound = AtapiClaimHwResources(DevExt,
+ ConfigInfo,
+ PCIBus,
+ PciConfig.u.type0.BaseAddresses[2] & PCI_ADDRESS_IO_ADDRESS_MASK,
+ PciConfig.u.type0.BaseAddresses[3] & PCI_ADDRESS_IO_ADDRESS_MASK,
+ BusMasterBasePort ? BusMasterBasePort + 8 : 0,
+ PciConfig.u.type0.InterruptLine);
+ if (ChannelFound)
+ {
+ AtapiFindDevices(DevExt, ConfigInfo);
+ *Again = FALSE;
+ LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
+ return SP_RETURN_FOUND;
+ }
+ }
+ }
+ }
+ }
+ StartFunctionNumber = 0;
+ }
*Again = FALSE;
-
+ LastSlotNumber.u.AsULONG = 0xFFFFFFFF;
DPRINT("AtapiFindNativePciController() done!\n");
return(SP_RETURN_NOT_FOUND);
}
+#endif
static BOOLEAN STDCALL
BOOLEAN IsAtapi;
ULONG Retries;
PUCHAR TargetAddress;
- ULONG SectorSize;
ULONG TransferSize;
DPRINT("AtapiInterrupt() called!\n");
DevExt = (PATAPI_MINIPORT_EXTENSION)DeviceExtension;
+
+ CommandPortBase = DevExt->CommandPortBase;
+ ControlPortBase = DevExt->ControlPortBase;
+
if (DevExt->ExpectingInterrupt == FALSE)
{
- DPRINT("AtapiInterrupt(): Unexpected interrupt\n");
+ DeviceStatus = IDEReadStatus(CommandPortBase);
+ DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase);
return(FALSE);
}
+ /* check if it was our irq */
+ if ((DeviceStatus = IDEReadAltStatus(ControlPortBase)) & IDE_SR_BUSY)
+ {
+ ScsiPortStallExecution(1);
+ if ((DeviceStatus = IDEReadAltStatus(ControlPortBase) & IDE_SR_BUSY))
+ {
+ DPRINT("AtapiInterrupt(): Unexpected interrupt (port=%x)\n", CommandPortBase);
+ return(FALSE);
+ }
+ }
+
Srb = DevExt->CurrentSrb;
DPRINT("Srb: %p\n", Srb);
- CommandPortBase = DevExt->CommandPortBase;
- ControlPortBase = DevExt->ControlPortBase;
DPRINT("CommandPortBase: %lx ControlPortBase: %lx\n", CommandPortBase, ControlPortBase);
IsAtapi = DevExt->DeviceAtapi[Srb->TargetId];
DeviceStatus = IDEReadStatus(CommandPortBase);
DPRINT("DeviceStatus: %x\n", DeviceStatus);
- if (DeviceStatus & IDE_SR_BUSY)
- {
- /* Wait for BUSY to drop */
- for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
- {
- DeviceStatus = IDEReadStatus(CommandPortBase);
- if (!(DeviceStatus & IDE_SR_BUSY))
- {
- break;
- }
- ScsiPortStallExecution(10);
- }
- if (Retries >= IDE_MAX_BUSY_RETRIES)
- {
- DPRINT1("Drive is BUSY for too long\n");
- /* FIXME: handle timeout */
- }
- }
-
if ((DeviceStatus & IDE_SR_ERR) &&
(Srb->Cdb[0] != SCSIOP_REQUEST_SENSE))
{
DPRINT("Read data\n");
/* Update controller/device state variables */
- TargetAddress = Srb->DataBuffer;
+ TargetAddress = DevExt->DataBuffer;
if (IsAtapi)
{
}
else
{
- TransferSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector;
+ TransferSize = DevExt->TransferSize[Srb->TargetId];
}
DPRINT("TransferLength: %lu\n", Srb->DataTransferLength);
DPRINT("TransferSize: %lu\n", TransferSize);
- if (Srb->DataTransferLength <= TransferSize)
+ if (DevExt->DataTransferLength <= TransferSize)
{
- Srb->DataTransferLength = 0;
+ if (!IsAtapi)
+ {
+ TransferSize = DevExt->DataTransferLength;
+ }
+ DevExt->DataTransferLength = 0;
IsLastBlock = TRUE;
}
else
{
- Srb->DataTransferLength -= TransferSize;
+ DevExt->DataTransferLength -= TransferSize;
IsLastBlock = FALSE;
}
- Srb->DataBuffer += TransferSize;
+ DevExt->DataBuffer += TransferSize;
DPRINT("IsLastBlock == %s\n", (IsLastBlock) ? "TRUE" : "FALSE");
/* Wait for DRQ assertion */
}
/* Copy the block of data */
- IDEReadBlock(CommandPortBase,
- TargetAddress,
- TransferSize);
-
+ if (DevExt->DWordIo[Srb->TargetId])
+ {
+ IDEReadBlock32(CommandPortBase,
+ TargetAddress,
+ TransferSize);
+ }
+ else
+ {
+ IDEReadBlock(CommandPortBase,
+ TargetAddress,
+ TransferSize);
+ }
/* check DRQ */
if (IsLastBlock)
{
}
/* Check for data overrun */
- if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
+ while (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
{
- /* FIXME: Handle error! */
- DPRINT1("AtapiInterrupt(): data overrun error!");
+ DPRINT1("AtapiInterrupt(): reading overrun data!\n");
+ IDEReadWord(CommandPortBase);
}
}
{
DPRINT("Write data\n");
- if (Srb->DataTransferLength == 0)
+ if (DevExt->DataTransferLength == 0)
{
-
- for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES &&
- (IDEReadStatus(CommandPortBase) & IDE_SR_BUSY);
- Retries++)
- {
- KeStallExecutionProcessor(10);
- }
-
/* Check for data overrun */
- if (IDEReadStatus(CommandPortBase) & IDE_SR_DRQ)
+ if (DeviceStatus & IDE_SR_DRQ)
{
/* FIXME: Handle error! */
- DPRINT1("AtapiInterrupt(): data overrun error!");
+ /* This can occure if the irq is shared with an other and if the
+ ide controller has a write buffer. We have write the last sectors
+ and the other device has a irq before ours. The isr is called but
+ we haven't a interrupt. The controller writes the sector buffer
+ and the status register shows DRQ because the write is not ended. */
+ DPRINT("AtapiInterrupt(): data overrun error!\n");
}
-
- DevExt->ExpectingInterrupt = FALSE;
IsLastBlock = TRUE;
}
else
{
- /* Update SRB data */
- SectorSize = DevExt->DeviceParams[Srb->TargetId].BytesPerSector;
-
- TargetAddress = Srb->DataBuffer;
- Srb->DataBuffer += SectorSize;
- Srb->DataTransferLength -= SectorSize;
+ /* Update DevExt data */
+ TransferSize = DevExt->TransferSize[Srb->TargetId];
+ if (DevExt->DataTransferLength < TransferSize)
+ {
+ TransferSize = DevExt->DataTransferLength;
+ }
+
+ TargetAddress = DevExt->DataBuffer;
+ DevExt->DataBuffer += TransferSize;
+ DevExt->DataTransferLength -= TransferSize;
/* Write the sector */
- IDEWriteBlock(CommandPortBase,
- TargetAddress,
- SectorSize);
+ if (DevExt->DWordIo[Srb->TargetId])
+ {
+ IDEWriteBlock32(CommandPortBase,
+ TargetAddress,
+ TransferSize);
+ }
+ else
+ {
+ IDEWriteBlock(CommandPortBase,
+ TargetAddress,
+ TransferSize);
+ }
}
Srb->SrbStatus = SRB_STATUS_SUCCESS;
return(TRUE);
}
-
-
-
-
-
// ---------------------------------------------------- Discardable statics
IDE_DC_nIEN);
ScsiPortStallExecution(500);
+ /* Check if a device is attached to the interface */
+ IDEWriteCylinderHigh(CommandPortBase, 0xaa);
+ IDEWriteCylinderLow(CommandPortBase, 0x55);
+
+ High = IDEReadCylinderHigh(CommandPortBase);
+ Low = IDEReadCylinderLow(CommandPortBase);
+
IDEWriteCylinderHigh(CommandPortBase, 0);
IDEWriteCylinderLow(CommandPortBase, 0);
+
+ if (Low != 0x55 || High != 0xaa)
+ {
+ DPRINT("No Drive found. UnitNumber %d CommandPortBase %x\n", UnitNumber, CommandPortBase);
+ continue;
+ }
+
IDEWriteCommand(CommandPortBase, IDE_CMD_RESET);
for (Retries = 0; Retries < 20000; Retries++)
DPRINT(" ATAPI drive found!\n");
DeviceExtension->DevicePresent[UnitNumber] = TRUE;
DeviceExtension->DeviceAtapi[UnitNumber] = TRUE;
+ DeviceExtension->TransferSize[UnitNumber] = DeviceExtension->DeviceParams[UnitNumber].BytesPerSector;
+ DeviceExtension->MultiSectorCommand[UnitNumber] = FALSE;
+ DeviceExtension->DWordIo[UnitNumber] = FALSE;
DeviceFound = TRUE;
}
else
DPRINT(" IDE drive found!\n");
DeviceExtension->DevicePresent[UnitNumber] = TRUE;
DeviceExtension->DeviceAtapi[UnitNumber] = FALSE;
+ DeviceExtension->TransferSize[UnitNumber] = DeviceExtension->DeviceParams[UnitNumber].BytesPerSector;
+ if ((DeviceExtension->DeviceParams[UnitNumber].RWMultImplemented & 0x8000) &&
+ (DeviceExtension->DeviceParams[UnitNumber].RWMultImplemented & 0xff) &&
+ (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0x100) &&
+ (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0xff))
+ {
+ DeviceExtension->TransferSize[UnitNumber] *= (DeviceExtension->DeviceParams[UnitNumber].RWMultCurrent & 0xff);
+ DeviceExtension->MultiSectorCommand[UnitNumber] = TRUE;
+ }
+ else
+ {
+ DeviceExtension->MultiSectorCommand[UnitNumber] = FALSE;
+ }
+ DeviceExtension->DWordIo[UnitNumber] = DeviceExtension->DeviceParams[UnitNumber].DWordIo ? TRUE : FALSE;
DeviceFound = TRUE;
}
else
}
}
+ /* Reset pending interrupts */
+ IDEReadStatus(CommandPortBase);
+ /* Reenable interrupts */
+ IDEWriteDriveControl(ControlPortBase, 0);
+ ScsiPortStallExecution(500);
+ /* Return with drive 0 selected */
+ IDEWriteDriveHead(CommandPortBase, IDE_DH_FIXED);
+ ScsiPortStallExecution(500);
DPRINT("AtapiFindDrives() done (DeviceFound %s)\n", (DeviceFound) ? "TRUE" : "FALSE");
DrvParms->ECCByteCnt,
DrvParms->FirmwareRev);
DPRINT("Model:[%.40s]\n", DrvParms->ModelNumber);
- DPRINT("RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n",
- (DrvParms->RWMultImplemented) & 0xff,
+ DPRINT("RWMultMax?:%04x RWMult?:%02x LBA:%d DMA:%d MinPIO:%d ns MinDMA:%d ns\n",
+ (DrvParms->RWMultImplemented),
+ (DrvParms->RWMultCurrent) & 0xff,
(DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED) ? 1 : 0,
(DrvParms->Capabilities & IDE_DRID_DMA_SUPPORTED) ? 1 : 0,
DrvParms->MinPIOTransTime,
DrvParms->TMSectorCountLo,
(ULONG)((DrvParms->TMSectorCountHi << 16) + DrvParms->TMSectorCountLo));
- DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector);
- if (DrvParms->BytesPerSector == 0)
+ if (! Atapi && 0 != (DrvParms->Capabilities & IDE_DRID_LBA_SUPPORTED))
{
+ /* LBA ATA drives always have a sector size of 512 */
DrvParms->BytesPerSector = 512;
}
else
{
- for (i = 15; i >= 0; i--)
- {
- if (DrvParms->BytesPerSector & (1 << i))
- {
- DrvParms->BytesPerSector = 1 << i;
- break;
- }
- }
+ DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector);
+ if (DrvParms->BytesPerSector == 0)
+ {
+ DrvParms->BytesPerSector = 512;
+ }
+ else
+ {
+ for (i = 15; i >= 0; i--)
+ {
+ if (DrvParms->BytesPerSector & (1 << i))
+ {
+ DrvParms->BytesPerSector = 1 << i;
+ break;
+ }
+ }
+ }
}
DPRINT("BytesPerSector %d\n", DrvParms->BytesPerSector);
ULONG RetryCount;
BOOLEAN Junk = FALSE;
UCHAR Status;
- UCHAR Control;
//#if 0
/* Wait for BUSY to clear */
ScsiPortStallExecution(500);
/* Disable interrupts */
- Control = IDEReadAltStatus(ControlPort);
- IDEWriteDriveControl(ControlPort, Control | IDE_DC_nIEN);
+ IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
ScsiPortStallExecution(500);
#if 0
{
if (Status & IDE_SR_ERR)
{
- IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN);
+ IDEWriteDriveControl(ControlPort, 0);
+ ScsiPortStallExecution(50);
+ IDEReadStatus(CommandPort);
+
return(IDE_ER_ABRT);
}
if (Status & IDE_SR_DRQ)
}
else
{
- IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN);
+ IDEWriteDriveControl(ControlPort, 0);
+ ScsiPortStallExecution(50);
+ IDEReadStatus(CommandPort);
+
return(IDE_ER_ABRT);
}
}
/* timed out */
if (RetryCount >= IDE_MAX_POLL_RETRIES)
{
- IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN);
+ IDEWriteDriveControl(ControlPort, 0);
+ ScsiPortStallExecution(50);
+ IDEReadStatus(CommandPort);
+
return(IDE_ER_ABRT);
}
{
if (Status & IDE_SR_ERR)
{
- IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN);
+ IDEWriteDriveControl(ControlPort, 0);
+ ScsiPortStallExecution(50);
+ IDEReadStatus(CommandPort);
+
return(IDE_ER_ABRT);
}
if (Status & IDE_SR_DRQ)
DPRINT("Read %lu sectors of junk!\n",
SectorCount - SectorCnt);
}
- IDEWriteDriveControl(ControlPort, Control & ~IDE_DC_nIEN);
+ IDEWriteDriveControl(ControlPort, 0);
+ ScsiPortStallExecution(50);
+ IDEReadStatus(CommandPort);
+
return(0);
}
}
Srb));
/* Set pointer to data buffer. */
- DeviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
+ DeviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
+ DeviceExtension->DataTransferLength = Srb->DataTransferLength;
DeviceExtension->CurrentSrb = Srb;
/* Wait for BUSY to clear */
}
#endif
- if (Srb->DataTransferLength < 0x10000)
+ if (DeviceExtension->DataTransferLength < 0x10000)
{
- ByteCountLow = (UCHAR)(Srb->DataTransferLength & 0xFF);
- ByteCountHigh = (UCHAR)(Srb->DataTransferLength >> 8);
+ ByteCountLow = (UCHAR)(DeviceExtension->DataTransferLength & 0xFF);
+ ByteCountHigh = (UCHAR)(DeviceExtension->DataTransferLength >> 8);
}
else
{
IDEWriteCylinderLow(DeviceExtension->CommandPortBase, ByteCountLow);
/* Issue command to drive */
- IDEWriteCommand(DeviceExtension->CommandPortBase, 0xA0); /* Packet command */
+ IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_PACKET);
/* Wait for DRQ to assert */
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
Srb);
break;
+ case SCSIOP_SYNCHRONIZE_CACHE:
+ SrbStatus = AtapiFlushCache(DeviceExtension,
+ Srb);
+ break;
+
case SCSIOP_MODE_SENSE:
case SCSIOP_TEST_UNIT_READY:
case SCSIOP_VERIFY:
if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)
{
- Command = IDE_CMD_READ;
+ Command = DeviceExtension->MultiSectorCommand[Srb->TargetId] ? IDE_CMD_READ_MULTIPLE : IDE_CMD_READ;
}
else
{
- Command = IDE_CMD_WRITE;
+ Command = DeviceExtension->MultiSectorCommand[Srb->TargetId] ? IDE_CMD_WRITE_MULTIPLE : IDE_CMD_WRITE;
}
if (DrvHead & IDE_DH_LBA)
}
/* Set pointer to data buffer. */
- DeviceExtension->DataBuffer = (PUSHORT)Srb->DataBuffer;
+ DeviceExtension->DataBuffer = (PUCHAR)Srb->DataBuffer;
+ DeviceExtension->DataTransferLength = Srb->DataTransferLength;
DeviceExtension->CurrentSrb = Srb;
- DeviceExtension->ExpectingInterrupt = TRUE;
-
-
/* wait for BUSY to clear */
for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
{
DPRINT ("Drive is BUSY for too long\n");
return(SRB_STATUS_BUSY);
-#if 0
- if (++ControllerExtension->Retries > IDE_MAX_CMD_RETRIES)
- {
- DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
- Irp = ControllerExtension->CurrentIrp;
- Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
- Irp->IoStatus.Information = 0;
-
- return FALSE;
- }
- else
- {
- DPRINT ("Beginning drive reset sequence\n");
- IDEBeginControllerReset(ControllerExtension);
-
- return TRUE;
- }
-#endif
}
/* Select the desired drive */
{
DPRINT("Drive is BUSY for too long after drive select\n");
return(SRB_STATUS_BUSY);
-#if 0
- if (ControllerExtension->Retries++ > IDE_MAX_CMD_RETRIES)
- {
- DbgPrint ("Max Retries on Drive reset reached, returning failure\n");
- Irp = ControllerExtension->CurrentIrp;
- Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
- Irp->IoStatus.Information = 0;
-
- return FALSE;
- }
- else
- {
- DPRINT("Beginning drive reset sequence\n");
- IDEBeginControllerReset(ControllerExtension);
-
- return TRUE;
- }
-#endif
}
#endif
- /* Indicate expecting an interrupt. */
- DeviceExtension->ExpectingInterrupt = TRUE;
-
/* Setup command parameters */
IDEWritePrecomp(DeviceExtension->CommandPortBase, 0);
IDEWriteSectorCount(DeviceExtension->CommandPortBase, SectorCount);
IDEWriteCommand(DeviceExtension->CommandPortBase, Command);
/* Write data block */
- if (Command == IDE_CMD_WRITE)
+ if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)
{
PUCHAR TargetAddress;
- ULONG SectorSize;
+ ULONG TransferSize;
/* Wait for controller ready */
for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
}
KeStallExecutionProcessor(10);
}
- if (Retries >= IDE_MAX_BUSY_RETRIES)
+ if (Retries >= IDE_MAX_WRITE_RETRIES)
{
- DPRINT("Drive is BUSY for too long after sending write command\n");
+ DPRINT1("Drive is BUSY for too long after sending write command\n");
return(SRB_STATUS_BUSY);
-#if 0
- if (DeviceExtension->Retries++ > IDE_MAX_CMD_RETRIES)
- {
- Irp = ControllerExtension->CurrentIrp;
- Irp->IoStatus.Status = STATUS_DISK_OPERATION_FAILED;
- Irp->IoStatus.Information = 0;
-
- return FALSE;
- }
- else
- {
- IDEBeginControllerReset(ControllerExtension);
-
- return TRUE;
- }
-#endif
}
- /* Update SRB data */
- SectorSize = DeviceExtension->DeviceParams[Srb->TargetId].BytesPerSector;
- TargetAddress = Srb->DataBuffer;
- Srb->DataBuffer += SectorSize;
- Srb->DataTransferLength -= SectorSize;
+ /* Update DeviceExtension data */
+ TransferSize = DeviceExtension->TransferSize[Srb->TargetId];
+ if (DeviceExtension->DataTransferLength < TransferSize)
+ {
+ TransferSize = DeviceExtension->DataTransferLength;
+ }
+
+ TargetAddress = DeviceExtension->DataBuffer;
+ DeviceExtension->DataBuffer += TransferSize;
+ DeviceExtension->DataTransferLength -= TransferSize;
/* Write data block */
- IDEWriteBlock(DeviceExtension->CommandPortBase,
- TargetAddress,
- SectorSize);
+ if (DeviceExtension->DWordIo[Srb->TargetId])
+ {
+ IDEWriteBlock32(DeviceExtension->CommandPortBase,
+ TargetAddress,
+ TransferSize);
+ }
+ else
+ {
+ IDEWriteBlock(DeviceExtension->CommandPortBase,
+ TargetAddress,
+ TransferSize);
+ }
}
-
+ /* Indicate expecting an interrupt. */
+ DeviceExtension->ExpectingInterrupt = TRUE;
DPRINT("AtapiReadWrite() done!\n");
}
+static ULONG
+AtapiFlushCache(PATAPI_MINIPORT_EXTENSION DeviceExtension,
+ PSCSI_REQUEST_BLOCK Srb)
+{
+ ULONG Retries;
+ UCHAR Status;
+
+ DPRINT1("AtapiFlushCache() called!\n");
+
+ if (Srb->PathId != 0)
+ {
+ Srb->SrbStatus = SRB_STATUS_INVALID_PATH_ID;
+ return(SRB_STATUS_INVALID_PATH_ID);
+ }
+
+ if (Srb->TargetId > 1)
+ {
+ Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
+ return(SRB_STATUS_INVALID_TARGET_ID);
+ }
+
+ if (Srb->Lun != 0)
+ {
+ Srb->SrbStatus = SRB_STATUS_INVALID_LUN;
+ return(SRB_STATUS_INVALID_LUN);
+ }
+
+ if (DeviceExtension->DevicePresent[Srb->TargetId] == FALSE)
+ {
+ Srb->SrbStatus = SRB_STATUS_NO_DEVICE;
+ return(SRB_STATUS_NO_DEVICE);
+ }
+
+ DPRINT1("SCSIOP_SYNCRONIZE_CACHE: TargetId: %lu\n",
+ Srb->TargetId);
+
+ /* Wait for BUSY to clear */
+ for (Retries = 0; Retries < IDE_MAX_BUSY_RETRIES; Retries++)
+ {
+ Status = IDEReadStatus(DeviceExtension->CommandPortBase);
+ if (!(Status & IDE_SR_BUSY))
+ {
+ break;
+ }
+ ScsiPortStallExecution(10);
+ }
+ DPRINT1("Status=%02x\n", Status);
+ DPRINT1("Waited %ld usecs for busy to clear\n", Retries * 10);
+ if (Retries >= IDE_MAX_BUSY_RETRIES)
+ {
+ DPRINT1("Drive is BUSY for too long\n");
+ return(SRB_STATUS_BUSY);
+ }
+
+ /* Select the desired drive */
+ IDEWriteDriveHead(DeviceExtension->CommandPortBase,
+ IDE_DH_FIXED | (Srb->TargetId ? IDE_DH_DRV1 : 0));
+ ScsiPortStallExecution(10);
+
+ /* Issue command to drive */
+ IDEWriteCommand(DeviceExtension->CommandPortBase, IDE_CMD_FLUSH_CACHE);
+
+ /* Wait for controller ready */
+ for (Retries = 0; Retries < IDE_MAX_WRITE_RETRIES; Retries++)
+ {
+ BYTE Status = IDEReadStatus(DeviceExtension->CommandPortBase);
+ if (!(Status & IDE_SR_BUSY) || (Status & IDE_SR_ERR))
+ {
+ break;
+ }
+ KeStallExecutionProcessor(10);
+ }
+ if (Retries >= IDE_MAX_WRITE_RETRIES)
+ {
+ DPRINT1("Drive is BUSY for too long after sending write command\n");
+ return(SRB_STATUS_BUSY);
+ }
+
+ /* Indicate expecting an interrupt. */
+ DeviceExtension->ExpectingInterrupt = TRUE;
+
+ DPRINT1("AtapiFlushCache() done!\n");
+
+ /* Wait for interrupt. */
+ return(SRB_STATUS_PENDING);
+}
+
+
static UCHAR
AtapiErrorToScsi(PVOID DeviceExtension,
PSCSI_REQUEST_BLOCK Srb)