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