[NTOS:KE/x64] Handle NMI vs swapgs race condition
[reactos.git] / hal / halx86 / legacy / bus / pcibus.c
1 /*
2 * PROJECT: ReactOS HAL
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: hal/halx86/legacy/bus/pcibus.c
5 * PURPOSE: PCI Bus Support (Configuration Space, Resource Allocation)
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* GLOBALS *******************************************************************/
16
17 extern BOOLEAN HalpPciLockSettings;
18 ULONG HalpBusType;
19
20 BOOLEAN HalpPCIConfigInitialized;
21 ULONG HalpMinPciBus, HalpMaxPciBus;
22 KSPIN_LOCK HalpPCIConfigLock;
23 PCI_CONFIG_HANDLER PCIConfigHandler;
24
25 /* PCI Operation Matrix */
26 UCHAR PCIDeref[4][4] =
27 {
28 {0, 1, 2, 2}, // ULONG-aligned offset
29 {1, 1, 1, 1}, // UCHAR-aligned offset
30 {2, 1, 2, 2}, // USHORT-aligned offset
31 {1, 1, 1, 1} // UCHAR-aligned offset
32 };
33
34 /* Type 1 PCI Bus */
35 PCI_CONFIG_HANDLER PCIConfigHandlerType1 =
36 {
37 /* Synchronization */
38 (FncSync)HalpPCISynchronizeType1,
39 (FncReleaseSync)HalpPCIReleaseSynchronzationType1,
40
41 /* Read */
42 {
43 (FncConfigIO)HalpPCIReadUlongType1,
44 (FncConfigIO)HalpPCIReadUcharType1,
45 (FncConfigIO)HalpPCIReadUshortType1
46 },
47
48 /* Write */
49 {
50 (FncConfigIO)HalpPCIWriteUlongType1,
51 (FncConfigIO)HalpPCIWriteUcharType1,
52 (FncConfigIO)HalpPCIWriteUshortType1
53 }
54 };
55
56 /* Type 2 PCI Bus */
57 PCI_CONFIG_HANDLER PCIConfigHandlerType2 =
58 {
59 /* Synchronization */
60 (FncSync)HalpPCISynchronizeType2,
61 (FncReleaseSync)HalpPCIReleaseSynchronizationType2,
62
63 /* Read */
64 {
65 (FncConfigIO)HalpPCIReadUlongType2,
66 (FncConfigIO)HalpPCIReadUcharType2,
67 (FncConfigIO)HalpPCIReadUshortType2
68 },
69
70 /* Write */
71 {
72 (FncConfigIO)HalpPCIWriteUlongType2,
73 (FncConfigIO)HalpPCIWriteUcharType2,
74 (FncConfigIO)HalpPCIWriteUshortType2
75 }
76 };
77
78 PCIPBUSDATA HalpFakePciBusData =
79 {
80 {
81 PCI_DATA_TAG,
82 PCI_DATA_VERSION,
83 HalpReadPCIConfig,
84 HalpWritePCIConfig,
85 NULL,
86 NULL,
87 {{{0, 0, 0}}},
88 {0, 0, 0, 0}
89 },
90 {{0, 0}},
91 32,
92 };
93
94 BUS_HANDLER HalpFakePciBusHandler =
95 {
96 1,
97 PCIBus,
98 PCIConfiguration,
99 0,
100 NULL,
101 NULL,
102 &HalpFakePciBusData,
103 0,
104 NULL,
105 {0, 0, 0, 0},
106 (PGETSETBUSDATA)HalpGetPCIData,
107 (PGETSETBUSDATA)HalpSetPCIData,
108 NULL,
109 HalpAssignPCISlotResources,
110 NULL,
111 NULL
112 };
113
114 /* TYPE 1 FUNCTIONS **********************************************************/
115
116 VOID
117 NTAPI
118 HalpPCISynchronizeType1(IN PBUS_HANDLER BusHandler,
119 IN PCI_SLOT_NUMBER Slot,
120 OUT PKIRQL OldIrql,
121 OUT PPCI_TYPE1_CFG_BITS PciCfg1)
122 {
123 /* Setup the PCI Configuration Register */
124 PciCfg1->u.AsULONG = 0;
125 PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
126 PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
127 PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
128 PciCfg1->u.bits.Enable = TRUE;
129
130 /* Acquire the lock */
131 KeRaiseIrql(HIGH_LEVEL, OldIrql);
132 KeAcquireSpinLockAtDpcLevel(&HalpPCIConfigLock);
133 }
134
135 VOID
136 NTAPI
137 HalpPCIReleaseSynchronzationType1(IN PBUS_HANDLER BusHandler,
138 IN KIRQL OldIrql)
139 {
140 PCI_TYPE1_CFG_BITS PciCfg1;
141
142 /* Clear the PCI Configuration Register */
143 PciCfg1.u.AsULONG = 0;
144 WRITE_PORT_ULONG(((PPCIPBUSDATA)BusHandler->BusData)->Config.Type1.Address,
145 PciCfg1.u.AsULONG);
146
147 /* Release the lock */
148 KeReleaseSpinLock(&HalpPCIConfigLock, OldIrql);
149 }
150
151 TYPE1_READ(HalpPCIReadUcharType1, UCHAR)
152 TYPE1_READ(HalpPCIReadUshortType1, USHORT)
153 TYPE1_READ(HalpPCIReadUlongType1, ULONG)
154 TYPE1_WRITE(HalpPCIWriteUcharType1, UCHAR)
155 TYPE1_WRITE(HalpPCIWriteUshortType1, USHORT)
156 TYPE1_WRITE(HalpPCIWriteUlongType1, ULONG)
157
158 /* TYPE 2 FUNCTIONS **********************************************************/
159
160 VOID
161 NTAPI
162 HalpPCISynchronizeType2(IN PBUS_HANDLER BusHandler,
163 IN PCI_SLOT_NUMBER Slot,
164 OUT PKIRQL OldIrql,
165 OUT PPCI_TYPE2_ADDRESS_BITS PciCfg)
166 {
167 PCI_TYPE2_CSE_BITS PciCfg2Cse;
168 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
169
170 /* Setup the configuration register */
171 PciCfg->u.AsUSHORT = 0;
172 PciCfg->u.bits.Agent = (USHORT)Slot.u.bits.DeviceNumber;
173 PciCfg->u.bits.AddressBase = (USHORT)BusData->Config.Type2.Base;
174
175 /* Acquire the lock */
176 KeRaiseIrql(HIGH_LEVEL, OldIrql);
177 KeAcquireSpinLockAtDpcLevel(&HalpPCIConfigLock);
178
179 /* Setup the CSE Register */
180 PciCfg2Cse.u.AsUCHAR = 0;
181 PciCfg2Cse.u.bits.Enable = TRUE;
182 PciCfg2Cse.u.bits.FunctionNumber = (UCHAR)Slot.u.bits.FunctionNumber;
183 PciCfg2Cse.u.bits.Key = -1;
184
185 /* Write the bus number and CSE */
186 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward,
187 (UCHAR)BusHandler->BusNumber);
188 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
189 }
190
191 VOID
192 NTAPI
193 HalpPCIReleaseSynchronizationType2(IN PBUS_HANDLER BusHandler,
194 IN KIRQL OldIrql)
195 {
196 PCI_TYPE2_CSE_BITS PciCfg2Cse;
197 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
198
199 /* Clear CSE and bus number */
200 PciCfg2Cse.u.AsUCHAR = 0;
201 WRITE_PORT_UCHAR(BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
202 WRITE_PORT_UCHAR(BusData->Config.Type2.Forward, 0);
203
204 /* Release the lock */
205 KeReleaseSpinLock(&HalpPCIConfigLock, OldIrql);
206 }
207
208 TYPE2_READ(HalpPCIReadUcharType2, UCHAR)
209 TYPE2_READ(HalpPCIReadUshortType2, USHORT)
210 TYPE2_READ(HalpPCIReadUlongType2, ULONG)
211 TYPE2_WRITE(HalpPCIWriteUcharType2, UCHAR)
212 TYPE2_WRITE(HalpPCIWriteUshortType2, USHORT)
213 TYPE2_WRITE(HalpPCIWriteUlongType2, ULONG)
214
215 /* PCI CONFIGURATION SPACE ***************************************************/
216
217 VOID
218 NTAPI
219 HalpPCIConfig(IN PBUS_HANDLER BusHandler,
220 IN PCI_SLOT_NUMBER Slot,
221 IN PUCHAR Buffer,
222 IN ULONG Offset,
223 IN ULONG Length,
224 IN FncConfigIO *ConfigIO)
225 {
226 KIRQL OldIrql;
227 ULONG i;
228 UCHAR State[20];
229
230 /* Synchronize the operation */
231 PCIConfigHandler.Synchronize(BusHandler, Slot, &OldIrql, State);
232
233 /* Loop every increment */
234 while (Length)
235 {
236 /* Find out the type of read/write we need to do */
237 i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
238
239 /* Do the read/write and return the number of bytes */
240 i = ConfigIO[i]((PPCIPBUSDATA)BusHandler->BusData,
241 State,
242 Buffer,
243 Offset);
244
245 /* Increment the buffer position and offset, and decrease the length */
246 Offset += i;
247 Buffer += i;
248 Length -= i;
249 }
250
251 /* Release the lock and PCI bus */
252 PCIConfigHandler.ReleaseSynchronzation(BusHandler, OldIrql);
253 }
254
255 VOID
256 NTAPI
257 HalpReadPCIConfig(IN PBUS_HANDLER BusHandler,
258 IN PCI_SLOT_NUMBER Slot,
259 IN PVOID Buffer,
260 IN ULONG Offset,
261 IN ULONG Length)
262 {
263 /* Validate the PCI Slot */
264 if (!HalpValidPCISlot(BusHandler, Slot))
265 {
266 /* Fill the buffer with invalid data */
267 RtlFillMemory(Buffer, Length, -1);
268 }
269 else
270 {
271 /* Send the request */
272 HalpPCIConfig(BusHandler,
273 Slot,
274 Buffer,
275 Offset,
276 Length,
277 PCIConfigHandler.ConfigRead);
278 }
279 }
280
281 VOID
282 NTAPI
283 HalpWritePCIConfig(IN PBUS_HANDLER BusHandler,
284 IN PCI_SLOT_NUMBER Slot,
285 IN PVOID Buffer,
286 IN ULONG Offset,
287 IN ULONG Length)
288 {
289 /* Validate the PCI Slot */
290 if (HalpValidPCISlot(BusHandler, Slot))
291 {
292 /* Send the request */
293 HalpPCIConfig(BusHandler,
294 Slot,
295 Buffer,
296 Offset,
297 Length,
298 PCIConfigHandler.ConfigWrite);
299 }
300 }
301
302 #ifdef SARCH_XBOX
303 static
304 BOOLEAN
305 HalpXboxBlacklistedPCISlot(
306 _In_ ULONG BusNumber,
307 _In_ PCI_SLOT_NUMBER Slot)
308 {
309 /* Trying to get PCI config data from devices 0:0:1 and 0:0:2 will completely
310 * hang the Xbox. Also, the device number doesn't seem to be decoded for the
311 * video card, so it appears to be present on 1:0:0 - 1:31:0.
312 * We hack around these problems by indicating "device not present" for devices
313 * 0:0:1, 0:0:2, 1:1:0, 1:2:0, 1:3:0, ...., 1:31:0 */
314 if ((BusNumber == 0 && Slot.u.bits.DeviceNumber == 0 &&
315 (Slot.u.bits.FunctionNumber == 1 || Slot.u.bits.FunctionNumber == 2)) ||
316 (BusNumber == 1 && Slot.u.bits.DeviceNumber != 0))
317 {
318 DPRINT("Blacklisted PCI slot (%d:%d:%d)\n",
319 BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
320 return TRUE;
321 }
322
323 return FALSE;
324 }
325 #endif
326
327 BOOLEAN
328 NTAPI
329 HalpValidPCISlot(IN PBUS_HANDLER BusHandler,
330 IN PCI_SLOT_NUMBER Slot)
331 {
332 PCI_SLOT_NUMBER MultiSlot;
333 PPCIPBUSDATA BusData = (PPCIPBUSDATA)BusHandler->BusData;
334 UCHAR HeaderType;
335 //ULONG Device;
336
337 /* Simple validation */
338 if (Slot.u.bits.Reserved) return FALSE;
339 if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) return FALSE;
340
341 #ifdef SARCH_XBOX
342 if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot))
343 return FALSE;
344 #endif
345
346 /* Function 0 doesn't need checking */
347 if (!Slot.u.bits.FunctionNumber) return TRUE;
348
349 /* Functions 0+ need Multi-Function support, so check the slot */
350 //Device = Slot.u.bits.DeviceNumber;
351 MultiSlot = Slot;
352 MultiSlot.u.bits.FunctionNumber = 0;
353
354 /* Send function 0 request to get the header back */
355 HalpReadPCIConfig(BusHandler,
356 MultiSlot,
357 &HeaderType,
358 FIELD_OFFSET(PCI_COMMON_CONFIG, HeaderType),
359 sizeof(UCHAR));
360
361 /* Now make sure the header is multi-function */
362 if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) return FALSE;
363 return TRUE;
364 }
365
366 CODE_SEG("INIT")
367 ULONG
368 HalpPhase0GetPciDataByOffset(
369 _In_ ULONG Bus,
370 _In_ PCI_SLOT_NUMBER PciSlot,
371 _Out_writes_bytes_all_(Length) PVOID Buffer,
372 _In_ ULONG Offset,
373 _In_ ULONG Length)
374 {
375 ULONG BytesLeft = Length;
376 PUCHAR BufferPtr = Buffer;
377 PCI_TYPE1_CFG_BITS PciCfg;
378
379 #ifdef SARCH_XBOX
380 if (HalpXboxBlacklistedPCISlot(Bus, PciSlot))
381 {
382 RtlFillMemory(Buffer, Length, 0xFF);
383 return Length;
384 }
385 #endif
386
387 PciCfg.u.AsULONG = 0;
388 PciCfg.u.bits.BusNumber = Bus;
389 PciCfg.u.bits.DeviceNumber = PciSlot.u.bits.DeviceNumber;
390 PciCfg.u.bits.FunctionNumber = PciSlot.u.bits.FunctionNumber;
391 PciCfg.u.bits.Enable = TRUE;
392
393 while (BytesLeft)
394 {
395 ULONG i;
396
397 PciCfg.u.bits.RegisterNumber = Offset / sizeof(ULONG);
398 WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDRESS_PORT, PciCfg.u.AsULONG);
399
400 i = PCIDeref[Offset % sizeof(ULONG)][BytesLeft % sizeof(ULONG)];
401 switch (i)
402 {
403 case 0:
404 {
405 *(PULONG)BufferPtr = READ_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT);
406
407 /* Number of bytes read */
408 i = sizeof(ULONG);
409 break;
410 }
411 case 1:
412 {
413 *BufferPtr = READ_PORT_UCHAR((PUCHAR)(PCI_TYPE1_DATA_PORT +
414 Offset % sizeof(ULONG)));
415 break;
416 }
417 case 2:
418 {
419 *(PUSHORT)BufferPtr = READ_PORT_USHORT((PUSHORT)(PCI_TYPE1_DATA_PORT +
420 Offset % sizeof(ULONG)));
421 break;
422 }
423
424 DEFAULT_UNREACHABLE;
425 }
426
427 Offset += i;
428 BufferPtr += i;
429 BytesLeft -= i;
430 }
431
432 return Length;
433 }
434
435 CODE_SEG("INIT")
436 ULONG
437 HalpPhase0SetPciDataByOffset(
438 _In_ ULONG Bus,
439 _In_ PCI_SLOT_NUMBER PciSlot,
440 _In_reads_bytes_(Length) PVOID Buffer,
441 _In_ ULONG Offset,
442 _In_ ULONG Length)
443 {
444 ULONG BytesLeft = Length;
445 PUCHAR BufferPtr = Buffer;
446 PCI_TYPE1_CFG_BITS PciCfg;
447
448 #ifdef SARCH_XBOX
449 if (HalpXboxBlacklistedPCISlot(Bus, PciSlot))
450 {
451 return 0;
452 }
453 #endif
454
455 PciCfg.u.AsULONG = 0;
456 PciCfg.u.bits.BusNumber = Bus;
457 PciCfg.u.bits.DeviceNumber = PciSlot.u.bits.DeviceNumber;
458 PciCfg.u.bits.FunctionNumber = PciSlot.u.bits.FunctionNumber;
459 PciCfg.u.bits.Enable = TRUE;
460
461 while (BytesLeft)
462 {
463 ULONG i;
464
465 PciCfg.u.bits.RegisterNumber = Offset / sizeof(ULONG);
466 WRITE_PORT_ULONG((PULONG)PCI_TYPE1_ADDRESS_PORT, PciCfg.u.AsULONG);
467
468 i = PCIDeref[Offset % sizeof(ULONG)][BytesLeft % sizeof(ULONG)];
469 switch (i)
470 {
471 case 0:
472 {
473 WRITE_PORT_ULONG((PULONG)PCI_TYPE1_DATA_PORT, *(PULONG)BufferPtr);
474
475 /* Number of bytes written */
476 i = sizeof(ULONG);
477 break;
478 }
479 case 1:
480 {
481 WRITE_PORT_UCHAR((PUCHAR)(PCI_TYPE1_DATA_PORT + Offset % sizeof(ULONG)),
482 *BufferPtr);
483 break;
484 }
485 case 2:
486 {
487 WRITE_PORT_USHORT((PUSHORT)(PCI_TYPE1_DATA_PORT + Offset % sizeof(ULONG)),
488 *(PUSHORT)BufferPtr);
489 break;
490 }
491
492 DEFAULT_UNREACHABLE;
493 }
494
495 Offset += i;
496 BufferPtr += i;
497 BytesLeft -= i;
498 }
499
500 return Length;
501 }
502
503 /* HAL PCI CALLBACKS *********************************************************/
504
505 ULONG
506 NTAPI
507 HalpGetPCIData(IN PBUS_HANDLER BusHandler,
508 IN PBUS_HANDLER RootHandler,
509 IN ULONG SlotNumber,
510 IN PVOID Buffer,
511 IN ULONG Offset,
512 IN ULONG Length)
513 {
514 PCI_SLOT_NUMBER Slot;
515 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH];
516 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer;
517 ULONG Len = 0;
518
519 Slot.u.AsULONG = SlotNumber;
520 #ifdef SARCH_XBOX
521 if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot))
522 {
523 RtlFillMemory(Buffer, Length, 0xFF);
524 return Length;
525 }
526 #endif
527
528 /* Normalize the length */
529 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG);
530
531 /* Check if this is a vendor-specific read */
532 if (Offset >= PCI_COMMON_HDR_LENGTH)
533 {
534 /* Read the header */
535 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG));
536
537 /* Make sure the vendor is valid */
538 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
539 }
540 else
541 {
542 /* Read the entire header */
543 Len = PCI_COMMON_HDR_LENGTH;
544 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len);
545
546 /* Validate the vendor ID */
547 if (PciConfig->VendorID == PCI_INVALID_VENDORID)
548 {
549 /* It's invalid, but we want to return this much */
550 Len = sizeof(USHORT);
551 }
552
553 /* Now check if there's space left */
554 if (Len < Offset) return 0;
555
556 /* There is, so return what's after the offset and normalize */
557 Len -= Offset;
558 if (Len > Length) Len = Length;
559
560 /* Copy the data into the caller's buffer */
561 RtlMoveMemory(Buffer, PciBuffer + Offset, Len);
562
563 /* Update buffer and offset, decrement total length */
564 Offset += Len;
565 Buffer = (PVOID)((ULONG_PTR)Buffer + Len);
566 Length -= Len;
567 }
568
569 /* Now we still have something to copy */
570 if (Length)
571 {
572 /* Check if it's vendor-specific data */
573 if (Offset >= PCI_COMMON_HDR_LENGTH)
574 {
575 /* Read it now */
576 HalpReadPCIConfig(BusHandler, Slot, Buffer, Offset, Length);
577 Len += Length;
578 }
579 }
580
581 /* Update the total length read */
582 return Len;
583 }
584
585 ULONG
586 NTAPI
587 HalpSetPCIData(IN PBUS_HANDLER BusHandler,
588 IN PBUS_HANDLER RootHandler,
589 IN ULONG SlotNumber,
590 IN PVOID Buffer,
591 IN ULONG Offset,
592 IN ULONG Length)
593 {
594 PCI_SLOT_NUMBER Slot;
595 UCHAR PciBuffer[PCI_COMMON_HDR_LENGTH];
596 PPCI_COMMON_CONFIG PciConfig = (PPCI_COMMON_CONFIG)PciBuffer;
597 ULONG Len = 0;
598
599 Slot.u.AsULONG = SlotNumber;
600 #ifdef SARCH_XBOX
601 if (HalpXboxBlacklistedPCISlot(BusHandler->BusNumber, Slot))
602 return 0;
603 #endif
604
605 /* Normalize the length */
606 if (Length > sizeof(PCI_COMMON_CONFIG)) Length = sizeof(PCI_COMMON_CONFIG);
607
608 /* Check if this is a vendor-specific read */
609 if (Offset >= PCI_COMMON_HDR_LENGTH)
610 {
611 /* Read the header */
612 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, sizeof(ULONG));
613
614 /* Make sure the vendor is valid */
615 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
616 }
617 else
618 {
619 /* Read the entire header and validate the vendor ID */
620 Len = PCI_COMMON_HDR_LENGTH;
621 HalpReadPCIConfig(BusHandler, Slot, PciConfig, 0, Len);
622 if (PciConfig->VendorID == PCI_INVALID_VENDORID) return 0;
623
624 /* Return what's after the offset and normalize */
625 Len -= Offset;
626 if (Len > Length) Len = Length;
627
628 /* Copy the specific caller data */
629 RtlMoveMemory(PciBuffer + Offset, Buffer, Len);
630
631 /* Write the actual configuration data */
632 HalpWritePCIConfig(BusHandler, Slot, PciBuffer + Offset, Offset, Len);
633
634 /* Update buffer and offset, decrement total length */
635 Offset += Len;
636 Buffer = (PVOID)((ULONG_PTR)Buffer + Len);
637 Length -= Len;
638 }
639
640 /* Now we still have something to copy */
641 if (Length)
642 {
643 /* Check if it's vendor-specific data */
644 if (Offset >= PCI_COMMON_HDR_LENGTH)
645 {
646 /* Read it now */
647 HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length);
648 Len += Length;
649 }
650 }
651
652 /* Update the total length read */
653 return Len;
654 }
655 #ifndef _MINIHAL_
656 ULONG
657 NTAPI
658 HalpGetPCIIntOnISABus(IN PBUS_HANDLER BusHandler,
659 IN PBUS_HANDLER RootHandler,
660 IN ULONG BusInterruptLevel,
661 IN ULONG BusInterruptVector,
662 OUT PKIRQL Irql,
663 OUT PKAFFINITY Affinity)
664 {
665 /* Validate the level first */
666 if (BusInterruptLevel < 1) return 0;
667
668 /* PCI has its IRQs on top of ISA IRQs, so pass it on to the ISA handler */
669 return HalGetInterruptVector(Isa,
670 0,
671 BusInterruptLevel,
672 0,
673 Irql,
674 Affinity);
675 }
676 #endif // _MINIHAL_
677
678 VOID
679 NTAPI
680 HalpPCIPin2ISALine(IN PBUS_HANDLER BusHandler,
681 IN PBUS_HANDLER RootHandler,
682 IN PCI_SLOT_NUMBER SlotNumber,
683 IN PPCI_COMMON_CONFIG PciData)
684 {
685 UNIMPLEMENTED_DBGBREAK();
686 }
687
688 VOID
689 NTAPI
690 HalpPCIISALine2Pin(IN PBUS_HANDLER BusHandler,
691 IN PBUS_HANDLER RootHandler,
692 IN PCI_SLOT_NUMBER SlotNumber,
693 IN PPCI_COMMON_CONFIG PciNewData,
694 IN PPCI_COMMON_CONFIG PciOldData)
695 {
696 UNIMPLEMENTED_DBGBREAK();
697 }
698
699 #ifndef _MINIHAL_
700 NTSTATUS
701 NTAPI
702 HalpGetISAFixedPCIIrq(IN PBUS_HANDLER BusHandler,
703 IN PBUS_HANDLER RootHandler,
704 IN PCI_SLOT_NUMBER PciSlot,
705 OUT PSUPPORTED_RANGE *Range)
706 {
707 PCI_COMMON_HEADER PciData;
708
709 /* Read PCI configuration data */
710 HalGetBusData(PCIConfiguration,
711 BusHandler->BusNumber,
712 PciSlot.u.AsULONG,
713 &PciData,
714 PCI_COMMON_HDR_LENGTH);
715
716 /* Make sure it's a real device */
717 if (PciData.VendorID == PCI_INVALID_VENDORID) return STATUS_UNSUCCESSFUL;
718
719 /* Allocate the supported range structure */
720 *Range = ExAllocatePoolWithTag(PagedPool, sizeof(SUPPORTED_RANGE), TAG_HAL);
721 if (!*Range) return STATUS_INSUFFICIENT_RESOURCES;
722
723 /* Set it up */
724 RtlZeroMemory(*Range, sizeof(SUPPORTED_RANGE));
725 (*Range)->Base = 1;
726
727 /* If the PCI device has no IRQ, nothing to do */
728 if (!PciData.u.type0.InterruptPin) return STATUS_SUCCESS;
729
730 /* FIXME: The PCI IRQ Routing Miniport should be called */
731
732 /* Also if the INT# seems bogus, nothing to do either */
733 if ((PciData.u.type0.InterruptLine == 0) ||
734 (PciData.u.type0.InterruptLine == 255))
735 {
736 /* Fake success */
737 return STATUS_SUCCESS;
738 }
739
740 /* Otherwise, the INT# should be valid, return it to the caller */
741 (*Range)->Base = PciData.u.type0.InterruptLine;
742 (*Range)->Limit = PciData.u.type0.InterruptLine;
743 return STATUS_SUCCESS;
744 }
745 #endif // _MINIHAL_
746
747 static ULONG NTAPI
748 PciSize(ULONG Base, ULONG Mask)
749 {
750 ULONG Size = Mask & Base; /* Find the significant bits */
751 Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */
752 return Size;
753 }
754
755 NTSTATUS
756 NTAPI
757 HalpAdjustPCIResourceList(IN PBUS_HANDLER BusHandler,
758 IN PBUS_HANDLER RootHandler,
759 IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList)
760 {
761 PPCIPBUSDATA BusData;
762 PCI_SLOT_NUMBER SlotNumber;
763 PSUPPORTED_RANGE Interrupt;
764 NTSTATUS Status;
765
766 /* Get PCI bus data */
767 BusData = BusHandler->BusData;
768 SlotNumber.u.AsULONG = (*pResourceList)->SlotNumber;
769
770 /* Get the IRQ supported range */
771 Status = BusData->GetIrqRange(BusHandler, RootHandler, SlotNumber, &Interrupt);
772 if (!NT_SUCCESS(Status)) return Status;
773 #ifndef _MINIHAL_
774 /* Handle the /PCILOCK feature */
775 if (HalpPciLockSettings)
776 {
777 /* /PCILOCK is not yet supported */
778 UNIMPLEMENTED_DBGBREAK("/PCILOCK boot switch is not yet supported.");
779 }
780 #endif
781 /* Now create the correct resource list based on the supported bus ranges */
782 #if 0
783 Status = HaliAdjustResourceListRange(BusHandler->BusAddresses,
784 Interrupt,
785 pResourceList);
786 #else
787 DPRINT1("HAL: No PCI Resource Adjustment done! Hardware may malfunction\n");
788 Status = STATUS_SUCCESS;
789 #endif
790
791 /* Return to caller */
792 ExFreePool(Interrupt);
793 return Status;
794 }
795
796 NTSTATUS
797 NTAPI
798 HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler,
799 IN PBUS_HANDLER RootHandler,
800 IN PUNICODE_STRING RegistryPath,
801 IN PUNICODE_STRING DriverClassName OPTIONAL,
802 IN PDRIVER_OBJECT DriverObject,
803 IN PDEVICE_OBJECT DeviceObject OPTIONAL,
804 IN ULONG Slot,
805 IN OUT PCM_RESOURCE_LIST *AllocatedResources)
806 {
807 PCI_COMMON_CONFIG PciConfig;
808 SIZE_T Address;
809 ULONG ResourceCount;
810 ULONG Size[PCI_TYPE0_ADDRESSES];
811 NTSTATUS Status = STATUS_SUCCESS;
812 UCHAR Offset;
813 PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
814 PCI_SLOT_NUMBER SlotNumber;
815 ULONG WriteBuffer;
816 DPRINT1("WARNING: PCI Slot Resource Assignment is FOOBAR\n");
817
818 /* FIXME: Should handle 64-bit addresses */
819
820 /* Read configuration data */
821 SlotNumber.u.AsULONG = Slot;
822 HalpReadPCIConfig(BusHandler, SlotNumber, &PciConfig, 0, PCI_COMMON_HDR_LENGTH);
823
824 /* Check if we read it correctly */
825 if (PciConfig.VendorID == PCI_INVALID_VENDORID)
826 return STATUS_NO_SUCH_DEVICE;
827
828 /* Read the PCI configuration space for the device and store base address and
829 size information in temporary storage. Count the number of valid base addresses */
830 ResourceCount = 0;
831 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
832 {
833 if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address])
834 PciConfig.u.type0.BaseAddresses[Address] = 0;
835
836 /* Memory resource */
837 if (0 != PciConfig.u.type0.BaseAddresses[Address])
838 {
839 ResourceCount++;
840
841 Offset = (UCHAR)FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);
842
843 /* Write 0xFFFFFFFF there */
844 WriteBuffer = 0xffffffff;
845 HalpWritePCIConfig(BusHandler, SlotNumber, &WriteBuffer, Offset, sizeof(ULONG));
846
847 /* Read that figure back from the config space */
848 HalpReadPCIConfig(BusHandler, SlotNumber, &Size[Address], Offset, sizeof(ULONG));
849
850 /* Write back initial value */
851 HalpWritePCIConfig(BusHandler, SlotNumber, &PciConfig.u.type0.BaseAddresses[Address], Offset, sizeof(ULONG));
852 }
853 }
854
855 /* Interrupt resource */
856 if (0 != PciConfig.u.type0.InterruptPin &&
857 0 != PciConfig.u.type0.InterruptLine &&
858 0xFF != PciConfig.u.type0.InterruptLine)
859 ResourceCount++;
860
861 /* Allocate output buffer and initialize */
862 *AllocatedResources = ExAllocatePoolWithTag(
863 PagedPool,
864 sizeof(CM_RESOURCE_LIST) +
865 (ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
866 TAG_HAL);
867
868 if (NULL == *AllocatedResources)
869 return STATUS_NO_MEMORY;
870
871 (*AllocatedResources)->Count = 1;
872 (*AllocatedResources)->List[0].InterfaceType = PCIBus;
873 (*AllocatedResources)->List[0].BusNumber = BusHandler->BusNumber;
874 (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
875 (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
876 (*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount;
877 Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
878
879 /* Store configuration information */
880 for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
881 {
882 if (0 != PciConfig.u.type0.BaseAddresses[Address])
883 {
884 if (PCI_ADDRESS_MEMORY_SPACE ==
885 (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
886 {
887 Descriptor->Type = CmResourceTypeMemory;
888 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
889 Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; /* FIXME Just a guess */
890 Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
891 Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_ADDRESS_MEMORY_ADDRESS_MASK);
892 }
893 else if (PCI_ADDRESS_IO_SPACE ==
894 (PciConfig.u.type0.BaseAddresses[Address] & 0x1))
895 {
896 Descriptor->Type = CmResourceTypePort;
897 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
898 Descriptor->Flags = CM_RESOURCE_PORT_IO; /* FIXME Just a guess */
899 Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_ADDRESS_IO_ADDRESS_MASK;
900 Descriptor->u.Port.Length = PciSize(Size[Address], PCI_ADDRESS_IO_ADDRESS_MASK & 0xffff);
901 }
902 else
903 {
904 ASSERT(FALSE);
905 return STATUS_UNSUCCESSFUL;
906 }
907 Descriptor++;
908 }
909 }
910
911 if (0 != PciConfig.u.type0.InterruptPin &&
912 0 != PciConfig.u.type0.InterruptLine &&
913 0xFF != PciConfig.u.type0.InterruptLine)
914 {
915 Descriptor->Type = CmResourceTypeInterrupt;
916 Descriptor->ShareDisposition = CmResourceShareShared; /* FIXME Just a guess */
917 Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; /* FIXME Just a guess */
918 Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
919 Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
920 Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
921
922 Descriptor++;
923 }
924
925 ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount);
926
927 /* FIXME: Should store the resources in the registry resource map */
928
929 return Status;
930 }
931
932 ULONG
933 NTAPI
934 HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler,
935 IN ULONG BusNumber,
936 IN PCI_SLOT_NUMBER SlotNumber,
937 IN PVOID Buffer,
938 IN ULONG Offset,
939 IN ULONG Length)
940 {
941 BUS_HANDLER BusHandler;
942
943 /* Setup fake PCI Bus handler */
944 RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
945 BusHandler.BusNumber = BusNumber;
946
947 /* Read configuration data */
948 HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length);
949
950 /* Return length */
951 return Length;
952 }
953
954 CODE_SEG("INIT")
955 PPCI_REGISTRY_INFO_INTERNAL
956 NTAPI
957 HalpQueryPciRegistryInfo(VOID)
958 {
959 #ifndef _MINIHAL_
960 WCHAR NameBuffer[8];
961 OBJECT_ATTRIBUTES ObjectAttributes;
962 UNICODE_STRING KeyName, ConfigName, IdentName;
963 HANDLE KeyHandle, BusKeyHandle, CardListHandle;
964 NTSTATUS Status;
965 UCHAR KeyBuffer[sizeof(CM_FULL_RESOURCE_DESCRIPTOR) + 100];
966 PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer;
967 UCHAR PartialKeyBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) +
968 sizeof(PCI_CARD_DESCRIPTOR)];
969 PKEY_VALUE_PARTIAL_INFORMATION PartialValueInfo = (PVOID)PartialKeyBuffer;
970 KEY_FULL_INFORMATION KeyInformation;
971 ULONG ResultLength;
972 PWSTR Tag;
973 ULONG i, ElementCount;
974 PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
975 PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
976 PPCI_REGISTRY_INFO PciRegInfo;
977 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
978 PPCI_CARD_DESCRIPTOR CardDescriptor;
979
980 /* Setup the object attributes for the key */
981 RtlInitUnicodeString(&KeyName,
982 L"\\Registry\\Machine\\Hardware\\Description\\"
983 L"System\\MultiFunctionAdapter");
984 InitializeObjectAttributes(&ObjectAttributes,
985 &KeyName,
986 OBJ_CASE_INSENSITIVE,
987 NULL,
988 NULL);
989
990 /* Open the key */
991 Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
992 if (!NT_SUCCESS(Status)) return NULL;
993
994 /* Setup the receiving string */
995 KeyName.Buffer = NameBuffer;
996 KeyName.MaximumLength = sizeof(NameBuffer);
997
998 /* Setup the configuration and identifier key names */
999 RtlInitUnicodeString(&ConfigName, L"Configuration Data");
1000 RtlInitUnicodeString(&IdentName, L"Identifier");
1001
1002 /* Keep looping for each ID */
1003 for (i = 0; TRUE; i++)
1004 {
1005 /* Setup the key name */
1006 RtlIntegerToUnicodeString(i, 10, &KeyName);
1007 InitializeObjectAttributes(&ObjectAttributes,
1008 &KeyName,
1009 OBJ_CASE_INSENSITIVE,
1010 KeyHandle,
1011 NULL);
1012
1013 /* Open it */
1014 Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes);
1015 if (!NT_SUCCESS(Status))
1016 {
1017 /* None left, fail */
1018 ZwClose(KeyHandle);
1019 return NULL;
1020 }
1021
1022 /* Read the registry data */
1023 Status = ZwQueryValueKey(BusKeyHandle,
1024 &IdentName,
1025 KeyValueFullInformation,
1026 ValueInfo,
1027 sizeof(KeyBuffer),
1028 &ResultLength);
1029 if (!NT_SUCCESS(Status))
1030 {
1031 /* Failed, try the next one */
1032 ZwClose(BusKeyHandle);
1033 continue;
1034 }
1035
1036 /* Get the PCI Tag and validate it */
1037 Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
1038 if ((Tag[0] != L'P') ||
1039 (Tag[1] != L'C') ||
1040 (Tag[2] != L'I') ||
1041 (Tag[3]))
1042 {
1043 /* Not a valid PCI entry, skip it */
1044 ZwClose(BusKeyHandle);
1045 continue;
1046 }
1047
1048 /* Now read our PCI structure */
1049 Status = ZwQueryValueKey(BusKeyHandle,
1050 &ConfigName,
1051 KeyValueFullInformation,
1052 ValueInfo,
1053 sizeof(KeyBuffer),
1054 &ResultLength);
1055 ZwClose(BusKeyHandle);
1056 if (!NT_SUCCESS(Status)) continue;
1057
1058 /* We read it OK! Get the actual resource descriptors */
1059 FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
1060 ((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
1061 PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
1062 ((ULONG_PTR)FullDescriptor->
1063 PartialResourceList.PartialDescriptors);
1064
1065 /* Check if this is our PCI Registry Information */
1066 if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
1067 {
1068 /* It is, stop searching */
1069 break;
1070 }
1071 }
1072
1073 /* Close the key */
1074 ZwClose(KeyHandle);
1075
1076 /* Save the PCI information for later */
1077 PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1);
1078
1079 /* Assume no Card List entries */
1080 ElementCount = 0;
1081
1082 /* Set up for checking the PCI Card List key */
1083 RtlInitUnicodeString(&KeyName,
1084 L"\\Registry\\Machine\\System\\CurrentControlSet\\"
1085 L"Control\\PnP\\PCI\\CardList");
1086 InitializeObjectAttributes(&ObjectAttributes,
1087 &KeyName,
1088 OBJ_CASE_INSENSITIVE,
1089 NULL,
1090 NULL);
1091
1092 /* Attempt to open it */
1093 Status = ZwOpenKey(&CardListHandle, KEY_READ, &ObjectAttributes);
1094 if (NT_SUCCESS(Status))
1095 {
1096 /* It exists, so let's query it */
1097 Status = ZwQueryKey(CardListHandle,
1098 KeyFullInformation,
1099 &KeyInformation,
1100 sizeof(KEY_FULL_INFORMATION),
1101 &ResultLength);
1102 if (!NT_SUCCESS(Status))
1103 {
1104 /* Failed to query, so no info */
1105 PciRegistryInfo = NULL;
1106 }
1107 else
1108 {
1109 /* Allocate the full structure */
1110 PciRegistryInfo =
1111 ExAllocatePoolWithTag(NonPagedPool,
1112 sizeof(PCI_REGISTRY_INFO_INTERNAL) +
1113 (KeyInformation.Values *
1114 sizeof(PCI_CARD_DESCRIPTOR)),
1115 TAG_HAL);
1116 if (PciRegistryInfo)
1117 {
1118 /* Get the first card descriptor entry */
1119 CardDescriptor = (PPCI_CARD_DESCRIPTOR)(PciRegistryInfo + 1);
1120
1121 /* Loop all the values */
1122 for (i = 0; i < KeyInformation.Values; i++)
1123 {
1124 /* Attempt to get the value */
1125 Status = ZwEnumerateValueKey(CardListHandle,
1126 i,
1127 KeyValuePartialInformation,
1128 PartialValueInfo,
1129 sizeof(PartialKeyBuffer),
1130 &ResultLength);
1131 if (!NT_SUCCESS(Status))
1132 {
1133 /* Something went wrong, stop the search */
1134 break;
1135 }
1136
1137 /* Make sure it is correctly sized */
1138 if (PartialValueInfo->DataLength == sizeof(PCI_CARD_DESCRIPTOR))
1139 {
1140 /* Sure is, copy it over */
1141 *CardDescriptor = *(PPCI_CARD_DESCRIPTOR)
1142 PartialValueInfo->Data;
1143
1144 /* One more Card List entry */
1145 ElementCount++;
1146
1147 /* Move to the next descriptor */
1148 CardDescriptor = (CardDescriptor + 1);
1149 }
1150 }
1151 }
1152 }
1153
1154 /* Close the Card List key */
1155 ZwClose(CardListHandle);
1156 }
1157 else
1158 {
1159 /* No key, no Card List */
1160 PciRegistryInfo = NULL;
1161 }
1162
1163 /* Check if we failed to get the full structure */
1164 if (!PciRegistryInfo)
1165 {
1166 /* Just allocate the basic structure then */
1167 PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool,
1168 sizeof(PCI_REGISTRY_INFO_INTERNAL),
1169 TAG_HAL);
1170 if (!PciRegistryInfo) return NULL;
1171 }
1172
1173 /* Save the info we got */
1174 PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision;
1175 PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision;
1176 PciRegistryInfo->NoBuses = PciRegInfo->NoBuses;
1177 PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism;
1178 PciRegistryInfo->ElementCount = ElementCount;
1179
1180 /* Return it */
1181 return PciRegistryInfo;
1182 #else
1183 return NULL;
1184 #endif
1185 }
1186
1187 CODE_SEG("INIT")
1188 VOID
1189 NTAPI
1190 HalpInitializePciStubs(VOID)
1191 {
1192 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
1193 UCHAR PciType;
1194 PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData;
1195 ULONG i;
1196 PCI_SLOT_NUMBER j;
1197 ULONG VendorId = 0;
1198 ULONG MaxPciBusNumber;
1199
1200 /* Query registry information */
1201 PciRegistryInfo = HalpQueryPciRegistryInfo();
1202 if (!PciRegistryInfo)
1203 {
1204 /* Assume type 1 */
1205 PciType = 1;
1206
1207 /* Force a manual bus scan later */
1208 MaxPciBusNumber = MAXULONG;
1209 }
1210 else
1211 {
1212 /* Get the PCI type */
1213 PciType = PciRegistryInfo->HardwareMechanism & 0xF;
1214
1215 /* Get MaxPciBusNumber and make it 0-based */
1216 MaxPciBusNumber = PciRegistryInfo->NoBuses - 1;
1217
1218 /* Free the info structure */
1219 ExFreePoolWithTag(PciRegistryInfo, TAG_HAL);
1220 }
1221
1222 /* Initialize the PCI lock */
1223 KeInitializeSpinLock(&HalpPCIConfigLock);
1224
1225 /* Check the type of PCI bus */
1226 switch (PciType)
1227 {
1228 /* Type 1 PCI Bus */
1229 case 1:
1230
1231 /* Copy the Type 1 handler data */
1232 RtlCopyMemory(&PCIConfigHandler,
1233 &PCIConfigHandlerType1,
1234 sizeof(PCIConfigHandler));
1235
1236 /* Set correct I/O Ports */
1237 BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
1238 BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
1239 break;
1240
1241 /* Type 2 PCI Bus */
1242 case 2:
1243
1244 /* Copy the Type 2 handler data */
1245 RtlCopyMemory(&PCIConfigHandler,
1246 &PCIConfigHandlerType2,
1247 sizeof (PCIConfigHandler));
1248
1249 /* Set correct I/O Ports */
1250 BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
1251 BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
1252 BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
1253
1254 /* Only 16 devices supported, not 32 */
1255 BusData->MaxDevice = 16;
1256 break;
1257
1258 default:
1259
1260 /* Invalid type */
1261 DbgPrint("HAL: Unknown PCI type\n");
1262 }
1263
1264 /* Run a forced bus scan if needed */
1265 if (MaxPciBusNumber == MAXULONG)
1266 {
1267 /* Initialize the max bus number to 0xFF */
1268 HalpMaxPciBus = 0xFF;
1269
1270 /* Initialize the counter */
1271 MaxPciBusNumber = 0;
1272
1273 /* Loop all possible buses */
1274 for (i = 0; i < HalpMaxPciBus; i++)
1275 {
1276 /* Loop all devices */
1277 for (j.u.AsULONG = 0; j.u.AsULONG < BusData->MaxDevice; j.u.AsULONG++)
1278 {
1279 /* Query the interface */
1280 if (HaliPciInterfaceReadConfig(NULL,
1281 i,
1282 j,
1283 &VendorId,
1284 0,
1285 sizeof(ULONG)))
1286 {
1287 /* Validate the vendor ID */
1288 if ((VendorId & 0xFFFF) != PCI_INVALID_VENDORID)
1289 {
1290 /* Set this as the maximum ID */
1291 MaxPciBusNumber = i;
1292 break;
1293 }
1294 }
1295 }
1296 }
1297 }
1298
1299 /* Set the real max bus number */
1300 HalpMaxPciBus = MaxPciBusNumber;
1301
1302 /* We're done */
1303 HalpPCIConfigInitialized = TRUE;
1304 }
1305
1306 /* EOF */
1307