xref: /reactos/hal/halx86/legacy/bussupp.c (revision 23373acb)
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, SubClassName, VendorName, ProductName, SubVendorName;
813     ULONG Length;
814     CHAR LookupString[16] = "";
815     CHAR bSubClassName[64] = "";
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 += 6;
828         sprintf(LookupString, "\t%02x  ", PciData->SubClass);
829         SubClassName = strstr(ClassName, LookupString);
830         if (SubClassName)
831         {
832             /* Copy the subclass into our buffer */
833             SubClassName += 5;
834             p = strpbrk(SubClassName, "\r\n");
835             Length = p - SubClassName;
836             if (Length >= sizeof(bSubClassName)) Length = sizeof(bSubClassName) - 1;
837             strncpy(bSubClassName, SubClassName, Length);
838             bSubClassName[Length] = '\0';
839         }
840     }
841 
842     /* Isolate the vendor name */
843     sprintf(LookupString, "\r\n%04x  ", PciData->VendorID);
844     VendorName = strstr((PCHAR)VendorTable, LookupString);
845     if (VendorName)
846     {
847         /* Copy the vendor name into our buffer */
848         VendorName += 8;
849         p = strpbrk(VendorName, "\r\n");
850         Length = p - VendorName;
851         if (Length >= sizeof(bVendorName)) Length = sizeof(bVendorName) - 1;
852         strncpy(bVendorName, VendorName, Length);
853         bVendorName[Length] = '\0';
854 
855         /* Isolate the product name */
856         sprintf(LookupString, "\t%04x  ", PciData->DeviceID);
857         ProductName = strstr(VendorName, LookupString);
858         if (ProductName)
859         {
860             /* Copy the product name into our buffer */
861             ProductName += 7;
862             p = strpbrk(ProductName, "\r\n");
863             Length = p - ProductName;
864             if (Length >= sizeof(bProductName)) Length = sizeof(bProductName) - 1;
865             strncpy(bProductName, ProductName, Length);
866             bProductName[Length] = '\0';
867 
868             /* Isolate the subvendor and subsystem name */
869             sprintf(LookupString,
870                     "\t\t%04x %04x  ",
871                     PciData->u.type0.SubVendorID,
872                     PciData->u.type0.SubSystemID);
873             SubVendorName = strstr(ProductName, LookupString);
874             if (SubVendorName)
875             {
876                 /* Copy the subvendor name into our buffer */
877                 SubVendorName += 13;
878                 p = strpbrk(SubVendorName, "\r\n");
879                 Length = p - SubVendorName;
880                 if (Length >= sizeof(bSubVendorName)) Length = sizeof(bSubVendorName) - 1;
881                 strncpy(bSubVendorName, SubVendorName, Length);
882                 bSubVendorName[Length] = '\0';
883             }
884         }
885     }
886 
887     /* Print out the data */
888     DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
889              "\tSubsystem: %s [%04x:%04x]\n",
890              i,
891              j,
892              k,
893              bSubClassName,
894              PciData->BaseClass,
895              PciData->SubClass,
896              bVendorName,
897              bProductName,
898              PciData->VendorID,
899              PciData->DeviceID,
900              PciData->RevisionID,
901              bSubVendorName,
902              PciData->u.type0.SubVendorID,
903              PciData->u.type0.SubSystemID);
904 
905     /* Print out and decode flags */
906     DbgPrint("\tFlags:");
907     if (PciData->Command & PCI_ENABLE_BUS_MASTER) DbgPrint(" bus master,");
908     if (PciData->Status & PCI_STATUS_66MHZ_CAPABLE) DbgPrint(" 66MHz,");
909     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x000) DbgPrint(" fast devsel,");
910     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x200) DbgPrint(" medium devsel,");
911     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x400) DbgPrint(" slow devsel,");
912     if ((PciData->Status & PCI_STATUS_DEVSEL) == 0x600) DbgPrint(" unknown devsel,");
913     DbgPrint(" latency %d", PciData->LatencyTimer);
914     if (PciData->u.type0.InterruptPin != 0 &&
915         PciData->u.type0.InterruptLine != 0 &&
916         PciData->u.type0.InterruptLine != 0xFF) DbgPrint(", IRQ %02d", PciData->u.type0.InterruptLine);
917     else if (PciData->u.type0.InterruptPin != 0) DbgPrint(", IRQ assignment required");
918     DbgPrint("\n");
919 
920     /* Scan addresses */
921     Size = 0;
922     for (b = 0; b < PCI_TYPE0_ADDRESSES; b++)
923     {
924         /* Check for a BAR */
925         Mem = PciData->u.type0.BaseAddresses[b];
926         if (Mem)
927         {
928             /* Decode the address type */
929             if (Mem & PCI_ADDRESS_IO_SPACE)
930             {
931                 /* Guess the size */
932                 Size = 1 << 2;
933                 while (!(Mem & Size) && (Size)) Size <<= 1;
934 
935                 /* Print it out */
936                 DbgPrint("\tI/O ports at %04lx", Mem & PCI_ADDRESS_IO_ADDRESS_MASK);
937                 ShowSize(Size);
938             }
939             else
940             {
941                 /* Guess the size */
942                 Size = 1 << 8;
943                 while (!(Mem & Size) && (Size)) Size <<= 1;
944 
945                 /* Print it out */
946                 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
947                          Mem & PCI_ADDRESS_MEMORY_ADDRESS_MASK,
948                          (Mem & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT ? 32 : 64,
949                          (Mem & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? "" : "non-");
950                 ShowSize(Size);
951             }
952         }
953     }
954 }
955 #endif
956 
957 INIT_FUNCTION
958 VOID
959 NTAPI
960 HalpInitializePciBus(VOID)
961 {
962 #ifndef _MINIHAL_
963     PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
964     UCHAR PciType;
965     PCI_SLOT_NUMBER PciSlot;
966     ULONG i, j, k;
967     UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH];
968     PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer;
969     PBUS_HANDLER BusHandler;
970     ULONG HackFlags;
971     BOOLEAN ExtendedAddressDecoding = FALSE;
972     NTSTATUS Status;
973 
974     /* Query registry information */
975     PciRegistryInfo = HalpQueryPciRegistryInfo();
976     if (!PciRegistryInfo) return;
977 
978     /* Initialize the PCI configuration lock */
979     KeInitializeSpinLock(&HalpPCIConfigLock);
980 
981     /* Get the type and free the info structure */
982     PciType = PciRegistryInfo->HardwareMechanism & 0xF;
983 
984     /* Check if this is a type 2 PCI bus with at least one bus */
985     if ((PciRegistryInfo->NoBuses) && (PciType == 2))
986     {
987         /* Setup the PCI slot */
988         PciSlot.u.bits.Reserved = 0;
989         PciSlot.u.bits.FunctionNumber = 0;
990 
991         /* Loop all slots */
992         for (i = 0; i < 32; i++)
993         {
994             /* Try to setup a Type 2 PCI slot */
995             PciType = 2;
996             BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE);
997             if (!BusHandler) break;
998 
999             /* Now check if it's valid */
1000             if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
1001 
1002             /* Heh, the BIOS lied... try Type 1 */
1003             PciType = 1;
1004             BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE);
1005             if (!BusHandler) break;
1006 
1007             /* Now check if it's valid */
1008             if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break;
1009 
1010             /* Keep trying */
1011             PciType = 2;
1012         }
1013 
1014         /* Now allocate the correct kind of handler */
1015         HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE);
1016     }
1017 
1018     /* Okay, now loop all PCI bridges */
1019     do
1020     {
1021         /* Loop all PCI buses */
1022         for (i = 0; i < PciRegistryInfo->NoBuses; i++)
1023         {
1024             /* Check if we have a handler for it */
1025             if (!HalHandlerForBus(PCIBus, i))
1026             {
1027                 /* Allocate it */
1028                 HalpAllocateAndInitPciBusHandler(PciType, i, FALSE);
1029             }
1030         }
1031         /* Go to the next bridge */
1032     } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses));
1033 
1034     /* Now build correct address range informaiton */
1035     HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses);
1036 
1037     /* Loop every bus */
1038     DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
1039     PciSlot.u.bits.Reserved = 0;
1040     for (i = 0; i < PciRegistryInfo->NoBuses; i++)
1041     {
1042         /* Get the bus handler */
1043         BusHandler = HalHandlerForBus(PCIBus, i);
1044 
1045         /* Loop every device */
1046         for (j = 0; j < 32; j++)
1047         {
1048             /* Loop every function */
1049             PciSlot.u.bits.DeviceNumber = j;
1050             for (k = 0; k < 8; k++)
1051             {
1052                 /* Build the final slot structure */
1053                 PciSlot.u.bits.FunctionNumber = k;
1054 
1055                 /* Read the configuration information */
1056                 HalpReadPCIConfig(BusHandler,
1057                                   PciSlot,
1058                                   PciData,
1059                                   0,
1060                                   PCI_COMMON_HDR_LENGTH);
1061 
1062                 /* Skip if this is an invalid function */
1063                 if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
1064 
1065                 /* Print out the entry */
1066                 HalpDebugPciDumpBus(i, j, k, PciData);
1067 
1068                 /* Check if this is a Cardbus bridge */
1069                 if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
1070                 {
1071                     /* Not supported */
1072                     DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
1073                     continue;
1074                 }
1075 
1076                 /* Check if this is a PCI device */
1077                 if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE)
1078                 {
1079                     /* Check if it has an interrupt pin and line registered */
1080                     if ((PciData->u.type1.InterruptPin) &&
1081                         (PciData->u.type1.InterruptLine))
1082                     {
1083                         /* Check if this interrupt line is connected to the bus */
1084                         if (PciData->u.type1.InterruptLine < 16)
1085                         {
1086                             /* Is this an IDE device? */
1087                             if (!HalpIsIdeDevice(PciData))
1088                             {
1089                                 /* We'll mask out this interrupt then */
1090                                 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
1091                                          PciData->u.type1.InterruptLine);
1092                                 HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine);
1093                             }
1094                         }
1095                     }
1096                 }
1097 
1098                 /* Check for broken Intel chips */
1099                 if (PciData->VendorID == 0x8086)
1100                 {
1101                     /* Check for broken 82830 PCI controller */
1102                     if ((PciData->DeviceID == 0x04A3) &&
1103                         (PciData->RevisionID < 0x11))
1104                     {
1105                         /* Skip */
1106                         DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
1107                         continue;
1108                     }
1109 
1110                     /* Check for broken 82378 PCI-to-ISA Bridge */
1111                     if ((PciData->DeviceID == 0x0484) &&
1112                         (PciData->RevisionID <= 3))
1113                     {
1114                         /* Skip */
1115                         DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
1116                         continue;
1117                     }
1118 
1119                     /* Check for broken 82450 PCI Bridge */
1120                     if ((PciData->DeviceID == 0x84C4) &&
1121                         (PciData->RevisionID <= 4))
1122                     {
1123                         DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
1124                         continue;
1125                     }
1126                 }
1127 
1128                 /* Do we know this card? */
1129                 if (!ExtendedAddressDecoding)
1130                 {
1131                     /* Check for it */
1132                     if (HalpIsRecognizedCard(PciRegistryInfo,
1133                                              PciData,
1134                                              HALP_CARD_FEATURE_FULL_DECODE))
1135                     {
1136                         /* We'll do chipset checks later */
1137                         DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1138                         ExtendedAddressDecoding = TRUE;
1139                     }
1140                 }
1141 
1142                 /* Now check the registry for chipset hacks */
1143                 Status = HalpGetChipHacks(PciData->VendorID,
1144                                           PciData->DeviceID,
1145                                           PciData->RevisionID,
1146                                           &HackFlags);
1147                 if (NT_SUCCESS(Status))
1148                 {
1149                     /* Check for broken ACPI routing */
1150                     if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING)
1151                     {
1152                         DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1153                         continue;
1154                     }
1155 
1156                     /* Check for broken ACPI timer */
1157                     if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER)
1158                     {
1159                          DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1160                          continue;
1161                     }
1162 
1163                     /* Check for hibernate-disable */
1164                     if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE)
1165                     {
1166                         DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1167                         continue;
1168                     }
1169 
1170                     /* Check for USB controllers that generate SMIs */
1171                     if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE)
1172                     {
1173                         DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1174                         continue;
1175                     }
1176                 }
1177 
1178                 /* Terminate the entry */
1179                 DbgPrint("\n");
1180             }
1181         }
1182     }
1183 
1184     /* Initialize NMI Crash Flag */
1185     HalpGetNMICrashFlag();
1186 
1187     /* Free the registry data */
1188     ExFreePoolWithTag(PciRegistryInfo, TAG_HAL);
1189 
1190     /* Tell PnP if this hard supports correct decoding */
1191     HalpMarkChipsetDecode(ExtendedAddressDecoding);
1192     DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1193 #endif
1194 }
1195 
1196 INIT_FUNCTION
1197 VOID
1198 NTAPI
1199 HalpInitBusHandlers(VOID)
1200 {
1201     /* Register the HAL Bus Handler support */
1202     HalpRegisterInternalBusHandlers();
1203 }
1204 
1205 INIT_FUNCTION
1206 VOID
1207 NTAPI
1208 HalpRegisterKdSupportFunctions(VOID)
1209 {
1210     /* Register PCI Device Functions */
1211     KdSetupPciDeviceForDebugging = HalpSetupPciDeviceForDebugging;
1212     KdReleasePciDeviceforDebugging = HalpReleasePciDeviceForDebugging;
1213 
1214     /* Register memory functions */
1215 #ifndef _MINIHAL_
1216 #if (NTDDI_VERSION >= NTDDI_VISTA)
1217     KdMapPhysicalMemory64 = HalpMapPhysicalMemory64Vista;
1218     KdUnmapVirtualAddress = HalpUnmapVirtualAddressVista;
1219 #else
1220     KdMapPhysicalMemory64 = HalpMapPhysicalMemory64;
1221     KdUnmapVirtualAddress = HalpUnmapVirtualAddress;
1222 #endif
1223 #endif
1224 
1225     /* Register ACPI stub */
1226     KdCheckPowerButton = HalpCheckPowerButton;
1227 }
1228 
1229 NTSTATUS
1230 NTAPI
1231 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath,
1232                         IN PUNICODE_STRING DriverClassName,
1233                         IN PDRIVER_OBJECT DriverObject,
1234                         IN PDEVICE_OBJECT DeviceObject,
1235                         IN INTERFACE_TYPE BusType,
1236                         IN ULONG BusNumber,
1237                         IN ULONG SlotNumber,
1238                         IN OUT PCM_RESOURCE_LIST *AllocatedResources)
1239 {
1240     PBUS_HANDLER Handler;
1241     NTSTATUS Status;
1242     PAGED_CODE();
1243     DPRINT1("Slot assignment for %d on bus %u\n", BusType, BusNumber);
1244 
1245     /* Find the handler */
1246     Handler = HalReferenceHandlerForBus(BusType, BusNumber);
1247     if (!Handler) return STATUS_NOT_FOUND;
1248 
1249     /* Do the assignment */
1250     Status = Handler->AssignSlotResources(Handler,
1251                                           Handler,
1252                                           RegistryPath,
1253                                           DriverClassName,
1254                                           DriverObject,
1255                                           DeviceObject,
1256                                           SlotNumber,
1257                                           AllocatedResources);
1258 
1259     /* Dereference the handler and return */
1260     HalDereferenceBusHandler(Handler);
1261     return Status;
1262 }
1263 
1264 BOOLEAN
1265 NTAPI
1266 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress,
1267                               IN OUT PULONG AddressSpace,
1268                               OUT PPHYSICAL_ADDRESS TranslatedAddress,
1269                               IN OUT PULONG_PTR Context,
1270                               IN BOOLEAN NextBus)
1271 {
1272     PHAL_BUS_HANDLER BusHandler;
1273     PBUS_HANDLER Handler;
1274     PLIST_ENTRY NextEntry;
1275     ULONG ContextValue;
1276 
1277     /* Make sure we have a context */
1278     if (!Context) return FALSE;
1279     ASSERT((*Context) || (NextBus == TRUE));
1280 
1281     /* Read the context */
1282     ContextValue = *Context;
1283 
1284     /* Find the bus handler */
1285     Handler = HalpContextToBusHandler(ContextValue);
1286     if (!Handler) return FALSE;
1287 
1288     /* Check if this is an ongoing lookup */
1289     if (NextBus)
1290     {
1291         /* Get the HAL bus handler */
1292         BusHandler = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
1293         NextEntry = &BusHandler->AllHandlers;
1294 
1295         /* Get the next one if we were already with one */
1296         if (ContextValue) NextEntry = NextEntry->Flink;
1297 
1298         /* Start scanning */
1299         while (TRUE)
1300         {
1301             /* Check if this is the last one */
1302             if (NextEntry == &HalpAllBusHandlers)
1303             {
1304                 /* Quit */
1305                 *Context = 1;
1306                 return FALSE;
1307             }
1308 
1309             /* Call this translator */
1310             BusHandler = CONTAINING_RECORD(NextEntry, HAL_BUS_HANDLER, AllHandlers);
1311             if (HalTranslateBusAddress(BusHandler->Handler.InterfaceType,
1312                                        BusHandler->Handler.BusNumber,
1313                                        BusAddress,
1314                                        AddressSpace,
1315                                        TranslatedAddress)) break;
1316 
1317             /* Try the next one */
1318             NextEntry = NextEntry->Flink;
1319         }
1320 
1321         /* If we made it, we're done */
1322         *Context = (ULONG_PTR)Handler;
1323         return TRUE;
1324     }
1325 
1326     /* Try the first one through */
1327     if (!HalTranslateBusAddress(Handler->InterfaceType,
1328                                 Handler->BusNumber,
1329                                 BusAddress,
1330                                 AddressSpace,
1331                                 TranslatedAddress)) return FALSE;
1332 
1333     /* Remember for next time */
1334     *Context = (ULONG_PTR)Handler;
1335     return TRUE;
1336 }
1337 
1338 BOOLEAN
1339 NTAPI
1340 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1341                         IN ULONG BusNumber,
1342                         IN PHYSICAL_ADDRESS BusAddress,
1343                         IN OUT PULONG AddressSpace,
1344                         OUT PPHYSICAL_ADDRESS TranslatedAddress)
1345 {
1346     PBUS_HANDLER Handler;
1347     BOOLEAN Status;
1348 
1349     /* Find the handler */
1350     Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
1351     if (!(Handler) || !(Handler->TranslateBusAddress))
1352     {
1353         DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType, BusNumber, Handler, BusAddress);
1354         return FALSE;
1355     }
1356 
1357     /* Do the assignment */
1358     Status = Handler->TranslateBusAddress(Handler,
1359                                           Handler,
1360                                           BusAddress,
1361                                           AddressSpace,
1362                                           TranslatedAddress);
1363 
1364     /* Dereference the handler and return */
1365     HalDereferenceBusHandler(Handler);
1366     return Status;
1367 }
1368 
1369 /* PUBLIC FUNCTIONS **********************************************************/
1370 
1371 /*
1372  * @implemented
1373  */
1374 NTSTATUS
1375 NTAPI
1376 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList)
1377 {
1378     PBUS_HANDLER Handler;
1379     ULONG Status;
1380     PAGED_CODE();
1381 
1382     /* Find the handler */
1383     Handler = HalReferenceHandlerForBus((*ResourceList)->InterfaceType,
1384                                         (*ResourceList)->BusNumber);
1385     if (!Handler) return STATUS_SUCCESS;
1386 
1387     /* Do the assignment */
1388     Status = Handler->AdjustResourceList(Handler,
1389                                          Handler,
1390                                          ResourceList);
1391 
1392     /* Dereference the handler and return */
1393     HalDereferenceBusHandler(Handler);
1394     return Status;
1395 }
1396 
1397 /*
1398  * @implemented
1399  */
1400 NTSTATUS
1401 NTAPI
1402 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath,
1403                        IN PUNICODE_STRING DriverClassName,
1404                        IN PDRIVER_OBJECT DriverObject,
1405                        IN PDEVICE_OBJECT DeviceObject,
1406                        IN INTERFACE_TYPE BusType,
1407                        IN ULONG BusNumber,
1408                        IN ULONG SlotNumber,
1409                        IN OUT PCM_RESOURCE_LIST *AllocatedResources)
1410 {
1411     PAGED_CODE();
1412 
1413     /* Check the bus type */
1414     if (BusType != PCIBus)
1415     {
1416         /* Call our internal handler */
1417         return HalpAssignSlotResources(RegistryPath,
1418                                        DriverClassName,
1419                                        DriverObject,
1420                                        DeviceObject,
1421                                        BusType,
1422                                        BusNumber,
1423                                        SlotNumber,
1424                                        AllocatedResources);
1425     }
1426     else
1427     {
1428         /* Call the PCI registered function */
1429         return HalPciAssignSlotResources(RegistryPath,
1430                                          DriverClassName,
1431                                          DriverObject,
1432                                          DeviceObject,
1433                                          PCIBus,
1434                                          BusNumber,
1435                                          SlotNumber,
1436                                          AllocatedResources);
1437     }
1438 }
1439 
1440 /*
1441  * @implemented
1442  */
1443 ULONG
1444 NTAPI
1445 HalGetBusData(IN BUS_DATA_TYPE BusDataType,
1446               IN ULONG BusNumber,
1447               IN ULONG SlotNumber,
1448               IN PVOID Buffer,
1449               IN ULONG Length)
1450 {
1451     /* Call the extended function */
1452     return HalGetBusDataByOffset(BusDataType,
1453                                  BusNumber,
1454                                  SlotNumber,
1455                                  Buffer,
1456                                  0,
1457                                  Length);
1458 }
1459 
1460 /*
1461  * @implemented
1462  */
1463 ULONG
1464 NTAPI
1465 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1466                       IN ULONG BusNumber,
1467                       IN ULONG SlotNumber,
1468                       IN PVOID Buffer,
1469                       IN ULONG Offset,
1470                       IN ULONG Length)
1471 {
1472     PBUS_HANDLER Handler;
1473     ULONG Status;
1474 
1475     /* Find the handler */
1476     Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
1477     if (!Handler) return 0;
1478 
1479     /* Do the assignment */
1480     Status = Handler->GetBusData(Handler,
1481                                  Handler,
1482                                  SlotNumber,
1483                                  Buffer,
1484                                  Offset,
1485                                  Length);
1486 
1487     /* Dereference the handler and return */
1488     HalDereferenceBusHandler(Handler);
1489     return Status;
1490 }
1491 
1492 /*
1493  * @implemented
1494  */
1495 ULONG
1496 NTAPI
1497 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType,
1498                       IN ULONG BusNumber,
1499                       IN ULONG BusInterruptLevel,
1500                       IN ULONG BusInterruptVector,
1501                       OUT PKIRQL Irql,
1502                       OUT PKAFFINITY Affinity)
1503 {
1504     PBUS_HANDLER Handler;
1505     ULONG Vector;
1506     PAGED_CODE();
1507 
1508     /* Defaults */
1509     *Irql = 0;
1510     *Affinity = 0;
1511 
1512     /* Find the handler */
1513     Handler = HalReferenceHandlerForBus(InterfaceType, BusNumber);
1514     if (!Handler) return 0;
1515 
1516     /* Do the assignment */
1517     Vector = Handler->GetInterruptVector(Handler,
1518                                          Handler,
1519                                          BusInterruptLevel,
1520                                          BusInterruptVector,
1521                                          Irql,
1522                                          Affinity);
1523     if ((Vector != IRQ2VECTOR(BusInterruptLevel)) ||
1524         (*Irql != VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel))))
1525     {
1526         DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1527                 *Irql, Vector, BusInterruptLevel, BusInterruptVector);
1528         DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1529                 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel)),
1530                 IRQ2VECTOR(BusInterruptLevel));
1531     }
1532 
1533     /* Dereference the handler and return */
1534     HalDereferenceBusHandler(Handler);
1535     return Vector;
1536 }
1537 
1538 /*
1539  * @implemented
1540  */
1541 ULONG
1542 NTAPI
1543 HalSetBusData(IN BUS_DATA_TYPE BusDataType,
1544               IN ULONG BusNumber,
1545               IN ULONG SlotNumber,
1546               IN PVOID Buffer,
1547               IN ULONG Length)
1548 {
1549     /* Call the extended function */
1550     return HalSetBusDataByOffset(BusDataType,
1551                                  BusNumber,
1552                                  SlotNumber,
1553                                  Buffer,
1554                                  0,
1555                                  Length);
1556 }
1557 
1558 /*
1559  * @implemented
1560  */
1561 ULONG
1562 NTAPI
1563 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType,
1564                       IN ULONG BusNumber,
1565                       IN ULONG SlotNumber,
1566                       IN PVOID Buffer,
1567                       IN ULONG Offset,
1568                       IN ULONG Length)
1569 {
1570     PBUS_HANDLER Handler;
1571     ULONG Status;
1572 
1573     /* Find the handler */
1574     Handler = HaliReferenceHandlerForConfigSpace(BusDataType, BusNumber);
1575     if (!Handler) return 0;
1576 
1577     /* Do the assignment */
1578     Status = Handler->SetBusData(Handler,
1579                                  Handler,
1580                                  SlotNumber,
1581                                  Buffer,
1582                                  Offset,
1583                                  Length);
1584 
1585     /* Dereference the handler and return */
1586     HalDereferenceBusHandler(Handler);
1587     return Status;
1588 }
1589 
1590 /*
1591  * @implemented
1592  */
1593 BOOLEAN
1594 NTAPI
1595 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
1596                        IN ULONG BusNumber,
1597                        IN PHYSICAL_ADDRESS BusAddress,
1598                        IN OUT PULONG AddressSpace,
1599                        OUT PPHYSICAL_ADDRESS TranslatedAddress)
1600 {
1601     /* Look as the bus type */
1602     if (InterfaceType == PCIBus)
1603     {
1604         /* Call the PCI registered function */
1605         return HalPciTranslateBusAddress(PCIBus,
1606                                          BusNumber,
1607                                          BusAddress,
1608                                          AddressSpace,
1609                                          TranslatedAddress);
1610     }
1611     else
1612     {
1613         /* Call the bus handler */
1614         return HaliTranslateBusAddress(InterfaceType,
1615                                        BusNumber,
1616                                        BusAddress,
1617                                        AddressSpace,
1618                                        TranslatedAddress);
1619     }
1620 }
1621 
1622 /* EOF */
1623