VOID NTAPI INIT_FUNCTION HalpInitializePciStubs(VOID) { PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; UCHAR PciType; PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData; ULONG i; PCI_SLOT_NUMBER j; ULONG VendorId = 0; ULONG MaxPciBusNumber; /* Query registry information */ PciRegistryInfo = HalpQueryPciRegistryInfo(); if (!PciRegistryInfo) { /* Assume type 1 */ PciType = 1; /* Force a manual bus scan later */ MaxPciBusNumber = MAXULONG; } else { /* Get the PCI type */ PciType = PciRegistryInfo->HardwareMechanism & 0xF; /* Get MaxPciBusNumber and make it 0-based */ MaxPciBusNumber = PciRegistryInfo->NoBuses - 1; /* Free the info structure */ ExFreePoolWithTag(PciRegistryInfo, TAG_HAL); } /* Initialize the PCI lock */ KeInitializeSpinLock(&HalpPCIConfigLock); /* Check the type of PCI bus */ switch (PciType) { /* Type 1 PCI Bus */ case 1: /* Copy the Type 1 handler data */ RtlCopyMemory(&PCIConfigHandler, &PCIConfigHandlerType1, sizeof(PCIConfigHandler)); /* Set correct I/O Ports */ BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT; BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT; break; /* Type 2 PCI Bus */ case 2: /* Copy the Type 2 handler data */ RtlCopyMemory(&PCIConfigHandler, &PCIConfigHandlerType2, sizeof (PCIConfigHandler)); /* Set correct I/O Ports */ BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT; BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT; BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE; /* Only 16 devices supported, not 32 */ BusData->MaxDevice = 16; break; default: /* Invalid type */ DbgPrint("HAL: Unknown PCI type\n"); } /* Run a forced bus scan if needed */ if (MaxPciBusNumber == MAXULONG) { /* Initialize the max bus number to 0xFF */ HalpMaxPciBus = 0xFF; /* Initialize the counter */ MaxPciBusNumber = 0; /* Loop all possible buses */ for (i = 0; i < HalpMaxPciBus; i++) { /* Loop all devices */ for (j.u.AsULONG = 0; j.u.AsULONG < BusData->MaxDevice; j.u.AsULONG++) { /* Query the interface */ if (HaliPciInterfaceReadConfig(NULL, i, j, &VendorId, 0, sizeof(ULONG))) { /* Validate the vendor ID */ if ((VendorId & 0xFFFF) != PCI_INVALID_VENDORID) { /* Set this as the maximum ID */ MaxPciBusNumber = i; break; } } } } } /* Set the real max bus number */ HalpMaxPciBus = MaxPciBusNumber; /* We're done */ HalpPCIConfigInitialized = TRUE; }
INIT_FUNCTION VOID NTAPI HalpInitializePciBus(VOID) { #ifndef _MINIHAL_ PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo; UCHAR PciType; PCI_SLOT_NUMBER PciSlot; ULONG i, j, k; UCHAR DataBuffer[PCI_COMMON_HDR_LENGTH]; PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)DataBuffer; PBUS_HANDLER BusHandler; ULONG HackFlags; BOOLEAN ExtendedAddressDecoding = FALSE; NTSTATUS Status; /* Query registry information */ PciRegistryInfo = HalpQueryPciRegistryInfo(); if (!PciRegistryInfo) return; /* Initialize the PCI configuration lock */ KeInitializeSpinLock(&HalpPCIConfigLock); /* Get the type and free the info structure */ PciType = PciRegistryInfo->HardwareMechanism & 0xF; /* Check if this is a type 2 PCI bus with at least one bus */ if ((PciRegistryInfo->NoBuses) && (PciType == 2)) { /* Setup the PCI slot */ PciSlot.u.bits.Reserved = 0; PciSlot.u.bits.FunctionNumber = 0; /* Loop all slots */ for (i = 0; i < 32; i++) { /* Try to setup a Type 2 PCI slot */ PciType = 2; BusHandler = HalpAllocateAndInitPciBusHandler(2, 0, TRUE); if (!BusHandler) break; /* Now check if it's valid */ if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; /* Heh, the BIOS lied... try Type 1 */ PciType = 1; BusHandler = HalpAllocateAndInitPciBusHandler(1, 0, TRUE); if (!BusHandler) break; /* Now check if it's valid */ if (HalpIsValidPCIDevice(BusHandler, PciSlot)) break; /* Keep trying */ PciType = 2; } /* Now allocate the correct kind of handler */ HalpAllocateAndInitPciBusHandler(PciType, 0, FALSE); } /* Okay, now loop all PCI bridges */ do { /* Loop all PCI buses */ for (i = 0; i < PciRegistryInfo->NoBuses; i++) { /* Check if we have a handler for it */ if (!HalHandlerForBus(PCIBus, i)) { /* Allocate it */ HalpAllocateAndInitPciBusHandler(PciType, i, FALSE); } } /* Go to the next bridge */ } while (HalpGetPciBridgeConfig(PciType, &PciRegistryInfo->NoBuses)); /* Now build correct address range informaiton */ HalpFixupPciSupportedRanges(PciRegistryInfo->NoBuses); /* Loop every bus */ DbgPrint("\n====== PCI BUS HARDWARE DETECTION =======\n\n"); PciSlot.u.bits.Reserved = 0; for (i = 0; i < PciRegistryInfo->NoBuses; i++) { /* Get the bus handler */ BusHandler = HalHandlerForBus(PCIBus, i); /* Loop every device */ for (j = 0; j < 32; j++) { /* Loop every function */ PciSlot.u.bits.DeviceNumber = j; for (k = 0; k < 8; k++) { /* Build the final slot structure */ PciSlot.u.bits.FunctionNumber = k; /* Read the configuration information */ HalpReadPCIConfig(BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH); /* Skip if this is an invalid function */ if (PciData->VendorID == PCI_INVALID_VENDORID) continue; /* Print out the entry */ HalpDebugPciDumpBus(i, j, k, PciData); /* Check if this is a Cardbus bridge */ if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE) { /* Not supported */ DbgPrint("\tDevice is a PCI Cardbus Bridge. It will not work!\n"); continue; } /* Check if this is a PCI device */ if (PCI_CONFIGURATION_TYPE(PciData) != PCI_BRIDGE_TYPE) { /* Check if it has an interrupt pin and line registered */ if ((PciData->u.type1.InterruptPin) && (PciData->u.type1.InterruptLine)) { /* Check if this interrupt line is connected to the bus */ if (PciData->u.type1.InterruptLine < 16) { /* Is this an IDE device? */ if (!HalpIsIdeDevice(PciData)) { /* We'll mask out this interrupt then */ DbgPrint("\tDevice is using IRQ %d! ISA Cards using that IRQ may fail!\n", PciData->u.type1.InterruptLine); HalpPciIrqMask |= (1 << PciData->u.type1.InterruptLine); } } } } /* Check for broken Intel chips */ if (PciData->VendorID == 0x8086) { /* Check for broken 82830 PCI controller */ if ((PciData->DeviceID == 0x04A3) && (PciData->RevisionID < 0x11)) { /* Skip */ DbgPrint("\tDevice is a broken Intel 82430 PCI Controller. It will not work!\n\n"); continue; } /* Check for broken 82378 PCI-to-ISA Bridge */ if ((PciData->DeviceID == 0x0484) && (PciData->RevisionID <= 3)) { /* Skip */ DbgPrint("\tDevice is a broken Intel 82378 PCI-to-ISA Bridge. It will not work!\n\n"); continue; } /* Check for broken 82450 PCI Bridge */ if ((PciData->DeviceID == 0x84C4) && (PciData->RevisionID <= 4)) { DbgPrint("\tDevice is a Intel Orion 82450 PCI Bridge. It will not work!\n\n"); continue; } } /* Do we know this card? */ if (!ExtendedAddressDecoding) { /* Check for it */ if (HalpIsRecognizedCard(PciRegistryInfo, PciData, HALP_CARD_FEATURE_FULL_DECODE)) { /* We'll do chipset checks later */ DbgPrint("\tDevice has Extended Address Decoding. It may fail to work on older BIOSes!\n"); ExtendedAddressDecoding = TRUE; } } /* Now check the registry for chipset hacks */ Status = HalpGetChipHacks(PciData->VendorID, PciData->DeviceID, PciData->RevisionID, &HackFlags); if (NT_SUCCESS(Status)) { /* Check for broken ACPI routing */ if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_ACPI_IRQ_ROUTING) { DbgPrint("This chipset has broken ACPI IRQ Routing! Be aware!\n\n"); continue; } /* Check for broken ACPI timer */ if (HackFlags & HAL_PCI_CHIP_HACK_BROKEN_ACPI_TIMER) { DbgPrint("This chipset has a broken ACPI timer! Be aware!\n\n"); continue; } /* Check for hibernate-disable */ if (HackFlags & HAL_PCI_CHIP_HACK_DISABLE_HIBERNATE) { DbgPrint("This chipset has a broken PCI device which is incompatible with hibernation. Be aware!\n\n"); continue; } /* Check for USB controllers that generate SMIs */ if (HackFlags & HAL_PCI_CHIP_HACK_USB_SMI_DISABLE) { DbgPrint("This chipset has a USB controller which generates SMIs. ReactOS will likely fail to boot!\n\n"); continue; } } /* Terminate the entry */ DbgPrint("\n"); } } } /* Initialize NMI Crash Flag */ HalpGetNMICrashFlag(); /* Free the registry data */ ExFreePoolWithTag(PciRegistryInfo, TAG_HAL); /* Tell PnP if this hard supports correct decoding */ HalpMarkChipsetDecode(ExtendedAddressDecoding); DbgPrint("====== PCI BUS DETECTION COMPLETE =======\n\n"); #endif }