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 *******************************************************************/
18 HalpAllocateAndInitPciBusHandler(
21 IN BOOLEAN TestAllocation
27 HalpFixupPciSupportedRanges(
44 HalpGetPciBridgeConfig(
53 IN PPCI_COMMON_CONFIG PciData
60 IN PPCI_COMMON_CONFIG PciData
67 IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
,
68 IN PPCI_COMMON_CONFIG PciData
,
76 IN PBUS_HANDLER BusHandler
,
77 IN PCI_SLOT_NUMBER Slot
83 HalpMarkChipsetDecode(
84 IN BOOLEAN OverrideEnable
90 HalpRegisterInternalBusHandlers(
102 #if defined(ALLOC_PRAGMA) && !defined(_MINIHAL_)
103 #pragma alloc_text(INIT, HalpAllocateAndInitPciBusHandler)
104 #pragma alloc_text(INIT, HalpDebugPciDumpBus)
105 #pragma alloc_text(INIT, HalpFixupPciSupportedRanges)
106 #pragma alloc_text(INIT, HalpGetChipHacks)
107 #pragma alloc_text(INIT, HalpGetPciBridgeConfig)
108 #pragma alloc_text(INIT, HalpInitBusHandlers)
109 #pragma alloc_text(INIT, HalpInitializePciBus)
110 #pragma alloc_text(INIT, HalpIsBridgeDevice)
111 #pragma alloc_text(INIT, HalpIsIdeDevice)
112 #pragma alloc_text(INIT, HalpIsRecognizedCard)
113 #pragma alloc_text(INIT, HalpIsValidPCIDevice)
114 #pragma alloc_text(INIT, HalpMarkChipsetDecode)
115 #pragma alloc_text(INIT, HalpRegisterKdSupportFunctions)
116 #pragma alloc_text(INIT, HalpRegisterInternalBusHandlers)
117 #pragma alloc_text(INIT, ShowSize)
120 /* GLOBALS ********************************************************************/
122 extern KSPIN_LOCK HalpPCIConfigLock
;
123 ULONG HalpPciIrqMask
;
125 /* PRIVATE FUNCTIONS **********************************************************/
129 HalpAllocateBusHandler(IN INTERFACE_TYPE InterfaceType
,
130 IN BUS_DATA_TYPE BusDataType
,
132 IN INTERFACE_TYPE ParentBusInterfaceType
,
133 IN ULONG ParentBusNumber
,
134 IN ULONG BusSpecificData
)
138 /* Register the bus handler */
139 HalRegisterBusHandler(InterfaceType
,
142 ParentBusInterfaceType
,
152 /* Check for a valid interface */
153 if (InterfaceType
!= InterfaceTypeUndefined
)
155 /* Allocate address ranges and zero them out */
156 Bus
->BusAddresses
= ExAllocatePoolWithTag(NonPagedPoolMustSucceed
,
157 sizeof(SUPPORTED_RANGES
),
159 RtlZeroMemory(Bus
->BusAddresses
, sizeof(SUPPORTED_RANGES
));
161 /* Build the data structure */
162 Bus
->BusAddresses
->Version
= HAL_SUPPORTED_RANGE_VERSION
;
163 Bus
->BusAddresses
->Dma
.Limit
= 7;
164 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFFFF;
165 Bus
->BusAddresses
->IO
.Limit
= 0xFFFF;
166 Bus
->BusAddresses
->IO
.SystemAddressSpace
= 1;
167 Bus
->BusAddresses
->PrefetchMemory
.Base
= 1;
170 /* Return the bus address */
177 HalpRegisterInternalBusHandlers(VOID
)
181 /* Only do processor 1 */
182 if (KeGetCurrentPrcb()->Number
) return;
184 /* Register root support */
185 HalpInitBusHandler();
187 /* Allocate the system bus */
188 Bus
= HalpAllocateBusHandler(Internal
,
189 ConfigurationSpaceUndefined
,
191 InterfaceTypeUndefined
,
197 Bus
->GetInterruptVector
= HalpGetSystemInterruptVector
;
198 Bus
->TranslateBusAddress
= HalpTranslateSystemBusAddress
;
201 /* Allocate the CMOS bus */
202 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
205 InterfaceTypeUndefined
,
211 Bus
->GetBusData
= HalpcGetCmosData
;
212 Bus
->SetBusData
= HalpcSetCmosData
;
215 /* Allocate the CMOS bus */
216 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
219 InterfaceTypeUndefined
,
225 Bus
->GetBusData
= HalpcGetCmosData
;
226 Bus
->SetBusData
= HalpcSetCmosData
;
229 /* Allocate ISA bus */
230 Bus
= HalpAllocateBusHandler(Isa
,
231 ConfigurationSpaceUndefined
,
239 Bus
->GetBusData
= HalpNoBusData
;
240 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFF;
241 Bus
->TranslateBusAddress
= HalpTranslateIsaBusAddress
;
244 /* No support for EISA or MCA */
245 ASSERT(HalpBusType
== MACHINE_TYPE_ISA
);
252 HalpMarkChipsetDecode(BOOLEAN OverrideEnable
)
255 UNICODE_STRING KeyString
;
256 ULONG Data
= OverrideEnable
;
257 HANDLE KeyHandle
, Handle
;
260 RtlInitUnicodeString(&KeyString
,
261 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
262 Status
= HalpOpenRegistryKey(&Handle
, 0, &KeyString
, KEY_ALL_ACCESS
, FALSE
);
263 if (NT_SUCCESS(Status
))
265 /* Open PNP Bios key */
266 RtlInitUnicodeString(&KeyString
, L
"Control\\Biosinfo\\PNPBios");
267 Status
= HalpOpenRegistryKey(&KeyHandle
,
276 /* Check if PNP BIOS key exists */
277 if (NT_SUCCESS(Status
))
279 /* Set the override value */
280 RtlInitUnicodeString(&KeyString
, L
"FullDecodeChipsetOverride");
281 Status
= ZwSetValueKey(KeyHandle
,
300 HalpAllocateAndInitPciBusHandler(IN ULONG PciType
,
302 IN BOOLEAN TestAllocation
)
305 PPCIPBUSDATA BusData
;
307 /* Allocate the bus handler */
308 Bus
= HalpAllocateBusHandler(PCIBus
,
313 sizeof(PCIPBUSDATA
));
316 Bus
->GetBusData
= HalpGetPCIData
;
317 Bus
->SetBusData
= HalpSetPCIData
;
318 Bus
->GetInterruptVector
= HalpGetPCIIntOnISABus
;
319 Bus
->AdjustResourceList
= HalpAdjustPCIResourceList
;
320 Bus
->AssignSlotResources
= HalpAssignPCISlotResources
;
321 Bus
->BusAddresses
->Dma
.Limit
= 0;
323 /* Get our custom bus data */
324 BusData
= (PPCIPBUSDATA
)Bus
->BusData
;
326 /* Setup custom bus data */
327 BusData
->CommonData
.Tag
= PCI_DATA_TAG
;
328 BusData
->CommonData
.Version
= PCI_DATA_VERSION
;
329 BusData
->CommonData
.ReadConfig
= HalpReadPCIConfig
;
330 BusData
->CommonData
.WriteConfig
= HalpWritePCIConfig
;
331 BusData
->CommonData
.Pin2Line
= HalpPCIPin2ISALine
;
332 BusData
->CommonData
.Line2Pin
= HalpPCIISALine2Pin
;
333 BusData
->MaxDevice
= PCI_MAX_DEVICES
;
334 BusData
->GetIrqRange
= HalpGetISAFixedPCIIrq
;
336 /* Initialize the bitmap */
337 RtlInitializeBitMap(&BusData
->DeviceConfigured
, BusData
->ConfiguredBits
, 256);
339 /* Check the type of PCI bus */
345 /* Copy the Type 1 handler data */
346 RtlCopyMemory(&PCIConfigHandler
,
347 &PCIConfigHandlerType1
,
348 sizeof(PCIConfigHandler
));
350 /* Set correct I/O Ports */
351 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
352 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
358 /* Copy the Type 1 handler data */
359 RtlCopyMemory(&PCIConfigHandler
,
360 &PCIConfigHandlerType2
,
361 sizeof (PCIConfigHandler
));
363 /* Set correct I/O Ports */
364 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
365 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
366 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
368 /* Only 16 devices supported, not 32 */
369 BusData
->MaxDevice
= 16;
375 DbgPrint("HAL: Unnkown PCI type\n");
378 /* Return the bus handler */
385 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler
,
386 IN PCI_SLOT_NUMBER Slot
)
388 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
389 PPCI_COMMON_CONFIG PciHeader
= (PVOID
)DataBuffer
;
393 /* Read the PCI header */
394 HalpReadPCIConfig(BusHandler
, Slot
, PciHeader
, 0, PCI_COMMON_HDR_LENGTH
);
396 /* Make sure it's a valid device */
397 if ((PciHeader
->VendorID
== PCI_INVALID_VENDORID
) ||
398 (PCI_CONFIGURATION_TYPE(PciHeader
) != PCI_DEVICE_TYPE
))
404 /* Make sure interrupt numbers make sense */
405 if (((PciHeader
->u
.type0
.InterruptPin
) &&
406 (PciHeader
->u
.type0
.InterruptPin
> 4)) ||
407 (PciHeader
->u
.type0
.InterruptLine
& 0x70))
413 /* Now scan PCI BARs */
414 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
416 /* Check what kind of address it is */
417 Address
= PciHeader
->u
.type0
.BaseAddresses
[i
];
418 if (Address
& PCI_ADDRESS_IO_SPACE
)
420 /* Highest I/O port is 65535 */
421 if (Address
> 0xFFFF) return FALSE
;
425 /* MMIO should be higher than 0x80000 */
426 if ((Address
> 0xF) && (Address
< 0x80000)) return FALSE
;
429 /* Is this a 64-bit address? */
430 if (!(Address
& PCI_ADDRESS_IO_SPACE
) &&
431 ((Address
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
))
433 /* Check the next-next entry, since this one 64-bits wide */
438 /* Header, interrupt and address data all make sense */
442 static BOOLEAN WarningsGiven
[5];
447 HalpGetChipHacks(IN USHORT VendorId
,
452 UNICODE_STRING KeyName
, ValueName
;
454 OBJECT_ATTRIBUTES ObjectAttributes
;
457 KEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
460 /* Setup the object attributes for the key */
461 RtlInitUnicodeString(&KeyName
,
462 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
464 InitializeObjectAttributes(&ObjectAttributes
,
466 OBJ_CASE_INSENSITIVE
,
471 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
472 if (!NT_SUCCESS(Status
)) return Status
;
475 swprintf(Buffer
, L
"%04X%04X", VendorId
, DeviceId
);
476 RtlInitUnicodeString(&ValueName
, Buffer
);
477 Status
= ZwQueryValueKey(KeyHandle
,
479 KeyValuePartialInformation
,
483 if (NT_SUCCESS(Status
))
485 /* Return the flags */
486 DbgPrint("\tFound HackFlags for your chipset\n");
487 *HackFlags
= *(PULONG
)PartialInfo
.Data
;
488 DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
489 *HackFlags
, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
), RevisionId
);
491 /* Does it apply to this revision? */
492 if ((RevisionId
) && (RevisionId
>= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
))))
494 /* Read the revision flags */
495 *HackFlags
= HALP_REVISION_HACK_FLAGS(*HackFlags
);
498 /* Throw out revision data */
499 *HackFlags
= HALP_HACK_FLAGS(*HackFlags
);
500 if (!*HackFlags
) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
503 /* Close the handle and return */
511 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
,
512 IN PPCI_COMMON_CONFIG PciData
,
515 ULONG ElementCount
, i
;
516 PPCI_CARD_DESCRIPTOR CardDescriptor
;
518 /* How many PCI Cards that we know about? */
519 ElementCount
= PciRegistryInfo
->ElementCount
;
520 if (!ElementCount
) return FALSE
;
522 /* Loop all descriptors */
523 CardDescriptor
= &PciRegistryInfo
->CardList
[0];
524 for (i
= 0; i
< ElementCount
; i
++, CardDescriptor
++)
526 /* Check for flag match */
527 if (CardDescriptor
->Flags
!= Flags
) continue;
529 /* Check for VID-PID match */
530 if ((CardDescriptor
->VendorID
!= PciData
->VendorID
) ||
531 (CardDescriptor
->DeviceID
!= PciData
->DeviceID
))
537 /* Check for revision match, if requested */
538 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_REVISION_ID
) &&
539 (CardDescriptor
->RevisionID
!= PciData
->RevisionID
))
545 /* Check what kind of device this is */
546 switch (PCI_CONFIGURATION_TYPE(PciData
))
549 case PCI_CARDBUS_BRIDGE_TYPE
:
551 /* This means the real device header is in the device-specific data */
552 PciData
= (PPCI_COMMON_CONFIG
)PciData
->DeviceSpecific
;
554 /* Normal PCI device */
555 case PCI_DEVICE_TYPE
:
557 /* Check for subvendor match, if requested */
558 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBVENDOR_ID
) &&
559 (CardDescriptor
->SubsystemVendorID
!= PciData
->u
.type0
.SubVendorID
))
565 /* Check for subsystem match, if requested */
566 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBSYSTEM_ID
) &&
567 (CardDescriptor
->SubsystemID
!= PciData
->u
.type0
.SubSystemID
))
576 /* PCI Bridge -- don't bother */
577 case PCI_BRIDGE_TYPE
:
585 /* This means the card isn't recognized */
592 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData
)
594 /* Simple test first */
595 if ((PciData
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
596 (PciData
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
))
598 /* The device is nice enough to admit it */
602 /* Symphony 82C101 */
603 if (PciData
->VendorID
== 0x1C1C) return TRUE
;
605 /* ALi MS4803 or M5219 */
606 if ((PciData
->VendorID
== 0x10B9) &&
607 ((PciData
->DeviceID
== 0x5215) || (PciData
->DeviceID
== 0x5219)))
612 /* Appian Technology */
613 if ((PciData
->VendorID
== 0x1097) && (PciData
->DeviceID
== 0x38)) return TRUE
;
615 /* Compaq Triflex Dual EIDE Controller */
616 if ((PciData
->VendorID
== 0xE11) && (PciData
->DeviceID
== 0xAE33)) return TRUE
;
618 /* Micron PC Tech RZ1000 */
619 if ((PciData
->VendorID
== 0x1042) && (PciData
->DeviceID
== 0x1000)) return TRUE
;
621 /* SiS 85C601 or 5513 [IDE] */
622 if ((PciData
->VendorID
== 0x1039) &&
623 ((PciData
->DeviceID
== 0x601) || (PciData
->DeviceID
== 0x5513)))
628 /* Symphony Labs W83769F */
629 if ((PciData
->VendorID
== 0x10AD) &&
630 ((PciData
->DeviceID
== 0x1) || (PciData
->DeviceID
== 0x150)))
636 if ((PciData
->VendorID
== 0x1060) && (PciData
->DeviceID
== 0x101)) return TRUE
;
638 /* You've survived */
645 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData
)
647 /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
648 return (((PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
) &&
649 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
650 (PciData
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
)) ||
651 ((PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
) &&
652 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
653 (PciData
->SubClass
== PCI_SUBCLASS_BR_CARDBUS
)));
659 HalpGetPciBridgeConfig(IN ULONG PciType
,
662 PCI_SLOT_NUMBER PciSlot
;
664 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
665 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
666 PBUS_HANDLER BusHandler
;
669 PciSlot
.u
.bits
.Reserved
= 0;
670 for (i
= 0; i
< *BusCount
; i
++)
672 /* Get the bus handler */
673 BusHandler
= HalHandlerForBus(PCIBus
, i
);
675 /* Loop every device */
676 for (j
= 0; j
< PCI_MAX_DEVICES
; j
++)
678 /* Loop every function */
679 PciSlot
.u
.bits
.DeviceNumber
= j
;
680 for (k
= 0; k
< PCI_MAX_FUNCTION
; k
++)
682 /* Build the final slot structure */
683 PciSlot
.u
.bits
.FunctionNumber
= k
;
685 /* Read the configuration information */
686 HalpReadPCIConfig(BusHandler
,
690 PCI_COMMON_HDR_LENGTH
);
692 /* Skip if this is an invalid function */
693 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
695 /* Make sure that this is a PCI bridge or a cardbus bridge */
696 if (!HalpIsBridgeDevice(PciData
)) continue;
699 if (!WarningsGiven
[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
705 /* If we exited the loop, then there's no bridge to worry about */
712 HalpFixupPciSupportedRanges(IN ULONG BusCount
)
715 PBUS_HANDLER Bus
, ParentBus
;
718 for (i
= 0; i
< BusCount
; i
++)
720 /* Get PCI bus handler */
721 Bus
= HalHandlerForBus(PCIBus
, i
);
723 /* Loop all parent buses */
724 ParentBus
= Bus
->ParentHandler
;
727 /* Should merge addresses */
728 if (!WarningsGiven
[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
730 /* Check the next parent */
731 ParentBus
= ParentBus
->ParentHandler
;
735 /* Loop all buses again */
736 for (i
= 0; i
< BusCount
; i
++)
738 /* Get PCI bus handler */
739 Bus
= HalHandlerForBus(PCIBus
, i
);
741 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
742 if (!((PPCIPBUSDATA
)Bus
->BusData
)->Subtractive
)
744 /* Loop all parent buses */
745 ParentBus
= Bus
->ParentHandler
;
748 /* But check only PCI parent buses specifically */
749 if (ParentBus
->InterfaceType
== PCIBus
)
751 /* Should trim addresses */
752 if (!WarningsGiven
[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
755 /* Check the next parent */
756 ParentBus
= ParentBus
->ParentHandler
;
761 /* Loop buses one last time */
762 for (i
= 0; i
< BusCount
; i
++)
764 /* Get the PCI bus handler */
765 Bus
= HalHandlerForBus(PCIBus
, i
);
767 /* Sort and combine (trim) bus address range information */
768 DPRINT("Warning: Bus addresses not being optimized!\n");
781 DbgPrint("%d", (int) x
);
783 else if (x
< 1048576)
785 DbgPrint("%dK", (int)(x
/ 1024));
787 else if (x
< 0x80000000)
789 DbgPrint("%dM", (int)(x
/ 1048576));
799 * These includes are required to define
800 * the ClassTable and VendorTable arrays.
802 #include "pci_classes.h"
803 #include "pci_vendors.h"
807 HalpDebugPciDumpBus(IN ULONG i
,
810 IN PPCI_COMMON_CONFIG PciData
)
812 PCHAR p
, ClassName
, SubClassName
, VendorName
, ProductName
, SubVendorName
;
814 CHAR LookupString
[16] = "";
815 CHAR bSubClassName
[64] = "";
816 CHAR bVendorName
[64] = "";
817 CHAR bProductName
[128] = "Unknown device";
818 CHAR bSubVendorName
[128] = "Unknown";
821 /* Isolate the class name */
822 sprintf(LookupString
, "C %02x ", PciData
->BaseClass
);
823 ClassName
= strstr((PCHAR
)ClassTable
, LookupString
);
826 /* Isolate the subclass name */
828 sprintf(LookupString
, "\t%02x ", PciData
->SubClass
);
829 SubClassName
= strstr(ClassName
, LookupString
);
832 /* Copy the subclass into our buffer */
834 p
= strpbrk(SubClassName
, "\r\n");
835 Length
= p
- SubClassName
;
836 if (Length
>= sizeof(bSubClassName
)) Length
= sizeof(bSubClassName
) - 1;
837 strncpy(bSubClassName
, SubClassName
, Length
);
838 bSubClassName
[Length
] = '\0';
842 /* Isolate the vendor name */
843 sprintf(LookupString
, "\r\n%04x ", PciData
->VendorID
);
844 VendorName
= strstr((PCHAR
)VendorTable
, LookupString
);
847 /* Copy the vendor name into our buffer */
849 p
= strpbrk(VendorName
, "\r\n");
850 Length
= p
- VendorName
;
851 if (Length
>= sizeof(bVendorName
)) Length
= sizeof(bVendorName
) - 1;
852 strncpy(bVendorName
, VendorName
, Length
);
853 bVendorName
[Length
] = '\0';
855 /* Isolate the product name */
856 sprintf(LookupString
, "\t%04x ", PciData
->DeviceID
);
857 ProductName
= strstr(VendorName
, LookupString
);
860 /* Copy the product name into our buffer */
862 p
= strpbrk(ProductName
, "\r\n");
863 Length
= p
- ProductName
;
864 if (Length
>= sizeof(bProductName
)) Length
= sizeof(bProductName
) - 1;
865 strncpy(bProductName
, ProductName
, Length
);
866 bProductName
[Length
] = '\0';
868 /* Isolate the subvendor and subsystem name */
869 sprintf(LookupString
,
871 PciData
->u
.type0
.SubVendorID
,
872 PciData
->u
.type0
.SubSystemID
);
873 SubVendorName
= strstr(ProductName
, LookupString
);
876 /* Copy the subvendor name into our buffer */
878 p
= strpbrk(SubVendorName
, "\r\n");
879 Length
= p
- SubVendorName
;
880 if (Length
>= sizeof(bSubVendorName
)) Length
= sizeof(bSubVendorName
) - 1;
881 strncpy(bSubVendorName
, SubVendorName
, Length
);
882 bSubVendorName
[Length
] = '\0';
887 /* Print out the data */
888 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
889 "\tSubsystem: %s [%04x:%04x]\n",
902 PciData
->u
.type0
.SubVendorID
,
903 PciData
->u
.type0
.SubSystemID
);
905 /* Print out and decode flags */
906 DbgPrint("\tFlags:");
907 if (PciData
->Command
& PCI_ENABLE_BUS_MASTER
) DbgPrint(" bus master,");
908 if (PciData
->Status
& PCI_STATUS_66MHZ_CAPABLE
) DbgPrint(" 66MHz,");
909 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x000) DbgPrint(" fast devsel,");
910 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x200) DbgPrint(" medium devsel,");
911 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x400) DbgPrint(" slow devsel,");
912 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x600) DbgPrint(" unknown devsel,");
913 DbgPrint(" latency %d", PciData
->LatencyTimer
);
914 if (PciData
->u
.type0
.InterruptPin
!= 0 &&
915 PciData
->u
.type0
.InterruptLine
!= 0 &&
916 PciData
->u
.type0
.InterruptLine
!= 0xFF) DbgPrint(", IRQ %02d", PciData
->u
.type0
.InterruptLine
);
917 else if (PciData
->u
.type0
.InterruptPin
!= 0) DbgPrint(", IRQ assignment required");
922 for (b
= 0; b
< PCI_TYPE0_ADDRESSES
; b
++)
924 /* Check for a BAR */
925 Mem
= PciData
->u
.type0
.BaseAddresses
[b
];
928 /* Decode the address type */
929 if (Mem
& PCI_ADDRESS_IO_SPACE
)
933 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
936 DbgPrint("\tI/O ports at %04lx", Mem
& PCI_ADDRESS_IO_ADDRESS_MASK
);
943 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
946 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
947 Mem
& PCI_ADDRESS_MEMORY_ADDRESS_MASK
,
948 (Mem
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_32BIT
? 32 : 64,
949 (Mem
& PCI_ADDRESS_MEMORY_PREFETCHABLE
) ? "" : "non-");
960 HalpInitializePciBus(VOID
)
963 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
965 PCI_SLOT_NUMBER PciSlot
;
967 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
968 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
969 PBUS_HANDLER BusHandler
;
971 BOOLEAN ExtendedAddressDecoding
= FALSE
;
974 /* Query registry information */
975 PciRegistryInfo
= HalpQueryPciRegistryInfo();
976 if (!PciRegistryInfo
) return;
978 /* Initialize the PCI configuration lock */
979 KeInitializeSpinLock(&HalpPCIConfigLock
);
981 /* Get the type and free the info structure */
982 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
984 /* Check if this is a type 2 PCI bus with at least one bus */
985 if ((PciRegistryInfo
->NoBuses
) && (PciType
== 2))
987 /* Setup the PCI slot */
988 PciSlot
.u
.bits
.Reserved
= 0;
989 PciSlot
.u
.bits
.FunctionNumber
= 0;
992 for (i
= 0; i
< 32; i
++)
994 /* Try to setup a Type 2 PCI slot */
996 BusHandler
= HalpAllocateAndInitPciBusHandler(2, 0, TRUE
);
997 if (!BusHandler
) break;
999 /* Now check if it's valid */
1000 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
1002 /* Heh, the BIOS lied... try Type 1 */
1004 BusHandler
= HalpAllocateAndInitPciBusHandler(1, 0, TRUE
);
1005 if (!BusHandler
) break;
1007 /* Now check if it's valid */
1008 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
1014 /* Now allocate the correct kind of handler */
1015 HalpAllocateAndInitPciBusHandler(PciType
, 0, FALSE
);
1018 /* Okay, now loop all PCI bridges */
1021 /* Loop all PCI buses */
1022 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
1024 /* Check if we have a handler for it */
1025 if (!HalHandlerForBus(PCIBus
, i
))
1028 HalpAllocateAndInitPciBusHandler(PciType
, i
, FALSE
);
1031 /* Go to the next bridge */
1032 } while (HalpGetPciBridgeConfig(PciType
, &PciRegistryInfo
->NoBuses
));
1034 /* Now build correct address range informaiton */
1035 HalpFixupPciSupportedRanges(PciRegistryInfo
->NoBuses
);
1037 /* Loop every bus */
1038 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
1039 PciSlot
.u
.bits
.Reserved
= 0;
1040 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
1042 /* Get the bus handler */
1043 BusHandler
= HalHandlerForBus(PCIBus
, i
);
1045 /* Loop every device */
1046 for (j
= 0; j
< 32; j
++)
1048 /* Loop every function */
1049 PciSlot
.u
.bits
.DeviceNumber
= j
;
1050 for (k
= 0; k
< 8; k
++)
1052 /* Build the final slot structure */
1053 PciSlot
.u
.bits
.FunctionNumber
= k
;
1055 /* Read the configuration information */
1056 HalpReadPCIConfig(BusHandler
,
1060 PCI_COMMON_HDR_LENGTH
);
1062 /* Skip if this is an invalid function */
1063 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
1065 /* Print out the entry */
1066 HalpDebugPciDumpBus(i
, j
, k
, PciData
);
1068 /* Check if this is a Cardbus bridge */
1069 if (PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
)
1072 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
1076 /* Check if this is a PCI device */
1077 if (PCI_CONFIGURATION_TYPE(PciData
) != PCI_BRIDGE_TYPE
)
1079 /* Check if it has an interrupt pin and line registered */
1080 if ((PciData
->u
.type1
.InterruptPin
) &&
1081 (PciData
->u
.type1
.InterruptLine
))
1083 /* Check if this interrupt line is connected to the bus */
1084 if (PciData
->u
.type1
.InterruptLine
< 16)
1086 /* Is this an IDE device? */
1087 if (!HalpIsIdeDevice(PciData
))
1089 /* We'll mask out this interrupt then */
1090 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
1091 PciData
->u
.type1
.InterruptLine
);
1092 HalpPciIrqMask
|= (1 << PciData
->u
.type1
.InterruptLine
);
1098 /* Check for broken Intel chips */
1099 if (PciData
->VendorID
== 0x8086)
1101 /* Check for broken 82830 PCI controller */
1102 if ((PciData
->DeviceID
== 0x04A3) &&
1103 (PciData
->RevisionID
< 0x11))
1106 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
1110 /* Check for broken 82378 PCI-to-ISA Bridge */
1111 if ((PciData
->DeviceID
== 0x0484) &&
1112 (PciData
->RevisionID
<= 3))
1115 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
1119 /* Check for broken 82450 PCI Bridge */
1120 if ((PciData
->DeviceID
== 0x84C4) &&
1121 (PciData
->RevisionID
<= 4))
1123 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
1128 /* Do we know this card? */
1129 if (!ExtendedAddressDecoding
)
1132 if (HalpIsRecognizedCard(PciRegistryInfo
,
1134 HALP_CARD_FEATURE_FULL_DECODE
))
1136 /* We'll do chipset checks later */
1137 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1138 ExtendedAddressDecoding
= TRUE
;
1142 /* Now check the registry for chipset hacks */
1143 Status
= HalpGetChipHacks(PciData
->VendorID
,
1145 PciData
->RevisionID
,
1147 if (NT_SUCCESS(Status
))
1149 /* Check for broken ACPI routing */
1150 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING
)
1152 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1156 /* Check for broken ACPI timer */
1157 if (HackFlags
& HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER
)
1159 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1163 /* Check for hibernate-disable */
1164 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE
)
1166 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1170 /* Check for USB controllers that generate SMIs */
1171 if (HackFlags
& HAL_PCI_CHIP_HACK_USB_SMI_DISABLE
)
1173 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1178 /* Terminate the entry */
1184 /* Initialize NMI Crash Flag */
1185 HalpGetNMICrashFlag();
1187 /* Free the registry data */
1188 ExFreePoolWithTag(PciRegistryInfo
, TAG_HAL
);
1190 /* Tell PnP if this hard supports correct decoding */
1191 HalpMarkChipsetDecode(ExtendedAddressDecoding
);
1192 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1199 HalpInitBusHandlers(VOID
)
1201 /* Register the HAL Bus Handler support */
1202 HalpRegisterInternalBusHandlers();
1208 HalpRegisterKdSupportFunctions(VOID
)
1210 /* Register PCI Device Functions */
1211 KdSetupPciDeviceForDebugging
= HalpSetupPciDeviceForDebugging
;
1212 KdReleasePciDeviceforDebugging
= HalpReleasePciDeviceForDebugging
;
1214 /* Register memory functions */
1216 #if (NTDDI_VERSION >= NTDDI_VISTA)
1217 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64Vista
;
1218 KdUnmapVirtualAddress
= HalpUnmapVirtualAddressVista
;
1220 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64
;
1221 KdUnmapVirtualAddress
= HalpUnmapVirtualAddress
;
1225 /* Register ACPI stub */
1226 KdCheckPowerButton
= HalpCheckPowerButton
;
1231 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1232 IN PUNICODE_STRING DriverClassName
,
1233 IN PDRIVER_OBJECT DriverObject
,
1234 IN PDEVICE_OBJECT DeviceObject
,
1235 IN INTERFACE_TYPE BusType
,
1237 IN ULONG SlotNumber
,
1238 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1240 PBUS_HANDLER Handler
;
1243 DPRINT1("Slot assignment for %d on bus %u\n", BusType
, BusNumber
);
1245 /* Find the handler */
1246 Handler
= HalReferenceHandlerForBus(BusType
, BusNumber
);
1247 if (!Handler
) return STATUS_NOT_FOUND
;
1249 /* Do the assignment */
1250 Status
= Handler
->AssignSlotResources(Handler
,
1257 AllocatedResources
);
1259 /* Dereference the handler and return */
1260 HalDereferenceBusHandler(Handler
);
1266 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress
,
1267 IN OUT PULONG AddressSpace
,
1268 OUT PPHYSICAL_ADDRESS TranslatedAddress
,
1269 IN OUT PULONG_PTR Context
,
1272 PHAL_BUS_HANDLER BusHandler
;
1273 PBUS_HANDLER Handler
;
1274 PLIST_ENTRY NextEntry
;
1277 /* Make sure we have a context */
1278 if (!Context
) return FALSE
;
1279 ASSERT((*Context
) || (NextBus
== TRUE
));
1281 /* Read the context */
1282 ContextValue
= *Context
;
1284 /* Find the bus handler */
1285 Handler
= HalpContextToBusHandler(ContextValue
);
1286 if (!Handler
) return FALSE
;
1288 /* Check if this is an ongoing lookup */
1291 /* Get the HAL bus handler */
1292 BusHandler
= CONTAINING_RECORD(Handler
, HAL_BUS_HANDLER
, Handler
);
1293 NextEntry
= &BusHandler
->AllHandlers
;
1295 /* Get the next one if we were already with one */
1296 if (ContextValue
) NextEntry
= NextEntry
->Flink
;
1298 /* Start scanning */
1301 /* Check if this is the last one */
1302 if (NextEntry
== &HalpAllBusHandlers
)
1309 /* Call this translator */
1310 BusHandler
= CONTAINING_RECORD(NextEntry
, HAL_BUS_HANDLER
, AllHandlers
);
1311 if (HalTranslateBusAddress(BusHandler
->Handler
.InterfaceType
,
1312 BusHandler
->Handler
.BusNumber
,
1315 TranslatedAddress
)) break;
1317 /* Try the next one */
1318 NextEntry
= NextEntry
->Flink
;
1321 /* If we made it, we're done */
1322 *Context
= (ULONG_PTR
)Handler
;
1326 /* Try the first one through */
1327 if (!HalTranslateBusAddress(Handler
->InterfaceType
,
1331 TranslatedAddress
)) return FALSE
;
1333 /* Remember for next time */
1334 *Context
= (ULONG_PTR
)Handler
;
1340 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1342 IN PHYSICAL_ADDRESS BusAddress
,
1343 IN OUT PULONG AddressSpace
,
1344 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1346 PBUS_HANDLER Handler
;
1349 /* Find the handler */
1350 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1351 if (!(Handler
) || !(Handler
->TranslateBusAddress
))
1353 DPRINT1("No translator Interface: %x, Bus: %x, Handler: %p, BusAddress: %x!\n", InterfaceType
, BusNumber
, Handler
, BusAddress
);
1357 /* Do the assignment */
1358 Status
= Handler
->TranslateBusAddress(Handler
,
1364 /* Dereference the handler and return */
1365 HalDereferenceBusHandler(Handler
);
1369 /* PUBLIC FUNCTIONS **********************************************************/
1376 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST
*ResourceList
)
1378 PBUS_HANDLER Handler
;
1382 /* Find the handler */
1383 Handler
= HalReferenceHandlerForBus((*ResourceList
)->InterfaceType
,
1384 (*ResourceList
)->BusNumber
);
1385 if (!Handler
) return STATUS_SUCCESS
;
1387 /* Do the assignment */
1388 Status
= Handler
->AdjustResourceList(Handler
,
1392 /* Dereference the handler and return */
1393 HalDereferenceBusHandler(Handler
);
1402 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1403 IN PUNICODE_STRING DriverClassName
,
1404 IN PDRIVER_OBJECT DriverObject
,
1405 IN PDEVICE_OBJECT DeviceObject
,
1406 IN INTERFACE_TYPE BusType
,
1408 IN ULONG SlotNumber
,
1409 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1413 /* Check the bus type */
1414 if (BusType
!= PCIBus
)
1416 /* Call our internal handler */
1417 return HalpAssignSlotResources(RegistryPath
,
1424 AllocatedResources
);
1428 /* Call the PCI registered function */
1429 return HalPciAssignSlotResources(RegistryPath
,
1436 AllocatedResources
);
1445 HalGetBusData(IN BUS_DATA_TYPE BusDataType
,
1447 IN ULONG SlotNumber
,
1451 /* Call the extended function */
1452 return HalGetBusDataByOffset(BusDataType
,
1465 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1467 IN ULONG SlotNumber
,
1472 PBUS_HANDLER Handler
;
1475 /* Find the handler */
1476 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1477 if (!Handler
) return 0;
1479 /* Do the assignment */
1480 Status
= Handler
->GetBusData(Handler
,
1487 /* Dereference the handler and return */
1488 HalDereferenceBusHandler(Handler
);
1497 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType
,
1499 IN ULONG BusInterruptLevel
,
1500 IN ULONG BusInterruptVector
,
1502 OUT PKAFFINITY Affinity
)
1504 PBUS_HANDLER Handler
;
1512 /* Find the handler */
1513 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1514 if (!Handler
) return 0;
1516 /* Do the assignment */
1517 Vector
= Handler
->GetInterruptVector(Handler
,
1523 if ((Vector
!= IRQ2VECTOR(BusInterruptLevel
)) ||
1524 (*Irql
!= VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
))))
1526 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1527 *Irql
, Vector
, BusInterruptLevel
, BusInterruptVector
);
1528 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1529 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
)),
1530 IRQ2VECTOR(BusInterruptLevel
));
1533 /* Dereference the handler and return */
1534 HalDereferenceBusHandler(Handler
);
1543 HalSetBusData(IN BUS_DATA_TYPE BusDataType
,
1545 IN ULONG SlotNumber
,
1549 /* Call the extended function */
1550 return HalSetBusDataByOffset(BusDataType
,
1563 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1565 IN ULONG SlotNumber
,
1570 PBUS_HANDLER Handler
;
1573 /* Find the handler */
1574 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1575 if (!Handler
) return 0;
1577 /* Do the assignment */
1578 Status
= Handler
->SetBusData(Handler
,
1585 /* Dereference the handler and return */
1586 HalDereferenceBusHandler(Handler
);
1595 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1597 IN PHYSICAL_ADDRESS BusAddress
,
1598 IN OUT PULONG AddressSpace
,
1599 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1601 /* Look as the bus type */
1602 if (InterfaceType
== PCIBus
)
1604 /* Call the PCI registered function */
1605 return HalPciTranslateBusAddress(PCIBus
,
1613 /* Call the bus handler */
1614 return HaliTranslateBusAddress(InterfaceType
,