diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/nthals/halx86/i386/ixpcibrd.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/ntos/nthals/halx86/i386/ixpcibrd.c')
-rw-r--r-- | private/ntos/nthals/halx86/i386/ixpcibrd.c | 1029 |
1 files changed, 1029 insertions, 0 deletions
diff --git a/private/ntos/nthals/halx86/i386/ixpcibrd.c b/private/ntos/nthals/halx86/i386/ixpcibrd.c new file mode 100644 index 000000000..c8b87d31e --- /dev/null +++ b/private/ntos/nthals/halx86/i386/ixpcibrd.c @@ -0,0 +1,1029 @@ +/*++ + + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + ixpcibrd.c + +Abstract: + + Get PCI-PCI bridge information + +Author: + + Ken Reneris (kenr) 14-June-1994 + +Environment: + + Kernel mode + +Revision History: + +--*/ + +#include "halp.h" +#include "pci.h" +#include "pcip.h" +#include "stdio.h" + +// debugging only... +// #define INIT_PCI_BRIDGE 1 + +extern WCHAR rgzMultiFunctionAdapter[]; +extern WCHAR rgzConfigurationData[]; +extern WCHAR rgzIdentifier[]; +extern WCHAR rgzReservedResources[]; + + +#if DBG +#define DBGMSG(a) DbgPrint(a) +#else +#define DBGMSG(a) +#endif + + + +#define IsPciBridge(a) \ + (a->VendorID != PCI_INVALID_VENDORID && \ + PCI_CONFIG_TYPE(a) == PCI_BRIDGE_TYPE && \ + a->SubClass == 4 && a->BaseClass == 6) + + +typedef struct { + ULONG BusNo; + PBUS_HANDLER BusHandler; + PPCIPBUSDATA BusData; + PCI_SLOT_NUMBER SlotNumber; + PPCI_COMMON_CONFIG PciData; + ULONG IO, Memory, PFMemory; + UCHAR Buffer[PCI_COMMON_HDR_LENGTH]; +} CONFIGBRIDGE, *PCONFIGBRIDGE; + +// +// Internal prototypes +// + + +#ifdef INIT_PCI_BRIDGE +VOID +HalpGetPciBridgeNeeds ( + IN ULONG HwType, + IN PUCHAR MaxPciBus, + IN PCONFIGBRIDGE Current + ); +#endif + +VOID +HalpSetPciBridgedVgaCronk ( + IN ULONG BusNumber, + IN ULONG Base, + IN ULONG Limit + ); + + +ULONG +HalpGetBridgedPCIInterrupt ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +ULONG +HalpGetBridgedPCIISAInt ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN ULONG BusInterruptLevel, + IN ULONG BusInterruptVector, + OUT PKIRQL Irql, + OUT PKAFFINITY Affinity + ); + +VOID +HalpPCIBridgedPin2Line ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ); + + +VOID +HalpPCIBridgedLine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ); + +NTSTATUS +HalpGetBridgedPCIIrqTable ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER PciSlot, + OUT PUCHAR IrqTable + ); + + + + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(INIT,HalpGetPciBridgeConfig) +#pragma alloc_text(INIT,HalpSetPciBridgedVgaCronk) +#pragma alloc_text(INIT,HalpFixupPciSupportedRanges) + +#ifdef INIT_PCI_BRIDGE +#pragma alloc_text(PAGE,HalpGetBridgedPCIInterrupt) +//#pragma alloc_text(PAGE,HalpGetBridgedPCIIrqTable) +#pragma alloc_text(INIT,HalpGetPciBridgeNeeds) +#endif +#endif + + +BOOLEAN +HalpGetPciBridgeConfig ( + IN ULONG HwType, + IN PUCHAR MaxPciBus + ) +/*++ + +Routine Description: + + Scan the devices on all known pci buses trying to locate any + pci to pci bridges. Record the hierarchy for the buses, and + which buses have what addressing limits. + +Arguments: + + HwType - Configuration type. + MaxPciBus - # of PCI buses reported by the bios + +--*/ +{ + PBUS_HANDLER ChildBus; + PPCIPBUSDATA ChildBusData; + ULONG d, f, i, j, BusNo; + UCHAR Rescan; + BOOLEAN FoundDisabledBridge; + CONFIGBRIDGE CB; + + Rescan = 0; + FoundDisabledBridge = FALSE; + + // + // Find each bus on a bridge and initialize it's base and limit information + // + + CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer; + CB.SlotNumber.u.bits.Reserved = 0; + for (BusNo=0; BusNo < *MaxPciBus; BusNo++) { + + CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + // + // Read PCI configuration information + // + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + // next device + break; + } + + if (!IsPciBridge (CB.PciData)) { + // not a PCI-PCI bridge, next function + continue; + } + + if (!(CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) { + // this PCI bridge is not enabled - skip it for now + FoundDisabledBridge = TRUE; + continue; + } + + if ((ULONG) CB.PciData->u.type1.PrimaryBus != + CB.BusHandler->BusNumber) { + + DBGMSG ("HAL GetPciData: bad primarybus!!!\n"); + // skip it... + continue; + } + + if ((ULONG) CB.PciData->u.type1.SecondaryBus <= CB.BusHandler->BusNumber) { + + // secondary bus number doesn't make any sense. HP Omnibook may + // not fill this field in on a virtually disabled pci-pci bridge + + FoundDisabledBridge = TRUE; + continue; + } + + // + // Found a PCI-PCI bridge. Determine it's parent child + // releationships + // + + ChildBus = HalpHandlerForBus (PCIBus, CB.PciData->u.type1.SecondaryBus); + if (!ChildBus) { + DBGMSG ("HAL GetPciData: found configured pci bridge\n"); + + // up the number of buses + if (CB.PciData->u.type1.SecondaryBus > Rescan) { + Rescan = CB.PciData->u.type1.SecondaryBus; + } + continue; + } + + ChildBusData = (PPCIPBUSDATA) ChildBus->BusData; + if (ChildBusData->BridgeConfigRead) { + // this child buses releationships already processed + continue; + } + + // + // Remember the limits which are programmed into this bridge + // + + ChildBusData->BridgeConfigRead = TRUE; + HalpSetBusHandlerParent (ChildBus, CB.BusHandler); + ChildBusData->ParentBus = (UCHAR) CB.BusHandler->BusNumber; + ChildBusData->CommonData.ParentSlot = CB.SlotNumber; + + ChildBus->BusAddresses->IO.Base = + PciBridgeIO2Base( + CB.PciData->u.type1.IOBase, + CB.PciData->u.type1.IOBaseUpper16 + ); + + ChildBus->BusAddresses->IO.Limit = + PciBridgeIO2Limit( + CB.PciData->u.type1.IOLimit, + CB.PciData->u.type1.IOLimitUpper16 + ); + + // + // Special VGA address remapping occuring on this bridge? + // + + if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA && + ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) { + + HalpSetPciBridgedVgaCronk ( + ChildBus->BusNumber, + (ULONG) ChildBus->BusAddresses->IO.Base, + (ULONG) ChildBus->BusAddresses->IO.Limit + ); + } + + // + // If supported I/O ranges on this bus are limitied to + // 256bytes on every 1K aligned boundry within the + // range, then redo supported IO BusAddresses to match + // + + if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA && + ChildBus->BusAddresses->IO.Base < ChildBus->BusAddresses->IO.Limit) { + + // assume Base is 1K aligned + i = (ULONG) ChildBus->BusAddresses->IO.Base; + j = (ULONG) ChildBus->BusAddresses->IO.Limit; + + // convert head entry + ChildBus->BusAddresses->IO.Limit = i + 255; + i += 1024; + + // add remaining ranges + while (i < j) { + HalpAddRange ( + &ChildBus->BusAddresses->IO, + 1, // address space + 0, // system base + i, // bus address + i + 255 // bus limit + ); + + // next range + i += 1024; + } + } + + ChildBus->BusAddresses->Memory.Base = + PciBridgeMemory2Base(CB.PciData->u.type1.MemoryBase); + + ChildBus->BusAddresses->Memory.Limit = + PciBridgeMemory2Limit(CB.PciData->u.type1.MemoryLimit); + + // On x86 it's ok to clip Prefetch to 32 bits + + if (CB.PciData->u.type1.PrefetchBaseUpper32 == 0) { + ChildBus->BusAddresses->PrefetchMemory.Base = + PciBridgeMemory2Base(CB.PciData->u.type1.PrefetchBase); + + + ChildBus->BusAddresses->PrefetchMemory.Limit = + PciBridgeMemory2Limit(CB.PciData->u.type1.PrefetchLimit); + + if (CB.PciData->u.type1.PrefetchLimitUpper32) { + ChildBus->BusAddresses->PrefetchMemory.Limit = 0xffffffff; + } + } + + // should call HalpAssignPCISlotResources to assign + // baseaddresses, etc... + } + } + } + + if (Rescan) { + *MaxPciBus = Rescan+1; + return TRUE; + } + + if (!FoundDisabledBridge) { + return FALSE; + } + + DBGMSG ("HAL GetPciData: found disabled pci bridge\n"); + +#ifdef INIT_PCI_BRIDGE + // + // We've calculated all the parent's buses known bases & limits. + // While doing this a pci-pci bus was found that the bios didn't + // configure. This is not expected, and we'll make some guesses + // at a configuration here and enable it. + // + // (this code is primarily for testing the above code since + // currently no system bioses actually configure the child buses) + // + + for (BusNo=0; BusNo < *MaxPciBus; BusNo++) { + + CB.BusHandler = HalpHandlerForBus (PCIBus, BusNo); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (!IsPciBridge (CB.PciData)) { + // not a PCI-PCI bridge + continue; + } + + if ((CB.PciData->Command & PCI_ENABLE_BUS_MASTER)) { + // this PCI bridge is enabled + continue; + } + + // + // We have a disabled bus - assign it a number, then + // determine all the requirements of all devices + // on the other side of this bridge + // + + CB.BusNo = BusNo; + HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB); + } + } + } + // preform Rescan + return TRUE; + +#else + + return FALSE; + +#endif + +} + +VOID +HalpFixupPciSupportedRanges ( + IN ULONG MaxBuses + ) +/*++ + +Routine Description: + + PCI-PCI bridged buses only see addresses which their parent + bueses support. So adjust any PCI SUPPORT_RANGES to be + a complete subset of all of it's parent buses. + + PCI-PCI briges use postive address decode to forward addresses. + So, remove any addresses from any PCI bus which are bridged to + a child PCI bus. + +--*/ +{ + ULONG i; + PBUS_HANDLER Bus, ParentBus; + PSUPPORTED_RANGES HRanges; + + // + // Pass 1 - shrink all PCI supported ranges to be a subset of + // all of it's parent buses + // + + for (i = 0; i < MaxBuses; i++) { + + Bus = HalpHandlerForBus (PCIBus, i); + + ParentBus = Bus->ParentHandler; + while (ParentBus) { + + HRanges = Bus->BusAddresses; + Bus->BusAddresses = HalpMergeRanges ( + ParentBus->BusAddresses, + HRanges + ); + + HalpFreeRangeList (HRanges); + ParentBus = ParentBus->ParentHandler; + } + } + + // + // Pass 2 - remove all child PCI bus ranges from parent PCI buses + // + + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + + ParentBus = Bus->ParentHandler; + while (ParentBus) { + + if (ParentBus->InterfaceType == PCIBus) { + HalpRemoveRanges ( + ParentBus->BusAddresses, + Bus->BusAddresses + ); + } + + ParentBus = ParentBus->ParentHandler; + } + } + + // + // Cleanup + // + + for (i = 0; i < MaxBuses; i++) { + Bus = HalpHandlerForBus (PCIBus, i); + HalpConsolidateRanges (Bus->BusAddresses); + } +} + + + +VOID +HalpSetPciBridgedVgaCronk ( + IN ULONG BusNumber, + IN ULONG BaseAddress, + IN ULONG LimitAddress + ) +/*++ + +Routine Description: . + + The 'vga compatible addresses' bit is set in the bridge control regiter. + This causes the bridge to pass any I/O address in the range of: 10bit + decode 3b0-3bb & 3c0-3df, as TEN bit addresses. + + As far as I can tell this "feature" is an attempt to solve some problem + which the folks solving it did not fully understand, so instead of doing + it right we have this fine mess. + + The solution is to take the least of all evils which is to remove any + I/O port ranges which are getting remapped from any IoAssignResource + request. (ie, IoAssignResources will never contimplate giving any + I/O port out in the suspected ranges). + + note: memory allocation error here is fatal so don't bother with the + return codes. + +Arguments: + + Base - Base of IO address range in question + Limit - Limit of IO address range in question + +--*/ +{ + UNICODE_STRING unicodeString; + OBJECT_ATTRIBUTES objectAttributes; + HANDLE handle; + ULONG Length; + PCM_RESOURCE_LIST ResourceList; + PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor; + ULONG AddressMSBs; + WCHAR ValueName[80]; + NTSTATUS status; + + // + // Open reserved resource settings + // + + RtlInitUnicodeString (&unicodeString, rgzReservedResources); + InitializeObjectAttributes( &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + status = ZwOpenKey( &handle, KEY_READ|KEY_WRITE, &objectAttributes); + if (!NT_SUCCESS(status)) { + return; + } + + // + // Build resource list of reseved ranges + // + + Length = ((LimitAddress - BaseAddress) / 1024 + 2) * 2 * + sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) + + sizeof (CM_RESOURCE_LIST); + + ResourceList = (PCM_RESOURCE_LIST) ExAllocatePool (PagedPool, Length); + memset (ResourceList, 0, Length); + + ResourceList->Count = 1; + ResourceList->List[0].InterfaceType = PCIBus; + ResourceList->List[0].BusNumber = BusNumber; + Descriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors; + + while (BaseAddress < LimitAddress) { + AddressMSBs = BaseAddress & ~0x3ff; // get upper 10bits of addr + + // + // Add xx3b0 through xx3bb + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3b0; + Descriptor->u.Port.Length = 0xb; + + Descriptor += 1; + ResourceList->List[0].PartialResourceList.Count += 1; + + // + // Add xx3c0 through xx3df + // + + Descriptor->Type = CmResourceTypePort; + Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; + Descriptor->Flags = CM_RESOURCE_PORT_IO; + Descriptor->u.Port.Start.QuadPart = AddressMSBs | 0x3c0; + Descriptor->u.Port.Length = 0x1f; + + Descriptor += 1; + ResourceList->List[0].PartialResourceList.Count += 1; + + // + // Next range + // + + BaseAddress += 1024; + } + + // + // Add the reserved ranges to avoid during IoAssignResource + // + + swprintf (ValueName, L"HAL_PCI_%d", BusNumber); + RtlInitUnicodeString (&unicodeString, ValueName); + + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_RESOURCE_LIST, + ResourceList, + (ULONG) Descriptor - (ULONG) ResourceList + ); + + + ExFreePool (ResourceList); + ZwClose (handle); +} + + + +#ifdef INIT_PCI_BRIDGE + +VOID +HalpGetPciBridgeNeeds ( + IN ULONG HwType, + IN PUCHAR MaxPciBus, + IN PCONFIGBRIDGE Current + ) +{ + ACCESS_MASK DesiredAccess; + UNICODE_STRING unicodeString; + PUCHAR buffer; + HANDLE handle; + OBJECT_ATTRIBUTES objectAttributes; + PCM_FULL_RESOURCE_DESCRIPTOR Descriptor; + PCONFIGURATION_COMPONENT Component; + CONFIGBRIDGE CB; + ULONG mnum, d, f, i; + NTSTATUS status; + + buffer = ExAllocatePool (PagedPool, 1024); + + // init + CB.PciData = (PPCI_COMMON_CONFIG) CB.Buffer; + CB.SlotNumber.u.bits.Reserved = 0; + Current->IO = Current->Memory = Current->PFMemory = 0; + + // + // Assign this bridge an ID, and turn on configuration space + // + + Current->PciData->u.type1.PrimaryBus = (UCHAR) Current->BusNo; + Current->PciData->u.type1.SecondaryBus = (UCHAR) *MaxPciBus; + Current->PciData->u.type1.SubordinateBus = (UCHAR) 0xFF; + Current->PciData->u.type1.SecondaryStatus = 0xffff; + Current->PciData->Status = 0xffff; + Current->PciData->Command = 0; + + Current->PciData->u.type1.BridgeControl = PCI_ASSERT_BRIDGE_RESET; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + KeStallExecutionProcessor (100); + + Current->PciData->u.type1.BridgeControl = 0; + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + + KeStallExecutionProcessor (100); + + // + // Allocate new handler for bus + // + + CB.BusHandler = HalpAllocateAndInitPciBusHandler (HwType, *MaxPciBus, FALSE); + CB.BusData = (PPCIPBUSDATA) CB.BusHandler->BusData; + CB.BusNo = *MaxPciBus; + *MaxPciBus += 1; + + // + // Add another PCI bus in the registry + // + + mnum = 0; + for (; ;) { + // + // Find next available MultiFunctionAdapter key + // + + DesiredAccess = KEY_READ | KEY_WRITE; + swprintf ((PWCHAR) buffer, L"%s\\%d", rgzMultiFunctionAdapter, mnum); + RtlInitUnicodeString (&unicodeString, (PWCHAR) buffer); + + InitializeObjectAttributes( &objectAttributes, + &unicodeString, + OBJ_CASE_INSENSITIVE, + NULL, + (PSECURITY_DESCRIPTOR) NULL + ); + + status = ZwOpenKey( &handle, DesiredAccess, &objectAttributes); + if (!NT_SUCCESS(status)) { + break; + } + + // already exists, next + ZwClose (handle); + mnum += 1; + } + + ZwCreateKey (&handle, + DesiredAccess, + &objectAttributes, + 0, + NULL, + REG_OPTION_VOLATILE, + &d + ); + + // + // Add needed registry values for this MultifucntionAdapter entry + // + + RtlInitUnicodeString (&unicodeString, rgzIdentifier); + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_SZ, + L"PCI", + sizeof (L"PCI") + ); + + RtlInitUnicodeString (&unicodeString, rgzConfigurationData); + Descriptor = (PCM_FULL_RESOURCE_DESCRIPTOR) buffer; + Descriptor->InterfaceType = PCIBus; + Descriptor->BusNumber = CB.BusNo; + Descriptor->PartialResourceList.Version = 0; + Descriptor->PartialResourceList.Revision = 0; + Descriptor->PartialResourceList.Count = 0; + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_FULL_RESOURCE_DESCRIPTOR, + Descriptor, + sizeof (*Descriptor) + ); + + + RtlInitUnicodeString (&unicodeString, L"Component Information"); + Component = (PCONFIGURATION_COMPONENT) buffer; + RtlZeroMemory (Component, sizeof (*Component)); + Component->AffinityMask = 0xffffffff; + ZwSetValueKey (handle, + &unicodeString, + 0L, + REG_BINARY, + Component, + FIELD_OFFSET (CONFIGURATION_COMPONENT, ConfigurationDataLength) + ); + + ZwClose (handle); + + + // + // Since the BIOS didn't configure this bridge we'll assume that + // the PCI interrupts are bridged. (for BIOS configured buses we + // assume that the BIOS put the ISA bus IRQ in the InterruptLine value) + // + + CB.BusData->Pin2Line = (PciPin2Line) HalpPCIBridgedPin2Line; + CB.BusData->Line2Pin = (PciLine2Pin) HalpPCIBridgedLine2Pin; + //CB.BusData->GetIrqTable = (PciIrqTable) HalpGetBridgedPCIIrqTable; + + if (Current->BusHandler->GetInterruptVector == HalpGetPCIIntOnISABus) { + + // + // The parent bus'es interrupt pin to vector mappings is not + // a static function, and is determined by the boot firmware. + // + + //CB.BusHandler->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetBridgedPCIISAInt; + + // read each device on parent bus + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + Current->BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (CB.PciData->u.type0.InterruptPin && + (PCI_CONFIG_TYPE (CB.PciData) == PCI_DEVICE_TYPE || + PCI_CONFIG_TYPE (CB.PciData) == PCI_BRIDGE_TYPE)) { + + // get bios supplied int mapping + i = CB.PciData->u.type0.InterruptPin + d % 4; + CB.BusData->SwizzleIn[i] = CB.PciData->u.type0.InterruptLine; + } + } + } + + } else { + _asm int 3; + } + + // + // Look at each device on the bus and determine it's resource needs + // + + for (d = 0; d < PCI_MAX_DEVICES; d++) { + CB.SlotNumber.u.bits.DeviceNumber = d; + + for (f = 0; f < PCI_MAX_FUNCTION; f++) { + CB.SlotNumber.u.bits.FunctionNumber = f; + + HalpReadPCIConfig ( + CB.BusHandler, + CB.SlotNumber, + CB.PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + if (CB.PciData->VendorID == PCI_INVALID_VENDORID) { + break; + } + + if (IsPciBridge (CB.PciData)) { + // oh look - another bridge ... + HalpGetPciBridgeNeeds (HwType, MaxPciBus, &CB); + continue; + } + + if (PCI_CONFIG_TYPE (CB.PciData) != PCI_DEVICE_TYPE) { + continue; + } + + // found a device - figure out the resources it needs + } + } + + // + // Found all sub-buses set SubordinateBus accordingly + // + + Current->PciData->u.type1.SubordinateBus = (UCHAR) *MaxPciBus - 1; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + + // + // Set the bridges IO, Memory, and Prefetch Memory windows + // + + // For now just pick some numbers & set everyone the same + // IO 0x6000 - 0xFFFF + // MEM 0x40000000 - 0x4FFFFFFF + // PFMEM 0x50000000 - 0x5FFFFFFF + + Current->PciData->u.type1.IOBase = 0x6000 >> 12 << 4; + Current->PciData->u.type1.IOLimit = 0xffff >> 12 << 4; + Current->PciData->u.type1.MemoryBase = 0x40000000 >> 20 << 4; + Current->PciData->u.type1.MemoryLimit = 0x4fffffff >> 20 << 4; + Current->PciData->u.type1.PrefetchBase = 0x50000000 >> 20 << 4; + Current->PciData->u.type1.PrefetchLimit = 0x5fffffff >> 20 << 4; + + Current->PciData->u.type1.PrefetchBaseUpper32 = 0; + Current->PciData->u.type1.PrefetchLimitUpper32 = 0; + Current->PciData->u.type1.IOBaseUpper16 = 0; + Current->PciData->u.type1.IOLimitUpper16 = 0; + Current->PciData->u.type1.BridgeControl = + PCI_ENABLE_BRIDGE_ISA; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + HalpReadPCIConfig ( + Current->BusHandler, + Current->SlotNumber, + Current->PciData, + 0, + PCI_COMMON_HDR_LENGTH + ); + + // enable memory & io decodes + + Current->PciData->Command = + PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE | PCI_ENABLE_BUS_MASTER; + + HalpWritePCIConfig ( + Current->BusHandler, + Current->SlotNumber, + &Current->PciData->Command, + FIELD_OFFSET (PCI_COMMON_CONFIG, Command), + sizeof (Current->PciData->Command) + ); + + ExFreePool (buffer); +} + +VOID +HalpPCIBridgedPin2Line ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciData + ) +/*++ + + This function maps the device's InterruptPin to an InterruptLine + value. + + test function particular to dec pci-pci bridge card + +--*/ +{ + PPCIPBUSDATA BusData; + ULONG i; + + if (!PciData->u.type0.InterruptPin) { + return ; + } + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + // + // Convert slot Pin into Bus INTA-D. + // + + i = (PciData->u.type0.InterruptPin + + SlotNumber.u.bits.DeviceNumber - 1) % 4; + + PciData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR; + PciData->u.type0.InterruptLine = 0x0b ^ IRQXOR; +} + + +VOID +HalpPCIBridgedLine2Pin ( + IN PBUS_HANDLER BusHandler, + IN PBUS_HANDLER RootHandler, + IN PCI_SLOT_NUMBER SlotNumber, + IN PPCI_COMMON_CONFIG PciNewData, + IN PPCI_COMMON_CONFIG PciOldData + ) +/*++ + + This functions maps the device's InterruptLine to it's + device specific InterruptPin value. + + test function particular to dec pci-pci bridge card + +--*/ +{ + PPCIPBUSDATA BusData; + ULONG i; + + if (!PciNewData->u.type0.InterruptPin) { + return ; + } + + BusData = (PPCIPBUSDATA) BusHandler->BusData; + + i = (PciNewData->u.type0.InterruptPin + + SlotNumber.u.bits.DeviceNumber - 1) % 4; + + PciNewData->u.type0.InterruptLine = BusData->SwizzleIn[i] ^ IRQXOR; + PciNewData->u.type0.InterruptLine = 0x0b ^ IRQXOR; +} + +#endif |