xref: /reactos/hal/halx86/legacy/bussupp.c (revision e1338178)
1 /*
2  * PROJECT:         ReactOS HAL
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            hal/halx86/legacy/bussupp.c
5  * PURPOSE:         HAL Legacy Bus Support Code
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <hal.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 INIT_FUNCTION
16 PBUS_HANDLER
17 NTAPI
18 HalpAllocateAndInitPciBusHandler(
19     IN ULONG PciType,
20     IN ULONG BusNo,
21     IN BOOLEAN TestAllocation
22 );
23 
24 INIT_FUNCTION
25 VOID
26 NTAPI
27 HalpFixupPciSupportedRanges(
28     IN ULONG BusCount
29 );
30 
31 INIT_FUNCTION
32 NTSTATUS
33 NTAPI
34 HalpGetChipHacks(
35     IN USHORT VendorId,
36     IN USHORT DeviceId,
37     IN UCHAR RevisionId,
38     IN PULONG HackFlags
39 );
40 
41 INIT_FUNCTION
42 BOOLEAN
43 NTAPI
44 HalpGetPciBridgeConfig(
45     IN ULONG PciType,
46     IN PUCHAR BusCount
47 );
48 
49 INIT_FUNCTION
50 BOOLEAN
51 NTAPI
52 HalpIsBridgeDevice(
53     IN PPCI_COMMON_CONFIG PciData
54 );
55 
56 INIT_FUNCTION
57 BOOLEAN
58 NTAPI
59 HalpIsIdeDevice(
60     IN PPCI_COMMON_CONFIG PciData
61 );
62 
63 INIT_FUNCTION
64 BOOLEAN
65 NTAPI
66 HalpIsRecognizedCard(
67     IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
68     IN PPCI_COMMON_CONFIG PciData,
69     IN ULONG Flags
70 );
71 
72 INIT_FUNCTION
73 BOOLEAN
74 NTAPI
75 HalpIsValidPCIDevice(
76     IN PBUS_HANDLER BusHandler,
77     IN PCI_SLOT_NUMBER Slot
78 );
79 
80 INIT_FUNCTION
81 NTSTATUS
82 NTAPI
83 HalpMarkChipsetDecode(
84     IN BOOLEAN OverrideEnable
85 );
86 
87 INIT_FUNCTION
88 VOID
89 NTAPI
90 HalpRegisterInternalBusHandlers(
91     VOID
92 );
93 
94 INIT_FUNCTION
95 VOID
96 NTAPI
97 ShowSize(
98     IN ULONG Size
99 );
100 
101 
102 #if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_)
103 #pragma alloc_text(INIT, HalpAllocateAndInitPciBusHandler)
104 #pragma alloc_text(INIT, HalpDebugPciDumpBus)
105 #pragma alloc_text(INIT, HalpFixupPciSupportedRanges)
106 #pragma alloc_text(INIT, HalpGetChipHacks)
107 #pragma alloc_text(INIT, HalpGetPciBridgeConfig)
108 #pragma alloc_text(INIT, HalpInitBusHandlers)
109 #pragma alloc_text(INIT, HalpInitializePciBus)
110 #pragma alloc_text(INIT, HalpIsBridgeDevice)
111 #pragma alloc_text(INIT, HalpIsIdeDevice)
112 #pragma alloc_text(INIT, HalpIsRecognizedCard)
113 #pragma alloc_text(INIT, HalpIsValidPCIDevice)
114 #pragma alloc_text(INIT, HalpMarkChipsetDecode)
115 #pragma alloc_text(INIT, HalpRegisterKdSupportFunctions)
116 #pragma alloc_text(INIT, HalpRegisterInternalBusHandlers)
117 #pragma alloc_text(INIT, ShowSize)
118 #endif
119 
120 /* GLOBALS ********************************************************************/
121 
122 extern KSPIN_LOCK HalpPCIConfigLock;
123 ULONG HalpPciIrqMask;
124 
125 /* PRIVATE FUNCTIONS **********************************************************/
126 
127 PBUS_HANDLER
128 NTAPI
129 HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType,
130                        IN BUS_DATA_TYPE BusDataType,
131                        IN ULONG BusNumber,
132                        IN INTERFACE_TYPE ParentBusInterfaceType,
133                        IN ULONG ParentBusNumber,
134                        IN ULONG BusSpecificData)
135 {
136     PBUS_HANDLER Bus;
137 
138     /* Register the bus handler */
139     HalRegisterBusHandler(InterfaceType,
140                           BusDataType,
141                           BusNumber,
142                           ParentBusInterfaceType,
143                           ParentBusNumber,
144                           BusSpecificData,
145                           NULL,
146                           &Bus);
147     if (!Bus)
148     {
149         return NULL;
150     }
151 
152     /* Check for a valid interface */
153     if (InterfaceType != InterfaceTypeUndefined)
154     {
155         /* Allocate address ranges and zero them out */
156         Bus->BusAddresses = ExAllocatePoolWithTag(NonPagedPoolMustSucceed,
157                                                   sizeof(SUPPORTED_RANGES),
158                                                   TAG_HAL);
159         RtlZeroMemory(Bus->BusAddresses, sizeof(SUPPORTED_RANGES));
160 
161         /* Build the data structure */
162         Bus->BusAddresses->Version = HAL_SUPPORTED_RANGE_VERSION;
163         Bus->BusAddresses->Dma.Limit = 7;
164         Bus->BusAddresses->Memory.Limit = 0xFFFFFFFF;
165         Bus->BusAddresses->IO.Limit = 0xFFFF;
166         Bus->BusAddresses->IO.SystemAddressSpace = 1;
167         Bus->BusAddresses->PrefetchMemory.Base = 1;
168     }
169 
170     /* Return the bus address */
171     return Bus;
172 }
173 
174 INIT_FUNCTION
175 VOID
176 NTAPI
177 HalpRegisterInternalBusHandlers(VOID)
178 {
179     PBUS_HANDLER Bus;
180 
181     /* Only do processor 1 */
182     if (KeGetCurrentPrcb()->Number) return;
183 
184     /* Register root support */
185     HalpInitBusHandler();
186 
187     /* Allocate the system bus */
188     Bus = HalpAllocateBusHandler(Internal,
189                                  ConfigurationSpaceUndefined,
190                                  0,
191                                  InterfaceTypeUndefined,
192                                  0,
193                                  0);
194     if (Bus)
195     {
196         /* Set it up */
197         Bus->GetInterruptVector = HalpGetSystemInterruptVector;
198         Bus->TranslateBusAddress = HalpTranslateSystemBusAddress;
199     }
200 
201     /* Allocate the CMOS bus */
202     Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
203                                  Cmos,
204                                  0,
205                                  InterfaceTypeUndefined,
206                                  0,
207                                  0);
208     if (Bus)
209     {
210         /* Set it up */
211         Bus->GetBusData = HalpcGetCmosData;
212         Bus->SetBusData = HalpcSetCmosData;
213     }
214 
215     /* Allocate the CMOS bus */
216     Bus = HalpAllocateBusHandler(InterfaceTypeUndefined,
217                                  Cmos,
218                                  1,
219                                  InterfaceTypeUndefined,
220                                  0,
221                                  0);
222     if (Bus)
223     {
224         /* Set it up */
225         Bus->GetBusData = HalpcGetCmosData;
226         Bus->SetBusData = HalpcSetCmosData;
227     }
228 
229     /* Allocate ISA bus */
230     Bus = HalpAllocateBusHandler(Isa,
231                                  ConfigurationSpaceUndefined,
232                                  0,
233                                  Internal,
234                                  0,
235                                  0);
236     if (Bus)
237     {
238         /* Set it up */
239         Bus->GetBusData = HalpNoBusData;
240         Bus->BusAddresses->Memory.Limit = 0xFFFFFF;
241         Bus->TranslateBusAddress = HalpTranslateIsaBusAddress;
242     }
243 
244     /* No support for EISA or MCA */
245     ASSERT(HalpBusType == MACHINE_TYPE_ISA);
246 }
247 
248 #ifndef _MINIHAL_
249 INIT_FUNCTION
250 NTSTATUS
251 NTAPI
252 HalpMarkChipsetDecode(BOOLEAN OverrideEnable)
253 {
254     NTSTATUS Status;
255     UNICODE_STRING KeyString;
256     ULONG Data = OverrideEnable;
257     HANDLE KeyHandle, Handle;
258 
259     /* Open CCS key */
260     RtlInitUnicodeString(&KeyString,
261                          L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
262     Status = HalpOpenRegistryKey(&Handle, 0, &KeyString, KEY_ALL_ACCESS, FALSE);
263     if (NT_SUCCESS(Status))
264     {
265         /* Open PNP Bios key */
266         RtlInitUnicodeString(&KeyString, L"Control\\Biosinfo\\PNPBios");
267         Status = HalpOpenRegistryKey(&KeyHandle,
268                                      Handle,
269                                      &KeyString,
270                                      KEY_ALL_ACCESS,
271                                      TRUE);
272 
273         /* Close root key */
274         ZwClose(Handle);
275 
276         /* Check if PNP BIOS key exists */
277         if (NT_SUCCESS(Status))
278         {
279             /* Set the override value */
280             RtlInitUnicodeString(&KeyString, L"FullDecodeChipsetOverride");
281             Status = ZwSetValueKey(KeyHandle,
282                                    &KeyString,
283                                    0,
284                                    REG_DWORD,
285                                    &Data,
286                                    sizeof(Data));
287 
288             /* Close subkey */
289             ZwClose(KeyHandle);
290         }
291     }
292 
293     /* Return status */
294     return Status;
295 }
296 
297 INIT_FUNCTION
298 PBUS_HANDLER
299 NTAPI
300 HalpAllocateAndInitPciBusHandler(IN ULONG PciType,
301                                  IN ULONG BusNo,
302                                  IN BOOLEAN TestAllocation)
303 {
304     PBUS_HANDLER Bus;
305     PPCIPBUSDATA BusData;
306 
307     /* Allocate the bus handler */
308     Bus = HalpAllocateBusHandler(PCIBus,
309                                  PCIConfiguration,
310                                  BusNo,
311                                  Internal,
312                                  0,
313                                  sizeof(PCIPBUSDATA));
314 
315     /* Set it up */
316     Bus->GetBusData = HalpGetPCIData;
317     Bus->SetBusData = HalpSetPCIData;
318     Bus->GetInterruptVector = HalpGetPCIIntOnISABus;
319     Bus->AdjustResourceList = HalpAdjustPCIResourceList;
320     Bus->AssignSlotResources = HalpAssignPCISlotResources;
321     Bus->BusAddresses->Dma.Limit = 0;
322 
323     /* Get our custom bus data */
324     BusData = (PPCIPBUSDATA)Bus->BusData;
325 
326     /* Setup custom bus data */
327     BusData->CommonData.Tag = PCI_DATA_TAG;
328     BusData->CommonData.Version = PCI_DATA_VERSION;
329     BusData->CommonData.ReadConfig = HalpReadPCIConfig;
330     BusData->CommonData.WriteConfig = HalpWritePCIConfig;
331     BusData->CommonData.Pin2Line = HalpPCIPin2ISALine;
332     BusData->CommonData.Line2Pin = HalpPCIISALine2Pin;
333     BusData->MaxDevice = PCI_MAX_DEVICES;
334     BusData->GetIrqRange = HalpGetISAFixedPCIIrq;
335 
336     /* Initialize the bitmap */
337     RtlInitializeBitMap(&BusData->DeviceConfigured, BusData->ConfiguredBits, 256);
338 
339     /* Check the type of PCI bus */
340     switch (PciType)
341     {
342         /* Type 1 PCI Bus */
343         case 1:
344 
345             /* Copy the Type 1 handler data */
346             RtlCopyMemory(&PCIConfigHandler,
347                           &PCIConfigHandlerType1,
348                           sizeof(PCIConfigHandler));
349 
350             /* Set correct I/O Ports */
351             BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
352             BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
353             break;
354 
355         /* Type 2 PCI Bus */
356         case 2:
357 
358             /* Copy the Type 1 handler data */
359             RtlCopyMemory(&PCIConfigHandler,
360                           &PCIConfigHandlerType2,
361                           sizeof (PCIConfigHandler));
362 
363             /* Set correct I/O Ports */
364             BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
365             BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
366             BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
367 
368             /* Only 16 devices supported, not 32 */
369             BusData->MaxDevice = 16;
370             break;
371 
372         default:
373 
374             /* Invalid type */
375             DbgPrint("HAL: Unnkown PCI type\n");
376     }
377 
378     /* Return the bus handler */
379     return Bus;
380 }
381 
382 INIT_FUNCTION
383 BOOLEAN
384 NTAPI
385 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler,
386                      IN PCI_SLOT_NUMBER Slot)
387 {
388     UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
389     PPCI_COMMON_CONFIG PciHeader = (PVOID)DataBuffer;
390     ULONG i;
391     ULONG_PTR Address;
392 
393     /* Read the PCI header */
394     HalpReadPCIConfig(BusHandler, Slot, PciHeader, 0, PCI_COMMON_HDR_LENGTH);
395 
396     /* Make sure it's a valid device */
397     if ((PciHeader->VendorID == PCI_INVALID_VENDORID) ||
398         (PCI_CONFIGURATION_TYPE(PciHeader) != PCI_DEVICE_TYPE))
399     {
400         /* Bail out */
401         return FALSE;
402     }
403 
404     /* Make sure interrupt numbers make sense */
405     if (((PciHeader->u.type0.InterruptPin) &&
406          (PciHeader->u.type0.InterruptPin > 4)) ||
407         (PciHeader->u.type0.InterruptLine & 0x70))
408     {
409         /* Bail out */
410         return FALSE;
411     }
412 
413     /* Now scan PCI BARs */
414     for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
415     {
416         /* Check what kind of address it is */
417         Address = PciHeader->u.type0.BaseAddresses[i];
418         if (Address & PCI_ADDRESS_IO_SPACE)
419         {
420             /* Highest I/O port is 65535 */
421             if (Address > 0xFFFF) return FALSE;
422         }
423         else
424         {
425             /* MMIO should be higher than 0x80000 */
426             if ((Address > 0xF) && (Address < 0x80000)) return FALSE;
427         }
428 
429         /* Is this a 64-bit address? */
430         if (!(Address & PCI_ADDRESS_IO_SPACE) &&
431             ((Address & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
432         {
433             /* Check the next-next entry, since this one 64-bits wide */
434             i++;
435         }
436     }
437 
438     /* Header, interrupt and address data all make sense */
439     return TRUE;
440 }
441 
442 static BOOLEAN WarningsGiven[5];
443 
444 INIT_FUNCTION
445 NTSTATUS
446 NTAPI
447 HalpGetChipHacks(IN USHORT VendorId,
448                  IN USHORT DeviceId,
449                  IN UCHAR RevisionId,
450                  IN PULONG HackFlags)
451 {
452     UNICODE_STRING KeyName, ValueName;
453     NTSTATUS Status;
454     OBJECT_ATTRIBUTES ObjectAttributes;
455     HANDLE KeyHandle;
456     WCHAR Buffer[32];
457     KEY_VALUE_PARTIAL_INFORMATION PartialInfo;
458     ULONG ResultLength;
459 
460     /* Setup the object attributes for the key */
461     RtlInitUnicodeString(&KeyName,
462                          L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
463                          L"Control\\HAL");
464     InitializeObjectAttributes(&ObjectAttributes,
465                                &KeyName,
466                                OBJ_CASE_INSENSITIVE,
467                                NULL,
468                                NULL);
469 
470     /* Open the key */
471     Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
472     if (!NT_SUCCESS(Status)) return Status;
473 
474     /* Query value */
475     swprintf(Buffer, L"%04X%04X", VendorId, DeviceId);
476     RtlInitUnicodeString(&ValueName, Buffer);
477     Status = ZwQueryValueKey(KeyHandle,
478                              &ValueName,
479                              KeyValuePartialInformation,
480                              &PartialInfo,
481                              sizeof(PartialInfo),
482                              &ResultLength);
483     if (NT_SUCCESS(Status))
484     {
485         /* Return the flags */
486         DbgPrint("\tFound HackFlags for your chipset\n");
487         *HackFlags = *(PULONG)PartialInfo.Data;
488         DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
489                  *HackFlags, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags), RevisionId);
490 
491         /* Does it apply to this revision? */
492         if ((RevisionId) && (RevisionId >= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags))))
493         {
494             /* Read the revision flags */
495             *HackFlags = HALP_REVISION_HACK_FLAGS(*HackFlags);
496         }
497 
498         /* Throw out revision data */
499         *HackFlags = HALP_HACK_FLAGS(*HackFlags);
500         if (!*HackFlags) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
501     }
502 
503     /* Close the handle and return */
504     ZwClose(KeyHandle);
505     return Status;
506 }
507 
508 INIT_FUNCTION
509 BOOLEAN
510 NTAPI
511 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo,
512                      IN PPCI_COMMON_CONFIG PciData,
513                      IN ULONG Flags)
514 {
515     ULONG ElementCount, i;
516     PPCI_CARD_DESCRIPTOR CardDescriptor;
517 
518     /* How many PCI Cards that we know about? */
519     ElementCount = PciRegistryInfo->ElementCount;
520     if (!ElementCount) return FALSE;
521 
522     /* Loop all descriptors */
523     CardDescriptor = &PciRegistryInfo->CardList[0];
524     for (i = 0; i < ElementCount; i++, CardDescriptor++)
525     {
526         /* Check for flag match */
527         if (CardDescriptor->Flags != Flags) continue;
528 
529         /* Check for VID-PID match */
530         if ((CardDescriptor->VendorID != PciData->VendorID) ||
531             (CardDescriptor->DeviceID != PciData->DeviceID))
532         {
533             /* Skip */
534             continue;
535         }
536 
537         /* Check for revision match, if requested */
538         if ((CardDescriptor->Flags & HALP_CHECK_CARD_REVISION_ID) &&
539             (CardDescriptor->RevisionID != PciData->RevisionID))
540         {
541             /* Skip */
542             continue;
543         }
544 
545         /* Check what kind of device this is */
546         switch (PCI_CONFIGURATION_TYPE(PciData))
547         {
548             /* CardBUS Bridge */
549             case PCI_CARDBUS_BRIDGE_TYPE:
550 
551                 /* This means the real device header is in the device-specific data */
552                 PciData = (PPCI_COMMON_CONFIG)PciData->DeviceSpecific;
553 
554             /* Normal PCI device */
555             case PCI_DEVICE_TYPE:
556 
557                 /* Check for subvendor match, if requested */
558                 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBVENDOR_ID) &&
559                     (CardDescriptor->SubsystemVendorID != PciData->u.type0.SubVendorID))
560                 {
561                     /* Skip */
562                     continue;
563                 }
564 
565                 /* Check for subsystem match, if requested */
566                 if ((CardDescriptor->Flags & HALP_CHECK_CARD_SUBSYSTEM_ID) &&
567                     (CardDescriptor->SubsystemID != PciData->u.type0.SubSystemID))
568                 {
569                     /* Skip */
570                     continue;
571                 }
572 
573                 /* You made it! */
574                 return TRUE;
575 
576             /* PCI Bridge -- don't bother */
577             case PCI_BRIDGE_TYPE:
578             default:
579 
580                 /* Recognize it */
581                 return TRUE;
582         }
583     }
584 
585     /* This means the card isn't recognized */
586     return FALSE;
587 }
588 
589 INIT_FUNCTION
590 BOOLEAN
591 NTAPI
592 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData)
593 {
594     /* Simple test first */
595     if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
596         (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
597     {
598         /* The device is nice enough to admit it */
599         return TRUE;
600     }
601 
602     /* Symphony 82C101 */
603     if (PciData->VendorID == 0x1C1C) return TRUE;
604 
605     /* ALi MS4803 or M5219 */
606     if ((PciData->VendorID == 0x10B9) &&
607         ((PciData->DeviceID == 0x5215) || (PciData->DeviceID == 0x5219)))
608     {
609         return TRUE;
610     }
611 
612     /* Appian Technology */
613     if ((PciData->VendorID == 0x1097) && (PciData->DeviceID == 0x38)) return TRUE;
614 
615     /* Compaq Triflex Dual EIDE Controller */
616     if ((PciData->VendorID == 0xE11) && (PciData->DeviceID == 0xAE33)) return TRUE;
617 
618     /* Micron PC Tech RZ1000 */
619     if ((PciData->VendorID == 0x1042) && (PciData->DeviceID == 0x1000)) return TRUE;
620 
621     /* SiS 85C601 or 5513 [IDE] */
622     if ((PciData->VendorID == 0x1039) &&
623         ((PciData->DeviceID == 0x601) || (PciData->DeviceID == 0x5513)))
624     {
625         return TRUE;
626     }
627 
628     /* Symphony Labs W83769F */
629     if ((PciData->VendorID == 0x10AD) &&
630         ((PciData->DeviceID == 0x1) || (PciData->DeviceID == 0x150)))
631     {
632         return TRUE;
633     }
634 
635     /* UMC UM8673F */
636     if ((PciData->VendorID == 0x1060) && (PciData->DeviceID == 0x101)) return TRUE;
637 
638     /* You've survived */
639     return FALSE;
640 }
641 
642 INIT_FUNCTION
643 BOOLEAN
644 NTAPI
645 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData)
646 {
647     /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
648     return (((PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE) &&
649              (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
650              (PciData->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)) ||
651             ((PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) &&
652              (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
653              (PciData->SubClass == PCI_SUBCLASS_BR_CARDBUS)));
654 }
655 
656 INIT_FUNCTION
657 BOOLEAN
658 NTAPI
659 HalpGetPciBridgeConfig(IN ULONG PciType,
660                        IN PUCHAR BusCount)
661 {
662     PCI_SLOT_NUMBER PciSlot;
663     ULONG i, j, k;
664     UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
665     PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
666     PBUS_HANDLER BusHandler;
667 
668     /* Loop PCI buses */
669     PciSlot.u.bits.Reserved = 0;
670     for (i = 0; i < *BusCount; i++)
671     {
672         /* Get the bus handler */
673         BusHandler = HalHandlerForBus(PCIBus, i);
674 
675         /* Loop every device */
676         for (j = 0; j < PCI_MAX_DEVICES; j++)
677         {
678             /* Loop every function */
679             PciSlot.u.bits.DeviceNumber = j;
680             for (k = 0; k < PCI_MAX_FUNCTION; k++)
681             {
682                 /* Build the final slot structure */
683                 PciSlot.u.bits.FunctionNumber = k;
684 
685                 /* Read the configuration information */
686                 HalpReadPCIConfig(BusHandler,
687                                   PciSlot,
688                                   PciData,
689                                   0,
690                                   PCI_COMMON_HDR_LENGTH);
691 
692                 /* Skip if this is an invalid function */
693                 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
694 
695                 /* Make sure that this is a PCI bridge or a cardbus bridge */
696                 if (!HalpIsBridgeDevice(PciData)) continue;
697 
698                 /* Not supported */
699                 if (!WarningsGiven[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
700                 continue;
701             }
702         }
703     }
704 
705     /* If we exited the loop, then there's no bridge to worry about */
706     return FALSE;
707 }
708 
709 INIT_FUNCTION
710 VOID
711 NTAPI
712 HalpFixupPciSupportedRanges(IN ULONG BusCount)
713 {
714     ULONG i;
715     PBUS_HANDLER Bus, ParentBus;
716 
717     /* Loop all buses */
718     for (i = 0; i < BusCount; i++)
719     {
720         /* Get PCI bus handler */
721         Bus = HalHandlerForBus(PCIBus, i);
722 
723         /* Loop all parent buses */
724         ParentBus = Bus->ParentHandler;
725         while (ParentBus)
726         {
727             /* Should merge addresses */
728             if (!WarningsGiven[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
729 
730             /* Check the next parent */
731             ParentBus = ParentBus->ParentHandler;
732         }
733     }
734 
735     /* Loop all buses again */
736     for (i = 0; i < BusCount; i++)
737     {
738         /* Get PCI bus handler */
739         Bus = HalHandlerForBus(PCIBus, i);
740 
741         /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
742         if (!((PPCIPBUSDATA)Bus->BusData)->Subtractive)
743         {
744             /* Loop all parent buses */
745             ParentBus = Bus->ParentHandler;
746             while (ParentBus)
747             {
748                 /* But check only PCI parent buses specifically */
749                 if (ParentBus->InterfaceType == PCIBus)
750                 {
751                     /* Should trim addresses */
752                     if (!WarningsGiven[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
753                 }
754 
755                 /* Check the next parent */
756                 ParentBus = ParentBus->ParentHandler;
757             }
758         }
759     }
760 
761     /* Loop buses one last time */
762     for (i = 0; i < BusCount; i++)
763     {
764         /* Get the PCI bus handler */
765         Bus = HalHandlerForBus(PCIBus, i);
766 
767         /* Sort and combine (trim) bus address range information */
768         DPRINT("Warning: Bus addresses not being optimized!\n");
769     }
770 }
771 
772 INIT_FUNCTION
773 VOID
774 NTAPI
775 ShowSize(ULONG x)
776 {
777     if (!x) return;
778     DbgPrint(" [size=");
779     if (x < 1024)
780     {
781         DbgPrint("%d", (int) x);
782     }
783     else if (x < 1048576)
784     {
785         DbgPrint("%dK", (int)(x / 1024));
786     }
787     else if (x < 0x80000000)
788     {
789         DbgPrint("%dM", (int)(x / 1048576));
790     }
791     else
792     {
793         DbgPrint("%d", x);
794     }
795     DbgPrint("]\n");
796 }
797 
798 /*
799  * These includes are required to define
800  * the ClassTable and VendorTable arrays.
801  */
802 #include "pci_classes.h"
803 #include "pci_vendors.h"
804 INIT_FUNCTION
805 VOID
806 NTAPI
807 HalpDebugPciDumpBus(IN ULONG i,
808                     IN ULONG j,
809                     IN ULONG k,
810                     IN PPCI_COMMON_CONFIG PciData)
811 {
812     PCHAR p, ClassName, Boundary, SubClassName, VendorName, ProductName, SubVendorName;
813     ULONG Length;
814     CHAR LookupString[16] = "";
815     CHAR bSubClassName[64] = "Unknown";
816     CHAR bVendorName[64] = "";
817     CHAR bProductName[128] = "Unknown device";
818     CHAR bSubVendorName[128] = "Unknown";
819     ULONG Size, Mem, b;
820 
821     /* Isolate the class name */
822     sprintf(LookupString, "C %02x  ", PciData->BaseClass);
823     ClassName = strstr((PCHAR)ClassTable, LookupString);
824     if (ClassName)
825     {
826         /* Isolate the subclass name */
827         ClassName += strlen("C 00  ");
828         Boundary = strstr(ClassName, "\nC ");
829         sprintf(LookupString, "\n\t%02x  ", PciData->SubClass);
830         SubClassName = strstr(ClassName, LookupString);
831         if (Boundary && SubClassName > Boundary)
832         {
833             SubClassName = NULL;
834         }
835         if (!SubClassName)
836         {
837             SubClassName = ClassName;
838         }
839         else
840         {
841             SubClassName += strlen("\n\t00  ");
842         }
843         /* Copy the subclass into our buffer */
844         p = strpbrk(SubClassName, "\r\n");
845         Length = p - SubClassName;
846         if (Length >= sizeof(bSubClassName)) Length = sizeof(bSubClassName) - 1;
847         strncpy(bSubClassName, SubClassName, Length);
848         bSubClassName[Length] = '\0';
849     }
850 
851     /* Isolate the vendor name */
852     sprintf(LookupString, "\r\n%04x  ", PciData->VendorID);
853     VendorName = strstr((PCHAR)VendorTable, LookupString);
854     if (VendorName)
855     {
856         /* Copy the vendor name into our buffer */
857         VendorName += strlen("\r\n0000  ");
858         p = strpbrk(VendorName, "\r\n");
859         Length = p - VendorName;
860         if (Length >= sizeof(bVendorName)) Length = sizeof(bVendorName) - 1;
861         strncpy(bVendorName, VendorName, Length);
862         bVendorName[Length] = '\0';
863         p += strlen("\r\n");
864         while (*p == '\t' || *p == '#')
865         {
866             p = strpbrk(p, "\r\n");
867             p += strlen("\r\n");
868         }
869         Boundary = p;
870 
871         /* Isolate the product name */
872         sprintf(LookupString, "\t%04x  ", PciData->DeviceID);
873         ProductName = strstr(VendorName, LookupString);
874         if (Boundary && ProductName >= Boundary)
875         {
876             ProductName = NULL;
877         }
878         if (ProductName)
879         {
880             /* Copy the product name into our buffer */
881             ProductName += strlen("\t0000  ");
882             p = strpbrk(ProductName, "\r\n");
883             Length = p - ProductName;
884             if (Length >= sizeof(bProductName)) Length = sizeof(bProductName) - 1;
885             strncpy(bProductName, ProductName, Length);
886             bProductName[Length] = '\0';
887             p += strlen("\r\n");
888             while ((*p == '\t' && *(p + 1) == '\t') || *p == '#')
889             {
890                 p = strpbrk(p, "\r\n");
891                 p += strlen("\r\n");
892             }
893             Boundary = p;
894 
895             /* Isolate the subvendor and subsystem name */
896             sprintf(LookupString,
897                     "\t\t%04x %04x  ",
898                     PciData->u.type0.SubVendorID,
899                     PciData->u.type0.SubSystemID);
900             SubVendorName = strstr(ProductName, LookupString);
901             if (Boundary && SubVendorName >= Boundary)
902             {
903                 SubVendorName = NULL;
904             }
905             if (SubVendorName)
906             {
907                 /* Copy the subvendor name into our buffer */
908                 SubVendorName += strlen("\t\t0000 0000  ");
909                 p = strpbrk(SubVendorName, "\r\n");
910                 Length = p - SubVendorName;
911                 if (Length >= sizeof(bSubVendorName)) Length = sizeof(bSubVendorName) - 1;
912                 strncpy(bSubVendorName, SubVendorName, Length);
913                 bSubVendorName[Length] = '\0';
914             }
915         }
916     }
917 
918     /* Print out the data */
919     DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
920              "\tSubsystem: %s [%04x:%04x]\n",
921              i,
922              j,
923              k,
924              bSubClassName,
925              PciData->BaseClass,
926              PciData->SubClass,
927              bVendorName,
928              bProductName,
929              PciData->VendorID,
930              PciData->DeviceID,
931              PciData->RevisionID,
932              bSubVendorName,
933              PciData->u.type0.SubVendorID,
934              PciData->u.type0.SubSystemID);
935 
936     /* Print out and decode flags */
937     DbgPrint("\tFlags:");
938     if (PciData->Command & PCI_ENABLE_BUS_MASTER) DbgPrint(" bus master,");
939     if (PciData->Status & PCI_STATUS_66MHZ_CAPABLE) DbgPrint(" 66MHz,");
940     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x000) DbgPrint(" fast devsel,");
941     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x200) DbgPrint(" medium devsel,");
942     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x400) DbgPrint(" slow devsel,");
943     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x600) DbgPrint(" unknown devsel,");
944     DbgPrint(" latency %d", PciData->LatencyTimer);
945     if (PciData->u.type0.InterruptPin != 0 &&
946         PciData->u.type0.InterruptLine != 0 &&
947         PciData->u.type0.InterruptLine != 0xFF) DbgPrint(", IRQ %02d", PciData->u.type0.InterruptLine);
948     else if (PciData->u.type0.InterruptPin != 0) DbgPrint(", IRQ assignment required");
949     DbgPrint("\n");
950 
951     /* Scan addresses */
952     Size = 0;
953     for (b = 0; b < PCI_TYPE0_ADDRESSES; b++)
954     {
955         /* Check for a BAR */
956         Mem = PciData->u.type0.BaseAddresses[b];
957         if (Mem)
958         {
959             /* Decode the address type */
960             if (Mem & PCI_ADDRESS_IO_SPACE)
961             {
962                 /* Guess the size */
963                 Size = 1 << 2;
964                 while (!(Mem & Size) && (Size)) Size <<= 1;
965 
966                 /* Print it out */
967                 DbgPrint("\tI/O ports at %04lx", Mem & PCI_ADDRESS_IO_ADDRESS_MASK);
968                 ShowSize(Size);
969             }
970             else
971             {
972                 /* Guess the size */
973                 Size = 1 << 8;
974                 while (!(Mem & Size) && (Size)) Size <<= 1;
975 
976                 /* Print it out */
977                 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
978                          Mem & PCI_ADDRESS_MEMORY_ADDRESS_MASK,
979                          (Mem & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT ? 32 : 64,
980                          (Mem & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? "" : "non-");
981                 ShowSize(Size);
982             }
983         }
984     }
985 }
986 #endif
987 
988 INIT_FUNCTION
989 VOID
990 NTAPI
991 HalpInitializePciBus(VOID)
992 {
993 #ifndef _MINIHAL_
994     PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
995     UCHAR PciType;
996     PCI_SLOT_NUMBER PciSlot;
997     ULONG i, j, k;
998     UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
999     PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
1000     PBUS_HANDLER BusHandler;
1001     ULONG HackFlags;
1002     BOOLEAN ExtendedAddressDecoding = FALSE;
1003     NTSTATUS Status;
1004 
1005     /* Query registry information */
1006     PciRegistryInfo = HalpQueryPciRegistryInfo();
1007     if (!PciRegistryInfo) return;
1008 
1009     /* Initialize the PCI configuration lock */
1010     KeInitializeSpinLock(&HalpPCIConfigLock);
1011 
1012     /* Get the type and free the info structure */
1013     PciType = PciRegistryInfo->HardwareMechanism & 0xF;
1014 
1015     /* Check if this is a type 2 PCI bus with at least one bus */
1016     if ((PciRegistryInfo->NoBuses) && (PciType == 2))
1017     {
1018         /* Setup the PCI slot */
1019         PciSlot.u.bits.Reserved = 0;
1020         PciSlot.u.bits.FunctionNumber = 0;
1021 
1022         /* Loop all slots */
1023         for (i = 0; i < 32; i++)
1024         {
1025             /* Try to setup a Type 2 PCI slot */
1026             PciType = 2;
1027             BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE);
1028             if (!BusHandler) break;
1029 
1030             /* Now check if it's valid */
1031             if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
1032 
1033             /* Heh, the BIOS lied... try Type 1 */
1034             PciType = 1;
1035             BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE);
1036             if (!BusHandler) break;
1037 
1038             /* Now check if it's valid */
1039             if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
1040 
1041             /* Keep trying */
1042             PciType = 2;
1043         }
1044 
1045         /* Now allocate the correct kind of handler */
1046         HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE);
1047     }
1048 
1049     /* Okay, now loop all PCI bridges */
1050     do
1051     {
1052         /* Loop all PCI buses */
1053         for (i = 0; i < PciRegistryInfo->NoBuses; i++)
1054         {
1055             /* Check if we have a handler for it */
1056             if (!HalHandlerForBus(PCIBus, i))
1057             {
1058                 /* Allocate it */
1059                 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE);
1060             }
1061         }
1062         /* Go to the next bridge */
1063     } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses));
1064 
1065     /* Now build correct address range informaiton */
1066     HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses);
1067 
1068     /* Loop every bus */
1069     DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
1070     PciSlot.u.bits.Reserved = 0;
1071     for (i = 0; i < PciRegistryInfo->NoBuses; i++)
1072     {
1073         /* Get the bus handler */
1074         BusHandler = HalHandlerForBus(PCIBus, i);
1075 
1076         /* Loop every device */
1077         for (j = 0; j < 32; j++)
1078         {
1079             /* Loop every function */
1080             PciSlot.u.bits.DeviceNumber = j;
1081             for (k = 0; k < 8; k++)
1082             {
1083                 /* Build the final slot structure */
1084                 PciSlot.u.bits.FunctionNumber = k;
1085 
1086                 /* Read the configuration information */
1087                 HalpReadPCIConfig(BusHandler,
1088                                   PciSlot,
1089                                   PciData,
1090                                   0,
1091                                   PCI_COMMON_HDR_LENGTH);
1092 
1093                 /* Skip if this is an invalid function */
1094                 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
1095 
1096                 /* Print out the entry */
1097                 HalpDebugPciDumpBus(i, j, k, PciData);
1098 
1099                 /* Check if this is a Cardbus bridge */
1100                 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
1101                 {
1102                     /* Not supported */
1103                     DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
1104                     continue;
1105                 }
1106 
1107                 /* Check if this is a PCI device */
1108                 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE)
1109                 {
1110                     /* Check if it has an interrupt pin and line registered */
1111                     if ((PciData->u.type1.InterruptPin) &&
1112                         (PciData->u.type1.InterruptLine))
1113                     {
1114                         /* Check if this interrupt line is connected to the bus */
1115                         if (PciData->u.type1.InterruptLine < 16)
1116                         {
1117                             /* Is this an IDE device? */
1118                             if (!HalpIsIdeDevice(PciData))
1119                             {
1120                                 /* We'll mask out this interrupt then */
1121                                 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
1122                                          PciData->u.type1.InterruptLine);
1123                                 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine);
1124                             }
1125                         }
1126                     }
1127                 }
1128 
1129                 /* Check for broken Intel chips */
1130                 if (PciData->VendorID == 0x8086)
1131                 {
1132                     /* Check for broken 82830 PCI controller */
1133                     if ((PciData->DeviceID == 0x04A3) &&
1134                         (PciData->RevisionID < 0x11))
1135                     {
1136                         /* Skip */
1137                         DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
1138                         continue;
1139                     }
1140 
1141                     /* Check for broken 82378 PCI-to-ISA Bridge */
1142                     if ((PciData->DeviceID == 0x0484) &&
1143                         (PciData->RevisionID <= 3))
1144                     {
1145                         /* Skip */
1146                         DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
1147                         continue;
1148                     }
1149 
1150                     /* Check for broken 82450 PCI Bridge */
1151                     if ((PciData->DeviceID == 0x84C4) &&
1152                         (PciData->RevisionID <= 4))
1153                     {
1154                         DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
1155                         continue;
1156                     }
1157                 }
1158 
1159                 /* Do we know this card? */
1160                 if (!ExtendedAddressDecoding)
1161                 {
1162                     /* Check for it */
1163                     if (HalpIsRecognizedCard(PciRegistryInfo,
1164                                              PciData,
1165                                              HALP_CARD_FEATURE_FULL_DECODE))
1166                     {
1167                         /* We'll do chipset checks later */
1168                         DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1169                         ExtendedAddressDecoding = TRUE;
1170                     }
1171                 }
1172 
1173                 /* Now check the registry for chipset hacks */
1174                 Status = HalpGetChipHacks(PciData->VendorID,
1175                                           PciData->DeviceID,
1176                                           PciData->RevisionID,
1177                                           &HackFlags);
1178                 if (NT_SUCCESS(Status))
1179                 {
1180                     /* Check for broken ACPI routing */
1181                     if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING)
1182                     {
1183                         DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1184                         continue;
1185                     }
1186 
1187                     /* Check for broken ACPI timer */
1188                     if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER)
1189                     {
1190                          DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1191                          continue;
1192                     }
1193 
1194                     /* Check for hibernate-disable */
1195                     if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE)
1196                     {
1197                         DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1198                         continue;
1199                     }
1200 
1201                     /* Check for USB controllers that generate SMIs */
1202                     if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE)
1203                     {
1204                         DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1205                         continue;
1206                     }
1207                 }
1208 
1209                 /* Terminate the entry */
1210                 DbgPrint("\n");
1211             }
1212         }
1213     }
1214 
1215     /* Initialize NMI Crash Flag */
1216     HalpGetNMICrashFlag();
1217 
1218     /* Free the registry data */
1219     ExFreePoolWithTag(PciRegistryInfo, TAG_HAL);
1220 
1221     /* Tell PnP if this hard supports correct decoding */
1222     HalpMarkChipsetDecode(ExtendedAddressDecoding);
1223     DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1224 #endif
1225 }
1226 
1227 INIT_FUNCTION
1228 VOID
1229 NTAPI
1230 HalpInitBusHandlers(VOID)
1231 {
1232     /* Register the HAL Bus Handler support */
1233     HalpRegisterInternalBusHandlers();
1234 }
1235 
1236 INIT_FUNCTION
1237 VOID
1238 NTAPI
1239 HalpRegisterKdSupportFunctions(VOID)
1240 {
1241     /* Register PCI Device Functions */
1242     KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
1243     KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging;
1244 
1245     /* Register memory functions */
1246 #ifndef _MINIHAL_
1247 #if (NTDDI_VERSION >= NTDDI_VISTA)
1248     KdMapPhysicalMemory64 = HalpMapPhysicalMemory64Vista;
1249     KdUnmapVirtualAddress = HalpUnmapVirtualAddressVista;
1250 #else
1251     KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
1252     KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
1253 #endif
1254 #endif
1255 
1256     /* Register ACPI stub */
1257     KdCheckPowerButton = HalpCheckPowerButton;
1258 }
1259 
1260 NTSTATUS
1261 NTAPI
1262 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,
1263                         IN PUNICODE_STRING DriverClassName,
1264                         IN PDRIVER_OBJECT DriverObject,
1265                         IN PDEVICE_OBJECT DeviceObject,
1266                         IN INTERFACE_TYPE BusType,
1267                         IN ULONG BusNumber,
1268                         IN ULONG SlotNumber,
1269                         IN OUT PCM_RESOURCE_LIST *AllocatedResources)
1270 {
1271     PBUS_HANDLER Handler;
1272     NTSTATUS Status;
1273     PAGED_CODE();
1274     DPRINT1("Slot assignment for %d on bus %u\n", BusType, BusNumber);
1275 
1276     /* Find the handler */
1277     Handler = HalReferenceHandlerForBus(BusType, BusNumber);
1278     if (!Handler) return STATUS_NOT_FOUND;
1279 
1280     /* Do the assignment */
1281     Status = Handler->AssignSlotResources(Handler,
1282                                           Handler,
1283                                           RegistryPath,
1284                                           DriverClassName,
1285                                           DriverObject,
1286                                           DeviceObject,
1287                                           SlotNumber,
1288                                           AllocatedResources);
1289 
1290     /* Dereference the handler and return */
1291     HalDereferenceBusHandler(Handler);
1292     return Status;
1293 }
1294 
1295 BOOLEAN
1296 NTAPI
1297 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
1298                               IN OUT PULONG AddressSpace,
1299                               OUT PPHYSICAL_ADDRESS TranslatedAddress,
1300                               IN OUT PULONG_PTR Context,
1301                               IN BOOLEAN NextBus)
1302 {
1303     PHAL_BUS_HANDLER BusHandler;
1304     PBUS_HANDLER Handler;
1305     PLIST_ENTRY NextEntry;
1306     ULONG ContextValue;
1307 
1308     /* Make sure we have a context */
1309     if (!Context) return FALSE;
1310     ASSERT((*Context) || (NextBus == TRUE));
1311 
1312     /* Read the context */
1313     ContextValue = *Context;
1314 
1315     /* Find the bus handler */
1316     Handler = HalpContextToBusHandler(ContextValue);
1317     if (!Handler) return FALSE;
1318 
1319     /* Check if this is an ongoing lookup */
1320     if (NextBus)
1321     {
1322         /* Get the HAL bus handler */
1323         BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
1324         NextEntry = &BusHandler->AllHandlers;
1325 
1326         /* Get the next one if we were already with one */
1327         if (ContextValue) NextEntry = NextEntry->Flink;
1328 
1329         /* Start scanning */
1330         while (TRUE)
1331         {
1332             /* Check if this is the last one */
1333             if (NextEntry == &HalpAllBusHandlers)
1334             {
1335                 /* Quit */
1336                 *Context = 1;
1337                 return FALSE;
1338             }
1339 
1340             /* Call this translator */
1341             BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers);
1342             if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType,
1343                                        BusHandler->Handler.BusNumber,
1344                                        BusAddress,
1345                                        AddressSpace,
1346                                        TranslatedAddress)) break;
1347 
1348             /* Try the next one */
1349             NextEntry = NextEntry->Flink;
1350         }
1351 
1352         /* If we made it, we're done */
1353         *Context = (ULONG_PTR)&BusHandler->Handler;
1354         return TRUE;
1355     }
1356 
1357     /* Try the first one through */
1358     if (!HalTranslateBusAddress(Handler->InterfaceType,
1359                                 Handler->BusNumber,
1360                                 BusAddress,
1361                                 AddressSpace,
1362                                 TranslatedAddress)) return FALSE;
1363 
1364     /* Remember for next time */
1365     *Context = (ULONG_PTR)Handler;
1366     return TRUE;
1367 }
1368 
1369 BOOLEAN
1370 NTAPI
1371 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1372                         IN ULONG BusNumber,
1373                         IN PHYSICAL_ADDRESS BusAddress,
1374                         IN OUT PULONG AddressSpace,
1375                         OUT PPHYSICAL_ADDRESS TranslatedAddress)
1376 {
1377     PBUS_HANDLER Handler;
1378     BOOLEAN Status;
1379 
1380     /* Find the handler */
1381     Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
1382     if (!(Handler) || !(Handler->TranslateBusAddress))
1383     {
1384         DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType, BusNumber, Handler, BusAddress);
1385         return FALSE;
1386     }
1387 
1388     /* Do the assignment */
1389     Status = Handler->TranslateBusAddress(Handler,
1390                                           Handler,
1391                                           BusAddress,
1392                                           AddressSpace,
1393                                           TranslatedAddress);
1394 
1395     /* Dereference the handler and return */
1396     HalDereferenceBusHandler(Handler);
1397     return Status;
1398 }
1399 
1400 /* PUBLIC FUNCTIONS **********************************************************/
1401 
1402 /*
1403  * @implemented
1404  */
1405 NTSTATUS
1406 NTAPI
1407 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList)
1408 {
1409     PBUS_HANDLER Handler;
1410     ULONG Status;
1411     PAGED_CODE();
1412 
1413     /* Find the handler */
1414     Handler = HalReferenceHandlerForBus((*ResourceList)->InterfaceType,
1415                                         (*ResourceList)->BusNumber);
1416     if (!Handler) return STATUS_SUCCESS;
1417 
1418     /* Do the assignment */
1419     Status = Handler->AdjustResourceList(Handler,
1420                                          Handler,
1421                                          ResourceList);
1422 
1423     /* Dereference the handler and return */
1424     HalDereferenceBusHandler(Handler);
1425     return Status;
1426 }
1427 
1428 /*
1429  * @implemented
1430  */
1431 NTSTATUS
1432 NTAPI
1433 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,
1434                        IN PUNICODE_STRING DriverClassName,
1435                        IN PDRIVER_OBJECT DriverObject,
1436                        IN PDEVICE_OBJECT DeviceObject,
1437                        IN INTERFACE_TYPE BusType,
1438                        IN ULONG BusNumber,
1439                        IN ULONG SlotNumber,
1440                        IN OUT PCM_RESOURCE_LIST *AllocatedResources)
1441 {
1442     PAGED_CODE();
1443 
1444     /* Check the bus type */
1445     if (BusType != PCIBus)
1446     {
1447         /* Call our internal handler */
1448         return HalpAssignSlotResources(RegistryPath,
1449                                        DriverClassName,
1450                                        DriverObject,
1451                                        DeviceObject,
1452                                        BusType,
1453                                        BusNumber,
1454                                        SlotNumber,
1455                                        AllocatedResources);
1456     }
1457     else
1458     {
1459         /* Call the PCI registered function */
1460         return HalPciAssignSlotResources(RegistryPath,
1461                                          DriverClassName,
1462                                          DriverObject,
1463                                          DeviceObject,
1464                                          PCIBus,
1465                                          BusNumber,
1466                                          SlotNumber,
1467                                          AllocatedResources);
1468     }
1469 }
1470 
1471 /*
1472  * @implemented
1473  */
1474 ULONG
1475 NTAPI
1476 HalGetBusData(IN BUS_DATA_TYPE BusDataType,
1477               IN ULONG BusNumber,
1478               IN ULONG SlotNumber,
1479               IN PVOID Buffer,
1480               IN ULONG Length)
1481 {
1482     /* Call the extended function */
1483     return HalGetBusDataByOffset(BusDataType,
1484                                  BusNumber,
1485                                  SlotNumber,
1486                                  Buffer,
1487                                  0,
1488                                  Length);
1489 }
1490 
1491 /*
1492  * @implemented
1493  */
1494 ULONG
1495 NTAPI
1496 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1497                       IN ULONG BusNumber,
1498                       IN ULONG SlotNumber,
1499                       IN PVOID Buffer,
1500                       IN ULONG Offset,
1501                       IN ULONG Length)
1502 {
1503     PBUS_HANDLER Handler;
1504     ULONG Status;
1505 
1506     /* Find the handler */
1507     Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
1508     if (!Handler) return 0;
1509 
1510     /* Do the assignment */
1511     Status = Handler->GetBusData(Handler,
1512                                  Handler,
1513                                  SlotNumber,
1514                                  Buffer,
1515                                  Offset,
1516                                  Length);
1517 
1518     /* Dereference the handler and return */
1519     HalDereferenceBusHandler(Handler);
1520     return Status;
1521 }
1522 
1523 /*
1524  * @implemented
1525  */
1526 ULONG
1527 NTAPI
1528 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
1529                       IN ULONG BusNumber,
1530                       IN ULONG BusInterruptLevel,
1531                       IN ULONG BusInterruptVector,
1532                       OUT PKIRQL Irql,
1533                       OUT PKAFFINITY Affinity)
1534 {
1535     PBUS_HANDLER Handler;
1536     ULONG Vector;
1537     PAGED_CODE();
1538 
1539     /* Defaults */
1540     *Irql = 0;
1541     *Affinity = 0;
1542 
1543     /* Find the handler */
1544     Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
1545     if (!Handler) return 0;
1546 
1547     /* Do the assignment */
1548     Vector = Handler->GetInterruptVector(Handler,
1549                                          Handler,
1550                                          BusInterruptLevel,
1551                                          BusInterruptVector,
1552                                          Irql,
1553                                          Affinity);
1554     if ((Vector != IRQ2VECTOR(BusInterruptLevel)) ||
1555         (*Irql != VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel))))
1556     {
1557         DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1558                 *Irql, Vector, BusInterruptLevel, BusInterruptVector);
1559         DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1560                 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)),
1561                 IRQ2VECTOR(BusInterruptLevel));
1562     }
1563 
1564     /* Dereference the handler and return */
1565     HalDereferenceBusHandler(Handler);
1566     return Vector;
1567 }
1568 
1569 /*
1570  * @implemented
1571  */
1572 ULONG
1573 NTAPI
1574 HalSetBusData(IN BUS_DATA_TYPE BusDataType,
1575               IN ULONG BusNumber,
1576               IN ULONG SlotNumber,
1577               IN PVOID Buffer,
1578               IN ULONG Length)
1579 {
1580     /* Call the extended function */
1581     return HalSetBusDataByOffset(BusDataType,
1582                                  BusNumber,
1583                                  SlotNumber,
1584                                  Buffer,
1585                                  0,
1586                                  Length);
1587 }
1588 
1589 /*
1590  * @implemented
1591  */
1592 ULONG
1593 NTAPI
1594 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1595                       IN ULONG BusNumber,
1596                       IN ULONG SlotNumber,
1597                       IN PVOID Buffer,
1598                       IN ULONG Offset,
1599                       IN ULONG Length)
1600 {
1601     PBUS_HANDLER Handler;
1602     ULONG Status;
1603 
1604     /* Find the handler */
1605     Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
1606     if (!Handler) return 0;
1607 
1608     /* Do the assignment */
1609     Status = Handler->SetBusData(Handler,
1610                                  Handler,
1611                                  SlotNumber,
1612                                  Buffer,
1613                                  Offset,
1614                                  Length);
1615 
1616     /* Dereference the handler and return */
1617     HalDereferenceBusHandler(Handler);
1618     return Status;
1619 }
1620 
1621 /*
1622  * @implemented
1623  */
1624 BOOLEAN
1625 NTAPI
1626 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1627                        IN ULONG BusNumber,
1628                        IN PHYSICAL_ADDRESS BusAddress,
1629                        IN OUT PULONG AddressSpace,
1630                        OUT PPHYSICAL_ADDRESS TranslatedAddress)
1631 {
1632     /* Look as the bus type */
1633     if (InterfaceType == PCIBus)
1634     {
1635         /* Call the PCI registered function */
1636         return HalPciTranslateBusAddress(PCIBus,
1637                                          BusNumber,
1638                                          BusAddress,
1639                                          AddressSpace,
1640                                          TranslatedAddress);
1641     }
1642     else
1643     {
1644         /* Call the bus handler */
1645         return HaliTranslateBusAddress(InterfaceType,
1646                                        BusNumber,
1647                                        BusAddress,
1648                                        AddressSpace,
1649                                        TranslatedAddress);
1650     }
1651 }
1652 
1653 /* EOF */
1654