Implement InterfacePciDevicePresent(Ex) of PCI_DEVICE_PRESENT_INTERFACE
Modified: trunk/reactos/drivers/bus/pci/fdo.c
Modified: trunk/reactos/drivers/bus/pci/pci.c
Modified: trunk/reactos/drivers/bus/pci/pci.h
Modified: trunk/reactos/drivers/bus/pci/pdo.c

Modified: trunk/reactos/drivers/bus/pci/fdo.c
--- trunk/reactos/drivers/bus/pci/fdo.c	2005-11-19 09:05:37 UTC (rev 19339)
+++ trunk/reactos/drivers/bus/pci/fdo.c	2005-11-19 09:08:08 UTC (rev 19340)
@@ -125,7 +125,7 @@
       Status = FdoLocateChildDevice(&Device, DeviceExtension, SlotNumber, &PciConfig);
       if (!NT_SUCCESS(Status))
       {
-        Device = (PPCI_DEVICE)ExAllocatePool(PagedPool, sizeof(PCI_DEVICE));
+        Device = (PPCI_DEVICE)ExAllocatePool(NonPagedPool, sizeof(PCI_DEVICE));
         if (!Device)
         {
           /* FIXME: Cleanup resources for already discovered devices */
@@ -413,6 +413,11 @@
   DeviceExtension->DeviceListCount = 0;
   DeviceExtension->State = dsStarted;
 
+  ExInterlockedInsertTailList(
+    &DriverExtension->BusListHead,
+    &DeviceExtension->ListEntry,
+    &DriverExtension->BusListLock);
+
   Irp->IoStatus.Information = 0;
 
   return STATUS_SUCCESS;

Modified: trunk/reactos/drivers/bus/pci/pci.c
--- trunk/reactos/drivers/bus/pci/pci.c	2005-11-19 09:05:37 UTC (rev 19339)
+++ trunk/reactos/drivers/bus/pci/pci.c	2005-11-19 09:08:08 UTC (rev 19340)
@@ -29,6 +29,7 @@
 
 /*** PUBLIC ******************************************************************/
 
+PPCI_DRIVER_EXTENSION DriverExtension = NULL;
 
 /*** PRIVATE *****************************************************************/
 
@@ -173,6 +174,8 @@
   IN PDRIVER_OBJECT DriverObject,
   IN PUNICODE_STRING RegistryPath)
 {
+  NTSTATUS Status;
+
   DPRINT("Peripheral Component Interconnect Bus Driver\n");
 
   DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchDeviceControl;
@@ -180,6 +183,18 @@
   DriverObject->MajorFunction[IRP_MJ_POWER] = PciPowerControl;
   DriverObject->DriverExtension->AddDevice = PciAddDevice;
 
+  Status = IoAllocateDriverObjectExtension(
+    DriverObject,
+    DriverObject,
+    sizeof(PCI_DRIVER_EXTENSION),
+    (PVOID*)&DriverExtension);
+  if (!NT_SUCCESS(Status))
+    return Status;
+  RtlZeroMemory(DriverExtension, sizeof(PCI_DRIVER_EXTENSION));
+
+  InitializeListHead(&DriverExtension->BusListHead);
+  KeInitializeSpinLock(&DriverExtension->BusListLock);
+
   return STATUS_SUCCESS;
 }
 

Modified: trunk/reactos/drivers/bus/pci/pci.h
--- trunk/reactos/drivers/bus/pci/pci.h	2005-11-19 09:05:37 UTC (rev 19339)
+++ trunk/reactos/drivers/bus/pci/pci.h	2005-11-19 09:08:08 UTC (rev 19340)
@@ -2,13 +2,6 @@
 #define __PCI_H
 
 
-typedef enum {
-  pbtUnknown = 0,
-  pbtType1,
-  pbtType2,
-} PCI_BUS_TYPE;
-
-
 typedef struct _PCI_DEVICE
 {
   // Entry on device list
@@ -77,6 +70,8 @@
 {
   // Common device data
   COMMON_DEVICE_EXTENSION Common;
+  // Entry on device list
+  LIST_ENTRY ListEntry;
   // PCI bus number serviced by this FDO
   ULONG BusNumber;
   // Current state of the driver
@@ -92,6 +87,21 @@
 } FDO_DEVICE_EXTENSION, *PFDO_DEVICE_EXTENSION;
 
 
+/* Driver extension associated with PCI driver */
+typedef struct _PCI_DRIVER_EXTENSION
+{
+  // 
+  LIST_ENTRY BusListHead;
+  // Lock for namespace bus list
+  KSPIN_LOCK BusListLock;
+} PCI_DRIVER_EXTENSION, *PPCI_DRIVER_EXTENSION;
+
+
+/* We need a global variable to get the driver extension,
+ * because at least InterfacePciDevicePresent has no
+ * other way to get it... */
+extern PPCI_DRIVER_EXTENSION DriverExtension;
+
 /* fdo.c */
 
 NTSTATUS

Modified: trunk/reactos/drivers/bus/pci/pdo.c
--- trunk/reactos/drivers/bus/pci/pdo.c	2005-11-19 09:05:37 UTC (rev 19339)
+++ trunk/reactos/drivers/bus/pci/pdo.c	2005-11-19 09:08:08 UTC (rev 19340)
@@ -954,41 +954,154 @@
   return Size;
 }
 
+
 static BOOLEAN NTAPI
 InterfacePciDevicePresent(
-  IN USHORT  VendorID,
-  IN USHORT  DeviceID,
-  IN UCHAR   RevisionID,
-  IN USHORT  SubVendorID,
-  IN USHORT  SubSystemID,
-  IN ULONG   Flags
-)
+  IN USHORT VendorID,
+  IN USHORT DeviceID,
+  IN UCHAR RevisionID,
+  IN USHORT SubVendorID,
+  IN USHORT SubSystemID,
+  IN ULONG Flags)
 {
-  DPRINT1("Checking for PCI %04X:%04X not implemented\n",
-    VendorID, DeviceID);
+  PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+  PPCI_DEVICE PciDevice;
+  PLIST_ENTRY CurrentBus, CurrentEntry;
+  KIRQL OldIrql;
+  BOOLEAN Found = FALSE;
 
-  return FALSE;
+  KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
+  CurrentBus = DriverExtension->BusListHead.Flink;
+  while (!Found && CurrentBus != &DriverExtension->BusListHead)
+  {
+    FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
+
+    KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
+    CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
+    while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
+    {
+      PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
+      if (PciDevice->PciConfig.VendorID == VendorID &&
+        PciDevice->PciConfig.DeviceID == DeviceID)
+      {
+        if (!(Flags & PCI_USE_SUBSYSTEM_IDS) || (
+          PciDevice->PciConfig.u.type0.SubVendorID == SubVendorID &&
+          PciDevice->PciConfig.u.type0.SubSystemID == SubSystemID))
+        {
+          if (!(Flags & PCI_USE_REVISION) ||
+            PciDevice->PciConfig.RevisionID == RevisionID)
+          {
+            DPRINT("Found the PCI device\n");
+            Found = TRUE;
+          }
+        }
+      }
+
+      CurrentEntry = CurrentEntry->Flink;
+    }
+
+    KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
+    CurrentBus = CurrentBus->Flink;
+  }
+  KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
+
+  return Found;
 }
 
+
+static BOOLEAN
+CheckPciDevice(
+  IN PPCI_COMMON_CONFIG PciConfig,
+  IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
+{
+  if ((Parameters->Flags & PCI_USE_VENDEV_IDS) && (
+    PciConfig->VendorID != Parameters->VendorID ||
+    PciConfig->DeviceID != Parameters->DeviceID))
+  {
+    return FALSE;
+  }
+  if ((Parameters->Flags && PCI_USE_CLASS_SUBCLASS) && (
+    PciConfig->u.type0.SubVendorID != Parameters->SubVendorID ||
+    PciConfig->u.type0.SubSystemID != Parameters->SubSystemID))
+  {
+    return FALSE;
+  }
+  if ((Parameters->Flags & PCI_USE_PROGIF) &&
+    PciConfig->ProgIf != Parameters->ProgIf)
+  {
+    return FALSE;
+  }
+  if ((Parameters->Flags & PCI_USE_SUBSYSTEM_IDS) && (
+    PciConfig->Command != Parameters->SubVendorID ||
+    PciConfig->Status != Parameters->SubSystemID))
+  {
+    return FALSE;
+  }
+  if ((Parameters->Flags & PCI_USE_REVISION) &&
+    PciConfig->RevisionID != Parameters->RevisionID)
+  {
+    return FALSE;
+  }
+  return TRUE;
+}
+
+
 static BOOLEAN NTAPI
 InterfacePciDevicePresentEx(
   IN PVOID Context,
   IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
 {
   PPDO_DEVICE_EXTENSION DeviceExtension;
+  PFDO_DEVICE_EXTENSION MyFdoDeviceExtension;
+  PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+  PPCI_DEVICE PciDevice;
+  PLIST_ENTRY CurrentBus, CurrentEntry;
+  KIRQL OldIrql;
+  BOOLEAN Found = FALSE;
 
-  DPRINT1("InterfacePciDevicePresentEx(%p %p) called\n",
+  DPRINT("InterfacePciDevicePresentEx(%p %p) called\n",
     Context, Parameters);
 
   if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
     return FALSE;
 
   DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
+  MyFdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
 
-  DPRINT1("Checking for PCI %04X:%04X not implemented\n",
-    Parameters->VendorID, Parameters->DeviceID);
+  if (Parameters->Flags & PCI_USE_LOCAL_DEVICE)
+  {
+    return CheckPciDevice(&DeviceExtension->PciDevice->PciConfig, Parameters);
+  }
 
-  return FALSE;
+  KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
+  CurrentBus = DriverExtension->BusListHead.Flink;
+  while (!Found && CurrentBus != &DriverExtension->BusListHead)
+  {
+    FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
+    if (!(Parameters->Flags & PCI_USE_LOCAL_BUS) || FdoDeviceExtension == MyFdoDeviceExtension)
+    {
+      KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
+      CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
+      while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
+      {
+        PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
+
+        if (CheckPciDevice(&PciDevice->PciConfig, Parameters))
+        {
+          DPRINT("Found the PCI device\n");
+          Found = TRUE;
+        }
+
+        CurrentEntry = CurrentEntry->Flink;
+      }
+
+      KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
+    }
+    CurrentBus = CurrentBus->Flink;
+  }
+  KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);
+
+  return Found;
 }
 
 
@@ -1034,15 +1147,15 @@
       Status = STATUS_BUFFER_TOO_SMALL;
     else
     {
-      PPCI_DEVICE_PRESENT_INTERFACE BusInterface;
-      BusInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
-      BusInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
-      BusInterface->Version = 1;
-      BusInterface->Context = DeviceObject;
-      BusInterface->InterfaceReference = InterfaceReference;
-      BusInterface->InterfaceDereference = InterfaceDereference;
-	  BusInterface->IsDevicePresent = InterfacePciDevicePresent;
-      BusInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
+      PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
+      PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
+      PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
+      PciDevicePresentInterface->Version = 1;
+      PciDevicePresentInterface->Context = DeviceObject;
+      PciDevicePresentInterface->InterfaceReference = InterfaceReference;
+      PciDevicePresentInterface->InterfaceDereference = InterfaceDereference;
+      PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
+      PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
       Status = STATUS_SUCCESS;
     }
   }