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