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 *******************************************************************/
17 HalpAllocateAndInitPciBusHandler(
20 IN BOOLEAN TestAllocation
25 HalpFixupPciSupportedRanges(
40 HalpGetPciBridgeConfig(
48 IN PPCI_COMMON_CONFIG PciData
54 IN PPCI_COMMON_CONFIG PciData
60 IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
,
61 IN PPCI_COMMON_CONFIG PciData
,
68 IN PBUS_HANDLER BusHandler
,
69 IN PCI_SLOT_NUMBER Slot
74 HalpMarkChipsetDecode(
75 IN BOOLEAN OverrideEnable
80 HalpRegisterInternalBusHandlers(
91 #if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_)
92 #pragma alloc_text(INIT, HalpAllocateAndInitPciBusHandler)
93 #pragma alloc_text(INIT, HalpDebugPciDumpBus)
94 #pragma alloc_text(INIT, HalpFixupPciSupportedRanges)
95 #pragma alloc_text(INIT, HalpGetChipHacks)
96 #pragma alloc_text(INIT, HalpGetPciBridgeConfig)
97 #pragma alloc_text(INIT, HalpInitBusHandlers)
98 #pragma alloc_text(INIT, HalpInitializePciBus)
99 #pragma alloc_text(INIT, HalpIsBridgeDevice)
100 #pragma alloc_text(INIT, HalpIsIdeDevice)
101 #pragma alloc_text(INIT, HalpIsRecognizedCard)
102 #pragma alloc_text(INIT, HalpIsValidPCIDevice)
103 #pragma alloc_text(INIT, HalpMarkChipsetDecode)
104 #pragma alloc_text(INIT, HalpRegisterKdSupportFunctions)
105 #pragma alloc_text(INIT, HalpRegisterInternalBusHandlers)
106 #pragma alloc_text(INIT, ShowSize)
109 /* GLOBALS ********************************************************************/
111 extern KSPIN_LOCK HalpPCIConfigLock
;
112 ULONG HalpPciIrqMask
;
114 /* PRIVATE FUNCTIONS **********************************************************/
118 HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType
,
119 IN BUS_DATA_TYPE BusDataType
,
121 IN INTERFACE_TYPE ParentBusInterfaceType
,
122 IN ULONG ParentBusNumber
,
123 IN ULONG BusSpecificData
)
127 /* Register the bus handler */
128 HalRegisterBusHandler(InterfaceType
,
131 ParentBusInterfaceType
,
141 /* Check for a valid interface */
142 if (InterfaceType
!= InterfaceTypeUndefined
)
144 /* Allocate address ranges and zero them out */
145 Bus
->BusAddresses
= ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
146 sizeof(SUPPORTED_RANGES
),
148 RtlZeroMemory(Bus
->BusAddresses
, sizeof(SUPPORTED_RANGES
));
150 /* Build the data structure */
151 Bus
->BusAddresses
->Version
= HAL_SUPPORTED_RANGE_VERSION
;
152 Bus
->BusAddresses
->Dma
.Limit
= 7;
153 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFFFF;
154 Bus
->BusAddresses
->IO
.Limit
= 0xFFFF;
155 Bus
->BusAddresses
->IO
.SystemAddressSpace
= 1;
156 Bus
->BusAddresses
->PrefetchMemory
.Base
= 1;
159 /* Return the bus address */
166 HalpRegisterInternalBusHandlers(VOID
)
170 /* Only do processor 1 */
171 if (KeGetCurrentPrcb()->Number
) return;
173 /* Register root support */
174 HalpInitBusHandler();
176 /* Allocate the system bus */
177 Bus
= HalpAllocateBusHandler(Internal
,
178 ConfigurationSpaceUndefined
,
180 InterfaceTypeUndefined
,
186 Bus
->GetInterruptVector
= HalpGetSystemInterruptVector
;
187 Bus
->TranslateBusAddress
= HalpTranslateSystemBusAddress
;
190 /* Allocate the CMOS bus */
191 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
194 InterfaceTypeUndefined
,
200 Bus
->GetBusData
= HalpcGetCmosData
;
201 Bus
->SetBusData
= HalpcSetCmosData
;
204 /* Allocate the CMOS bus */
205 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
208 InterfaceTypeUndefined
,
214 Bus
->GetBusData
= HalpcGetCmosData
;
215 Bus
->SetBusData
= HalpcSetCmosData
;
218 /* Allocate ISA bus */
219 Bus
= HalpAllocateBusHandler(Isa
,
220 ConfigurationSpaceUndefined
,
228 Bus
->GetBusData
= HalpNoBusData
;
229 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFF;
230 Bus
->TranslateBusAddress
= HalpTranslateIsaBusAddress
;
233 /* No support for EISA or MCA */
234 ASSERT(HalpBusType
== MACHINE_TYPE_ISA
);
241 HalpMarkChipsetDecode(BOOLEAN OverrideEnable
)
244 UNICODE_STRING KeyString
;
245 ULONG Data
= OverrideEnable
;
246 HANDLE KeyHandle
, Handle
;
249 RtlInitUnicodeString(&KeyString
,
250 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
251 Status
= HalpOpenRegistryKey(&Handle
, 0, &KeyString
, KEY_ALL_ACCESS
, FALSE
);
252 if (NT_SUCCESS(Status
))
254 /* Open PNP Bios key */
255 RtlInitUnicodeString(&KeyString
, L
"Control\\Biosinfo\\PNPBios");
256 Status
= HalpOpenRegistryKey(&KeyHandle
,
265 /* Check if PNP BIOS key exists */
266 if (NT_SUCCESS(Status
))
268 /* Set the override value */
269 RtlInitUnicodeString(&KeyString
, L
"FullDecodeChipsetOverride");
270 Status
= ZwSetValueKey(KeyHandle
,
289 HalpAllocateAndInitPciBusHandler(IN ULONG PciType
,
291 IN BOOLEAN TestAllocation
)
294 PPCIPBUSDATA BusData
;
296 /* Allocate the bus handler */
297 Bus
= HalpAllocateBusHandler(PCIBus
,
302 sizeof(PCIPBUSDATA
));
305 Bus
->GetBusData
= HalpGetPCIData
;
306 Bus
->SetBusData
= HalpSetPCIData
;
307 Bus
->GetInterruptVector
= HalpGetPCIIntOnISABus
;
308 Bus
->AdjustResourceList
= HalpAdjustPCIResourceList
;
309 Bus
->AssignSlotResources
= HalpAssignPCISlotResources
;
310 Bus
->BusAddresses
->Dma
.Limit
= 0;
312 /* Get our custom bus data */
313 BusData
= (PPCIPBUSDATA
)Bus
->BusData
;
315 /* Setup custom bus data */
316 BusData
->CommonData
.Tag
= PCI_DATA_TAG
;
317 BusData
->CommonData
.Version
= PCI_DATA_VERSION
;
318 BusData
->CommonData
.ReadConfig
= HalpReadPCIConfig
;
319 BusData
->CommonData
.WriteConfig
= HalpWritePCIConfig
;
320 BusData
->CommonData
.Pin2Line
= HalpPCIPin2ISALine
;
321 BusData
->CommonData
.Line2Pin
= HalpPCIISALine2Pin
;
322 BusData
->MaxDevice
= PCI_MAX_DEVICES
;
323 BusData
->GetIrqRange
= HalpGetISAFixedPCIIrq
;
325 /* Initialize the bitmap */
326 RtlInitializeBitMap(&BusData
->DeviceConfigured
, BusData
->ConfiguredBits
, 256);
328 /* Check the type of PCI bus */
334 /* Copy the Type 1 handler data */
335 RtlCopyMemory(&PCIConfigHandler
,
336 &PCIConfigHandlerType1
,
337 sizeof(PCIConfigHandler
));
339 /* Set correct I/O Ports */
340 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
341 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
347 /* Copy the Type 1 handler data */
348 RtlCopyMemory(&PCIConfigHandler
,
349 &PCIConfigHandlerType2
,
350 sizeof (PCIConfigHandler
));
352 /* Set correct I/O Ports */
353 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
354 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
355 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
357 /* Only 16 devices supported, not 32 */
358 BusData
->MaxDevice
= 16;
364 DbgPrint("HAL: Unnkown PCI type\n");
367 /* Return the bus handler */
374 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler
,
375 IN PCI_SLOT_NUMBER Slot
)
377 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
378 PPCI_COMMON_CONFIG PciHeader
= (PVOID
)DataBuffer
;
382 /* Read the PCI header */
383 HalpReadPCIConfig(BusHandler
, Slot
, PciHeader
, 0, PCI_COMMON_HDR_LENGTH
);
385 /* Make sure it's a valid device */
386 if ((PciHeader
->VendorID
== PCI_INVALID_VENDORID
) ||
387 (PCI_CONFIGURATION_TYPE(PciHeader
) != PCI_DEVICE_TYPE
))
393 /* Make sure interrupt numbers make sense */
394 if (((PciHeader
->u
.type0
.InterruptPin
) &&
395 (PciHeader
->u
.type0
.InterruptPin
> 4)) ||
396 (PciHeader
->u
.type0
.InterruptLine
& 0x70))
402 /* Now scan PCI BARs */
403 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
405 /* Check what kind of address it is */
406 Address
= PciHeader
->u
.type0
.BaseAddresses
[i
];
407 if (Address
& PCI_ADDRESS_IO_SPACE
)
409 /* Highest I/O port is 65535 */
410 if (Address
> 0xFFFF) return FALSE
;
414 /* MMIO should be higher than 0x80000 */
415 if ((Address
> 0xF) && (Address
< 0x80000)) return FALSE
;
418 /* Is this a 64-bit address? */
419 if (!(Address
& PCI_ADDRESS_IO_SPACE
) &&
420 ((Address
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
))
422 /* Check the next-next entry, since this one 64-bits wide */
427 /* Header, interrupt and address data all make sense */
431 static BOOLEAN WarningsGiven
[5];
436 HalpGetChipHacks(IN USHORT VendorId
,
441 UNICODE_STRING KeyName
, ValueName
;
443 OBJECT_ATTRIBUTES ObjectAttributes
;
446 KEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
449 /* Setup the object attributes for the key */
450 RtlInitUnicodeString(&KeyName
,
451 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
453 InitializeObjectAttributes(&ObjectAttributes
,
455 OBJ_CASE_INSENSITIVE
,
460 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
461 if (!NT_SUCCESS(Status
)) return Status
;
464 swprintf(Buffer
, L
"%04X%04X", VendorId
, DeviceId
);
465 RtlInitUnicodeString(&ValueName
, Buffer
);
466 Status
= ZwQueryValueKey(KeyHandle
,
468 KeyValuePartialInformation
,
472 if (NT_SUCCESS(Status
))
474 /* Return the flags */
475 DbgPrint("\tFound HackFlags for your chipset\n");
476 *HackFlags
= *(PULONG
)PartialInfo
.Data
;
477 DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
478 *HackFlags
, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
), RevisionId
);
480 /* Does it apply to this revision? */
481 if ((RevisionId
) && (RevisionId
>= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
))))
483 /* Read the revision flags */
484 *HackFlags
= HALP_REVISION_HACK_FLAGS(*HackFlags
);
487 /* Throw out revision data */
488 *HackFlags
= HALP_HACK_FLAGS(*HackFlags
);
489 if (!*HackFlags
) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
492 /* Close the handle and return */
500 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
,
501 IN PPCI_COMMON_CONFIG PciData
,
504 ULONG ElementCount
, i
;
505 PPCI_CARD_DESCRIPTOR CardDescriptor
;
507 /* How many PCI Cards that we know about? */
508 ElementCount
= PciRegistryInfo
->ElementCount
;
509 if (!ElementCount
) return FALSE
;
511 /* Loop all descriptors */
512 CardDescriptor
= &PciRegistryInfo
->CardList
[0];
513 for (i
= 0; i
< ElementCount
; i
++, CardDescriptor
++)
515 /* Check for flag match */
516 if (CardDescriptor
->Flags
!= Flags
) continue;
518 /* Check for VID-PID match */
519 if ((CardDescriptor
->VendorID
!= PciData
->VendorID
) ||
520 (CardDescriptor
->DeviceID
!= PciData
->DeviceID
))
526 /* Check for revision match, if requested */
527 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_REVISION_ID
) &&
528 (CardDescriptor
->RevisionID
!= PciData
->RevisionID
))
534 /* Check what kind of device this is */
535 switch (PCI_CONFIGURATION_TYPE(PciData
))
538 case PCI_CARDBUS_BRIDGE_TYPE
:
540 /* This means the real device header is in the device-specific data */
541 PciData
= (PPCI_COMMON_CONFIG
)PciData
->DeviceSpecific
;
543 /* Normal PCI device */
544 case PCI_DEVICE_TYPE
:
546 /* Check for subvendor match, if requested */
547 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBVENDOR_ID
) &&
548 (CardDescriptor
->SubsystemVendorID
!= PciData
->u
.type0
.SubVendorID
))
554 /* Check for subsystem match, if requested */
555 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBSYSTEM_ID
) &&
556 (CardDescriptor
->SubsystemID
!= PciData
->u
.type0
.SubSystemID
))
565 /* PCI Bridge -- don't bother */
566 case PCI_BRIDGE_TYPE
:
574 /* This means the card isn't recognized */
581 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData
)
583 /* Simple test first */
584 if ((PciData
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
585 (PciData
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
))
587 /* The device is nice enough to admit it */
591 /* Symphony 82C101 */
592 if (PciData
->VendorID
== 0x1C1C) return TRUE
;
594 /* ALi MS4803 or M5219 */
595 if ((PciData
->VendorID
== 0x10B9) &&
596 ((PciData
->DeviceID
== 0x5215) || (PciData
->DeviceID
== 0x5219)))
601 /* Appian Technology */
602 if ((PciData
->VendorID
== 0x1097) && (PciData
->DeviceID
== 0x38)) return TRUE
;
604 /* Compaq Triflex Dual EIDE Controller */
605 if ((PciData
->VendorID
== 0xE11) && (PciData
->DeviceID
== 0xAE33)) return TRUE
;
607 /* Micron PC Tech RZ1000 */
608 if ((PciData
->VendorID
== 0x1042) && (PciData
->DeviceID
== 0x1000)) return TRUE
;
610 /* SiS 85C601 or 5513 [IDE] */
611 if ((PciData
->VendorID
== 0x1039) &&
612 ((PciData
->DeviceID
== 0x601) || (PciData
->DeviceID
== 0x5513)))
617 /* Symphony Labs W83769F */
618 if ((PciData
->VendorID
== 0x10AD) &&
619 ((PciData
->DeviceID
== 0x1) || (PciData
->DeviceID
== 0x150)))
625 if ((PciData
->VendorID
== 0x1060) && (PciData
->DeviceID
== 0x101)) return TRUE
;
627 /* You've survived */
634 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData
)
636 /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
637 return (((PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
) &&
638 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
639 (PciData
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
)) ||
640 ((PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
) &&
641 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
642 (PciData
->SubClass
== PCI_SUBCLASS_BR_CARDBUS
)));
648 HalpGetPciBridgeConfig(IN ULONG PciType
,
651 PCI_SLOT_NUMBER PciSlot
;
653 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
654 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
655 PBUS_HANDLER BusHandler
;
658 PciSlot
.u
.bits
.Reserved
= 0;
659 for (i
= 0; i
< *BusCount
; i
++)
661 /* Get the bus handler */
662 BusHandler
= HalHandlerForBus(PCIBus
, i
);
664 /* Loop every device */
665 for (j
= 0; j
< PCI_MAX_DEVICES
; j
++)
667 /* Loop every function */
668 PciSlot
.u
.bits
.DeviceNumber
= j
;
669 for (k
= 0; k
< PCI_MAX_FUNCTION
; k
++)
671 /* Build the final slot structure */
672 PciSlot
.u
.bits
.FunctionNumber
= k
;
674 /* Read the configuration information */
675 HalpReadPCIConfig(BusHandler
,
679 PCI_COMMON_HDR_LENGTH
);
681 /* Skip if this is an invalid function */
682 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
684 /* Make sure that this is a PCI bridge or a cardbus bridge */
685 if (!HalpIsBridgeDevice(PciData
)) continue;
688 if (!WarningsGiven
[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
694 /* If we exited the loop, then there's no bridge to worry about */
701 HalpFixupPciSupportedRanges(IN ULONG BusCount
)
704 PBUS_HANDLER Bus
, ParentBus
;
707 for (i
= 0; i
< BusCount
; i
++)
709 /* Get PCI bus handler */
710 Bus
= HalHandlerForBus(PCIBus
, i
);
712 /* Loop all parent buses */
713 ParentBus
= Bus
->ParentHandler
;
716 /* Should merge addresses */
717 if (!WarningsGiven
[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
719 /* Check the next parent */
720 ParentBus
= ParentBus
->ParentHandler
;
724 /* Loop all buses again */
725 for (i
= 0; i
< BusCount
; i
++)
727 /* Get PCI bus handler */
728 Bus
= HalHandlerForBus(PCIBus
, i
);
730 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
731 if (!((PPCIPBUSDATA
)Bus
->BusData
)->Subtractive
)
733 /* Loop all parent buses */
734 ParentBus
= Bus
->ParentHandler
;
737 /* But check only PCI parent buses specifically */
738 if (ParentBus
->InterfaceType
== PCIBus
)
740 /* Should trim addresses */
741 if (!WarningsGiven
[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
744 /* Check the next parent */
745 ParentBus
= ParentBus
->ParentHandler
;
750 /* Loop buses one last time */
751 for (i
= 0; i
< BusCount
; i
++)
753 /* Get the PCI bus handler */
754 Bus
= HalHandlerForBus(PCIBus
, i
);
756 /* Sort and combine (trim) bus address range information */
757 DPRINT("Warning: Bus addresses not being optimized!\n");
770 DbgPrint("%d", (int) x
);
772 else if (x
< 1048576)
774 DbgPrint("%dK", (int)(x
/ 1024));
776 else if (x
< 0x80000000)
778 DbgPrint("%dM", (int)(x
/ 1048576));
788 * These includes are required to define
789 * the ClassTable and VendorTable arrays.
791 #include "pci_classes.h"
792 #include "pci_vendors.h"
796 HalpDebugPciDumpBus(IN ULONG i
,
799 IN PPCI_COMMON_CONFIG PciData
)
801 PCHAR p
, ClassName
, SubClassName
, VendorName
, ProductName
, SubVendorName
;
803 CHAR LookupString
[16] = "";
804 CHAR bSubClassName
[64] = "";
805 CHAR bVendorName
[64] = "";
806 CHAR bProductName
[128] = "Unknown device";
807 CHAR bSubVendorName
[128] = "Unknown";
810 /* Isolate the class name */
811 sprintf(LookupString
, "C %02x ", PciData
->BaseClass
);
812 ClassName
= strstr((PCHAR
)ClassTable
, LookupString
);
815 /* Isolate the subclass name */
817 sprintf(LookupString
, "\t%02x ", PciData
->SubClass
);
818 SubClassName
= strstr(ClassName
, LookupString
);
821 /* Copy the subclass into our buffer */
823 p
= strpbrk(SubClassName
, "\r\n");
824 Length
= p
- SubClassName
;
825 if (Length
>= sizeof(bSubClassName
)) Length
= sizeof(bSubClassName
) - 1;
826 strncpy(bSubClassName
, SubClassName
, Length
);
827 bSubClassName
[Length
] = '\0';
831 /* Isolate the vendor name */
832 sprintf(LookupString
, "\r\n%04x ", PciData
->VendorID
);
833 VendorName
= strstr((PCHAR
)VendorTable
, LookupString
);
836 /* Copy the vendor name into our buffer */
838 p
= strpbrk(VendorName
, "\r\n");
839 Length
= p
- VendorName
;
840 if (Length
>= sizeof(bVendorName
)) Length
= sizeof(bVendorName
) - 1;
841 strncpy(bVendorName
, VendorName
, Length
);
842 bVendorName
[Length
] = '\0';
844 /* Isolate the product name */
845 sprintf(LookupString
, "\t%04x ", PciData
->DeviceID
);
846 ProductName
= strstr(VendorName
, LookupString
);
849 /* Copy the product name into our buffer */
851 p
= strpbrk(ProductName
, "\r\n");
852 Length
= p
- ProductName
;
853 if (Length
>= sizeof(bProductName
)) Length
= sizeof(bProductName
) - 1;
854 strncpy(bProductName
, ProductName
, Length
);
855 bProductName
[Length
] = '\0';
857 /* Isolate the subvendor and subsystem name */
858 sprintf(LookupString
,
860 PciData
->u
.type0
.SubVendorID
,
861 PciData
->u
.type0
.SubSystemID
);
862 SubVendorName
= strstr(ProductName
, LookupString
);
865 /* Copy the subvendor name into our buffer */
867 p
= strpbrk(SubVendorName
, "\r\n");
868 Length
= p
- SubVendorName
;
869 if (Length
>= sizeof(bSubVendorName
)) Length
= sizeof(bSubVendorName
) - 1;
870 strncpy(bSubVendorName
, SubVendorName
, Length
);
871 bSubVendorName
[Length
] = '\0';
876 /* Print out the data */
877 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
878 "\tSubsystem: %s [%04x:%04x]\n",
891 PciData
->u
.type0
.SubVendorID
,
892 PciData
->u
.type0
.SubSystemID
);
894 /* Print out and decode flags */
895 DbgPrint("\tFlags:");
896 if (PciData
->Command
& PCI_ENABLE_BUS_MASTER
) DbgPrint(" bus master,");
897 if (PciData
->Status
& PCI_STATUS_66MHZ_CAPABLE
) DbgPrint(" 66MHz,");
898 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x000) DbgPrint(" fast devsel,");
899 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x200) DbgPrint(" medium devsel,");
900 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x400) DbgPrint(" slow devsel,");
901 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x600) DbgPrint(" unknown devsel,");
902 DbgPrint(" latency %d", PciData
->LatencyTimer
);
903 if (PciData
->u
.type0
.InterruptPin
!= 0 &&
904 PciData
->u
.type0
.InterruptLine
!= 0 &&
905 PciData
->u
.type0
.InterruptLine
!= 0xFF) DbgPrint(", IRQ %02d", PciData
->u
.type0
.InterruptLine
);
906 else if (PciData
->u
.type0
.InterruptPin
!= 0) DbgPrint(", IRQ assignment required");
911 for (b
= 0; b
< PCI_TYPE0_ADDRESSES
; b
++)
913 /* Check for a BAR */
914 Mem
= PciData
->u
.type0
.BaseAddresses
[b
];
917 /* Decode the address type */
918 if (Mem
& PCI_ADDRESS_IO_SPACE
)
922 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
925 DbgPrint("\tI/O ports at %04lx", Mem
& PCI_ADDRESS_IO_ADDRESS_MASK
);
932 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
935 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
936 Mem
& PCI_ADDRESS_MEMORY_ADDRESS_MASK
,
937 (Mem
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_32BIT
? 32 : 64,
938 (Mem
& PCI_ADDRESS_MEMORY_PREFETCHABLE
) ? "" : "non-");
949 HalpInitializePciBus(VOID
)
952 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
954 PCI_SLOT_NUMBER PciSlot
;
956 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
957 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
958 PBUS_HANDLER BusHandler
;
960 BOOLEAN ExtendedAddressDecoding
= FALSE
;
963 /* Query registry information */
964 PciRegistryInfo
= HalpQueryPciRegistryInfo();
965 if (!PciRegistryInfo
) return;
967 /* Initialize the PCI configuration lock */
968 KeInitializeSpinLock(&HalpPCIConfigLock
);
970 /* Get the type and free the info structure */
971 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
973 /* Check if this is a type 2 PCI bus with at least one bus */
974 if ((PciRegistryInfo
->NoBuses
) && (PciType
== 2))
976 /* Setup the PCI slot */
977 PciSlot
.u
.bits
.Reserved
= 0;
978 PciSlot
.u
.bits
.FunctionNumber
= 0;
981 for (i
= 0; i
< 32; i
++)
983 /* Try to setup a Type 2 PCI slot */
985 BusHandler
= HalpAllocateAndInitPciBusHandler(2, 0, TRUE
);
986 if (!BusHandler
) break;
988 /* Now check if it's valid */
989 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
991 /* Heh, the BIOS lied... try Type 1 */
993 BusHandler
= HalpAllocateAndInitPciBusHandler(1, 0, TRUE
);
994 if (!BusHandler
) break;
996 /* Now check if it's valid */
997 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
1003 /* Now allocate the correct kind of handler */
1004 HalpAllocateAndInitPciBusHandler(PciType
, 0, FALSE
);
1007 /* Okay, now loop all PCI bridges */
1010 /* Loop all PCI buses */
1011 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
1013 /* Check if we have a handler for it */
1014 if (!HalHandlerForBus(PCIBus
, i
))
1017 HalpAllocateAndInitPciBusHandler(PciType
, i
, FALSE
);
1020 /* Go to the next bridge */
1021 } while (HalpGetPciBridgeConfig(PciType
, &PciRegistryInfo
->NoBuses
));
1023 /* Now build correct address range informaiton */
1024 HalpFixupPciSupportedRanges(PciRegistryInfo
->NoBuses
);
1026 /* Loop every bus */
1027 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
1028 PciSlot
.u
.bits
.Reserved
= 0;
1029 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
1031 /* Get the bus handler */
1032 BusHandler
= HalHandlerForBus(PCIBus
, i
);
1034 /* Loop every device */
1035 for (j
= 0; j
< 32; j
++)
1037 /* Loop every function */
1038 PciSlot
.u
.bits
.DeviceNumber
= j
;
1039 for (k
= 0; k
< 8; k
++)
1041 /* Build the final slot structure */
1042 PciSlot
.u
.bits
.FunctionNumber
= k
;
1044 /* Read the configuration information */
1045 HalpReadPCIConfig(BusHandler
,
1049 PCI_COMMON_HDR_LENGTH
);
1051 /* Skip if this is an invalid function */
1052 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
1054 /* Print out the entry */
1055 HalpDebugPciDumpBus(i
, j
, k
, PciData
);
1057 /* Check if this is a Cardbus bridge */
1058 if (PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
)
1061 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
1065 /* Check if this is a PCI device */
1066 if (PCI_CONFIGURATION_TYPE(PciData
) != PCI_BRIDGE_TYPE
)
1068 /* Check if it has an interrupt pin and line registered */
1069 if ((PciData
->u
.type1
.InterruptPin
) &&
1070 (PciData
->u
.type1
.InterruptLine
))
1072 /* Check if this interrupt line is connected to the bus */
1073 if (PciData
->u
.type1
.InterruptLine
< 16)
1075 /* Is this an IDE device? */
1076 if (!HalpIsIdeDevice(PciData
))
1078 /* We'll mask out this interrupt then */
1079 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
1080 PciData
->u
.type1
.InterruptLine
);
1081 HalpPciIrqMask
|= (1 << PciData
->u
.type1
.InterruptLine
);
1087 /* Check for broken Intel chips */
1088 if (PciData
->VendorID
== 0x8086)
1090 /* Check for broken 82830 PCI controller */
1091 if ((PciData
->DeviceID
== 0x04A3) &&
1092 (PciData
->RevisionID
< 0x11))
1095 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
1099 /* Check for broken 82378 PCI-to-ISA Bridge */
1100 if ((PciData
->DeviceID
== 0x0484) &&
1101 (PciData
->RevisionID
<= 3))
1104 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
1108 /* Check for broken 82450 PCI Bridge */
1109 if ((PciData
->DeviceID
== 0x84C4) &&
1110 (PciData
->RevisionID
<= 4))
1112 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
1117 /* Do we know this card? */
1118 if (!ExtendedAddressDecoding
)
1121 if (HalpIsRecognizedCard(PciRegistryInfo
,
1123 HALP_CARD_FEATURE_FULL_DECODE
))
1125 /* We'll do chipset checks later */
1126 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1127 ExtendedAddressDecoding
= TRUE
;
1131 /* Check if this is a USB controller */
1132 if ((PciData
->BaseClass
== PCI_CLASS_SERIAL_BUS_CTLR
) &&
1133 (PciData
->SubClass
== PCI_SUBCLASS_SB_USB
))
1135 /* Check if this is an OHCI controller */
1136 if (PciData
->ProgIf
== 0x10)
1138 DbgPrint("\tDevice is an OHCI (USB) PCI Expansion Card. Turn off Legacy USB in your BIOS!\n\n");
1142 /* Check for Intel UHCI controller */
1143 if (PciData
->VendorID
== 0x8086)
1145 DbgPrint("\tDevice is an Intel UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
1149 /* Check for VIA UHCI controller */
1150 if (PciData
->VendorID
== 0x1106)
1152 DbgPrint("\tDevice is a VIA UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
1157 /* Now check the registry for chipset hacks */
1158 Status
= HalpGetChipHacks(PciData
->VendorID
,
1160 PciData
->RevisionID
,
1162 if (NT_SUCCESS(Status
))
1164 /* Check for broken ACPI routing */
1165 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING
)
1167 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1171 /* Check for broken ACPI timer */
1172 if (HackFlags
& HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER
)
1174 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1178 /* Check for hibernate-disable */
1179 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE
)
1181 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1185 /* Check for USB controllers that generate SMIs */
1186 if (HackFlags
& HAL_PCI_CHIP_HACK_USB_SMI_DISABLE
)
1188 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1193 /* Terminate the entry */
1199 /* Initialize NMI Crash Flag */
1200 HalpGetNMICrashFlag();
1202 /* Free the registry data */
1203 ExFreePoolWithTag(PciRegistryInfo
, TAG_HAL
);
1205 /* Tell PnP if this hard supports correct decoding */
1206 HalpMarkChipsetDecode(ExtendedAddressDecoding
);
1207 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1214 HalpInitBusHandlers(VOID
)
1216 /* Register the HAL Bus Handler support */
1217 HalpRegisterInternalBusHandlers();
1223 HalpRegisterKdSupportFunctions(VOID
)
1225 /* Register PCI Device Functions */
1226 KdSetupPciDeviceForDebugging
= HalpSetupPciDeviceForDebugging
;
1227 KdReleasePciDeviceforDebugging
= HalpReleasePciDeviceForDebugging
;
1229 /* Register memory functions */
1231 #if (NTDDI_VERSION >= NTDDI_VISTA)
1232 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64Vista
;
1233 KdUnmapVirtualAddress
= HalpUnmapVirtualAddressVista
;
1235 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64
;
1236 KdUnmapVirtualAddress
= HalpUnmapVirtualAddress
;
1240 /* Register ACPI stub */
1241 KdCheckPowerButton
= HalpCheckPowerButton
;
1246 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1247 IN PUNICODE_STRING DriverClassName
,
1248 IN PDRIVER_OBJECT DriverObject
,
1249 IN PDEVICE_OBJECT DeviceObject
,
1250 IN INTERFACE_TYPE BusType
,
1252 IN ULONG SlotNumber
,
1253 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1255 PBUS_HANDLER Handler
;
1258 DPRINT1("Slot assignment for %d on bus %u\n", BusType
, BusNumber
);
1260 /* Find the handler */
1261 Handler
= HalReferenceHandlerForBus(BusType
, BusNumber
);
1262 if (!Handler
) return STATUS_NOT_FOUND
;
1264 /* Do the assignment */
1265 Status
= Handler
->AssignSlotResources(Handler
,
1272 AllocatedResources
);
1274 /* Dereference the handler and return */
1275 HalDereferenceBusHandler(Handler
);
1281 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress
,
1282 IN OUT PULONG AddressSpace
,
1283 OUT PPHYSICAL_ADDRESS TranslatedAddress
,
1284 IN OUT PULONG_PTR Context
,
1287 PHAL_BUS_HANDLER BusHandler
;
1288 PBUS_HANDLER Handler
;
1289 PLIST_ENTRY NextEntry
;
1292 /* Make sure we have a context */
1293 if (!Context
) return FALSE
;
1294 ASSERT((*Context
) || (NextBus
== TRUE
));
1296 /* Read the context */
1297 ContextValue
= *Context
;
1299 /* Find the bus handler */
1300 Handler
= HalpContextToBusHandler(ContextValue
);
1301 if (!Handler
) return FALSE
;
1303 /* Check if this is an ongoing lookup */
1306 /* Get the HAL bus handler */
1307 BusHandler
= CONTAINING_RECORD(Handler
, HAL_BUS_HANDLER
, Handler
);
1308 NextEntry
= &BusHandler
->AllHandlers
;
1310 /* Get the next one if we were already with one */
1311 if (ContextValue
) NextEntry
= NextEntry
->Flink
;
1313 /* Start scanning */
1316 /* Check if this is the last one */
1317 if (NextEntry
== &HalpAllBusHandlers
)
1324 /* Call this translator */
1325 BusHandler
= CONTAINING_RECORD(NextEntry
, HAL_BUS_HANDLER
, AllHandlers
);
1326 if (HalTranslateBusAddress(BusHandler
->Handler
.InterfaceType
,
1327 BusHandler
->Handler
.BusNumber
,
1330 TranslatedAddress
)) break;
1332 /* Try the next one */
1333 NextEntry
= NextEntry
->Flink
;
1336 /* If we made it, we're done */
1337 *Context
= (ULONG_PTR
)Handler
;
1341 /* Try the first one through */
1342 if (!HalTranslateBusAddress(Handler
->InterfaceType
,
1346 TranslatedAddress
)) return FALSE
;
1348 /* Remember for next time */
1349 *Context
= (ULONG_PTR
)Handler
;
1355 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1357 IN PHYSICAL_ADDRESS BusAddress
,
1358 IN OUT PULONG AddressSpace
,
1359 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1361 PBUS_HANDLER Handler
;
1364 /* Find the handler */
1365 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1366 if (!(Handler
) || !(Handler
->TranslateBusAddress
))
1368 DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType
, BusNumber
, Handler
, BusAddress
);
1372 /* Do the assignment */
1373 Status
= Handler
->TranslateBusAddress(Handler
,
1379 /* Dereference the handler and return */
1380 HalDereferenceBusHandler(Handler
);
1384 /* PUBLIC FUNCTIONS **********************************************************/
1391 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST
*ResourceList
)
1393 PBUS_HANDLER Handler
;
1397 /* Find the handler */
1398 Handler
= HalReferenceHandlerForBus((*ResourceList
)->InterfaceType
,
1399 (*ResourceList
)->BusNumber
);
1400 if (!Handler
) return STATUS_SUCCESS
;
1402 /* Do the assignment */
1403 Status
= Handler
->AdjustResourceList(Handler
,
1407 /* Dereference the handler and return */
1408 HalDereferenceBusHandler(Handler
);
1417 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1418 IN PUNICODE_STRING DriverClassName
,
1419 IN PDRIVER_OBJECT DriverObject
,
1420 IN PDEVICE_OBJECT DeviceObject
,
1421 IN INTERFACE_TYPE BusType
,
1423 IN ULONG SlotNumber
,
1424 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1428 /* Check the bus type */
1429 if (BusType
!= PCIBus
)
1431 /* Call our internal handler */
1432 return HalpAssignSlotResources(RegistryPath
,
1439 AllocatedResources
);
1443 /* Call the PCI registered function */
1444 return HalPciAssignSlotResources(RegistryPath
,
1451 AllocatedResources
);
1460 HalGetBusData(IN BUS_DATA_TYPE BusDataType
,
1462 IN ULONG SlotNumber
,
1466 /* Call the extended function */
1467 return HalGetBusDataByOffset(BusDataType
,
1480 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1482 IN ULONG SlotNumber
,
1487 PBUS_HANDLER Handler
;
1490 /* Find the handler */
1491 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1492 if (!Handler
) return 0;
1494 /* Do the assignment */
1495 Status
= Handler
->GetBusData(Handler
,
1502 /* Dereference the handler and return */
1503 HalDereferenceBusHandler(Handler
);
1512 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType
,
1514 IN ULONG BusInterruptLevel
,
1515 IN ULONG BusInterruptVector
,
1517 OUT PKAFFINITY Affinity
)
1519 PBUS_HANDLER Handler
;
1527 /* Find the handler */
1528 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1529 if (!Handler
) return 0;
1531 /* Do the assignment */
1532 Vector
= Handler
->GetInterruptVector(Handler
,
1538 if ((Vector
!= IRQ2VECTOR(BusInterruptLevel
)) ||
1539 (*Irql
!= VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
))))
1541 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1542 *Irql
, Vector
, BusInterruptLevel
, BusInterruptVector
);
1543 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1544 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
)),
1545 IRQ2VECTOR(BusInterruptLevel
));
1548 /* Dereference the handler and return */
1549 HalDereferenceBusHandler(Handler
);
1558 HalSetBusData(IN BUS_DATA_TYPE BusDataType
,
1560 IN ULONG SlotNumber
,
1564 /* Call the extended function */
1565 return HalSetBusDataByOffset(BusDataType
,
1578 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1580 IN ULONG SlotNumber
,
1585 PBUS_HANDLER Handler
;
1588 /* Find the handler */
1589 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1590 if (!Handler
) return 0;
1592 /* Do the assignment */
1593 Status
= Handler
->SetBusData(Handler
,
1600 /* Dereference the handler and return */
1601 HalDereferenceBusHandler(Handler
);
1610 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1612 IN PHYSICAL_ADDRESS BusAddress
,
1613 IN OUT PULONG AddressSpace
,
1614 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1616 /* Look as the bus type */
1617 if (InterfaceType
== PCIBus
)
1619 /* Call the PCI registered function */
1620 return HalPciTranslateBusAddress(PCIBus
,
1628 /* Call the bus handler */
1629 return HaliTranslateBusAddress(InterfaceType
,