[PCI]: Add PCI IRQ Routing Table structure to Shared, Internal PCI Header (based...
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / hwpci.c
index 1046ec1..20960cf 100644 (file)
@@ -13,9 +13,9 @@
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include <freeldr.h>
 #define NDEBUG
 #include <debug.h>
 
-typedef struct _ROUTING_SLOT
-{
-  UCHAR  BusNumber;
-  UCHAR  DeviceNumber;
-  UCHAR  LinkA;
-  USHORT BitmapA;
-  UCHAR  LinkB;
-  USHORT BitmapB;
-  UCHAR  LinkC;
-  USHORT BitmapC;
-  UCHAR  LinkD;
-  USHORT BitmapD;
-  UCHAR  SlotNumber;
-  UCHAR  Reserved;
-} __attribute__((packed)) ROUTING_SLOT, *PROUTING_SLOT;
-
-typedef struct _PCI_IRQ_ROUTING_TABLE
-{
-  ULONG Signature;
-  USHORT Version;
-  USHORT Size;
-  UCHAR  RouterBus;
-  UCHAR  RouterSlot;
-  USHORT ExclusiveIRQs;
-  ULONG CompatibleRouter;
-  ULONG MiniportData;
-  UCHAR  Reserved[11];
-  UCHAR  Checksum;
-  ROUTING_SLOT Slot[1];
-} __attribute__((packed)) PCI_IRQ_ROUTING_TABLE, *PPCI_IRQ_ROUTING_TABLE;
-
-typedef struct _CM_PCI_BUS_DATA
-{
-  UCHAR  BusCount;
-  USHORT PciVersion;
-  UCHAR  HardwareMechanism;
-} __attribute__((packed)) CM_PCI_BUS_DATA, *PCM_PCI_BUS_DATA;
-
-
 static PPCI_IRQ_ROUTING_TABLE
 GetPciIrqRoutingTable(VOID)
 {
@@ -71,34 +32,34 @@ GetPciIrqRoutingTable(VOID)
   ULONG i;
 
   Table = (PPCI_IRQ_ROUTING_TABLE)0xF0000;
-  while ((ULONG)Table < 0x100000)
+  while ((ULONG_PTR)Table < 0x100000)
     {
-      if (Table->Signature == 0x52495024)
+      if (Table->Signature == 'RIP$')
        {
-         DbgPrint((DPRINT_HWDETECT,
-                   "Found signature\n"));
+         DPRINTM(DPRINT_HWDETECT,
+                   "Found signature\n");
 
          Ptr = (PUCHAR)Table;
          Sum = 0;
-         for (i = 0; i < Table->Size; i++)
+         for (i = 0; i < Table->TableSize; i++)
            {
              Sum += Ptr[i];
            }
 
          if ((Sum & 0xFF) != 0)
            {
-             DbgPrint((DPRINT_HWDETECT,
-                       "Invalid routing table\n"));
+             DPRINTM(DPRINT_HWDETECT,
+                       "Invalid routing table\n");
              return NULL;
            }
 
-         DbgPrint((DPRINT_HWDETECT,
-                  "Valid checksum\n"));
+         DPRINTM(DPRINT_HWDETECT,
+                  "Valid checksum\n");
 
          return Table;
        }
 
-      Table = (PPCI_IRQ_ROUTING_TABLE)((ULONG)Table + 0x10);
+      Table = (PPCI_IRQ_ROUTING_TABLE)((ULONG_PTR)Table + 0x10);
     }
 
   return NULL;
@@ -106,7 +67,7 @@ GetPciIrqRoutingTable(VOID)
 
 
 static BOOLEAN
-FindPciBios(PCM_PCI_BUS_DATA BusData)
+FindPciBios(PPCI_REGISTRY_INFO BusData)
 {
   REGS  RegsIn;
   REGS  RegsOut;
@@ -118,249 +79,202 @@ FindPciBios(PCM_PCI_BUS_DATA BusData)
 
   if (INT386_SUCCESS(RegsOut) && RegsOut.d.edx == 0x20494350 && RegsOut.b.ah == 0)
     {
-      DbgPrint((DPRINT_HWDETECT, "Found PCI bios\n"));
+      DPRINTM(DPRINT_HWDETECT, "Found PCI bios\n");
 
-      DbgPrint((DPRINT_HWDETECT, "AL: %x\n", RegsOut.b.al));
-      DbgPrint((DPRINT_HWDETECT, "BH: %x\n", RegsOut.b.bh));
-      DbgPrint((DPRINT_HWDETECT, "BL: %x\n", RegsOut.b.bl));
-      DbgPrint((DPRINT_HWDETECT, "CL: %x\n", RegsOut.b.cl));
+      DPRINTM(DPRINT_HWDETECT, "AL: %x\n", RegsOut.b.al);
+      DPRINTM(DPRINT_HWDETECT, "BH: %x\n", RegsOut.b.bh);
+      DPRINTM(DPRINT_HWDETECT, "BL: %x\n", RegsOut.b.bl);
+      DPRINTM(DPRINT_HWDETECT, "CL: %x\n", RegsOut.b.cl);
 
-      BusData->BusCount = RegsOut.b.cl + 1;
-      BusData->PciVersion = RegsOut.w.bx;
-      BusData->HardwareMechanism = RegsOut.b.cl;
+      BusData->NoBuses = RegsOut.b.cl + 1;
+      BusData->MajorRevision = RegsOut.b.bh;
+      BusData->MinorRevision = RegsOut.b.bl;
+      BusData->HardwareMechanism = RegsOut.b.al;
 
       return TRUE;
     }
 
 
-  DbgPrint((DPRINT_HWDETECT, "No PCI bios found\n"));
+  DPRINTM(DPRINT_HWDETECT, "No PCI bios found\n");
 
   return FALSE;
 }
 
 
 static VOID
-DetectPciIrqRoutingTable(FRLDRHKEY BusKey)
+DetectPciIrqRoutingTable(PCONFIGURATION_COMPONENT_DATA BusKey)
 {
-  PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
+  PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
   PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
   PPCI_IRQ_ROUTING_TABLE Table;
-  FRLDRHKEY TableKey;
+  PCONFIGURATION_COMPONENT_DATA TableKey;
   ULONG Size;
-  LONG Error;
 
   Table = GetPciIrqRoutingTable();
   if (Table != NULL)
     {
-      DbgPrint((DPRINT_HWDETECT, "Table size: %u\n", Table->Size));
-
-      Error = RegCreateKey(BusKey,
-                          L"RealModeIrqRoutingTable\\0",
-                          &TableKey);
-      if (Error != ERROR_SUCCESS)
-       {
-         DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
-         return;
-       }
-
-      /* Set 'Component Information' */
-      SetComponentInformation(TableKey,
-                              0x0,
-                              0x0,
-                              0xFFFFFFFF);
-
-      /* Set 'Identifier' value */
-      Error = RegSetValue(TableKey,
-                         L"Identifier",
-                         REG_SZ,
-                         (PCHAR)L"PCI Real-mode IRQ Routing Table",
-                         32 * sizeof(WCHAR));
-      if (Error != ERROR_SUCCESS)
-       {
-         DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
-         return;
-       }
+      DPRINTM(DPRINT_HWDETECT, "Table size: %u\n", Table->TableSize);
 
       /* Set 'Configuration Data' value */
-      Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
-            Table->Size;
-      FullResourceDescriptor = MmAllocateMemory(Size);
-      if (FullResourceDescriptor == NULL)
-       {
-         DbgPrint((DPRINT_HWDETECT,
-                   "Failed to allocate resource descriptor\n"));
-         return;
-       }
+      Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors) +
+         2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) + Table->TableSize;
+      PartialResourceList = MmHeapAlloc(Size);
+      if (PartialResourceList == NULL)
+      {
+          DPRINTM(DPRINT_HWDETECT,
+              "Failed to allocate resource descriptor\n");
+          return;
+      }
 
       /* Initialize resource descriptor */
-      memset(FullResourceDescriptor, 0, Size);
-      FullResourceDescriptor->InterfaceType = Isa;
-      FullResourceDescriptor->BusNumber = 0;
-      FullResourceDescriptor->PartialResourceList.Count = 1;
-
-      PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
+      memset(PartialResourceList, 0, Size);
+      PartialResourceList->Version = 1;
+      PartialResourceList->Revision = 1;
+      PartialResourceList->Count = 2;
+
+      PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
+      PartialDescriptor->Type = CmResourceTypeBusNumber;
+      PartialDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+      PartialDescriptor->u.BusNumber.Start = 0;
+      PartialDescriptor->u.BusNumber.Length = 1;
+
+      PartialDescriptor = &PartialResourceList->PartialDescriptors[1];
       PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
       PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
-      PartialDescriptor->u.DeviceSpecificData.DataSize = Table->Size;
-
-      memcpy((PVOID)((ULONG_PTR)FullResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR)),
-            Table,
-            Table->Size);
-
-      /* Set 'Configuration Data' value */
-      Error = RegSetValue(TableKey,
-                         L"Configuration Data",
-                         REG_FULL_RESOURCE_DESCRIPTOR,
-                         (PCHAR) FullResourceDescriptor,
-                         Size);
-      MmFreeMemory(FullResourceDescriptor);
-      if (Error != ERROR_SUCCESS)
-       {
-         DbgPrint((DPRINT_HWDETECT,
-                   "RegSetValue(Configuration Data) failed (Error %u)\n",
-                   (int)Error));
-         return;
-       }
+      PartialDescriptor->u.DeviceSpecificData.DataSize = Table->TableSize;
+
+      memcpy(&PartialResourceList->PartialDescriptors[2],
+          Table, Table->TableSize);
+
+      FldrCreateComponentKey(BusKey,
+                             PeripheralClass,
+                             RealModeIrqRoutingTable,
+                             0x0,
+                             0x0,
+                             0xFFFFFFFF,
+                             "PCI Real-mode IRQ Routing Table",
+                             PartialResourceList,
+                             Size,
+                             &TableKey);
+
+      MmHeapFree(PartialResourceList);
     }
 }
 
 
 VOID
-DetectPciBios(FRLDRHKEY SystemKey, ULONG *BusNumber)
+DetectPciBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
 {
-  PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
-  CM_PCI_BUS_DATA BusData;
-  WCHAR Buffer[80];
-  FRLDRHKEY BiosKey;
+  PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
+  PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
+  PCI_REGISTRY_INFO BusData;
+  PCONFIGURATION_COMPONENT_DATA BiosKey;
   ULONG Size;
-  LONG Error;
-#if 0
-  FRLDRHKEY BusKey;
+  PCONFIGURATION_COMPONENT_DATA BusKey;
   ULONG i;
-  WCHAR szPci[] = L"PCI";
-#endif
 
   /* Report the PCI BIOS */
   if (FindPciBios(&BusData))
     {
-      /* Create new bus key */
-      swprintf(Buffer,
-             L"MultifunctionAdapter\\%u", *BusNumber);
-      Error = RegCreateKey(SystemKey,
-                          Buffer,
-                          &BiosKey);
-      if (Error != ERROR_SUCCESS)
-       {
-         DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
-         return;
-       }
+      /* Set 'Configuration Data' value */
+      Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST,
+                          PartialDescriptors);
+      PartialResourceList = MmHeapAlloc(Size);
+      if (PartialResourceList == NULL)
+      {
+          DPRINTM(DPRINT_HWDETECT,
+              "Failed to allocate resource descriptor\n");
+          return;
+      }
 
-      /* Set 'Component Information' */
-      SetComponentInformation(BiosKey,
-                              0x0,
-                              0x0,
-                              0xFFFFFFFF);
+      /* Initialize resource descriptor */
+      memset(PartialResourceList, 0, Size);
+
+      /* Create new bus key */
+      FldrCreateComponentKey(SystemKey,
+                             AdapterClass,
+                             MultiFunctionAdapter,
+                             0x0,
+                             0x0,
+                             0xFFFFFFFF,
+                             "PCI BIOS",
+                             PartialResourceList,
+                             Size,
+                             &BiosKey);
 
       /* Increment bus number */
       (*BusNumber)++;
 
-      /* Set 'Identifier' value */
-      Error = RegSetValue(BiosKey,
-                         L"Identifier",
-                         REG_SZ,
-                         (PCHAR)L"PCI BIOS",
-                         9 * sizeof(WCHAR));
-      if (Error != ERROR_SUCCESS)
-       {
-         DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
-         return;
-       }
-
-      /* Set 'Configuration Data' value */
-      Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR);
-      FullResourceDescriptor = MmAllocateMemory(Size);
-      if (FullResourceDescriptor == NULL)
-       {
-         DbgPrint((DPRINT_HWDETECT,
-                   "Failed to allocate resource descriptor\n"));
-         return;
-       }
-
-      /* Initialize resource descriptor */
-      memset(FullResourceDescriptor, 0, Size);
-      FullResourceDescriptor->InterfaceType = PCIBus;
-      FullResourceDescriptor->BusNumber = 0;
-      FullResourceDescriptor->PartialResourceList.Version = 1;
-      FullResourceDescriptor->PartialResourceList.Revision = 1;
-      FullResourceDescriptor->PartialResourceList.Count = 1;
-      FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].Type = CmResourceTypeBusNumber;
-      FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].ShareDisposition = CmResourceShareDeviceExclusive;
-      FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.BusNumber.Start = 0;
-      FullResourceDescriptor->PartialResourceList.PartialDescriptors[0].u.BusNumber.Length = 1;
-
-      /* Set 'Configuration Data' value */
-      Error = RegSetValue(BiosKey,
-                         L"Configuration Data",
-                         REG_FULL_RESOURCE_DESCRIPTOR,
-                         (PCHAR) FullResourceDescriptor,
-                         Size);
-      MmFreeMemory(FullResourceDescriptor);
-      if (Error != ERROR_SUCCESS)
-       {
-         DbgPrint((DPRINT_HWDETECT,
-                   "RegSetValue(Configuration Data) failed (Error %u)\n",
-                   (int)Error));
-         return;
-       }
+      MmHeapFree(PartialResourceList);
 
       DetectPciIrqRoutingTable(BiosKey);
 
-#if 0
-      /*
-       * FIXME:
-       * Enabling this piece of code will corrupt the boot sequence!
-       * This is probably caused by a bug in the registry code!
-       */
-
       /* Report PCI buses */
-      for (i = 0; i < (ULONG)BusData.BusCount; i++)
-       {
-         swprintf(Buffer,
-                  L"MultifunctionAdapter\\%u", *BusNumber);
-         Error = RegCreateKey(SystemKey,
-                              Buffer,
-                              &BusKey);
-         if (Error != ERROR_SUCCESS)
-           {
-             DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
-             printf("RegCreateKey() failed (Error %u)\n", (int)Error);
-             return;
-           }
-
-         /* Set 'Component Information' */
-         SetComponentInformation(BusKey,
-                                 0x0,
-                                 0x0,
-                                 0xFFFFFFFF);
-
-         /* Increment bus number */
-         (*BusNumber)++;
-
-
-         /* Set 'Identifier' value */
-         Error = RegSetValue(BusKey,
-                             L"Identifier",
-                             REG_SZ,
-                             (PCSTR)szPci,
-                             sizeof(szPci));
-         if (Error != ERROR_SUCCESS)
-           {
-             DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
-             return;
-           }
-       }
-#endif
-
+      for (i = 0; i < (ULONG)BusData.NoBuses; i++)
+      {
+          /* Check if this is the first bus */
+          if (i == 0)
+          {
+              /* Set 'Configuration Data' value */
+              Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST,
+                                  PartialDescriptors) +
+                     sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) +
+                     sizeof(PCI_REGISTRY_INFO);
+              PartialResourceList = MmHeapAlloc(Size);
+              if (!PartialResourceList)
+              {
+                  DPRINTM(DPRINT_HWDETECT,
+                            "Failed to allocate resource descriptor\n");
+                  return;
+              }
+
+              /* Initialize resource descriptor */
+              memset(PartialResourceList, 0, Size);
+              PartialResourceList->Version = 1;
+              PartialResourceList->Revision = 1;
+              PartialResourceList->Count = 1;
+              PartialDescriptor = &PartialResourceList->PartialDescriptors[0];
+              PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
+              PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
+              PartialDescriptor->u.DeviceSpecificData.DataSize = sizeof(PCI_REGISTRY_INFO);
+              memcpy(&PartialResourceList->PartialDescriptors[1],
+                     &BusData,
+                     sizeof(PCI_REGISTRY_INFO));
+          }
+          else
+          {
+              /* Set 'Configuration Data' value */
+              Size = FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST,
+                                  PartialDescriptors);
+              PartialResourceList = MmHeapAlloc(Size);
+              if (!PartialResourceList)
+              {
+                  DPRINTM(DPRINT_HWDETECT,
+                            "Failed to allocate resource descriptor\n");
+                  return;
+              }
+
+              /* Initialize resource descriptor */
+              memset(PartialResourceList, 0, Size);
+          }
+
+          /* Create the bus key */
+          FldrCreateComponentKey(SystemKey,
+                                 AdapterClass,
+                                 MultiFunctionAdapter,
+                                 0x0,
+                                 0x0,
+                                 0xFFFFFFFF,
+                                 "PCI",
+                                 PartialResourceList,
+                                 Size,
+                                 &BusKey);
+
+          MmHeapFree(PartialResourceList);
+
+          /* Increment bus number */
+          (*BusNumber)++;
+      }
     }
 }