acac5dc21c7e518191b1550768bdd1351f6504d3
[reactos.git] / reactos / boot / freeldr / freeldr / arch / i386 / hwpci.c
1 /*
2 * FreeLoader
3 *
4 * Copyright (C) 2004 Eric Kohl
5 *
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.
10 *
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.
15 *
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.
19 */
20
21 #include <freeldr.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 typedef struct _ROUTING_SLOT
27 {
28 UCHAR BusNumber;
29 UCHAR DeviceNumber;
30 UCHAR LinkA;
31 USHORT BitmapA;
32 UCHAR LinkB;
33 USHORT BitmapB;
34 UCHAR LinkC;
35 USHORT BitmapC;
36 UCHAR LinkD;
37 USHORT BitmapD;
38 UCHAR SlotNumber;
39 UCHAR Reserved;
40 } __attribute__((packed)) ROUTING_SLOT, *PROUTING_SLOT;
41
42 typedef struct _PCI_IRQ_ROUTING_TABLE
43 {
44 ULONG Signature;
45 USHORT Version;
46 USHORT Size;
47 UCHAR RouterBus;
48 UCHAR RouterSlot;
49 USHORT ExclusiveIRQs;
50 ULONG CompatibleRouter;
51 ULONG MiniportData;
52 UCHAR Reserved[11];
53 UCHAR Checksum;
54 ROUTING_SLOT Slot[1];
55 } __attribute__((packed)) PCI_IRQ_ROUTING_TABLE, *PPCI_IRQ_ROUTING_TABLE;
56
57 typedef struct _CM_PCI_BUS_DATA
58 {
59 UCHAR BusCount;
60 USHORT PciVersion;
61 UCHAR HardwareMechanism;
62 } __attribute__((packed)) CM_PCI_BUS_DATA, *PCM_PCI_BUS_DATA;
63
64
65 static PPCI_IRQ_ROUTING_TABLE
66 GetPciIrqRoutingTable(VOID)
67 {
68 PPCI_IRQ_ROUTING_TABLE Table;
69 PUCHAR Ptr;
70 ULONG Sum;
71 ULONG i;
72
73 Table = (PPCI_IRQ_ROUTING_TABLE)0xF0000;
74 while ((ULONG)Table < 0x100000)
75 {
76 if (Table->Signature == 0x52495024)
77 {
78 DbgPrint((DPRINT_HWDETECT,
79 "Found signature\n"));
80
81 Ptr = (PUCHAR)Table;
82 Sum = 0;
83 for (i = 0; i < Table->Size; i++)
84 {
85 Sum += Ptr[i];
86 }
87
88 if ((Sum & 0xFF) != 0)
89 {
90 DbgPrint((DPRINT_HWDETECT,
91 "Invalid routing table\n"));
92 return NULL;
93 }
94
95 DbgPrint((DPRINT_HWDETECT,
96 "Valid checksum\n"));
97
98 return Table;
99 }
100
101 Table = (PPCI_IRQ_ROUTING_TABLE)((ULONG)Table + 0x10);
102 }
103
104 return NULL;
105 }
106
107
108 static BOOL
109 FindPciBios(PCM_PCI_BUS_DATA BusData)
110 {
111 REGS RegsIn;
112 REGS RegsOut;
113
114 RegsIn.b.ah = 0xB1; /* Subfunction B1h */
115 RegsIn.b.al = 0x01; /* PCI BIOS present */
116
117 Int386(0x1A, &RegsIn, &RegsOut);
118
119 if (INT386_SUCCESS(RegsOut) && RegsOut.d.edx == 0x20494350 && RegsOut.b.ah == 0)
120 {
121 DbgPrint((DPRINT_HWDETECT, "Found PCI bios\n"));
122
123 DbgPrint((DPRINT_HWDETECT, "AL: %x\n", RegsOut.b.al));
124 DbgPrint((DPRINT_HWDETECT, "BH: %x\n", RegsOut.b.bh));
125 DbgPrint((DPRINT_HWDETECT, "BL: %x\n", RegsOut.b.bl));
126 DbgPrint((DPRINT_HWDETECT, "CL: %x\n", RegsOut.b.cl));
127
128 BusData->BusCount = RegsOut.b.cl + 1;
129 BusData->PciVersion = RegsOut.w.bx;
130 BusData->HardwareMechanism = RegsOut.b.cl;
131
132 return TRUE;
133 }
134
135
136 DbgPrint((DPRINT_HWDETECT, "No PCI bios found\n"));
137
138 return FALSE;
139 }
140
141
142 static VOID
143 DetectPciIrqRoutingTable(FRLDRHKEY BusKey)
144 {
145 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
146 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
147 PPCI_IRQ_ROUTING_TABLE Table;
148 FRLDRHKEY TableKey;
149 ULONG Size;
150 LONG Error;
151
152 Table = GetPciIrqRoutingTable();
153 if (Table != NULL)
154 {
155 DbgPrint((DPRINT_HWDETECT, "Table size: %u\n", Table->Size));
156
157 Error = RegCreateKey(BusKey,
158 L"RealModeIrqRoutingTable\\0",
159 &TableKey);
160 if (Error != ERROR_SUCCESS)
161 {
162 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
163 return;
164 }
165
166 /* Set 'Component Information' */
167 SetComponentInformation(TableKey,
168 0x0,
169 0x0,
170 0xFFFFFFFF);
171
172 /* Set 'Identifier' value */
173 Error = RegSetValue(TableKey,
174 L"Identifier",
175 REG_SZ,
176 (PCHAR)L"PCI Real-mode IRQ Routing Table",
177 32 * sizeof(WCHAR));
178 if (Error != ERROR_SUCCESS)
179 {
180 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
181 return;
182 }
183
184 /* Set 'Configuration Data' value */
185 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) +
186 Table->Size;
187 FullResourceDescriptor = MmAllocateMemory(Size);
188 if (FullResourceDescriptor == NULL)
189 {
190 DbgPrint((DPRINT_HWDETECT,
191 "Failed to allocate resource descriptor\n"));
192 return;
193 }
194
195 /* Initialize resource descriptor */
196 memset(FullResourceDescriptor, 0, Size);
197 FullResourceDescriptor->InterfaceType = Isa;
198 FullResourceDescriptor->BusNumber = 0;
199 FullResourceDescriptor->PartialResourceList.Count = 1;
200
201 PartialDescriptor = &FullResourceDescriptor->PartialResourceList.PartialDescriptors[0];
202 PartialDescriptor->Type = CmResourceTypeDeviceSpecific;
203 PartialDescriptor->ShareDisposition = CmResourceShareUndetermined;
204 PartialDescriptor->u.DeviceSpecificData.DataSize = Table->Size;
205
206 memcpy((PVOID)((ULONG_PTR)FullResourceDescriptor + sizeof(CM_FULL_RESOURCE_DESCRIPTOR)),
207 Table,
208 Table->Size);
209
210 /* Set 'Configuration Data' value */
211 Error = RegSetValue(TableKey,
212 L"Configuration Data",
213 REG_FULL_RESOURCE_DESCRIPTOR,
214 (PCHAR) FullResourceDescriptor,
215 Size);
216 MmFreeMemory(FullResourceDescriptor);
217 if (Error != ERROR_SUCCESS)
218 {
219 DbgPrint((DPRINT_HWDETECT,
220 "RegSetValue(Configuration Data) failed (Error %u)\n",
221 (int)Error));
222 return;
223 }
224 }
225 }
226
227
228 VOID
229 DetectPciBios(FRLDRHKEY SystemKey, ULONG *BusNumber)
230 {
231 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
232 CM_PCI_BUS_DATA BusData;
233 WCHAR Buffer[80];
234 FRLDRHKEY BiosKey;
235 ULONG Size;
236 LONG Error;
237 #if 0
238 FRLDRHKEY BusKey;
239 ULONG i;
240 WCHAR szPci[] = L"PCI";
241 #endif
242
243 /* Report the PCI BIOS */
244 if (FindPciBios(&BusData))
245 {
246 /* Create new bus key */
247 swprintf(Buffer,
248 L"MultifunctionAdapter\\%u", *BusNumber);
249 Error = RegCreateKey(SystemKey,
250 Buffer,
251 &BiosKey);
252 if (Error != ERROR_SUCCESS)
253 {
254 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
255 return;
256 }
257
258 /* Set 'Component Information' */
259 SetComponentInformation(BiosKey,
260 0x0,
261 0x0,
262 0xFFFFFFFF);
263
264 /* Increment bus number */
265 (*BusNumber)++;
266
267 /* Set 'Identifier' value */
268 Error = RegSetValue(BiosKey,
269 L"Identifier",
270 REG_SZ,
271 (PCHAR)L"PCI BIOS",
272 9 * sizeof(WCHAR));
273 if (Error != ERROR_SUCCESS)
274 {
275 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
276 return;
277 }
278
279 /* Set 'Configuration Data' value */
280 Size = sizeof(CM_FULL_RESOURCE_DESCRIPTOR) -
281 sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
282 FullResourceDescriptor = MmAllocateMemory(Size);
283 if (FullResourceDescriptor == NULL)
284 {
285 DbgPrint((DPRINT_HWDETECT,
286 "Failed to allocate resource descriptor\n"));
287 return;
288 }
289
290 /* Initialize resource descriptor */
291 memset(FullResourceDescriptor, 0, Size);
292 FullResourceDescriptor->InterfaceType = PCIBus;
293 FullResourceDescriptor->BusNumber = 0;
294 FullResourceDescriptor->PartialResourceList.Count = 0;
295
296 /* Set 'Configuration Data' value */
297 Error = RegSetValue(BiosKey,
298 L"Configuration Data",
299 REG_FULL_RESOURCE_DESCRIPTOR,
300 (PCHAR) FullResourceDescriptor,
301 Size);
302 MmFreeMemory(FullResourceDescriptor);
303 if (Error != ERROR_SUCCESS)
304 {
305 DbgPrint((DPRINT_HWDETECT,
306 "RegSetValue(Configuration Data) failed (Error %u)\n",
307 (int)Error));
308 return;
309 }
310
311 DetectPciIrqRoutingTable(BiosKey);
312
313 #if 0
314 /*
315 * FIXME:
316 * Enabling this piece of code will corrupt the boot sequence!
317 * This is probably caused by a bug in the registry code!
318 */
319
320 /* Report PCI buses */
321 for (i = 0; i < (ULONG)BusData.BusCount; i++)
322 {
323 swprintf(Buffer,
324 L"MultifunctionAdapter\\%u", *BusNumber);
325 Error = RegCreateKey(SystemKey,
326 Buffer,
327 &BusKey);
328 if (Error != ERROR_SUCCESS)
329 {
330 DbgPrint((DPRINT_HWDETECT, "RegCreateKey() failed (Error %u)\n", (int)Error));
331 printf("RegCreateKey() failed (Error %u)\n", (int)Error);
332 return;
333 }
334
335 /* Set 'Component Information' */
336 SetComponentInformation(BusKey,
337 0x0,
338 0x0,
339 0xFFFFFFFF);
340
341 /* Increment bus number */
342 (*BusNumber)++;
343
344
345 /* Set 'Identifier' value */
346 Error = RegSetValue(BusKey,
347 L"Identifier",
348 REG_SZ,
349 (PCSTR)szPci,
350 sizeof(szPci));
351 if (Error != ERROR_SUCCESS)
352 {
353 DbgPrint((DPRINT_HWDETECT, "RegSetValue() failed (Error %u)\n", (int)Error));
354 return;
355 }
356 }
357 #endif
358
359 }
360 }
361
362 /* EOF */