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 */
68 HalpRegisterInternalBusHandlers(VOID
)
72 /* Only do processor 1 */
73 if (KeGetCurrentPrcb()->Number
) return;
75 /* Register root support */
78 /* Allocate the system bus */
79 Bus
= HalpAllocateBusHandler(Internal
,
80 ConfigurationSpaceUndefined
,
82 InterfaceTypeUndefined
,
88 Bus
->GetInterruptVector
= HalpGetSystemInterruptVector
;
89 Bus
->TranslateBusAddress
= HalpTranslateSystemBusAddress
;
92 /* Allocate the CMOS bus */
93 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
96 InterfaceTypeUndefined
,
102 Bus
->GetBusData
= HalpcGetCmosData
;
103 Bus
->SetBusData
= HalpcSetCmosData
;
106 /* Allocate the CMOS bus */
107 Bus
= HalpAllocateBusHandler(InterfaceTypeUndefined
,
110 InterfaceTypeUndefined
,
116 Bus
->GetBusData
= HalpcGetCmosData
;
117 Bus
->SetBusData
= HalpcSetCmosData
;
120 /* Allocate ISA bus */
121 Bus
= HalpAllocateBusHandler(Isa
,
122 ConfigurationSpaceUndefined
,
130 Bus
->GetBusData
= HalpNoBusData
;
131 Bus
->BusAddresses
->Memory
.Limit
= 0xFFFFFF;
132 Bus
->TranslateBusAddress
= HalpTranslateIsaBusAddress
;
135 /* No support for EISA or MCA */
136 ASSERT(HalpBusType
== MACHINE_TYPE_ISA
);
142 HalpMarkChipsetDecode(BOOLEAN OverrideEnable
)
145 UNICODE_STRING KeyString
;
146 ULONG Data
= OverrideEnable
;
147 HANDLE KeyHandle
, Handle
;
150 RtlInitUnicodeString(&KeyString
,
151 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET");
152 Status
= HalpOpenRegistryKey(&Handle
, 0, &KeyString
, KEY_ALL_ACCESS
, FALSE
);
153 if (NT_SUCCESS(Status
))
155 /* Open PNP Bios key */
156 RtlInitUnicodeString(&KeyString
, L
"Control\\Biosinfo\\PNPBios");
157 Status
= HalpOpenRegistryKey(&KeyHandle
,
166 /* Check if PNP BIOS key exists */
167 if (NT_SUCCESS(Status
))
169 /* Set the override value */
170 RtlInitUnicodeString(&KeyString
, L
"FullDecodeChipsetOverride");
171 Status
= ZwSetValueKey(KeyHandle
,
189 HalpAllocateAndInitPciBusHandler(IN ULONG PciType
,
191 IN BOOLEAN TestAllocation
)
194 PPCIPBUSDATA BusData
;
196 /* Allocate the bus handler */
197 Bus
= HalpAllocateBusHandler(PCIBus
,
202 sizeof(PCIPBUSDATA
));
205 Bus
->GetBusData
= (PGETSETBUSDATA
)HalpGetPCIData
;
206 Bus
->SetBusData
= (PGETSETBUSDATA
)HalpSetPCIData
;
207 Bus
->GetInterruptVector
= (PGETINTERRUPTVECTOR
)HalpGetPCIIntOnISABus
;
208 Bus
->AdjustResourceList
= (PADJUSTRESOURCELIST
)HalpAdjustPCIResourceList
;
209 Bus
->AssignSlotResources
= (PASSIGNSLOTRESOURCES
)HalpAssignPCISlotResources
;
210 Bus
->BusAddresses
->Dma
.Limit
= 0;
212 /* Get our custom bus data */
213 BusData
= (PPCIPBUSDATA
)Bus
->BusData
;
215 /* Setup custom bus data */
216 BusData
->CommonData
.Tag
= PCI_DATA_TAG
;
217 BusData
->CommonData
.Version
= PCI_DATA_VERSION
;
218 BusData
->CommonData
.ReadConfig
= (PciReadWriteConfig
)HalpReadPCIConfig
;
219 BusData
->CommonData
.WriteConfig
= (PciReadWriteConfig
)HalpWritePCIConfig
;
220 BusData
->CommonData
.Pin2Line
= (PciPin2Line
)HalpPCIPin2ISALine
;
221 BusData
->CommonData
.Line2Pin
= (PciLine2Pin
)HalpPCIISALine2Pin
;
222 BusData
->MaxDevice
= PCI_MAX_DEVICES
;
223 BusData
->GetIrqRange
= (PciIrqRange
)HalpGetISAFixedPCIIrq
;
225 /* Initialize the bitmap */
226 RtlInitializeBitMap(&BusData
->DeviceConfigured
, BusData
->ConfiguredBits
, 256);
228 /* Check the type of PCI bus */
234 /* Copy the Type 1 handler data */
235 RtlCopyMemory(&PCIConfigHandler
,
236 &PCIConfigHandlerType1
,
237 sizeof(PCIConfigHandler
));
239 /* Set correct I/O Ports */
240 BusData
->Config
.Type1
.Address
= PCI_TYPE1_ADDRESS_PORT
;
241 BusData
->Config
.Type1
.Data
= PCI_TYPE1_DATA_PORT
;
247 /* Copy the Type 1 handler data */
248 RtlCopyMemory(&PCIConfigHandler
,
249 &PCIConfigHandlerType2
,
250 sizeof (PCIConfigHandler
));
252 /* Set correct I/O Ports */
253 BusData
->Config
.Type2
.CSE
= PCI_TYPE2_CSE_PORT
;
254 BusData
->Config
.Type2
.Forward
= PCI_TYPE2_FORWARD_PORT
;
255 BusData
->Config
.Type2
.Base
= PCI_TYPE2_ADDRESS_BASE
;
257 /* Only 16 devices supported, not 32 */
258 BusData
->MaxDevice
= 16;
264 DbgPrint("HAL: Unnkown PCI type\n");
267 /* Return the bus handler */
273 HalpIsValidPCIDevice(IN PBUS_HANDLER BusHandler
,
274 IN PCI_SLOT_NUMBER Slot
)
276 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
277 PPCI_COMMON_CONFIG PciHeader
= (PVOID
)DataBuffer
;
281 /* Read the PCI header */
282 HalpReadPCIConfig(BusHandler
, Slot
, PciHeader
, 0, PCI_COMMON_HDR_LENGTH
);
284 /* Make sure it's a valid device */
285 if ((PciHeader
->VendorID
== PCI_INVALID_VENDORID
) ||
286 (PCI_CONFIGURATION_TYPE(PciHeader
) != PCI_DEVICE_TYPE
))
292 /* Make sure interrupt numbers make sense */
293 if (((PciHeader
->u
.type0
.InterruptPin
) &&
294 (PciHeader
->u
.type0
.InterruptPin
> 4)) ||
295 (PciHeader
->u
.type0
.InterruptLine
& 0x70))
301 /* Now scan PCI BARs */
302 for (i
= 0; i
< PCI_TYPE0_ADDRESSES
; i
++)
304 /* Check what kind of address it is */
305 Address
= PciHeader
->u
.type0
.BaseAddresses
[i
];
306 if (Address
& PCI_ADDRESS_IO_SPACE
)
308 /* Highest I/O port is 65535 */
309 if (Address
> 0xFFFF) return FALSE
;
313 /* MMIO should be higher than 0x80000 */
314 if ((Address
> 0xF) && (Address
< 0x80000)) return FALSE
;
317 /* Is this a 64-bit address? */
318 if (!(Address
& PCI_ADDRESS_IO_SPACE
) &&
319 ((Address
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_64BIT
))
321 /* Check the next-next entry, since this one 64-bits wide */
326 /* Header, interrupt and address data all make sense */
330 static BOOLEAN WarningsGiven
[5];
334 HalpGetChipHacks(IN USHORT VendorId
,
339 UNICODE_STRING KeyName
, ValueName
;
341 OBJECT_ATTRIBUTES ObjectAttributes
;
344 KEY_VALUE_PARTIAL_INFORMATION PartialInfo
;
347 /* Setup the object attributes for the key */
348 RtlInitUnicodeString(&KeyName
,
349 L
"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\"
351 InitializeObjectAttributes(&ObjectAttributes
,
353 OBJ_CASE_INSENSITIVE
,
358 Status
= ZwOpenKey(&KeyHandle
, KEY_READ
, &ObjectAttributes
);
359 if (!NT_SUCCESS(Status
)) return Status
;
362 swprintf(Buffer
, L
"%04X%04X", VendorId
, DeviceId
);
363 RtlInitUnicodeString(&ValueName
, Buffer
);
364 Status
= ZwQueryValueKey(KeyHandle
,
366 KeyValuePartialInformation
,
370 if (NT_SUCCESS(Status
))
372 /* Return the flags */
373 DbgPrint("\tFound HackFlags for your chipset\n");
374 *HackFlags
= *(PULONG
)PartialInfo
.Data
;
375 DbgPrint("\t\tHack Flags: %lx (Hack Revision: %lx-Your Revision: %lx)\n",
376 *HackFlags
, HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
), RevisionId
);
378 /* Does it apply to this revision? */
379 if ((RevisionId
) && (RevisionId
>= (HALP_REVISION_FROM_HACK_FLAGS(*HackFlags
))))
381 /* Read the revision flags */
382 *HackFlags
= HALP_REVISION_HACK_FLAGS(*HackFlags
);
385 /* Throw out revision data */
386 *HackFlags
= HALP_HACK_FLAGS(*HackFlags
);
387 if (!*HackFlags
) DbgPrint("\tNo HackFlags for your chipset's revision!\n");
390 /* Close the handle and return */
397 HalpIsRecognizedCard(IN PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
,
398 IN PPCI_COMMON_CONFIG PciData
,
401 ULONG ElementCount
, i
;
402 PPCI_CARD_DESCRIPTOR CardDescriptor
;
404 /* How many PCI Cards that we know about? */
405 ElementCount
= PciRegistryInfo
->ElementCount
;
406 if (!ElementCount
) return FALSE
;
408 /* Loop all descriptors */
409 CardDescriptor
= &PciRegistryInfo
->CardList
[0];
410 for (i
= 0; i
< ElementCount
; i
++, CardDescriptor
++)
412 /* Check for flag match */
413 if (CardDescriptor
->Flags
!= Flags
) continue;
415 /* Check for VID-PID match */
416 if ((CardDescriptor
->VendorID
!= PciData
->VendorID
) ||
417 (CardDescriptor
->DeviceID
!= PciData
->DeviceID
))
423 /* Check for revision match, if requested */
424 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_REVISION_ID
) &&
425 (CardDescriptor
->RevisionID
!= PciData
->RevisionID
))
431 /* Check what kind of device this is */
432 switch (PCI_CONFIGURATION_TYPE(PciData
))
435 case PCI_CARDBUS_BRIDGE_TYPE
:
437 /* This means the real device header is in the device-specific data */
438 PciData
= (PPCI_COMMON_CONFIG
)PciData
->DeviceSpecific
;
440 /* Normal PCI device */
441 case PCI_DEVICE_TYPE
:
443 /* Check for subvendor match, if requested */
444 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBVENDOR_ID
) &&
445 (CardDescriptor
->SubsystemVendorID
!= PciData
->u
.type0
.SubVendorID
))
451 /* Check for subsystem match, if requested */
452 if ((CardDescriptor
->Flags
& HALP_CHECK_CARD_SUBSYSTEM_ID
) &&
453 (CardDescriptor
->SubsystemID
!= PciData
->u
.type0
.SubSystemID
))
462 /* PCI Bridge -- don't bother */
463 case PCI_BRIDGE_TYPE
:
471 /* This means the card isn't recognized */
477 HalpIsIdeDevice(IN PPCI_COMMON_CONFIG PciData
)
479 /* Simple test first */
480 if ((PciData
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
481 (PciData
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
))
483 /* The device is nice enough to admit it */
487 /* Symphony 82C101 */
488 if (PciData
->VendorID
== 0x1C1C) return TRUE
;
490 /* ALi MS4803 or M5219 */
491 if ((PciData
->VendorID
== 0x10B9) &&
492 ((PciData
->DeviceID
== 0x5215) || (PciData
->DeviceID
== 0x5219)))
497 /* Appian Technology */
498 if ((PciData
->VendorID
== 0x1097) && (PciData
->DeviceID
== 0x38)) return TRUE
;
500 /* Compaq Triflex Dual EIDE Controller */
501 if ((PciData
->VendorID
== 0xE11) && (PciData
->DeviceID
== 0xAE33)) return TRUE
;
503 /* Micron PC Tech RZ1000 */
504 if ((PciData
->VendorID
== 0x1042) && (PciData
->DeviceID
== 0x1000)) return TRUE
;
506 /* SiS 85C601 or 5513 [IDE] */
507 if ((PciData
->VendorID
== 0x1039) &&
508 ((PciData
->DeviceID
== 0x601) || (PciData
->DeviceID
== 0x5513)))
513 /* Symphony Labs W83769F */
514 if ((PciData
->VendorID
== 0x10AD) &&
515 ((PciData
->DeviceID
== 0x1) || (PciData
->DeviceID
== 0x150)))
521 if ((PciData
->VendorID
== 0x1060) && (PciData
->DeviceID
== 0x101)) return TRUE
;
523 /* You've survived */
529 HalpIsBridgeDevice(IN PPCI_COMMON_CONFIG PciData
)
531 /* Either this is a PCI-to-PCI Bridge, or a CardBUS Bridge */
532 return (((PCI_CONFIGURATION_TYPE(PciData
) == PCI_BRIDGE_TYPE
) &&
533 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
534 (PciData
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
)) ||
535 ((PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
) &&
536 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
537 (PciData
->SubClass
== PCI_SUBCLASS_BR_CARDBUS
)));
542 HalpGetPciBridgeConfig(IN ULONG PciType
,
545 PCI_SLOT_NUMBER PciSlot
;
547 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
548 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
549 PBUS_HANDLER BusHandler
;
552 PciSlot
.u
.bits
.Reserved
= 0;
553 for (i
= 0; i
< *BusCount
; i
++)
555 /* Get the bus handler */
556 BusHandler
= HalHandlerForBus(PCIBus
, i
);
558 /* Loop every device */
559 for (j
= 0; j
< PCI_MAX_DEVICES
; j
++)
561 /* Loop every function */
562 PciSlot
.u
.bits
.DeviceNumber
= j
;
563 for (k
= 0; k
< PCI_MAX_FUNCTION
; k
++)
565 /* Build the final slot structure */
566 PciSlot
.u
.bits
.FunctionNumber
= k
;
568 /* Read the configuration information */
569 HalpReadPCIConfig(BusHandler
,
573 PCI_COMMON_HDR_LENGTH
);
575 /* Skip if this is an invalid function */
576 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
578 /* Make sure that this is a PCI bridge or a cardbus bridge */
579 if (!HalpIsBridgeDevice(PciData
)) continue;
582 if (!WarningsGiven
[2]++) DPRINT1("Your machine has a PCI-to-PCI or CardBUS Bridge. PCI devices may fail!\n");
588 /* If we exited the loop, then there's no bridge to worry about */
594 HalpFixupPciSupportedRanges(IN ULONG BusCount
)
597 PBUS_HANDLER Bus
, ParentBus
;
600 for (i
= 0; i
< BusCount
; i
++)
602 /* Get PCI bus handler */
603 Bus
= HalHandlerForBus(PCIBus
, i
);
605 /* Loop all parent buses */
606 ParentBus
= Bus
->ParentHandler
;
609 /* Should merge addresses */
610 if (!WarningsGiven
[0]++) DPRINT1("Found parent bus (indicating PCI Bridge). PCI devices may fail!\n");
612 /* Check the next parent */
613 ParentBus
= ParentBus
->ParentHandler
;
617 /* Loop all buses again */
618 for (i
= 0; i
< BusCount
; i
++)
620 /* Get PCI bus handler */
621 Bus
= HalHandlerForBus(PCIBus
, i
);
623 /* Check if this is a PCI 2.2 Bus with Subtractive Decode */
624 if (!((PPCIPBUSDATA
)Bus
->BusData
)->Subtractive
)
626 /* Loop all parent buses */
627 ParentBus
= Bus
->ParentHandler
;
630 /* But check only PCI parent buses specifically */
631 if (ParentBus
->InterfaceType
== PCIBus
)
633 /* Should trim addresses */
634 if (!WarningsGiven
[1]++) DPRINT1("Found parent PCI Bus (indicating PCI-to-PCI Bridge). PCI devices may fail!\n");
637 /* Check the next parent */
638 ParentBus
= ParentBus
->ParentHandler
;
643 /* Loop buses one last time */
644 for (i
= 0; i
< BusCount
; i
++)
646 /* Get the PCI bus handler */
647 Bus
= HalHandlerForBus(PCIBus
, i
);
649 /* Sort and combine (trim) bus address range information */
650 DPRINT("Warning: Bus addresses not being optimized!\n");
662 DbgPrint("%d", (int) x
);
664 else if (x
< 1048576)
666 DbgPrint("%dK", (int)(x
/ 1024));
668 else if (x
< 0x80000000)
670 DbgPrint("%dM", (int)(x
/ 1048576));
681 HalpDebugPciBus(IN ULONG i
,
684 IN PPCI_COMMON_CONFIG PciData
)
686 extern CHAR ClassTable
[3922];
687 extern CHAR VendorTable
[642355];
688 PCHAR p
, ClassName
, SubClassName
, VendorName
, ProductName
, SubVendorName
;
690 CHAR LookupString
[16] = "";
691 CHAR bSubClassName
[32] = "";
692 CHAR bVendorName
[32] = "";
693 CHAR bProductName
[32] = "Unknown device";
694 CHAR bSubVendorName
[32] = "Unknown";
697 /* Isolate the class name */
698 sprintf(LookupString
, "C %02x", PciData
->BaseClass
);
699 ClassName
= strstr(ClassTable
, LookupString
);
702 /* Isolate the subclass name */
704 sprintf(LookupString
, "\t%02x", PciData
->SubClass
);
705 SubClassName
= strstr(ClassName
, LookupString
);
708 /* Copy the subclass into our buffer */
710 p
= strchr(SubClassName
, '\r');
711 Length
= p
- SubClassName
;
712 if (Length
> sizeof(bSubClassName
)) Length
= sizeof(bSubClassName
);
713 strncpy(bSubClassName
, SubClassName
, Length
);
714 bSubClassName
[Length
] = '\0';
718 /* Isolate the vendor name */
719 sprintf(LookupString
, "\n%04x ", PciData
->VendorID
);
720 VendorName
= strstr(VendorTable
, LookupString
);
723 /* Copy the vendor name into our buffer */
725 p
= strchr(VendorName
, '\r');
726 Length
= p
- VendorName
;
727 if (Length
> sizeof(bVendorName
)) Length
= sizeof(bVendorName
);
728 strncpy(bVendorName
, VendorName
, Length
);
729 bVendorName
[Length
] = '\0';
731 /* Isolate the product name */
732 sprintf(LookupString
, "\t%04x", PciData
->DeviceID
);
733 ProductName
= strstr(VendorName
, LookupString
);
736 /* Copy the product name into our buffer */
738 p
= strchr(ProductName
, '\r');
739 Length
= p
- ProductName
;
740 if (Length
> sizeof(bProductName
)) Length
= sizeof(bProductName
);
741 strncpy(bProductName
, ProductName
, Length
);
742 bProductName
[Length
] = '\0';
744 /* Isolate the subvendor and subsystem name */
745 sprintf(LookupString
,
747 PciData
->u
.type0
.SubVendorID
,
748 PciData
->u
.type0
.SubSystemID
);
749 SubVendorName
= strstr(ProductName
, LookupString
);
752 /* Copy the subvendor name into our buffer */
754 p
= strchr(SubVendorName
, '\r');
755 Length
= p
- SubVendorName
;
756 if (Length
> sizeof(bSubVendorName
)) Length
= sizeof(bSubVendorName
);
757 strncpy(bSubVendorName
, SubVendorName
, Length
);
758 bSubVendorName
[Length
] = '\0';
763 /* Print out the data */
764 DbgPrint("%02x:%02x.%x %s [%02x%02x]: %s %s [%04x:%04x] (rev %02x)\n"
765 "\tSubsystem: %s [%04x:%04x]\n",
778 PciData
->u
.type0
.SubVendorID
,
779 PciData
->u
.type0
.SubSystemID
);
781 /* Print out and decode flags */
782 DbgPrint("\tFlags:");
783 if (PciData
->Command
& PCI_ENABLE_BUS_MASTER
) DbgPrint(" bus master,");
784 if (PciData
->Status
& PCI_STATUS_66MHZ_CAPABLE
) DbgPrint(" 66MHz,");
785 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x200) DbgPrint(" medium devsel,");
786 if ((PciData
->Status
& PCI_STATUS_DEVSEL
) == 0x400) DbgPrint(" fast devsel,");
787 DbgPrint(" latency %d", PciData
->LatencyTimer
);
788 if (PciData
->u
.type0
.InterruptLine
) DbgPrint(", IRQ %02d", PciData
->u
.type0
.InterruptLine
);
793 for (b
= 0; b
< PCI_TYPE0_ADDRESSES
; b
++)
795 /* Check for a BAR */
796 Mem
= PciData
->u
.type0
.BaseAddresses
[b
];
799 /* Decode the address type */
800 if (Mem
& PCI_ADDRESS_IO_SPACE
)
802 /* Decode the size */
804 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
807 DbgPrint("\tI/O ports at %04lx", Mem
& PCI_ADDRESS_IO_ADDRESS_MASK
);
812 /* Decode the size */
814 while (!(Mem
& Size
) && (Size
)) Size
<<= 1;
817 DbgPrint("\tMemory at %08lx (%d-bit, %sprefetchable)",
818 Mem
& PCI_ADDRESS_MEMORY_ADDRESS_MASK
,
819 (Mem
& PCI_ADDRESS_MEMORY_TYPE_MASK
) == PCI_TYPE_32BIT
? 32 : 64,
820 (Mem
& PCI_ADDRESS_MEMORY_PREFETCHABLE
) ? "" : "non-");
830 HalpInitializePciBus(VOID
)
833 PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo
;
835 PCI_SLOT_NUMBER PciSlot
;
837 UCHAR DataBuffer
[PCI_COMMON_HDR_LENGTH
];
838 PPCI_COMMON_CONFIG PciData
= (PPCI_COMMON_CONFIG
)DataBuffer
;
839 PBUS_HANDLER BusHandler
;
841 BOOLEAN ExtendedAddressDecoding
= FALSE
;
844 /* Query registry information */
845 PciRegistryInfo
= HalpQueryPciRegistryInfo();
846 if (!PciRegistryInfo
) return;
848 /* Initialize the PCI configuration lock */
849 KeInitializeSpinLock(&HalpPCIConfigLock
);
851 /* Get the type and free the info structure */
852 PciType
= PciRegistryInfo
->HardwareMechanism
& 0xF;
854 /* Check if this is a type 2 PCI bus with at least one bus */
855 if ((PciRegistryInfo
->NoBuses
) && (PciType
== 2))
857 /* Setup the PCI slot */
858 PciSlot
.u
.bits
.Reserved
= 0;
859 PciSlot
.u
.bits
.FunctionNumber
= 0;
862 for (i
= 0; i
< 32; i
++)
864 /* Try to setup a Type 2 PCI slot */
866 BusHandler
= HalpAllocateAndInitPciBusHandler(2, 0, TRUE
);
867 if (!BusHandler
) break;
869 /* Now check if it's valid */
870 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
872 /* Heh, the BIOS lied... try Type 1 */
874 BusHandler
= HalpAllocateAndInitPciBusHandler(1, 0, TRUE
);
875 if (!BusHandler
) break;
877 /* Now check if it's valid */
878 if (HalpIsValidPCIDevice(BusHandler
, PciSlot
)) break;
884 /* Now allocate the correct kind of handler */
885 HalpAllocateAndInitPciBusHandler(PciType
, 0, FALSE
);
888 /* Okay, now loop all PCI bridges */
891 /* Loop all PCI buses */
892 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
894 /* Check if we have a handler for it */
895 if (!HalHandlerForBus(PCIBus
, i
))
898 HalpAllocateAndInitPciBusHandler(PciType
, i
, FALSE
);
901 /* Go to the next bridge */
902 } while (HalpGetPciBridgeConfig(PciType
, &PciRegistryInfo
->NoBuses
));
904 /* Now build correct address range informaiton */
905 HalpFixupPciSupportedRanges(PciRegistryInfo
->NoBuses
);
908 DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n");
909 PciSlot
.u
.bits
.Reserved
= 0;
910 for (i
= 0; i
< PciRegistryInfo
->NoBuses
; i
++)
912 /* Get the bus handler */
913 BusHandler
= HalHandlerForBus(PCIBus
, i
);
915 /* Loop every device */
916 for (j
= 0; j
< 32; j
++)
918 /* Loop every function */
919 PciSlot
.u
.bits
.DeviceNumber
= j
;
920 for (k
= 0; k
< 8; k
++)
922 /* Build the final slot structure */
923 PciSlot
.u
.bits
.FunctionNumber
= k
;
925 /* Read the configuration information */
926 HalpReadPCIConfig(BusHandler
,
930 PCI_COMMON_HDR_LENGTH
);
932 /* Skip if this is an invalid function */
933 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
935 /* Print out the entry */
936 HalpDebugPciBus(i
, j
, k
, PciData
);
938 /* Check if this is a Cardbus bridge */
939 if (PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
)
942 DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n");
946 /* Check if this is a PCI device */
947 if (PCI_CONFIGURATION_TYPE(PciData
) != PCI_BRIDGE_TYPE
)
949 /* Check if it has an interrupt pin and line registered */
950 if ((PciData
->u
.type1
.InterruptPin
) &&
951 (PciData
->u
.type1
.InterruptLine
))
953 /* Check if this interrupt line is connected to the bus */
954 if (PciData
->u
.type1
.InterruptLine
< 16)
956 /* Is this an IDE device? */
957 if (!HalpIsIdeDevice(PciData
))
959 /* We'll mask out this interrupt then */
960 DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n",
961 PciData
->u
.type1
.InterruptLine
);
962 HalpPciIrqMask
|= (1 << PciData
->u
.type1
.InterruptLine
);
968 /* Check for broken Intel chips */
969 if (PciData
->VendorID
== 0x8086)
971 /* Check for broken 82830 PCI controller */
972 if ((PciData
->DeviceID
== 0x04A3) &&
973 (PciData
->RevisionID
< 0x11))
976 DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n");
980 /* Check for broken 82378 PCI-to-ISA Bridge */
981 if ((PciData
->DeviceID
== 0x0484) &&
982 (PciData
->RevisionID
<= 3))
985 DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n");
989 /* Check for broken 82450 PCI Bridge */
990 if ((PciData
->DeviceID
== 0x84C4) &&
991 (PciData
->RevisionID
<= 4))
993 DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n");
998 /* Do we know this card? */
999 if (!ExtendedAddressDecoding
)
1002 if (HalpIsRecognizedCard(PciRegistryInfo
,
1004 HALP_CARD_FEATURE_FULL_DECODE
))
1006 /* We'll do chipset checks later */
1007 DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n");
1008 ExtendedAddressDecoding
= TRUE
;
1012 /* Check if this is a USB controller */
1013 if ((PciData
->BaseClass
== PCI_CLASS_SERIAL_BUS_CTLR
) &&
1014 (PciData
->SubClass
== PCI_SUBCLASS_SB_USB
))
1016 /* Check if this is an OHCI controller */
1017 if (PciData
->ProgIf
== 0x10)
1019 DbgPrint("\tDevice is an OHCI (USB) PCI Expansion Card. Turn off Legacy USB in your BIOS!\n\n");
1023 /* Check for Intel UHCI controller */
1024 if (PciData
->VendorID
== 0x8086)
1026 DbgPrint("\tDevice is an Intel UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
1030 /* Check for VIA UHCI controller */
1031 if (PciData
->VendorID
== 0x1106)
1033 DbgPrint("\tDevice is a VIA UHCI (USB) Controller. Turn off Legacy USB in your BIOS!\n\n");
1038 /* Now check the registry for chipset hacks */
1039 Status
= HalpGetChipHacks(PciData
->VendorID
,
1041 PciData
->RevisionID
,
1043 if (NT_SUCCESS(Status
))
1045 /* Check for broken ACPI routing */
1046 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING
)
1048 DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n");
1052 /* Check for broken ACPI timer */
1053 if (HackFlags
& HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER
)
1055 DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n");
1059 /* Check for hibernate-disable */
1060 if (HackFlags
& HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE
)
1062 DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n");
1066 /* Check for USB controllers that generate SMIs */
1067 if (HackFlags
& HAL_PCI_CHIP_HACK_USB_SMI_DISABLE
)
1069 DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n");
1074 /* Terminate the entry */
1080 /* Initialize NMI Crash Flag */
1081 HalpGetNMICrashFlag();
1083 /* Free the registry data */
1084 ExFreePool(PciRegistryInfo
);
1086 /* Tell PnP if this hard supports correct decoding */
1087 HalpMarkChipsetDecode(ExtendedAddressDecoding
);
1088 DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n");
1094 HalpInitBusHandlers(VOID
)
1096 /* Register the HAL Bus Handler support */
1097 HalpRegisterInternalBusHandlers();
1102 HalpRegisterKdSupportFunctions(VOID
)
1104 /* Register PCI Device Functions */
1105 KdSetupPciDeviceForDebugging
= HalpSetupPciDeviceForDebugging
;
1106 KdReleasePciDeviceforDebugging
= HalpReleasePciDeviceForDebugging
;
1108 /* Register memory functions */
1110 KdMapPhysicalMemory64
= HalpMapPhysicalMemory64
;
1111 KdUnmapVirtualAddress
= HalpUnmapVirtualAddress
;
1114 /* Register ACPI stub */
1115 KdCheckPowerButton
= HalpCheckPowerButton
;
1120 HalpAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1121 IN PUNICODE_STRING DriverClassName
,
1122 IN PDRIVER_OBJECT DriverObject
,
1123 IN PDEVICE_OBJECT DeviceObject
,
1124 IN INTERFACE_TYPE BusType
,
1126 IN ULONG SlotNumber
,
1127 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1129 BUS_HANDLER BusHandler
;
1132 /* Only PCI is supported */
1133 if (BusType
!= PCIBus
) return STATUS_NOT_IMPLEMENTED
;
1135 /* Setup fake PCI Bus handler */
1136 RtlCopyMemory(&BusHandler
, &HalpFakePciBusHandler
, sizeof(BUS_HANDLER
));
1137 BusHandler
.BusNumber
= BusNumber
;
1139 /* Call the PCI function */
1140 return HalpAssignPCISlotResources(&BusHandler
,
1147 AllocatedResources
);
1152 HalpTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1154 IN PHYSICAL_ADDRESS BusAddress
,
1155 IN OUT PULONG AddressSpace
,
1156 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1158 /* Translation is easy */
1159 TranslatedAddress
->QuadPart
= BusAddress
.QuadPart
;
1165 HalpGetSystemInterruptVector_Acpi(IN ULONG BusNumber
,
1166 IN ULONG BusInterruptLevel
,
1167 IN ULONG BusInterruptVector
,
1169 OUT PKAFFINITY Affinity
)
1171 ULONG Vector
= IRQ2VECTOR(BusInterruptLevel
);
1172 *Irql
= (KIRQL
)VECTOR2IRQL(Vector
);
1173 *Affinity
= 0xFFFFFFFF;
1179 HalpFindBusAddressTranslation(IN PHYSICAL_ADDRESS BusAddress
,
1180 IN OUT PULONG AddressSpace
,
1181 OUT PPHYSICAL_ADDRESS TranslatedAddress
,
1182 IN OUT PULONG_PTR Context
,
1185 /* Make sure we have a context */
1186 if (!Context
) return FALSE
;
1188 /* If we have data in the context, then this shouldn't be a new lookup */
1189 if ((*Context
) && (NextBus
== TRUE
)) return FALSE
;
1191 /* Return bus data */
1192 TranslatedAddress
->QuadPart
= BusAddress
.QuadPart
;
1194 /* Set context value and return success */
1201 HaliTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1203 IN PHYSICAL_ADDRESS BusAddress
,
1204 IN OUT PULONG AddressSpace
,
1205 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1207 PBUS_HANDLER Handler
;
1210 /* Find the handler */
1211 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1212 if (!(Handler
) || !(Handler
->TranslateBusAddress
))
1214 DPRINT1("No translator!\n");
1218 /* Do the assignment */
1219 Status
= Handler
->TranslateBusAddress(Handler
,
1225 /* Dereference the handler and return */
1226 HalDereferenceBusHandler(Handler
);
1230 /* PUBLIC FUNCTIONS **********************************************************/
1237 HalAdjustResourceList(IN PCM_RESOURCE_LIST Resources
)
1239 /* Deprecated, return success */
1240 return STATUS_SUCCESS
;
1248 HalAssignSlotResources(IN PUNICODE_STRING RegistryPath
,
1249 IN PUNICODE_STRING DriverClassName
,
1250 IN PDRIVER_OBJECT DriverObject
,
1251 IN PDEVICE_OBJECT DeviceObject
,
1252 IN INTERFACE_TYPE BusType
,
1254 IN ULONG SlotNumber
,
1255 IN OUT PCM_RESOURCE_LIST
*AllocatedResources
)
1257 /* Check the bus type */
1258 if (BusType
!= PCIBus
)
1260 /* Call our internal handler */
1261 return HalpAssignSlotResources(RegistryPath
,
1268 AllocatedResources
);
1272 /* Call the PCI registered function */
1273 return HalPciAssignSlotResources(RegistryPath
,
1280 AllocatedResources
);
1289 HalGetBusData(IN BUS_DATA_TYPE BusDataType
,
1291 IN ULONG SlotNumber
,
1295 /* Call the extended function */
1296 return HalGetBusDataByOffset(BusDataType
,
1309 HalGetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1311 IN ULONG SlotNumber
,
1316 PBUS_HANDLER Handler
;
1319 /* Find the handler */
1320 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1321 if (!Handler
) return 0;
1323 /* Do the assignment */
1324 Status
= Handler
->GetBusData(Handler
,
1331 /* Dereference the handler and return */
1332 HalDereferenceBusHandler(Handler
);
1341 HalGetInterruptVector(IN INTERFACE_TYPE InterfaceType
,
1343 IN ULONG BusInterruptLevel
,
1344 IN ULONG BusInterruptVector
,
1346 OUT PKAFFINITY Affinity
)
1348 PBUS_HANDLER Handler
;
1356 /* Find the handler */
1357 Handler
= HalReferenceHandlerForBus(InterfaceType
, BusNumber
);
1358 if (!Handler
) return 0;
1360 /* Do the assignment */
1361 Vector
= Handler
->GetInterruptVector(Handler
,
1367 if ((Vector
!= IRQ2VECTOR(BusInterruptLevel
)) ||
1368 (*Irql
!= VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
))))
1370 DPRINT1("Returning IRQL %lx, Vector %lx for Level/Vector: %lx/%lx\n",
1371 *Irql
, Vector
, BusInterruptLevel
, BusInterruptVector
);
1372 DPRINT1("Old HAL would've returned IRQL %lx and Vector %lx\n",
1373 VECTOR2IRQL(IRQ2VECTOR(BusInterruptLevel
)),
1374 IRQ2VECTOR(BusInterruptLevel
));
1377 /* Dereference the handler and return */
1378 HalDereferenceBusHandler(Handler
);
1387 HalSetBusData(IN BUS_DATA_TYPE BusDataType
,
1389 IN ULONG SlotNumber
,
1393 /* Call the extended function */
1394 return HalSetBusDataByOffset(BusDataType
,
1407 HalSetBusDataByOffset(IN BUS_DATA_TYPE BusDataType
,
1409 IN ULONG SlotNumber
,
1414 PBUS_HANDLER Handler
;
1417 /* Find the handler */
1418 Handler
= HaliReferenceHandlerForConfigSpace(BusDataType
, BusNumber
);
1419 if (!Handler
) return 0;
1421 /* Do the assignment */
1422 Status
= Handler
->SetBusData(Handler
,
1429 /* Dereference the handler and return */
1430 HalDereferenceBusHandler(Handler
);
1439 HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType
,
1441 IN PHYSICAL_ADDRESS BusAddress
,
1442 IN OUT PULONG AddressSpace
,
1443 OUT PPHYSICAL_ADDRESS TranslatedAddress
)
1445 /* Look as the bus type */
1446 if (InterfaceType
== PCIBus
)
1448 /* Call the PCI registered function */
1449 return HalPciTranslateBusAddress(PCIBus
,
1457 /* Call the bus handler */
1458 return HaliTranslateBusAddress(InterfaceType
,