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