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
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 extern KSPIN_LOCK HalpPCIConfigLock
;
20 /* PRIVATE FUNCTIONS **********************************************************/
24 HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType
,
25 IN BUS_DATA_TYPE BusDataType
,
27 IN INTERFACE_TYPE ParentBusInterfaceType
,
28 IN ULONG ParentBusNumber
,
29 IN ULONG BusSpecificData
)
33 /* Register the bus handler */
34 HalRegisterBusHandler(InterfaceType
,
37 ParentBusInterfaceType
,
47 /* Check for a valid interface */
48 if (InterfaceType
!= InterfaceTypeUndefined
)
50 /* Allocate address ranges and zero them out */
51 Bus
->BusAddresses
= ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
52 sizeof(SUPPORTED_RANGES
),
54 RtlZeroMemory(Bus
->BusAddresses
, sizeof(SUPPORTED_RANGES
));
56 /* Build the data structure */
57 Bus
->BusAddresses
->Version
= HAL_SUPPORTED_RANGE_VERSION
;
58 Bus
->BusAddresses
->Dma
.Limit
= 7;
59 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFFFF;
60 Bus
->BusAddresses
->IO
.Limit
= 0xFFFF;
61 Bus
->BusAddresses
->IO
.SystemAddressSpace
= 1;
62 Bus
->BusAddresses
->PrefetchMemory
.Base
= 1;
65 /* Return the bus address */
72 HalpRegisterInternalBusHandlers(VOID
)
76 /* Only do processor 1 */
77 if (KeGetCurrentPrcb()->Number
) return;
79 /* Register root support */
82 /* Allocate the system bus */
83 Bus
= HalpAllocateBusHandler(Internal
,
84 ConfigurationSpaceUndefined
,
86 InterfaceTypeUndefined
,
92 Bus
->GetInterruptVector
= HalpGetSystemInterruptVector
;
93 Bus
->TranslateBusAddress
= HalpTranslateSystemBusAddress
;
96 /* Allocate the CMOS bus */
97 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
100 InterfaceTypeUndefined
,
106 Bus
->GetBusData
= HalpcGetCmosData
;
107 Bus
->SetBusData
= HalpcSetCmosData
;
110 /* Allocate the CMOS bus */
111 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
114 InterfaceTypeUndefined
,
120 Bus
->GetBusData
= HalpcGetCmosData
;
121 Bus
->SetBusData
= HalpcSetCmosData
;
124 /* Allocate ISA bus */
125 Bus
= HalpAllocateBusHandler(Isa
,
126 ConfigurationSpaceUndefined
,
134 Bus
->GetBusData
= HalpNoBusData
;
135 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFF;
136 Bus
->TranslateBusAddress
= HalpTranslateIsaBusAddress
;
139 /* No support for EISA or MCA */
140 ASSERT(HalpBusType
== MACHINE_TYPE_ISA
);
147 HalpMarkChipsetDecode(BOOLEAN OverrideEnable
)
150 UNICODE_STRING KeyString
;
151 ULONG Data
= OverrideEnable
;
152 HANDLE KeyHandle
, Handle
;
155 RtlInitUnicodeString(&KeyString
,
156 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
157 Status
= HalpOpenRegistryKey(&Handle
, 0, &KeyString
, KEY_ALL_ACCESS
, FALSE
);
158 if (NT_SUCCESS(Status
))
160 /* Open PNP Bios key */
161 RtlInitUnicodeString(&KeyString
, L
"Control\\Biosinfo\\PNPBios");
162 Status
= HalpOpenRegistryKey(&KeyHandle
,
171 /* Check if PNP BIOS key exists */
172 if (NT_SUCCESS(Status
))
174 /* Set the override value */
175 RtlInitUnicodeString(&KeyString
, L
"FullDecodeChipsetOverride");
176 Status
= ZwSetValueKey(KeyHandle
,
195 HalpAllocateAndInitPciBusHandler(IN ULONG PciType
,
197 IN BOOLEAN TestAllocation
)
200 PPCIPBUSDATA BusData
;
202 /* Allocate the bus handler */
203 Bus
= HalpAllocateBusHandler(PCIBus
,
208 sizeof(PCIPBUSDATA
));
211 Bus
->GetBusData
= HalpGetPCIData
;
212 Bus
->SetBusData
= HalpSetPCIData
;
213 Bus
->GetInterruptVector
= HalpGetPCIIntOnISABus
;
214 Bus
->AdjustResourceList
= HalpAdjustPCIResourceList
;
215 Bus
->AssignSlotResources
= HalpAssignPCISlotResources
;
216 Bus
->BusAddresses
->Dma
.Limit
= 0;
218 /* Get our custom bus data */
219 BusData
= (PPCIPBUSDATA
)Bus
->BusData
;
221 /* Setup custom bus data */
222 BusData
->CommonData
.Tag
= PCI_DATA_TAG
;
223 BusData
->CommonData
.Version
= PCI_DATA_VERSION
;
224 BusData
->CommonData
.ReadConfig
= HalpReadPCIConfig
;
225 BusData
->CommonData
.WriteConfig
= HalpWritePCIConfig
;
226 BusData
->CommonData
.Pin2Line
= HalpPCIPin2ISALine
;
227 BusData
->CommonData
.Line2Pin
= HalpPCIISALine2Pin
;
228 BusData
->MaxDevice
= PCI_MAX_DEVICES
;
229 BusData
->GetIrqRange
= HalpGetISAFixedPCIIrq
;
231 /* Initialize the bitmap */
232 RtlInitializeBitMap(&BusData
->DeviceConfigured
, BusData
->ConfiguredBits
, 256);
234 /* Check the type of PCI bus */
240 /* Copy the Type 1 handler data */
241 RtlCopyMemory(&PCIConfigHandler
,
242 &PCIConfigHandlerType1
,
243 sizeof(PCIConfigHandler
));
245 /* Set correct I/O Ports */
246 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
247 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
253 /* Copy the Type 1 handler data */
254 RtlCopyMemory(&PCIConfigHandler
,
255 &PCIConfigHandlerType2
,
256 sizeof (PCIConfigHandler
));
258 /* Set correct I/O Ports */
259 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
260 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
261 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
263 /* Only 16 devices supported, not 32 */
264 BusData
->MaxDevice
= 16;
270 DbgPrint("HAL: Unnkown PCI type\n");
273 /* Return the bus handler */
280 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler
,
281 IN PCI_SLOT_NUMBER Slot
)
283 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
284 PPCI_COMMON_CONFIG PciHeader
= (PVOID
)DataBuffer
;
288 /* Read the PCI header */
289 HalpReadPCIConfig(BusHandler
, Slot
, PciHeader
, 0, PCI_COMMON_HDR_LENGTH
);
291 /* Make sure it's a valid device */
292 if ((PciHeader
->VendorID
== PCI_INVALID_VENDORID
) ||
293 (PCI_CONFIGURATION_TYPE(PciHeader
) != PCI_DEVICE_TYPE
))
299 /* Make sure interrupt numbers make sense */
300 if (((PciHeader
->u
.type0
.InterruptPin
) &&
301 (PciHeader
->u
.type0
.InterruptPin
> 4)) ||
302 (PciHeader
->u
.type0
.InterruptLine
& 0x70))
308 /* Now scan PCI BARs */
309 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
311 /* Check what kind of address it is */
312 Address
= PciHeader
->u
.type0
.BaseAddresses
[i
];
313 if (Address
& PCI_ADDRESS_IO_SPACE
)
315 /* Highest I/O port is 65535 */
316 if (Address
> 0xFFFF) return FALSE
;
320 /* MMIO should be higher than 0x80000 */
321 if ((Address
> 0xF) && (Address
< 0x80000)) return FALSE
;
324 /* Is this a 64-bit address? */
325 if (!(Address
& PCI_ADDRESS_IO_SPACE
) &&
326 ((Address
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
))
328 /* Check the next-next entry, since this one 64-bits wide */
333 /* Header, interrupt and address data all make sense */
337 static BOOLEAN WarningsGiven
[5];
342 HalpGetChipHacks(IN USHORT VendorId
,
347 UNICODE_STRING KeyName
, ValueName
;
349 OBJECT_ATTRIBUTES ObjectAttributes
;
352 KEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
355 /* Setup the object attributes for the key */
356 RtlInitUnicodeString(&KeyName
,
357 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
359 InitializeObjectAttributes(&ObjectAttributes
,
361 OBJ_CASE_INSENSITIVE
,
366 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
367 if (!NT_SUCCESS(Status
)) return Status
;
370 swprintf(Buffer
, L
"%04X%04X", VendorId
, DeviceId
);
371 RtlInitUnicodeString(&ValueName
, Buffer
);
372 Status
= ZwQueryValueKey(KeyHandle
,
374 KeyValuePartialInformation
,
378 if (NT_SUCCESS(Status
))
380 /* Return the flags */
381 DbgPrint("\tFound HackFlags for your chipset\n");
382 *HackFlags
= *(PULONG
)PartialInfo
.Data
;
383 DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
384 *HackFlags
, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
), RevisionId
);
386 /* Does it apply to this revision? */
387 if ((RevisionId
) && (RevisionId
>= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
))))
389 /* Read the revision flags */
390 *HackFlags
= HALP_REVISION_HACK_FLAGS(*HackFlags
);
393 /* Throw out revision data */
394 *HackFlags
= HALP_HACK_FLAGS(*HackFlags
);
395 if (!*HackFlags
) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
398 /* Close the handle and return */
406 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
,
407 IN PPCI_COMMON_CONFIG PciData
,
410 ULONG ElementCount
, i
;
411 PPCI_CARD_DESCRIPTOR CardDescriptor
;
413 /* How many PCI Cards that we know about? */
414 ElementCount
= PciRegistryInfo
->ElementCount
;
415 if (!ElementCount
) return FALSE
;
417 /* Loop all descriptors */
418 CardDescriptor
= &PciRegistryInfo
->CardList
[0];
419 for (i
= 0; i
< ElementCount
; i
++, CardDescriptor
++)
421 /* Check for flag match */
422 if (CardDescriptor
->Flags
!= Flags
) continue;
424 /* Check for VID-PID match */
425 if ((CardDescriptor
->VendorID
!= PciData
->VendorID
) ||
426 (CardDescriptor
->DeviceID
!= PciData
->DeviceID
))
432 /* Check for revision match, if requested */
433 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_REVISION_ID
) &&
434 (CardDescriptor
->RevisionID
!= PciData
->RevisionID
))
440 /* Check what kind of device this is */
441 switch (PCI_CONFIGURATION_TYPE(PciData
))
444 case PCI_CARDBUS_BRIDGE_TYPE
:
446 /* This means the real device header is in the device-specific data */
447 PciData
= (PPCI_COMMON_CONFIG
)PciData
->DeviceSpecific
;
449 /* Normal PCI device */
450 case PCI_DEVICE_TYPE
:
452 /* Check for subvendor match, if requested */
453 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBVENDOR_ID
) &&
454 (CardDescriptor
->SubsystemVendorID
!= PciData
->u
.type0
.SubVendorID
))
460 /* Check for subsystem match, if requested */
461 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBSYSTEM_ID
) &&
462 (CardDescriptor
->SubsystemID
!= PciData
->u
.type0
.SubSystemID
))
471 /* PCI Bridge -- don't bother */
472 case PCI_BRIDGE_TYPE
:
480 /* This means the card isn't recognized */
487 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData
)
489 /* Simple test first */
490 if ((PciData
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
491 (PciData
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
))
493 /* The device is nice enough to admit it */
497 /* Symphony 82C101 */
498 if (PciData
->VendorID
== 0x1C1C) return TRUE
;
500 /* ALi MS4803 or M5219 */
501 if ((PciData
->VendorID
== 0x10B9) &&
502 ((PciData
->DeviceID
== 0x5215) || (PciData
->DeviceID
== 0x5219)))
507 /* Appian Technology */
508 if ((PciData
->VendorID
== 0x1097) && (PciData
->DeviceID
== 0x38)) return TRUE
;
510 /* Compaq Triflex Dual EIDE Controller */
511 if ((PciData
->VendorID
== 0xE11) && (PciData
->DeviceID
== 0xAE33)) return TRUE
;
513 /* Micron PC Tech RZ1000 */
514 if ((PciData
->VendorID
== 0x1042) && (PciData
->DeviceID
== 0x1000)) return TRUE
;
516 /* SiS 85C601 or 5513 [IDE] */
517 if ((PciData
->VendorID
== 0x1039) &&
518 ((PciData
->DeviceID
== 0x601) || (PciData
->DeviceID
== 0x5513)))
523 /* Symphony Labs W83769F */
524 if ((PciData
->VendorID
== 0x10AD) &&
525 ((PciData
->DeviceID
== 0x1) || (PciData
->DeviceID
== 0x150)))
531 if ((PciData
->VendorID
== 0x1060) && (PciData
->DeviceID
== 0x101)) return TRUE
;
533 /* You've survived */
540 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData
)
542 /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
543 return (((PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
) &&
544 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
545 (PciData
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
)) ||
546 ((PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
) &&
547 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
548 (PciData
->SubClass
== PCI_SUBCLASS_BR_CARDBUS
)));
554 HalpGetPciBridgeConfig(IN ULONG PciType
,
557 PCI_SLOT_NUMBER PciSlot
;
559 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
560 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
561 PBUS_HANDLER BusHandler
;
564 PciSlot
.u
.bits
.Reserved
= 0;
565 for (i
= 0; i
< *BusCount
; i
++)
567 /* Get the bus handler */
568 BusHandler
= HalHandlerForBus(PCIBus
, i
);
570 /* Loop every device */
571 for (j
= 0; j
< PCI_MAX_DEVICES
; j
++)
573 /* Loop every function */
574 PciSlot
.u
.bits
.DeviceNumber
= j
;
575 for (k
= 0; k
< PCI_MAX_FUNCTION
; k
++)
577 /* Build the final slot structure */
578 PciSlot
.u
.bits
.FunctionNumber
= k
;
580 /* Read the configuration information */
581 HalpReadPCIConfig(BusHandler
,
585 PCI_COMMON_HDR_LENGTH
);
587 /* Skip if this is an invalid function */
588 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
590 /* Make sure that this is a PCI bridge or a cardbus bridge */
591 if (!HalpIsBridgeDevice(PciData
)) continue;
594 if (!WarningsGiven
[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
600 /* If we exited the loop, then there's no bridge to worry about */
607 HalpFixupPciSupportedRanges(IN ULONG BusCount
)
610 PBUS_HANDLER Bus
, ParentBus
;
613 for (i
= 0; i
< BusCount
; i
++)
615 /* Get PCI bus handler */
616 Bus
= HalHandlerForBus(PCIBus
, i
);
618 /* Loop all parent buses */
619 ParentBus
= Bus
->ParentHandler
;
622 /* Should merge addresses */
623 if (!WarningsGiven
[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
625 /* Check the next parent */
626 ParentBus
= ParentBus
->ParentHandler
;
630 /* Loop all buses again */
631 for (i
= 0; i
< BusCount
; i
++)
633 /* Get PCI bus handler */
634 Bus
= HalHandlerForBus(PCIBus
, i
);
636 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
637 if (!((PPCIPBUSDATA
)Bus
->BusData
)->Subtractive
)
639 /* Loop all parent buses */
640 ParentBus
= Bus
->ParentHandler
;
643 /* But check only PCI parent buses specifically */
644 if (ParentBus
->InterfaceType
== PCIBus
)
646 /* Should trim addresses */
647 if (!WarningsGiven
[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
650 /* Check the next parent */
651 ParentBus
= ParentBus
->ParentHandler
;
656 /* Loop buses one last time */
657 for (i
= 0; i
< BusCount
; i
++)
659 /* Get the PCI bus handler */
660 Bus
= HalHandlerForBus(PCIBus
, i
);
662 /* Sort and combine (trim) bus address range information */
663 DPRINT("Warning: Bus addresses not being optimized!\n");
676 DbgPrint("%d", (int) x
);
678 else if (x
< 1048576)
680 DbgPrint("%dK", (int)(x
/ 1024));
682 else if (x
< 0x80000000)
684 DbgPrint("%dM", (int)(x
/ 1048576));
694 * These includes are required to define
695 * the ClassTable and VendorTable arrays.
697 #include "pci_classes.h"
698 #include "pci_vendors.h"
702 HalpDebugPciDumpBus(IN ULONG i
,
705 IN PPCI_COMMON_CONFIG PciData
)
707 PCHAR p
, ClassName
, Boundary
, SubClassName
, VendorName
, ProductName
, SubVendorName
;
709 CHAR LookupString
[16] = "";
710 CHAR bSubClassName
[64] = "Unknown";
711 CHAR bVendorName
[64] = "";
712 CHAR bProductName
[128] = "Unknown device";
713 CHAR bSubVendorName
[128] = "Unknown";
716 /* Isolate the class name */
717 sprintf(LookupString
, "C %02x ", PciData
->BaseClass
);
718 ClassName
= strstr((PCHAR
)ClassTable
, LookupString
);
721 /* Isolate the subclass name */
722 ClassName
+= strlen("C 00 ");
723 Boundary
= strstr(ClassName
, "\nC ");
724 sprintf(LookupString
, "\n\t%02x ", PciData
->SubClass
);
725 SubClassName
= strstr(ClassName
, LookupString
);
726 if (Boundary
&& SubClassName
> Boundary
)
732 SubClassName
= ClassName
;
736 SubClassName
+= strlen("\n\t00 ");
738 /* Copy the subclass into our buffer */
739 p
= strpbrk(SubClassName
, "\r\n");
740 Length
= p
- SubClassName
;
741 if (Length
>= sizeof(bSubClassName
)) Length
= sizeof(bSubClassName
) - 1;
742 strncpy(bSubClassName
, SubClassName
, Length
);
743 bSubClassName
[Length
] = '\0';
746 /* Isolate the vendor name */
747 sprintf(LookupString
, "\r\n%04x ", PciData
->VendorID
);
748 VendorName
= strstr((PCHAR
)VendorTable
, LookupString
);
751 /* Copy the vendor name into our buffer */
752 VendorName
+= strlen("\r\n0000 ");
753 p
= strpbrk(VendorName
, "\r\n");
754 Length
= p
- VendorName
;
755 if (Length
>= sizeof(bVendorName
)) Length
= sizeof(bVendorName
) - 1;
756 strncpy(bVendorName
, VendorName
, Length
);
757 bVendorName
[Length
] = '\0';
759 while (*p
== '\t' || *p
== '#')
761 p
= strpbrk(p
, "\r\n");
766 /* Isolate the product name */
767 sprintf(LookupString
, "\t%04x ", PciData
->DeviceID
);
768 ProductName
= strstr(VendorName
, LookupString
);
769 if (Boundary
&& ProductName
>= Boundary
)
775 /* Copy the product name into our buffer */
776 ProductName
+= strlen("\t0000 ");
777 p
= strpbrk(ProductName
, "\r\n");
778 Length
= p
- ProductName
;
779 if (Length
>= sizeof(bProductName
)) Length
= sizeof(bProductName
) - 1;
780 strncpy(bProductName
, ProductName
, Length
);
781 bProductName
[Length
] = '\0';
783 while ((*p
== '\t' && *(p
+ 1) == '\t') || *p
== '#')
785 p
= strpbrk(p
, "\r\n");
790 /* Isolate the subvendor and subsystem name */
791 sprintf(LookupString
,
793 PciData
->u
.type0
.SubVendorID
,
794 PciData
->u
.type0
.SubSystemID
);
795 SubVendorName
= strstr(ProductName
, LookupString
);
796 if (Boundary
&& SubVendorName
>= Boundary
)
798 SubVendorName
= NULL
;
802 /* Copy the subvendor name into our buffer */
803 SubVendorName
+= strlen("\t\t0000 0000 ");
804 p
= strpbrk(SubVendorName
, "\r\n");
805 Length
= p
- SubVendorName
;
806 if (Length
>= sizeof(bSubVendorName
)) Length
= sizeof(bSubVendorName
) - 1;
807 strncpy(bSubVendorName
, SubVendorName
, Length
);
808 bSubVendorName
[Length
] = '\0';
813 /* Print out the data */
814 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
815 "\tSubsystem: %s [%04x:%04x]\n",
828 PciData
->u
.type0
.SubVendorID
,
829 PciData
->u
.type0
.SubSystemID
);
831 /* Print out and decode flags */
832 DbgPrint("\tFlags:");
833 if (PciData
->Command
& PCI_ENABLE_BUS_MASTER
) DbgPrint(" bus master,");
834 if (PciData
->Status
& PCI_STATUS_66MHZ_CAPABLE
) DbgPrint(" 66MHz,");
835 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x000) DbgPrint(" fast devsel,");
836 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x200) DbgPrint(" medium devsel,");
837 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x400) DbgPrint(" slow devsel,");
838 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x600) DbgPrint(" unknown devsel,");
839 DbgPrint(" latency %d", PciData
->LatencyTimer
);
840 if (PciData
->u
.type0
.InterruptPin
!= 0 &&
841 PciData
->u
.type0
.InterruptLine
!= 0 &&
842 PciData
->u
.type0
.InterruptLine
!= 0xFF) DbgPrint(", IRQ %02d", PciData
->u
.type0
.InterruptLine
);
843 else if (PciData
->u
.type0
.InterruptPin
!= 0) DbgPrint(", IRQ assignment required");
848 for (b
= 0; b
< PCI_TYPE0_ADDRESSES
; b
++)
850 /* Check for a BAR */
851 Mem
= PciData
->u
.type0
.BaseAddresses
[b
];
854 /* Decode the address type */
855 if (Mem
& PCI_ADDRESS_IO_SPACE
)
859 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
862 DbgPrint("\tI/O ports at %04lx", Mem
& PCI_ADDRESS_IO_ADDRESS_MASK
);
869 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
872 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
873 Mem
& PCI_ADDRESS_MEMORY_ADDRESS_MASK
,
874 (Mem
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_32BIT
? 32 : 64,
875 (Mem
& PCI_ADDRESS_MEMORY_PREFETCHABLE
) ? "" : "non-");
887 HalpInitializePciBus(VOID
)
890 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
892 PCI_SLOT_NUMBER PciSlot
;
894 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
895 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
896 PBUS_HANDLER BusHandler
;
898 BOOLEAN ExtendedAddressDecoding
= FALSE
;
901 /* Query registry information */
902 PciRegistryInfo
= HalpQueryPciRegistryInfo();
903 if (!PciRegistryInfo
) return;
905 /* Initialize the PCI configuration lock */
906 KeInitializeSpinLock(&HalpPCIConfigLock
);
908 /* Get the type and free the info structure */
909 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
911 /* Check if this is a type 2 PCI bus with at least one bus */
912 if ((PciRegistryInfo
->NoBuses
) && (PciType
== 2))
914 /* Setup the PCI slot */
915 PciSlot
.u
.bits
.Reserved
= 0;
916 PciSlot
.u
.bits
.FunctionNumber
= 0;
919 for (i
= 0; i
< 32; i
++)
921 /* Try to setup a Type 2 PCI slot */
923 BusHandler
= HalpAllocateAndInitPciBusHandler(2, 0, TRUE
);
924 if (!BusHandler
) break;
926 /* Now check if it's valid */
927 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
929 /* Heh, the BIOS lied... try Type 1 */
931 BusHandler
= HalpAllocateAndInitPciBusHandler(1, 0, TRUE
);
932 if (!BusHandler
) break;
934 /* Now check if it's valid */
935 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
941 /* Now allocate the correct kind of handler */
942 HalpAllocateAndInitPciBusHandler(PciType
, 0, FALSE
);
945 /* Okay, now loop all PCI bridges */
948 /* Loop all PCI buses */
949 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
951 /* Check if we have a handler for it */
952 if (!HalHandlerForBus(PCIBus
, i
))
955 HalpAllocateAndInitPciBusHandler(PciType
, i
, FALSE
);
958 /* Go to the next bridge */
959 } while (HalpGetPciBridgeConfig(PciType
, &PciRegistryInfo
->NoBuses
));
961 /* Now build correct address range informaiton */
962 HalpFixupPciSupportedRanges(PciRegistryInfo
->NoBuses
);
965 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
966 PciSlot
.u
.bits
.Reserved
= 0;
967 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
969 /* Get the bus handler */
970 BusHandler
= HalHandlerForBus(PCIBus
, i
);
972 /* Loop every device */
973 for (j
= 0; j
< 32; j
++)
975 /* Loop every function */
976 PciSlot
.u
.bits
.DeviceNumber
= j
;
977 for (k
= 0; k
< 8; k
++)
979 /* Build the final slot structure */
980 PciSlot
.u
.bits
.FunctionNumber
= k
;
982 /* Read the configuration information */
983 HalpReadPCIConfig(BusHandler
,
987 PCI_COMMON_HDR_LENGTH
);
989 /* Skip if this is an invalid function */
990 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
992 /* Print out the entry */
993 HalpDebugPciDumpBus(i
, j
, k
, PciData
);
995 /* Check if this is a Cardbus bridge */
996 if (PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
)
999 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
1003 /* Check if this is a PCI device */
1004 if (PCI_CONFIGURATION_TYPE(PciData
) != PCI_BRIDGE_TYPE
)
1006 /* Check if it has an interrupt pin and line registered */
1007 if ((PciData
->u
.type1
.InterruptPin
) &&
1008 (PciData
->u
.type1
.InterruptLine
))
1010 /* Check if this interrupt line is connected to the bus */
1011 if (PciData
->u
.type1
.InterruptLine
< 16)
1013 /* Is this an IDE device? */
1014 if (!HalpIsIdeDevice(PciData
))
1016 /* We'll mask out this interrupt then */
1017 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
1018 PciData
->u
.type1
.InterruptLine
);
1019 HalpPciIrqMask
|= (1 << PciData
->u
.type1
.InterruptLine
);
1025 /* Check for broken Intel chips */
1026 if (PciData
->VendorID
== 0x8086)
1028 /* Check for broken 82830 PCI controller */
1029 if ((PciData
->DeviceID
== 0x04A3) &&
1030 (PciData
->RevisionID
< 0x11))
1033 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
1037 /* Check for broken 82378 PCI-to-ISA Bridge */
1038 if ((PciData
->DeviceID
== 0x0484) &&
1039 (PciData
->RevisionID
<= 3))
1042 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
1046 /* Check for broken 82450 PCI Bridge */
1047 if ((PciData
->DeviceID
== 0x84C4) &&
1048 (PciData
->RevisionID
<= 4))
1050 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
1055 /* Do we know this card? */
1056 if (!ExtendedAddressDecoding
)
1059 if (HalpIsRecognizedCard(PciRegistryInfo
,
1061 HALP_CARD_FEATURE_FULL_DECODE
))
1063 /* We'll do chipset checks later */
1064 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1065 ExtendedAddressDecoding
= TRUE
;
1069 /* Now check the registry for chipset hacks */
1070 Status
= HalpGetChipHacks(PciData
->VendorID
,
1072 PciData
->RevisionID
,
1074 if (NT_SUCCESS(Status
))
1076 /* Check for broken ACPI routing */
1077 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING
)
1079 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1083 /* Check for broken ACPI timer */
1084 if (HackFlags
& HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER
)
1086 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1090 /* Check for hibernate-disable */
1091 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE
)
1093 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1097 /* Check for USB controllers that generate SMIs */
1098 if (HackFlags
& HAL_PCI_CHIP_HACK_USB_SMI_DISABLE
)
1100 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1105 /* Terminate the entry */
1111 /* Initialize NMI Crash Flag */
1112 HalpGetNMICrashFlag();
1114 /* Free the registry data */
1115 ExFreePoolWithTag(PciRegistryInfo
, TAG_HAL
);
1117 /* Tell PnP if this hard supports correct decoding */
1118 HalpMarkChipsetDecode(ExtendedAddressDecoding
);
1119 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1126 HalpInitBusHandlers(VOID
)
1128 /* Register the HAL Bus Handler support */
1129 HalpRegisterInternalBusHandlers();
1135 HalpRegisterKdSupportFunctions(VOID
)
1137 /* Register PCI Device Functions */
1138 KdSetupPciDeviceForDebugging
= HalpSetupPciDeviceForDebugging
;
1139 KdReleasePciDeviceforDebugging
= HalpReleasePciDeviceForDebugging
;
1141 /* Register memory functions */
1143 #if (NTDDI_VERSION >= NTDDI_VISTA)
1144 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64Vista
;
1145 KdUnmapVirtualAddress
= HalpUnmapVirtualAddressVista
;
1147 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64
;
1148 KdUnmapVirtualAddress
= HalpUnmapVirtualAddress
;
1152 /* Register ACPI stub */
1153 KdCheckPowerButton
= HalpCheckPowerButton
;
1158 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1159 IN PUNICODE_STRING DriverClassName
,
1160 IN PDRIVER_OBJECT DriverObject
,
1161 IN PDEVICE_OBJECT DeviceObject
,
1162 IN INTERFACE_TYPE BusType
,
1164 IN ULONG SlotNumber
,
1165 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1167 PBUS_HANDLER Handler
;
1170 DPRINT1("Slot assignment for %d on bus %u\n", BusType
, BusNumber
);
1172 /* Find the handler */
1173 Handler
= HalReferenceHandlerForBus(BusType
, BusNumber
);
1174 if (!Handler
) return STATUS_NOT_FOUND
;
1176 /* Do the assignment */
1177 Status
= Handler
->AssignSlotResources(Handler
,
1184 AllocatedResources
);
1186 /* Dereference the handler and return */
1187 HalDereferenceBusHandler(Handler
);
1193 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress
,
1194 IN OUT PULONG AddressSpace
,
1195 OUT PPHYSICAL_ADDRESS TranslatedAddress
,
1196 IN OUT PULONG_PTR Context
,
1199 PHAL_BUS_HANDLER BusHandler
;
1200 PBUS_HANDLER Handler
;
1201 PLIST_ENTRY NextEntry
;
1204 /* Make sure we have a context */
1205 if (!Context
) return FALSE
;
1206 ASSERT((*Context
) || (NextBus
== TRUE
));
1208 /* Read the context */
1209 ContextValue
= *Context
;
1211 /* Find the bus handler */
1212 Handler
= HalpContextToBusHandler(ContextValue
);
1213 if (!Handler
) return FALSE
;
1215 /* Check if this is an ongoing lookup */
1218 /* Get the HAL bus handler */
1219 BusHandler
= CONTAINING_RECORD(Handler
, HAL_BUS_HANDLER
, Handler
);
1220 NextEntry
= &BusHandler
->AllHandlers
;
1222 /* Get the next one if we were already with one */
1223 if (ContextValue
) NextEntry
= NextEntry
->Flink
;
1225 /* Start scanning */
1228 /* Check if this is the last one */
1229 if (NextEntry
== &HalpAllBusHandlers
)
1236 /* Call this translator */
1237 BusHandler
= CONTAINING_RECORD(NextEntry
, HAL_BUS_HANDLER
, AllHandlers
);
1238 if (HalTranslateBusAddress(BusHandler
->Handler
.InterfaceType
,
1239 BusHandler
->Handler
.BusNumber
,
1242 TranslatedAddress
)) break;
1244 /* Try the next one */
1245 NextEntry
= NextEntry
->Flink
;
1248 /* If we made it, we're done */
1249 *Context
= (ULONG_PTR
)&BusHandler
->Handler
;
1253 /* Try the first one through */
1254 if (!HalTranslateBusAddress(Handler
->InterfaceType
,
1258 TranslatedAddress
)) return FALSE
;
1260 /* Remember for next time */
1261 *Context
= (ULONG_PTR
)Handler
;
1267 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1269 IN PHYSICAL_ADDRESS BusAddress
,
1270 IN OUT PULONG AddressSpace
,
1271 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1273 PBUS_HANDLER Handler
;
1276 /* Find the handler */
1277 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1278 if (!(Handler
) || !(Handler
->TranslateBusAddress
))
1280 DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType
, BusNumber
, Handler
, BusAddress
);
1284 /* Do the assignment */
1285 Status
= Handler
->TranslateBusAddress(Handler
,
1291 /* Dereference the handler and return */
1292 HalDereferenceBusHandler(Handler
);
1296 /* PUBLIC FUNCTIONS **********************************************************/
1303 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST
*ResourceList
)
1305 PBUS_HANDLER Handler
;
1309 /* Find the handler */
1310 Handler
= HalReferenceHandlerForBus((*ResourceList
)->InterfaceType
,
1311 (*ResourceList
)->BusNumber
);
1312 if (!Handler
) return STATUS_SUCCESS
;
1314 /* Do the assignment */
1315 Status
= Handler
->AdjustResourceList(Handler
,
1319 /* Dereference the handler and return */
1320 HalDereferenceBusHandler(Handler
);
1329 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1330 IN PUNICODE_STRING DriverClassName
,
1331 IN PDRIVER_OBJECT DriverObject
,
1332 IN PDEVICE_OBJECT DeviceObject
,
1333 IN INTERFACE_TYPE BusType
,
1335 IN ULONG SlotNumber
,
1336 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1340 /* Check the bus type */
1341 if (BusType
!= PCIBus
)
1343 /* Call our internal handler */
1344 return HalpAssignSlotResources(RegistryPath
,
1351 AllocatedResources
);
1355 /* Call the PCI registered function */
1356 return HalPciAssignSlotResources(RegistryPath
,
1363 AllocatedResources
);
1372 HalGetBusData(IN BUS_DATA_TYPE BusDataType
,
1374 IN ULONG SlotNumber
,
1378 /* Call the extended function */
1379 return HalGetBusDataByOffset(BusDataType
,
1392 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1394 IN ULONG SlotNumber
,
1399 PBUS_HANDLER Handler
;
1402 /* Find the handler */
1403 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1404 if (!Handler
) return 0;
1406 /* Do the assignment */
1407 Status
= Handler
->GetBusData(Handler
,
1414 /* Dereference the handler and return */
1415 HalDereferenceBusHandler(Handler
);
1424 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType
,
1426 IN ULONG BusInterruptLevel
,
1427 IN ULONG BusInterruptVector
,
1429 OUT PKAFFINITY Affinity
)
1431 PBUS_HANDLER Handler
;
1439 /* Find the handler */
1440 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1441 if (!Handler
) return 0;
1443 /* Do the assignment */
1444 Vector
= Handler
->GetInterruptVector(Handler
,
1450 if ((Vector
!= IRQ2VECTOR(BusInterruptLevel
)) ||
1451 (*Irql
!= VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
))))
1453 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1454 *Irql
, Vector
, BusInterruptLevel
, BusInterruptVector
);
1455 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1456 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
)),
1457 IRQ2VECTOR(BusInterruptLevel
));
1460 /* Dereference the handler and return */
1461 HalDereferenceBusHandler(Handler
);
1470 HalSetBusData(IN BUS_DATA_TYPE BusDataType
,
1472 IN ULONG SlotNumber
,
1476 /* Call the extended function */
1477 return HalSetBusDataByOffset(BusDataType
,
1490 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1492 IN ULONG SlotNumber
,
1497 PBUS_HANDLER Handler
;
1500 /* Find the handler */
1501 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1502 if (!Handler
) return 0;
1504 /* Do the assignment */
1505 Status
= Handler
->SetBusData(Handler
,
1512 /* Dereference the handler and return */
1513 HalDereferenceBusHandler(Handler
);
1522 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1524 IN PHYSICAL_ADDRESS BusAddress
,
1525 IN OUT PULONG AddressSpace
,
1526 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1528 /* Look as the bus type */
1529 if (InterfaceType
== PCIBus
)
1531 /* Call the PCI registered function */
1532 return HalPciTranslateBusAddress(PCIBus
,
1540 /* Call the bus handler */
1541 return HaliTranslateBusAddress(InterfaceType
,