xref: /reactos/hal/halx86/legacy/bus/pcibus.c (revision 98e8827a)
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 
1308