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