Build Hardware IDs and Compatible IDs for PCI devices.
[reactos.git] / reactos / drivers / bus / pci / pci.c
index 57a8e23..ce7a1b3 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: pci.c,v 1.1 2001/09/16 13:18:24 chorns Exp $
+/* $Id: pci.c,v 1.7 2004/06/09 14:22:53 ekohl Exp $
  *
  * PROJECT:         ReactOS PCI Bus driver
  * FILE:            pci.c
@@ -7,7 +7,11 @@
  * UPDATE HISTORY:
  *      10-09-2001  CSH  Created
  */
-#include <pci.h>
+
+#include <ddk/ntddk.h>
+
+#include "pcidef.h"
+#include "pci.h"
 
 #define NDEBUG
 #include <debug.h>
 
 /*** 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(
@@ -544,7 +149,7 @@ PciAddDevice(
 
   RtlZeroMemory(DeviceExtension, sizeof(FDO_DEVICE_EXTENSION));
 
-  DeviceExtension->IsFDO = TRUE;
+  DeviceExtension->Common.IsFDO = TRUE;
 
   DeviceExtension->Ldo =
     IoAttachDeviceToDeviceStack(Fdo, PhysicalDeviceObject);
@@ -580,7 +185,7 @@ DriverEntry(
 
 BOOLEAN
 PciCreateUnicodeString(
-  PUNICODE_STRING      Destination,
+  PUNICODE_STRING Destination,
   PWSTR Source,
   POOL_TYPE PoolType)
 {
@@ -610,4 +215,198 @@ PciCreateUnicodeString(
   return TRUE;
 }
 
+
+NTSTATUS
+PciDuplicateUnicodeString(
+  PUNICODE_STRING Destination,
+  PUNICODE_STRING Source,
+  POOL_TYPE PoolType)
+{
+  if (Source == NULL)
+  {
+    RtlInitUnicodeString(Destination, NULL);
+    return STATUS_SUCCESS;
+  }
+
+  Destination->Buffer = ExAllocatePool(PoolType, Source->MaximumLength);
+  if (Destination->Buffer == NULL)
+  {
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  Destination->MaximumLength = Source->MaximumLength;
+  Destination->Length = Source->Length;
+  RtlCopyMemory(Destination->Buffer, Source->Buffer, Source->MaximumLength);
+
+  return STATUS_SUCCESS;
+}
+
+
+BOOLEAN
+PciCreateDeviceIDString(PUNICODE_STRING DeviceID,
+                        PPCI_DEVICE Device)
+{
+  WCHAR Buffer[256];
+
+  swprintf(Buffer,
+           L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.DeviceID,
+           (Device->PciConfig.u.type0.SubSystemID << 16) +
+           Device->PciConfig.u.type0.SubVendorID,
+           Device->PciConfig.RevisionID);
+
+  if (!PciCreateUnicodeString(DeviceID, Buffer, PagedPool))
+  {
+    return FALSE;
+  }
+
+  return TRUE;
+}
+
+
+BOOLEAN
+PciCreateInstanceIDString(PUNICODE_STRING DeviceID,
+                          PPCI_DEVICE Device)
+{
+  /* FIXME */
+
+#if 0
+  swprintf(Buffer,
+           L"%02lx&%04lx",
+           Device->BusNumber,
+           Device->SlotNumber.SlotNumber.u.AsULONG);
+#endif
+
+  return PciCreateUnicodeString(DeviceID, L"0000", PagedPool);
+}
+
+
+BOOLEAN
+PciCreateHardwareIDsString(PUNICODE_STRING HardwareIDs,
+                           PPCI_DEVICE Device)
+{
+  WCHAR Buffer[256];
+  ULONG Length;
+  ULONG Index;
+
+  Index = 0;
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X&REV_%02X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.DeviceID,
+           (Device->PciConfig.u.type0.SubSystemID << 16) +
+           Device->PciConfig.u.type0.SubVendorID,
+           Device->PciConfig.RevisionID);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X&DEV_%04X&SUBSYS_%08X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.DeviceID,
+           (Device->PciConfig.u.type0.SubSystemID << 16) +
+           Device->PciConfig.u.type0.SubVendorID);
+  Index++;
+
+  Buffer[Index] = UNICODE_NULL;
+
+  Length = (Index + 1) * sizeof(WCHAR);
+  HardwareIDs->Buffer = ExAllocatePool(PagedPool, Length);
+  if (Buffer == NULL)
+  {
+    return FALSE;
+  }
+
+  HardwareIDs->Length = Length - sizeof(WCHAR);
+  HardwareIDs->MaximumLength = Length;
+  RtlCopyMemory(HardwareIDs->Buffer, Buffer, Length);
+
+  return TRUE;
+}
+
+
+BOOLEAN
+PciCreateCompatibleIDsString(PUNICODE_STRING HardwareIDs,
+                             PPCI_DEVICE Device)
+{
+  WCHAR Buffer[256];
+  ULONG Length;
+  ULONG Index;
+
+  Index = 0;
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X&DEV_%04X&REV_%02X&CC_%02X%02X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.DeviceID,
+           Device->PciConfig.RevisionID,
+           Device->PciConfig.BaseClass,
+           Device->PciConfig.SubClass);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X%02X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.DeviceID,
+           Device->PciConfig.BaseClass,
+           Device->PciConfig.SubClass,
+           Device->PciConfig.ProgIf);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X&DEV_%04X&CC_%02X%02X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.DeviceID,
+           Device->PciConfig.BaseClass,
+           Device->PciConfig.SubClass);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X&CC_%02X%02X%02X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.BaseClass,
+           Device->PciConfig.SubClass,
+           Device->PciConfig.ProgIf);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X&CC_%02X%02X",
+           Device->PciConfig.VendorID,
+           Device->PciConfig.BaseClass,
+           Device->PciConfig.SubClass);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\VEN_%04X",
+           Device->PciConfig.VendorID);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\CC_%02X%02X%02X",
+           Device->PciConfig.BaseClass,
+           Device->PciConfig.SubClass,
+           Device->PciConfig.ProgIf);
+  Index++;
+
+  Index += swprintf(&Buffer[Index],
+           L"PCI\\CC_%02X%02X",
+           Device->PciConfig.BaseClass,
+           Device->PciConfig.SubClass);
+  Index++;
+
+  Buffer[Index] = UNICODE_NULL;
+
+  Length = (Index + 1) * sizeof(WCHAR);
+  HardwareIDs->Buffer = ExAllocatePool(PagedPool, Length);
+  if (Buffer == NULL)
+  {
+    return FALSE;
+  }
+
+  HardwareIDs->Length = Length - sizeof(WCHAR);
+  HardwareIDs->MaximumLength = Length;
+  RtlCopyMemory(HardwareIDs->Buffer, Buffer, Length);
+
+  return TRUE;
+}
+
 /* EOF */