2454 lines
62 KiB
C
2454 lines
62 KiB
C
|
/*++
|
|||
|
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
Copyright (c) 1994 Digital Equipment Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
pcisup.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Platform-independent PCI bus routines
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "halp.h"
|
|||
|
#include "pci.h"
|
|||
|
#include "pcip.h"
|
|||
|
|
|||
|
typedef ULONG (*FncConfigIO) (
|
|||
|
IN PVOID State,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
);
|
|||
|
|
|||
|
typedef struct {
|
|||
|
FncConfigIO ConfigRead[3];
|
|||
|
FncConfigIO ConfigWrite[3];
|
|||
|
} CONFIG_HANDLER, *PCONFIG_HANDLER;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Define PCI slot validity
|
|||
|
//
|
|||
|
typedef enum _VALID_SLOT {
|
|||
|
InvalidBus = 0,
|
|||
|
InvalidSlot,
|
|||
|
ValidSlot
|
|||
|
} VALID_SLOT;
|
|||
|
|
|||
|
//
|
|||
|
// Local prototypes for routines supporting PCI bus handler routines
|
|||
|
//
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpGetPCIData (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN ULONG Slot,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
);
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpSetPCIData (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN ULONG Slot,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpAdjustPCIResourceList (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpAssignPCISlotResources (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN PUNICODE_STRING RegistryPath,
|
|||
|
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
|||
|
IN ULONG Slot,
|
|||
|
IN OUT PCM_RESOURCE_LIST *pAllocatedResources
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
HalpReadPCIConfig (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
HalpWritePCIConfig (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
);
|
|||
|
|
|||
|
VALID_SLOT
|
|||
|
HalpValidPCISlot (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
HalpPCIConfig (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length,
|
|||
|
IN FncConfigIO *ConfigIO
|
|||
|
);
|
|||
|
|
|||
|
ULONG HalpPCIReadUlong (
|
|||
|
IN PVOID State,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
);
|
|||
|
|
|||
|
ULONG HalpPCIReadUchar (
|
|||
|
IN PVOID State,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
);
|
|||
|
|
|||
|
ULONG HalpPCIReadUshort (
|
|||
|
IN PVOID State,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
);
|
|||
|
|
|||
|
ULONG HalpPCIWriteUlong (
|
|||
|
IN PVOID State,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
);
|
|||
|
|
|||
|
ULONG HalpPCIWriteUchar (
|
|||
|
IN PVOID State,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
);
|
|||
|
|
|||
|
ULONG HalpPCIWriteUshort (
|
|||
|
IN PVOID State,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
HalpPCILine2PinNop (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|||
|
IN PPCI_COMMON_CONFIG PciNewData,
|
|||
|
IN PPCI_COMMON_CONFIG PciOldData
|
|||
|
);
|
|||
|
|
|||
|
VOID
|
|||
|
HalpPCIPin2LineNop (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|||
|
IN PPCI_COMMON_CONFIG PciData
|
|||
|
);
|
|||
|
|
|||
|
#if DBG
|
|||
|
BOOLEAN
|
|||
|
HalpValidPCIAddr(
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PHYSICAL_ADDRESS BAddr,
|
|||
|
IN ULONG Length,
|
|||
|
IN ULONG AddressSpace
|
|||
|
);
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Local prototypes of functions that are not built for Alpha AXP firmware
|
|||
|
//
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpAssignPCISlotResources (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN PUNICODE_STRING RegistryPath,
|
|||
|
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
|||
|
IN ULONG Slot,
|
|||
|
IN OUT PCM_RESOURCE_LIST *pAllocatedResources
|
|||
|
);
|
|||
|
|
|||
|
#if DBG
|
|||
|
VOID
|
|||
|
HalpTestPci (
|
|||
|
ULONG
|
|||
|
);
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Pragmas to assign functions to different kinds of pages.
|
|||
|
//
|
|||
|
|
|||
|
#if !defined(AXP_FIRMWARE)
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(INIT,HalpInitializePCIBus)
|
|||
|
#pragma alloc_text(INIT,HalpAllocateAndInitPCIBusHandler)
|
|||
|
#pragma alloc_text(INIT,HalpRegisterPCIInstallHandler )
|
|||
|
#pragma alloc_text(INIT,HalpDefaultPCIInstallHandler )
|
|||
|
#pragma alloc_text(INIT,HalpDeterminePCIDevicesPresent )
|
|||
|
#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
|
|||
|
#pragma alloc_text(PAGE,HalpAdjustPCIResourceList)
|
|||
|
#endif // ALLOC_PRAGMA
|
|||
|
#endif // !defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
#ifdef AXP_FIRMWARE
|
|||
|
|
|||
|
#define ExFreePool(PoolData)
|
|||
|
|
|||
|
#pragma alloc_text(DISTEXT, HalpInitializePCIBus )
|
|||
|
#pragma alloc_text(DISTEXT, HalpAllocateAndInitPCIBusHandler)
|
|||
|
#pragma alloc_text(DISTEXT, HalpRegisterPCIInstallHandler )
|
|||
|
#pragma alloc_text(DISTEXT, HalpDefaultPCIInstallHandler )
|
|||
|
#pragma alloc_text(DISTEXT, HalpDeterminePCIDevicesPresent )
|
|||
|
#pragma alloc_text(DISTEXT, HalpGetPCIData )
|
|||
|
#pragma alloc_text(DISTEXT, HalpSetPCIData )
|
|||
|
#pragma alloc_text(DISTEXT, HalpReadPCIConfig )
|
|||
|
#pragma alloc_text(DISTEXT, HalpWritePCIConfig )
|
|||
|
#pragma alloc_text(DISTEXT, HalpValidPCISlot )
|
|||
|
#if DBG
|
|||
|
#pragma alloc_text(DISTEXT, HalpValidPCIAddr )
|
|||
|
#endif
|
|||
|
#pragma alloc_text(DISTEXT, HalpPCIConfig )
|
|||
|
#pragma alloc_text(DISTEXT, HalpPCIReadUchar )
|
|||
|
#pragma alloc_text(DISTEXT, HalpPCIReadUshort )
|
|||
|
#pragma alloc_text(DISTEXT, HalpPCIReadUlong )
|
|||
|
#pragma alloc_text(DISTEXT, HalpPCIWriteUchar )
|
|||
|
#pragma alloc_text(DISTEXT, HalpPCIWriteUshort )
|
|||
|
#pragma alloc_text(DISTEXT, HalpPCIWriteUlong )
|
|||
|
#pragma alloc_text(DISTEXT, HalpAssignPCISlotResources)
|
|||
|
#pragma alloc_text(DISTEXT, HalpAdjustPCIResourceList)
|
|||
|
|
|||
|
#endif // AXP_FIRMWARE
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Globals
|
|||
|
//
|
|||
|
|
|||
|
KSPIN_LOCK HalpPCIConfigLock;
|
|||
|
BOOLEAN PCIInitialized = FALSE;
|
|||
|
ULONG PCIMaxLocalDevice;
|
|||
|
ULONG PCIMaxDevice;
|
|||
|
ULONG PCIMaxBus;
|
|||
|
PINSTALL_BUS_HANDLER PCIInstallHandler = HalpDefaultPCIInstallHandler;
|
|||
|
|
|||
|
CONFIG_HANDLER PCIConfigHandlers = {
|
|||
|
{
|
|||
|
HalpPCIReadUlong, // 0
|
|||
|
HalpPCIReadUchar, // 1
|
|||
|
HalpPCIReadUshort // 2
|
|||
|
},
|
|||
|
{
|
|||
|
HalpPCIWriteUlong, // 0
|
|||
|
HalpPCIWriteUchar, // 1
|
|||
|
HalpPCIWriteUshort // 2
|
|||
|
}
|
|||
|
};
|
|||
|
UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
|
|||
|
|
|||
|
WCHAR rgzMultiFunctionAdapter[] = L"\\Registry\\Machine\\Hardware\\Description\\System\\MultifunctionAdapter";
|
|||
|
WCHAR rgzConfigurationData[] = L"Configuration Data";
|
|||
|
WCHAR rgzIdentifier[] = L"Identifier";
|
|||
|
WCHAR rgzPCIIndetifier[] = L"PCI";
|
|||
|
|
|||
|
#define Is64BitBaseAddress(a) \
|
|||
|
(((a & PCI_ADDRESS_IO_SPACE) == 0) && \
|
|||
|
((a & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
|
|||
|
|
|||
|
#if !defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
VOID
|
|||
|
HalpRegisterPciBus(
|
|||
|
IN PCONFIGURATION_COMPONENT Component,
|
|||
|
IN PVOID ConfigurationData
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function uses information obtained from the ARC configuration
|
|||
|
tree to create PCI bus handlers. If configuration data was passed
|
|||
|
with the PCI component, then that information is used to create the
|
|||
|
bus handler. Otherwise, we use a priori knowledge (and bus scanning)
|
|||
|
to generate the bus handler data. This function supports firmware
|
|||
|
that both provide and do not provide configuration data payloads.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Component - The ARC configuration component for this bus.
|
|||
|
|
|||
|
ConfigurationData - The configuration data payload (or NULL).
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOLEAN ConfigurationDataPresent;
|
|||
|
ARC_PCI_CONFIGURATION ArcPciConfiguration;
|
|||
|
ULONG BusNumber;
|
|||
|
ULONG HwBusNumber;
|
|||
|
BOOLEAN BusIsAcrossPPB;
|
|||
|
PBUS_HANDLER BusHandler;
|
|||
|
PPCIPBUSDATA BusData;
|
|||
|
RTL_BITMAP DevicePresent;
|
|||
|
PCI_SLOT_NUMBER SlotNumber;
|
|||
|
ULONG DeviceNumber;
|
|||
|
ULONG FunctionNumber;
|
|||
|
PCI_COMMON_CONFIG CommonConfig;
|
|||
|
PCI_SLOT_NUMBER Dummy;
|
|||
|
|
|||
|
memset(&Dummy, 0, sizeof(PCI_SLOT_NUMBER) );
|
|||
|
|
|||
|
//
|
|||
|
// Ascertain whether the ARC firmware provided configuration data as part
|
|||
|
// of the multi-function adapter component.
|
|||
|
//
|
|||
|
|
|||
|
ConfigurationDataPresent = Component->ConfigurationDataLength != 0;
|
|||
|
|
|||
|
//
|
|||
|
// If configuration data was provided use it to allocate and initialize
|
|||
|
// the handler for this bus. Otherwise, use a priori knowledge to
|
|||
|
// generate reasonable values.
|
|||
|
//
|
|||
|
|
|||
|
if (ConfigurationDataPresent) {
|
|||
|
|
|||
|
//
|
|||
|
// Copy the configuration data from the component.
|
|||
|
//
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
&ArcPciConfiguration,
|
|||
|
ConfigurationData,
|
|||
|
sizeof (ARC_PCI_CONFIGURATION)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Use the values provided.
|
|||
|
//
|
|||
|
|
|||
|
BusNumber = ArcPciConfiguration.BusNumber;
|
|||
|
HwBusNumber = ArcPciConfiguration.HwBusNumber;
|
|||
|
BusIsAcrossPPB = ArcPciConfiguration.BusIsAcrossPPB;
|
|||
|
|
|||
|
//
|
|||
|
// Despite its name, PCIMaxBus is really the number of busses present
|
|||
|
// in the system.
|
|||
|
//
|
|||
|
|
|||
|
if (PCIMaxBus < BusNumber + 1) {
|
|||
|
PCIMaxBus = BusNumber + 1;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// PCIMaxBus keeps a running count of the number of busses seen up
|
|||
|
// to this point. Use the current value as the bus number and advance
|
|||
|
// the counter. Set HwBusNumber and BusIsAcrossPPB to reasonable
|
|||
|
// values.
|
|||
|
//
|
|||
|
|
|||
|
BusNumber = PCIMaxBus++;
|
|||
|
HwBusNumber = 0;
|
|||
|
BusIsAcrossPPB = BusNumber != 0;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Allocate and initialize the handler for this bus. N.B. device-present
|
|||
|
// checking is disabled at this point. We will enable it below.
|
|||
|
//
|
|||
|
|
|||
|
BusHandler = HalpAllocateAndInitPCIBusHandler(
|
|||
|
BusNumber,
|
|||
|
HwBusNumber,
|
|||
|
BusIsAcrossPPB,
|
|||
|
0, // MS here
|
|||
|
Dummy // MS here
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Get a pointer to the bus-specific data.
|
|||
|
//
|
|||
|
|
|||
|
BusData = (PPCIPBUSDATA)BusHandler->BusData;
|
|||
|
|
|||
|
//
|
|||
|
// Compute the device-present bitmap for this bus. If configuration
|
|||
|
// data is present then the bitmap has been pre-computed for us by the
|
|||
|
// firmware. In this case, use the bitmap provided. otherwise, we
|
|||
|
// have to do the work now of generating the bitmap.
|
|||
|
//
|
|||
|
|
|||
|
if (ConfigurationDataPresent) {
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the device-present bitmap for this bus.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitializeBitMap(
|
|||
|
&BusData->DevicePresent,
|
|||
|
BusData->DevicePresentBits,
|
|||
|
PCI_MAX_DEVICES * PCI_MAX_FUNCTION
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// The firmware has already computed the device-present bitmap for
|
|||
|
// us. Copy the bitmap from the configuration data.
|
|||
|
//
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
BusData->DevicePresentBits,
|
|||
|
ArcPciConfiguration.DevicePresentBits,
|
|||
|
sizeof (BusData->DevicePresentBits)
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Initialize a bitmap which we will use to accumulate the results
|
|||
|
// of the device-present scan. N.B. Device-present checking is
|
|||
|
// currently disabled.
|
|||
|
//
|
|||
|
|
|||
|
RtlInitializeBitMap(
|
|||
|
&DevicePresent,
|
|||
|
BusData->DevicePresentBits,
|
|||
|
PCI_MAX_DEVICES * PCI_MAX_FUNCTION
|
|||
|
);
|
|||
|
|
|||
|
RtlClearBits(
|
|||
|
&DevicePresent,
|
|||
|
0,
|
|||
|
PCI_MAX_DEVICES * PCI_MAX_FUNCTION
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the slot number.
|
|||
|
//
|
|||
|
|
|||
|
SlotNumber.u.AsULONG = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Loop through each device number.
|
|||
|
//
|
|||
|
|
|||
|
for (DeviceNumber = 0;
|
|||
|
DeviceNumber < PCI_MAX_DEVICES;
|
|||
|
DeviceNumber++) {
|
|||
|
|
|||
|
SlotNumber.u.bits.DeviceNumber = DeviceNumber;
|
|||
|
|
|||
|
//
|
|||
|
// Loop through each function number.
|
|||
|
//
|
|||
|
|
|||
|
for (FunctionNumber = 0;
|
|||
|
FunctionNumber < PCI_MAX_FUNCTION;
|
|||
|
FunctionNumber++) {
|
|||
|
|
|||
|
SlotNumber.u.bits.FunctionNumber = FunctionNumber;
|
|||
|
|
|||
|
//
|
|||
|
// Read the common configuration header.
|
|||
|
//
|
|||
|
|
|||
|
HalpReadPCIConfig(
|
|||
|
BusHandler,
|
|||
|
SlotNumber,
|
|||
|
&CommonConfig,
|
|||
|
0,
|
|||
|
PCI_COMMON_HDR_LENGTH
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If the Vendor ID is invalid, then no device is present
|
|||
|
// at this device/function number.
|
|||
|
//
|
|||
|
|
|||
|
if (CommonConfig.VendorID == PCI_INVALID_VENDORID) {
|
|||
|
if (FunctionNumber == 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Set a bit indicating a device is present.
|
|||
|
//
|
|||
|
|
|||
|
RtlSetBits(
|
|||
|
&DevicePresent,
|
|||
|
PciBitIndex(DeviceNumber, FunctionNumber),
|
|||
|
1
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If this is not a multi-function device, then terminate
|
|||
|
// the function number loop.
|
|||
|
//
|
|||
|
|
|||
|
if ((CommonConfig.HeaderType & PCI_MULTIFUNCTION) == 0) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Enable device-present checking.
|
|||
|
//
|
|||
|
|
|||
|
BusData->DevicePresent = DevicePresent;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
#if !defined(AXP_FIRMWARE)
|
|||
|
|
|||
|
VOID
|
|||
|
HalpQueryPciBusConfiguration(
|
|||
|
IN PCONFIGURATION_COMPONENT_DATA Root
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function loops through each multi-function adapter component
|
|||
|
in the ARC configuration tree and calls HalpRegisterPciBus() to create
|
|||
|
a bus handler for it.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Root - The root of the ARC configuration tree.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ULONG Key;
|
|||
|
PCONFIGURATION_COMPONENT_DATA Adapter;
|
|||
|
|
|||
|
//
|
|||
|
// Loop through each multi-function adapter component in the ARC
|
|||
|
// configuration tree.
|
|||
|
//
|
|||
|
|
|||
|
for (Key = 0; TRUE; Key++) {
|
|||
|
|
|||
|
//
|
|||
|
// Get a pointer to the component data.
|
|||
|
//
|
|||
|
|
|||
|
Adapter = KeFindConfigurationEntry(
|
|||
|
Root,
|
|||
|
AdapterClass,
|
|||
|
MultiFunctionAdapter,
|
|||
|
&Key
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// If there are no more multi-function adapters in the ARC
|
|||
|
// configuration tree, then we're done.
|
|||
|
//
|
|||
|
|
|||
|
if (Adapter == NULL) {
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Ascertain whether this is a PCI multi-function adapter component.
|
|||
|
// If so, register a bus handler for it.
|
|||
|
//
|
|||
|
|
|||
|
if (_stricmp(Adapter->ComponentEntry.Identifier, "PCI") == 0) {
|
|||
|
HalpRegisterPciBus(
|
|||
|
&Adapter->ComponentEntry,
|
|||
|
Adapter->ConfigurationData
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
VOID
|
|||
|
HalpInitializePCIBus(
|
|||
|
IN PLOADER_PARAMETER_BLOCK LoaderBlock
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function intializes global PCI bus state from the registry.
|
|||
|
|
|||
|
The Arc firmware is responsible for building configuration information
|
|||
|
about the number of PCI buses on the system and nature (local vs. secondary
|
|||
|
- across a PCI-PCI bridge) of the each bus.
|
|||
|
|
|||
|
The maximum virtual slot number on the local (type 0 config cycle)
|
|||
|
PCI bus is registered here, based on the machine dependent define
|
|||
|
PCI_MAX_LOCAL_DEVICE. This state is carried in PCIMaxLocalDevice.
|
|||
|
|
|||
|
The maximum number of virtual slots on a secondary bus is fixed by the
|
|||
|
PCI Specification and is represented by PCI_MAX_DEVICES. This
|
|||
|
state is held in PCIMaxDevice.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
//
|
|||
|
// Only initialize the PCI subsystem once.
|
|||
|
//
|
|||
|
|
|||
|
if (PCIInitialized) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize PCI subsystem variables.
|
|||
|
//
|
|||
|
|
|||
|
#ifdef AXP_FIRMWARE
|
|||
|
PCIMaxBus = PCI_MAX_BUSSES;
|
|||
|
#else
|
|||
|
PCIMaxBus = 0;
|
|||
|
#endif
|
|||
|
PCIMaxLocalDevice = PCI_MAX_LOCAL_DEVICE;
|
|||
|
PCIMaxDevice = PCI_MAX_DEVICES - 1;
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the PCI configuration spinlock.
|
|||
|
//
|
|||
|
|
|||
|
KeInitializeSpinLock(&HalpPCIConfigLock);
|
|||
|
|
|||
|
#if !AXP_FIRMWARE
|
|||
|
|
|||
|
//
|
|||
|
// Consult the ARC configuration tree and register bus handlers for
|
|||
|
// all PCI multi-function adapter nodes.
|
|||
|
//
|
|||
|
|
|||
|
HalpQueryPciBusConfiguration(LoaderBlock->ConfigurationRoot);
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// The PCI subsystem has been initialized.
|
|||
|
//
|
|||
|
|
|||
|
PCIInitialized = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
PBUS_HANDLER
|
|||
|
HalpAllocateAndInitPCIBusHandler (
|
|||
|
IN ULONG BusNo,
|
|||
|
IN ULONG HwBusNo,
|
|||
|
IN BOOLEAN BusIsAcrossPPB,
|
|||
|
IN ULONG PPBBusNumber,
|
|||
|
IN PCI_SLOT_NUMBER PPBSlotNumber
|
|||
|
)
|
|||
|
{
|
|||
|
PBUS_HANDLER Bus;
|
|||
|
PPCIPBUSDATA BusData;
|
|||
|
|
|||
|
HaliRegisterBusHandler (
|
|||
|
PCIBus, // Interface type
|
|||
|
PCIConfiguration, // Has this configuration space
|
|||
|
BusNo, // Bus Number
|
|||
|
Internal, // child of this bus
|
|||
|
0, // and number
|
|||
|
sizeof (PCIPBUSDATA), // sizeof bus specific buffer
|
|||
|
PCIInstallHandler, // PCI install handler
|
|||
|
&Bus); // Bushandler return
|
|||
|
|
|||
|
BusData = (PPCIPBUSDATA) Bus->BusData;
|
|||
|
BusData->HwBusNumber = HwBusNo;
|
|||
|
BusData->BusIsAcrossPPB = BusIsAcrossPPB;
|
|||
|
BusData->PPBBusNumber = PPBBusNumber;
|
|||
|
BusData->PPBSlotNumber = PPBSlotNumber;
|
|||
|
|
|||
|
return Bus;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpDefaultPCIInstallHandler(
|
|||
|
IN PBUS_HANDLER Bus
|
|||
|
)
|
|||
|
{
|
|||
|
PPCIPBUSDATA BusData;
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Fill in PCI handlers
|
|||
|
//
|
|||
|
|
|||
|
Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
|
|||
|
Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
|
|||
|
Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
|
|||
|
Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
|
|||
|
|
|||
|
BusData = (PPCIPBUSDATA) Bus->BusData;
|
|||
|
|
|||
|
//
|
|||
|
// Fill in common PCI data
|
|||
|
//
|
|||
|
|
|||
|
BusData->CommonData.Tag = PCI_DATA_TAG;
|
|||
|
BusData->CommonData.Version = PCI_DATA_VERSION;
|
|||
|
BusData->CommonData.ReadConfig = (PciReadWriteConfig)HalpReadPCIConfig;
|
|||
|
BusData->CommonData.WriteConfig = (PciReadWriteConfig)HalpWritePCIConfig;
|
|||
|
BusData->CommonData.Pin2Line = (PciPin2Line)HalpPCIPin2LineNop;
|
|||
|
BusData->CommonData.Line2Pin = (PciLine2Pin)HalpPCILine2PinNop;
|
|||
|
|
|||
|
|
|||
|
// set defaults
|
|||
|
//
|
|||
|
// ecrfix - if we knew more about the PCI bus at this
|
|||
|
// point (e.g., local vs. across bridge, PCI config
|
|||
|
// space base QVA, APECS vs. Sable T2/T4 vs. LCA4 vs. ??? config
|
|||
|
// cycle type 0 mechanism), we could put this info into
|
|||
|
// the "BusData" structure. The nice thing about this is
|
|||
|
// that we could eliminate the platform-dependent module
|
|||
|
// PCIBUS.C.
|
|||
|
//
|
|||
|
|
|||
|
BusData->MaxDevice = PCI_MAX_DEVICES - 1; // not currently used anywhere
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpRegisterPCIInstallHandler(
|
|||
|
IN PINSTALL_BUS_HANDLER MachineSpecificPCIInstallHandler
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function register's a machine-specific PCI Install Handler.
|
|||
|
This allows a specific platform to override the default PCI install
|
|||
|
handler, DefaultPCIInstallHandler().
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
MachineSpecificPCIInstallHandler - Function that provides machine
|
|||
|
specific PCI Bus Handler setup.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PCIInstallHandler = MachineSpecificPCIInstallHandler;
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpGetPCIData (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN ULONG Slot,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function returns the PCI bus data for a device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusHandler - Registered BUS_HANDLER for the target configuration space
|
|||
|
|
|||
|
RootHandler - Register BUS_HANDLER for the orginating HalGetBusData request.
|
|||
|
|
|||
|
VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
|
|||
|
|
|||
|
Buffer - Supplies the space to store the data.
|
|||
|
|
|||
|
Length - Supplies a count in bytes of the maximum amount to return.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the amount of data stored into the buffer.
|
|||
|
|
|||
|
If this PCI slot has never been set, then the configuration information
|
|||
|
returned is zeroed.
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PPCI_COMMON_CONFIG PciData;
|
|||
|
UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
|
|||
|
ULONG Len;
|
|||
|
PCI_SLOT_NUMBER PciSlot;
|
|||
|
|
|||
|
|
|||
|
if (Length > sizeof (PCI_COMMON_CONFIG)) {
|
|||
|
Length = sizeof (PCI_COMMON_CONFIG);
|
|||
|
}
|
|||
|
|
|||
|
Len = 0;
|
|||
|
PciData = (PPCI_COMMON_CONFIG) iBuffer;
|
|||
|
PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
|
|||
|
|
|||
|
if (Offset >= PCI_COMMON_HDR_LENGTH) {
|
|||
|
//
|
|||
|
// The user did not request any data from the common
|
|||
|
// header. Verify the PCI device exists, then continue
|
|||
|
// in the device specific area.
|
|||
|
//
|
|||
|
|
|||
|
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
|
|||
|
|
|||
|
//
|
|||
|
// Check for invalid slot
|
|||
|
//
|
|||
|
|
|||
|
if (PciData->VendorID == PCI_INVALID_VENDORID) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Caller requested at least some data within the
|
|||
|
// common header. Read the whole header, effect the
|
|||
|
// fields we need to and then copy the user's requested
|
|||
|
// bytes from the header
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Read this PCI devices slot data
|
|||
|
//
|
|||
|
|
|||
|
Len = PCI_COMMON_HDR_LENGTH;
|
|||
|
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
|
|||
|
|
|||
|
//
|
|||
|
// Check for invalid slot
|
|||
|
//
|
|||
|
|
|||
|
if (PciData->VendorID == PCI_INVALID_VENDORID) {
|
|||
|
PciData->VendorID = PCI_INVALID_VENDORID;
|
|||
|
Len = 2; // only return invalid id
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy whatever data overlaps into the callers buffer
|
|||
|
//
|
|||
|
|
|||
|
if (Len < Offset) {
|
|||
|
// no data at caller's buffer
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
Len -= Offset;
|
|||
|
if (Len > Length) {
|
|||
|
Len = Length;
|
|||
|
}
|
|||
|
|
|||
|
RtlMoveMemory(Buffer, iBuffer + Offset, Len);
|
|||
|
|
|||
|
Offset += Len;
|
|||
|
Buffer += Len;
|
|||
|
Length -= Len;
|
|||
|
}
|
|||
|
|
|||
|
if (Length) {
|
|||
|
if (Offset >= PCI_COMMON_HDR_LENGTH) {
|
|||
|
//
|
|||
|
// The remaining Buffer comes from the Device Specific
|
|||
|
// area - put on the kitten gloves and read from it.
|
|||
|
//
|
|||
|
// Specific read/writes to the PCI device specific area
|
|||
|
// are guarenteed:
|
|||
|
//
|
|||
|
// Not to read/write any byte outside the area specified
|
|||
|
// by the caller. (this may cause WORD or BYTE references
|
|||
|
// to the area in order to read the non-dword aligned
|
|||
|
// ends of the request)
|
|||
|
//
|
|||
|
// To use a WORD access if the requested length is exactly
|
|||
|
// a WORD long.
|
|||
|
//
|
|||
|
// To use a BYTE access if the requested length is exactly
|
|||
|
// a BYTE long.
|
|||
|
//
|
|||
|
|
|||
|
HalpReadPCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
|
|||
|
Len += Length;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Len;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpSetPCIData (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN ULONG Slot,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function returns the Pci bus data for a device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusHandler - Registered BUS_HANDLER for the target configuration space
|
|||
|
|
|||
|
RootHandler - Register BUS_HANDLER for the orginating HalSetBusData request.
|
|||
|
|
|||
|
VendorSpecificDevice - The VendorID (low Word) and DeviceID (High Word)
|
|||
|
|
|||
|
Buffer - Supplies the space to store the data.
|
|||
|
|
|||
|
Length - Supplies a count in bytes of the maximum amount to return.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Returns the amount of data stored into the buffer.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PPCI_COMMON_CONFIG PciData, PciData2;
|
|||
|
UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
|
|||
|
UCHAR iBuffer2[PCI_COMMON_HDR_LENGTH];
|
|||
|
ULONG Len;
|
|||
|
PCI_SLOT_NUMBER PciSlot;
|
|||
|
|
|||
|
|
|||
|
if (Length > sizeof (PCI_COMMON_CONFIG)) {
|
|||
|
Length = sizeof (PCI_COMMON_CONFIG);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
Len = 0;
|
|||
|
PciData = (PPCI_COMMON_CONFIG) iBuffer;
|
|||
|
PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
|
|||
|
PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
|
|||
|
|
|||
|
|
|||
|
if (Offset >= PCI_COMMON_HDR_LENGTH) {
|
|||
|
//
|
|||
|
// The user did not request any data from the common
|
|||
|
// header. Verify the PCI device exists, then continue in
|
|||
|
// the device specific area.
|
|||
|
//
|
|||
|
|
|||
|
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, sizeof(ULONG));
|
|||
|
|
|||
|
if (PciData->VendorID == PCI_INVALID_VENDORID ||
|
|||
|
PciData->VendorID == 0x00) {
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
//
|
|||
|
// Caller requested to set at least some data within the
|
|||
|
// common header.
|
|||
|
//
|
|||
|
|
|||
|
Len = PCI_COMMON_HDR_LENGTH;
|
|||
|
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, Len);
|
|||
|
if (PciData->VendorID == PCI_INVALID_VENDORID ||
|
|||
|
PciData->VendorID == 0x00) {
|
|||
|
|
|||
|
// no device
|
|||
|
return 0;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy COMMON_HDR values to buffer2, then overlay callers changes.
|
|||
|
//
|
|||
|
|
|||
|
RtlMoveMemory (iBuffer2, iBuffer, Len);
|
|||
|
|
|||
|
Len -= Offset;
|
|||
|
if (Len > Length) {
|
|||
|
Len = Length;
|
|||
|
}
|
|||
|
|
|||
|
RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
|
|||
|
|
|||
|
#if DBG
|
|||
|
//
|
|||
|
// Verify R/O fields haven't changed
|
|||
|
//
|
|||
|
if (PciData2->VendorID != PciData->VendorID ||
|
|||
|
PciData2->DeviceID != PciData->DeviceID ||
|
|||
|
PciData2->RevisionID != PciData->RevisionID ||
|
|||
|
PciData2->ProgIf != PciData->ProgIf ||
|
|||
|
PciData2->SubClass != PciData->SubClass ||
|
|||
|
PciData2->BaseClass != PciData->BaseClass ||
|
|||
|
PciData2->HeaderType != PciData->HeaderType ||
|
|||
|
PciData2->BaseClass != PciData->BaseClass ||
|
|||
|
PciData2->u.type0.MinimumGrant != PciData->u.type0.MinimumGrant ||
|
|||
|
PciData2->u.type0.MaximumLatency != PciData->u.type0.MaximumLatency) {
|
|||
|
DbgPrint ("PCI SetBusData: Read-Only configation value changed\n");
|
|||
|
DbgBreakPoint ();
|
|||
|
}
|
|||
|
#endif // DBG
|
|||
|
//
|
|||
|
// Set new PCI configuration
|
|||
|
//
|
|||
|
|
|||
|
HalpWritePCIConfig (BusHandler, PciSlot, iBuffer2+Offset, Offset, Len);
|
|||
|
|
|||
|
Offset += Len;
|
|||
|
Buffer += Len;
|
|||
|
Length -= Len;
|
|||
|
}
|
|||
|
|
|||
|
if (Length) {
|
|||
|
|
|||
|
if (Offset >= PCI_COMMON_HDR_LENGTH) {
|
|||
|
//
|
|||
|
// The remaining Buffer comes from the Device Specific
|
|||
|
// area - put on the kitten gloves and write it
|
|||
|
//
|
|||
|
// Specific read/writes to the PCI device specific area
|
|||
|
// are guarenteed:
|
|||
|
//
|
|||
|
// Not to read/write any byte outside the area specified
|
|||
|
// by the caller. (this may cause WORD or BYTE references
|
|||
|
// to the area in order to read the non-dword aligned
|
|||
|
// ends of the request)
|
|||
|
//
|
|||
|
// To use a WORD access if the requested length is exactly
|
|||
|
// a WORD long.
|
|||
|
//
|
|||
|
// To use a BYTE access if the requested length is exactly
|
|||
|
// a BYTE long.
|
|||
|
//
|
|||
|
|
|||
|
HalpWritePCIConfig (BusHandler, PciSlot, Buffer, Offset, Length);
|
|||
|
Len += Length;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return Len;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpPCILine2PinNop (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|||
|
IN PPCI_COMMON_CONFIG PciNewData,
|
|||
|
IN PPCI_COMMON_CONFIG PciOldData
|
|||
|
)
|
|||
|
{
|
|||
|
// line-pin mappings not needed on alpha machines
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpPCIPin2LineNop (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN PCI_SLOT_NUMBER SlotNumber,
|
|||
|
IN PPCI_COMMON_CONFIG PciData
|
|||
|
)
|
|||
|
{
|
|||
|
// line-pin mappings not needed on alpha machines
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpReadPCIConfig (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
{
|
|||
|
#if 0
|
|||
|
if (!HalpValidPCISlot (BusHandler, Slot)) {
|
|||
|
//
|
|||
|
// Invalid SlotID return no data
|
|||
|
//
|
|||
|
|
|||
|
RtlFillMemory (Buffer, Length, (UCHAR) -1);
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
|
|||
|
PCIConfigHandlers.ConfigRead);
|
|||
|
#endif // 0
|
|||
|
|
|||
|
//
|
|||
|
// Read the slot, if it's valid.
|
|||
|
// Otherwise, return an Invalid VendorId for a invalid slot on an existing bus
|
|||
|
// or a null (zero) buffer if we have a non-existant bus.
|
|||
|
//
|
|||
|
|
|||
|
switch (HalpValidPCISlot (BusHandler, Slot))
|
|||
|
{
|
|||
|
|
|||
|
case ValidSlot:
|
|||
|
|
|||
|
HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
|
|||
|
PCIConfigHandlers.ConfigRead);
|
|||
|
break;
|
|||
|
|
|||
|
case InvalidSlot:
|
|||
|
|
|||
|
//
|
|||
|
// Invalid SlotID return no data (Invalid Slot ID = 0xFFFF)
|
|||
|
//
|
|||
|
|
|||
|
RtlFillMemory (Buffer, Length, (UCHAR) -1);
|
|||
|
break ;
|
|||
|
|
|||
|
case InvalidBus:
|
|||
|
|
|||
|
//
|
|||
|
// Invalid Bus, return return no data
|
|||
|
//
|
|||
|
|
|||
|
RtlFillMemory (Buffer, Length, (UCHAR) 0);
|
|||
|
break ;
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpWritePCIConfig (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot,
|
|||
|
IN PVOID Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length
|
|||
|
)
|
|||
|
{
|
|||
|
|
|||
|
if (HalpValidPCISlot (BusHandler, Slot) != ValidSlot) {
|
|||
|
//
|
|||
|
// Invalid SlotID do nothing
|
|||
|
//
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
|
|||
|
PCIConfigHandlers.ConfigWrite);
|
|||
|
}
|
|||
|
|
|||
|
VALID_SLOT
|
|||
|
HalpValidPCISlot (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG BusNumber;
|
|||
|
PPCIPBUSDATA BusData;
|
|||
|
PCI_SLOT_NUMBER Slot2;
|
|||
|
PCI_CONFIGURATION_TYPES PciConfigType;
|
|||
|
UCHAR HeaderType;
|
|||
|
ULONG i, bit;
|
|||
|
|
|||
|
BusNumber = BusHandler->BusNumber;
|
|||
|
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
|||
|
|
|||
|
if (Slot.u.bits.Reserved != 0) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the initial device probe has been completed and no device
|
|||
|
// is present for this slot then simply return invalid slot.
|
|||
|
//
|
|||
|
|
|||
|
bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
|
|||
|
|
|||
|
if( ( (BusData->DevicePresent).Buffer != NULL) &&
|
|||
|
!RtlCheckBit(&BusData->DevicePresent, bit) ) {
|
|||
|
|
|||
|
return InvalidSlot;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Get the config cycle type for the proposed bus.
|
|||
|
// (PciConfigTypeInvalid indicates a non-existent bus.)
|
|||
|
//
|
|||
|
|
|||
|
PciConfigType = HalpPCIConfigCycleType(BusHandler);
|
|||
|
|
|||
|
//
|
|||
|
// The number of devices allowed on a local PCI bus may be different
|
|||
|
// than that across a PCI-PCI bridge.
|
|||
|
//
|
|||
|
|
|||
|
switch(PciConfigType) {
|
|||
|
case PciConfigType0:
|
|||
|
|
|||
|
if (Slot.u.bits.DeviceNumber > PCIMaxLocalDevice) {
|
|||
|
#if HALDBG
|
|||
|
DbgPrint("Invalid local PCI Slot %x\n", Slot.u.bits.DeviceNumber);
|
|||
|
#endif
|
|||
|
return InvalidSlot;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case PciConfigType1:
|
|||
|
|
|||
|
if (Slot.u.bits.DeviceNumber > PCIMaxDevice) {
|
|||
|
#if HALDBG
|
|||
|
DbgPrint("Invalid remote PCI Slot %x\n", Slot.u.bits.DeviceNumber);
|
|||
|
#endif
|
|||
|
return InvalidSlot;
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case PciConfigTypeInvalid:
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
DbgPrint("Invalid PCI Bus %x\n", BusNumber);
|
|||
|
#endif
|
|||
|
return InvalidBus;
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check function number
|
|||
|
//
|
|||
|
|
|||
|
if (Slot.u.bits.FunctionNumber == 0) {
|
|||
|
return ValidSlot;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Non zero function numbers are only supported if the
|
|||
|
// device has the PCI_MULTIFUNCTION bit set in it's header
|
|||
|
//
|
|||
|
|
|||
|
i = Slot.u.bits.DeviceNumber;
|
|||
|
|
|||
|
//
|
|||
|
// Read DeviceNumber, Function zero, to determine if the
|
|||
|
// PCI supports multifunction devices
|
|||
|
//
|
|||
|
|
|||
|
Slot2 = Slot;
|
|||
|
Slot2.u.bits.FunctionNumber = 0;
|
|||
|
|
|||
|
HalpReadPCIConfig (
|
|||
|
BusHandler,
|
|||
|
Slot2,
|
|||
|
&HeaderType,
|
|||
|
FIELD_OFFSET (PCI_COMMON_CONFIG, HeaderType),
|
|||
|
sizeof (UCHAR)
|
|||
|
);
|
|||
|
|
|||
|
if (!(HeaderType & PCI_MULTIFUNCTION) || (HeaderType == 0xFF)) {
|
|||
|
// this device doesn't exists or doesn't support MULTIFUNCTION types
|
|||
|
return InvalidSlot;
|
|||
|
}
|
|||
|
|
|||
|
return ValidSlot;
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
HalpPCIConfig (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PCI_SLOT_NUMBER Slot,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset,
|
|||
|
IN ULONG Length,
|
|||
|
IN FncConfigIO *ConfigIO
|
|||
|
)
|
|||
|
{
|
|||
|
KIRQL OldIrql;
|
|||
|
ULONG i;
|
|||
|
PCI_CFG_CYCLE_BITS PciAddr;
|
|||
|
ULONG BusNumber;
|
|||
|
|
|||
|
//
|
|||
|
// Setup platform-dependent state for configuration space access
|
|||
|
//
|
|||
|
|
|||
|
HalpPCIConfigAddr(BusHandler, Slot, &PciAddr);
|
|||
|
|
|||
|
//
|
|||
|
// Synchronize with PCI config space
|
|||
|
//
|
|||
|
|
|||
|
KeAcquireSpinLock (&HalpPCIConfigLock, &OldIrql);
|
|||
|
|
|||
|
//
|
|||
|
// Do the I/O to PCI configuration space
|
|||
|
//
|
|||
|
|
|||
|
while (Length) {
|
|||
|
i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
|
|||
|
i = ConfigIO[i] (&PciAddr, Buffer, Offset);
|
|||
|
|
|||
|
Offset += i;
|
|||
|
Buffer += i;
|
|||
|
Length -= i;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Release spinlock
|
|||
|
//
|
|||
|
|
|||
|
KeReleaseSpinLock (&HalpPCIConfigLock, OldIrql);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpPCIReadUchar (
|
|||
|
IN PPCI_CFG_CYCLE_BITS PciCfg,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG ConfigurationCycleType;
|
|||
|
|
|||
|
//
|
|||
|
// The configuration cycle type is extracted from bits[1:0] of PciCfg.
|
|||
|
//
|
|||
|
// Since an LCA4 register generates the configuration cycle type
|
|||
|
// on the PCI bus, and because Offset bits[1:0] are used to
|
|||
|
// generate the PCI byte enables (C/BE[3:0]), clear PciCfg bits [1:0]
|
|||
|
// out before adding in Offset.
|
|||
|
//
|
|||
|
|
|||
|
ConfigurationCycleType = PciCfg->u.bits.Reserved1;
|
|||
|
PciCfg->u.bits.Reserved1 = 0;
|
|||
|
|
|||
|
*Buffer = READ_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset),
|
|||
|
ConfigurationCycleType);
|
|||
|
|
|||
|
//
|
|||
|
// Reset state to preserve config cycle type across calls
|
|||
|
//
|
|||
|
|
|||
|
PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
|
|||
|
|
|||
|
return sizeof (UCHAR);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpPCIReadUshort (
|
|||
|
IN PPCI_CFG_CYCLE_BITS PciCfg,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG ConfigurationCycleType;
|
|||
|
|
|||
|
ConfigurationCycleType = PciCfg->u.bits.Reserved1;
|
|||
|
PciCfg->u.bits.Reserved1 = 0;
|
|||
|
|
|||
|
*((PUSHORT) Buffer) = READ_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset),
|
|||
|
ConfigurationCycleType);
|
|||
|
//
|
|||
|
// Reset state to preserve config cycle type across calls
|
|||
|
//
|
|||
|
|
|||
|
PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
|
|||
|
|
|||
|
return sizeof (USHORT);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpPCIReadUlong (
|
|||
|
IN PPCI_CFG_CYCLE_BITS PciCfg,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG ConfigurationCycleType;
|
|||
|
|
|||
|
ConfigurationCycleType = PciCfg->u.bits.Reserved1;
|
|||
|
PciCfg->u.bits.Reserved1 = 0;
|
|||
|
|
|||
|
*((PULONG) Buffer) = READ_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset),
|
|||
|
ConfigurationCycleType);
|
|||
|
//
|
|||
|
// Reset state to preserve config cycle type across calls
|
|||
|
//
|
|||
|
|
|||
|
PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
|
|||
|
|
|||
|
return sizeof (ULONG);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpPCIWriteUchar (
|
|||
|
IN PPCI_CFG_CYCLE_BITS PciCfg,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG ConfigurationCycleType;
|
|||
|
|
|||
|
ConfigurationCycleType = PciCfg->u.bits.Reserved1;
|
|||
|
PciCfg->u.bits.Reserved1 = 0;
|
|||
|
|
|||
|
WRITE_CONFIG_UCHAR ((PUCHAR) (PciCfg->u.AsULONG + Offset), *Buffer,
|
|||
|
ConfigurationCycleType);
|
|||
|
//
|
|||
|
// Reset state to preserve config cycle type across calls
|
|||
|
//
|
|||
|
|
|||
|
PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
|
|||
|
|
|||
|
return sizeof (UCHAR);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpPCIWriteUshort (
|
|||
|
IN PPCI_CFG_CYCLE_BITS PciCfg,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG ConfigurationCycleType;
|
|||
|
|
|||
|
ConfigurationCycleType = PciCfg->u.bits.Reserved1;
|
|||
|
PciCfg->u.bits.Reserved1 = 0;
|
|||
|
|
|||
|
WRITE_CONFIG_USHORT ((PUSHORT) (PciCfg->u.AsULONG + Offset), *((PUSHORT) Buffer),
|
|||
|
ConfigurationCycleType);
|
|||
|
//
|
|||
|
// Reset state to preserve config cycle type across calls
|
|||
|
//
|
|||
|
|
|||
|
PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
|
|||
|
|
|||
|
return sizeof (USHORT);
|
|||
|
}
|
|||
|
|
|||
|
ULONG
|
|||
|
HalpPCIWriteUlong (
|
|||
|
IN PPCI_CFG_CYCLE_BITS PciCfg,
|
|||
|
IN PUCHAR Buffer,
|
|||
|
IN ULONG Offset
|
|||
|
)
|
|||
|
{
|
|||
|
ULONG ConfigurationCycleType;
|
|||
|
|
|||
|
ConfigurationCycleType = PciCfg->u.bits.Reserved1;
|
|||
|
PciCfg->u.bits.Reserved1 = 0;
|
|||
|
|
|||
|
WRITE_CONFIG_ULONG ((PULONG) (PciCfg->u.AsULONG + Offset), *((PULONG) Buffer),
|
|||
|
ConfigurationCycleType);
|
|||
|
//
|
|||
|
// Reset state to preserve config cycle type across calls
|
|||
|
//
|
|||
|
|
|||
|
PciCfg->u.bits.Reserved1 = ConfigurationCycleType;
|
|||
|
|
|||
|
return sizeof (ULONG);
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
HalpValidPCIAddr(
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PHYSICAL_ADDRESS BAddr,
|
|||
|
IN ULONG Length,
|
|||
|
IN ULONG AddressSpace)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Checks to see that the begining and ending 64 bit PCI bus addresses
|
|||
|
of the 32 bit range of length Length are supported on the system.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BAddr - the 64 bit starting address
|
|||
|
|
|||
|
Length - a 32 bit length
|
|||
|
|
|||
|
AddressSpace - is this I/O (1) or memory space (0)
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE or FALSE
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PHYSICAL_ADDRESS EAddr, TBAddr, TEAddr;
|
|||
|
LARGE_INTEGER LiILen;
|
|||
|
ULONG inIoSpace, inIoSpace2;
|
|||
|
BOOLEAN flag, flag2;
|
|||
|
ULONG BusNumber;
|
|||
|
|
|||
|
BusNumber = BusHandler->BusNumber;
|
|||
|
|
|||
|
//
|
|||
|
// Translated address to system global setting and verify
|
|||
|
// resource is available.
|
|||
|
//
|
|||
|
// Note that this code will need to be changed to support
|
|||
|
// 64 bit PCI bus addresses.
|
|||
|
//
|
|||
|
|
|||
|
LiILen.QuadPart = (ULONG)(Length - 1); // Inclusive length
|
|||
|
EAddr.QuadPart = BAddr.QuadPart + LiILen.QuadPart;
|
|||
|
|
|||
|
inIoSpace = inIoSpace2 = AddressSpace;
|
|||
|
|
|||
|
flag = HalTranslateBusAddress ( PCIBus,
|
|||
|
BusNumber,
|
|||
|
BAddr,
|
|||
|
&inIoSpace,
|
|||
|
&TBAddr
|
|||
|
);
|
|||
|
|
|||
|
flag2 = HalTranslateBusAddress (PCIBus,
|
|||
|
BusNumber,
|
|||
|
EAddr,
|
|||
|
&inIoSpace2,
|
|||
|
&TEAddr
|
|||
|
);
|
|||
|
|
|||
|
if (flag == FALSE || flag2 == FALSE || inIoSpace != inIoSpace2) {
|
|||
|
|
|||
|
//
|
|||
|
// HalAdjustResourceList should ensure that the returned range
|
|||
|
// for the bus is within the bus limits and no translation
|
|||
|
// within those limits should ever fail
|
|||
|
//
|
|||
|
|
|||
|
DbgPrint ("HalpValidPCIAddr: Error return for HalTranslateBusAddress %x.%x:%x %x.%x:%x\n",
|
|||
|
BAddr.HighPart, BAddr.LowPart, flag,
|
|||
|
EAddr.HighPart, EAddr.LowPart, flag2);
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpAssignPCISlotResources (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN PUNICODE_STRING RegistryPath,
|
|||
|
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
|||
|
IN PDRIVER_OBJECT DriverObject,
|
|||
|
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
|||
|
IN ULONG Slot,
|
|||
|
IN OUT PCM_RESOURCE_LIST *pAllocatedResources
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Reads the targeted device to determine the firmwaire-assigned resources.
|
|||
|
Calls IoReportResources to report/confirm them.
|
|||
|
Returns the assignments to the caller.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS or error
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
NTSTATUS status;
|
|||
|
PUCHAR WorkingPool;
|
|||
|
PPCI_COMMON_CONFIG PciData, PciOrigData;
|
|||
|
PCI_SLOT_NUMBER PciSlot;
|
|||
|
|
|||
|
PCM_RESOURCE_LIST CmRes;
|
|||
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDesc;
|
|||
|
PHYSICAL_ADDRESS BAddr;
|
|||
|
ULONG addr;
|
|||
|
ULONG Command;
|
|||
|
ULONG cnt, len;
|
|||
|
BOOLEAN conflict;
|
|||
|
|
|||
|
ULONG i, j, m, length, holdvalue;
|
|||
|
ULONG BusNumber;
|
|||
|
|
|||
|
BusNumber = BusHandler->BusNumber;
|
|||
|
|
|||
|
*pAllocatedResources = NULL;
|
|||
|
PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
|
|||
|
|
|||
|
//
|
|||
|
// Allocate some pool for working space
|
|||
|
//
|
|||
|
|
|||
|
i = sizeof (CM_RESOURCE_LIST) +
|
|||
|
sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
|
|||
|
PCI_COMMON_HDR_LENGTH * 2;
|
|||
|
|
|||
|
WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
|
|||
|
if (!WorkingPool) {
|
|||
|
return STATUS_NO_MEMORY;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Zero initialize pool, and get pointers into memory - here we allocate
|
|||
|
// a single chunk of memory and partition it into three pieces, pointed
|
|||
|
// to by three separate pointers.
|
|||
|
//
|
|||
|
|
|||
|
RtlZeroMemory (WorkingPool, i);
|
|||
|
CmRes = (PCM_RESOURCE_LIST) WorkingPool;
|
|||
|
PciData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
|
|||
|
PciOrigData = (PPCI_COMMON_CONFIG)(WorkingPool + i - PCI_COMMON_HDR_LENGTH);
|
|||
|
|
|||
|
//
|
|||
|
// Read the PCI device configuration
|
|||
|
//
|
|||
|
|
|||
|
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
|||
|
if (PciData->VendorID == PCI_INVALID_VENDORID || // empty slot
|
|||
|
PciData->VendorID == 0x00) { // non-existant bus
|
|||
|
ExFreePool (WorkingPool);
|
|||
|
return STATUS_NO_SUCH_DEVICE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make a copy of the devices current settings
|
|||
|
//
|
|||
|
|
|||
|
RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
|
|||
|
|
|||
|
//
|
|||
|
// Set resources to all bits on to see what type of resources
|
|||
|
// are required.
|
|||
|
//
|
|||
|
|
|||
|
for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
|
|||
|
PciData->u.type0.BaseAddresses[j] = 0xFFFFFFFF;
|
|||
|
}
|
|||
|
|
|||
|
PciData->u.type0.ROMBaseAddress = 0xFFFFFFFF;
|
|||
|
|
|||
|
PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
|
|||
|
PciData->u.type0.ROMBaseAddress &= ~PCI_ROMADDRESS_ENABLED;
|
|||
|
HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
|||
|
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
|||
|
|
|||
|
//
|
|||
|
// Build an CM_RESOURCE_LIST for the PCI device to report resources
|
|||
|
// to IoReportResourceUsage.
|
|||
|
//
|
|||
|
// This code does *not* use IoAssignoResources, as the PCI
|
|||
|
// address space resources have been previously assigned by the ARC firmware
|
|||
|
//
|
|||
|
|
|||
|
CmRes->Count = 1;
|
|||
|
CmRes->List[0].InterfaceType = PCIBus;
|
|||
|
CmRes->List[0].BusNumber = BusNumber;
|
|||
|
|
|||
|
CmRes->List[0].PartialResourceList.Count = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Set current CM_RESOURCE_LIST version and revision
|
|||
|
//
|
|||
|
|
|||
|
CmRes->List[0].PartialResourceList.Version = 0;
|
|||
|
CmRes->List[0].PartialResourceList.Revision = 0;
|
|||
|
|
|||
|
CmDesc = CmRes->List[0].PartialResourceList.PartialDescriptors;
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint ("HalAssignSlotResources: Resource List V%d.%d for slot %x:\n",
|
|||
|
CmRes->List[0].PartialResourceList.Version,
|
|||
|
CmRes->List[0].PartialResourceList.Revision,
|
|||
|
Slot);
|
|||
|
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Interrupt resource
|
|||
|
//
|
|||
|
|
|||
|
if (PciData->u.type0.InterruptPin) {
|
|||
|
|
|||
|
CmDesc->Type = CmResourceTypeInterrupt;
|
|||
|
CmDesc->ShareDisposition = CmResourceShareShared;
|
|||
|
CmDesc->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
|||
|
|
|||
|
CmDesc->u.Interrupt.Level = PciData->u.type0.InterruptLine;
|
|||
|
CmDesc->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint (" INT Level %x, Vector %x\n",
|
|||
|
CmDesc->u.Interrupt.Level, CmDesc->u.Interrupt.Vector );
|
|||
|
#endif
|
|||
|
|
|||
|
CmRes->List[0].PartialResourceList.Count++;
|
|||
|
CmDesc++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Add a memory or port resoruce for each PCI resource
|
|||
|
// (Compute the ROM address as well. Just append it to the Base
|
|||
|
// Address table.)
|
|||
|
//
|
|||
|
|
|||
|
holdvalue = PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES];
|
|||
|
PciData->u.type0.BaseAddresses[PCI_TYPE0_ADDRESSES] =
|
|||
|
PciData->u.type0.ROMBaseAddress & ~PCI_ADDRESS_IO_SPACE;
|
|||
|
|
|||
|
Command = PciOrigData->Command;
|
|||
|
for (j=0; j < PCI_TYPE0_ADDRESSES + 1; j++) {
|
|||
|
if (PciData->u.type0.BaseAddresses[j]) {
|
|||
|
addr = i = PciData->u.type0.BaseAddresses[j];
|
|||
|
|
|||
|
//
|
|||
|
// calculate the length necessary - note there is more complicated
|
|||
|
// code in the x86 HAL that probably isn't necessary
|
|||
|
//
|
|||
|
|
|||
|
length = ~(i & ~((i & 1) ? 3 : 15)) + 1;
|
|||
|
|
|||
|
//
|
|||
|
// I/O space resource
|
|||
|
//
|
|||
|
|
|||
|
if (addr & PCI_ADDRESS_IO_SPACE) {
|
|||
|
|
|||
|
CmDesc->Type = CmResourceTypePort;
|
|||
|
CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
|
|||
|
CmDesc->Flags = CM_RESOURCE_PORT_IO;
|
|||
|
|
|||
|
BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~3;
|
|||
|
BAddr.HighPart = 0;
|
|||
|
|
|||
|
#if DBG
|
|||
|
HalpValidPCIAddr(BusHandler, BAddr, length, 1); // I/O space
|
|||
|
#endif
|
|||
|
|
|||
|
CmDesc->u.Port.Start = BAddr;
|
|||
|
CmDesc->u.Port.Length = length;
|
|||
|
Command |= PCI_ENABLE_IO_SPACE;
|
|||
|
#if DBG
|
|||
|
DbgPrint (" IO Start %x:%08x, Len %x\n",
|
|||
|
CmDesc->u.Port.Start.HighPart, CmDesc->u.Port.Start.LowPart,
|
|||
|
CmDesc->u.Port.Length );
|
|||
|
#endif
|
|||
|
//
|
|||
|
// Memory space resource
|
|||
|
//
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
CmDesc->Type = CmResourceTypeMemory;
|
|||
|
CmDesc->ShareDisposition = CmResourceShareDeviceExclusive;
|
|||
|
|
|||
|
if (j == PCI_TYPE0_ADDRESSES) {
|
|||
|
// this is a ROM address
|
|||
|
if ((PciOrigData->u.type0.ROMBaseAddress & PCI_ROMADDRESS_ENABLED) == 0) {
|
|||
|
//
|
|||
|
// Ignore expansion ROMs which are not enabled by
|
|||
|
// the firmware/ROM BIOS.
|
|||
|
//
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
CmDesc->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
|
|||
|
BAddr.LowPart = PciOrigData->u.type0.ROMBaseAddress &
|
|||
|
~PCI_ROMADDRESS_ENABLED;
|
|||
|
BAddr.HighPart = 0;
|
|||
|
} else {
|
|||
|
// this is a memory space base address
|
|||
|
CmDesc->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
|
|||
|
BAddr.LowPart = PciOrigData->u.type0.BaseAddresses[j] & ~15;
|
|||
|
BAddr.HighPart = 0;
|
|||
|
}
|
|||
|
|
|||
|
#if DBG
|
|||
|
HalpValidPCIAddr(BusHandler, BAddr, length, 0); // Memory space
|
|||
|
#endif
|
|||
|
|
|||
|
CmDesc->u.Memory.Start = BAddr;
|
|||
|
CmDesc->u.Memory.Length = length;
|
|||
|
#if DBG
|
|||
|
DbgPrint (" MEM Start %x:%08x, Len %x\n",
|
|||
|
CmDesc->u.Memory.Start.HighPart, CmDesc->u.Memory.Start.LowPart,
|
|||
|
CmDesc->u.Memory.Length );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
CmRes->List[0].PartialResourceList.Count++;
|
|||
|
CmDesc++;
|
|||
|
|
|||
|
if (Is64BitBaseAddress(addr)) {
|
|||
|
// skip upper half of 64 bit address since we
|
|||
|
// only supports 32 bits PCI addresses for now.
|
|||
|
j++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Setup the resource list.
|
|||
|
// Count only the acquired resources.
|
|||
|
//
|
|||
|
|
|||
|
*pAllocatedResources = CmRes;
|
|||
|
cnt = CmRes->List[0].PartialResourceList.Count;
|
|||
|
len = sizeof (CM_RESOURCE_LIST) +
|
|||
|
cnt * sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint("HalAssignSlotResources: Acq. Resourses = %d (len %x list %x\n)",
|
|||
|
cnt, len, *pAllocatedResources);
|
|||
|
#endif
|
|||
|
|
|||
|
//
|
|||
|
// Report the IO resource assignments
|
|||
|
//
|
|||
|
|
|||
|
if (!DeviceObject) {
|
|||
|
status = IoReportResourceUsage (
|
|||
|
DriverClassName,
|
|||
|
DriverObject, // DriverObject
|
|||
|
*pAllocatedResources, // DriverList
|
|||
|
len, // DriverListSize
|
|||
|
DeviceObject, // DeviceObject
|
|||
|
NULL, // DeviceList
|
|||
|
0, // DeviceListSize
|
|||
|
FALSE, // override conflict
|
|||
|
&conflict // conflicted detected
|
|||
|
);
|
|||
|
} else {
|
|||
|
status = IoReportResourceUsage (
|
|||
|
DriverClassName,
|
|||
|
DriverObject, // DriverObject
|
|||
|
NULL, // DriverList
|
|||
|
0, // DriverListSize
|
|||
|
DeviceObject,
|
|||
|
*pAllocatedResources, // DeviceList
|
|||
|
len, // DeviceListSize
|
|||
|
FALSE, // override conflict
|
|||
|
&conflict // conflicted detected
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
if (NT_SUCCESS(status) && conflict) {
|
|||
|
|
|||
|
//
|
|||
|
// IopReportResourceUsage saw a conflict?
|
|||
|
//
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint("HalAssignSlotResources: IoAssignResources detected a conflict: %x\n",
|
|||
|
status);
|
|||
|
#endif
|
|||
|
status = STATUS_CONFLICTING_ADDRESSES;
|
|||
|
goto CleanUp;
|
|||
|
}
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
#if DBG
|
|||
|
DbgPrint("HalAssignSlotResources: IoAssignResources failed: %x\n", status);
|
|||
|
#endif
|
|||
|
goto CleanUp;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Restore orginial data, turning on the appropiate decodes
|
|||
|
//
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint ("HalAssignSlotResources: IoReportResourseUsage succeeded\n");
|
|||
|
#endif
|
|||
|
|
|||
|
// enable IO & Memory decodes
|
|||
|
|
|||
|
PciOrigData->Command |= (USHORT) Command;
|
|||
|
|
|||
|
HalpWritePCIConfig (
|
|||
|
BusHandler,
|
|||
|
PciSlot,
|
|||
|
PciOrigData,
|
|||
|
0,
|
|||
|
PCI_COMMON_HDR_LENGTH
|
|||
|
);
|
|||
|
|
|||
|
#if DBG
|
|||
|
DbgPrint ("HalAssignSlotResources: PCI Config Space updated with Command = %x\n",
|
|||
|
Command);
|
|||
|
#endif
|
|||
|
|
|||
|
CleanUp:
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
//
|
|||
|
// Failure, if there are any allocated resources free them
|
|||
|
//
|
|||
|
|
|||
|
i = 0;
|
|||
|
if (*pAllocatedResources) {
|
|||
|
|
|||
|
if (!DeviceObject) {
|
|||
|
status = IoReportResourceUsage (
|
|||
|
DriverClassName,
|
|||
|
DriverObject, // DriverObject
|
|||
|
(PCM_RESOURCE_LIST) &i, // DriverList
|
|||
|
sizeof (i), // DriverListSize
|
|||
|
DeviceObject,
|
|||
|
NULL, // DeviceList
|
|||
|
0, // DeviceListSize
|
|||
|
FALSE, // override conflict
|
|||
|
&conflict // conflicted detected
|
|||
|
);
|
|||
|
} else {
|
|||
|
status = IoReportResourceUsage (
|
|||
|
DriverClassName,
|
|||
|
DriverObject, // DriverObject
|
|||
|
NULL, // DriverList
|
|||
|
0, // DriverListSize
|
|||
|
DeviceObject,
|
|||
|
(PCM_RESOURCE_LIST) &i, // DeviceList
|
|||
|
sizeof (i), // DeviceListSize
|
|||
|
FALSE, // override conflict
|
|||
|
&conflict // conflicted detected
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
ExFreePool (*pAllocatedResources);
|
|||
|
*pAllocatedResources = NULL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Restore the device settings as we found them, enable memory
|
|||
|
// and io decode after setting base addresses
|
|||
|
//
|
|||
|
|
|||
|
HalpWritePCIConfig (
|
|||
|
BusHandler,
|
|||
|
PciSlot,
|
|||
|
PciOrigData,
|
|||
|
FIELD_OFFSET (PCI_COMMON_CONFIG, Status),
|
|||
|
PCI_COMMON_HDR_LENGTH - FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
|
|||
|
);
|
|||
|
|
|||
|
HalpWritePCIConfig (
|
|||
|
BusHandler,
|
|||
|
PciSlot,
|
|||
|
PciOrigData,
|
|||
|
0,
|
|||
|
FIELD_OFFSET (PCI_COMMON_CONFIG, Status)
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
HalpAdjustPCIResourceList (
|
|||
|
IN PBUS_HANDLER BusHandler,
|
|||
|
IN PBUS_HANDLER RootHandler,
|
|||
|
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
The function adjusts a PCI pResourceList and forces it to match the
|
|||
|
pre-configured values in PCI configuration space for this device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
BusHandler - Registered BUS_HANDLER for the target configuration space
|
|||
|
|
|||
|
RootHandler - Register BUS_HANDLER for the orginating HalAdjustResourceList request.
|
|||
|
|
|||
|
pResourceList - Supplies the PIO_RESOURCE_REQUIREMENTS_LIST to be checked.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
STATUS_SUCCESS
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UCHAR buffer[PCI_COMMON_HDR_LENGTH];
|
|||
|
PCI_SLOT_NUMBER PciSlot;
|
|||
|
PPCI_COMMON_CONFIG PciData;
|
|||
|
PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
|
|||
|
PIO_RESOURCE_LIST ResourceList;
|
|||
|
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
|||
|
ULONG alt, cnt, bcnt;
|
|||
|
ULONG MemoryBaseAddress, RomIndex;
|
|||
|
PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
|
|||
|
|
|||
|
//
|
|||
|
// Fix any requested resources for this device to be the
|
|||
|
// value set in PCI configuration space for this device.
|
|||
|
//
|
|||
|
|
|||
|
//
|
|||
|
// Get PCI common configuration space for this slot
|
|||
|
//
|
|||
|
|
|||
|
PciSlot = *((PPCI_SLOT_NUMBER) &(*pResourceList)->SlotNumber),
|
|||
|
PciData = (PPCI_COMMON_CONFIG) buffer;
|
|||
|
|
|||
|
HalGetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
BusHandler->BusNumber,
|
|||
|
PciSlot.u.AsULONG,
|
|||
|
PciData,
|
|||
|
PCI_COMMON_HDR_LENGTH
|
|||
|
);
|
|||
|
|
|||
|
if (PciData->VendorID == PCI_INVALID_VENDORID) {
|
|||
|
return STATUS_UNSUCCESSFUL;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy base addresses based on configuration data type
|
|||
|
//
|
|||
|
|
|||
|
switch (PCI_CONFIG_TYPE(PciData)) {
|
|||
|
case 0 :
|
|||
|
for (bcnt=0; bcnt < PCI_TYPE0_ADDRESSES; bcnt++) {
|
|||
|
BaseAddress[bcnt] = &PciData->u.type0.BaseAddresses[bcnt];
|
|||
|
}
|
|||
|
BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
|
|||
|
RomIndex = bcnt;
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
for (bcnt=0; bcnt < PCI_TYPE1_ADDRESSES; bcnt++) {
|
|||
|
BaseAddress[bcnt] = &PciData->u.type1.BaseAddresses[bcnt];
|
|||
|
}
|
|||
|
BaseAddress[bcnt] = &PciData->u.type0.ROMBaseAddress;
|
|||
|
RomIndex = bcnt;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
return STATUS_NO_SUCH_DEVICE;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Walk each ResourceList and confine resources
|
|||
|
// to preconfigured settings.
|
|||
|
//
|
|||
|
|
|||
|
CompleteList = *pResourceList;
|
|||
|
ResourceList = CompleteList->List;
|
|||
|
ResourceList->Version = 1;
|
|||
|
ResourceList->Revision = 1;
|
|||
|
|
|||
|
for (alt=0; alt < CompleteList->AlternativeLists; alt++) {
|
|||
|
Descriptor = ResourceList->Descriptors;
|
|||
|
|
|||
|
//
|
|||
|
// For each alternative list, reset to review entire
|
|||
|
// set of Base Address registers
|
|||
|
//
|
|||
|
// We assume that the order of resource descriptors for
|
|||
|
// each alternative list matches the order of the
|
|||
|
// PCI configuration space base address registers
|
|||
|
//
|
|||
|
|
|||
|
bcnt = 0;
|
|||
|
|
|||
|
for (cnt = ResourceList->Count; cnt; cnt--) {
|
|||
|
|
|||
|
//
|
|||
|
// Limit desctiptor to to preconfigured setting
|
|||
|
// held in the InterruptLine register.
|
|||
|
//
|
|||
|
|
|||
|
switch (Descriptor->Type) {
|
|||
|
case CmResourceTypeInterrupt:
|
|||
|
|
|||
|
//
|
|||
|
// Confine interrupt vector to preconfigured setting.
|
|||
|
//
|
|||
|
|
|||
|
Descriptor->u.Interrupt.MinimumVector = PciData->u.type0.InterruptLine;
|
|||
|
Descriptor->u.Interrupt.MaximumVector = PciData->u.type0.InterruptLine;
|
|||
|
break;
|
|||
|
|
|||
|
case CmResourceTypePort:
|
|||
|
|
|||
|
//
|
|||
|
// Assure that requested descriptor is valid
|
|||
|
//
|
|||
|
|
|||
|
if (bcnt > RomIndex) {
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Confine to preconfigured setting.
|
|||
|
//
|
|||
|
|
|||
|
Descriptor->u.Port.MinimumAddress.QuadPart =
|
|||
|
*BaseAddress[bcnt++] & ~0x3;
|
|||
|
|
|||
|
Descriptor->u.Port.MaximumAddress.QuadPart =
|
|||
|
Descriptor->u.Port.MinimumAddress.QuadPart +
|
|||
|
Descriptor->u.Port.Length - 1;
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
DbgPrint("AdjustPCIResourceList\nPort: MinimumAddress set to %x\n",
|
|||
|
Descriptor->u.Port.MinimumAddress.QuadPart);
|
|||
|
|
|||
|
DbgPrint(" MaximumAddress set to %x\n",
|
|||
|
Descriptor->u.Port.MaximumAddress.QuadPart);
|
|||
|
#endif
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case CmResourceTypeMemory:
|
|||
|
|
|||
|
//
|
|||
|
// Assure that requested descriptor is valid
|
|||
|
//
|
|||
|
|
|||
|
if (bcnt > RomIndex) {
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Confine to preconfigured setting.
|
|||
|
//
|
|||
|
|
|||
|
MemoryBaseAddress = *BaseAddress[bcnt];
|
|||
|
|
|||
|
if (bcnt == RomIndex) {
|
|||
|
Descriptor->u.Memory.MinimumAddress.QuadPart =
|
|||
|
*BaseAddress[bcnt++] & ~PCI_ROMADDRESS_ENABLED;
|
|||
|
} else {
|
|||
|
Descriptor->u.Memory.MinimumAddress.QuadPart =
|
|||
|
*BaseAddress[bcnt++] & ~0xF;
|
|||
|
}
|
|||
|
|
|||
|
Descriptor->u.Memory.MaximumAddress.QuadPart =
|
|||
|
Descriptor->u.Memory.MinimumAddress.QuadPart +
|
|||
|
Descriptor->u.Memory.Length - 1;
|
|||
|
|
|||
|
if (Is64BitBaseAddress(MemoryBaseAddress)) {
|
|||
|
// skip upper half of 64 bit address since we
|
|||
|
// only supports 32 bits PCI addresses for now.
|
|||
|
bcnt++;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#if HALDBG
|
|||
|
DbgPrint("AdjustPCIResourceList\nMemory: MinimumAddress set to %x\n",
|
|||
|
Descriptor->u.Memory.MinimumAddress.QuadPart);
|
|||
|
|
|||
|
DbgPrint(" MaximumAddress set to %x\n",
|
|||
|
Descriptor->u.Memory.MaximumAddress.QuadPart);
|
|||
|
#endif
|
|||
|
break;
|
|||
|
|
|||
|
case CmResourceTypeDma:
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
return STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Next descriptor
|
|||
|
//
|
|||
|
Descriptor++;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Next Resource List
|
|||
|
//
|
|||
|
ResourceList = (PIO_RESOURCE_LIST) Descriptor;
|
|||
|
}
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define TEST_PCI 1
|
|||
|
|
|||
|
#if DBG && TEST_PCI
|
|||
|
|
|||
|
VOID HalpTestPci (ULONG flag2)
|
|||
|
{
|
|||
|
PCI_SLOT_NUMBER SlotNumber;
|
|||
|
PCI_COMMON_CONFIG PciData, OrigData;
|
|||
|
ULONG i, f, j, k, bus;
|
|||
|
BOOLEAN flag;
|
|||
|
|
|||
|
if (!flag2) {
|
|||
|
return ;
|
|||
|
}
|
|||
|
|
|||
|
DbgBreakPoint ();
|
|||
|
SlotNumber.u.bits.Reserved = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Read every possible PCI Device/Function and display it's
|
|||
|
// default info.
|
|||
|
//
|
|||
|
// (note this destories it's current settings)
|
|||
|
//
|
|||
|
|
|||
|
flag = TRUE;
|
|||
|
for (bus = 0; flag; bus++) {
|
|||
|
|
|||
|
for (i = 0; i < 32; i++) {
|
|||
|
SlotNumber.u.bits.DeviceNumber = i;
|
|||
|
|
|||
|
for (f = 0; f < 8; f++) {
|
|||
|
SlotNumber.u.bits.FunctionNumber = f;
|
|||
|
|
|||
|
|
|||
|
j = HalGetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&PciData,
|
|||
|
sizeof (PciData)
|
|||
|
);
|
|||
|
|
|||
|
if (j == 0) {
|
|||
|
// out of buses
|
|||
|
flag = FALSE;
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if (j < PCI_COMMON_HDR_LENGTH) {
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
HalSetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&PciData,
|
|||
|
1
|
|||
|
);
|
|||
|
|
|||
|
HalGetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&PciData,
|
|||
|
sizeof (PciData)
|
|||
|
);
|
|||
|
|
|||
|
memcpy (&OrigData, &PciData, sizeof PciData);
|
|||
|
|
|||
|
for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
|
|||
|
PciData.u.type0.BaseAddresses[j] = 0xFFFFFFFF;
|
|||
|
}
|
|||
|
|
|||
|
PciData.u.type0.ROMBaseAddress = 0xFFFFFFFF;
|
|||
|
|
|||
|
HalSetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&PciData,
|
|||
|
sizeof (PciData)
|
|||
|
);
|
|||
|
|
|||
|
HalGetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&PciData,
|
|||
|
sizeof (PciData)
|
|||
|
);
|
|||
|
|
|||
|
DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
|
|||
|
bus, i, f, PciData.VendorID, PciData.DeviceID,
|
|||
|
PciData.RevisionID);
|
|||
|
|
|||
|
if (PciData.u.type0.InterruptPin) {
|
|||
|
DbgPrint (" IntPin:%x", PciData.u.type0.InterruptPin);
|
|||
|
}
|
|||
|
|
|||
|
if (PciData.u.type0.InterruptLine) {
|
|||
|
DbgPrint (" IntLine:%x", PciData.u.type0.InterruptLine);
|
|||
|
}
|
|||
|
|
|||
|
if (PciData.u.type0.ROMBaseAddress) {
|
|||
|
DbgPrint (" ROM:%08lx", PciData.u.type0.ROMBaseAddress);
|
|||
|
}
|
|||
|
|
|||
|
DbgPrint ("\n ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
|
|||
|
PciData.ProgIf, PciData.SubClass, PciData.BaseClass);
|
|||
|
|
|||
|
k = 0;
|
|||
|
for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
|
|||
|
if (PciData.u.type0.BaseAddresses[j]) {
|
|||
|
DbgPrint (" Ad%d:%08lx", j, PciData.u.type0.BaseAddresses[j]);
|
|||
|
k = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (PciData.u.type0.ROMBaseAddress == 0xC08001) {
|
|||
|
|
|||
|
PciData.u.type0.ROMBaseAddress = 0xC00001;
|
|||
|
HalSetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&PciData,
|
|||
|
sizeof (PciData)
|
|||
|
);
|
|||
|
|
|||
|
HalGetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&PciData,
|
|||
|
sizeof (PciData)
|
|||
|
);
|
|||
|
|
|||
|
DbgPrint ("\n Bogus rom address, edit yields:%08lx",
|
|||
|
PciData.u.type0.ROMBaseAddress);
|
|||
|
}
|
|||
|
if (k) {
|
|||
|
DbgPrint ("\n");
|
|||
|
}
|
|||
|
|
|||
|
if (PciData.VendorID == 0x8086) {
|
|||
|
// dump complete buffer
|
|||
|
DbgPrint ("Command %x, Status %x, BIST %x\n",
|
|||
|
PciData.Command, PciData.Status,
|
|||
|
PciData.BIST
|
|||
|
);
|
|||
|
|
|||
|
DbgPrint ("CacheLineSz %x, LatencyTimer %x",
|
|||
|
PciData.CacheLineSize, PciData.LatencyTimer
|
|||
|
);
|
|||
|
|
|||
|
for (j=0; j < 192; j++) {
|
|||
|
if ((j & 0xf) == 0) {
|
|||
|
DbgPrint ("\n%02x: ", j + 0x40);
|
|||
|
}
|
|||
|
DbgPrint ("%02x ", PciData.DeviceSpecific[j]);
|
|||
|
}
|
|||
|
DbgPrint ("\n");
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// now print original data
|
|||
|
//
|
|||
|
|
|||
|
if (OrigData.u.type0.ROMBaseAddress) {
|
|||
|
DbgPrint (" oROM:%08lx", OrigData.u.type0.ROMBaseAddress);
|
|||
|
}
|
|||
|
|
|||
|
DbgPrint ("\n");
|
|||
|
k = 0;
|
|||
|
for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
|
|||
|
if (OrigData.u.type0.BaseAddresses[j]) {
|
|||
|
DbgPrint (" oAd%d:%08lx", j, OrigData.u.type0.BaseAddresses[j]);
|
|||
|
k = 1;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Restore original settings
|
|||
|
//
|
|||
|
|
|||
|
HalSetBusData (
|
|||
|
PCIConfiguration,
|
|||
|
bus,
|
|||
|
SlotNumber.u.AsULONG,
|
|||
|
&OrigData,
|
|||
|
sizeof (PciData)
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Next
|
|||
|
//
|
|||
|
|
|||
|
if (k) {
|
|||
|
DbgPrint ("\n\n");
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
DbgBreakPoint();
|
|||
|
}
|
|||
|
|
|||
|
#endif // DBG && TEST_PCI
|