Added PCI bus driver skeleton
authorCasper Hornstrup <chorns@users.sourceforge.net>
Sun, 16 Sep 2001 13:18:24 +0000 (13:18 +0000)
committerCasper Hornstrup <chorns@users.sourceforge.net>
Sun, 16 Sep 2001 13:18:24 +0000 (13:18 +0000)
svn path=/trunk/; revision=2253

reactos/drivers/bus/pci/fdo.c [new file with mode: 0644]
reactos/drivers/bus/pci/makefile [new file with mode: 0644]
reactos/drivers/bus/pci/pci.c [new file with mode: 0644]
reactos/drivers/bus/pci/pci.h [new file with mode: 0644]
reactos/drivers/bus/pci/pci.rc [new file with mode: 0644]
reactos/drivers/bus/pci/pcidef.h [new file with mode: 0644]
reactos/drivers/bus/pci/pdo.c [new file with mode: 0644]

diff --git a/reactos/drivers/bus/pci/fdo.c b/reactos/drivers/bus/pci/fdo.c
new file mode 100644 (file)
index 0000000..23f1dd7
--- /dev/null
@@ -0,0 +1,458 @@
+/* $Id: fdo.c,v 1.1 2001/09/16 13:18:24 chorns Exp $
+ *
+ * PROJECT:         ReactOS PCI bus driver
+ * FILE:            fdo.c
+ * PURPOSE:         PCI device object dispatch routines
+ * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ *      10-09-2001  CSH  Created
+ */
+#include <pci.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/*** PRIVATE *****************************************************************/
+
+NTSTATUS
+FdoLocateChildDevice(
+  PPCI_DEVICE *Device,
+  PFDO_DEVICE_EXTENSION DeviceExtension,
+  PPCI_COMMON_CONFIG PciConfig)
+{
+  PLIST_ENTRY CurrentEntry;
+  PPCI_DEVICE CurrentDevice;
+
+  CurrentEntry = DeviceExtension->DeviceListHead.Flink;
+  while (CurrentEntry != &DeviceExtension->DeviceListHead) {
+    CurrentDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
+
+    /* If both vendor ID and device ID match, it is the same device */
+    if ((PciConfig->VendorID == CurrentDevice->PciConfig.VendorID) &&
+      (PciConfig->DeviceID == CurrentDevice->PciConfig.DeviceID)) {
+      *Device = CurrentDevice;
+      return STATUS_SUCCESS;
+    }
+
+    CurrentEntry = CurrentEntry->Flink;
+  }
+
+  *Device = NULL;
+  return STATUS_UNSUCCESSFUL;
+}
+
+
+NTSTATUS
+FdoEnumerateDevices(
+  PDEVICE_OBJECT DeviceObject)
+{
+  PFDO_DEVICE_EXTENSION DeviceExtension;
+  PCI_COMMON_CONFIG PciConfig;
+  PLIST_ENTRY CurrentEntry;
+  PPCI_DEVICE Device;
+  NTSTATUS Status;
+  ULONG Slot;
+  ULONG Size;
+
+  DPRINT("Called\n");
+
+  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  /* Mark all devices to be removed. If we don't discover them again during
+     enumeration, assume that they have been surprise removed */
+  CurrentEntry = DeviceExtension->DeviceListHead.Flink;
+  while (CurrentEntry != &DeviceExtension->DeviceListHead) {
+    Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
+    Device->RemovePending = TRUE;
+    CurrentEntry = CurrentEntry->Flink;
+  }
+
+  DeviceExtension->DeviceListCount = 0;
+
+  /* Enumerate devices on the PCI bus */
+  for (Slot = 0; Slot < 256; Slot++)
+       {
+         Size = PciGetBusData(
+      DeviceExtension->BusNumber,
+                       Slot,
+                       &PciConfig,
+      0,
+                       sizeof(PCI_COMMON_CONFIG));
+         if (Size != 0)
+    {
+      DPRINT("Bus %1lu  Device %2lu  Func %1lu  VenID 0x%04hx  DevID 0x%04hx\n",
+                       DeviceExtension->BusNumber,
+                       Slot>>3,
+                       Slot & 0x07,
+                       PciConfig.VendorID,
+                       PciConfig.DeviceID);
+
+      Status = FdoLocateChildDevice(&Device, DeviceExtension, &PciConfig);
+      if (!NT_SUCCESS(Status)) {
+        Device = (PPCI_DEVICE)ExAllocatePool(PagedPool, sizeof(PCI_DEVICE));
+        if (!Device)
+        {
+          /* FIXME: Cleanup resources for already discovered devices */
+          return STATUS_INSUFFICIENT_RESOURCES;
+        }
+
+        RtlZeroMemory(Device, sizeof(PCI_DEVICE));
+
+        RtlMoveMemory(&Device->PciConfig, &PciConfig, sizeof(PCI_COMMON_CONFIG));
+
+        ExInterlockedInsertTailList(
+          &DeviceExtension->DeviceListHead,
+          &Device->ListEntry,
+          &DeviceExtension->DeviceListLock);
+      }
+
+      /* Don't remove this device */
+      Device->RemovePending = FALSE;
+
+      DeviceExtension->DeviceListCount++;
+    }
+       }
+
+  return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+FdoQueryBusRelations(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PPDO_DEVICE_EXTENSION PdoDeviceExtension;
+  PFDO_DEVICE_EXTENSION DeviceExtension;
+  PDEVICE_RELATIONS Relations;
+  PLIST_ENTRY CurrentEntry;
+  PPCI_DEVICE Device;
+  NTSTATUS Status;
+  BOOLEAN ErrorOccurred;
+  NTSTATUS ErrorStatus;
+  WCHAR Buffer[MAX_PATH];
+  ULONG Size;
+  ULONG i;
+
+  DPRINT("Called\n");
+
+  ErrorStatus = STATUS_INSUFFICIENT_RESOURCES;
+
+  Status = STATUS_SUCCESS;
+
+  ErrorOccurred = FALSE;
+
+  FdoEnumerateDevices(DeviceObject);
+
+  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  if (Irp->IoStatus.Information) {
+    /* FIXME: Another bus driver has already created a DEVICE_RELATIONS 
+              structure so we must merge this structure with our own */
+  }
+
+  Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
+    (DeviceExtension->DeviceListCount - 1);
+  Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
+  if (!Relations)
+    return STATUS_INSUFFICIENT_RESOURCES;
+
+  Relations->Count = DeviceExtension->DeviceListCount;
+
+  i = 0;
+  CurrentEntry = DeviceExtension->DeviceListHead.Flink;
+  while (CurrentEntry != &DeviceExtension->DeviceListHead) {
+    Device = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
+
+    PdoDeviceExtension = NULL;
+
+    if (!Device->Pdo) {
+      /* Create a physical device object for the
+         device as it does not already have one */
+      Status = IoCreateDevice(
+        DeviceObject->DriverObject,
+        sizeof(PDO_DEVICE_EXTENSION),
+        NULL,
+        FILE_DEVICE_CONTROLLER,
+        0,
+        FALSE,
+        &Device->Pdo);
+      if (!NT_SUCCESS(Status)) {
+        DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
+        ErrorStatus = Status;
+        ErrorOccurred = TRUE;
+        break;
+      }
+
+      Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
+
+      Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+      //Device->Pdo->Flags |= DO_POWER_PAGABLE;
+
+      PdoDeviceExtension = (PPDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;
+
+      RtlZeroMemory(PdoDeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
+
+      PdoDeviceExtension->IsFDO = FALSE;
+
+      PdoDeviceExtension->DeviceObject = Device->Pdo;
+
+      PdoDeviceExtension->DevicePowerState = PowerDeviceD0;
+
+      /* FIXME: Get device properties (Hardware IDs, etc.) */
+
+      swprintf(
+        Buffer,
+        L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
+        Device->PciConfig.VendorID,
+        Device->PciConfig.DeviceID,
+        Device->PciConfig.u.type0.SubSystemID,
+        Device->PciConfig.RevisionID);
+
+      if (!PciCreateUnicodeString(
+        &PdoDeviceExtension->DeviceID,
+        Buffer,
+        PagedPool)) {
+        ErrorOccurred = TRUE;
+        break;
+      }
+
+      DPRINT("DeviceID: %S\n", PdoDeviceExtension->DeviceID.Buffer);
+    }
+
+    if (!Device->RemovePending) {
+      /* Reference the physical device object. The PnP manager
+         will dereference it again when it is no longer needed */
+      ObReferenceObject(Device->Pdo);
+
+      Relations->Objects[i] = Device->Pdo;
+
+      i++;
+    }
+
+    CurrentEntry = CurrentEntry->Flink;
+  }
+
+  if (ErrorOccurred) {
+    /* FIXME: Cleanup all new PDOs created in this call. Please give me SEH!!! ;-) */
+    /* FIXME: Should IoAttachDeviceToDeviceStack() be undone? */
+    if (PdoDeviceExtension) {
+      RtlFreeUnicodeString(&PdoDeviceExtension->DeviceID);
+      ExFreePool(PdoDeviceExtension);
+    }
+
+    ExFreePool(Relations);
+    return ErrorStatus;
+  }
+
+  Irp->IoStatus.Information = (ULONG_PTR)Relations;
+
+  return Status;
+}
+
+
+NTSTATUS
+FdoStartDevice(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp)
+{
+  PFDO_DEVICE_EXTENSION DeviceExtension;
+
+  DPRINT("Called\n");
+
+  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  assert(DeviceExtension->State == dsStopped);
+
+  InitializeListHead(&DeviceExtension->DeviceListHead);
+  KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
+  DeviceExtension->DeviceListCount = 0;
+
+  PciBusConfigType = PciGetBusConfigType();
+
+  DPRINT("Bus configuration is %d\n", PciBusConfigType);
+
+  if (PciBusConfigType != pbtUnknown) {
+    /* At least one PCI bus is found */
+  }
+
+  /* FIXME: Find a way to get this information */
+  DeviceExtension->BusNumber = 0;
+
+  DeviceExtension->State = dsStarted;
+
+  //Irp->IoStatus.Information = 0;
+
+       return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+FdoSetPower(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PFDO_DEVICE_EXTENSION DeviceExtension;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  if (IrpSp->Parameters.Power.Type == DevicePowerState) {
+    /* FIXME: Set device power state for the device */
+    Status = STATUS_UNSUCCESSFUL;
+  } else {
+    Status = STATUS_UNSUCCESSFUL;
+  }
+
+  return Status;
+}
+
+
+/*** PUBLIC ******************************************************************/
+
+NTSTATUS
+FdoPnpControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp)
+/*
+ * FUNCTION: Handle Plug and Play IRPs for the PCI device object
+ * ARGUMENTS:
+ *     DeviceObject = Pointer to functional device object of the PCI driver
+ *     Irp          = Pointer to IRP that should be handled
+ * RETURNS:
+ *     Status
+ */
+{
+  PFDO_DEVICE_EXTENSION DeviceExtension;
+  PIO_STACK_LOCATION IrpSp;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  IrpSp = IoGetCurrentIrpStackLocation(Irp);
+  switch (IrpSp->MinorFunction) {
+#if 0
+  case IRP_MN_CANCEL_REMOVE_DEVICE:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+
+  case IRP_MN_CANCEL_STOP_DEVICE:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+
+  case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+
+  case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+#endif
+  case IRP_MN_QUERY_DEVICE_RELATIONS:
+    Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
+    break;
+#if 0
+  case IRP_MN_QUERY_PNP_DEVICE_STATE:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+
+  case IRP_MN_QUERY_REMOVE_DEVICE:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+
+  case IRP_MN_QUERY_STOP_DEVICE:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+
+  case IRP_MN_REMOVE_DEVICE:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+#endif
+  case IRP_MN_START_DEVICE:
+    DPRINT("IRP_MN_START_DEVICE received\n");
+    Status = FdoStartDevice(DeviceObject, Irp);
+    break;
+  case IRP_MN_STOP_DEVICE:
+    /* Currently not supported */
+    Status = STATUS_UNSUCCESSFUL;
+    break;
+#if 0
+  case IRP_MN_SURPRISE_REMOVAL:
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+#endif
+  default:
+    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
+
+    /*
+     * Do NOT complete the IRP as it will be processed by the lower
+     * device object, which will complete the IRP
+     */
+    IoSkipCurrentIrpStackLocation(Irp);
+    Status = IoCallDriver(DeviceExtension->Ldo, Irp);
+    return Status;
+    break;
+  }
+
+
+  if (Status != STATUS_PENDING) {
+    if (Status != STATUS_NOT_IMPLEMENTED)
+      Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+  }
+
+  DPRINT("Leaving. Status 0x%X\n", Status);
+
+  return Status;
+}
+
+
+NTSTATUS
+FdoPowerControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp)
+/*
+ * FUNCTION: Handle power management IRPs for the PCI device object
+ * ARGUMENTS:
+ *     DeviceObject = Pointer to functional device object of the PCI driver
+ *     Irp          = Pointer to IRP that should be handled
+ * RETURNS:
+ *     Status
+ */
+{
+  PIO_STACK_LOCATION IrpSp;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+  switch (IrpSp->MinorFunction) {
+  case IRP_MN_SET_POWER:
+    Status = FdoSetPower(DeviceObject, Irp, IrpSp);
+    break;
+
+  default:
+    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+  }
+
+  if (Status != STATUS_PENDING) {
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+  }
+
+  DPRINT("Leaving. Status 0x%X\n", Status);
+
+  return Status;
+}
+
+/* EOF */
diff --git a/reactos/drivers/bus/pci/makefile b/reactos/drivers/bus/pci/makefile
new file mode 100644 (file)
index 0000000..eb1ccc3
--- /dev/null
@@ -0,0 +1,13 @@
+# $Id: makefile,v 1.1 2001/09/16 13:18:24 chorns Exp $
+
+PATH_TO_TOP = ../../..
+
+TARGET_TYPE = driver
+
+TARGET_NAME = pci
+
+TARGET_OBJECTS = fdo.o pci.o pdo.o
+
+include $(PATH_TO_TOP)/rules.mak
+
+include $(TOOLS_PATH)/helper.mk
diff --git a/reactos/drivers/bus/pci/pci.c b/reactos/drivers/bus/pci/pci.c
new file mode 100644 (file)
index 0000000..57a8e23
--- /dev/null
@@ -0,0 +1,613 @@
+/* $Id: pci.c,v 1.1 2001/09/16 13:18:24 chorns Exp $
+ *
+ * PROJECT:         ReactOS PCI Bus driver
+ * FILE:            pci.c
+ * PURPOSE:         Driver entry
+ * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ *      10-09-2001  CSH  Created
+ */
+#include <pci.h>
+
+#define NDEBUG
+#include <debug.h>
+
+
+#ifdef  ALLOC_PRAGMA
+
+// Make the initialization routines discardable, so that they 
+// don't waste space
+
+#pragma  alloc_text(init, DriverEntry)
+
+#endif  /*  ALLOC_PRAGMA  */
+
+/*** PUBLIC ******************************************************************/
+
+PCI_BUS_TYPE PciBusConfigType = pbtUnknown;
+
+
+/*** PRIVATE *****************************************************************/
+
+static NTSTATUS
+PciReadConfigUchar(UCHAR Bus,
+                  UCHAR Slot,
+                  UCHAR Offset,
+                  PUCHAR Value)
+{
+   switch (PciBusConfigType)
+     {
+     case pbtType1:
+       WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+       *Value = READ_PORT_UCHAR((PUCHAR)0xCFC + (Offset & 3));
+       return STATUS_SUCCESS;
+
+     case pbtType2:
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
+       WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+       *Value = READ_PORT_UCHAR((PUCHAR)(IOADDR(Slot, Offset)));
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+       return STATUS_SUCCESS;
+     }
+   return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+PciReadConfigUshort(UCHAR Bus,
+                   UCHAR Slot,
+                   UCHAR Offset,
+                   PUSHORT Value)
+{
+   if ((Offset & 1) != 0)
+     {
+       return STATUS_INVALID_PARAMETER;
+     }
+
+   switch (PciBusConfigType)
+     {
+     case pbtType1:
+       WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+       *Value = READ_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1));
+       return STATUS_SUCCESS;
+
+     case pbtType2:
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
+       WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+       *Value = READ_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)));
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+       return STATUS_SUCCESS;
+     }
+   return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+PciReadConfigUlong(UCHAR Bus,
+                  UCHAR Slot,
+                  UCHAR Offset,
+                  PULONG Value)
+{
+   if ((Offset & 3) != 0)
+     {
+       return STATUS_INVALID_PARAMETER;
+     }
+
+   switch (PciBusConfigType)
+     {
+     case pbtType1:
+       WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+       *Value = READ_PORT_ULONG((PULONG)0xCFC);
+       return STATUS_SUCCESS;
+
+     case pbtType2:
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
+       WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+       *Value = READ_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)));
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+       return STATUS_SUCCESS;
+     }
+   return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+PciWriteConfigUchar(UCHAR Bus,
+                   UCHAR Slot,
+                   UCHAR Offset,
+                   UCHAR Value)
+{
+   switch (PciBusConfigType)
+     {
+     case pbtType1:
+       WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+       WRITE_PORT_UCHAR((PUCHAR)0xCFC + (Offset&3), Value);
+       return STATUS_SUCCESS;
+
+     case pbtType2:
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
+       WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+       WRITE_PORT_UCHAR((PUCHAR)(IOADDR(Slot,Offset)), Value);
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+       return STATUS_SUCCESS;
+     }
+   return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+PciWriteConfigUshort(UCHAR Bus,
+                    UCHAR Slot,
+                    UCHAR Offset,
+                    USHORT Value)
+{
+   if ((Offset & 1) != 0)
+     {
+       return STATUS_INVALID_PARAMETER;
+     }
+
+   switch (PciBusConfigType)
+     {
+     case pbtType1:
+       WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+       WRITE_PORT_USHORT((PUSHORT)0xCFC + (Offset & 1), Value);
+       return STATUS_SUCCESS;
+
+     case pbtType2:
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
+       WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+       WRITE_PORT_USHORT((PUSHORT)(IOADDR(Slot, Offset)), Value);
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+       return STATUS_SUCCESS;
+     }
+   return STATUS_UNSUCCESSFUL;
+}
+
+
+static NTSTATUS
+PciWriteConfigUlong(UCHAR Bus,
+                   UCHAR Slot,
+                   UCHAR Offset,
+                   ULONG Value)
+{
+   if ((Offset & 3) != 0)
+     {
+       return STATUS_INVALID_PARAMETER;
+     }
+
+   switch (PciBusConfigType)
+     {
+     case pbtType1:
+       WRITE_PORT_ULONG((PULONG)0xCF8, CONFIG_CMD(Bus, Slot, Offset));
+       WRITE_PORT_ULONG((PULONG)0xCFC, Value);
+       return STATUS_SUCCESS;
+
+     case pbtType2:
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, FUNC(Slot));
+       WRITE_PORT_UCHAR((PUCHAR)0xCFA, Bus);
+       WRITE_PORT_ULONG((PULONG)(IOADDR(Slot, Offset)), Value);
+       WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0);
+       return STATUS_SUCCESS;
+     }
+   return STATUS_UNSUCCESSFUL;
+}
+
+
+ULONG
+PciGetBusData(ULONG BusNumber,
+              ULONG SlotNumber,
+              PVOID Buffer,
+              ULONG Offset,
+              ULONG Length)
+{
+   PVOID Ptr = Buffer;
+   ULONG Address = Offset;
+   ULONG Len = Length;
+   ULONG Vendor;
+   UCHAR HeaderType;
+
+#if 0
+   DPRINT("  BusNumber %lu\n", BusNumber);
+   DPRINT("  SlotNumber %lu\n", SlotNumber);
+   DPRINT("  Offset 0x%lx\n", Offset);
+   DPRINT("  Length 0x%lx\n", Length);
+#endif
+
+   if ((Length == 0) || (PciBusConfigType == 0))
+     return 0;
+
+   /* 0E=PCI_HEADER_TYPE */
+   PciReadConfigUchar(BusNumber,
+                     SlotNumber & 0xF8,
+                     0x0E,
+                     &HeaderType);
+   if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
+     return 0;
+
+   PciReadConfigUlong(BusNumber,
+                     SlotNumber,
+                     0x00,
+                     &Vendor);
+   /* some broken boards return 0 if a slot is empty: */
+   if (Vendor == 0xFFFFFFFF || Vendor == 0)
+     return 0;
+
+   if ((Address & 1) && (Len >= 1))
+     {
+       PciReadConfigUchar(BusNumber,
+                          SlotNumber,
+                          Address,
+                          Ptr);
+       Ptr = Ptr + 1;
+       Address++;
+       Len--;
+     }
+
+   if ((Address & 2) && (Len >= 2))
+     {
+       PciReadConfigUshort(BusNumber,
+                           SlotNumber,
+                           Address,
+                           Ptr);
+       Ptr = Ptr + 2;
+       Address += 2;
+       Len -= 2;
+     }
+
+   while (Len >= 4)
+     {
+       PciReadConfigUlong(BusNumber,
+                          SlotNumber,
+                          Address,
+                          Ptr);
+       Ptr = Ptr + 4;
+       Address += 4;
+       Len -= 4;
+     }
+
+   if (Len >= 2)
+     {
+       PciReadConfigUshort(BusNumber,
+                           SlotNumber,
+                           Address,
+                           Ptr);
+       Ptr = Ptr + 2;
+       Address += 2;
+       Len -= 2;
+     }
+
+   if (Len >= 1)
+     {
+       PciReadConfigUchar(BusNumber,
+                          SlotNumber,
+                          Address,
+                          Ptr);
+       Ptr = Ptr + 1;
+       Address++;
+       Len--;
+     }
+
+   return Length - Len;
+}
+
+
+ULONG
+PciSetBusData(ULONG BusNumber,
+              ULONG SlotNumber,
+              PVOID Buffer,
+              ULONG Offset,
+              ULONG Length)
+{
+   PVOID Ptr = Buffer;
+   ULONG Address = Offset;
+   ULONG Len = Length;
+   ULONG Vendor;
+   UCHAR HeaderType;
+
+#if 0
+   DPRINT("  BusNumber %lu\n", BusNumber);
+   DPRINT("  SlotNumber %lu\n", SlotNumber);
+   DPRINT("  Offset 0x%lx\n", Offset);
+   DPRINT("  Length 0x%lx\n", Length);
+#endif
+
+   if ((Length == 0) || (PciBusConfigType == 0))
+     return 0;
+
+   /* 0E=PCI_HEADER_TYPE */
+   PciReadConfigUchar(BusNumber,
+                     SlotNumber & 0xF8,
+                     0x0E,
+                     &HeaderType);
+   if (((HeaderType & 0x80) == 0) && ((SlotNumber & 0x07) != 0))
+     return 0;
+
+   PciReadConfigUlong(BusNumber,
+                     SlotNumber,
+                     0x00,
+                     &Vendor);
+   /* some broken boards return 0 if a slot is empty: */
+   if (Vendor == 0xFFFFFFFF || Vendor == 0)
+     return 0;
+
+   if ((Address & 1) && (Len >= 1))
+     {
+       PciWriteConfigUchar(BusNumber,
+                           SlotNumber,
+                           Address,
+                           *(PUCHAR)Ptr);
+       Ptr = Ptr + 1;
+       Address++;
+       Len--;
+     }
+
+   if ((Address & 2) && (Len >= 2))
+     {
+       PciWriteConfigUshort(BusNumber,
+                            SlotNumber,
+                            Address,
+                            *(PUSHORT)Ptr);
+       Ptr = Ptr + 2;
+       Address += 2;
+       Len -= 2;
+     }
+
+   while (Len >= 4)
+     {
+       PciWriteConfigUlong(BusNumber,
+                           SlotNumber,
+                           Address,
+                           *(PULONG)Ptr);
+       Ptr = Ptr + 4;
+       Address += 4;
+       Len -= 4;
+     }
+
+   if (Len >= 2)
+     {
+       PciWriteConfigUshort(BusNumber,
+                            SlotNumber,
+                            Address,
+                            *(PUSHORT)Ptr);
+       Ptr = Ptr + 2;
+       Address += 2;
+       Len -= 2;
+     }
+
+   if (Len >= 1)
+     {
+       PciWriteConfigUchar(BusNumber,
+                           SlotNumber,
+                           Address,
+                           *(PUCHAR)Ptr);
+       Ptr = Ptr + 1;
+       Address++;
+       Len--;
+     }
+
+   return Length - Len;
+}
+
+
+PCI_BUS_TYPE
+PciGetBusConfigType(VOID)
+{
+   ULONG Value;
+
+   DPRINT("Called\n");
+
+   DPRINT("Checking configuration type 1:\n");
+   WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x01);
+   Value = READ_PORT_ULONG((PULONG)0xCF8);
+   WRITE_PORT_ULONG((PULONG)0xCF8, 0x80000000);
+   if (READ_PORT_ULONG((PULONG)0xCF8) == 0x80000000)
+     {
+       WRITE_PORT_ULONG((PULONG)0xCF8, Value);
+       DPRINT("  Success!\n");
+       return pbtType1;
+     }
+   WRITE_PORT_ULONG((PULONG)0xCF8, Value);
+   DPRINT("  Unsuccessful!\n");
+
+   DPRINT("Checking configuration type 2:\n");
+   WRITE_PORT_UCHAR((PUCHAR)0xCFB, 0x00);
+   WRITE_PORT_UCHAR((PUCHAR)0xCF8, 0x00);
+   WRITE_PORT_UCHAR((PUCHAR)0xCFA, 0x00);
+   if (READ_PORT_UCHAR((PUCHAR)0xCF8) == 0x00 &&
+       READ_PORT_UCHAR((PUCHAR)0xCFB) == 0x00)
+     {
+       DPRINT("  Success!\n");
+       return pbtType2;
+     }
+   DPRINT("  Unsuccessful!\n");
+
+   DPRINT("No pci bus found!\n");
+   return pbtUnknown;
+}
+
+
+NTSTATUS
+STDCALL
+PciDispatchDeviceControl(
+  IN PDEVICE_OBJECT DeviceObject, 
+  IN PIRP Irp) 
+{
+  PIO_STACK_LOCATION IrpSp;
+  NTSTATUS Status;
+
+  DPRINT("Called. IRP is at (0x%X)\n", Irp);
+
+  Irp->IoStatus.Information = 0;
+
+  IrpSp = IoGetCurrentIrpStackLocation(Irp);
+  switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) {
+  default:
+    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->Parameters.DeviceIoControl.IoControlCode);
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+  }
+
+  if (Status != STATUS_PENDING) {
+    Irp->IoStatus.Status = Status;
+
+    DPRINT("Completing IRP at 0x%X\n", Irp);
+
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+  }
+
+  DPRINT("Leaving. Status 0x%X\n", Status);
+
+  return Status;
+}
+
+
+NTSTATUS
+STDCALL
+PciPnpControl(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp)
+/*
+ * FUNCTION: Handle Plug and Play IRPs
+ * ARGUMENTS:
+ *     DeviceObject = Pointer to PDO or FDO
+ *     Irp          = Pointer to IRP that should be handled
+ * RETURNS:
+ *     Status
+ */
+{
+  PCOMMON_DEVICE_EXTENSION DeviceExtension;
+  NTSTATUS Status;
+
+  DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  DPRINT("IsFDO %d\n", DeviceExtension->IsFDO);
+
+  if (DeviceExtension->IsFDO) {
+    Status = FdoPnpControl(DeviceObject, Irp);
+  } else {
+    Status = PdoPnpControl(DeviceObject, Irp);
+  }
+
+  return Status;
+}
+
+
+NTSTATUS
+STDCALL
+PciPowerControl(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp)
+/*
+ * FUNCTION: Handle power management IRPs
+ * ARGUMENTS:
+ *     DeviceObject = Pointer to PDO or FDO
+ *     Irp          = Pointer to IRP that should be handled
+ * RETURNS:
+ *     Status
+ */
+{
+  PCOMMON_DEVICE_EXTENSION DeviceExtension;
+  NTSTATUS Status;
+
+  DeviceExtension = (PCOMMON_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  if (DeviceExtension->IsFDO) {
+    Status = FdoPowerControl(DeviceObject, Irp);
+  } else {
+    Status = PdoPowerControl(DeviceObject, Irp);
+  }
+
+  return Status;
+}
+
+
+NTSTATUS
+STDCALL
+PciAddDevice(
+  IN PDRIVER_OBJECT DriverObject,
+  IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+  PFDO_DEVICE_EXTENSION DeviceExtension;
+  PDEVICE_OBJECT Fdo;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  Status = IoCreateDevice(DriverObject, sizeof(FDO_DEVICE_EXTENSION),
+    NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
+  if (!NT_SUCCESS(Status)) {
+    DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
+    return Status;
+  }
+
+  DeviceExtension = (PFDO_DEVICE_EXTENSION)Fdo->DeviceExtension;
+
+  RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
+
+  DeviceExtension->IsFDO = TRUE;
+
+  DeviceExtension->Ldo =
+    IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
+
+  DeviceExtension->State = dsStopped;
+
+  Fdo->Flags &= ~DO_DEVICE_INITIALIZING;
+
+  //Fdo->Flags |= DO_POWER_PAGABLE;
+
+  DPRINT("Done AddDevice\n");
+
+  return STATUS_SUCCESS;
+}
+
+
+NTSTATUS
+STDCALL
+DriverEntry(
+  IN PDRIVER_OBJECT DriverObject,
+  IN PUNICODE_STRING RegistryPath)
+{
+  DbgPrint("Peripheral Component Interconnect Bus Driver\n");
+
+  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl;
+  DriverObject->MajorFunction[IRP_MJ_PNP] = PciPnpControl;
+  DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl;
+  DriverObject->DriverExtension->AddDevice = PciAddDevice;
+
+  return STATUS_SUCCESS;
+}
+
+
+BOOLEAN
+PciCreateUnicodeString(
+  PUNICODE_STRING      Destination,
+  PWSTR Source,
+  POOL_TYPE PoolType)
+{
+  ULONG Length;
+
+  if (!Source)
+  {
+    RtlInitUnicodeString(Destination, NULL);
+    return TRUE;
+  }
+
+  Length = (wcslen(Source) + 1) * sizeof(WCHAR);
+
+  Destination->Buffer = ExAllocatePool(PoolType, Length);
+
+  if (Destination->Buffer == NULL)
+  {
+    return FALSE;
+  }
+
+  RtlCopyMemory(Destination->Buffer, Source, Length);
+
+  Destination->MaximumLength = Length;
+
+  Destination->Length = Length - sizeof(WCHAR);
+
+  return TRUE;
+}
+
+/* EOF */
diff --git a/reactos/drivers/bus/pci/pci.h b/reactos/drivers/bus/pci/pci.h
new file mode 100644 (file)
index 0000000..a27c4ad
--- /dev/null
@@ -0,0 +1,129 @@
+/* $Id: pci.h,v 1.1 2001/09/16 13:18:24 chorns Exp $ */
+
+#ifndef __PCI_H
+#define __PCI_H
+
+#include <ddk/ntddk.h>
+#include <pcidef.h>
+
+
+typedef enum {
+  pbtUnknown = 0,
+  pbtType1,
+  pbtType2,
+} PCI_BUS_TYPE;
+
+
+typedef struct _PCI_DEVICE
+{
+  // Entry on device list
+  LIST_ENTRY ListEntry;
+  // Physical Device Object of device
+  PDEVICE_OBJECT Pdo;
+  // PCI configuration data
+  PCI_COMMON_CONFIG PciConfig;
+  // Flag used during enumeration to locate removed devices
+  BOOLEAN RemovePending;
+} PCI_DEVICE, *PPCI_DEVICE;
+
+
+typedef enum {
+  dsStopped,
+  dsStarted,
+  dsPaused,
+  dsRemoved,
+  dsSurpriseRemoved
+} PCI_DEVICE_STATE;
+
+
+typedef struct _COMMON_DEVICE_EXTENSION
+{
+  // Pointer to device object, this device extension is associated with
+  PDEVICE_OBJECT DeviceObject;
+  // Wether this device extension is for an FDO or PDO
+  BOOLEAN IsFDO;
+  // Wether the device is removed
+  BOOLEAN Removed;
+  // Current device power state for the device
+  DEVICE_POWER_STATE DevicePowerState;
+} __attribute((packed)) COMMON_DEVICE_EXTENSION, *PCOMMON_DEVICE_EXTENSION;
+
+/* Physical Device Object device extension for a child device */
+typedef struct _PDO_DEVICE_EXTENSION
+{
+  // Common device data
+  COMMON_DEVICE_EXTENSION;
+  // Device ID
+  UNICODE_STRING DeviceID;
+  // Instance ID
+  UNICODE_STRING InstanceID;
+  // Hardware IDs
+  UNICODE_STRING HardwareIDs;
+  // Compatible IDs
+  UNICODE_STRING CompatibleIDs;
+  // Textual description of device
+  UNICODE_STRING DeviceText;
+  // Textual description of device
+  UNICODE_STRING DeviceTextLocation;
+} __attribute((packed)) PDO_DEVICE_EXTENSION, *PPDO_DEVICE_EXTENSION;
+
+/* Functional Device Object device extension for the PCI driver device object */
+typedef struct _FDO_DEVICE_EXTENSION
+{
+  // Common device data
+  COMMON_DEVICE_EXTENSION;
+  // Physical Device Object
+  PDEVICE_OBJECT Pdo;
+  // Current state of the driver
+  PCI_DEVICE_STATE State;
+  // Namespace device list
+  LIST_ENTRY DeviceListHead;
+  // Number of (not removed) devices in device list
+  ULONG DeviceListCount;
+  // Lock for namespace device list
+  KSPIN_LOCK DeviceListLock;
+  // PCI bus number
+  ULONG BusNumber;
+  // Lower device object
+  PDEVICE_OBJECT Ldo;
+} __attribute((packed)) FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
+
+
+/* fdo.c */
+
+NTSTATUS
+FdoPnpControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp);
+
+NTSTATUS
+FdoPowerControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp);
+
+/* pci.c */
+
+extern PCI_BUS_TYPE PciBusConfigType;
+
+PCI_BUS_TYPE
+PciGetBusConfigType(VOID);
+
+BOOLEAN
+PciCreateUnicodeString(
+  PUNICODE_STRING      Destination,
+  PWSTR Source,
+  POOL_TYPE PoolType);
+
+/* pdo.c */
+
+NTSTATUS
+PdoPnpControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp);
+
+NTSTATUS
+PdoPowerControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp);
+
+#endif  /*  __PCI_H  */
diff --git a/reactos/drivers/bus/pci/pci.rc b/reactos/drivers/bus/pci/pci.rc
new file mode 100644 (file)
index 0000000..e21a994
--- /dev/null
@@ -0,0 +1,38 @@
+
+#include <defines.h>
+#include <reactos/resource.h>
+
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+
+VS_VERSION_INFO VERSIONINFO
+       FILEVERSION     RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD
+       PRODUCTVERSION  RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD
+       FILEFLAGSMASK   0x3fL
+#ifdef _DEBUG
+       FILEFLAGS       0x1L
+#else
+       FILEFLAGS       0x0L
+#endif
+       FILEOS          0x40004L
+       FILETYPE        0x2L
+       FILESUBTYPE     0x0L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "CompanyName",       RES_STR_COMPANY_NAME
+            VALUE "FileDescription",   "PCI Bus Driver\0"
+            VALUE "FileVersion",       "0.0.0\0"
+            VALUE "InternalName",      "pci\0"
+            VALUE "LegalCopyright",    RES_STR_LEGAL_COPYRIGHT
+            VALUE "OriginalFilename",  "pci.sys\0"
+            VALUE "ProductName",       RES_STR_PRODUCT_NAME
+            VALUE "ProductVersion",    RES_STR_PRODUCT_VERSION
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
diff --git a/reactos/drivers/bus/pci/pcidef.h b/reactos/drivers/bus/pci/pcidef.h
new file mode 100644 (file)
index 0000000..71267ba
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ *     $Id: pcidef.h,v 1.1 2001/09/16 13:18:24 chorns Exp $
+ *
+ *     PCI defines and function prototypes
+ *     Copyright 1994, Drew Eckhardt
+ *     Copyright 1997--1999 Martin Mares <mj@suse.cz>
+ *
+ *     For more information, please consult the following manuals (look at
+ *     http://www.pcisig.com/ for how to get them):
+ *
+ *     PCI BIOS Specification
+ *     PCI Local Bus Specification
+ *     PCI to PCI Bridge Specification
+ *     PCI System Design Guide
+ *
+ *  Ported from linux pci.h to ReactOS by:
+ *    Casper S. Hornstrup (chorns@users.sourceforge.net)
+ */
+
+#ifndef _PCIDEF_H
+#define _PCIDEF_H
+
+/*
+ * Under PCI, each device has 256 bytes of configuration address space,
+ * of which the first 64 bytes are standardized as follows:
+ */
+#define PCI_VENDOR_ID          0x00    /* 16 bits */
+#define PCI_DEVICE_ID          0x02    /* 16 bits */
+#define PCI_COMMAND            0x04    /* 16 bits */
+#define  PCI_COMMAND_IO                0x1     /* Enable response in I/O space */
+#define  PCI_COMMAND_MEMORY    0x2     /* Enable response in Memory space */
+#define  PCI_COMMAND_MASTER    0x4     /* Enable bus mastering */
+#define  PCI_COMMAND_SPECIAL   0x8     /* Enable response to special cycles */
+#define  PCI_COMMAND_INVALIDATE        0x10    /* Use memory write and invalidate */
+#define  PCI_COMMAND_VGA_PALETTE 0x20  /* Enable palette snooping */
+#define  PCI_COMMAND_PARITY    0x40    /* Enable parity checking */
+#define  PCI_COMMAND_WAIT      0x80    /* Enable address/data stepping */
+#define  PCI_COMMAND_SERR      0x100   /* Enable SERR */
+#define  PCI_COMMAND_FAST_BACK 0x200   /* Enable back-to-back writes */
+
+#define PCI_STATUS             0x06    /* 16 bits */
+#define  PCI_STATUS_CAP_LIST   0x10    /* Support Capability List */
+#define  PCI_STATUS_66MHZ      0x20    /* Support 66 Mhz PCI 2.1 bus */
+#define  PCI_STATUS_UDF                0x40    /* Support User Definable Features [obsolete] */
+#define  PCI_STATUS_FAST_BACK  0x80    /* Accept fast-back to back */
+#define  PCI_STATUS_PARITY     0x100   /* Detected parity error */
+#define  PCI_STATUS_DEVSEL_MASK        0x600   /* DEVSEL timing */
+#define  PCI_STATUS_DEVSEL_FAST        0x000   
+#define  PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define  PCI_STATUS_DEVSEL_SLOW 0x400
+#define  PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
+#define  PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
+#define  PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
+#define  PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
+#define  PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
+
+#define PCI_CLASS_REVISION     0x08    /* High 24 bits are class, low 8
+                                          revision */
+#define PCI_REVISION_ID         0x08    /* Revision ID */
+#define PCI_CLASS_PROG          0x09    /* Reg. Level Programming Interface */
+#define PCI_CLASS_DEVICE        0x0a    /* Device class */
+
+#define PCI_CACHE_LINE_SIZE    0x0c    /* 8 bits */
+#define PCI_LATENCY_TIMER      0x0d    /* 8 bits */
+#define PCI_HEADER_TYPE                0x0e    /* 8 bits */
+#define  PCI_HEADER_TYPE_NORMAL        0
+#define  PCI_HEADER_TYPE_BRIDGE 1
+#define  PCI_HEADER_TYPE_CARDBUS 2
+
+#define PCI_BIST               0x0f    /* 8 bits */
+#define PCI_BIST_CODE_MASK     0x0f    /* Return result */
+#define PCI_BIST_START         0x40    /* 1 to start BIST, 2 secs or less */
+#define PCI_BIST_CAPABLE       0x80    /* 1 if BIST capable */
+
+/*
+ * Base addresses specify locations in memory or I/O space.
+ * Decoded size can be determined by writing a value of 
+ * 0xffffffff to the register, and reading it back.  Only 
+ * 1 bits are decoded.
+ */
+#define PCI_BASE_ADDRESS_0     0x10    /* 32 bits */
+#define PCI_BASE_ADDRESS_1     0x14    /* 32 bits [htype 0,1 only] */
+#define PCI_BASE_ADDRESS_2     0x18    /* 32 bits [htype 0 only] */
+#define PCI_BASE_ADDRESS_3     0x1c    /* 32 bits */
+#define PCI_BASE_ADDRESS_4     0x20    /* 32 bits */
+#define PCI_BASE_ADDRESS_5     0x24    /* 32 bits */
+#define  PCI_BASE_ADDRESS_SPACE        0x01    /* 0 = memory, 1 = I/O */
+#define  PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define  PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define  PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define  PCI_BASE_ADDRESS_MEM_TYPE_32  0x00    /* 32 bit address */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_1M  0x02    /* Below 1M [obsolete] */
+#define  PCI_BASE_ADDRESS_MEM_TYPE_64  0x04    /* 64 bit address */
+#define  PCI_BASE_ADDRESS_MEM_PREFETCH 0x08    /* prefetchable? */
+#define  PCI_BASE_ADDRESS_MEM_MASK     (~0x0fUL)
+#define  PCI_BASE_ADDRESS_IO_MASK      (~0x03UL)
+/* bit 1 is reserved if address_space = 1 */
+
+/* Header type 0 (normal devices) */
+#define PCI_CARDBUS_CIS                0x28
+#define PCI_SUBSYSTEM_VENDOR_ID        0x2c
+#define PCI_SUBSYSTEM_ID       0x2e  
+#define PCI_ROM_ADDRESS                0x30    /* Bits 31..11 are address, 10..1 reserved */
+#define  PCI_ROM_ADDRESS_ENABLE        0x01
+#define PCI_ROM_ADDRESS_MASK   (~0x7ffUL)
+
+#define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list entry */
+
+/* 0x35-0x3b are reserved */
+#define PCI_INTERRUPT_LINE     0x3c    /* 8 bits */
+#define PCI_INTERRUPT_PIN      0x3d    /* 8 bits */
+#define PCI_MIN_GNT            0x3e    /* 8 bits */
+#define PCI_MAX_LAT            0x3f    /* 8 bits */
+
+/* Header type 1 (PCI-to-PCI bridges) */
+#define PCI_PRIMARY_BUS                0x18    /* Primary bus number */
+#define PCI_SECONDARY_BUS      0x19    /* Secondary bus number */
+#define PCI_SUBORDINATE_BUS    0x1a    /* Highest bus number behind the bridge */
+#define PCI_SEC_LATENCY_TIMER  0x1b    /* Latency timer for secondary interface */
+#define PCI_IO_BASE            0x1c    /* I/O range behind the bridge */
+#define PCI_IO_LIMIT           0x1d
+#define  PCI_IO_RANGE_TYPE_MASK        0x0f    /* I/O bridging type */
+#define  PCI_IO_RANGE_TYPE_16  0x00
+#define  PCI_IO_RANGE_TYPE_32  0x01
+#define  PCI_IO_RANGE_MASK     ~0x0f
+#define PCI_SEC_STATUS         0x1e    /* Secondary status register, only bit 14 used */
+#define PCI_MEMORY_BASE                0x20    /* Memory range behind */
+#define PCI_MEMORY_LIMIT       0x22
+#define  PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define  PCI_MEMORY_RANGE_MASK ~0x0f
+#define PCI_PREF_MEMORY_BASE   0x24    /* Prefetchable memory range behind */
+#define PCI_PREF_MEMORY_LIMIT  0x26
+#define  PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define  PCI_PREF_RANGE_TYPE_32        0x00
+#define  PCI_PREF_RANGE_TYPE_64        0x01
+#define  PCI_PREF_RANGE_MASK   ~0x0f
+#define PCI_PREF_BASE_UPPER32  0x28    /* Upper half of prefetchable memory range */
+#define PCI_PREF_LIMIT_UPPER32 0x2c
+#define PCI_IO_BASE_UPPER16    0x30    /* Upper half of I/O addresses */
+#define PCI_IO_LIMIT_UPPER16   0x32
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
+#define PCI_ROM_ADDRESS1       0x38    /* Same as PCI_ROM_ADDRESS, but for htype 1 */
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_BRIDGE_CONTROL     0x3e
+#define  PCI_BRIDGE_CTL_PARITY 0x01    /* Enable parity detection on secondary interface */
+#define  PCI_BRIDGE_CTL_SERR   0x02    /* The same for SERR forwarding */
+#define  PCI_BRIDGE_CTL_NO_ISA 0x04    /* Disable bridging of ISA ports */
+#define  PCI_BRIDGE_CTL_VGA    0x08    /* Forward VGA addresses */
+#define  PCI_BRIDGE_CTL_MASTER_ABORT 0x20  /* Report master aborts */
+#define  PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
+#define  PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
+
+/* Header type 2 (CardBus bridges) */
+#define PCI_CB_CAPABILITY_LIST 0x14
+/* 0x15 reserved */
+#define PCI_CB_SEC_STATUS      0x16    /* Secondary status */
+#define PCI_CB_PRIMARY_BUS     0x18    /* PCI bus number */
+#define PCI_CB_CARD_BUS                0x19    /* CardBus bus number */
+#define PCI_CB_SUBORDINATE_BUS 0x1a    /* Subordinate bus number */
+#define PCI_CB_LATENCY_TIMER   0x1b    /* CardBus latency timer */
+#define PCI_CB_MEMORY_BASE_0   0x1c
+#define PCI_CB_MEMORY_LIMIT_0  0x20
+#define PCI_CB_MEMORY_BASE_1   0x24
+#define PCI_CB_MEMORY_LIMIT_1  0x28
+#define PCI_CB_IO_BASE_0       0x2c
+#define PCI_CB_IO_BASE_0_HI    0x2e
+#define PCI_CB_IO_LIMIT_0      0x30
+#define PCI_CB_IO_LIMIT_0_HI   0x32
+#define PCI_CB_IO_BASE_1       0x34
+#define PCI_CB_IO_BASE_1_HI    0x36
+#define PCI_CB_IO_LIMIT_1      0x38
+#define PCI_CB_IO_LIMIT_1_HI   0x3a
+#define  PCI_CB_IO_RANGE_MASK  ~0x03
+/* 0x3c-0x3d are same as for htype 0 */
+#define PCI_CB_BRIDGE_CONTROL  0x3e
+#define  PCI_CB_BRIDGE_CTL_PARITY      0x01    /* Similar to standard bridge control register */
+#define  PCI_CB_BRIDGE_CTL_SERR                0x02
+#define  PCI_CB_BRIDGE_CTL_ISA         0x04
+#define  PCI_CB_BRIDGE_CTL_VGA         0x08
+#define  PCI_CB_BRIDGE_CTL_MASTER_ABORT        0x20
+#define  PCI_CB_BRIDGE_CTL_CB_RESET    0x40    /* CardBus reset */
+#define  PCI_CB_BRIDGE_CTL_16BIT_INT   0x80    /* Enable interrupt for 16-bit cards */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
+#define  PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define  PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define PCI_CB_SUBSYSTEM_ID    0x42
+#define PCI_CB_LEGACY_MODE_BASE        0x44    /* 16-bit PC Card legacy mode base address (ExCa) */
+/* 0x48-0x7f reserved */
+
+/* Capability lists */
+
+#define PCI_CAP_LIST_ID                0       /* Capability ID */
+#define  PCI_CAP_ID_PM         0x01    /* Power Management */
+#define  PCI_CAP_ID_AGP                0x02    /* Accelerated Graphics Port */
+#define  PCI_CAP_ID_VPD                0x03    /* Vital Product Data */
+#define  PCI_CAP_ID_SLOTID     0x04    /* Slot Identification */
+#define  PCI_CAP_ID_MSI                0x05    /* Message Signalled Interrupts */
+#define  PCI_CAP_ID_CHSWP      0x06    /* CompactPCI HotSwap */
+#define PCI_CAP_LIST_NEXT      1       /* Next capability in the list */
+#define PCI_CAP_FLAGS          2       /* Capability defined flags (16 bits) */
+#define PCI_CAP_SIZEOF         4
+
+/* Power Management Registers */
+
+#define PCI_PM_PMC              2       /* PM Capabilities Register */
+#define  PCI_PM_CAP_VER_MASK   0x0007  /* Version */
+#define  PCI_PM_CAP_PME_CLOCK  0x0008  /* PME clock required */
+#define  PCI_PM_CAP_RESERVED    0x0010  /* Reserved field */
+#define  PCI_PM_CAP_DSI                0x0020  /* Device specific initialization */
+#define  PCI_PM_CAP_AUX_POWER  0x01C0  /* Auxilliary power support mask */
+#define  PCI_PM_CAP_D1         0x0200  /* D1 power state support */
+#define  PCI_PM_CAP_D2         0x0400  /* D2 power state support */
+#define  PCI_PM_CAP_PME                0x0800  /* PME pin supported */
+#define  PCI_PM_CAP_PME_MASK    0xF800  /* PME Mask of all supported states */
+#define  PCI_PM_CAP_PME_D0      0x0800  /* PME# from D0 */
+#define  PCI_PM_CAP_PME_D1      0x1000  /* PME# from D1 */
+#define  PCI_PM_CAP_PME_D2      0x2000  /* PME# from D2 */
+#define  PCI_PM_CAP_PME_D3      0x4000  /* PME# from D3 (hot) */
+#define  PCI_PM_CAP_PME_D3cold  0x8000  /* PME# from D3 (cold) */
+#define PCI_PM_CTRL            4       /* PM control and status register */
+#define  PCI_PM_CTRL_STATE_MASK        0x0003  /* Current power state (D0 to D3) */
+#define  PCI_PM_CTRL_PME_ENABLE        0x0100  /* PME pin enable */
+#define  PCI_PM_CTRL_DATA_SEL_MASK     0x1e00  /* Data select (??) */
+#define  PCI_PM_CTRL_DATA_SCALE_MASK   0x6000  /* Data scale (??) */
+#define  PCI_PM_CTRL_PME_STATUS        0x8000  /* PME pin status */
+#define PCI_PM_PPB_EXTENSIONS  6       /* PPB support extensions (??) */
+#define  PCI_PM_PPB_B2_B3      0x40    /* Stop clock when in D3hot (??) */
+#define  PCI_PM_BPCC_ENABLE    0x80    /* Bus power/clock control enable (??) */
+#define PCI_PM_DATA_REGISTER   7       /* (??) */
+#define PCI_PM_SIZEOF          8
+
+/* AGP registers */
+
+#define PCI_AGP_VERSION                2       /* BCD version number */
+#define PCI_AGP_RFU            3       /* Rest of capability flags */
+#define PCI_AGP_STATUS         4       /* Status register */
+#define  PCI_AGP_STATUS_RQ_MASK        0xff000000      /* Maximum number of requests - 1 */
+#define  PCI_AGP_STATUS_SBA    0x0200  /* Sideband addressing supported */
+#define  PCI_AGP_STATUS_64BIT  0x0020  /* 64-bit addressing supported */
+#define  PCI_AGP_STATUS_FW     0x0010  /* FW transfers supported */
+#define  PCI_AGP_STATUS_RATE4  0x0004  /* 4x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE2  0x0002  /* 2x transfer rate supported */
+#define  PCI_AGP_STATUS_RATE1  0x0001  /* 1x transfer rate supported */
+#define PCI_AGP_COMMAND                8       /* Control register */
+#define  PCI_AGP_COMMAND_RQ_MASK 0xff000000  /* Master: Maximum number of requests */
+#define  PCI_AGP_COMMAND_SBA   0x0200  /* Sideband addressing enabled */
+#define  PCI_AGP_COMMAND_AGP   0x0100  /* Allow processing of AGP transactions */
+#define  PCI_AGP_COMMAND_64BIT 0x0020  /* Allow processing of 64-bit addresses */
+#define  PCI_AGP_COMMAND_FW    0x0010  /* Force FW transfers */
+#define  PCI_AGP_COMMAND_RATE4 0x0004  /* Use 4x rate */
+#define  PCI_AGP_COMMAND_RATE2 0x0002  /* Use 4x rate */
+#define  PCI_AGP_COMMAND_RATE1 0x0001  /* Use 4x rate */
+#define PCI_AGP_SIZEOF         12
+
+/* Slot Identification */
+
+#define PCI_SID_ESR            2       /* Expansion Slot Register */
+#define  PCI_SID_ESR_NSLOTS    0x1f    /* Number of expansion slots available */
+#define  PCI_SID_ESR_FIC       0x20    /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR     3       /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS          2       /* Various flags */
+#define  PCI_MSI_FLAGS_64BIT   0x80    /* 64-bit addresses allowed */
+#define  PCI_MSI_FLAGS_QSIZE   0x70    /* Message queue size configured */
+#define  PCI_MSI_FLAGS_QMASK   0x0e    /* Maximum queue size available */
+#define  PCI_MSI_FLAGS_ENABLE  0x01    /* MSI feature enabled */
+#define PCI_MSI_RFU            3       /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO     4       /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI     8       /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32                8       /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64                12      /* 16 bits of data for 64-bit devices */
+
+/*
+ * The PCI interface treats multi-function devices as independent
+ * devices.  The slot/function address of each device is encoded
+ * in a single byte as follows:
+ *
+ *     7:3 = slot
+ *     2:0 = function
+ */
+#define PCI_DEVFN(slot,func)   ((((slot) & 0x1f) << 3) | ((func) & 0x07))
+#define PCI_SLOT(devfn)                (((devfn) >> 3) & 0x1f)
+#define PCI_FUNC(devfn)                ((devfn) & 0x07)
+
+
+/*
+ *  For PCI devices, the region numbers are assigned this way:
+ *
+ *     0-5     standard PCI regions
+ *     6       expansion ROM
+ *     7-10    bridges: address space assigned to buses behind the bridge
+ */
+
+#define PCI_ROM_RESOURCE 6
+#define PCI_BRIDGE_RESOURCES 7
+#define PCI_NUM_RESOURCES 11
+  
+#define PCI_REGION_FLAG_MASK 0x0f      /* These bits of resource flags tell us the PCI region flags */
+
+
+
+#define PCI_TYPE0_ADDRESSES             6
+#define PCI_TYPE1_ADDRESSES             2
+
+typedef struct _PCI_COMMON_CONFIG
+{
+  USHORT VendorID;                   // (ro)
+  USHORT DeviceID;                   // (ro)
+  USHORT Command;                    // Device control
+  USHORT Status;
+  UCHAR  RevisionID;                 // (ro)
+  UCHAR  ProgIf;                     // (ro)
+  UCHAR  SubClass;                   // (ro)
+  UCHAR  BaseClass;                  // (ro)
+  UCHAR  CacheLineSize;              // (ro+)
+  UCHAR  LatencyTimer;               // (ro+)
+  UCHAR  HeaderType;                 // (ro)
+  UCHAR  BIST;                       // Built in self test
+  union
+    {
+      struct _PCI_HEADER_TYPE_0
+       {
+         ULONG  BaseAddresses[PCI_TYPE0_ADDRESSES];
+         ULONG  CIS;
+         USHORT SubVendorID;
+         USHORT SubSystemID;
+         ULONG  ROMBaseAddress;
+    UCHAR  Capabilities; 
+         UCHAR  Reserved2[3];
+    ULONG  Reserved3;
+         UCHAR  InterruptLine;      //
+         UCHAR  InterruptPin;       // (ro)
+         UCHAR  MinimumGrant;          /* read-only */
+         UCHAR  MaximumLatency;        /* read-only */
+       } type0;
+    } u;
+  UCHAR DeviceSpecific[192];
+} __attribute__((packed)) PCI_COMMON_CONFIG, *PPCI_COMMON_CONFIG;
+
+
+#define CONFIG_CMD(bus, device_fn, where) \
+       (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
+
+#define IOADDR(devfn, where) \
+       ((0xC000 | ((devfn & 0x78) << 5)) + where)
+
+#define FUNC(devfn) \
+       (((devfn & 7) << 1) | 0xf0)
+
+#endif /* _PCIDEF_H */
diff --git a/reactos/drivers/bus/pci/pdo.c b/reactos/drivers/bus/pci/pdo.c
new file mode 100644 (file)
index 0000000..560a58a
--- /dev/null
@@ -0,0 +1,242 @@
+/* $Id: pdo.c,v 1.1 2001/09/16 13:18:24 chorns Exp $
+ *
+ * PROJECT:         ReactOS PCI bus driver
+ * FILE:            pdo.c
+ * PURPOSE:         Child device object dispatch routines
+ * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
+ * UPDATE HISTORY:
+ *      10-09-2001  CSH  Created
+ */
+#include <pci.h>
+
+#define NDEBUG
+#include <debug.h>
+
+/*** PRIVATE *****************************************************************/
+
+NTSTATUS
+PdoQueryId(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  UNICODE_STRING String;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+//  Irp->IoStatus.Information = 0;
+
+  Status = STATUS_SUCCESS;
+
+  RtlInitUnicodeString(&String, NULL);
+
+  switch (IrpSp->Parameters.QueryId.IdType) {
+    case BusQueryDeviceID:
+      Status = PciCreateUnicodeString(
+        &String,
+        DeviceExtension->DeviceID.Buffer,
+        PagedPool);
+
+      DPRINT("DeviceID: %S\n", String.Buffer);
+
+      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+      break;
+
+    case BusQueryHardwareIDs:
+    case BusQueryCompatibleIDs:
+      Status = STATUS_NOT_IMPLEMENTED;
+      break;
+
+    case BusQueryInstanceID:
+      Status = PciCreateUnicodeString(
+        &String,
+        L"0000",
+        PagedPool);
+
+      DPRINT("InstanceID: %S\n", String.Buffer);
+
+      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
+      break;
+
+    case BusQueryDeviceSerialNumber:
+    default:
+      Status = STATUS_NOT_IMPLEMENTED;
+  }
+
+  return Status;
+}
+
+
+NTSTATUS
+PdoSetPower(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  if (IrpSp->Parameters.Power.Type == DevicePowerState) {
+    Status = STATUS_SUCCESS;
+    switch (IrpSp->Parameters.Power.State.SystemState) {
+    default:
+      Status = STATUS_UNSUCCESSFUL;
+    }
+  } else {
+    Status = STATUS_UNSUCCESSFUL;
+  }
+
+  return Status;
+}
+
+
+/*** PUBLIC ******************************************************************/
+
+NTSTATUS
+PdoPnpControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp)
+/*
+ * FUNCTION: Handle Plug and Play IRPs for the child device
+ * ARGUMENTS:
+ *     DeviceObject = Pointer to physical device object of the child device
+ *     Irp          = Pointer to IRP that should be handled
+ * RETURNS:
+ *     Status
+ */
+{
+  PIO_STACK_LOCATION IrpSp;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  Status = Irp->IoStatus.Status;
+
+  IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+  switch (IrpSp->MinorFunction) {
+#if 0
+  case IRP_MN_CANCEL_REMOVE_DEVICE:
+    break;
+
+  case IRP_MN_CANCEL_STOP_DEVICE:
+    break;
+
+  case IRP_MN_DEVICE_USAGE_NOTIFICATION:
+    break;
+
+  case IRP_MN_EJECT:
+    break;
+
+  case IRP_MN_QUERY_BUS_INFORMATION:
+    break;
+
+  case IRP_MN_QUERY_CAPABILITIES:
+    break;
+
+  case IRP_MN_QUERY_DEVICE_RELATIONS:
+    /* FIXME: Possibly handle for RemovalRelations */
+    break;
+
+  case IRP_MN_QUERY_DEVICE_TEXT:
+    break;
+#endif
+  case IRP_MN_QUERY_ID:
+    Status = PdoQueryId(DeviceObject, Irp, IrpSp);
+    break;
+#if 0
+  case IRP_MN_QUERY_PNP_DEVICE_STATE:
+    break;
+
+  case IRP_MN_QUERY_REMOVE_DEVICE:
+    break;
+
+  case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+    break;
+
+  case IRP_MN_QUERY_RESOURCES:
+    break;
+
+  case IRP_MN_QUERY_STOP_DEVICE:
+    break;
+
+  case IRP_MN_REMOVE_DEVICE:
+    break;
+
+  case IRP_MN_SET_LOCK:
+    break;
+
+  case IRP_MN_START_DEVICE:
+    break;
+
+  case IRP_MN_STOP_DEVICE:
+    break;
+
+  case IRP_MN_SURPRISE_REMOVAL:
+    break;
+#endif
+  default:
+    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
+    break;
+  }
+
+  if (Status != STATUS_PENDING) {
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+  }
+
+  DPRINT("Leaving. Status 0x%X\n", Status);
+
+  return Status;
+}
+
+NTSTATUS
+PdoPowerControl(
+  PDEVICE_OBJECT DeviceObject,
+  PIRP Irp)
+/*
+ * FUNCTION: Handle power management IRPs for the child device
+ * ARGUMENTS:
+ *     DeviceObject = Pointer to physical device object of the child device
+ *     Irp          = Pointer to IRP that should be handled
+ * RETURNS:
+ *     Status
+ */
+{
+  PIO_STACK_LOCATION IrpSp;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+  switch (IrpSp->MinorFunction) {
+  case IRP_MN_SET_POWER:
+    Status = PdoSetPower(DeviceObject, Irp, IrpSp);
+    break;
+
+  default:
+    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
+    Status = STATUS_NOT_IMPLEMENTED;
+    break;
+  }
+
+  if (Status != STATUS_PENDING) {
+    Irp->IoStatus.Status = Status;
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+  }
+
+  DPRINT("Leaving. Status 0x%X\n", Status);
+
+  return Status;
+}
+
+/* EOF */