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.
443 lines
12 KiB
443 lines
12 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1999 - 1999
|
|
|
|
Module Name:
|
|
|
|
init.c
|
|
|
|
Abstract:
|
|
|
|
Generic PCI IDE mini driver
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "pciide.h"
|
|
|
|
//
|
|
// Driver Entry Point
|
|
//
|
|
NTSTATUS
|
|
DriverEntry(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PUNICODE_STRING RegistryPath
|
|
)
|
|
{
|
|
//
|
|
// call system pci ide driver (pciidex)
|
|
// for initializeation
|
|
//
|
|
return PciIdeXInitialize (
|
|
DriverObject,
|
|
RegistryPath,
|
|
GenericIdeGetControllerProperties,
|
|
sizeof (DEVICE_EXTENSION)
|
|
);
|
|
}
|
|
|
|
|
|
//
|
|
// Called on every I/O. Returns 1 if DMA is allowed.
|
|
// Returns 0 if DMA is not allowed.
|
|
//
|
|
ULONG
|
|
GenericIdeUseDma(
|
|
IN PVOID DeviceExtension,
|
|
IN PVOID cdbcmd,
|
|
IN UCHAR slave)
|
|
/**++
|
|
* Arguments : DeviceExtension
|
|
Cdb
|
|
Slave =1, if slave
|
|
=0, if master
|
|
--**/
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceExtension;
|
|
PUCHAR cdb= cdbcmd;
|
|
|
|
return 1;
|
|
}
|
|
|
|
//
|
|
// Query controller properties
|
|
//
|
|
NTSTATUS
|
|
GenericIdeGetControllerProperties (
|
|
IN PVOID DeviceExtension,
|
|
IN PIDE_CONTROLLER_PROPERTIES ControllerProperties
|
|
)
|
|
{
|
|
PDEVICE_EXTENSION deviceExtension = DeviceExtension;
|
|
NTSTATUS status;
|
|
ULONG i;
|
|
ULONG j;
|
|
ULONG xferMode;
|
|
|
|
//
|
|
// make sure we are in sync
|
|
//
|
|
if (ControllerProperties->Size != sizeof (IDE_CONTROLLER_PROPERTIES)) {
|
|
|
|
return STATUS_REVISION_MISMATCH;
|
|
}
|
|
|
|
//
|
|
// see what kind of PCI IDE controller we have
|
|
//
|
|
status = PciIdeXGetBusData (
|
|
deviceExtension,
|
|
&deviceExtension->pciConfigData,
|
|
0,
|
|
sizeof (PCIIDE_CONFIG_HEADER)
|
|
);
|
|
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
return status;
|
|
}
|
|
|
|
//
|
|
// assume we support all DMA mode if PCI master bit is set
|
|
//
|
|
xferMode = PIO_SUPPORT;
|
|
if ((deviceExtension->pciConfigData.MasterIde) &&
|
|
(deviceExtension->pciConfigData.Command.b.MasterEnable)) {
|
|
|
|
xferMode |= SWDMA_SUPPORT | MWDMA_SUPPORT | UDMA_SUPPORT;
|
|
}
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
|
|
//
|
|
// Run PIO by default for the Sis Chipset
|
|
//
|
|
if ((deviceExtension->pciConfigData.VendorID == 0x1039) &&
|
|
(deviceExtension->pciConfigData.DeviceID == 0x5513)) {
|
|
ControllerProperties->DefaultPIO = 1;
|
|
}
|
|
|
|
//
|
|
// Run PIO by default for the Rcc Chipset
|
|
//
|
|
if ((deviceExtension->pciConfigData.VendorID == 0x1166) &&
|
|
(deviceExtension->pciConfigData.DeviceID == 0x0211)) {
|
|
ControllerProperties->DefaultPIO = 1;
|
|
}
|
|
|
|
|
|
//
|
|
// continuous status register polling causes some ALI
|
|
// controller to corrupt data if the controller internal
|
|
// FIFO is enabled
|
|
//
|
|
// to play safe, we will always disable the FIFO
|
|
// see the ALi IDE controller programming spec for details
|
|
//
|
|
if ((deviceExtension->pciConfigData.VendorID == 0x10b9) &&
|
|
(deviceExtension->pciConfigData.DeviceID == 0x5229)) {
|
|
|
|
USHORT pciData;
|
|
USHORT pciDataMask;
|
|
|
|
pciData = 0;
|
|
pciDataMask = 0xcccc;
|
|
status = PciIdeXSetBusData(
|
|
DeviceExtension,
|
|
&pciData,
|
|
&pciDataMask,
|
|
0x54,
|
|
0x2);
|
|
if (!NT_SUCCESS(status)) {
|
|
|
|
return status;
|
|
}
|
|
}
|
|
|
|
//
|
|
// ALi IDE controllers have lots of busmaster problems
|
|
// some versions of them can't do busmaster with ATAPI devices
|
|
// and some other versions of them return bogus busmaster status values
|
|
// (the busmaster active bit doesn't get cleared when it should be
|
|
// during an end of busmaster interrupt)
|
|
//
|
|
if ((deviceExtension->pciConfigData.VendorID == 0x10b9) &&
|
|
(deviceExtension->pciConfigData.DeviceID == 0x5229) &&
|
|
((deviceExtension->pciConfigData.RevisionID == 0x20) ||
|
|
(deviceExtension->pciConfigData.RevisionID == 0xc1))) {
|
|
|
|
PciIdeXDebugPrint ((0, "pciide: overcome the sticky BM active bit problem in ALi controller\n"));
|
|
|
|
ControllerProperties->IgnoreActiveBitForAtaDevice = TRUE;
|
|
}
|
|
|
|
if ((deviceExtension->pciConfigData.VendorID == 0x0e11) &&
|
|
(deviceExtension->pciConfigData.DeviceID == 0xae33) &&
|
|
(deviceExtension->pciConfigData.Chan0OpMode ||
|
|
deviceExtension->pciConfigData.Chan1OpMode)) {
|
|
|
|
PciIdeXDebugPrint ((0, "pciide: overcome the bogus busmaster interrupt in CPQ controller\n"));
|
|
|
|
ControllerProperties->AlwaysClearBusMasterInterrupt = TRUE;
|
|
}
|
|
|
|
// @@END_DDKSPLIT
|
|
|
|
//
|
|
// fill in the controller properties
|
|
//
|
|
for (i=0; i< MAX_IDE_CHANNEL; i++) {
|
|
|
|
for (j=0; j< MAX_IDE_DEVICE; j++) {
|
|
|
|
ControllerProperties->SupportedTransferMode[i][j] =
|
|
deviceExtension->SupportedTransferMode[i][j] = xferMode;
|
|
}
|
|
}
|
|
|
|
ControllerProperties->PciIdeChannelEnabled = GenericIdeChannelEnabled;
|
|
ControllerProperties->PciIdeSyncAccessRequired = GenericIdeSyncAccessRequired;
|
|
ControllerProperties->PciIdeTransferModeSelect = NULL;
|
|
ControllerProperties->PciIdeUdmaModesSupported = GenericIdeUdmaModesSupported;
|
|
ControllerProperties->PciIdeUseDma = GenericIdeUseDma;
|
|
ControllerProperties->AlignmentRequirement=1;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
IDE_CHANNEL_STATE
|
|
GenericIdeChannelEnabled (
|
|
IN PDEVICE_EXTENSION DeviceExtension,
|
|
IN ULONG Channel
|
|
)
|
|
{
|
|
// @@BEGIN_DDKSPLIT
|
|
NTSTATUS status;
|
|
PCI_COMMON_CONFIG pciHeader;
|
|
ULONG pciDataByte;
|
|
UCHAR maskByte = 0;
|
|
|
|
status = PciIdeXGetBusData (
|
|
DeviceExtension,
|
|
&pciHeader,
|
|
0,
|
|
sizeof (pciHeader)
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
if ((pciHeader.VendorID == 0x0e11) &&
|
|
(pciHeader.DeviceID == 0xae33)) {
|
|
|
|
//
|
|
// Compaq
|
|
//
|
|
status = PciIdeXGetBusData (
|
|
DeviceExtension,
|
|
&pciDataByte,
|
|
0x80,
|
|
sizeof (pciDataByte)
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
if (pciDataByte & (1 << Channel)) {
|
|
|
|
return ChannelEnabled;
|
|
} else {
|
|
|
|
return ChannelDisabled;
|
|
}
|
|
}
|
|
|
|
} else if ((pciHeader.VendorID == 0x1095) &&
|
|
((pciHeader.DeviceID == 0x0646) || (pciHeader.DeviceID == 0x0643))) {
|
|
|
|
//
|
|
// CMD
|
|
//
|
|
status = PciIdeXGetBusData (
|
|
DeviceExtension,
|
|
&pciDataByte,
|
|
0x51,
|
|
sizeof (pciDataByte)
|
|
);
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
if (pciHeader.RevisionID < 0x3) {
|
|
|
|
//
|
|
// early revision doesn't have a
|
|
// bit to enable/disable primary
|
|
// channel since it is always enabled
|
|
|
|
// newer version does have a bit defined
|
|
// for this purpose. to make the check
|
|
// easier later. we will set primary enable bit
|
|
// for the early revision
|
|
pciDataByte |= 0x4;
|
|
}
|
|
|
|
if (Channel == 0) {
|
|
|
|
maskByte = 0x4;
|
|
|
|
} else {
|
|
|
|
maskByte = 0x8;
|
|
}
|
|
|
|
if (pciDataByte & maskByte) {
|
|
return ChannelEnabled;
|
|
} else {
|
|
return ChannelDisabled;
|
|
}
|
|
}
|
|
} else if ((pciHeader.VendorID == 0x1039) &&
|
|
(pciHeader.DeviceID == 0x5513)) {
|
|
|
|
//
|
|
// SiS
|
|
//
|
|
status = PciIdeXGetBusData (
|
|
DeviceExtension,
|
|
&pciDataByte,
|
|
0x4a,
|
|
sizeof (pciDataByte)
|
|
);
|
|
if (Channel == 0) {
|
|
maskByte = 0x2;
|
|
} else {
|
|
maskByte = 0x4;
|
|
}
|
|
|
|
if (pciDataByte & maskByte) {
|
|
return ChannelEnabled;
|
|
} else {
|
|
return ChannelDisabled;
|
|
}
|
|
} else if ((pciHeader.VendorID == 0x110A) &&
|
|
(pciHeader.DeviceID == 0x0002)) {
|
|
//
|
|
// Siemens
|
|
//
|
|
ULONG configOffset = (Channel == 0)?0x41:0x49;
|
|
|
|
status = PciIdeXGetBusData (
|
|
DeviceExtension,
|
|
&pciDataByte,
|
|
configOffset,
|
|
sizeof (pciDataByte)
|
|
);
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
maskByte = 0x08;
|
|
|
|
if (pciDataByte & maskByte) {
|
|
|
|
return ChannelEnabled;
|
|
|
|
} else {
|
|
|
|
return ChannelDisabled;
|
|
|
|
}
|
|
}
|
|
} else if ((pciHeader.VendorID == 0x1106) &&
|
|
(pciHeader.DeviceID == 0x0571)) {
|
|
//
|
|
// VIA
|
|
//
|
|
status = PciIdeXGetBusData (
|
|
DeviceExtension,
|
|
&pciDataByte,
|
|
0x40,
|
|
sizeof (pciDataByte)
|
|
);
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
maskByte = (Channel == 0)? 0x02:0x01;
|
|
|
|
if (pciDataByte & maskByte) {
|
|
|
|
return ChannelEnabled;
|
|
|
|
} else {
|
|
|
|
return ChannelDisabled;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// @@END_DDKSPLIT
|
|
//
|
|
// Can't tell if a channel is enabled or not.
|
|
//
|
|
return ChannelStateUnknown;
|
|
}
|
|
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
VENDOR_ID_DEVICE_ID SingleFifoController[] = {
|
|
{0x1095, 0x0640}, // CMD 640
|
|
{0x1039, 0x0601} // SiS ????
|
|
};
|
|
#define NUMBER_OF_SINGLE_FIFO_CONTROLLER (sizeof(SingleFifoController) / sizeof(VENDOR_ID_DEVICE_ID))
|
|
// @@END_DDKSPLIT
|
|
|
|
BOOLEAN
|
|
GenericIdeSyncAccessRequired (
|
|
IN PDEVICE_EXTENSION DeviceExtension
|
|
)
|
|
{
|
|
ULONG i;
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
for (i=0; i<NUMBER_OF_SINGLE_FIFO_CONTROLLER; i++) {
|
|
|
|
if ((DeviceExtension->pciConfigData.VendorID == SingleFifoController[i].VendorId) &&
|
|
(DeviceExtension->pciConfigData.DeviceID == SingleFifoController[i].DeviceId)) {
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
// @@END_DDKSPLIT
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
GenericIdeUdmaModesSupported (
|
|
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;
|
|
}
|
|
|
|
|
|
|