4 * Copyright (C) 2004 Eric Kohl
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 typedef struct _ROUTING_SLOT
42 } ROUTING_SLOT
, *PROUTING_SLOT
;
44 typedef struct _PCI_IRQ_ROUTING_TABLE
52 ULONG CompatibleRouter
;
57 } PCI_IRQ_ROUTING_TABLE
, *PPCI_IRQ_ROUTING_TABLE
;
61 typedef struct _PCI_REGISTRY_INFO
66 UCHAR HardwareMechanism
;
67 } PCI_REGISTRY_INFO
, *PPCI_REGISTRY_INFO
;
69 static PPCI_IRQ_ROUTING_TABLE
70 GetPciIrqRoutingTable(VOID
)
72 PPCI_IRQ_ROUTING_TABLE Table
;
77 Table
= (PPCI_IRQ_ROUTING_TABLE
)0xF0000;
78 while ((ULONG_PTR
)Table
< 0x100000)
80 if (Table
->Signature
== 0x52495024)
82 DPRINTM(DPRINT_HWDETECT
,
87 for (i
= 0; i
< Table
->Size
; i
++)
92 if ((Sum
& 0xFF) != 0)
94 DPRINTM(DPRINT_HWDETECT
,
95 "Invalid routing table\n");
99 DPRINTM(DPRINT_HWDETECT
,
105 Table
= (PPCI_IRQ_ROUTING_TABLE
)((ULONG_PTR
)Table
+ 0x10);
113 FindPciBios(PPCI_REGISTRY_INFO BusData
)
118 RegsIn
.b
.ah
= 0xB1; /* Subfunction B1h */
119 RegsIn
.b
.al
= 0x01; /* PCI BIOS present */
121 Int386(0x1A, &RegsIn
, &RegsOut
);
123 if (INT386_SUCCESS(RegsOut
) && RegsOut
.d
.edx
== 0x20494350 && RegsOut
.b
.ah
== 0)
125 DPRINTM(DPRINT_HWDETECT
, "Found PCI bios\n");
127 DPRINTM(DPRINT_HWDETECT
, "AL: %x\n", RegsOut
.b
.al
);
128 DPRINTM(DPRINT_HWDETECT
, "BH: %x\n", RegsOut
.b
.bh
);
129 DPRINTM(DPRINT_HWDETECT
, "BL: %x\n", RegsOut
.b
.bl
);
130 DPRINTM(DPRINT_HWDETECT
, "CL: %x\n", RegsOut
.b
.cl
);
132 BusData
->NoBuses
= RegsOut
.b
.cl
+ 1;
133 BusData
->MajorRevision
= RegsOut
.b
.bh
;
134 BusData
->MinorRevision
= RegsOut
.b
.bl
;
135 BusData
->HardwareMechanism
= RegsOut
.b
.al
;
141 DPRINTM(DPRINT_HWDETECT
, "No PCI bios found\n");
148 DetectPciIrqRoutingTable(PCONFIGURATION_COMPONENT_DATA BusKey
)
150 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
151 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
152 PPCI_IRQ_ROUTING_TABLE Table
;
153 PCONFIGURATION_COMPONENT_DATA TableKey
;
156 Table
= GetPciIrqRoutingTable();
159 DPRINTM(DPRINT_HWDETECT
, "Table size: %u\n", Table
->Size
);
161 /* Set 'Configuration Data' value */
162 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
) +
163 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + Table
->Size
;
164 PartialResourceList
= MmHeapAlloc(Size
);
165 if (PartialResourceList
== NULL
)
167 DPRINTM(DPRINT_HWDETECT
,
168 "Failed to allocate resource descriptor\n");
172 /* Initialize resource descriptor */
173 memset(PartialResourceList
, 0, Size
);
174 PartialResourceList
->Version
= 1;
175 PartialResourceList
->Revision
= 1;
176 PartialResourceList
->Count
= 2;
178 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
179 PartialDescriptor
->Type
= CmResourceTypeBusNumber
;
180 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
181 PartialDescriptor
->u
.BusNumber
.Start
= 0;
182 PartialDescriptor
->u
.BusNumber
.Length
= 1;
184 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
185 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
186 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
187 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= Table
->Size
;
189 memcpy(&PartialResourceList
->PartialDescriptors
[2],
192 FldrCreateComponentKey(BusKey
,
194 RealModeIrqRoutingTable
,
198 "PCI Real-mode IRQ Routing Table",
203 MmHeapFree(PartialResourceList
);
209 DetectPciBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
211 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
212 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
213 PCI_REGISTRY_INFO BusData
;
214 PCONFIGURATION_COMPONENT_DATA BiosKey
;
216 PCONFIGURATION_COMPONENT_DATA BusKey
;
219 /* Report the PCI BIOS */
220 if (FindPciBios(&BusData
))
222 /* Set 'Configuration Data' value */
223 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
,
225 PartialResourceList
= MmHeapAlloc(Size
);
226 if (PartialResourceList
== NULL
)
228 DPRINTM(DPRINT_HWDETECT
,
229 "Failed to allocate resource descriptor\n");
233 /* Initialize resource descriptor */
234 memset(PartialResourceList
, 0, Size
);
236 /* Create new bus key */
237 FldrCreateComponentKey(SystemKey
,
239 MultiFunctionAdapter
,
248 /* Increment bus number */
251 MmHeapFree(PartialResourceList
);
253 DetectPciIrqRoutingTable(BiosKey
);
255 /* Report PCI buses */
256 for (i
= 0; i
< (ULONG
)BusData
.NoBuses
; i
++)
258 /* Check if this is the first bus */
261 /* Set 'Configuration Data' value */
262 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
,
263 PartialDescriptors
) +
264 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
265 sizeof(PCI_REGISTRY_INFO
);
266 PartialResourceList
= MmHeapAlloc(Size
);
267 if (!PartialResourceList
)
269 DPRINTM(DPRINT_HWDETECT
,
270 "Failed to allocate resource descriptor\n");
274 /* Initialize resource descriptor */
275 memset(PartialResourceList
, 0, Size
);
276 PartialResourceList
->Version
= 1;
277 PartialResourceList
->Revision
= 1;
278 PartialResourceList
->Count
= 1;
279 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
280 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
281 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
282 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(PCI_REGISTRY_INFO
);
283 memcpy(&PartialResourceList
->PartialDescriptors
[1],
285 sizeof(PCI_REGISTRY_INFO
));
289 /* Set 'Configuration Data' value */
290 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
,
292 PartialResourceList
= MmHeapAlloc(Size
);
293 if (!PartialResourceList
)
295 DPRINTM(DPRINT_HWDETECT
,
296 "Failed to allocate resource descriptor\n");
300 /* Initialize resource descriptor */
301 memset(PartialResourceList
, 0, Size
);
304 /* Create the bus key */
305 FldrCreateComponentKey(SystemKey
,
307 MultiFunctionAdapter
,
316 MmHeapFree(PartialResourceList
);
318 /* Increment bus number */