mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1453 lines
42 KiB
1453 lines
42 KiB
/*++
|
|
|
|
|
|
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)->BaseClass == PCI_CLASS_BRIDGE_DEV && \
|
|
(a)->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)
|
|
|
|
#define IsCardbusBridge(a) \
|
|
((a)->VendorID != PCI_INVALID_VENDORID && \
|
|
PCI_CONFIG_TYPE(a) == PCI_CARDBUS_BRIDGE_TYPE && \
|
|
(a)->BaseClass == PCI_CLASS_BRIDGE_DEV && \
|
|
(a)->SubClass == PCI_SUBCLASS_BR_CARDBUS)
|
|
|
|
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
|
|
|
|
VOID
|
|
HalpCardBusPin2Line(
|
|
IN PBUS_HANDLER BusHandler,
|
|
IN PBUS_HANDLER RootHandler,
|
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|
IN PPCI_COMMON_CONFIG PciData
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Devices on CardBus busses use the interrupt assigned to the bridge.
|
|
That's how it works.
|
|
|
|
Arguments:
|
|
|
|
BusHandler Bus Handler for the bus this (cardbus) device. That
|
|
is, the bus handler which was created for the bridge
|
|
under which this device resides.
|
|
RootHandler Pointer to the bus handler for the root.
|
|
SlotNumber Slot number for the cardbus device (typically 0).
|
|
PciData PCI Config space common header (64 bytes).
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PPCIPBUSDATA ChildBusData;
|
|
ULONG Length;
|
|
UCHAR ParentInterruptLine;
|
|
|
|
//
|
|
// If this device doesn't use interrupts, do nothing.
|
|
//
|
|
|
|
if (!PciData->u.type0.InterruptPin) {
|
|
return;
|
|
}
|
|
|
|
ChildBusData = (PPCIPBUSDATA)BusHandler->BusData;
|
|
|
|
//
|
|
// Read the interrupt information from the parent, ie the
|
|
// cardbus bridge's config space.
|
|
//
|
|
// Note: We use HalGetBusData because it will do the Pin2Line
|
|
// function in the parent for us.
|
|
|
|
Length = HalGetBusDataByOffset(
|
|
PCIConfiguration,
|
|
ChildBusData->ParentBus,
|
|
ChildBusData->CommonData.ParentSlot.u.AsULONG,
|
|
&ParentInterruptLine,
|
|
FIELD_OFFSET(PCI_COMMON_CONFIG, u.type2.InterruptLine),
|
|
sizeof(ParentInterruptLine)
|
|
);
|
|
|
|
//
|
|
// Return the parent's interrupt line value.
|
|
//
|
|
|
|
PciData->u.type0.InterruptLine = ParentInterruptLine;
|
|
}
|
|
|
|
VOID
|
|
HalpPciMakeBusAChild(
|
|
IN PBUS_HANDLER Child,
|
|
IN PBUS_HANDLER Parent
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Make bus 'Child' a child of bus 'Parent'. This routine is used
|
|
when the child bus is disabled or not really present. The child
|
|
bus consumes no resources.
|
|
|
|
Arguments:
|
|
|
|
Child The bus which is to become a child.
|
|
Parent The bus Child is a child of.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
HalpSetBusHandlerParent(Child, Parent);
|
|
((PPCIPBUSDATA)(Child->BusData))->ParentBus = (UCHAR)Parent->BusNumber;
|
|
|
|
//
|
|
// Give the bus an empty range list so it isn't
|
|
// consumed from the parent.
|
|
//
|
|
|
|
HalpFreeRangeList(Child->BusAddresses);
|
|
Child->BusAddresses = HalpAllocateNewRangeList();
|
|
}
|
|
|
|
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;
|
|
PBUS_HANDLER LastKnownRoot;
|
|
PPCIPBUSDATA ChildBusData;
|
|
ULONG d, f, i, j, BusNo;
|
|
ULONG ChildBusNo, ChildSubNo, ChildPrimaryBusNo;
|
|
ULONG FixupBusNo;
|
|
UCHAR Rescan, TestLimit1, TestLimit2;
|
|
BOOLEAN FoundDisabledBridge;
|
|
BOOLEAN FoundSomeFunction;
|
|
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;
|
|
FoundSomeFunction = FALSE;
|
|
|
|
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) {
|
|
// function not populated
|
|
continue;
|
|
}
|
|
|
|
FoundSomeFunction = TRUE;
|
|
|
|
if (IsPciBridge(CB.PciData)) {
|
|
|
|
//
|
|
// PCI-PCI bridge
|
|
//
|
|
|
|
ChildBusNo = (ULONG)CB.PciData->u.type1.SecondaryBus;
|
|
ChildSubNo = (ULONG)CB.PciData->u.type1.SubordinateBus;
|
|
ChildPrimaryBusNo = (ULONG)CB.PciData->u.type1.PrimaryBus;
|
|
|
|
} else if (IsCardbusBridge(CB.PciData)) {
|
|
|
|
//
|
|
// PCI-Cardbus bridge
|
|
//
|
|
|
|
ChildBusNo = (ULONG)CB.PciData->u.type2.SecondaryBus;
|
|
ChildSubNo = (ULONG)CB.PciData->u.type2.SubordinateBus;
|
|
ChildPrimaryBusNo = (ULONG)CB.PciData->u.type2.PrimaryBus;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Not a known bridge type, next function.
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Whenever we find a bridge, mark all all bus nodes that
|
|
// have not already been processed between this bus and
|
|
// the new child as children of this bus.
|
|
//
|
|
// eg if, on bus 0, we find a bridge to bus 6 thru 8, mark
|
|
// busses 1 thru 8 as a child of 0. (unless they have
|
|
// already been processed).
|
|
//
|
|
// This stops non-existant busses in the gap between the
|
|
// primary bus and the first child bus from looking like
|
|
// additional root busses.
|
|
//
|
|
|
|
for (FixupBusNo = CB.BusHandler->BusNumber + 1;
|
|
FixupBusNo <= ChildSubNo;
|
|
FixupBusNo++) {
|
|
|
|
ChildBus = HalpHandlerForBus(PCIBus, FixupBusNo);
|
|
|
|
if (ChildBus == NULL) {
|
|
continue;
|
|
}
|
|
|
|
ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
|
|
|
|
if (ChildBusData->BridgeConfigRead) {
|
|
|
|
//
|
|
// This child bus's relationships already processed
|
|
//
|
|
|
|
continue;
|
|
}
|
|
|
|
HalpPciMakeBusAChild(ChildBus, CB.BusHandler);
|
|
ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
|
|
}
|
|
|
|
if (!(CB.PciData->Command &
|
|
(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
|
|
// this PCI bridge is not enabled - skip it for now
|
|
|
|
FoundDisabledBridge = TRUE;
|
|
|
|
// Even though the bridge is disabled the bus number
|
|
// may have been set. If so then update the parent
|
|
// child relation ship so that the we do not see this
|
|
// as a root bus.
|
|
|
|
if (ChildBusNo <= CB.BusHandler->BusNumber) {
|
|
continue;
|
|
}
|
|
|
|
ChildBus = HalpHandlerForBus (PCIBus, ChildBusNo);
|
|
if (ChildBus == NULL) {
|
|
|
|
//
|
|
// Even though the bus is currently disabled,
|
|
// the system may configure it so we still
|
|
// want a bus handler created for it.
|
|
//
|
|
|
|
if (ChildBusNo > Rescan) {
|
|
Rescan = (UCHAR)ChildBusNo;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
ChildBusData = (PPCIPBUSDATA) ChildBus->BusData;
|
|
if (ChildBusData->BridgeConfigRead) {
|
|
// this child buses relationships already processed
|
|
continue;
|
|
}
|
|
|
|
HalpPciMakeBusAChild(ChildBus, CB.BusHandler);
|
|
ChildBusData->CommonData.ParentSlot = CB.SlotNumber;
|
|
|
|
//
|
|
// Even though we won't actually configure the
|
|
// bridge, mark the configuration as read so we
|
|
// don't mistake it for a root bus.
|
|
//
|
|
|
|
ChildBusData->BridgeConfigRead = TRUE;
|
|
continue;
|
|
}
|
|
|
|
if (ChildPrimaryBusNo != CB.BusHandler->BusNumber) {
|
|
|
|
DBGMSG ("HAL GetPciData: bad primarybus!!!\n");
|
|
// skip it...
|
|
continue;
|
|
}
|
|
|
|
if (ChildBusNo <= 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, ChildBusNo);
|
|
if (!ChildBus) {
|
|
DBGMSG ("HAL GetPciData: found configured pci bridge\n");
|
|
|
|
// up the number of buses
|
|
if (ChildBusNo > Rescan) {
|
|
Rescan = (UCHAR)ChildBusNo;
|
|
}
|
|
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;
|
|
|
|
if (IsCardbusBridge(CB.PciData)) {
|
|
|
|
//
|
|
// Cardbus handled by the PCI driver, don't try to
|
|
// interpret here.
|
|
//
|
|
|
|
HalpFreeRangeList(ChildBus->BusAddresses);
|
|
ChildBus->BusAddresses = HalpAllocateNewRangeList();
|
|
|
|
//
|
|
// Pin to Line (and vis-versa) for a device plugged
|
|
// into the cardbus bus, get the same values as the
|
|
// bridge itself. Override the line2pin routine in
|
|
// the cardbus bridge handler to use the parent's
|
|
// slot value. Note: line2pin doesn't do much.
|
|
// In DBG PC/AT builds, it simply undoes the IRQXOR
|
|
// used to catch drivers that are accessing the h/w
|
|
// directly. The normal routine will do this just
|
|
// fine so we don't need to override it as well.
|
|
//
|
|
|
|
ChildBusData->CommonData.Pin2Line = HalpCardBusPin2Line;
|
|
continue;
|
|
}
|
|
|
|
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
|
|
);
|
|
|
|
ChildBus->BusAddresses->IO.SystemAddressSpace = 1;
|
|
|
|
//
|
|
// Special VGA address remapping occuring on this bridge?
|
|
//
|
|
|
|
if (CB.PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) {
|
|
|
|
//
|
|
// Yes, then this bridge is positively decoding the
|
|
// range 0xA0000 thru 0xBFFFF regardless of the memory
|
|
// range settings. Add this range, if it overlaps it
|
|
// will get cleaned up later.
|
|
//
|
|
// Also, IO ranges 3b0 thru 3bb and 3c0 thru 3df.
|
|
//
|
|
|
|
HalpAddRange(
|
|
&ChildBus->BusAddresses->Memory,
|
|
0, // address space
|
|
0, // system base
|
|
0xa0000, // range base
|
|
0xbffff // range limit
|
|
);
|
|
|
|
HalpAddRange(
|
|
&ChildBus->BusAddresses->IO,
|
|
1, // address space
|
|
0, // system base
|
|
0x3b0, // range base
|
|
0x3bb // range limit
|
|
);
|
|
|
|
HalpAddRange(
|
|
&ChildBus->BusAddresses->IO,
|
|
1, // address space
|
|
0, // system base
|
|
0x3c0, // range base
|
|
0x3df // range limit
|
|
);
|
|
|
|
//
|
|
// Claim all aliases to these IO addresses.
|
|
//
|
|
// Bits 15:10 are not decoded so anything in
|
|
// the same 10 bits as the above in the range
|
|
// 0x400 thru 0xffff is an alias.
|
|
//
|
|
|
|
HalpSetPciBridgedVgaCronk (
|
|
ChildBus->BusNumber,
|
|
0x0400,
|
|
0xffff
|
|
);
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
//
|
|
// h/w hack the Win9x people allowed folks to make. Determine
|
|
// if the bridge is subtractive decode or not by seeing if
|
|
// it's IObase/limit is read-only.
|
|
//
|
|
|
|
TestLimit1 = CB.PciData->u.type1.IOLimit + 1;
|
|
if (!TestLimit1) {
|
|
TestLimit1 = 0xFE;
|
|
}
|
|
#if 0
|
|
DbgPrint ("PciBridge OrigLimit=%d TestLimit=%d ",
|
|
CB.PciData->u.type1.IOLimit,
|
|
TestLimit1
|
|
);
|
|
#endif
|
|
|
|
HalpWritePCIConfig (
|
|
CB.BusHandler,
|
|
CB.SlotNumber,
|
|
&TestLimit1,
|
|
FIELD_OFFSET (PCI_COMMON_CONFIG, u.type1.IOLimit),
|
|
1
|
|
);
|
|
|
|
HalpReadPCIConfig (
|
|
CB.BusHandler,
|
|
CB.SlotNumber,
|
|
&TestLimit2,
|
|
FIELD_OFFSET (PCI_COMMON_CONFIG, u.type1.IOLimit),
|
|
1
|
|
);
|
|
|
|
HalpWritePCIConfig (
|
|
CB.BusHandler,
|
|
CB.SlotNumber,
|
|
&CB.PciData->u.type1.IOLimit,
|
|
FIELD_OFFSET (PCI_COMMON_CONFIG, u.type1.IOLimit),
|
|
1
|
|
);
|
|
|
|
ChildBusData->Subtractive = TestLimit1 != TestLimit2;
|
|
#if 0
|
|
DbgPrint ("Result=%d, Subtractive=%d\n",
|
|
TestLimit2,
|
|
ChildBusData->Subtractive
|
|
);
|
|
|
|
DbgPrint ("Device buffer %x\n", CB.PciData);
|
|
#endif
|
|
|
|
//
|
|
// Now if its substractive, assume no range means the entire
|
|
// range.
|
|
//
|
|
|
|
if (ChildBusData->Subtractive) {
|
|
|
|
if (ChildBus->BusAddresses->IO.Base == PciBridgeIO2Base(0,0) &&
|
|
ChildBus->BusAddresses->IO.Limit <= PciBridgeIO2Limit(0,0)) {
|
|
|
|
ChildBus->BusAddresses->IO.Limit = 0x7FFFFFFFFFFFFFFF;
|
|
|
|
if (ChildBus->BusAddresses->Memory.Base == PciBridgeMemory2Base(0)) {
|
|
ChildBus->BusAddresses->Memory.Limit = 0x7FFFFFFFFFFFFFFF;
|
|
}
|
|
}
|
|
}
|
|
|
|
// should call HalpAssignPCISlotResources to assign
|
|
// baseaddresses, etc...
|
|
}
|
|
}
|
|
if (!((PPCIPBUSDATA)(CB.BusHandler->BusData))->BridgeConfigRead) {
|
|
|
|
//
|
|
// We believe this bus to be a root.
|
|
//
|
|
|
|
if ((FoundSomeFunction == FALSE) && (BusNo != 0)) {
|
|
|
|
//
|
|
// Nothing found on this bus. Assume it's not really
|
|
// a root. (Always assume 0 is a root). (This bus
|
|
// probably doesn't exist at all but ntdetect doesn't
|
|
// tell us that).
|
|
//
|
|
// Pretend this bus is a child of the last known root.
|
|
// At least this way it won't get a PDO and be handed
|
|
// to the PCI driver.
|
|
//
|
|
|
|
HalpPciMakeBusAChild(CB.BusHandler, LastKnownRoot);
|
|
|
|
} else {
|
|
|
|
//
|
|
// Found something on it (or it's zero), set as last
|
|
// known root.
|
|
//
|
|
|
|
LastKnownRoot = CB.BusHandler;
|
|
}
|
|
}
|
|
}
|
|
|
|
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) {
|
|
continue;
|
|
}
|
|
|
|
if (!IsPciBridge (CB.PciData)) {
|
|
// not a PCI-PCI bridge
|
|
continue;
|
|
}
|
|
|
|
if ((CB.PciData->Command &
|
|
(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE))) {
|
|
// 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.
|
|
|
|
For PCI-PCI briges which use postive address decode to forward
|
|
addresses, remove any addresses from any PCI bus which are bridged
|
|
to a child PCI bus.
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
PBUS_HANDLER Bus, ParentBus;
|
|
PPCIPBUSDATA BusData;
|
|
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 positive child PCI bus ranges from parent PCI buses
|
|
//
|
|
|
|
for (i = 0; i < MaxBuses; i++) {
|
|
Bus = HalpHandlerForBus (PCIBus, i);
|
|
BusData = (PPCIPBUSDATA) Bus->BusData;
|
|
|
|
//
|
|
// If the bridge is not subtractive, remove the ranges from the parents
|
|
//
|
|
|
|
if (!BusData->Subtractive) {
|
|
|
|
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)ExAllocatePoolWithTag(PagedPool,
|
|
Length,
|
|
HAL_POOL_TAG);
|
|
if (!ResourceList) {
|
|
|
|
//
|
|
// Can't possibly be out of paged pool at this stage of the
|
|
// game. This system is very unwell, get out.
|
|
//
|
|
|
|
return;
|
|
}
|
|
RtlZeroMemory(ResourceList, 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 = ExAllocatePoolWithTag(PagedPool, 1024, HAL_POOL_TAG);
|
|
|
|
if (!buffer) {
|
|
|
|
//
|
|
// Give up, we're not going anywhere anyway.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Init CB structure
|
|
//
|
|
|
|
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) {
|
|
continue;
|
|
}
|
|
|
|
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) {
|
|
continue;
|
|
}
|
|
|
|
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
|