Add pciidex (controller driver) and pciide (miniport driver). They enumerate channels...
authorHervé Poussineau <hpoussin@reactos.org>
Thu, 20 Oct 2005 19:33:16 +0000 (19:33 +0000)
committerHervé Poussineau <hpoussin@reactos.org>
Thu, 20 Oct 2005 19:33:16 +0000 (19:33 +0000)
svn path=/trunk/; revision=18644

18 files changed:
reactos/bootdata/packages/reactos.dff
reactos/drivers/storage/directory.xml
reactos/drivers/storage/pciide/pciide.c [new file with mode: 0644]
reactos/drivers/storage/pciide/pciide.h [new file with mode: 0644]
reactos/drivers/storage/pciide/pciide.rc [new file with mode: 0644]
reactos/drivers/storage/pciide/pciide.xml [new file with mode: 0644]
reactos/drivers/storage/pciidex/fdo.c [new file with mode: 0644]
reactos/drivers/storage/pciidex/miniport.c [new file with mode: 0644]
reactos/drivers/storage/pciidex/misc.c [new file with mode: 0644]
reactos/drivers/storage/pciidex/pciidex.c [new file with mode: 0644]
reactos/drivers/storage/pciidex/pciidex.def [new file with mode: 0644]
reactos/drivers/storage/pciidex/pciidex.h [new file with mode: 0644]
reactos/drivers/storage/pciidex/pciidex.rc [new file with mode: 0644]
reactos/drivers/storage/pciidex/pciidex.xml [new file with mode: 0644]
reactos/drivers/storage/pciidex/pdo.c [new file with mode: 0644]
reactos/media/inf/hdc.inf [new file with mode: 0644]
reactos/media/inf/syssetup.inf
reactos/w32api/include/ddk/ide.h [new file with mode: 0644]

index 88efae6..7473b93 100755 (executable)
@@ -293,7 +293,7 @@ media\nls\c_28599.nls                   1
 media\drivers\etc\services              5
 media\inf\acpi.inf                      6
 media\inf\cdrom.inf                     6
-media\inf\NET_NIC.inf                   6
+media\inf\hdc.inf                       6
 media\inf\layout.inf                    6
 media\inf\machine.inf                   6
 media\inf\mouse.inf                     6
index e62ac01..720be6d 100644 (file)
 <directory name="floppy">
        <xi:include href="floppy/floppy.xml" />
 </directory>
+<directory name="pciide">
+       <xi:include href="pciide/pciide.xml" />
+</directory>
+<directory name="pciidex">
+       <xi:include href="pciidex/pciidex.xml" />
+</directory>
 <directory name="scsiport">
        <xi:include href="scsiport/scsiport.xml" />
 </directory>
diff --git a/reactos/drivers/storage/pciide/pciide.c b/reactos/drivers/storage/pciide/pciide.c
new file mode 100644 (file)
index 0000000..fca806e
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         PCI IDE bus driver
+ * FILE:            drivers/storage/pciide/pciide.c
+ * PURPOSE:         Main file
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+#include "pciide.h"
+
+IDE_CHANNEL_STATE NTAPI
+PciIdeChannelEnabled(
+       IN PVOID DeviceExtension,
+       IN ULONG Channel)
+{
+       PCI_COMMON_CONFIG PciConfig;
+       NTSTATUS Status;
+
+       DPRINT("PciIdeChannelEnabled(%p, %lu)\n", DeviceExtension, Channel);
+
+       Status = PciIdeXGetBusData(
+               DeviceExtension,
+               &PciConfig,
+               0,
+               PCI_COMMON_HDR_LENGTH);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("PciIdeXGetBusData() failed with status 0x%08lx\n", Status);
+               return ChannelStateUnknown;
+       }
+
+       if (PCI_CONFIGURATION_TYPE(&PciConfig) != PCI_DEVICE_TYPE)
+       {
+               DPRINT("Wrong PCI card type. Disabling IDE channel #%lu\n", Channel);
+               return ChannelDisabled;
+       }
+
+       if (PciConfig.BaseClass != PCI_CLASS_MASS_STORAGE_CTLR || PciConfig.SubClass != PCI_SUBCLASS_MSC_IDE_CTLR)
+       {
+               DPRINT("Wrong PCI card base class/sub class. Disabling IDE channel #%lu\n", Channel);
+               return ChannelDisabled;
+       }
+
+       /* FIXME: I don't know where to find the enabled/disabled
+        * bits for channels, so assume they are always enabled
+        */
+       return ChannelEnabled;
+}
+
+BOOLEAN NTAPI
+PciIdeSyncAccessRequired(
+       IN PVOID DeviceExtension)
+{
+       DPRINT1("PciIdeSyncAccessRequired %p\n", DeviceExtension);
+
+       return FALSE; /* FIXME */
+}
+
+NTSTATUS NTAPI
+PciIdeTransferModeSelect(
+       IN PVOID DeviceExtension,
+       IN PPCIIDE_TRANSFER_MODE_SELECT XferMode)
+{
+       ULONG i;
+
+       DPRINT1("PciIdeTransferModeSelect(%p %p)\n", DeviceExtension, XferMode);
+
+       for (i = 0; i < MAX_IDE_DEVICE; i++)
+               XferMode->DevicePresent[i] = FALSE; /* FIXME */
+
+       return STATUS_SUCCESS;
+}
+
+BOOLEAN NTAPI
+PciIdeUseDma(
+       IN PVOID DeviceExtension,
+       IN PUCHAR CdbCommand,
+       IN PUCHAR Slave)
+{
+       DPRINT1("PciIdeUseDma(%p %p %p)\n", DeviceExtension, CdbCommand, Slave);
+
+       return FALSE;
+}
+
+NTSTATUS NTAPI
+PciIdeGetControllerProperties(
+       IN PVOID DeviceExtension,
+       OUT PIDE_CONTROLLER_PROPERTIES ControllerProperties)
+{
+       if (ControllerProperties->Size != sizeof(IDE_CONTROLLER_PROPERTIES))
+               return STATUS_REVISION_MISMATCH;
+
+       ControllerProperties->PciIdeChannelEnabled = PciIdeChannelEnabled;
+       ControllerProperties->PciIdeSyncAccessRequired = PciIdeSyncAccessRequired;
+       ControllerProperties->PciIdeTransferModeSelect = PciIdeTransferModeSelect;
+       ControllerProperties->IgnoreActiveBitForAtaDevice = FALSE;
+       ControllerProperties->AlwaysClearBusMasterInterrupt = TRUE;
+       ControllerProperties->PciIdeUseDma = PciIdeUseDma;
+       ControllerProperties->AlignmentRequirement = 1; /* FIXME */
+       ControllerProperties->DefaultPIO = 0; /* FIXME */
+       ControllerProperties->PciIdeUdmaModesSupported = NULL; /* optional */
+       
+       ControllerProperties->SupportedTransferMode[0][0] =
+       ControllerProperties->SupportedTransferMode[0][1] =
+       ControllerProperties->SupportedTransferMode[1][0] =
+       ControllerProperties->SupportedTransferMode[1][0] =
+               PIO_MODE0 | PIO_MODE1 | PIO_MODE2 | PIO_MODE3 | PIO_MODE4 |
+               SWDMA_MODE0 | SWDMA_MODE1 | SWDMA_MODE2 |
+               MWDMA_MODE0 | MWDMA_MODE1 | MWDMA_MODE2 |
+               UDMA_MODE0 | UDMA_MODE1 | UDMA_MODE2 | UDMA_MODE3 | UDMA_MODE4;
+
+       return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+DriverEntry(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PUNICODE_STRING RegistryPath)
+{
+       NTSTATUS Status;
+
+       Status = PciIdeXInitialize(
+               DriverObject,
+               RegistryPath,
+               PciIdeGetControllerProperties,
+               0);
+
+       return Status;
+}
diff --git a/reactos/drivers/storage/pciide/pciide.h b/reactos/drivers/storage/pciide/pciide.h
new file mode 100644 (file)
index 0000000..3ed0a73
--- /dev/null
@@ -0,0 +1,2 @@
+#include <ntddk.h>
+#include <ide.h>
diff --git a/reactos/drivers/storage/pciide/pciide.rc b/reactos/drivers/storage/pciide/pciide.rc
new file mode 100644 (file)
index 0000000..c0327a2
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "PCI IDE bus driver\0"
+#define REACTOS_STR_INTERNAL_NAME      "pciide\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "pciide.sys\0"
+#include <reactos/version.rc>
diff --git a/reactos/drivers/storage/pciide/pciide.xml b/reactos/drivers/storage/pciide/pciide.xml
new file mode 100644 (file)
index 0000000..5b75c25
--- /dev/null
@@ -0,0 +1,7 @@
+<module name="pciide" type="kernelmodedriver" installbase="system32/drivers" installname="pciide.sys">
+       <define name="__USE_W32API" />
+       <library>pciidex</library>
+       <library>ntoskrnl</library>
+       <file>pciide.c</file>
+       <file>pciide.rc</file>
+</module>
diff --git a/reactos/drivers/storage/pciidex/fdo.c b/reactos/drivers/storage/pciidex/fdo.c
new file mode 100644 (file)
index 0000000..dd6f26e
--- /dev/null
@@ -0,0 +1,437 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         PCI IDE bus driver extension
+ * FILE:            drivers/storage/pciidex/fdo.c
+ * PURPOSE:         IRP_MJ_PNP operations for FDOs
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+#include "pciidex.h"
+
+static NTSTATUS
+GetBusInterface(
+       IN PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+       PBUS_INTERFACE_STANDARD BusInterface = NULL;
+       KEVENT Event;
+       IO_STATUS_BLOCK IoStatus;
+       PIRP Irp;
+       PIO_STACK_LOCATION Stack;
+       NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+       if (DeviceExtension->BusInterface)
+       {
+               DPRINT("We already have the bus interface\n");
+               goto cleanup;
+       }
+
+       BusInterface = ExAllocatePool(PagedPool, sizeof(BUS_INTERFACE_STANDARD));
+       if (!BusInterface)
+       {
+               DPRINT("ExAllocatePool() failed\n");
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+               goto cleanup;
+       }
+
+       KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+       Irp = IoBuildSynchronousFsdRequest(
+               IRP_MJ_PNP,
+               DeviceExtension->LowerDevice,
+               NULL,
+               0,
+               NULL,
+               &Event,
+               &IoStatus);
+       if (!Irp)
+       {
+               DPRINT("IoBuildSynchronousFsdRequest() failed\n");
+               Status = STATUS_INSUFFICIENT_RESOURCES;
+               goto cleanup;
+       }
+
+       Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+       Irp->IoStatus.Information = 0;
+
+       Stack = IoGetNextIrpStackLocation(Irp);
+       Stack->MajorFunction = IRP_MJ_PNP;
+       Stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
+       Stack->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_BUS_INTERFACE_STANDARD;
+       Stack->Parameters.QueryInterface.Version = 1;
+       Stack->Parameters.QueryInterface.Size = sizeof(BUS_INTERFACE_STANDARD);
+       Stack->Parameters.QueryInterface.Interface = (PINTERFACE)BusInterface;
+       Stack->Parameters.QueryInterface.InterfaceSpecificData = NULL;
+
+       Status = IoCallDriver(DeviceExtension->LowerDevice, Irp);
+       if (Status == STATUS_PENDING)
+       {
+               KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+               Status = IoStatus.Status;
+       }
+       if (!NT_SUCCESS(Status))
+               goto cleanup;
+
+       DeviceExtension->BusInterface = BusInterface;
+       BusInterface = NULL;
+       Status = STATUS_SUCCESS;
+
+cleanup:
+       ExFreePool(BusInterface);
+       return Status;
+}
+
+/*
+static NTSTATUS
+ReleaseBusInterface(
+       IN PFDO_DEVICE_EXTENSION DeviceExtension)
+{
+       NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+       if (DeviceExtension->BusInterface)
+       {
+               (*DeviceExtension->BusInterface->InterfaceDereference)(
+                       DeviceExtension->BusInterface->Context);
+               DeviceExtension->BusInterface = NULL;
+               Status = STATUS_SUCCESS;
+       }
+
+       return Status;
+}
+*/
+
+NTSTATUS NTAPI
+PciIdeXAddDevice(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PDEVICE_OBJECT Pdo)
+{
+       PPCIIDEX_DRIVER_EXTENSION DriverExtension;
+       PFDO_DEVICE_EXTENSION DeviceExtension;
+       PDEVICE_OBJECT Fdo;
+       NTSTATUS Status;
+
+       DPRINT("PciIdeXAddDevice(%p %p)\n", DriverObject, Pdo);
+
+       DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
+       ASSERT(DriverExtension);
+
+       Status = IoCreateDevice(
+               DriverObject,
+               sizeof(FDO_DEVICE_EXTENSION) + DriverExtension->MiniControllerExtensionSize,
+               NULL,
+               FILE_DEVICE_BUS_EXTENDER,
+               FILE_DEVICE_SECURE_OPEN,
+               TRUE,
+               &Fdo);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("IoCreateDevice() failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+
+       DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
+       RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
+
+       DeviceExtension->Common.IsFDO = TRUE;
+
+       Status = IoAttachDeviceToDeviceStackSafe(Fdo, Pdo, &DeviceExtension->LowerDevice);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("IoAttachDeviceToDeviceStackSafe() failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+
+       Status = GetBusInterface(DeviceExtension);
+       if (!NT_SUCCESS(Status))
+       {
+               DPRINT("GetBusInterface() failed() failed with status 0x%08lx\n", Status);
+               return Status;
+       }
+
+       Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS NTAPI
+PciIdeXUdmaModesSupported(
+       IN IDE_DRIVE_IDENTIFY IdentifyData,
+       OUT PULONG BestXferMode,
+       OUT PULONG CurrentXferMode)
+{
+       ULONG Best = PIO_MODE0;
+       ULONG Current = PIO_MODE0;
+
+       DPRINT("PciIdeXUdmaModesSupported(%lu, %p %p)\n",
+               IdentifyData, BestXferMode, CurrentXferMode);
+
+       /* FIXME: if current mode is a PIO mode, how to get it?
+        * At the moment, PIO_MODE0 is always returned...
+        */
+
+       if (IdentifyData.TranslationFieldsValid & 0x2)
+       {
+               /* PIO modes and some DMA modes are supported */
+               if (IdentifyData.AdvancedPIOModes & 0x10)
+                       Best = PIO_MODE4;
+               else if (IdentifyData.AdvancedPIOModes & 0x8)
+                       Best = PIO_MODE3;
+               else if (IdentifyData.AdvancedPIOModes & 0x4)
+                       Best = PIO_MODE2;
+               else if (IdentifyData.AdvancedPIOModes & 0x2)
+                       Best = PIO_MODE1;
+               else if (IdentifyData.AdvancedPIOModes & 0x1)
+                       Best = PIO_MODE0;
+
+               if (IdentifyData.SingleWordDMASupport & 0x4)
+                       Best = SWDMA_MODE2;
+               else if (IdentifyData.SingleWordDMASupport & 0x2)
+                       Best = SWDMA_MODE1;
+               else if (IdentifyData.SingleWordDMASupport & 0x1)
+                       Best = SWDMA_MODE0;
+
+               if (IdentifyData.SingleWordDMAActive & 0x4)
+                       Current = SWDMA_MODE2;
+               else if (IdentifyData.SingleWordDMAActive & 0x2)
+                       Current = SWDMA_MODE1;
+               else if (IdentifyData.SingleWordDMAActive & 0x1)
+                       Current = SWDMA_MODE0;
+
+               if (IdentifyData.MultiWordDMASupport & 0x4)
+                       Best = MWDMA_MODE2;
+               else if (IdentifyData.MultiWordDMASupport & 0x2)
+                       Best = MWDMA_MODE1;
+               else if (IdentifyData.MultiWordDMASupport & 0x1)
+                       Best = MWDMA_MODE0;
+
+               if (IdentifyData.MultiWordDMAActive & 0x4)
+                       Current = MWDMA_MODE2;
+               else if (IdentifyData.MultiWordDMAActive & 0x2)
+                       Current = MWDMA_MODE1;
+               else if (IdentifyData.MultiWordDMAActive & 0x1)
+                       Current = MWDMA_MODE0;
+       }
+
+       if (IdentifyData.TranslationFieldsValid & 0x4)
+       {
+               /* UDMA modes are supported */
+               if (IdentifyData.UltraDMAActive & 0x10)
+                       Current = UDMA_MODE4;
+               else if (IdentifyData.UltraDMAActive & 0x8)
+                       Current = UDMA_MODE3;
+               else if (IdentifyData.UltraDMAActive & 0x4)
+                       Current = UDMA_MODE2;
+               else if (IdentifyData.UltraDMAActive & 0x2)
+                       Current = UDMA_MODE1;
+               else if (IdentifyData.UltraDMAActive & 0x1)
+                       Current = UDMA_MODE0;
+
+               if (IdentifyData.UltraDMASupport & 0x10)
+                       Best = UDMA_MODE4;
+               else if (IdentifyData.UltraDMASupport & 0x8)
+                       Best = UDMA_MODE3;
+               else if (IdentifyData.UltraDMASupport & 0x4)
+                       Best = UDMA_MODE2;
+               else if (IdentifyData.UltraDMASupport & 0x2)
+                       Best = UDMA_MODE1;
+               else if (IdentifyData.UltraDMASupport & 0x1)
+                       Best = UDMA_MODE0;
+       }
+
+       *BestXferMode = Best;
+       *CurrentXferMode = Current;
+       return TRUE;
+}
+
+static NTSTATUS
+PciIdeXFdoStartDevice(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       PPCIIDEX_DRIVER_EXTENSION DriverExtension;
+       PFDO_DEVICE_EXTENSION DeviceExtension;
+       PCM_RESOURCE_LIST ResourceList;
+       NTSTATUS Status;
+
+       DPRINT("PciIdeXStartDevice(%p %p)\n", DeviceObject, Irp);
+
+       DriverExtension = IoGetDriverObjectExtension(DeviceObject->DriverObject, DeviceObject->DriverObject);
+       ASSERT(DriverExtension);
+       DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+       ASSERT(DeviceExtension);
+       ASSERT(DeviceExtension->Common.IsFDO);
+
+       DeviceExtension->Properties.Size = sizeof(IDE_CONTROLLER_PROPERTIES);
+       DeviceExtension->Properties.ExtensionSize = DriverExtension->MiniControllerExtensionSize;
+       Status = DriverExtension->HwGetControllerProperties(
+               DeviceExtension->MiniControllerExtension,
+               &DeviceExtension->Properties);
+       if (!NT_SUCCESS(Status))
+               return Status;
+
+       DriverExtension->HwUdmaModesSupported = DeviceExtension->Properties.PciIdeUdmaModesSupported;
+       if (!DriverExtension->HwUdmaModesSupported)
+               /* This method is optional, so provide our own one */
+               DriverExtension->HwUdmaModesSupported = PciIdeXUdmaModesSupported;
+
+       /* Get bus master port base, if any */
+       ResourceList = IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources;
+       if (ResourceList
+               && ResourceList->Count == 1
+               && ResourceList->List[0].PartialResourceList.Count == 1
+               && ResourceList->List[0].PartialResourceList.Version == 1
+               && ResourceList->List[0].PartialResourceList.Revision == 1
+               && ResourceList->List[0].PartialResourceList.PartialDescriptors[0].Type == CmResourceTypePort
+               && ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Length == 16)
+       {
+               DeviceExtension->BusMasterPortBase = ResourceList->List[0].PartialResourceList.PartialDescriptors[0].u.Port.Start;
+       }
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+PciIdeXFdoQueryBusRelations(
+       IN PDEVICE_OBJECT DeviceObject,
+       OUT PDEVICE_RELATIONS* pDeviceRelations)
+{
+       PFDO_DEVICE_EXTENSION DeviceExtension;
+       PDEVICE_RELATIONS DeviceRelations = NULL;
+       PDEVICE_OBJECT Pdo;
+       PPDO_DEVICE_EXTENSION PdoDeviceExtension;
+       ULONG i, j;
+       ULONG PDOs = 0;
+       IDE_CHANNEL_STATE ChannelState;
+       NTSTATUS Status;
+
+       DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+       ASSERT(DeviceExtension);
+       ASSERT(DeviceExtension->Common.IsFDO);
+
+       for (i = 0; i < MAX_IDE_CHANNEL; i++)
+       {
+               if (DeviceExtension->Pdo[i])
+               {
+                       PDOs++;
+                       continue;
+               }
+               ChannelState = DeviceExtension->Properties.PciIdeChannelEnabled(
+                       DeviceExtension->MiniControllerExtension, i);
+               if (ChannelState != ChannelEnabled)
+               {
+                       DPRINT("Channel %lu is disabled\n", i);
+                       continue;
+               }
+
+               /* Need to create a PDO */
+               Status = IoCreateDevice(
+                       DeviceObject->DriverObject,
+                       sizeof(PDO_DEVICE_EXTENSION),
+                       NULL,
+                       FILE_DEVICE_CONTROLLER,
+                       FILE_AUTOGENERATED_DEVICE_NAME,
+                       FALSE,
+                       &Pdo);
+               if (!NT_SUCCESS(Status))
+                       /* FIXME: handle error */
+                       continue;
+
+               PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Pdo->DeviceExtension;
+               RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
+               PdoDeviceExtension->Common.IsFDO = FALSE;
+               PdoDeviceExtension->Channel = i;
+               PdoDeviceExtension->ControllerFdo = DeviceObject;
+               Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
+               Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+               DeviceExtension->Pdo[i] = Pdo;
+               PDOs++;
+       }
+
+       if (PDOs == 0)
+       {
+               DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
+                       PagedPool,
+                       sizeof(DEVICE_RELATIONS));
+       }
+       else
+       {
+               DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
+                       PagedPool,
+                       sizeof(DEVICE_RELATIONS) + sizeof(PDEVICE_OBJECT) * (PDOs - 1));
+       }
+       if (!DeviceRelations)
+               return STATUS_INSUFFICIENT_RESOURCES;
+
+       DeviceRelations->Count = PDOs;
+       for (i = 0, j = 0; i < MAX_IDE_CHANNEL; i++)
+       {
+               if (DeviceExtension->Pdo[i])
+               {
+                       ObReferenceObject(DeviceExtension->Pdo[i]);
+                       DeviceRelations->Objects[j++] = DeviceExtension->Pdo[i];
+               }
+       }
+
+       *pDeviceRelations = DeviceRelations;
+       return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+PciIdeXFdoPnpDispatch(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       ULONG MinorFunction;
+       PIO_STACK_LOCATION Stack;
+       ULONG_PTR Information = 0;
+       NTSTATUS Status;
+
+       Stack = IoGetCurrentIrpStackLocation(Irp);
+       MinorFunction = Stack->MinorFunction;
+
+       switch (MinorFunction)
+       {
+               case IRP_MN_START_DEVICE: /* 0x00 */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
+                       /* Call lower driver */
+                       Status = ForwardIrpAndWait(DeviceObject, Irp);
+                       if (NT_SUCCESS(Status))
+                               Status = PciIdeXFdoStartDevice(DeviceObject, Irp);
+                       break;
+               }
+               case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
+               {
+                       switch (Stack->Parameters.QueryDeviceRelations.Type)
+                       {
+                               case BusRelations:
+                               {
+                                       PDEVICE_RELATIONS DeviceRelations = NULL;
+                                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / BusRelations\n");
+                                       Status = PciIdeXFdoQueryBusRelations(DeviceObject, &DeviceRelations);
+                                       Information = (ULONG_PTR)DeviceRelations;
+                                       break;
+                               }
+                               default:
+                               {
+                                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
+                                               Stack->Parameters.QueryDeviceRelations.Type);
+                                       Status = STATUS_NOT_IMPLEMENTED;
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               default:
+               {
+                       DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
+                       return ForwardIrpAndForget(DeviceObject, Irp);
+               }
+       }
+
+       Irp->IoStatus.Information = Information;
+       Irp->IoStatus.Status = Status;
+       IoCompleteRequest(Irp, IO_NO_INCREMENT);
+       return Status;
+}
diff --git a/reactos/drivers/storage/pciidex/miniport.c b/reactos/drivers/storage/pciidex/miniport.c
new file mode 100644 (file)
index 0000000..a9be42b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         PCI IDE bus driver extension
+ * FILE:            drivers/storage/pciidex/miniport.c
+ * PURPOSE:         Miniport functions
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+#define INITGUID
+#include "pciidex.h"
+
+static NTSTATUS NTAPI
+PciIdeXPnpDispatch(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       if (((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO)
+               return PciIdeXFdoPnpDispatch(DeviceObject, Irp);
+       else
+               return PciIdeXPdoPnpDispatch(DeviceObject, Irp);
+}
+
+NTSTATUS NTAPI
+PciIdeXInitialize(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PUNICODE_STRING RegistryPath,
+       IN PCONTROLLER_PROPERTIES HwGetControllerProperties,
+       IN ULONG ExtensionSize)
+{
+       ULONG i;
+       PPCIIDEX_DRIVER_EXTENSION DriverExtension;
+       NTSTATUS Status;
+
+       DPRINT("PciIdeXInitialize(%p '%wZ' %p 0x%lx)\n",
+               DriverObject, RegistryPath, HwGetControllerProperties, ExtensionSize);
+
+       Status = IoAllocateDriverObjectExtension(
+               DriverObject,
+               DriverObject,
+               sizeof(PCIIDEX_DRIVER_EXTENSION),
+               (PVOID*)&DriverExtension);
+       if (!NT_SUCCESS(Status))
+               return Status;
+       RtlZeroMemory(DriverExtension, sizeof(PCIIDEX_DRIVER_EXTENSION));
+       DriverExtension->MiniControllerExtensionSize = ExtensionSize;
+       DriverExtension->HwGetControllerProperties = HwGetControllerProperties;
+
+       DriverObject->DriverExtension->AddDevice = PciIdeXAddDevice;
+
+       for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
+               DriverObject->MajorFunction[i] = ForwardIrpAndForget;
+       DriverObject->MajorFunction[IRP_MJ_PNP] = PciIdeXPnpDispatch;
+
+       return STATUS_SUCCESS;
+}
+
+/* May be called at IRQL <= DISPATCH_LEVEL */
+NTSTATUS NTAPI
+PciIdeXGetBusData(
+       IN PVOID DeviceExtension,
+       IN PVOID Buffer,
+       IN ULONG ConfigDataOffset,
+       IN ULONG BufferLength)
+{
+       PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+       ULONG BytesRead = 0;
+       NTSTATUS Status = STATUS_UNSUCCESSFUL;
+
+       DPRINT("PciIdeXGetBusData(%p %p 0x%lx 0x%lx)\n",
+               DeviceExtension, Buffer, ConfigDataOffset, BufferLength);
+
+       FdoDeviceExtension = CONTAINING_RECORD(DeviceExtension, FDO_DEVICE_EXTENSION, MiniControllerExtension);
+       if (FdoDeviceExtension->BusInterface)
+       {
+               BytesRead = (*FdoDeviceExtension->BusInterface->GetBusData)(
+                       FdoDeviceExtension->BusInterface->Context,
+                       PCI_WHICHSPACE_CONFIG,
+                       Buffer,
+                       ConfigDataOffset,
+                       BufferLength);
+               if (BytesRead == BufferLength)
+                       Status = STATUS_SUCCESS;
+       }
+
+       return Status;
+}
+
+/* May be called at IRQL <= DISPATCH_LEVEL */
+NTSTATUS NTAPI
+PciIdeXSetBusData(
+       IN PVOID DeviceExtension,
+       IN PVOID Buffer,
+       IN PVOID DataMask,
+       IN ULONG ConfigDataOffset,
+       IN ULONG BufferLength)
+{
+       DPRINT1("PciIdeXSetBusData(%p %p %p 0x%lx 0x%lx)\n",
+               DeviceExtension, Buffer, DataMask, ConfigDataOffset, BufferLength);
+
+       return STATUS_NOT_IMPLEMENTED;
+}
diff --git a/reactos/drivers/storage/pciidex/misc.c b/reactos/drivers/storage/pciidex/misc.c
new file mode 100644 (file)
index 0000000..23a9de2
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         PCI IDE bus driver extension
+ * FILE:            drivers/storage/pciidex/misc.c
+ * PURPOSE:         Misceallenous operations
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+#include "pciidex.h"
+
+NTSTATUS NTAPI
+PciIdeXGenericCompletion(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       IN PVOID Context)
+{
+       if (Irp->PendingReturned)
+               KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
+       return STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+NTSTATUS
+ForwardIrpAndWait(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       PDEVICE_OBJECT LowerDevice;
+       KEVENT Event;
+       NTSTATUS Status;
+
+       ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
+       LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
+       ASSERT(LowerDevice);
+
+       KeInitializeEvent(&Event, NotificationEvent, FALSE);
+       IoCopyCurrentIrpStackLocationToNext(Irp);
+
+       DPRINT("Calling lower device %p [%wZ]\n", LowerDevice, &LowerDevice->DriverObject->DriverName);
+       IoSetCompletionRoutine(Irp, PciIdeXGenericCompletion, &Event, TRUE, TRUE, TRUE);
+
+       Status = IoCallDriver(LowerDevice, Irp);
+       if (Status == STATUS_PENDING)
+       {
+               Status = KeWaitForSingleObject(&Event, Suspended, KernelMode, FALSE, NULL);
+               if (NT_SUCCESS(Status))
+                       Status = Irp->IoStatus.Status;
+       }
+
+       return Status;
+}
+
+NTSTATUS NTAPI
+ForwardIrpAndForget(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       PDEVICE_OBJECT LowerDevice;
+
+       ASSERT(((PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->IsFDO);
+       LowerDevice = ((PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LowerDevice;
+       ASSERT(LowerDevice);
+
+       IoSkipCurrentIrpStackLocation(Irp);
+       return IoCallDriver(LowerDevice, Irp);
+}
diff --git a/reactos/drivers/storage/pciidex/pciidex.c b/reactos/drivers/storage/pciidex/pciidex.c
new file mode 100644 (file)
index 0000000..b561afc
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         PCI IDE bus driver extension
+ * FILE:            drivers/storage/pciidex/pciidex.c
+ * PURPOSE:         Main file
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+#include "pciidex.h"
+
+NTSTATUS NTAPI
+DriverEntry(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PUNICODE_STRING RegistryPath)
+{
+       return STATUS_SUCCESS;
+}
diff --git a/reactos/drivers/storage/pciidex/pciidex.def b/reactos/drivers/storage/pciidex/pciidex.def
new file mode 100644 (file)
index 0000000..5f810fe
--- /dev/null
@@ -0,0 +1,8 @@
+LIBRARY pciidex.sys
+
+EXPORTS
+PciIdeXGetBusData@16
+PciIdeXInitialize@16
+PciIdeXSetBusData@20
+
+;EOF
\ No newline at end of file
diff --git a/reactos/drivers/storage/pciidex/pciidex.h b/reactos/drivers/storage/pciidex/pciidex.h
new file mode 100644 (file)
index 0000000..2f8381e
--- /dev/null
@@ -0,0 +1,81 @@
+#include <ntddk.h>
+#include <ntifs.h>
+#include <ide.h>
+#include <wdmguid.h>
+#include <stdio.h>
+
+/* FIXME: I don't know why it is not defined anywhere... */
+NTSTATUS STDCALL
+IoAttachDeviceToDeviceStackSafe(
+  IN PDEVICE_OBJECT SourceDevice,
+  IN PDEVICE_OBJECT TargetDevice,
+  OUT PDEVICE_OBJECT *AttachedToDeviceObject);
+
+typedef struct _PCIIDEX_DRIVER_EXTENSION
+{
+       PCONTROLLER_PROPERTIES HwGetControllerProperties;
+       ULONG MiniControllerExtensionSize;
+       PCIIDE_UDMA_MODES_SUPPORTED HwUdmaModesSupported;
+} PCIIDEX_DRIVER_EXTENSION, *PPCIIDEX_DRIVER_EXTENSION;
+
+typedef struct _COMMON_DEVICE_EXTENSION
+{
+       BOOLEAN IsFDO;
+} COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
+
+typedef struct _FDO_DEVICE_EXTENSION
+{
+       COMMON_DEVICE_EXTENSION Common;
+
+       PBUS_INTERFACE_STANDARD BusInterface;
+       IDE_CONTROLLER_PROPERTIES Properties;
+       PHYSICAL_ADDRESS BusMasterPortBase;
+       PDEVICE_OBJECT LowerDevice;
+       PDEVICE_OBJECT Pdo[MAX_IDE_CHANNEL];
+       PBYTE MiniControllerExtension[0];
+} FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
+
+typedef struct _PDO_DEVICE_EXTENSION
+{
+       COMMON_DEVICE_EXTENSION Common;
+
+       ULONG Channel;
+       PDEVICE_OBJECT ControllerFdo;
+} PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
+
+/* fdo.c */
+
+NTSTATUS NTAPI
+PciIdeXAddDevice(
+       IN PDRIVER_OBJECT DriverObject,
+       IN PDEVICE_OBJECT Pdo);
+
+NTSTATUS NTAPI
+PciIdeXFdoPnpDispatch(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
+
+/* misc.c */
+
+NTSTATUS NTAPI
+PciIdeXGenericCompletion(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       IN PVOID Context);
+
+NTSTATUS
+ForwardIrpAndWait(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
+
+NTSTATUS NTAPI
+ForwardIrpAndForget(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
+
+/* pdo.c */
+
+NTSTATUS NTAPI
+PciIdeXPdoPnpDispatch(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp);
diff --git a/reactos/drivers/storage/pciidex/pciidex.rc b/reactos/drivers/storage/pciidex/pciidex.rc
new file mode 100644 (file)
index 0000000..d57f017
--- /dev/null
@@ -0,0 +1,5 @@
+#define REACTOS_VERSION_DLL
+#define REACTOS_STR_FILE_DESCRIPTION   "PCI IDE bus driver extension\0"
+#define REACTOS_STR_INTERNAL_NAME      "pciidex\0"
+#define REACTOS_STR_ORIGINAL_FILENAME  "pciidex.sys\0"
+#include <reactos/version.rc>
diff --git a/reactos/drivers/storage/pciidex/pciidex.xml b/reactos/drivers/storage/pciidex/pciidex.xml
new file mode 100644 (file)
index 0000000..4dcbabe
--- /dev/null
@@ -0,0 +1,11 @@
+<module name="pciidex" type="kernelmodedriver" installbase="system32/drivers" installname="pciidex.sys">
+       <importlibrary definition="pciidex.def" />
+       <define name="__USE_W32API" />
+       <library>ntoskrnl</library>
+       <file>fdo.c</file>
+       <file>miniport.c</file>
+       <file>misc.c</file>
+       <file>pciidex.c</file>
+       <file>pdo.c</file>
+       <file>pciidex.rc</file>
+</module>
diff --git a/reactos/drivers/storage/pciidex/pdo.c b/reactos/drivers/storage/pciidex/pdo.c
new file mode 100644 (file)
index 0000000..bd26591
--- /dev/null
@@ -0,0 +1,471 @@
+/*
+ * COPYRIGHT:       See COPYING in the top level directory
+ * PROJECT:         PCI IDE bus driver extension
+ * FILE:            drivers/storage/pciidex/pdo.c
+ * PURPOSE:         IRP_MJ_PNP operations for PDOs
+ * PROGRAMMERS:     Hervé Poussineau (hpoussin@reactos.org)
+ */
+
+#define NDEBUG
+#include <debug.h>
+
+#include "pciidex.h"
+
+static NTSTATUS
+PciIdeXPdoQueryId(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       OUT ULONG_PTR* Information)
+{
+       PPDO_DEVICE_EXTENSION DeviceExtension;
+       WCHAR Buffer[256];
+       ULONG Index = 0;
+       ULONG IdType;
+       UNICODE_STRING SourceString;
+       UNICODE_STRING String;
+       NTSTATUS Status;
+
+       IdType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryId.IdType;
+       DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+       switch (IdType)
+       {
+               case BusQueryDeviceID:
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryDeviceID\n");
+                       RtlInitUnicodeString(&SourceString, L"PCIIDE\\IDEChannel");
+                       break;
+               }
+               case BusQueryHardwareIDs:
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryHardwareIDs\n");
+
+                       if (DeviceExtension->Channel == 0)
+                               Index += swprintf(&Buffer[Index], L"Primary_IDE_Channel");
+                       else
+                               Index += swprintf(&Buffer[Index], L"Secondary_IDE_Channel");
+                       Index++;
+                       Buffer[Index] = UNICODE_NULL;
+                       SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR);
+                       SourceString.Buffer = Buffer;
+                       break;
+               }
+               case BusQueryCompatibleIDs:
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryCompatibleIDs\n");
+
+                       Index += swprintf(&Buffer[Index],
+                               L"*PNP0600");
+                       Index++;
+                       Buffer[Index] = UNICODE_NULL;
+                       SourceString.Length = SourceString.MaximumLength = Index * sizeof(WCHAR);
+                       SourceString.Buffer = Buffer;
+                       break;
+               case BusQueryInstanceID:
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_ID / BusQueryInstanceID\n");
+                       swprintf(Buffer, L"%lu", DeviceExtension->Channel);
+                       RtlInitUnicodeString(&SourceString, Buffer);
+                       break;
+               }
+               default:
+                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_ID / unknown query id type 0x%lx\n", IdType);
+#ifndef NDEBUG
+                       DbgBreakPoint();
+#endif                                 
+                       return STATUS_NOT_SUPPORTED;
+       }
+
+       Status = RtlDuplicateUnicodeString(
+               RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+               &SourceString,
+               &String);
+       *Information = (ULONG_PTR)String.Buffer;
+       return Status;
+}
+
+static NTSTATUS
+GetCurrentResources(
+       IN PDEVICE_OBJECT DeviceObject,
+       OUT PULONG CommandPortBase,
+       OUT PULONG ControlPortBase,
+       OUT PULONG BusMasterPortBase,
+       OUT PULONG InterruptVector)
+{
+       PPDO_DEVICE_EXTENSION DeviceExtension;
+       PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+       ULONG BaseIndex;
+       PCI_COMMON_CONFIG PciConfig;
+       NTSTATUS Status;
+       NTSTATUS ret = STATUS_UNSUCCESSFUL;
+
+       DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+       FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->ControllerFdo->DeviceExtension;
+       BaseIndex = DeviceExtension->Channel * 2;
+
+       Status = PciIdeXGetBusData(
+               FdoDeviceExtension->MiniControllerExtension,
+               &PciConfig,
+               0,
+               PCI_COMMON_HDR_LENGTH);
+       if (!NT_SUCCESS(Status))
+               return Status;
+
+       /* 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");
+               *BusMasterPortBase = PciConfig.u.type0.BaseAddresses[4] & PCI_ADDRESS_IO_ADDRESS_MASK;
+               DPRINT("  IDE Bus Master Registers at IO %lx\n", *BusMasterPortBase);
+       }
+       else
+       {
+               *BusMasterPortBase = 0;
+       }
+
+       if ((PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & PCI_ADDRESS_IO_SPACE) &&
+           (PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & PCI_ADDRESS_IO_SPACE))
+       {
+               /* Channel is enabled */
+               *CommandPortBase = PciConfig.u.type0.BaseAddresses[BaseIndex + 0] & PCI_ADDRESS_IO_ADDRESS_MASK;
+               *ControlPortBase = PciConfig.u.type0.BaseAddresses[BaseIndex + 1] & PCI_ADDRESS_IO_ADDRESS_MASK;
+               *InterruptVector = PciConfig.u.type0.InterruptLine;
+               ret = STATUS_SUCCESS;
+       }
+       else
+       {
+               switch (DeviceExtension->Channel)
+               {
+                       case 0:
+                               *CommandPortBase = 0x1F0;
+                               *ControlPortBase = 0x3F6;
+                               *InterruptVector = 14;
+                               ret = STATUS_SUCCESS;
+                               break;
+                       case 1:
+                               *CommandPortBase = 0x170;
+                               *ControlPortBase = 0x376;
+                               *InterruptVector = 15;
+                               ret = STATUS_SUCCESS;
+                               break;
+               }
+       }
+
+       return ret;
+}
+
+static NTSTATUS
+PciIdeXPdoQueryResourceRequirements(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       OUT ULONG_PTR* Information)
+{
+       ULONG CommandPortBase;
+       ULONG ControlPortBase;
+       ULONG BusMasterPortBase;
+       ULONG InterruptVector;
+       ULONG ListSize;
+       PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
+       PIO_RESOURCE_DESCRIPTOR Descriptor;
+       NTSTATUS Status;
+
+       Status = GetCurrentResources(DeviceObject, &CommandPortBase,
+               &ControlPortBase, &BusMasterPortBase, &InterruptVector);
+       if (!NT_SUCCESS(Status))
+               return Status;
+
+       DPRINT("IDE Channel %lu: IO %x and %x, BM %lx, Irq %lu\n",
+               ((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->Channel,
+               CommandPortBase, ControlPortBase,
+               BusMasterPortBase, InterruptVector);
+
+       /* FIXME: what to do with BusMasterPortBase? */
+
+       ListSize = sizeof(PIO_RESOURCE_REQUIREMENTS_LIST)
+               + 2 * sizeof(IO_RESOURCE_DESCRIPTOR);
+       RequirementsList = ExAllocatePool(PagedPool, ListSize);
+       if (!RequirementsList)
+               return STATUS_INSUFFICIENT_RESOURCES;
+
+       RtlZeroMemory(RequirementsList, ListSize);
+       RequirementsList->ListSize = ListSize;
+       RequirementsList->AlternativeLists = 1;
+
+       RequirementsList->List[0].Version = 1;
+       RequirementsList->List[0].Revision = 1;
+       RequirementsList->List[0].Count = 3;
+
+       Descriptor = &RequirementsList->List[0].Descriptors[0];
+
+       /* Command port base */
+       Descriptor->Option = 0; /* Required */
+       Descriptor->Type = CmResourceTypePort;
+       Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+       Descriptor->Flags = CM_RESOURCE_PORT_IO |
+                           CM_RESOURCE_PORT_16_BIT_DECODE |
+                           CM_RESOURCE_PORT_POSITIVE_DECODE;
+       Descriptor->u.Port.Length = 7;
+       Descriptor->u.Port.Alignment = 1;
+       Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)CommandPortBase;
+       Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(CommandPortBase + 7 - 1);
+       Descriptor++;
+
+       /* Control port base */
+       Descriptor->Option = 0; /* Required */
+       Descriptor->Type = CmResourceTypePort;
+       Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+       Descriptor->Flags = CM_RESOURCE_PORT_IO |
+                           CM_RESOURCE_PORT_16_BIT_DECODE |
+                           CM_RESOURCE_PORT_POSITIVE_DECODE;
+       Descriptor->u.Port.Length = 1;
+       Descriptor->u.Port.Alignment = 1;
+       Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)ControlPortBase;
+       Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(ControlPortBase + 1 - 1);
+       Descriptor++;
+
+       /* Interrupt */
+       Descriptor->Option = 0; /* Required */
+       Descriptor->Type = CmResourceTypeInterrupt;
+       Descriptor->ShareDisposition = CmResourceShareShared;
+       Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+       Descriptor->u.Interrupt.MinimumVector = InterruptVector;
+       Descriptor->u.Interrupt.MaximumVector = InterruptVector;
+
+       *Information = (ULONG_PTR)RequirementsList;
+       return STATUS_SUCCESS;
+}
+
+static NTSTATUS
+PciIdeXPdoQueryDeviceText(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp,
+       OUT ULONG_PTR* Information)
+{
+       PPDO_DEVICE_EXTENSION DeviceExtension;
+       ULONG DeviceTextType;
+       PCWSTR SourceString;
+       UNICODE_STRING String;
+
+       DeviceTextType = IoGetCurrentIrpStackLocation(Irp)->Parameters.QueryDeviceText.DeviceTextType;
+       DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+       switch (DeviceTextType)
+       {
+               case DeviceTextDescription:
+               case DeviceTextLocationInformation:
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / %S\n",
+                               DeviceTextType == DeviceTextDescription ? L"DeviceTextDescription" : L"DeviceTextLocationInformation");
+                       if (DeviceExtension->Channel == 0)
+                               SourceString = L"Primary channel";
+                       else
+                               SourceString = L"Secondary channel";
+                       break;
+               }
+               default:
+                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_TEXT / unknown type 0x%lx\n", DeviceTextType);
+#ifndef NDEBUG
+                       DbgBreakPoint();
+#endif                                 
+                       return STATUS_NOT_SUPPORTED;
+       }
+
+       if (RtlCreateUnicodeString(&String, SourceString))
+       {
+               *Information = (ULONG_PTR)String.Buffer;
+               return STATUS_SUCCESS;
+       }
+       else
+               return STATUS_INSUFFICIENT_RESOURCES;
+}
+
+static NTSTATUS
+PciIdeXPdoQueryDeviceRelations(
+       IN PDEVICE_OBJECT DeviceObject,
+       OUT PDEVICE_RELATIONS* pDeviceRelations)
+{
+       PFDO_DEVICE_EXTENSION DeviceExtension;
+       PDEVICE_RELATIONS DeviceRelations;
+
+       DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+       ASSERT(DeviceExtension->Common.IsFDO);
+
+       DeviceRelations = (PDEVICE_RELATIONS)ExAllocatePool(
+               PagedPool,
+               sizeof(DEVICE_RELATIONS));
+       if (!DeviceRelations)
+               return STATUS_INSUFFICIENT_RESOURCES;
+
+       ObReferenceObject(DeviceObject);
+       DeviceRelations->Count = 1;
+       DeviceRelations->Objects[0] = DeviceObject;
+
+       *pDeviceRelations = DeviceRelations;
+       return STATUS_SUCCESS;
+}
+
+NTSTATUS NTAPI
+PciIdeXPdoPnpDispatch(
+       IN PDEVICE_OBJECT DeviceObject,
+       IN PIRP Irp)
+{
+       ULONG MinorFunction;
+       PIO_STACK_LOCATION Stack;
+       ULONG_PTR Information = 0;
+       NTSTATUS Status;
+
+       Stack = IoGetCurrentIrpStackLocation(Irp);
+       MinorFunction = Stack->MinorFunction;
+
+       switch (MinorFunction)
+       {
+               /* FIXME:
+                * Those are required:
+                *    IRP_MN_START_DEVICE (done)
+                *    IRP_MN_QUERY_STOP_DEVICE
+                *    IRP_MN_STOP_DEVICE
+                *    IRP_MN_CANCEL_STOP_DEVICE
+                *    IRP_MN_QUERY_REMOVE_DEVICE
+                *    IRP_MN_REMOVE_DEVICE
+                *    IRP_MN_CANCEL_REMOVE_DEVICE
+                *    IRP_MN_SURPRISE_REMOVAL
+                *    IRP_MN_QUERY_CAPABILITIES (done)
+                *    IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelations (done)
+                *    IRP_MN_QUERY_ID / BusQueryDeviceID (done)
+                * Those may be required/optional:
+                *    IRP_MN_DEVICE_USAGE_NOTIFICATION
+                *    IRP_MN_QUERY_RESOURCES
+                *    IRP_MN_QUERY_RESOURCE_REQUIREMENTS (done)
+                *    IRP_MN_QUERY_DEVICE_TEXT
+                *    IRP_MN_QUERY_BUS_INFORMATION
+                *    IRP_MN_QUERY_INTERFACE
+                *    IRP_MN_READ_CONFIG
+                *    IRP_MN_WRITE_CONFIG
+                *    IRP_MN_EJECT
+                *    IRP_MN_SET_LOCK
+                * Those are optional:
+                *    IRP_MN_QUERY_DEVICE_RELATIONS / EjectionRelations
+                *    IRP_MN_QUERY_ID / BusQueryHardwareIDs (done)
+                *    IRP_MN_QUERY_ID / BusQueryCompatibleIDs (done)
+                *    IRP_MN_QUERY_ID / BusQueryInstanceID (done)
+                */
+               case IRP_MN_START_DEVICE: /* 0x00 */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_START_DEVICE\n");
+                       Status = STATUS_SUCCESS;
+                       break;
+               }
+               case IRP_MN_QUERY_DEVICE_RELATIONS: /* 0x07 */
+               {
+                       switch (Stack->Parameters.QueryDeviceRelations.Type)
+                       {
+                               case TargetDeviceRelation:
+                               {
+                                       PDEVICE_RELATIONS DeviceRelations = NULL;
+                                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / TargetDeviceRelation\n");
+                                       Status = PciIdeXPdoQueryDeviceRelations(DeviceObject, &DeviceRelations);
+                                       Information = (ULONG_PTR)DeviceRelations;
+                                       break;
+                               }
+                               default:
+                               {
+                                       DPRINT1("IRP_MJ_PNP / IRP_MN_QUERY_DEVICE_RELATIONS / Unknown type 0x%lx\n",
+                                               Stack->Parameters.QueryDeviceRelations.Type);
+#ifndef NDEBUG
+                                       DbgBreakPoint();
+#endif                                 
+                                       Status = STATUS_NOT_SUPPORTED;
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               case IRP_MN_QUERY_CAPABILITIES: /* 0x09 */
+               {
+                       PDEVICE_CAPABILITIES DeviceCapabilities;
+                       ULONG i;
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_CAPABILITIES\n");
+
+                       DeviceCapabilities = (PDEVICE_CAPABILITIES)Stack->Parameters.DeviceCapabilities.Capabilities;
+                       /* FIXME: capabilities can change with connected device */
+                       DeviceCapabilities->LockSupported = FALSE;
+                       DeviceCapabilities->EjectSupported = FALSE;
+                       DeviceCapabilities->Removable = TRUE;
+                       DeviceCapabilities->DockDevice = FALSE;
+                       DeviceCapabilities->UniqueID = FALSE;
+                       DeviceCapabilities->SilentInstall = FALSE;
+                       DeviceCapabilities->RawDeviceOK = TRUE;
+                       DeviceCapabilities->SurpriseRemovalOK = TRUE;
+                       DeviceCapabilities->HardwareDisabled = FALSE; /* FIXME */
+                       //DeviceCapabilities->NoDisplayInUI = FALSE; /* FIXME */
+                       DeviceCapabilities->DeviceState[0] = PowerDeviceD0; /* FIXME */
+                       for (i = 0; i < PowerSystemMaximum; i++)
+                               DeviceCapabilities->DeviceState[i] = PowerDeviceD3; /* FIXME */
+                       //DeviceCapabilities->DeviceWake = PowerDeviceUndefined; /* FIXME */
+                       DeviceCapabilities->D1Latency = 0; /* FIXME */
+                       DeviceCapabilities->D2Latency = 0; /* FIXME */
+                       DeviceCapabilities->D3Latency = 0; /* FIXME */
+                       Status = STATUS_SUCCESS;
+                       break;
+               }
+               case IRP_MN_QUERY_RESOURCES: /* 0x0a */
+               {
+                       /* This IRP is optional; do nothing */
+                       Information = Irp->IoStatus.Information;
+                       Status = Irp->IoStatus.Status;
+                       break;
+               }
+               case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: /* 0x0b */
+               {
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_RESOURCE_REQUIREMENTS\n");
+                       Status = PciIdeXPdoQueryResourceRequirements(DeviceObject, Irp, &Information);
+                       break;
+               }
+               case IRP_MN_QUERY_DEVICE_TEXT: /* 0x0c */
+               {
+                       Status = PciIdeXPdoQueryDeviceText(DeviceObject, Irp, &Information);
+                       break;
+               }
+               case IRP_MN_QUERY_ID: /* 0x13 */
+               {
+                       Status = PciIdeXPdoQueryId(DeviceObject, Irp, &Information);
+                       break;
+               }
+               case IRP_MN_QUERY_BUS_INFORMATION: /* 0x15 */
+               {
+                       PPNP_BUS_INFORMATION BusInfo;
+                       DPRINT("IRP_MJ_PNP / IRP_MN_QUERY_BUS_INFORMATION\n");
+
+                       BusInfo = (PPNP_BUS_INFORMATION)ExAllocatePool(PagedPool, sizeof(PNP_BUS_INFORMATION));
+                       if (!BusInfo)
+                               Status = STATUS_INSUFFICIENT_RESOURCES;
+                       else
+                       {
+                               /*RtlCopyMemory(
+                                       &BusInfo->BusTypeGuid,
+                                       &GUID_DEVINTERFACE_XXX,
+                                       sizeof(GUID));*/
+                               BusInfo->LegacyBusType = PNPBus;
+                               BusInfo->BusNumber = 0; /* FIXME */
+                               Information = (ULONG_PTR)BusInfo;
+                               Status = STATUS_SUCCESS;
+                       }
+                       break;
+               }
+               default:
+               {
+                       /* We can't forward request to the lower driver, because
+                        * we are a Pdo, so we don't have lower driver... */
+                       DPRINT1("IRP_MJ_PNP / Unknown minor function 0x%lx\n", MinorFunction);
+#ifndef NDEBUG
+                       DbgBreakPoint();
+#endif
+                       Information = Irp->IoStatus.Information;
+                       Status = Irp->IoStatus.Status;
+               }
+       }
+
+       Irp->IoStatus.Information = Information;
+       Irp->IoStatus.Status = Status;
+       IoCompleteRequest(Irp, IO_NO_INCREMENT);
+       return Status;
+}
diff --git a/reactos/media/inf/hdc.inf b/reactos/media/inf/hdc.inf
new file mode 100644 (file)
index 0000000..3fa0aa1
--- /dev/null
@@ -0,0 +1,77 @@
+; HDC.INF\r
+\r
+; Installation file for hard disk controllers\r
+\r
+[Version]\r
+Signature  = "$Windows NT$"\r
+;Signature  = "$ReactOS$"\r
+LayoutFile = layout.inf\r
+Class      = hdc\r
+ClassGUID  = {4D36E96A-E325-11CE-BFC1-08002BE10318}\r
+Provider   = %ReactOS%\r
+DriverVer  = 15/08/2005,1.01.0.0\r
+\r
+[DestinationDirs]\r
+DefaultDestDir = 12\r
+\r
+[ClassInstall32.NT]\r
+AddReg = HDC.NT.AddReg\r
+\r
+[HDC.NT.AddReg]\r
+HKR, , ,               0, %HDCClassName%\r
+HKR, , Icon,           0, "-9"\r
+;HKR, , Installer32,    0, "syssetup.dll,HdcClassInstaller"\r
+\r
+[Manufacturer]\r
+%GenericMfg% = GenericMfg\r
+\r
+[GenericMfg]\r
+%PCI\CC_0101.DeviceDesc% = PciIde_Inst,PCI\CC_0101\r
+%*PNP0600.DeviceDesc% = Atapi_Inst,*PNP0600\r
+\r
+;---------------------------- PCI IDE DRIVER ----------------------------\r
+\r
+[PciIde_Inst.NT]\r
+CopyFiles = PciIde_CopyFiles.NT\r
+\r
+[PciIde_CopyFiles.NT]\r
+pciide.sys\r
+pciidex.sys\r
+\r
+[PciIde_Inst.NT.Services]\r
+AddService = pciide, 0x00000002, pciide_Service_Inst\r
+\r
+[pciide_Service_Inst]\r
+ServiceType    = 1\r
+StartType      = 0\r
+ErrorControl   = 1\r
+ServiceBinary  = %12%\pciide.sys\r
+LoadOrderGroup = System Bus Extender\r
+\r
+;----------------------------- ATAPI DRIVER -----------------------------\r
+\r
+[Atapi_Inst.NT]\r
+CopyFiles = Atapi_CopyFiles.NT\r
+\r
+[Atapi_CopyFiles.NT]\r
+atapi.sys\r
+\r
+[Atapi_Inst.NT.Services]\r
+AddService = atapi, 0x00000002, atapi_Service_Inst\r
+\r
+[atapi_Service_Inst]\r
+ServiceType    = 1\r
+StartType      = 0\r
+ErrorControl   = 1\r
+ServiceBinary  = %12%\atapi.sys\r
+LoadOrderGroup = SCSI Miniport\r
+\r
+;-------------------------------- STRINGS -------------------------------\r
+\r
+[Strings]\r
+ReactOS = "ReactOS Team"\r
+HDCClassName = "Hard disks controllers"\r
+\r
+GenericMfg = "(Generic IDE controllers)"\r
+PCI\CC_0101.DeviceDesc = "Generic PCI IDE controller (double channel)"\r
+*PNP0600.DeviceDesc = "Generic IDE channel"\r
index c1d9112..e987cd8 100644 (file)
@@ -15,6 +15,7 @@ ClassGUID={00000000-0000-0000-0000-000000000000}
 ; MS uses netnovel.inf as class-installer INF for NICs
 ; we use a separate one to keep things clean
 cdrom.inf
+hdc.inf
 machine.inf
 mouse.inf
 NET_NIC.inf
diff --git a/reactos/w32api/include/ddk/ide.h b/reactos/w32api/include/ddk/ide.h
new file mode 100644 (file)
index 0000000..ed7beae
--- /dev/null
@@ -0,0 +1,218 @@
+/*
+ * ide.h
+ *
+ * IDE driver interface
+ *
+ * This file is part of the w32api package.
+ *
+ * Contributors:
+ *   Created by Hervé Poussineau <hpoussin@reactos.org>
+ *
+ * THIS SOFTWARE IS NOT COPYRIGHTED
+ *
+ * This source code is offered for use in the public domain. You may
+ * use, modify or distribute it freely.
+ *
+ * This code is distributed in the hope that it will be useful but
+ * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY
+ * DISCLAIMED. This includes but is not limited to warranties of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifndef __IDE_H
+#define __IDE_H
+
+#if __GNUC__ >=3
+#pragma GCC system_header
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define MAX_IDE_CHANNEL   2
+#define MAX_IDE_DEVICE    2
+
+#include <pshpack1.h>
+typedef struct _IDE_DRIVE_IDENTIFY
+{
+  USHORT GeneralConfiguration;
+  USHORT NumberOfCylinders;
+  USHORT Reserved1;
+  USHORT NumberOfHeads;
+  USHORT UnformattedBytesPerTrack;
+  USHORT UnformattedBytesPerSector;
+  USHORT SectorsPerTrack;
+  USHORT VendorUnique1[3];
+  BYTE   SerialNumber[20];
+  USHORT BufferType;
+  USHORT BufferSectorSize;
+  USHORT NumberOfEccBytes;
+  BYTE   FirmwareRevision[8];
+  BYTE   ModelNumber[40];
+  BYTE   MaximumBlockTransfer;
+  BYTE   VendorUnique2;
+  USHORT DoubleWordIo;
+  USHORT Capabilities;
+  USHORT Reserved2;
+  BYTE   VendorUnique3;
+  BYTE   PioCycleTimingMode;
+  BYTE   VendorUnique4;
+  BYTE   DmaCycleTimingMode;
+  USHORT TranslationFieldsValid:3;
+  USHORT Reserved3:13;
+  USHORT NumberOfCurrentCylinders;
+  USHORT NumberOfCurrentHeads;
+  USHORT CurrentSectorsPerTrack;
+  ULONG  CurrentSectorCapacity;
+  USHORT CurrentMultiSectorSetting;
+  ULONG  UserAddressableSectors;
+  USHORT SingleWordDMASupport : 8;
+  USHORT SingleWordDMAActive : 8;
+  USHORT MultiWordDMASupport : 8;
+  USHORT MultiWordDMAActive : 8;
+  USHORT AdvancedPIOModes : 8;
+  USHORT Reserved4 : 8;
+  USHORT MinimumMWXferCycleTime;
+  USHORT RecommendedMWXferCycleTime;
+  USHORT MinimumPIOCycleTime;
+  USHORT MinimumPIOCycleTimeIORDY;
+  USHORT Reserved5[11];
+  USHORT MajorRevision;
+  USHORT MinorRevision;
+  USHORT Reserved6[6];
+  USHORT UltraDMASupport : 8;
+  USHORT UltraDMAActive : 8;
+  USHORT Reserved7[37];
+  USHORT LastLun:3;
+  USHORT Reserved8:13;
+  USHORT MediaStatusNotification:2;
+  USHORT Reserved9:6;
+  USHORT DeviceWriteProtect:1;
+  USHORT Reserved10:7;
+  USHORT Reserved11[128];
+} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
+#include <poppack.h>
+
+typedef struct _PCIIDE_TRANSFER_MODE_SELECT
+{
+  ULONG Channel;
+  BOOLEAN DevicePresent[MAX_IDE_DEVICE];
+  BOOLEAN FixedDisk[MAX_IDE_DEVICE];
+  BOOLEAN IoReadySupported[MAX_IDE_DEVICE];
+  ULONG DeviceTransferModeSupported[MAX_IDE_DEVICE];
+  ULONG BestPioCycleTime[MAX_IDE_DEVICE];
+  ULONG BestSwDmaCycleTime[MAX_IDE_DEVICE];
+  ULONG BestMwDmaCycleTime[MAX_IDE_DEVICE];
+  ULONG BestUDmaCycleTime[MAX_IDE_DEVICE];
+  ULONG DeviceTransferModeCurrent[MAX_IDE_DEVICE];
+  ULONG DeviceTransferModeSelected[MAX_IDE_DEVICE];
+} PCIIDE_TRANSFER_MODE_SELECT, *PPCIIDE_TRANSFER_MODE_SELECT;
+
+typedef enum
+{
+  ChannelDisabled,
+  ChannelEnabled,
+  ChannelStateUnknown
+} IDE_CHANNEL_STATE;
+
+typedef IDE_CHANNEL_STATE
+(NTAPI *PCIIDE_CHANNEL_ENABLED)(
+  IN PVOID DeviceExtension,
+  IN ULONG Channel);
+
+typedef BOOLEAN
+(NTAPI *PCIIDE_SYNC_ACCESS_REQUIRED)(
+  IN PVOID DeviceExtension);
+
+typedef NTSTATUS
+(NTAPI *PCIIDE_TRANSFER_MODE_SELECT_FUNC)(
+  IN PVOID DeviceExtension,
+  IN OUT PPCIIDE_TRANSFER_MODE_SELECT XferMode);
+
+typedef BOOLEAN
+(NTAPI *PCIIDE_USEDMA_FUNC)(
+  IN PVOID DeviceExtension,
+  IN PUCHAR CdbCommand,
+  IN PUCHAR Slave);
+
+typedef NTSTATUS
+(NTAPI *PCIIDE_UDMA_MODES_SUPPORTED)(
+  IN IDE_DRIVE_IDENTIFY IdentifyData,
+  OUT PULONG BestXferMode,
+  OUT PULONG CurrentXferMode);
+
+typedef struct _IDE_CONTROLLER_PROPERTIES
+{
+  ULONG Size;
+  ULONG ExtensionSize;
+  ULONG SupportedTransferMode[MAX_IDE_CHANNEL][MAX_IDE_DEVICE];
+  PCIIDE_CHANNEL_ENABLED PciIdeChannelEnabled;
+  PCIIDE_SYNC_ACCESS_REQUIRED PciIdeSyncAccessRequired;
+  PCIIDE_TRANSFER_MODE_SELECT_FUNC PciIdeTransferModeSelect;
+  BOOLEAN IgnoreActiveBitForAtaDevice;
+  BOOLEAN AlwaysClearBusMasterInterrupt;
+  PCIIDE_USEDMA_FUNC PciIdeUseDma;
+  ULONG AlignmentRequirement;
+  ULONG DefaultPIO;
+  PCIIDE_UDMA_MODES_SUPPORTED PciIdeUdmaModesSupported;
+} IDE_CONTROLLER_PROPERTIES, *PIDE_CONTROLLER_PROPERTIES;
+
+typedef NTSTATUS
+(NTAPI *PCONTROLLER_PROPERTIES)(
+  IN PVOID DeviceExtension,
+  IN PIDE_CONTROLLER_PROPERTIES ControllerProperties);
+
+NTSTATUS NTAPI
+PciIdeXInitialize(
+  IN PDRIVER_OBJECT DriverObject,
+  IN PUNICODE_STRING RegistryPath,
+  IN PCONTROLLER_PROPERTIES HwGetControllerProperties,
+  IN ULONG ExtensionSize);
+
+NTSTATUS NTAPI
+PciIdeXGetBusData(
+  IN PVOID DeviceExtension,
+  IN PVOID Buffer,
+  IN ULONG ConfigDataOffset,
+  IN ULONG BufferLength);
+
+NTSTATUS NTAPI
+PciIdeXSetBusData(
+  IN PVOID DeviceExtension,
+  IN PVOID Buffer,
+  IN PVOID DataMask,
+  IN ULONG ConfigDataOffset,
+  IN ULONG BufferLength);
+
+/* Bit field values for 
+ * PCIIDE_TRANSFER_MODE_SELECT.DeviceTransferModeSupported and
+ * IDE_CONTROLLER_PROPERTIES.SupportedTransferMode
+ */
+// PIO Modes
+#define PIO_MODE0   (1 << 0)
+#define PIO_MODE1   (1 << 1)
+#define PIO_MODE2   (1 << 2)
+#define PIO_MODE3   (1 << 3)
+#define PIO_MODE4   (1 << 4)
+// Single-word DMA Modes
+#define SWDMA_MODE0 (1 << 5)
+#define SWDMA_MODE1 (1 << 6)
+#define SWDMA_MODE2 (1 << 7)
+// Multi-word DMA Modes
+#define MWDMA_MODE0 (1 << 8)
+#define MWDMA_MODE1 (1 << 9)
+#define MWDMA_MODE2 (1 << 10)
+// Ultra DMA Modes
+#define UDMA_MODE0  (1 << 11)
+#define UDMA_MODE1  (1 << 12)
+#define UDMA_MODE2  (1 << 13)
+#define UDMA_MODE3  (1 << 14)
+#define UDMA_MODE4  (1 << 15)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __IDE_H */