3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: hal/halx86/generic/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
,
42 if (!Bus
) return NULL
;
44 /* Check for a valid interface */
45 if (InterfaceType
!= InterfaceTypeUndefined
)
47 /* Allocate address ranges and zero them out */
48 Bus
->BusAddresses
= ExAllocatePoolWithTag(NonPagedPool
,
49 sizeof(SUPPORTED_RANGES
),
51 RtlZeroMemory(Bus
->BusAddresses
, sizeof(SUPPORTED_RANGES
));
53 /* Build the data structure */
54 Bus
->BusAddresses
->Version
= HAL_SUPPORTED_RANGE_VERSION
;
55 Bus
->BusAddresses
->Dma
.Limit
= 7;
56 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFFFF;
57 Bus
->BusAddresses
->IO
.Limit
= 0xFFFF;
58 Bus
->BusAddresses
->IO
.SystemAddressSpace
= 1;
59 Bus
->BusAddresses
->PrefetchMemory
.Base
= 1;
62 /* Return the bus address */
69 HalpRegisterInternalBusHandlers(VOID
)
73 /* Only do processor 1 */
74 if (KeGetCurrentPrcb()->Number
) return;
76 /* Register root support */
79 /* Allocate the system bus */
80 Bus
= HalpAllocateBusHandler(Internal
,
81 ConfigurationSpaceUndefined
,
83 InterfaceTypeUndefined
,
89 Bus
->GetInterruptVector
= HalpGetSystemInterruptVector
;
90 Bus
->TranslateBusAddress
= HalpTranslateSystemBusAddress
;
93 /* Allocate the CMOS bus */
94 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
97 InterfaceTypeUndefined
,
103 Bus
->GetBusData
= HalpcGetCmosData
;
104 Bus
->SetBusData
= HalpcSetCmosData
;
107 /* Allocate the CMOS bus */
108 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
111 InterfaceTypeUndefined
,
117 Bus
->GetBusData
= HalpcGetCmosData
;
118 Bus
->SetBusData
= HalpcSetCmosData
;
121 /* Allocate ISA bus */
122 Bus
= HalpAllocateBusHandler(Isa
,
123 ConfigurationSpaceUndefined
,
131 Bus
->GetBusData
= HalpNoBusData
;
132 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFF;
133 Bus
->TranslateBusAddress
= HalpTranslateIsaBusAddress
;
136 /* No support for EISA or MCA */
137 ASSERT(HalpBusType
== MACHINE_TYPE_ISA
);
144 HalpMarkChipsetDecode(BOOLEAN OverrideEnable
)
147 UNICODE_STRING KeyString
;
148 ULONG Data
= OverrideEnable
;
149 HANDLE KeyHandle
, Handle
;
152 RtlInitUnicodeString(&KeyString
,
153 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
154 Status
= HalpOpenRegistryKey(&Handle
, 0, &KeyString
, KEY_ALL_ACCESS
, FALSE
);
155 if (NT_SUCCESS(Status
))
157 /* Open PNP Bios key */
158 RtlInitUnicodeString(&KeyString
, L
"Control\\Biosinfo\\PNPBios");
159 Status
= HalpOpenRegistryKey(&KeyHandle
,
168 /* Check if PNP BIOS key exists */
169 if (NT_SUCCESS(Status
))
171 /* Set the override value */
172 RtlInitUnicodeString(&KeyString
, L
"FullDecodeChipsetOverride");
173 Status
= ZwSetValueKey(KeyHandle
,
192 HalpAllocateAndInitPciBusHandler(IN ULONG PciType
,
194 IN BOOLEAN TestAllocation
)
197 PPCIPBUSDATA BusData
;
199 /* Allocate the bus handler */
200 Bus
= HalpAllocateBusHandler(PCIBus
,
205 sizeof(PCIPBUSDATA
));
208 Bus
->GetBusData
= (PGETSETBUSDATA
)HalpGetPCIData
;
209 Bus
->SetBusData
= (PGETSETBUSDATA
)HalpSetPCIData
;
210 Bus
->GetInterruptVector
= (PGETINTERRUPTVECTOR
)HalpGetPCIIntOnISABus
;
211 Bus
->AdjustResourceList
= (PADJUSTRESOURCELIST
)HalpAdjustPCIResourceList
;
212 Bus
->AssignSlotResources
= (PASSIGNSLOTRESOURCES
)HalpAssignPCISlotResources
;
213 Bus
->BusAddresses
->Dma
.Limit
= 0;
215 /* Get our custom bus data */
216 BusData
= (PPCIPBUSDATA
)Bus
->BusData
;
218 /* Setup custom bus data */
219 BusData
->CommonData
.Tag
= PCI_DATA_TAG
;
220 BusData
->CommonData
.Version
= PCI_DATA_VERSION
;
221 BusData
->CommonData
.ReadConfig
= (PciReadWriteConfig
)HalpReadPCIConfig
;
222 BusData
->CommonData
.WriteConfig
= (PciReadWriteConfig
)HalpWritePCIConfig
;
223 BusData
->CommonData
.Pin2Line
= (PciPin2Line
)HalpPCIPin2ISALine
;
224 BusData
->CommonData
.Line2Pin
= (PciLine2Pin
)HalpPCIISALine2Pin
;
225 BusData
->MaxDevice
= PCI_MAX_DEVICES
;
226 BusData
->GetIrqRange
= (PciIrqRange
)HalpGetISAFixedPCIIrq
;
228 /* Initialize the bitmap */
229 RtlInitializeBitMap(&BusData
->DeviceConfigured
, BusData
->ConfiguredBits
, 256);
231 /* Check the type of PCI bus */
237 /* Copy the Type 1 handler data */
238 RtlCopyMemory(&PCIConfigHandler
,
239 &PCIConfigHandlerType1
,
240 sizeof(PCIConfigHandler
));
242 /* Set correct I/O Ports */
243 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
244 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
250 /* Copy the Type 1 handler data */
251 RtlCopyMemory(&PCIConfigHandler
,
252 &PCIConfigHandlerType2
,
253 sizeof (PCIConfigHandler
));
255 /* Set correct I/O Ports */
256 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
257 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
258 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
260 /* Only 16 devices supported, not 32 */
261 BusData
->MaxDevice
= 16;
267 DbgPrint("HAL: Unnkown PCI type\n");
270 /* Return the bus handler */
277 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler
,
278 IN PCI_SLOT_NUMBER Slot
)
280 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
281 PPCI_COMMON_CONFIG PciHeader
= (PVOID
)DataBuffer
;
285 /* Read the PCI header */
286 HalpReadPCIConfig(BusHandler
, Slot
, PciHeader
, 0, PCI_COMMON_HDR_LENGTH
);
288 /* Make sure it's a valid device */
289 if ((PciHeader
->VendorID
== PCI_INVALID_VENDORID
) ||
290 (PCI_CONFIGURATION_TYPE(PciHeader
) != PCI_DEVICE_TYPE
))
296 /* Make sure interrupt numbers make sense */
297 if (((PciHeader
->u
.type0
.InterruptPin
) &&
298 (PciHeader
->u
.type0
.InterruptPin
> 4)) ||
299 (PciHeader
->u
.type0
.InterruptLine
& 0x70))
305 /* Now scan PCI BARs */
306 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
308 /* Check what kind of address it is */
309 Address
= PciHeader
->u
.type0
.BaseAddresses
[i
];
310 if (Address
& PCI_ADDRESS_IO_SPACE
)
312 /* Highest I/O port is 65535 */
313 if (Address
> 0xFFFF) return FALSE
;
317 /* MMIO should be higher than 0x80000 */
318 if ((Address
> 0xF) && (Address
< 0x80000)) return FALSE
;
321 /* Is this a 64-bit address? */
322 if (!(Address
& PCI_ADDRESS_IO_SPACE
) &&
323 ((Address
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
))
325 /* Check the next-next entry, since this one 64-bits wide */
330 /* Header, interrupt and address data all make sense */
334 static BOOLEAN WarningsGiven
[5];
339 HalpGetChipHacks(IN USHORT VendorId
,
344 UNICODE_STRING KeyName
, ValueName
;
346 OBJECT_ATTRIBUTES ObjectAttributes
;
349 KEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
352 /* Setup the object attributes for the key */
353 RtlInitUnicodeString(&KeyName
,
354 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
356 InitializeObjectAttributes(&ObjectAttributes
,
358 OBJ_CASE_INSENSITIVE
,
363 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
364 if (!NT_SUCCESS(Status
)) return Status
;
367 swprintf(Buffer
, L
"%04X%04X", VendorId
, DeviceId
);
368 RtlInitUnicodeString(&ValueName
, Buffer
);
369 Status
= ZwQueryValueKey(KeyHandle
,
371 KeyValuePartialInformation
,
375 if (NT_SUCCESS(Status
))
377 /* Return the flags */
378 DbgPrint("\tFound HackFlags for your chipset\n");
379 *HackFlags
= *(PULONG
)PartialInfo
.Data
;
380 DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
381 *HackFlags
, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
), RevisionId
);
383 /* Does it apply to this revision? */
384 if ((RevisionId
) && (RevisionId
>= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
))))
386 /* Read the revision flags */
387 *HackFlags
= HALP_REVISION_HACK_FLAGS(*HackFlags
);
390 /* Throw out revision data */
391 *HackFlags
= HALP_HACK_FLAGS(*HackFlags
);
392 if (!*HackFlags
) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
395 /* Close the handle and return */
403 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
,
404 IN PPCI_COMMON_CONFIG PciData
,
407 ULONG ElementCount
, i
;
408 PPCI_CARD_DESCRIPTOR CardDescriptor
;
410 /* How many PCI Cards that we know about? */
411 ElementCount
= PciRegistryInfo
->ElementCount
;
412 if (!ElementCount
) return FALSE
;
414 /* Loop all descriptors */
415 CardDescriptor
= &PciRegistryInfo
->CardList
[0];
416 for (i
= 0; i
< ElementCount
; i
++, CardDescriptor
++)
418 /* Check for flag match */
419 if (CardDescriptor
->Flags
!= Flags
) continue;
421 /* Check for VID-PID match */
422 if ((CardDescriptor
->VendorID
!= PciData
->VendorID
) ||
423 (CardDescriptor
->DeviceID
!= PciData
->DeviceID
))
429 /* Check for revision match, if requested */
430 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_REVISION_ID
) &&
431 (CardDescriptor
->RevisionID
!= PciData
->RevisionID
))
437 /* Check what kind of device this is */
438 switch (PCI_CONFIGURATION_TYPE(PciData
))
441 case PCI_CARDBUS_BRIDGE_TYPE
:
443 /* This means the real device header is in the device-specific data */
444 PciData
= (PPCI_COMMON_CONFIG
)PciData
->DeviceSpecific
;
446 /* Normal PCI device */
447 case PCI_DEVICE_TYPE
:
449 /* Check for subvendor match, if requested */
450 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBVENDOR_ID
) &&
451 (CardDescriptor
->SubsystemVendorID
!= PciData
->u
.type0
.SubVendorID
))
457 /* Check for subsystem match, if requested */
458 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBSYSTEM_ID
) &&
459 (CardDescriptor
->SubsystemID
!= PciData
->u
.type0
.SubSystemID
))
468 /* PCI Bridge -- don't bother */
469 case PCI_BRIDGE_TYPE
:
477 /* This means the card isn't recognized */
484 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData
)
486 /* Simple test first */
487 if ((PciData
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
488 (PciData
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
))
490 /* The device is nice enough to admit it */
494 /* Symphony 82C101 */
495 if (PciData
->VendorID
== 0x1C1C) return TRUE
;
497 /* ALi MS4803 or M5219 */
498 if ((PciData
->VendorID
== 0x10B9) &&
499 ((PciData
->DeviceID
== 0x5215) || (PciData
->DeviceID
== 0x5219)))
504 /* Appian Technology */
505 if ((PciData
->VendorID
== 0x1097) && (PciData
->DeviceID
== 0x38)) return TRUE
;
507 /* Compaq Triflex Dual EIDE Controller */
508 if ((PciData
->VendorID
== 0xE11) && (PciData
->DeviceID
== 0xAE33)) return TRUE
;
510 /* Micron PC Tech RZ1000 */
511 if ((PciData
->VendorID
== 0x1042) && (PciData
->DeviceID
== 0x1000)) return TRUE
;
513 /* SiS 85C601 or 5513 [IDE] */
514 if ((PciData
->VendorID
== 0x1039) &&
515 ((PciData
->DeviceID
== 0x601) || (PciData
->DeviceID
== 0x5513)))
520 /* Symphony Labs W83769F */
521 if ((PciData
->VendorID
== 0x10AD) &&
522 ((PciData
->DeviceID
== 0x1) || (PciData
->DeviceID
== 0x150)))
528 if ((PciData
->VendorID
== 0x1060) && (PciData
->DeviceID
== 0x101)) return TRUE
;
530 /* You've survived */
537 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData
)
539 /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
540 return (((PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
) &&
541 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
542 (PciData
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
)) ||
543 ((PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
) &&
544 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
545 (PciData
->SubClass
== PCI_SUBCLASS_BR_CARDBUS
)));
551 HalpGetPciBridgeConfig(IN ULONG PciType
,
554 PCI_SLOT_NUMBER PciSlot
;
556 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
557 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
558 PBUS_HANDLER BusHandler
;
561 PciSlot
.u
.bits
.Reserved
= 0;
562 for (i
= 0; i
< *BusCount
; i
++)
564 /* Get the bus handler */
565 BusHandler
= HalHandlerForBus(PCIBus
, i
);
567 /* Loop every device */
568 for (j
= 0; j
< PCI_MAX_DEVICES
; j
++)
570 /* Loop every function */
571 PciSlot
.u
.bits
.DeviceNumber
= j
;
572 for (k
= 0; k
< PCI_MAX_FUNCTION
; k
++)
574 /* Build the final slot structure */
575 PciSlot
.u
.bits
.FunctionNumber
= k
;
577 /* Read the configuration information */
578 HalpReadPCIConfig(BusHandler
,
582 PCI_COMMON_HDR_LENGTH
);
584 /* Skip if this is an invalid function */
585 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
587 /* Make sure that this is a PCI bridge or a cardbus bridge */
588 if (!HalpIsBridgeDevice(PciData
)) continue;
591 if (!WarningsGiven
[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
597 /* If we exited the loop, then there's no bridge to worry about */
604 HalpFixupPciSupportedRanges(IN ULONG BusCount
)
607 PBUS_HANDLER Bus
, ParentBus
;
610 for (i
= 0; i
< BusCount
; i
++)
612 /* Get PCI bus handler */
613 Bus
= HalHandlerForBus(PCIBus
, i
);
615 /* Loop all parent buses */
616 ParentBus
= Bus
->ParentHandler
;
619 /* Should merge addresses */
620 if (!WarningsGiven
[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
622 /* Check the next parent */
623 ParentBus
= ParentBus
->ParentHandler
;
627 /* Loop all buses again */
628 for (i
= 0; i
< BusCount
; i
++)
630 /* Get PCI bus handler */
631 Bus
= HalHandlerForBus(PCIBus
, i
);
633 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
634 if (!((PPCIPBUSDATA
)Bus
->BusData
)->Subtractive
)
636 /* Loop all parent buses */
637 ParentBus
= Bus
->ParentHandler
;
640 /* But check only PCI parent buses specifically */
641 if (ParentBus
->InterfaceType
== PCIBus
)
643 /* Should trim addresses */
644 if (!WarningsGiven
[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
647 /* Check the next parent */
648 ParentBus
= ParentBus
->ParentHandler
;
653 /* Loop buses one last time */
654 for (i
= 0; i
< BusCount
; i
++)
656 /* Get the PCI bus handler */
657 Bus
= HalHandlerForBus(PCIBus
, i
);
659 /* Sort and combine (trim) bus address range information */
660 DPRINT("Warning: Bus addresses not being optimized!\n");
673 DbgPrint("%d", (int) x
);
675 else if (x
< 1048576)
677 DbgPrint("%dK", (int)(x
/ 1024));
679 else if (x
< 0x80000000)
681 DbgPrint("%dM", (int)(x
/ 1048576));
693 HalpDebugPciDumpBus(IN ULONG i
,
696 IN PPCI_COMMON_CONFIG PciData
)
698 extern CHAR ClassTable
[3922];
699 extern CHAR VendorTable
[642355];
700 PCHAR p
, ClassName
, SubClassName
, VendorName
, ProductName
, SubVendorName
;
702 CHAR LookupString
[16] = "";
703 CHAR bSubClassName
[32] = "";
704 CHAR bVendorName
[32] = "";
705 CHAR bProductName
[32] = "Unknown device";
706 CHAR bSubVendorName
[32] = "Unknown";
709 /* Isolate the class name */
710 sprintf(LookupString
, "C %02x", PciData
->BaseClass
);
711 ClassName
= strstr(ClassTable
, LookupString
);
714 /* Isolate the subclass name */
716 sprintf(LookupString
, "\t%02x", PciData
->SubClass
);
717 SubClassName
= strstr(ClassName
, LookupString
);
720 /* Copy the subclass into our buffer */
722 p
= strchr(SubClassName
, '\r');
723 Length
= p
- SubClassName
;
724 if (Length
> sizeof(bSubClassName
)) Length
= sizeof(bSubClassName
);
725 strncpy(bSubClassName
, SubClassName
, Length
);
726 bSubClassName
[Length
] = '\0';
730 /* Isolate the vendor name */
731 sprintf(LookupString
, "\n%04x ", PciData
->VendorID
);
732 VendorName
= strstr(VendorTable
, LookupString
);
735 /* Copy the vendor name into our buffer */
737 p
= strchr(VendorName
, '\r');
738 Length
= p
- VendorName
;
739 if (Length
> sizeof(bVendorName
)) Length
= sizeof(bVendorName
);
740 strncpy(bVendorName
, VendorName
, Length
);
741 bVendorName
[Length
] = '\0';
743 /* Isolate the product name */
744 sprintf(LookupString
, "\t%04x", PciData
->DeviceID
);
745 ProductName
= strstr(VendorName
, LookupString
);
748 /* Copy the product name into our buffer */
750 p
= strchr(ProductName
, '\r');
751 Length
= p
- ProductName
;
752 if (Length
> sizeof(bProductName
)) Length
= sizeof(bProductName
);
753 strncpy(bProductName
, ProductName
, Length
);
754 bProductName
[Length
] = '\0';
756 /* Isolate the subvendor and subsystem name */
757 sprintf(LookupString
,
759 PciData
->u
.type0
.SubVendorID
,
760 PciData
->u
.type0
.SubSystemID
);
761 SubVendorName
= strstr(ProductName
, LookupString
);
764 /* Copy the subvendor name into our buffer */
766 p
= strchr(SubVendorName
, '\r');
767 Length
= p
- SubVendorName
;
768 if (Length
> sizeof(bSubVendorName
)) Length
= sizeof(bSubVendorName
);
769 strncpy(bSubVendorName
, SubVendorName
, Length
);
770 bSubVendorName
[Length
] = '\0';
775 /* Print out the data */
776 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
777 "\tSubsystem: %s [%04x:%04x]\n",
790 PciData
->u
.type0
.SubVendorID
,
791 PciData
->u
.type0
.SubSystemID
);
793 /* Print out and decode flags */
794 DbgPrint("\tFlags:");
795 if (PciData
->Command
& PCI_ENABLE_BUS_MASTER
) DbgPrint(" bus master,");
796 if (PciData
->Status
& PCI_STATUS_66MHZ_CAPABLE
) DbgPrint(" 66MHz,");
797 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x200) DbgPrint(" medium devsel,");
798 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x400) DbgPrint(" fast devsel,");
799 DbgPrint(" latency %d", PciData
->LatencyTimer
);
800 if (PciData
->u
.type0
.InterruptPin
!= 0 &&
801 PciData
->u
.type0
.InterruptLine
!= 0 &&
802 PciData
->u
.type0
.InterruptLine
!= 0xFF) DbgPrint(", IRQ %02d", PciData
->u
.type0
.InterruptLine
);
807 for (b
= 0; b
< PCI_TYPE0_ADDRESSES
; b
++)
809 /* Check for a BAR */
810 Mem
= PciData
->u
.type0
.BaseAddresses
[b
];
813 /* Decode the address type */
814 if (Mem
& PCI_ADDRESS_IO_SPACE
)
816 /* Decode the size */
818 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
821 DbgPrint("\tI/O ports at %04lx", Mem
& PCI_ADDRESS_IO_ADDRESS_MASK
);
826 /* Decode the size */
828 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
831 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
832 Mem
& PCI_ADDRESS_MEMORY_ADDRESS_MASK
,
833 (Mem
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_32BIT
? 32 : 64,
834 (Mem
& PCI_ADDRESS_MEMORY_PREFETCHABLE
) ? "" : "non-");
845 HalpInitializePciBus(VOID
)
848 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
850 PCI_SLOT_NUMBER PciSlot
;
852 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
853 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
854 PBUS_HANDLER BusHandler
;
856 BOOLEAN ExtendedAddressDecoding
= FALSE
;
859 /* Query registry information */
860 PciRegistryInfo
= HalpQueryPciRegistryInfo();
861 if (!PciRegistryInfo
) return;
863 /* Initialize the PCI configuration lock */
864 KeInitializeSpinLock(&HalpPCIConfigLock
);
866 /* Get the type and free the info structure */
867 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
869 /* Check if this is a type 2 PCI bus with at least one bus */
870 if ((PciRegistryInfo
->NoBuses
) && (PciType
== 2))
872 /* Setup the PCI slot */
873 PciSlot
.u
.bits
.Reserved
= 0;
874 PciSlot
.u
.bits
.FunctionNumber
= 0;
877 for (i
= 0; i
< 32; i
++)
879 /* Try to setup a Type 2 PCI slot */
881 BusHandler
= HalpAllocateAndInitPciBusHandler(2, 0, TRUE
);
882 if (!BusHandler
) break;
884 /* Now check if it's valid */
885 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
887 /* Heh, the BIOS lied... try Type 1 */
889 BusHandler
= HalpAllocateAndInitPciBusHandler(1, 0, TRUE
);
890 if (!BusHandler
) break;
892 /* Now check if it's valid */
893 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
899 /* Now allocate the correct kind of handler */
900 HalpAllocateAndInitPciBusHandler(PciType
, 0, FALSE
);
903 /* Okay, now loop all PCI bridges */
906 /* Loop all PCI buses */
907 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
909 /* Check if we have a handler for it */
910 if (!HalHandlerForBus(PCIBus
, i
))
913 HalpAllocateAndInitPciBusHandler(PciType
, i
, FALSE
);
916 /* Go to the next bridge */
917 } while (HalpGetPciBridgeConfig(PciType
, &PciRegistryInfo
->NoBuses
));
919 /* Now build correct address range informaiton */
920 HalpFixupPciSupportedRanges(PciRegistryInfo
->NoBuses
);
923 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
924 PciSlot
.u
.bits
.Reserved
= 0;
925 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
927 /* Get the bus handler */
928 BusHandler
= HalHandlerForBus(PCIBus
, i
);
930 /* Loop every device */
931 for (j
= 0; j
< 32; j
++)
933 /* Loop every function */
934 PciSlot
.u
.bits
.DeviceNumber
= j
;
935 for (k
= 0; k
< 8; k
++)
937 /* Build the final slot structure */
938 PciSlot
.u
.bits
.FunctionNumber
= k
;
940 /* Read the configuration information */
941 HalpReadPCIConfig(BusHandler
,
945 PCI_COMMON_HDR_LENGTH
);
947 /* Skip if this is an invalid function */
948 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
950 /* Print out the entry */
951 HalpDebugPciDumpBus(i
, j
, k
, PciData
);
953 /* Check if this is a Cardbus bridge */
954 if (PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
)
957 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
961 /* Check if this is a PCI device */
962 if (PCI_CONFIGURATION_TYPE(PciData
) != PCI_BRIDGE_TYPE
)
964 /* Check if it has an interrupt pin and line registered */
965 if ((PciData
->u
.type1
.InterruptPin
) &&
966 (PciData
->u
.type1
.InterruptLine
))
968 /* Check if this interrupt line is connected to the bus */
969 if (PciData
->u
.type1
.InterruptLine
< 16)
971 /* Is this an IDE device? */
972 if (!HalpIsIdeDevice(PciData
))
974 /* We'll mask out this interrupt then */
975 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
976 PciData
->u
.type1
.InterruptLine
);
977 HalpPciIrqMask
|= (1 << PciData
->u
.type1
.InterruptLine
);
983 /* Check for broken Intel chips */
984 if (PciData
->VendorID
== 0x8086)
986 /* Check for broken 82830 PCI controller */
987 if ((PciData
->DeviceID
== 0x04A3) &&
988 (PciData
->RevisionID
< 0x11))
991 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
995 /* Check for broken 82378 PCI-to-ISA Bridge */
996 if ((PciData
->DeviceID
== 0x0484) &&
997 (PciData
->RevisionID
<= 3))
1000 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
1004 /* Check for broken 82450 PCI Bridge */
1005 if ((PciData
->DeviceID
== 0x84C4) &&
1006 (PciData
->RevisionID
<= 4))
1008 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
1013 /* Do we know this card? */
1014 if (!ExtendedAddressDecoding
)
1017 if (HalpIsRecognizedCard(PciRegistryInfo
,
1019 HALP_CARD_FEATURE_FULL_DECODE
))
1021 /* We'll do chipset checks later */
1022 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1023 ExtendedAddressDecoding
= TRUE
;
1027 /* Check if this is a USB controller */
1028 if ((PciData
->BaseClass
== PCI_CLASS_SERIAL_BUS_CTLR
) &&
1029 (PciData
->SubClass
== PCI_SUBCLASS_SB_USB
))
1031 /* Check if this is an OHCI controller */
1032 if (PciData
->ProgIf
== 0x10)
1034 DbgPrint("\tDevice is an OHCI (USB) PCI Expansion Card. Turn off Legacy USB in your BIOS!\n\n");
1038 /* Check for Intel UHCI controller */
1039 if (PciData
->VendorID
== 0x8086)
1041 DbgPrint("\tDevice is an Intel UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
1045 /* Check for VIA UHCI controller */
1046 if (PciData
->VendorID
== 0x1106)
1048 DbgPrint("\tDevice is a VIA UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
1053 /* Now check the registry for chipset hacks */
1054 Status
= HalpGetChipHacks(PciData
->VendorID
,
1056 PciData
->RevisionID
,
1058 if (NT_SUCCESS(Status
))
1060 /* Check for broken ACPI routing */
1061 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING
)
1063 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1067 /* Check for broken ACPI timer */
1068 if (HackFlags
& HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER
)
1070 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1074 /* Check for hibernate-disable */
1075 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE
)
1077 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1081 /* Check for USB controllers that generate SMIs */
1082 if (HackFlags
& HAL_PCI_CHIP_HACK_USB_SMI_DISABLE
)
1084 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1089 /* Terminate the entry */
1095 /* Initialize NMI Crash Flag */
1096 HalpGetNMICrashFlag();
1098 /* Free the registry data */
1099 ExFreePool(PciRegistryInfo
);
1101 /* Tell PnP if this hard supports correct decoding */
1102 HalpMarkChipsetDecode(ExtendedAddressDecoding
);
1103 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1110 HalpInitBusHandlers(VOID
)
1112 /* Register the HAL Bus Handler support */
1113 HalpRegisterInternalBusHandlers();
1119 HalpRegisterKdSupportFunctions(VOID
)
1121 /* Register PCI Device Functions */
1122 KdSetupPciDeviceForDebugging
= HalpSetupPciDeviceForDebugging
;
1123 KdReleasePciDeviceforDebugging
= HalpReleasePciDeviceForDebugging
;
1125 /* Register memory functions */
1127 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64
;
1128 KdUnmapVirtualAddress
= HalpUnmapVirtualAddress
;
1131 /* Register ACPI stub */
1132 KdCheckPowerButton
= HalpCheckPowerButton
;
1137 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1138 IN PUNICODE_STRING DriverClassName
,
1139 IN PDRIVER_OBJECT DriverObject
,
1140 IN PDEVICE_OBJECT DeviceObject
,
1141 IN INTERFACE_TYPE BusType
,
1143 IN ULONG SlotNumber
,
1144 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1146 PBUS_HANDLER Handler
;
1149 DPRINT1("Slot assignment for %d on bus %d\n", BusType
, BusNumber
);
1151 /* Find the handler */
1152 Handler
= HalReferenceHandlerForBus(BusType
, BusNumber
);
1153 if (!Handler
) return STATUS_NOT_FOUND
;
1155 /* Do the assignment */
1156 Status
= Handler
->AssignSlotResources(Handler
,
1163 AllocatedResources
);
1165 /* Dereference the handler and return */
1166 HalDereferenceBusHandler(Handler
);
1172 HaliFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress
,
1173 IN OUT PULONG AddressSpace
,
1174 OUT PPHYSICAL_ADDRESS TranslatedAddress
,
1175 IN OUT PULONG_PTR Context
,
1178 PHAL_BUS_HANDLER BusHandler
;
1179 PBUS_HANDLER Handler
;
1180 PLIST_ENTRY NextEntry
;
1183 /* Make sure we have a context */
1184 if (!Context
) return FALSE
;
1185 ASSERT((*Context
) || (NextBus
== TRUE
));
1187 /* Read the context */
1188 ContextValue
= *Context
;
1190 /* Find the bus handler */
1191 Handler
= HalpContextToBusHandler(ContextValue
);
1192 if (!Handler
) return FALSE
;
1194 /* Check if this is an ongoing lookup */
1197 /* Get the HAL bus handler */
1198 BusHandler
= CONTAINING_RECORD(Handler
, HAL_BUS_HANDLER
, Handler
);
1199 NextEntry
= &BusHandler
->AllHandlers
;
1201 /* Get the next one if we were already with one */
1202 if (ContextValue
) NextEntry
= NextEntry
->Flink
;
1204 /* Start scanning */
1207 /* Check if this is the last one */
1208 if (NextEntry
== &HalpAllBusHandlers
)
1215 /* Call this translator */
1216 BusHandler
= CONTAINING_RECORD(NextEntry
, HAL_BUS_HANDLER
, AllHandlers
);
1217 if (HalTranslateBusAddress(BusHandler
->Handler
.InterfaceType
,
1218 BusHandler
->Handler
.BusNumber
,
1221 TranslatedAddress
)) break;
1223 /* Try the next one */
1224 NextEntry
= NextEntry
->Flink
;
1227 /* If we made it, we're done */
1228 *Context
= (ULONG_PTR
)Handler
;
1232 /* Try the first one through */
1233 if (!HalTranslateBusAddress(Handler
->InterfaceType
,
1237 TranslatedAddress
)) return FALSE
;
1239 /* Remember for next time */
1240 *Context
= (ULONG_PTR
)Handler
;
1246 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1248 IN PHYSICAL_ADDRESS BusAddress
,
1249 IN OUT PULONG AddressSpace
,
1250 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1252 PBUS_HANDLER Handler
;
1255 /* Find the handler */
1256 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1257 if (!(Handler
) || !(Handler
->TranslateBusAddress
))
1259 DPRINT1("No translator!\n");
1263 /* Do the assignment */
1264 Status
= Handler
->TranslateBusAddress(Handler
,
1270 /* Dereference the handler and return */
1271 HalDereferenceBusHandler(Handler
);
1275 /* PUBLIC FUNCTIONS **********************************************************/
1282 HalAdjustResourceList(IN PIO_RESOURCE_REQUIREMENTS_LIST
*ResourceList
)
1284 PBUS_HANDLER Handler
;
1288 /* Find the handler */
1289 Handler
= HalReferenceHandlerForBus((*ResourceList
)->InterfaceType
,
1290 (*ResourceList
)->BusNumber
);
1291 if (!Handler
) return STATUS_SUCCESS
;
1293 /* Do the assignment */
1294 Status
= Handler
->AdjustResourceList(Handler
,
1298 /* Dereference the handler and return */
1299 HalDereferenceBusHandler(Handler
);
1308 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1309 IN PUNICODE_STRING DriverClassName
,
1310 IN PDRIVER_OBJECT DriverObject
,
1311 IN PDEVICE_OBJECT DeviceObject
,
1312 IN INTERFACE_TYPE BusType
,
1314 IN ULONG SlotNumber
,
1315 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1319 /* Check the bus type */
1320 if (BusType
!= PCIBus
)
1322 /* Call our internal handler */
1323 return HalpAssignSlotResources(RegistryPath
,
1330 AllocatedResources
);
1334 /* Call the PCI registered function */
1335 return HalPciAssignSlotResources(RegistryPath
,
1342 AllocatedResources
);
1351 HalGetBusData(IN BUS_DATA_TYPE BusDataType
,
1353 IN ULONG SlotNumber
,
1357 /* Call the extended function */
1358 return HalGetBusDataByOffset(BusDataType
,
1371 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1373 IN ULONG SlotNumber
,
1378 PBUS_HANDLER Handler
;
1381 /* Find the handler */
1382 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1383 if (!Handler
) return 0;
1385 /* Do the assignment */
1386 Status
= Handler
->GetBusData(Handler
,
1393 /* Dereference the handler and return */
1394 HalDereferenceBusHandler(Handler
);
1403 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType
,
1405 IN ULONG BusInterruptLevel
,
1406 IN ULONG BusInterruptVector
,
1408 OUT PKAFFINITY Affinity
)
1410 PBUS_HANDLER Handler
;
1418 /* Find the handler */
1419 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1420 if (!Handler
) return 0;
1422 /* Do the assignment */
1423 Vector
= Handler
->GetInterruptVector(Handler
,
1429 if ((Vector
!= IRQ2VECTOR(BusInterruptLevel
)) ||
1430 (*Irql
!= VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
))))
1432 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1433 *Irql
, Vector
, BusInterruptLevel
, BusInterruptVector
);
1434 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1435 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
)),
1436 IRQ2VECTOR(BusInterruptLevel
));
1439 /* Dereference the handler and return */
1440 HalDereferenceBusHandler(Handler
);
1449 HalSetBusData(IN BUS_DATA_TYPE BusDataType
,
1451 IN ULONG SlotNumber
,
1455 /* Call the extended function */
1456 return HalSetBusDataByOffset(BusDataType
,
1469 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1471 IN ULONG SlotNumber
,
1476 PBUS_HANDLER Handler
;
1479 /* Find the handler */
1480 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1481 if (!Handler
) return 0;
1483 /* Do the assignment */
1484 Status
= Handler
->SetBusData(Handler
,
1491 /* Dereference the handler and return */
1492 HalDereferenceBusHandler(Handler
);
1501 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1503 IN PHYSICAL_ADDRESS BusAddress
,
1504 IN OUT PULONG AddressSpace
,
1505 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1507 /* Look as the bus type */
1508 if (InterfaceType
== PCIBus
)
1510 /* Call the PCI registered function */
1511 return HalPciTranslateBusAddress(PCIBus
,
1519 /* Call the bus handler */
1520 return HaliTranslateBusAddress(InterfaceType
,