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