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