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
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 typedef struct _ROUTING_SLOT
40 } __attribute__((packed
)) ROUTING_SLOT
, *PROUTING_SLOT
;
42 typedef struct _PCI_IRQ_ROUTING_TABLE
50 ULONG CompatibleRouter
;
55 } __attribute__((packed
)) PCI_IRQ_ROUTING_TABLE
, *PPCI_IRQ_ROUTING_TABLE
;
57 typedef struct _PCI_REGISTRY_INFO
62 UCHAR HardwareMechanism
;
63 } PCI_REGISTRY_INFO
, *PPCI_REGISTRY_INFO
;
65 static PPCI_IRQ_ROUTING_TABLE
66 GetPciIrqRoutingTable(VOID
)
68 PPCI_IRQ_ROUTING_TABLE Table
;
73 Table
= (PPCI_IRQ_ROUTING_TABLE
)0xF0000;
74 while ((ULONG_PTR
)Table
< 0x100000)
76 if (Table
->Signature
== 0x52495024)
78 DPRINTM(DPRINT_HWDETECT
,
83 for (i
= 0; i
< Table
->Size
; i
++)
88 if ((Sum
& 0xFF) != 0)
90 DPRINTM(DPRINT_HWDETECT
,
91 "Invalid routing table\n");
95 DPRINTM(DPRINT_HWDETECT
,
101 Table
= (PPCI_IRQ_ROUTING_TABLE
)((ULONG_PTR
)Table
+ 0x10);
109 FindPciBios(PPCI_REGISTRY_INFO BusData
)
114 RegsIn
.b
.ah
= 0xB1; /* Subfunction B1h */
115 RegsIn
.b
.al
= 0x01; /* PCI BIOS present */
117 Int386(0x1A, &RegsIn
, &RegsOut
);
119 if (INT386_SUCCESS(RegsOut
) && RegsOut
.d
.edx
== 0x20494350 && RegsOut
.b
.ah
== 0)
121 DPRINTM(DPRINT_HWDETECT
, "Found PCI bios\n");
123 DPRINTM(DPRINT_HWDETECT
, "AL: %x\n", RegsOut
.b
.al
);
124 DPRINTM(DPRINT_HWDETECT
, "BH: %x\n", RegsOut
.b
.bh
);
125 DPRINTM(DPRINT_HWDETECT
, "BL: %x\n", RegsOut
.b
.bl
);
126 DPRINTM(DPRINT_HWDETECT
, "CL: %x\n", RegsOut
.b
.cl
);
128 BusData
->NoBuses
= RegsOut
.b
.cl
+ 1;
129 BusData
->MajorRevision
= RegsOut
.b
.bh
;
130 BusData
->MinorRevision
= RegsOut
.b
.bl
;
131 BusData
->HardwareMechanism
= RegsOut
.b
.cl
;
137 DPRINTM(DPRINT_HWDETECT
, "No PCI bios found\n");
144 DetectPciIrqRoutingTable(PCONFIGURATION_COMPONENT_DATA BusKey
)
146 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
147 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
148 PPCI_IRQ_ROUTING_TABLE Table
;
149 PCONFIGURATION_COMPONENT_DATA TableKey
;
152 Table
= GetPciIrqRoutingTable();
155 DPRINTM(DPRINT_HWDETECT
, "Table size: %u\n", Table
->Size
);
157 /* Set 'Configuration Data' value */
158 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
, PartialDescriptors
) +
159 2 * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) + Table
->Size
;
160 PartialResourceList
= MmHeapAlloc(Size
);
161 if (PartialResourceList
== NULL
)
163 DPRINTM(DPRINT_HWDETECT
,
164 "Failed to allocate resource descriptor\n");
168 /* Initialize resource descriptor */
169 memset(PartialResourceList
, 0, Size
);
170 PartialResourceList
->Version
= 1;
171 PartialResourceList
->Revision
= 1;
172 PartialResourceList
->Count
= 2;
174 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
175 PartialDescriptor
->Type
= CmResourceTypeBusNumber
;
176 PartialDescriptor
->ShareDisposition
= CmResourceShareDeviceExclusive
;
177 PartialDescriptor
->u
.BusNumber
.Start
= 0;
178 PartialDescriptor
->u
.BusNumber
.Length
= 1;
180 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[1];
181 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
182 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
183 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= Table
->Size
;
185 memcpy(&PartialResourceList
->PartialDescriptors
[2],
188 FldrCreateComponentKey(BusKey
,
190 RealModeIrqRoutingTable
,
194 "PCI Real-mode IRQ Routing Table",
199 MmHeapFree(PartialResourceList
);
205 DetectPciBios(PCONFIGURATION_COMPONENT_DATA SystemKey
, ULONG
*BusNumber
)
207 PCM_PARTIAL_RESOURCE_LIST PartialResourceList
;
208 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor
;
209 PCI_REGISTRY_INFO BusData
;
210 PCONFIGURATION_COMPONENT_DATA BiosKey
;
212 PCONFIGURATION_COMPONENT_DATA BusKey
;
215 /* Report the PCI BIOS */
216 if (FindPciBios(&BusData
))
218 /* Set 'Configuration Data' value */
219 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
,
221 PartialResourceList
= MmHeapAlloc(Size
);
222 if (PartialResourceList
== NULL
)
224 DPRINTM(DPRINT_HWDETECT
,
225 "Failed to allocate resource descriptor\n");
229 /* Initialize resource descriptor */
230 memset(PartialResourceList
, 0, Size
);
232 /* Create new bus key */
233 FldrCreateComponentKey(SystemKey
,
235 MultiFunctionAdapter
,
244 /* Increment bus number */
247 MmHeapFree(PartialResourceList
);
249 DetectPciIrqRoutingTable(BiosKey
);
251 /* Report PCI buses */
252 for (i
= 0; i
< (ULONG
)BusData
.NoBuses
; i
++)
254 /* Check if this is the first bus */
257 /* Set 'Configuration Data' value */
258 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
,
259 PartialDescriptors
) +
260 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR
) +
261 sizeof(PCI_REGISTRY_INFO
);
262 PartialResourceList
= MmHeapAlloc(Size
);
263 if (!PartialResourceList
)
265 DPRINTM(DPRINT_HWDETECT
,
266 "Failed to allocate resource descriptor\n");
270 /* Initialize resource descriptor */
271 memset(PartialResourceList
, 0, Size
);
272 PartialResourceList
->Version
= 1;
273 PartialResourceList
->Revision
= 1;
274 PartialResourceList
->Count
= 1;
275 PartialDescriptor
= &PartialResourceList
->PartialDescriptors
[0];
276 PartialDescriptor
->Type
= CmResourceTypeDeviceSpecific
;
277 PartialDescriptor
->ShareDisposition
= CmResourceShareUndetermined
;
278 PartialDescriptor
->u
.DeviceSpecificData
.DataSize
= sizeof(PCI_REGISTRY_INFO
);
279 memcpy(&PartialResourceList
->PartialDescriptors
[1],
281 sizeof(PCI_REGISTRY_INFO
));
285 /* Set 'Configuration Data' value */
286 Size
= FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST
,
288 PartialResourceList
= MmHeapAlloc(Size
);
289 if (!PartialResourceList
)
291 DPRINTM(DPRINT_HWDETECT
,
292 "Failed to allocate resource descriptor\n");
296 /* Initialize resource descriptor */
297 memset(PartialResourceList
, 0, Size
);
300 /* Create the bus key */
301 FldrCreateComponentKey(SystemKey
,
303 MultiFunctionAdapter
,
312 MmHeapFree(PartialResourceList
);
314 /* Increment bus number */