3586 lines
100 KiB
C
3586 lines
100 KiB
C
// #pragma comment(exestr, "@(#) pcibus.c 1.1 95/09/28 15:45:56 nec")
|
||
/*++
|
||
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
ixpcidat.c
|
||
|
||
Abstract:
|
||
|
||
Get/Set bus data routines for the PCI bus
|
||
|
||
Author:
|
||
|
||
Ken Reneris (kenr) 14-June-1994
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
Modification History:
|
||
|
||
H001 Fri Jun 30 02:54:08 1995 kbnes!kisimoto
|
||
- Merge build 1057 ixpcibus.c
|
||
H002 Tue Jul 4 20:43:12 1995 kbnes!kisimoto
|
||
- disable preferred setting for back-to-back
|
||
support. If enable, IoAssign... allocates
|
||
current enabled address space.
|
||
H003 Wed Jul 5 14:27:46 1995 kbnes!kisimoto
|
||
- initialize with FALSE
|
||
H004 Tue Sep 5 20:06:16 1995 kbnes!kisimoto
|
||
- PCI Fast Back-to-back transfer support
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
#include "pci.h"
|
||
#include "pcip.h"
|
||
|
||
#if defined(_R94A_) // H001
|
||
#include "r94adef.h"
|
||
#include "string.h"
|
||
#endif // _R94A_
|
||
|
||
extern WCHAR rgzMultiFunctionAdapter[];
|
||
extern WCHAR rgzConfigurationData[];
|
||
extern WCHAR rgzIdentifier[];
|
||
extern WCHAR rgzPCIIdentifier[];
|
||
|
||
|
||
typedef ULONG (*FncConfigIO) (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
typedef VOID (*FncSync) (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PKIRQL Irql,
|
||
IN PVOID State
|
||
);
|
||
|
||
typedef VOID (*FncReleaseSync) (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN KIRQL Irql
|
||
);
|
||
|
||
typedef struct _PCI_CONFIG_HANDLER {
|
||
FncSync Synchronize;
|
||
FncReleaseSync ReleaseSynchronzation;
|
||
FncConfigIO ConfigRead[3];
|
||
FncConfigIO ConfigWrite[3];
|
||
} PCI_CONFIG_HANDLER, *PPCI_CONFIG_HANDLER;
|
||
|
||
|
||
|
||
//
|
||
// Prototypes
|
||
//
|
||
|
||
ULONG
|
||
HalpGetPCIData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PCI_SLOT_NUMBER SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
ULONG
|
||
HalpSetPCIData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PCI_SLOT_NUMBER SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
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 SlotNumber,
|
||
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
||
);
|
||
|
||
#if 0
|
||
VOID
|
||
HalpInitializePciBus (
|
||
VOID
|
||
);
|
||
#endif
|
||
|
||
BOOLEAN
|
||
HalpIsValidPCIDevice (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot
|
||
);
|
||
|
||
BOOLEAN
|
||
HalpValidPCISlot (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot
|
||
);
|
||
|
||
//-------------------------------------------------
|
||
|
||
VOID HalpPCISynchronizeType1 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PKIRQL Irql,
|
||
IN PVOID State
|
||
);
|
||
|
||
VOID HalpPCIReleaseSynchronzationType1 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN KIRQL Irql
|
||
);
|
||
|
||
ULONG HalpPCIReadUlongType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIReadUcharType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIReadUshortType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIWriteUlongType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIWriteUcharType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIWriteUshortType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
VOID HalpPCISynchronizeType2 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PKIRQL Irql,
|
||
IN PVOID State
|
||
);
|
||
|
||
VOID HalpPCIReleaseSynchronzationType2 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN KIRQL Irql
|
||
);
|
||
|
||
ULONG HalpPCIReadUlongType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIReadUcharType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIReadUshortType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIWriteUlongType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIWriteUcharType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
ULONG HalpPCIWriteUshortType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PVOID State,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
);
|
||
|
||
|
||
//
|
||
// Globals
|
||
//
|
||
|
||
// KSPIN_LOCK HalpPCIConfigLock; // H001
|
||
|
||
PCI_CONFIG_HANDLER PCIConfigHandler;
|
||
|
||
PCI_CONFIG_HANDLER PCIConfigHandlerType1 = {
|
||
HalpPCISynchronizeType1,
|
||
HalpPCIReleaseSynchronzationType1,
|
||
{
|
||
HalpPCIReadUlongType1, // 0
|
||
HalpPCIReadUcharType1, // 1
|
||
HalpPCIReadUshortType1 // 2
|
||
},
|
||
{
|
||
HalpPCIWriteUlongType1, // 0
|
||
HalpPCIWriteUcharType1, // 1
|
||
HalpPCIWriteUshortType1 // 2
|
||
}
|
||
};
|
||
|
||
PCI_CONFIG_HANDLER PCIConfigHandlerType2 = {
|
||
HalpPCISynchronizeType2,
|
||
HalpPCIReleaseSynchronzationType2,
|
||
{
|
||
HalpPCIReadUlongType2, // 0
|
||
HalpPCIReadUcharType2, // 1
|
||
HalpPCIReadUshortType2 // 2
|
||
},
|
||
{
|
||
HalpPCIWriteUlongType2, // 0
|
||
HalpPCIWriteUcharType2, // 1
|
||
HalpPCIWriteUshortType2 // 2
|
||
}
|
||
};
|
||
|
||
UCHAR PCIDeref[4][4] = { {0,1,2,2},{1,1,1,1},{2,1,2,2},{1,1,1,1} };
|
||
|
||
BOOLEAN HalpDoingCrashDump = FALSE; // H003
|
||
ULONG HalpFoundUncapablePCIDevice = 0; // H004
|
||
ULONG HalpPCINumberOfMappedGA = 0;
|
||
ULONG HalpPCIBackToBackReg0Start = 0;
|
||
ULONG HalpPCIBackToBackReg1Start = 0;
|
||
ULONG HalpPCIBackToBackReg0Open = 1;
|
||
ULONG HalpPCIBackToBackReg1Open = 1;
|
||
ULONG HalpNumberOfPCIGA = 0;
|
||
ULONG HalpPCIMemoryLimit = 0xffffffff;
|
||
|
||
#define INIT_VALUE_OF_BACK_TO_BACK_ADDR 0x00000000
|
||
#define INIT_VALUE_OF_BACK_TO_BACK_MASK 0xffffffff
|
||
|
||
VOID
|
||
HalpPCIConfig (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length,
|
||
IN FncConfigIO *ConfigIO
|
||
);
|
||
|
||
#if defined(_R94A_) // H001
|
||
ULONG
|
||
HalpGetPCIInterruptVector(
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG BusInterruptLevel,
|
||
IN ULONG BusInterruptVector,
|
||
OUT PKIRQL Irql,
|
||
OUT PKAFFINITY Affinity
|
||
);
|
||
ULONG
|
||
HalpGetNumberOfPCIGA(
|
||
IN ULONG NumberBuses
|
||
);
|
||
VOID
|
||
HalpSetBackToBackSpace(
|
||
IN PPCI_COMMON_CONFIG PciConfigRequired,
|
||
IN PPCI_COMMON_CONFIG PciConfigMapped,
|
||
IN PBUS_HANDLER BusHandler
|
||
);
|
||
VOID
|
||
HalpSetBackToBackRegister(
|
||
IN ULONG BaseAddress,
|
||
IN ULONG Length,
|
||
IN ULONG Register
|
||
);
|
||
#endif // _R94A_
|
||
|
||
#if DBG
|
||
#define DBGMSG(a) DbgPrint(a)
|
||
ULONG R94aDoTestPci = 0;
|
||
ULONG R94aDoTestPciNec = 0;
|
||
ULONG R94aDoOtherTest = 0;
|
||
VOID
|
||
HalpTestPciNec (
|
||
ULONG
|
||
);
|
||
VOID
|
||
HalpTestPciPrintResult(
|
||
IN PULONG Buffer,
|
||
IN ULONG Length
|
||
);
|
||
VOID
|
||
HalpOtherTestNec (
|
||
ULONG
|
||
);
|
||
VOID
|
||
HalpTestPci (
|
||
ULONG
|
||
);
|
||
#else
|
||
#define DBGMSG(a)
|
||
#endif
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT,HalpInitializePciBus)
|
||
#pragma alloc_text(INIT,HalpAllocateAndInitPciBusHandler)
|
||
#pragma alloc_text(INIT,HalpIsValidPCIDevice)
|
||
#pragma alloc_text(PAGE,HalpAssignPCISlotResources)
|
||
#endif
|
||
|
||
|
||
|
||
VOID
|
||
HalpInitializePciBus (
|
||
VOID
|
||
)
|
||
{
|
||
PPCI_REGISTRY_INFO PCIRegInfo;
|
||
UNICODE_STRING unicodeString, ConfigName, IdentName;
|
||
OBJECT_ATTRIBUTES objectAttributes;
|
||
HANDLE hMFunc, hBus;
|
||
NTSTATUS status;
|
||
UCHAR buffer [sizeof(PPCI_REGISTRY_INFO) + 99];
|
||
PWSTR p;
|
||
WCHAR wstr[8];
|
||
ULONG i, d, junk, HwType, BusNo, f;
|
||
PBUS_HANDLER BusHandler;
|
||
PCI_SLOT_NUMBER SlotNumber;
|
||
PPCI_COMMON_CONFIG PciData;
|
||
UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
|
||
PKEY_VALUE_FULL_INFORMATION ValueInfo;
|
||
PCM_FULL_RESOURCE_DESCRIPTOR Desc;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR PDesc;
|
||
|
||
PCI_REGISTRY_INFO tPCIRegInfo; // H001
|
||
|
||
#if 0 // H001
|
||
//
|
||
// Search the hardware description looking for any reported
|
||
// PCI bus. The first ARC entry for a PCI bus will contain
|
||
// the PCI_REGISTRY_INFO.
|
||
|
||
RtlInitUnicodeString (&unicodeString, rgzMultiFunctionAdapter);
|
||
InitializeObjectAttributes (
|
||
&objectAttributes,
|
||
&unicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
NULL, // handle
|
||
NULL);
|
||
|
||
|
||
status = ZwOpenKey (&hMFunc, KEY_READ, &objectAttributes);
|
||
if (!NT_SUCCESS(status)) {
|
||
return ;
|
||
}
|
||
|
||
unicodeString.Buffer = wstr;
|
||
unicodeString.MaximumLength = sizeof (wstr);
|
||
|
||
RtlInitUnicodeString (&ConfigName, rgzConfigurationData);
|
||
RtlInitUnicodeString (&IdentName, rgzIdentifier);
|
||
|
||
ValueInfo = (PKEY_VALUE_FULL_INFORMATION) buffer;
|
||
|
||
for (i=0; TRUE; i++) {
|
||
RtlIntegerToUnicodeString (i, 10, &unicodeString);
|
||
InitializeObjectAttributes (
|
||
&objectAttributes,
|
||
&unicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
hMFunc,
|
||
NULL);
|
||
|
||
status = ZwOpenKey (&hBus, KEY_READ, &objectAttributes);
|
||
if (!NT_SUCCESS(status)) {
|
||
//
|
||
// Out of Multifunction adapter entries...
|
||
//
|
||
|
||
ZwClose (hMFunc);
|
||
return ;
|
||
}
|
||
|
||
//
|
||
// Check the Indentifier to see if this is a PCI entry
|
||
//
|
||
|
||
status = ZwQueryValueKey (
|
||
hBus,
|
||
&IdentName,
|
||
KeyValueFullInformation,
|
||
ValueInfo,
|
||
sizeof (buffer),
|
||
&junk
|
||
);
|
||
|
||
if (!NT_SUCCESS (status)) {
|
||
ZwClose (hBus);
|
||
continue;
|
||
}
|
||
|
||
p = (PWSTR) ((PUCHAR) ValueInfo + ValueInfo->DataOffset);
|
||
if (p[0] != L'P' || p[1] != L'C' || p[2] != L'I' || p[3] != 0) {
|
||
ZwClose (hBus);
|
||
continue;
|
||
}
|
||
|
||
//
|
||
// The first PCI entry has the PCI_REGISTRY_INFO structure
|
||
// attached to it.
|
||
//
|
||
|
||
status = ZwQueryValueKey (
|
||
hBus,
|
||
&ConfigName,
|
||
KeyValueFullInformation,
|
||
ValueInfo,
|
||
sizeof (buffer),
|
||
&junk
|
||
);
|
||
|
||
ZwClose (hBus);
|
||
if (!NT_SUCCESS(status)) {
|
||
continue ;
|
||
}
|
||
|
||
Desc = (PCM_FULL_RESOURCE_DESCRIPTOR) ((PUCHAR)
|
||
ValueInfo + ValueInfo->DataOffset);
|
||
PDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)
|
||
Desc->PartialResourceList.PartialDescriptors);
|
||
|
||
if (PDesc->Type == CmResourceTypeDeviceSpecific) {
|
||
// got it..
|
||
PCIRegInfo = (PPCI_REGISTRY_INFO) (PDesc+1);
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Initialize spinlock for synchronizing access to PCI space
|
||
//
|
||
|
||
// KeInitializeSpinLock (&HalpPCIConfigLock); // H001
|
||
PciData = (PPCI_COMMON_CONFIG) iBuffer;
|
||
|
||
#endif // 0
|
||
|
||
#if defined(_R94A_) // H001
|
||
|
||
PCIRegInfo = &tPCIRegInfo;
|
||
PCIRegInfo->NoBuses = 1;
|
||
PCIRegInfo->HardwareMechanism=0x1; // HURRICANE PCI Config Type
|
||
|
||
#if DBG
|
||
DbgPrint("PCI System Get Data:\n");
|
||
DbgPrint("MajorRevision %x\n", PCIRegInfo->MajorRevision );
|
||
DbgPrint("MinorRevision %x\n", PCIRegInfo->MinorRevision );
|
||
DbgPrint("NoBuses %x\n", PCIRegInfo->NoBuses );
|
||
DbgPrint("HwMechanism %x\n", PCIRegInfo->HardwareMechanism );
|
||
#endif // DBG
|
||
|
||
#endif // _R94A_
|
||
|
||
//
|
||
// PCIRegInfo describes the system's PCI support as indicated by the BIOS.
|
||
//
|
||
|
||
HwType = PCIRegInfo->HardwareMechanism & 0xf;
|
||
|
||
//
|
||
// Some AMI bioses claim machines are Type2 configuration when they
|
||
// are really type1. If this is a Type2 with at least one bus,
|
||
// try to verify it's not really a type1 bus
|
||
//
|
||
|
||
if (PCIRegInfo->NoBuses && HwType == 2) {
|
||
|
||
//
|
||
// Check each slot for a valid device. Which every style configuration
|
||
// space shows a valid device first will be used
|
||
//
|
||
|
||
SlotNumber.u.bits.Reserved = 0;
|
||
SlotNumber.u.bits.FunctionNumber = 0;
|
||
|
||
for (d = 0; d < PCI_MAX_DEVICES; d++) {
|
||
SlotNumber.u.bits.DeviceNumber = d;
|
||
|
||
//
|
||
// First try what the BIOS claims - type 2. Allocate type2
|
||
// test handle for PCI bus 0.
|
||
//
|
||
|
||
HwType = 2;
|
||
BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
|
||
|
||
if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Valid device not found on Type2 access for this slot.
|
||
// Reallocate the bus handler are Type1 and take a look.
|
||
//
|
||
|
||
HwType = 1;
|
||
BusHandler = HalpAllocateAndInitPciBusHandler (HwType, 0, TRUE);
|
||
|
||
if (HalpIsValidPCIDevice (BusHandler, SlotNumber)) {
|
||
break;
|
||
}
|
||
|
||
HwType = 2;
|
||
}
|
||
|
||
//
|
||
// Reset handler for PCI bus 0 to whatever style config space
|
||
// was finally decided.
|
||
//
|
||
|
||
HalpAllocateAndInitPciBusHandler (HwType, 0, FALSE);
|
||
}
|
||
|
||
|
||
//
|
||
// For each PCI bus present, allocate a handler structure and
|
||
// fill in the dispatch functions
|
||
//
|
||
|
||
#if 0 // H001
|
||
do {
|
||
#endif
|
||
for (i=0; i < PCIRegInfo->NoBuses; i++) {
|
||
|
||
//
|
||
// If handler not already built, do it now
|
||
//
|
||
|
||
if (!HalpHandlerForBus (PCIBus, i)) {
|
||
HalpAllocateAndInitPciBusHandler (HwType, i, FALSE);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Bus handlers for all PCI buses have been allocated, go collect
|
||
// pci bridge information.
|
||
//
|
||
|
||
#if 0 // H001
|
||
} while (HalpGetPciBridgeConfig (HwType, &PCIRegInfo->NoBuses)) ;
|
||
|
||
//
|
||
// Fixup SUPPORTED_RANGES
|
||
//
|
||
|
||
HalpFixupPciSupportedRanges (PCIRegInfo->NoBuses);
|
||
|
||
//
|
||
// Look for PCI controllers which have known work-arounds, and make
|
||
// sure they are applied.
|
||
//
|
||
|
||
SlotNumber.u.bits.Reserved = 0;
|
||
for (BusNo=0; BusNo < PCIRegInfo->NoBuses; BusNo++) {
|
||
BusHandler = HalpHandlerForBus (PCIBus, BusNo);
|
||
|
||
for (d = 0; d < PCI_MAX_DEVICES; d++) {
|
||
SlotNumber.u.bits.DeviceNumber = d;
|
||
|
||
for (f = 0; f < PCI_MAX_FUNCTION; f++) {
|
||
SlotNumber.u.bits.FunctionNumber = f;
|
||
|
||
//
|
||
// Read PCI configuration information
|
||
//
|
||
|
||
HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
||
|
||
//
|
||
// Check for chips with known work-arounds to apply
|
||
//
|
||
|
||
if (PciData->VendorID == 0x8086 &&
|
||
PciData->DeviceID == 0x04A3 &&
|
||
PciData->RevisionID < 0x11) {
|
||
|
||
//
|
||
// 82430 PCMC controller
|
||
//
|
||
|
||
HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
|
||
|
||
buffer[0] &= ~0x08; // turn off bit 3 register 0x53
|
||
|
||
if (PciData->RevisionID == 0x10) { // on rev 0x10, also turn
|
||
buffer[1] &= ~0x01; // bit 0 register 0x54
|
||
}
|
||
|
||
HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x53, 2);
|
||
}
|
||
|
||
if (PciData->VendorID == 0x8086 &&
|
||
PciData->DeviceID == 0x0484 &&
|
||
PciData->RevisionID <= 3) {
|
||
|
||
//
|
||
// 82378 ISA bridge & SIO
|
||
//
|
||
|
||
HalpReadPCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
|
||
|
||
buffer[0] &= ~0x1; // turn off bit 0 register 0x41
|
||
|
||
HalpWritePCIConfig (BusHandler, SlotNumber, buffer, 0x41, 1);
|
||
}
|
||
|
||
} // next function
|
||
} // next device
|
||
} // next bus
|
||
#endif
|
||
|
||
//
|
||
// H005
|
||
// Compute the number of PCI-GA device and
|
||
// initialize Fast Back-to-back register.
|
||
//
|
||
|
||
HalpNumberOfPCIGA = HalpGetNumberOfPCIGA(PCIRegInfo->NoBuses);
|
||
|
||
#if DBG
|
||
HalpTestPci (0);
|
||
#if defined(_R94A_)
|
||
DbgPrint("HalpInitializePciBus: Call HalpTestPci(%x)\n",R94aDoTestPci);
|
||
HalpTestPci (R94aDoTestPci);
|
||
DbgPrint("HalpInitializePciBus: Call HalpTestPciNec(%x)\n",R94aDoTestPciNec);
|
||
HalpTestPciNec (R94aDoTestPciNec);
|
||
DbgPrint("HalpInitializePciBus: Call HalpOtherTest(%x)\n",R94aDoOtherTest);
|
||
HalpOtherTestNec (R94aDoOtherTest);
|
||
#endif
|
||
#endif
|
||
}
|
||
|
||
|
||
PBUS_HANDLER
|
||
HalpAllocateAndInitPciBusHandler (
|
||
IN ULONG HwType,
|
||
IN ULONG BusNo,
|
||
IN BOOLEAN TestAllocation
|
||
)
|
||
{
|
||
PBUS_HANDLER Bus;
|
||
PPCIPBUSDATA BusData;
|
||
|
||
Bus = HalpAllocateBusHandler (
|
||
PCIBus, // Interface type
|
||
PCIConfiguration, // Has this configuration space
|
||
BusNo, // bus #
|
||
Internal, // child of this bus
|
||
0, // and number
|
||
sizeof (PCIPBUSDATA) // sizeof bus specific buffer
|
||
);
|
||
|
||
//
|
||
// Fill in PCI handlers
|
||
//
|
||
|
||
Bus->GetBusData = (PGETSETBUSDATA) HalpGetPCIData;
|
||
Bus->SetBusData = (PGETSETBUSDATA) HalpSetPCIData;
|
||
#if defined(_R94A_)
|
||
Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIInterruptVector;
|
||
#else
|
||
Bus->GetInterruptVector = (PGETINTERRUPTVECTOR) HalpGetPCIIntOnISABus;
|
||
#endif
|
||
Bus->AdjustResourceList = (PADJUSTRESOURCELIST) HalpAdjustPCIResourceList;
|
||
Bus->AssignSlotResources = (PASSIGNSLOTRESOURCES) HalpAssignPCISlotResources;
|
||
Bus->BusAddresses->Dma.Limit = 0;
|
||
|
||
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) HalpPCIPin2ISALine;
|
||
BusData->CommonData.Line2Pin = (PciLine2Pin) HalpPCIISALine2Pin;
|
||
|
||
//
|
||
// Set defaults
|
||
//
|
||
|
||
BusData->MaxDevice = PCI_MAX_DEVICES;
|
||
BusData->GetIrqRange = (PciIrqRange) HalpGetISAFixedPCIIrq;
|
||
|
||
RtlInitializeBitMap (&BusData->DeviceConfigured,
|
||
BusData->ConfiguredBits, 256);
|
||
|
||
switch (HwType) {
|
||
case 1:
|
||
//
|
||
// Initialize access port information for Type1 handlers
|
||
//
|
||
|
||
RtlCopyMemory (&PCIConfigHandler,
|
||
&PCIConfigHandlerType1,
|
||
sizeof (PCIConfigHandler));
|
||
|
||
#if defined(_R94A_) // H001
|
||
BusData->Config.Type1.Address = (PULONG)R94A_PCI_TYPE1_ADDR_PORT;
|
||
BusData->Config.Type1.Data = R94A_PCI_TYPE1_DATA_PORT;
|
||
#else
|
||
BusData->Config.Type1.Address = PCI_TYPE1_ADDR_PORT;
|
||
BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
|
||
#endif // _R94A_
|
||
break;
|
||
|
||
case 2:
|
||
//
|
||
// Initialize access port information for Type2 handlers
|
||
//
|
||
|
||
RtlCopyMemory (&PCIConfigHandler,
|
||
&PCIConfigHandlerType2,
|
||
sizeof (PCIConfigHandler));
|
||
|
||
BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
|
||
BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
|
||
BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
|
||
|
||
//
|
||
// Early PCI machines didn't decode the last bit of
|
||
// the device id. Shrink type 2 support max device.
|
||
//
|
||
BusData->MaxDevice = 0x10;
|
||
|
||
break;
|
||
|
||
default:
|
||
// unsupport type
|
||
DBGMSG ("HAL: Unkown PCI type\n");
|
||
}
|
||
|
||
if (!TestAllocation) {
|
||
#ifdef SUBCLASSPCI
|
||
HalpSubclassPCISupport (Bus, HwType);
|
||
#endif
|
||
}
|
||
|
||
return Bus;
|
||
}
|
||
|
||
BOOLEAN
|
||
HalpIsValidPCIDevice (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Reads the device configuration data for the given slot and
|
||
returns TRUE if the configuration data appears to be valid for
|
||
a PCI device; otherwise returns FALSE.
|
||
|
||
Arguments:
|
||
|
||
BusHandler - Bus to check
|
||
Slot - Slot to check
|
||
|
||
--*/
|
||
|
||
{
|
||
PPCI_COMMON_CONFIG PciData;
|
||
UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
|
||
ULONG i, j;
|
||
|
||
|
||
PciData = (PPCI_COMMON_CONFIG) iBuffer;
|
||
|
||
//
|
||
// Read device common header
|
||
//
|
||
|
||
HalpReadPCIConfig (BusHandler, Slot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
||
|
||
//
|
||
// Valid device header?
|
||
//
|
||
|
||
if (PciData->VendorID == PCI_INVALID_VENDORID ||
|
||
PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// Check fields for reasonable values
|
||
//
|
||
|
||
if ((PciData->u.type0.InterruptPin && PciData->u.type0.InterruptPin > 4) ||
|
||
(PciData->u.type0.InterruptLine & 0x70)) {
|
||
return FALSE;
|
||
}
|
||
|
||
for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
|
||
j = PciData->u.type0.BaseAddresses[i];
|
||
|
||
if (j & PCI_ADDRESS_IO_SPACE) {
|
||
if ((j > 0x2 && j < 0xffff) || j > 0xffffff) { // H001
|
||
// IO port < 64KB | IO port > 16MB
|
||
return FALSE;
|
||
}
|
||
} else {
|
||
if (j > 0xf && j < 0x3ffffff) { // H001
|
||
// Mem address < 64MB
|
||
return FALSE;
|
||
}
|
||
}
|
||
|
||
if (Is64BitBaseAddress(j)) {
|
||
i += 1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Guess it's a valid device..
|
||
//
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
ULONG
|
||
HalpGetPCIData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The function returns the Pci bus data for a device.
|
||
|
||
Arguments:
|
||
|
||
BusNumber - Indicates which bus.
|
||
|
||
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];
|
||
PPCIPBUSDATA BusData;
|
||
ULONG Len;
|
||
ULONG i, bit;
|
||
|
||
if (Length > sizeof (PCI_COMMON_CONFIG)) {
|
||
Length = sizeof (PCI_COMMON_CONFIG);
|
||
}
|
||
|
||
Len = 0;
|
||
PciData = (PPCI_COMMON_CONFIG) iBuffer;
|
||
|
||
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, Slot, PciData, 0, sizeof(ULONG));
|
||
|
||
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
|
||
//
|
||
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
|
||
//
|
||
// Read this PCI devices slot data
|
||
//
|
||
|
||
Len = PCI_COMMON_HDR_LENGTH;
|
||
HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
|
||
|
||
#if 0
|
||
DbgPrint ("--------------->>> Now Print the Slot Information\n");
|
||
DbgPrint ("PCI Bus %d Slot %2d %2d ID:%04lx-%04lx Rev:%04lx",
|
||
BusHandler->BusNumber, Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber, 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);
|
||
|
||
{ ULONG k, j;
|
||
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;
|
||
}
|
||
}
|
||
DbgPrint("\n");
|
||
}
|
||
#endif // DBG
|
||
|
||
if (PciData->VendorID == PCI_INVALID_VENDORID ||
|
||
PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
|
||
PciData->VendorID = PCI_INVALID_VENDORID;
|
||
Len = 2; // only return invalid id
|
||
|
||
} else {
|
||
|
||
BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData);
|
||
}
|
||
|
||
//
|
||
// Has this PCI device been configured?
|
||
//
|
||
|
||
#if DBG
|
||
|
||
//
|
||
// On DBG build, if this PCI device has not yet been configured,
|
||
// then don't report any current configuration the device may have.
|
||
//
|
||
|
||
bit = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
|
||
if (!RtlCheckBit(&BusData->DeviceConfigured, bit)) {
|
||
|
||
for (i=0; i < PCI_TYPE0_ADDRESSES; i++) {
|
||
PciData->u.type0.BaseAddresses[i] = 0;
|
||
}
|
||
|
||
PciData->u.type0.ROMBaseAddress = 0;
|
||
PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
|
||
}
|
||
#endif
|
||
|
||
|
||
//
|
||
// 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, Slot, Buffer, Offset, Length);
|
||
Len += Length;
|
||
}
|
||
}
|
||
|
||
return Len;
|
||
}
|
||
|
||
ULONG
|
||
HalpSetPCIData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
The function returns the Pci bus data for a device.
|
||
|
||
Arguments:
|
||
|
||
|
||
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];
|
||
PPCIPBUSDATA BusData;
|
||
ULONG Len, cnt;
|
||
|
||
|
||
if (Length > sizeof (PCI_COMMON_CONFIG)) {
|
||
Length = sizeof (PCI_COMMON_CONFIG);
|
||
}
|
||
|
||
|
||
Len = 0;
|
||
PciData = (PPCI_COMMON_CONFIG) iBuffer;
|
||
PciData2 = (PPCI_COMMON_CONFIG) iBuffer2;
|
||
|
||
|
||
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, Slot, PciData, 0, sizeof(ULONG));
|
||
|
||
if (PciData->VendorID == PCI_INVALID_VENDORID) {
|
||
return 0;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// Caller requested to set at least some data within the
|
||
// common header.
|
||
//
|
||
|
||
Len = PCI_COMMON_HDR_LENGTH;
|
||
HalpReadPCIConfig (BusHandler, Slot, PciData, 0, Len);
|
||
if (PciData->VendorID == PCI_INVALID_VENDORID ||
|
||
PCI_CONFIG_TYPE (PciData) != PCI_DEVICE_TYPE) {
|
||
|
||
// no device, or header type unkown
|
||
return 0;
|
||
}
|
||
|
||
|
||
//
|
||
// Set this device as configured
|
||
//
|
||
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
#if DBG
|
||
cnt = PciBitIndex(Slot.u.bits.DeviceNumber, Slot.u.bits.FunctionNumber);
|
||
RtlSetBits (&BusData->DeviceConfigured, cnt, 1);
|
||
#endif
|
||
//
|
||
// Copy COMMON_HDR values to buffer2, then overlay callers changes.
|
||
//
|
||
|
||
RtlMoveMemory (iBuffer2, iBuffer, Len);
|
||
BusData->CommonData.Pin2Line (BusHandler, RootHandler, Slot, PciData2);
|
||
|
||
Len -= Offset;
|
||
if (Len > Length) {
|
||
Len = Length;
|
||
}
|
||
|
||
RtlMoveMemory (iBuffer2+Offset, Buffer, Len);
|
||
|
||
// in case interrupt line or pin was editted
|
||
BusData->CommonData.Line2Pin (BusHandler, RootHandler, Slot, PciData2, PciData);
|
||
|
||
#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 configuration value changed\n");
|
||
DbgBreakPoint ();
|
||
}
|
||
#endif
|
||
//
|
||
// Set new PCI configuration
|
||
//
|
||
|
||
#if DBG // H001
|
||
DbgPrint("SetPciData: PciData2->u.type0.InterruptLine:%x\n",PciData2->u.type0.InterruptLine);
|
||
#endif
|
||
HalpWritePCIConfig (BusHandler, Slot, 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, Slot, Buffer, Offset, Length);
|
||
Len += Length;
|
||
}
|
||
}
|
||
|
||
return Len;
|
||
}
|
||
|
||
VOID
|
||
HalpReadPCIConfig (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
USHORT IdValue; // H001
|
||
ULONG OrigData; // H001
|
||
|
||
if (!HalpValidPCISlot (BusHandler, Slot)) {
|
||
//
|
||
// Invalid SlotID return no data
|
||
//
|
||
RtlFillMemory (Buffer, Length, (UCHAR) -1);
|
||
|
||
return ;
|
||
}
|
||
|
||
#if defined(_R94A_) // H001
|
||
|
||
//
|
||
// resolve PCI master abort during we are looking for PCI device
|
||
// check to see if spcified slot is valid.
|
||
//
|
||
|
||
//
|
||
// Disable PCI-MasterAbort interrupt during configration read.
|
||
//
|
||
|
||
OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
|
||
WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
|
||
|
||
HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
|
||
PCIConfigHandler.ConfigRead);
|
||
|
||
if (IdValue == 0xffff){
|
||
|
||
//
|
||
// This PCI slot has no card
|
||
// wait until ReceivedMasterAbort bit is set
|
||
//
|
||
|
||
while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
|
||
;
|
||
|
||
//
|
||
// clear the ReceivedMasterAbort bit
|
||
//
|
||
|
||
WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
|
||
|
||
//
|
||
// Clear memory address error registers.
|
||
//
|
||
|
||
{
|
||
LARGE_INTEGER registerLarge;
|
||
READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge);
|
||
}
|
||
|
||
//
|
||
// Restore the PCIInterruptEnable register, and return no data
|
||
//
|
||
|
||
WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
|
||
RtlFillMemory (Buffer, Length, (UCHAR) -1);
|
||
|
||
return ;
|
||
}
|
||
|
||
//
|
||
// Restore the PCIInterruptEnable register.
|
||
//
|
||
|
||
WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
|
||
|
||
#endif // _R94A_
|
||
|
||
HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
|
||
PCIConfigHandler.ConfigRead);
|
||
}
|
||
|
||
VOID
|
||
HalpWritePCIConfig (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
USHORT IdValue; // H001
|
||
ULONG OrigData; // H001
|
||
|
||
if (!HalpValidPCISlot (BusHandler, Slot)) {
|
||
//
|
||
// Invalid SlotID do nothing
|
||
//
|
||
return ;
|
||
}
|
||
|
||
#if defined(_R94A_) // H001
|
||
|
||
//
|
||
// resolve PCI master abort during we are looking for PCI device
|
||
// check to see if spcified slot is valid.
|
||
//
|
||
|
||
//
|
||
// Disable PCI-MasterAbort interrupt during configration read.
|
||
//
|
||
|
||
OrigData = READ_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable);
|
||
WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData & 0xffffff7f);
|
||
|
||
HalpPCIConfig (BusHandler, Slot, (PUCHAR) &IdValue, 0, 2,
|
||
PCIConfigHandler.ConfigRead);
|
||
|
||
if (IdValue == 0xffff){
|
||
|
||
//
|
||
// This PCI slot has no card
|
||
// wait until ReceivedMasterAbort bit is set
|
||
//
|
||
|
||
while(!(READ_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus) & 0x2000))
|
||
;
|
||
|
||
//
|
||
// clear the ReceivedMasterAbort bit
|
||
//
|
||
|
||
WRITE_REGISTER_USHORT(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIStatus, 0x2000);
|
||
|
||
//
|
||
// Clear memory address error registers.
|
||
//
|
||
|
||
{
|
||
LARGE_INTEGER registerLarge;
|
||
READ_REGISTER_DWORD((PVOID)&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->InvalidAddress, ®isterLarge);
|
||
}
|
||
|
||
//
|
||
// Restore the PCIInterruptEnable register, and return no data
|
||
//
|
||
|
||
WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
|
||
RtlFillMemory (Buffer, Length, (UCHAR) -1);
|
||
|
||
return ;
|
||
}
|
||
|
||
//
|
||
// Restore the PCIInterruptEnable register.
|
||
//
|
||
|
||
WRITE_REGISTER_ULONG(&((PDMA_REGISTERS)DMA_VIRTUAL_BASE)->PCIInterruptEnable, OrigData);
|
||
|
||
#endif // _R94A_
|
||
|
||
HalpPCIConfig (BusHandler, Slot, (PUCHAR) Buffer, Offset, Length,
|
||
PCIConfigHandler.ConfigWrite);
|
||
}
|
||
|
||
BOOLEAN
|
||
HalpValidPCISlot (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot
|
||
)
|
||
{
|
||
PCI_SLOT_NUMBER Slot2;
|
||
PPCIPBUSDATA BusData;
|
||
UCHAR HeaderType;
|
||
ULONG i;
|
||
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
|
||
if (Slot.u.bits.Reserved != 0) {
|
||
return FALSE;
|
||
}
|
||
|
||
#if defined(_R94A_) // H001
|
||
if (Slot.u.bits.DeviceNumber < 3 ||
|
||
Slot.u.bits.DeviceNumber > 20) {
|
||
return FALSE;
|
||
}
|
||
#else
|
||
if (Slot.u.bits.DeviceNumber >= BusData->MaxDevice) {
|
||
return FALSE;
|
||
}
|
||
#endif // _R94A_
|
||
|
||
if (Slot.u.bits.FunctionNumber == 0) {
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// 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 FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
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;
|
||
UCHAR State[20];
|
||
PPCIPBUSDATA BusData;
|
||
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
|
||
if (Slot.u.bits.DeviceNumber < 3) { // H001
|
||
#if DBG
|
||
DbgPrint("HalpPCIConfig: Ignore Slot %x\n",Slot.u.bits.DeviceNumber);
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
PCIConfigHandler.Synchronize (BusHandler, Slot, &OldIrql, State);
|
||
|
||
while (Length) {
|
||
i = PCIDeref[Offset % sizeof(ULONG)][Length % sizeof(ULONG)];
|
||
i = ConfigIO[i] (BusData, State, Buffer, Offset);
|
||
|
||
Offset += i;
|
||
Buffer += i;
|
||
Length -= i;
|
||
}
|
||
|
||
PCIConfigHandler.ReleaseSynchronzation (BusHandler, OldIrql);
|
||
}
|
||
|
||
VOID HalpPCISynchronizeType1 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PKIRQL Irql,
|
||
IN PPCI_TYPE1_CFG_BITS PciCfg1
|
||
)
|
||
{
|
||
//
|
||
// Initialize PciCfg1
|
||
//
|
||
|
||
PciCfg1->u.AsULONG = 0;
|
||
PciCfg1->u.bits.BusNumber = BusHandler->BusNumber;
|
||
PciCfg1->u.bits.DeviceNumber = Slot.u.bits.DeviceNumber;
|
||
PciCfg1->u.bits.FunctionNumber = Slot.u.bits.FunctionNumber;
|
||
PciCfg1->u.bits.Enable = TRUE;
|
||
|
||
//
|
||
// Synchronize with PCI type1 config space
|
||
//
|
||
|
||
if (!HalpDoingCrashDump) {
|
||
KeRaiseIrql (PROFILE_LEVEL, Irql); // H001
|
||
KiAcquireSpinLock (&HalpPCIConfigLock);
|
||
} else {
|
||
*Irql = HIGH_LEVEL;
|
||
}
|
||
}
|
||
|
||
VOID HalpPCIReleaseSynchronzationType1 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN KIRQL Irql
|
||
)
|
||
{
|
||
PCI_TYPE1_CFG_BITS PciCfg1;
|
||
PPCIPBUSDATA BusData;
|
||
|
||
//
|
||
// Disable PCI configuration space
|
||
//
|
||
|
||
PciCfg1.u.AsULONG = 0;
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1.u.AsULONG);
|
||
|
||
//
|
||
// Release spinlock
|
||
//
|
||
|
||
if (!HalpDoingCrashDump) {
|
||
KiReleaseSpinLock (&HalpPCIConfigLock);
|
||
KeLowerIrql (Irql); // H001
|
||
}
|
||
}
|
||
|
||
|
||
ULONG
|
||
HalpPCIReadUcharType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE1_CFG_BITS PciCfg1,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
ULONG i;
|
||
|
||
i = Offset % sizeof(ULONG);
|
||
PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
||
WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
|
||
*Buffer = READ_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i));
|
||
return sizeof (UCHAR);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIReadUshortType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE1_CFG_BITS PciCfg1,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
ULONG i;
|
||
|
||
i = Offset % sizeof(ULONG);
|
||
PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
||
WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
|
||
*((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i));
|
||
return sizeof (USHORT);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIReadUlongType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE1_CFG_BITS PciCfg1,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
||
WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
|
||
*((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) BusData->Config.Type1.Data);
|
||
return sizeof (ULONG);
|
||
}
|
||
|
||
|
||
ULONG
|
||
HalpPCIWriteUcharType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE1_CFG_BITS PciCfg1,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
ULONG i;
|
||
|
||
i = Offset % sizeof(ULONG);
|
||
PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
||
WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
|
||
WRITE_PORT_UCHAR ((PUCHAR) (BusData->Config.Type1.Data + i), *Buffer);
|
||
return sizeof (UCHAR);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIWriteUshortType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE1_CFG_BITS PciCfg1,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
ULONG i;
|
||
|
||
i = Offset % sizeof(ULONG);
|
||
PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
||
WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
|
||
WRITE_PORT_USHORT ((PUSHORT) (BusData->Config.Type1.Data + i), *((PUSHORT) Buffer));
|
||
return sizeof (USHORT);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIWriteUlongType1 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE1_CFG_BITS PciCfg1,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg1->u.bits.RegisterNumber = Offset / sizeof(ULONG);
|
||
WRITE_PORT_ULONG (BusData->Config.Type1.Address, PciCfg1->u.AsULONG);
|
||
WRITE_PORT_ULONG ((PULONG) BusData->Config.Type1.Data, *((PULONG) Buffer));
|
||
return sizeof (ULONG);
|
||
}
|
||
|
||
|
||
VOID HalpPCISynchronizeType2 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PCI_SLOT_NUMBER Slot,
|
||
IN PKIRQL Irql,
|
||
IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr
|
||
)
|
||
{
|
||
PCI_TYPE2_CSE_BITS PciCfg2Cse;
|
||
PPCIPBUSDATA BusData;
|
||
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
|
||
//
|
||
// Initialize Cfg2Addr
|
||
//
|
||
|
||
PciCfg2Addr->u.AsUSHORT = 0;
|
||
PciCfg2Addr->u.bits.Agent = (USHORT) Slot.u.bits.DeviceNumber;
|
||
PciCfg2Addr->u.bits.AddressBase = (USHORT) BusData->Config.Type2.Base;
|
||
|
||
//
|
||
// Synchronize with type2 config space - type2 config space
|
||
// remaps 4K of IO space, so we can not allow other I/Os to occur
|
||
// while using type2 config space.
|
||
//
|
||
|
||
HalpPCIAcquireType2Lock (&HalpPCIConfigLock, Irql);
|
||
|
||
PciCfg2Cse.u.AsUCHAR = 0;
|
||
PciCfg2Cse.u.bits.Enable = TRUE;
|
||
PciCfg2Cse.u.bits.FunctionNumber = (UCHAR) Slot.u.bits.FunctionNumber;
|
||
PciCfg2Cse.u.bits.Key = 0xff;
|
||
|
||
//
|
||
// Select bus & enable type 2 configuration space
|
||
//
|
||
|
||
WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) BusHandler->BusNumber);
|
||
WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
|
||
}
|
||
|
||
|
||
VOID HalpPCIReleaseSynchronzationType2 (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN KIRQL Irql
|
||
)
|
||
{
|
||
PCI_TYPE2_CSE_BITS PciCfg2Cse;
|
||
PPCIPBUSDATA BusData;
|
||
|
||
//
|
||
// disable PCI configuration space
|
||
//
|
||
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
|
||
PciCfg2Cse.u.AsUCHAR = 0;
|
||
WRITE_PORT_UCHAR (BusData->Config.Type2.CSE, PciCfg2Cse.u.AsUCHAR);
|
||
WRITE_PORT_UCHAR (BusData->Config.Type2.Forward, (UCHAR) 0);
|
||
|
||
//
|
||
// Restore interrupts, release spinlock
|
||
//
|
||
|
||
HalpPCIReleaseType2Lock (&HalpPCIConfigLock, Irql);
|
||
}
|
||
|
||
|
||
ULONG
|
||
HalpPCIReadUcharType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
|
||
*Buffer = READ_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT);
|
||
return sizeof (UCHAR);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIReadUshortType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
|
||
*((PUSHORT) Buffer) = READ_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT);
|
||
return sizeof (USHORT);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIReadUlongType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
|
||
*((PULONG) Buffer) = READ_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT);
|
||
return sizeof(ULONG);
|
||
}
|
||
|
||
|
||
ULONG
|
||
HalpPCIWriteUcharType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
|
||
WRITE_PORT_UCHAR ((PUCHAR) PciCfg2Addr->u.AsUSHORT, *Buffer);
|
||
return sizeof (UCHAR);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIWriteUshortType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
|
||
WRITE_PORT_USHORT ((PUSHORT) PciCfg2Addr->u.AsUSHORT, *((PUSHORT) Buffer));
|
||
return sizeof (USHORT);
|
||
}
|
||
|
||
ULONG
|
||
HalpPCIWriteUlongType2 (
|
||
IN PPCIPBUSDATA BusData,
|
||
IN PPCI_TYPE2_ADDRESS_BITS PciCfg2Addr,
|
||
IN PUCHAR Buffer,
|
||
IN ULONG Offset
|
||
)
|
||
{
|
||
PciCfg2Addr->u.bits.RegisterNumber = (USHORT) Offset;
|
||
WRITE_PORT_ULONG ((PULONG) PciCfg2Addr->u.AsUSHORT, *((PULONG) Buffer));
|
||
return sizeof(ULONG);
|
||
}
|
||
|
||
|
||
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 it's required resources.
|
||
Calls IoAssignResources to allocate them.
|
||
Sets the targeted device with it's assigned resoruces
|
||
and returns the assignments to the caller.
|
||
|
||
Arguments:
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS or error
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status;
|
||
PUCHAR WorkingPool;
|
||
PPCI_COMMON_CONFIG PciData, PciOrigData, PciData2;
|
||
PCI_COMMON_CONFIG PciData3; // H005
|
||
PCI_SLOT_NUMBER PciSlot;
|
||
PPCIPBUSDATA BusData;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
|
||
PIO_RESOURCE_DESCRIPTOR Descriptor;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
|
||
ULONG BusNumber;
|
||
ULONG i, j, m, length, memtype;
|
||
ULONG NoBaseAddress, RomIndex, Option;
|
||
PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
|
||
PULONG OrigAddress[PCI_TYPE0_ADDRESSES + 1];
|
||
BOOLEAN Match, EnableRomBase;
|
||
|
||
|
||
*pAllocatedResources = NULL;
|
||
PciSlot = *((PPCI_SLOT_NUMBER) &Slot);
|
||
BusNumber = BusHandler->BusNumber;
|
||
BusData = (PPCIPBUSDATA) BusHandler->BusData;
|
||
|
||
//
|
||
// Allocate some pool for working space
|
||
//
|
||
|
||
i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
|
||
sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
|
||
PCI_COMMON_HDR_LENGTH * 3;
|
||
|
||
WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
|
||
if (!WorkingPool) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Zero initialize pool, and get pointers into memory
|
||
//
|
||
|
||
RtlZeroMemory (WorkingPool, i);
|
||
CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
|
||
PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 3);
|
||
PciData2 = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 2);
|
||
PciOrigData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH * 1);
|
||
|
||
//
|
||
// Read the PCI device's configuration
|
||
//
|
||
|
||
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
||
if (PciData->VendorID == PCI_INVALID_VENDORID) {
|
||
ExFreePool (WorkingPool);
|
||
return STATUS_NO_SUCH_DEVICE;
|
||
}
|
||
|
||
//
|
||
// Make a copy of the device's current settings
|
||
//
|
||
|
||
RtlMoveMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
|
||
|
||
//
|
||
// Initialize base addresses base on configuration data type
|
||
//
|
||
|
||
switch (PCI_CONFIG_TYPE(PciData)) {
|
||
case 0 :
|
||
NoBaseAddress = PCI_TYPE0_ADDRESSES+1;
|
||
for (j=0; j < PCI_TYPE0_ADDRESSES; j++) {
|
||
BaseAddress[j] = &PciData->u.type0.BaseAddresses[j];
|
||
OrigAddress[j] = &PciOrigData->u.type0.BaseAddresses[j];
|
||
}
|
||
BaseAddress[j] = &PciData->u.type0.ROMBaseAddress;
|
||
OrigAddress[j] = &PciOrigData->u.type0.ROMBaseAddress;
|
||
RomIndex = j;
|
||
break;
|
||
case 1:
|
||
NoBaseAddress = PCI_TYPE1_ADDRESSES+1;
|
||
for (j=0; j < PCI_TYPE1_ADDRESSES; j++) {
|
||
BaseAddress[j] = &PciData->u.type1.BaseAddresses[j];
|
||
OrigAddress[j] = &PciOrigData->u.type1.BaseAddresses[j];
|
||
}
|
||
BaseAddress[j] = &PciData->u.type1.ROMBaseAddress;
|
||
OrigAddress[j] = &PciOrigData->u.type1.ROMBaseAddress;
|
||
RomIndex = j;
|
||
break;
|
||
|
||
default:
|
||
ExFreePool (WorkingPool);
|
||
return STATUS_NO_SUCH_DEVICE;
|
||
}
|
||
|
||
//
|
||
// If the BIOS doesn't have the device's ROM enabled, then we won't
|
||
// enable it either. Remove it from the list.
|
||
//
|
||
|
||
EnableRomBase = TRUE;
|
||
|
||
#if 0 // H001
|
||
if (!(*BaseAddress[RomIndex] & PCI_ROMADDRESS_ENABLED)) {
|
||
ASSERT (RomIndex+1 == NoBaseAddress);
|
||
EnableRomBase = FALSE;
|
||
NoBaseAddress -= 1;
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Set resources to all bits on to see what type of resources
|
||
// are required.
|
||
//
|
||
|
||
for (j=0; j < NoBaseAddress; j++) {
|
||
*BaseAddress[j] = 0xFFFFFFFF;
|
||
}
|
||
|
||
PciData->Command &= ~(PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE);
|
||
*BaseAddress[RomIndex] &= ~PCI_ROMADDRESS_ENABLED;
|
||
HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
||
HalpReadPCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
||
|
||
//
|
||
// H004
|
||
// Make a copy of the device's current settings
|
||
//
|
||
|
||
RtlMoveMemory ((PPCI_COMMON_CONFIG)&PciData3, PciData, PCI_COMMON_HDR_LENGTH);
|
||
|
||
// note type0 & type1 overlay ROMBaseAddress, InterruptPin, and InterruptLine
|
||
BusData->CommonData.Pin2Line (BusHandler, RootHandler, PciSlot, PciData);
|
||
|
||
//
|
||
// Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
|
||
//
|
||
|
||
CompleteList->InterfaceType = PCIBus;
|
||
CompleteList->BusNumber = BusNumber;
|
||
CompleteList->SlotNumber = Slot;
|
||
CompleteList->AlternativeLists = 1;
|
||
|
||
CompleteList->List[0].Version = 1;
|
||
CompleteList->List[0].Revision = 1;
|
||
|
||
Descriptor = CompleteList->List[0].Descriptors;
|
||
|
||
//
|
||
// If PCI device has an interrupt resource, add it
|
||
//
|
||
|
||
if (PciData->u.type0.InterruptPin) {
|
||
CompleteList->List[0].Count++;
|
||
|
||
Descriptor->Option = 0;
|
||
Descriptor->Type = CmResourceTypeInterrupt;
|
||
Descriptor->ShareDisposition = CmResourceShareShared;
|
||
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
||
|
||
// Fill in any vector here - we'll pick it back up in
|
||
// HalAdjustResourceList and adjust it to it's allowed settings
|
||
Descriptor->u.Interrupt.MinimumVector = 0;
|
||
Descriptor->u.Interrupt.MaximumVector = 0xff;
|
||
Descriptor++;
|
||
}
|
||
|
||
//
|
||
// Add a memory/port resoruce for each PCI resource
|
||
//
|
||
|
||
// Clear ROM reserved bits
|
||
|
||
*BaseAddress[RomIndex] &= ~0x7FF;
|
||
|
||
for (j=0; j < NoBaseAddress; j++) {
|
||
if (*BaseAddress[j]) {
|
||
i = *BaseAddress[j];
|
||
|
||
// scan for first set bit, that's the length & alignment
|
||
length = 1 << (i & PCI_ADDRESS_IO_SPACE ? 2 : 4);
|
||
while (!(i & length) && length) {
|
||
length <<= 1;
|
||
}
|
||
|
||
// scan for last set bit, that's the maxaddress + 1
|
||
for (m = length; i & m; m <<= 1) ;
|
||
m--;
|
||
|
||
// check for hosed PCI configuration requirements
|
||
if (length & ~m) {
|
||
#if DBG
|
||
DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
|
||
BusNumber,
|
||
PciSlot.u.bits.DeviceNumber,
|
||
PciSlot.u.bits.FunctionNumber
|
||
);
|
||
|
||
DbgPrint ("PCI: BaseAddress[%d] = %08lx\n", j, i);
|
||
#endif
|
||
// the device is in error - punt. don't allow this
|
||
// resource any option - it either gets set to whatever
|
||
// bits it was able to return, or it doesn't get set.
|
||
|
||
if (i & PCI_ADDRESS_IO_SPACE) {
|
||
m = i & ~0x3;
|
||
Descriptor->u.Port.MinimumAddress.LowPart = m;
|
||
} else {
|
||
m = i & ~0xf;
|
||
Descriptor->u.Memory.MinimumAddress.LowPart = m;
|
||
}
|
||
|
||
m += length; // max address is min address + length
|
||
}
|
||
|
||
//
|
||
// Add requested resource
|
||
//
|
||
|
||
Descriptor->Option = 0;
|
||
if (i & PCI_ADDRESS_IO_SPACE) {
|
||
memtype = 0;
|
||
|
||
#if 0 // H002
|
||
if (!Is64BitBaseAddress(i) &&
|
||
PciOrigData->Command & PCI_ENABLE_IO_SPACE) {
|
||
|
||
//
|
||
// The IO range is/was already enabled at some location, add that
|
||
// as it's preferred setting.
|
||
//
|
||
|
||
Descriptor->Type = CmResourceTypePort;
|
||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||
Descriptor->Flags = CM_RESOURCE_PORT_IO;
|
||
Descriptor->Option = IO_RESOURCE_PREFERRED;
|
||
|
||
Descriptor->u.Port.Length = length;
|
||
Descriptor->u.Port.Alignment = length;
|
||
Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0x3;
|
||
Descriptor->u.Port.MaximumAddress.LowPart =
|
||
Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
|
||
|
||
CompleteList->List[0].Count++;
|
||
Descriptor++;
|
||
|
||
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
||
}
|
||
#endif
|
||
//
|
||
// Add this IO range
|
||
//
|
||
|
||
Descriptor->Type = CmResourceTypePort;
|
||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||
Descriptor->Flags = CM_RESOURCE_PORT_IO;
|
||
|
||
Descriptor->u.Port.Length = length;
|
||
Descriptor->u.Port.Alignment = length;
|
||
Descriptor->u.Port.MaximumAddress.LowPart = m;
|
||
|
||
#if DBG // H001
|
||
DbgPrint("HalpAssign: Port %x len %x align %x\n", length, length, m);
|
||
#endif // DBG
|
||
|
||
} else {
|
||
|
||
memtype = i & PCI_ADDRESS_MEMORY_TYPE_MASK;
|
||
|
||
Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
|
||
if (j == RomIndex) {
|
||
// this is a ROM address
|
||
Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
|
||
}
|
||
|
||
if (i & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
|
||
Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
|
||
}
|
||
|
||
#if 0 // H002
|
||
if (!Is64BitBaseAddress(i) &&
|
||
(j == RomIndex ||
|
||
PciOrigData->Command & PCI_ENABLE_MEMORY_SPACE)) {
|
||
|
||
//
|
||
// The memory range is/was already enabled at some location, add that
|
||
// as it's preferred setting.
|
||
//
|
||
|
||
Descriptor->Type = CmResourceTypeMemory;
|
||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||
Descriptor->Option = IO_RESOURCE_PREFERRED;
|
||
|
||
Descriptor->u.Port.Length = length;
|
||
Descriptor->u.Port.Alignment = length;
|
||
Descriptor->u.Port.MinimumAddress.LowPart = *OrigAddress[j] & ~0xF;
|
||
Descriptor->u.Port.MaximumAddress.LowPart =
|
||
Descriptor->u.Port.MinimumAddress.LowPart + length - 1;
|
||
|
||
CompleteList->List[0].Count++;
|
||
Descriptor++;
|
||
|
||
Descriptor->Flags = Descriptor[-1].Flags;
|
||
Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
|
||
}
|
||
#endif
|
||
//
|
||
// Add this memory range
|
||
//
|
||
|
||
Descriptor->Type = CmResourceTypeMemory;
|
||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||
|
||
Descriptor->u.Memory.Length = length;
|
||
Descriptor->u.Memory.Alignment = length;
|
||
Descriptor->u.Memory.MaximumAddress.LowPart = m;
|
||
|
||
if (memtype == PCI_TYPE_20BIT && m > 0xFFFFF) {
|
||
// limit to 20 bit address
|
||
Descriptor->u.Memory.MaximumAddress.LowPart = 0xFFFFF;
|
||
}
|
||
|
||
#if DBG // H001
|
||
DbgPrint("HalpAssign: Memory %x len %x align %x\n", length, length, m);
|
||
#endif // DBG
|
||
|
||
}
|
||
|
||
CompleteList->List[0].Count++;
|
||
Descriptor++;
|
||
|
||
|
||
if (Is64BitBaseAddress(i)) {
|
||
// skip upper half of 64 bit address since this processor
|
||
// only supports 32 bits of address space
|
||
j++;
|
||
}
|
||
}
|
||
}
|
||
|
||
CompleteList->ListSize = (ULONG)
|
||
((PUCHAR) Descriptor - (PUCHAR) CompleteList);
|
||
|
||
//
|
||
// Restore the device settings as we found them, enable memory
|
||
// and io decode after setting base addresses. This is done in
|
||
// case HalAdjustResourceList wants to read the current settings
|
||
// in the device.
|
||
//
|
||
|
||
HalpWritePCIConfig (
|
||
BusHandler,
|
||
PciSlot,
|
||
&PciOrigData->Status,
|
||
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)
|
||
);
|
||
|
||
//
|
||
// Have the IO system allocate resource assignments
|
||
//
|
||
|
||
#if DBG // H001
|
||
DbgPrint("Call IoAssignResources\n");
|
||
#endif // DBG
|
||
|
||
status = IoAssignResources (
|
||
RegistryPath,
|
||
DriverClassName,
|
||
DriverObject,
|
||
DeviceObject,
|
||
CompleteList,
|
||
pAllocatedResources
|
||
);
|
||
|
||
if (!NT_SUCCESS(status)) {
|
||
goto CleanUp;
|
||
}
|
||
|
||
//
|
||
// Slurp the assigments back into the PciData structure and
|
||
// perform them
|
||
//
|
||
|
||
CmDescriptor = (*pAllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
|
||
|
||
//
|
||
// If PCI device has an interrupt resource then that was
|
||
// passed in as the first requested resource
|
||
//
|
||
|
||
if (PciData->u.type0.InterruptPin) {
|
||
PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
|
||
BusData->CommonData.Line2Pin (BusHandler, RootHandler, PciSlot, PciData, PciOrigData);
|
||
CmDescriptor++;
|
||
}
|
||
|
||
//
|
||
// Pull out resources in the order they were passed to IoAssignResources
|
||
//
|
||
|
||
for (j=0; j < NoBaseAddress; j++) {
|
||
i = *BaseAddress[j];
|
||
if (i) {
|
||
if (i & PCI_ADDRESS_IO_SPACE) {
|
||
*BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
|
||
#if DBG // H001
|
||
DbgPrint("HalpAssign assigned: Port %x\n", *BaseAddress[j]);
|
||
#endif // DBG
|
||
} else {
|
||
*BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
|
||
#if DBG // H001
|
||
DbgPrint("HalpAssign assigned: Memory %x\n", *BaseAddress[j]);
|
||
#endif // DBG
|
||
}
|
||
CmDescriptor++;
|
||
}
|
||
|
||
if (Is64BitBaseAddress(i)) {
|
||
// skip upper 32 bits
|
||
j++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Turn off decodes, then set new addresses
|
||
//
|
||
|
||
#if DBG // H001
|
||
DbgPrint("Set Assigned Resources\n");
|
||
#endif // DBG
|
||
|
||
HalpWritePCIConfig (BusHandler, PciSlot, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
||
|
||
//
|
||
// Read configuration back and verify address settings took
|
||
//
|
||
|
||
#if DBG // H001
|
||
DbgPrint("Read Common header to see write results\n");
|
||
#endif // DBG
|
||
|
||
HalpReadPCIConfig(BusHandler, PciSlot, PciData2, 0, PCI_COMMON_HDR_LENGTH);
|
||
|
||
Match = TRUE;
|
||
if (PciData->u.type0.InterruptLine != PciData2->u.type0.InterruptLine ||
|
||
PciData->u.type0.InterruptPin != PciData2->u.type0.InterruptPin ||
|
||
PciData->u.type0.ROMBaseAddress != PciData2->u.type0.ROMBaseAddress) {
|
||
Match = FALSE;
|
||
}
|
||
|
||
for (j=0; j < NoBaseAddress; j++) {
|
||
if (*BaseAddress[j]) {
|
||
if (*BaseAddress[j] & PCI_ADDRESS_IO_SPACE) {
|
||
i = (ULONG) ~0x3;
|
||
} else {
|
||
i = (ULONG) ~0xF;
|
||
}
|
||
|
||
if ((*BaseAddress[j] & i) !=
|
||
*((PULONG) ((PUCHAR) BaseAddress[j] -
|
||
(PUCHAR) PciData +
|
||
(PUCHAR) PciData2)) & i) {
|
||
|
||
Match = FALSE;
|
||
}
|
||
|
||
if (Is64BitBaseAddress(*BaseAddress[j])) {
|
||
// skip upper 32 bits
|
||
j++;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!Match) {
|
||
#if DBG
|
||
DbgPrint ("PCI: defective device! Bus %d, Slot %d, Function %d\n",
|
||
BusNumber,
|
||
PciSlot.u.bits.DeviceNumber,
|
||
PciSlot.u.bits.FunctionNumber
|
||
);
|
||
#endif
|
||
status = STATUS_DEVICE_PROTOCOL_ERROR;
|
||
goto CleanUp;
|
||
}
|
||
|
||
//
|
||
// H004
|
||
// set memory space as back-to-back available
|
||
//
|
||
|
||
HalpSetBackToBackSpace(&PciData3, PciData2, BusHandler);
|
||
|
||
//
|
||
// Settings took - turn on the appropiate decodes
|
||
//
|
||
|
||
if (EnableRomBase && *BaseAddress[RomIndex]) {
|
||
// a rom address was allocated and should be enabled
|
||
*BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
|
||
HalpWritePCIConfig (
|
||
BusHandler,
|
||
PciSlot,
|
||
BaseAddress[RomIndex],
|
||
(ULONG) ((PUCHAR) BaseAddress[RomIndex] - (PUCHAR) PciData),
|
||
sizeof (ULONG)
|
||
);
|
||
}
|
||
|
||
//
|
||
// Enable IO, Memory, and BUS_MASTER decodes
|
||
// (use HalSetBusData since valid settings now set)
|
||
//
|
||
|
||
PciData->Command |= PCI_ENABLE_IO_SPACE |
|
||
PCI_ENABLE_MEMORY_SPACE |
|
||
PCI_ENABLE_BUS_MASTER;
|
||
|
||
HalSetBusDataByOffset (
|
||
PCIConfiguration,
|
||
BusHandler->BusNumber,
|
||
PciSlot.u.AsULONG,
|
||
&PciData->Command,
|
||
FIELD_OFFSET (PCI_COMMON_CONFIG, Command),
|
||
sizeof (PciData->Command)
|
||
);
|
||
|
||
CleanUp:
|
||
if (!NT_SUCCESS(status)) {
|
||
|
||
//
|
||
// Failure, if there are any allocated resources free them
|
||
//
|
||
|
||
if (*pAllocatedResources) {
|
||
IoAssignResources (
|
||
RegistryPath,
|
||
DriverClassName,
|
||
DriverObject,
|
||
DeviceObject,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
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->Status,
|
||
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)
|
||
);
|
||
}
|
||
|
||
ExFreePool (WorkingPool);
|
||
return status;
|
||
}
|
||
|
||
#if DBG
|
||
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 < PCI_MAX_DEVICES; i++) {
|
||
SlotNumber.u.bits.DeviceNumber = i;
|
||
|
||
for (f = 0; f < PCI_MAX_FUNCTION; f++) {
|
||
SlotNumber.u.bits.FunctionNumber = f;
|
||
|
||
//
|
||
// Note: This is reading the DeviceSpecific area of
|
||
// the device's configuration - normally this should
|
||
// only be done on device for which the caller understands.
|
||
// I'm doing it here only for debugging.
|
||
//
|
||
|
||
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)
|
||
);
|
||
|
||
#if 0
|
||
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)
|
||
);
|
||
#endif
|
||
|
||
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 Cmd:%04x Status:%04x ProgIf:%04x SubClass:%04x BaseClass:%04lx\n",
|
||
PciData.Command, PciData.Status, 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 0
|
||
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);
|
||
}
|
||
#endif
|
||
|
||
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");
|
||
}
|
||
|
||
|
||
#if 0
|
||
//
|
||
// 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)
|
||
);
|
||
#endif
|
||
|
||
//
|
||
// Next
|
||
//
|
||
|
||
if (k) {
|
||
DbgPrint ("\n\n");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
DbgBreakPoint ();
|
||
}
|
||
|
||
#if defined (_R94A_) // H001
|
||
VOID
|
||
HalpTestPciNec (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 < 1; bus++) { /* R94A_ Support Only 1 */
|
||
|
||
for (i = 0; i < PCI_MAX_DEVICES; i++) { /* R94A_ Support Only 2 slots(include bridge) */
|
||
SlotNumber.u.bits.DeviceNumber = i;
|
||
|
||
for (f = 0; f < 8; f++) {
|
||
SlotNumber.u.bits.FunctionNumber = f;
|
||
DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
|
||
j = HalGetBusData (
|
||
PCIConfiguration,
|
||
bus,
|
||
SlotNumber.u.AsULONG,
|
||
&PciData,
|
||
sizeof (PciData)
|
||
);
|
||
HalpTestPciPrintResult((PULONG)&PciData, j);
|
||
if (j == 0) {
|
||
// out of buses
|
||
flag = FALSE;
|
||
break;
|
||
}
|
||
|
||
if (j < PCI_COMMON_HDR_LENGTH) {
|
||
continue;
|
||
}
|
||
DbgPrint("===== SetBusData slot(%d) func(%d)\n", i, f);
|
||
HalSetBusData (
|
||
PCIConfiguration,
|
||
bus,
|
||
SlotNumber.u.AsULONG,
|
||
&PciData,
|
||
1
|
||
);
|
||
HalpTestPciPrintResult((PULONG)&PciData, 1);
|
||
DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
|
||
HalGetBusData (
|
||
PCIConfiguration,
|
||
bus,
|
||
SlotNumber.u.AsULONG,
|
||
&PciData,
|
||
sizeof (PciData)
|
||
);
|
||
HalpTestPciPrintResult((PULONG)&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;
|
||
PciData.u.type0.InterruptLine = 5; // For trial
|
||
DbgPrint("===== (Change Contents (SetBusData) slot(%d) func(%d)\n", i, f);
|
||
HalSetBusData (
|
||
PCIConfiguration,
|
||
bus,
|
||
SlotNumber.u.AsULONG,
|
||
&PciData,
|
||
PCI_COMMON_HDR_LENGTH // To avoid alias problem(HDR <--> DevSpecific)
|
||
);
|
||
HalpTestPciPrintResult((PULONG)&PciData, PCI_COMMON_HDR_LENGTH);
|
||
DbgPrint("===== GetBusData slot(%d) func(%d)\n", i, f);
|
||
HalGetBusData (
|
||
PCIConfiguration,
|
||
bus,
|
||
SlotNumber.u.AsULONG,
|
||
&PciData,
|
||
sizeof (PciData)
|
||
);
|
||
HalpTestPciPrintResult((PULONG)&PciData, sizeof (PciData));
|
||
|
||
DbgPrint ("--------------->>> Now Print the Slot Information\n");
|
||
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 ("We got the bridge\n");
|
||
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
|
||
//
|
||
DbgPrint ("--------------->>> Now Print the Original Slot Information\n");
|
||
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
|
||
//
|
||
DbgPrint("===== Restore (GetBusData) slot(%d) func(%d)\n", i, f);
|
||
HalSetBusData (
|
||
PCIConfiguration,
|
||
bus,
|
||
SlotNumber.u.AsULONG,
|
||
&OrigData,
|
||
sizeof (PciData)
|
||
);
|
||
HalpTestPciPrintResult((PULONG)&OrigData, sizeof (PciData));
|
||
//
|
||
// Next
|
||
//
|
||
|
||
if (k) {
|
||
DbgPrint ("\n\n");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
DbgBreakPoint ();
|
||
}
|
||
|
||
|
||
VOID
|
||
HalpTestPciPrintResult(
|
||
IN PULONG Buffer,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
ULONG i, Lines, pchar;
|
||
|
||
DbgPrint("----- I/O Data. (%d)byts.\n", Length);
|
||
|
||
for (Lines = 0, pchar = 0; Lines < ((Length + 15)/ 16) && pchar < Length; Lines++) {
|
||
DbgPrint("%08x: ", Lines * 16);
|
||
for (i = 0; i < 4; pchar += 4, i++) {
|
||
if (pchar >= Length)
|
||
break;
|
||
DbgPrint("%08x ", *Buffer++);
|
||
}
|
||
DbgPrint("\n");
|
||
}
|
||
}
|
||
|
||
VOID
|
||
HalpOtherTestNec (
|
||
IN ULONG doOtherTest
|
||
)
|
||
{
|
||
if (!doOtherTest)
|
||
return;
|
||
|
||
|
||
DbgPrint("\n\n===== Additional Testing...\n");
|
||
{
|
||
CM_EISA_SLOT_INFORMATION EisaSlotInfo;
|
||
PCM_EISA_SLOT_INFORMATION EisaBuffer;
|
||
PCM_EISA_FUNCTION_INFORMATION EisaFunctionInfo;
|
||
ULONG slot, funcs, Length;
|
||
|
||
#define MAX_EISA_SLOT 4
|
||
|
||
DbgPrint("----- Read Eisa Configration:\n");
|
||
for (slot = 0; slot < MAX_EISA_SLOT; slot++) {
|
||
Length = HalGetBusData (EisaConfiguration,0,slot,&EisaSlotInfo,sizeof (EisaSlotInfo));
|
||
if (Length < sizeof(CM_EISA_SLOT_INFORMATION)) {
|
||
|
||
//
|
||
// The data is messed up since this should never occur
|
||
//
|
||
|
||
break;
|
||
}
|
||
Length = sizeof(CM_EISA_SLOT_INFORMATION) +
|
||
(sizeof(CM_EISA_FUNCTION_INFORMATION) * EisaSlotInfo.NumberFunctions);
|
||
EisaBuffer = ExAllocatePool(NonPagedPool, Length);
|
||
HalGetBusData (EisaConfiguration,0,slot,&EisaBuffer,Length);
|
||
// Print all Eisa Data
|
||
|
||
EisaFunctionInfo = (PCM_EISA_FUNCTION_INFORMATION)
|
||
((char *)&EisaBuffer + sizeof(CM_EISA_SLOT_INFORMATION));
|
||
|
||
DbgPrint("----- HalGetBusData Eisa Slot No=%d\n", slot);
|
||
DbgPrint("ReturnCode = 0x%x, ReturnFlags = 0x%x, MajorRev = 0x%x, MinorRev = 0x%x, \n",
|
||
EisaBuffer->ReturnCode, EisaBuffer->ReturnFlags,
|
||
EisaBuffer->MajorRevision, EisaBuffer->MinorRevision);
|
||
DbgPrint("CheckSum = 0x%x, NumberFunctions = 0x%x, FunctionInformation = 0x%x, CompressedId = 0x%x\n",
|
||
EisaBuffer->Checksum,
|
||
EisaBuffer->NumberFunctions,
|
||
EisaBuffer->FunctionInformation,
|
||
EisaBuffer->CompressedId);
|
||
for (funcs = 0; funcs < EisaBuffer->NumberFunctions; funcs++) {
|
||
DbgPrint("CompressId = 0x%x, IdSlotFlags1 = 0x%x, IdSlotFlags2 = 0x%x, MinorRevision = 0x%x, MajorRevision = 0x%x\n",
|
||
EisaFunctionInfo->CompressedId, EisaFunctionInfo->IdSlotFlags1,
|
||
EisaFunctionInfo->IdSlotFlags2, EisaFunctionInfo->MinorRevision,
|
||
EisaFunctionInfo->MajorRevision);
|
||
|
||
// EisaFunctionInfo->Selections[26];
|
||
// EisaFunctionInfo->FunctionFlags;
|
||
// EisaFunctionInfo->TypeString[80];
|
||
// EISA_MEMORY_CONFIGURATION EisaFunctionInfo->EisaMemory[9];
|
||
// EISA_IRQ_CONFIGURATION EisaFunctionInfo->EisaIrq[7];
|
||
// EISA_DMA_CONFIGURATION EisaFunctionInfo->EisaDma[4];
|
||
// EISA_PORT_CONFIGURATION EisaFunctionInfo->EisaPort[20];
|
||
// UCHAR EisaFunctionInfo->InitializationData[60];
|
||
EisaFunctionInfo++;
|
||
}
|
||
|
||
}
|
||
}
|
||
DbgBreakPoint ();
|
||
{
|
||
#define MEMORY_SPACE 0
|
||
#define IO_SPACE 1
|
||
PHYSICAL_ADDRESS cardAddress;
|
||
ULONG addressSpace = IO_SPACE;
|
||
PHYSICAL_ADDRESS PhysAddr;
|
||
|
||
PhysAddr.LowPart = 0;
|
||
PhysAddr.HighPart = 0;
|
||
|
||
|
||
|
||
DbgPrint("----- Translate Internal Bus Address(I/O): ");
|
||
HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
|
||
DbgPrint("Translate Eisa Bus Address(I/O): ");
|
||
addressSpace = IO_SPACE;
|
||
HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
|
||
DbgPrint("Translate Isa Bus Address(I/O): ");
|
||
addressSpace = IO_SPACE;
|
||
HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
|
||
DbgPrint("Translate PCI Bus Address(I/O): ");
|
||
addressSpace = IO_SPACE;
|
||
HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
|
||
DbgPrint("Translate Internal Bus Address(MEMORY): ");
|
||
addressSpace = MEMORY_SPACE;
|
||
HalTranslateBusAddress(Internal, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
|
||
DbgPrint("Translate Eisa Bus Address(MEMORY): ");
|
||
addressSpace = MEMORY_SPACE;
|
||
HalTranslateBusAddress(Eisa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
|
||
DbgPrint("Translate Isa Bus Address(MEMORY): ");
|
||
addressSpace = MEMORY_SPACE;
|
||
HalTranslateBusAddress(Isa, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
|
||
DbgPrint("Translate PCI Bus Address(MEMORY): ");
|
||
addressSpace = MEMORY_SPACE;
|
||
HalTranslateBusAddress(PCIBus, (ULONG)0, PhysAddr, &addressSpace, &cardAddress);
|
||
DbgPrint("H-AD: %x\tL-AD: %x\n\n", cardAddress.HighPart, cardAddress.LowPart);
|
||
}
|
||
DbgBreakPoint ();
|
||
|
||
{
|
||
KAFFINITY affinity;
|
||
KIRQL Irql;
|
||
ULONG Vec;
|
||
|
||
DbgPrint("----- GetInterruptVector internal\n");
|
||
Vec = HalGetInterruptVector(Internal, 0, 0, 0, &Irql, &affinity);
|
||
DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
|
||
|
||
DbgPrint("GetInterruptVector Eisa\n");
|
||
Vec = HalGetInterruptVector(Eisa, 0, 0, 0, &Irql, &affinity);
|
||
DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
|
||
|
||
DbgPrint("GetInterruptVector Isa\n");
|
||
Vec = HalGetInterruptVector(Isa, 0, 0, 0, &Irql, &affinity);
|
||
DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
|
||
|
||
DbgPrint("GetInterruptVector PCI\n");
|
||
Vec = HalGetInterruptVector(PCIBus, 0, 0, 0, &Irql, &affinity);
|
||
DbgPrint(" Irql = 0x%x, affinity = 0x%x, vector = 0x%x\n\n", Irql, affinity, Vec);
|
||
|
||
}
|
||
DbgBreakPoint ();
|
||
}
|
||
|
||
#endif // _R94A_
|
||
#endif // DBG
|
||
|
||
VOID
|
||
HalpSetBackToBackSpace(
|
||
IN PPCI_COMMON_CONFIG PciConfigRequired,
|
||
IN PPCI_COMMON_CONFIG PciConfigMapped,
|
||
IN PBUS_HANDLER BusHandler
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function sets memory space of PCI device to Fast Back-to-back register.
|
||
|
||
Arguments:
|
||
|
||
PciConfigRequired - Supplies the description of the memory space which
|
||
device required.
|
||
PciConfigMapped - Supplies the description of the memory space which
|
||
should be mapped to back-to-back space.
|
||
BusHandler - Supplies the pointer to Bushandler.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG NoBaseAddress;
|
||
ULONG BaseAddress, LowerAddress;
|
||
ULONG CurrentAddress;
|
||
ULONG FoundMemoryAddress;
|
||
ULONG i, j, Length;
|
||
|
||
#if DBG
|
||
DbgPrint(" check PCI-device!\n");
|
||
DbgPrint(" - VendorID ................ %04x\n", PciConfigMapped->VendorID);
|
||
DbgPrint(" - DeviceID ................ %04x\n", PciConfigMapped->DeviceID);
|
||
DbgPrint(" - back-to-back capable? ... %s\n", (PciConfigMapped->Status & 0x80) ? "o" : "x");
|
||
if (PciConfigMapped->BaseClass == 0x03
|
||
|| (PciConfigMapped->BaseClass == 0x00 && PciConfigMapped->SubClass == 0x01)){
|
||
DbgPrint(" - Is this GA device? ...... o\n");
|
||
} else {
|
||
DbgPrint(" - Is this GA device? ...... x\n");
|
||
}
|
||
#endif
|
||
|
||
KiAcquireSpinLock(&HalpPCIBackToBackLock);
|
||
|
||
//
|
||
// calulate memory region of this device.
|
||
//
|
||
|
||
switch (PCI_CONFIG_TYPE(PciConfigMapped)) {
|
||
case 0 :
|
||
NoBaseAddress = PCI_TYPE0_ADDRESSES;
|
||
break;
|
||
case 1:
|
||
NoBaseAddress = PCI_TYPE1_ADDRESSES;
|
||
break;
|
||
default:
|
||
// never come here.
|
||
// (already except by HalpAssignPCISlotResources)
|
||
return;
|
||
}
|
||
|
||
Length = 0;
|
||
BaseAddress = 0xffffffff;
|
||
LowerAddress = 0xffffffff;
|
||
FoundMemoryAddress = 0;
|
||
|
||
//
|
||
// get base and limit address
|
||
//
|
||
|
||
for (i = 0; i < NoBaseAddress; i++) {
|
||
CurrentAddress = PciConfigMapped->u.type0.BaseAddresses[i];
|
||
if (!(CurrentAddress & PCI_ADDRESS_IO_SPACE)
|
||
&& ((CurrentAddress & PCI_ADDRESS_MEMORY_TYPE_MASK) != 0x2)) {
|
||
|
||
//
|
||
// this is memory space and not need to map below 1M
|
||
//
|
||
|
||
CurrentAddress = CurrentAddress & 0xfffffff0;
|
||
if (CurrentAddress) {
|
||
FoundMemoryAddress = 1;
|
||
if (LowerAddress > CurrentAddress)
|
||
LowerAddress = CurrentAddress;
|
||
// scan for first set bit, that's the length & alignment
|
||
j = 1 << 4;
|
||
while (!(PciConfigRequired->u.type0.BaseAddresses[i] & j) && j)
|
||
j <<= 1;
|
||
#if DBG
|
||
DbgPrint(" - [%d]MemoryAddress ........ 0x%08x\n", i, CurrentAddress);
|
||
DbgPrint(" - [%d]Length ............... 0x%08x\n", i, j);
|
||
#endif
|
||
if (Length < j){
|
||
BaseAddress = CurrentAddress;
|
||
Length = j;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
#if DBG
|
||
DbgPrint(" - LowerAddress ............ 0x%08x\n", LowerAddress);
|
||
DbgPrint(" - BaseAddress ............. 0x%08x\n", BaseAddress);
|
||
DbgPrint(" - Length .................. 0x%08x\n", Length);
|
||
#endif
|
||
|
||
//
|
||
// If this device has memory space, then change memory limit
|
||
// value used be allocation for PCI memory space to
|
||
// 'LowerAddress - 1' of this device, otherwise release spinlock
|
||
// and return.
|
||
//
|
||
|
||
if (FoundMemoryAddress) {
|
||
HalpPCIMemoryLimit = LowerAddress - 1;
|
||
} else {
|
||
goto NotSetBackToBack;
|
||
}
|
||
|
||
//
|
||
// We do not support the PCI devices which connected under
|
||
// PCI-PCI bridge.
|
||
//
|
||
|
||
if (BusHandler->BusNumber == 0) {
|
||
|
||
if (PciConfigMapped->Status & 0x80) {
|
||
|
||
//
|
||
// This device is back-to-back capable.
|
||
// We can map the memory space of this device as
|
||
// back-to-back available.
|
||
// Set flag to indicate setting started.
|
||
//
|
||
|
||
if (!HalpPCIBackToBackReg0Start) {
|
||
HalpPCIBackToBackReg0Start = 1;
|
||
|
||
} else if (HalpPCIBackToBackReg0Start && !HalpPCIBackToBackReg0Open) {
|
||
HalpPCIBackToBackReg1Start = 1;
|
||
|
||
}
|
||
|
||
//
|
||
// BUGBUG: Some pci drivers assign its memory space by itself.
|
||
// This means that we can not control the memory address of
|
||
// such device by MemoryLimit value. So, we can not enable the
|
||
// following codes now.
|
||
// N.B. following code does not finished.
|
||
//
|
||
|
||
// if (!HalpFoundUncapablePCIDevice) {
|
||
//
|
||
// //
|
||
// // Uncapable device not mapped yet, so we can expand
|
||
// // back-to-back space.
|
||
// // We expand back-to-back space until uncapable device
|
||
// // is found.
|
||
// //
|
||
//
|
||
// if (back-to-back reg0 == initialize value){
|
||
// HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
|
||
// } else {
|
||
// back-to-back reg0 =+ add this memory range;
|
||
// MemoryLimit = the BaseAddress of this device;
|
||
// }
|
||
//
|
||
// if (PciConfigMapped->BaseClass == 0x03
|
||
// || (PciConfigMapped->BaseClass == 0x00
|
||
// && PciConfigMapped->SubClass == 0x01)) {
|
||
// HalpPCINumberOfMappedGA++;
|
||
// }
|
||
//
|
||
// } else {
|
||
|
||
if (HalpNumberOfPCIGA > 1) {
|
||
|
||
//
|
||
// There are some PCI-GA cards.
|
||
// If this is PCI-GA, then set to back-to-back,
|
||
// else we do not map.
|
||
//
|
||
|
||
if (PciConfigMapped->BaseClass == 0x03
|
||
|| (PciConfigMapped->BaseClass == 0x00
|
||
&& PciConfigMapped->SubClass == 0x01)) {
|
||
|
||
switch (HalpPCINumberOfMappedGA) {
|
||
|
||
case 0:
|
||
|
||
//
|
||
// We need set PCI-GA to both back-to-back space.
|
||
// The control reach here, it indicates PCI-GA
|
||
// not mapped to back-to-back space yet.
|
||
//
|
||
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
|
||
HalpPCIBackToBackReg0Open = 0;
|
||
break;
|
||
|
||
case 1:
|
||
|
||
//
|
||
// Control is transfered to this routine when one PCI-GA
|
||
// is already mapped. This means that reg0 had already used.
|
||
// We use reg1.
|
||
//
|
||
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
|
||
HalpPCIBackToBackReg1Open = 0;
|
||
|
||
}
|
||
|
||
HalpPCINumberOfMappedGA++;
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// There is only one-card as PCI-GA.
|
||
// We need set PCI-GA to back-to-back.
|
||
// If this is GA and reg0 is opened, then use reg0.
|
||
// If this is GA and reg0 is closeed, then use reg1.
|
||
//
|
||
|
||
if (PciConfigMapped->BaseClass == 0x03
|
||
|| (PciConfigMapped->BaseClass == 0x00
|
||
&& PciConfigMapped->SubClass == 0x01)) {
|
||
|
||
if (HalpPCIBackToBackReg0Open) {
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
|
||
HalpPCIBackToBackReg0Open = 0;
|
||
|
||
} else {
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
|
||
HalpPCIBackToBackReg1Open = 0;
|
||
|
||
}
|
||
|
||
HalpPCINumberOfMappedGA++;
|
||
|
||
} else {
|
||
|
||
//
|
||
// We can set only if reg0 or reg1 is not used.
|
||
//
|
||
|
||
if (HalpPCIBackToBackReg0Open) {
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
|
||
HalpPCIBackToBackReg0Open = 0;
|
||
|
||
} else if (HalpPCIBackToBackReg1Open){
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
|
||
HalpPCIBackToBackReg1Open = 0;
|
||
|
||
}
|
||
}
|
||
}
|
||
// }
|
||
|
||
} else {
|
||
|
||
//
|
||
// This is back-to-back uncapable.
|
||
//
|
||
|
||
HalpFoundUncapablePCIDevice = 1;
|
||
|
||
//
|
||
// if device is back-to-back uncapable<6C><65>map only GA.
|
||
//
|
||
|
||
if (PciConfigMapped->BaseClass == 0x03
|
||
|| (PciConfigMapped->BaseClass == 0x00
|
||
&& PciConfigMapped->SubClass == 0x01)) {
|
||
|
||
//
|
||
// In case of two or more cards are connected, the
|
||
// process is depend on the number of PCI-GA which
|
||
// already mapped.
|
||
// But we do not need to map 3rd PCI-GA or more.
|
||
//
|
||
|
||
if (HalpNumberOfPCIGA > 1) {
|
||
|
||
switch (HalpPCINumberOfMappedGA) {
|
||
|
||
case 0:
|
||
|
||
//
|
||
// Re-nitialize all values to void already settings,
|
||
// and use reg0
|
||
//
|
||
|
||
HalpPCIBackToBackReg0Start = 1;
|
||
HalpPCIBackToBackReg1Start = 0;
|
||
HalpPCIBackToBackReg0Open = 1;
|
||
HalpPCIBackToBackReg1Open = 1;
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
|
||
break;
|
||
|
||
case 1:
|
||
|
||
//
|
||
// Control is transfered to this routine when one PCI-GA
|
||
// is already mapped. This means that reg0 had already used.
|
||
// We use reg1.
|
||
//
|
||
// N.B. We do not know reg0 is opened or closed, so close
|
||
// reg0 here.
|
||
// (ex) 1st mapped ... capable = 1, not GA
|
||
// 2nd mapped ... capable = 0, GA
|
||
//
|
||
|
||
HalpPCIBackToBackReg0Open = 0;
|
||
HalpPCIBackToBackReg1Start = 1;
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
//
|
||
// There is only one-card as PCI-GA.
|
||
// If back-to-back reg0 not being useed, use reg0,
|
||
// else close the space of reg0 and use reg1.
|
||
// (Also when reg0 is closed, use reg1)
|
||
//
|
||
|
||
if (!HalpPCIBackToBackReg0Start) {
|
||
HalpPCIBackToBackReg0Start = 1;
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)0);
|
||
|
||
} else {
|
||
HalpPCIBackToBackReg0Open = 0;
|
||
HalpPCIBackToBackReg1Start = 1;
|
||
HalpSetBackToBackRegister(BaseAddress, Length, (ULONG)1);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// if being to set to back-to-back register, we have to close.
|
||
//
|
||
|
||
if (HalpPCIBackToBackReg0Start && HalpPCIBackToBackReg0Open) {
|
||
HalpPCIBackToBackReg0Open = 0;
|
||
|
||
} else if (HalpPCIBackToBackReg1Start && HalpPCIBackToBackReg1Open) {
|
||
HalpPCIBackToBackReg1Open = 0;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
NotSetBackToBack:
|
||
KiReleaseSpinLock(&HalpPCIBackToBackLock);
|
||
|
||
}
|
||
|
||
VOID
|
||
HalpSetBackToBackRegister(
|
||
IN ULONG BaseAddress,
|
||
IN ULONG Length,
|
||
IN ULONG Register
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function sets memory space of PCI device to Fast Back-to-back register.
|
||
|
||
Arguments:
|
||
|
||
BaseAddress - Supplies the address which to be mapped with back-to-back.
|
||
Length - Supplies the length which to be mapped with back-to-back.
|
||
Register - Supplies the back-to-back register number.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG Mask;
|
||
|
||
//
|
||
// make mask value
|
||
//
|
||
|
||
Mask = ~(Length - 1);
|
||
|
||
//
|
||
// set to back-to-back register
|
||
//
|
||
|
||
#if DBG
|
||
DbgPrint(" set back-to-back register.\n");
|
||
DbgPrint(" - Register ................ %d\n", Register);
|
||
DbgPrint(" - Address ................. 0x%08x\n", BaseAddress);
|
||
DbgPrint(" - Mask .................... 0x%08x\n", Mask);
|
||
#endif
|
||
|
||
WRITE_REGISTER_ULONG(
|
||
&DMA_CONTROL->PCIFastBackToBack[Register].Address,
|
||
BaseAddress
|
||
);
|
||
|
||
WRITE_REGISTER_ULONG(
|
||
&DMA_CONTROL->PCIFastBackToBack[Register].Mask,
|
||
Mask
|
||
);
|
||
|
||
}
|
||
|
||
ULONG
|
||
HalpGetNumberOfPCIGA(
|
||
IN ULONG NumberBuses
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function determines the number of PCI-GAs.
|
||
And initialize Fast Back-to-back register.
|
||
|
||
Arguments:
|
||
|
||
NumberBuses - Supplies the number of the PCI-buses.
|
||
|
||
Return Value:
|
||
|
||
number of PCI-GA.
|
||
|
||
--*/
|
||
|
||
{
|
||
UCHAR iBuffer[PCI_COMMON_HDR_LENGTH];
|
||
ULONG Bus;
|
||
ULONG Slot;
|
||
ULONG Function;
|
||
PBUS_HANDLER BusHandler;
|
||
PCI_SLOT_NUMBER SlotNumber;
|
||
PPCI_COMMON_CONFIG PciData;
|
||
ULONG Count;
|
||
ULONG Register;
|
||
USHORT commandValue;
|
||
|
||
Count = 0;
|
||
PciData = (PPCI_COMMON_CONFIG)&iBuffer;
|
||
|
||
//
|
||
// BUGBUG: Fast Back-to-back transaction can be used
|
||
// only bus number zero on this version.
|
||
// PCI devices connected on bus number 1 or more will
|
||
// be available with back-to-back on future.
|
||
//
|
||
|
||
NumberBuses = 1;
|
||
|
||
//
|
||
// Look for PCI controllers which have known work-arounds, and make
|
||
// sure they are applied.
|
||
//
|
||
|
||
SlotNumber.u.bits.Reserved = 0;
|
||
for (Bus = 0; Bus < NumberBuses; Bus++) {
|
||
BusHandler = HalpHandlerForBus (PCIBus, Bus);
|
||
|
||
for (Slot = 0; Slot < PCI_MAX_DEVICES; Slot++) {
|
||
SlotNumber.u.bits.DeviceNumber = Slot;
|
||
|
||
for (Function = 0; Function < PCI_MAX_FUNCTION; Function++) {
|
||
SlotNumber.u.bits.FunctionNumber = Function;
|
||
|
||
//
|
||
// Read PCI configuration information
|
||
//
|
||
|
||
HalpReadPCIConfig (BusHandler, SlotNumber, PciData, 0, PCI_COMMON_HDR_LENGTH);
|
||
|
||
//
|
||
// Check for chips with known work-arounds to apply
|
||
//
|
||
|
||
if (PciData->BaseClass == 0x03
|
||
|| (PciData->BaseClass == 0x00 && PciData->SubClass == 0x01)){
|
||
|
||
//
|
||
// This is Graphics Adapter. Inclement count.
|
||
//
|
||
|
||
Count++;
|
||
}
|
||
|
||
} // next PCI function
|
||
|
||
} // next PCI slot
|
||
|
||
} // next PCI bus
|
||
|
||
#if DBG
|
||
DbgPrint(" number of PCI-GA.\n");
|
||
DbgPrint(" - number of PCI-GA ........ %d\n", Count);
|
||
#endif
|
||
|
||
//
|
||
// Initialize Fast Back-to-back register.
|
||
//
|
||
|
||
for (Register = 0; Register < 2; Register++) {
|
||
WRITE_REGISTER_ULONG(
|
||
&DMA_CONTROL->PCIFastBackToBack[Register].Address,
|
||
INIT_VALUE_OF_BACK_TO_BACK_ADDR
|
||
);
|
||
|
||
WRITE_REGISTER_ULONG(
|
||
&DMA_CONTROL->PCIFastBackToBack[Register].Mask,
|
||
INIT_VALUE_OF_BACK_TO_BACK_MASK
|
||
);
|
||
}
|
||
|
||
commandValue = READ_REGISTER_USHORT(&DMA_CONTROL->PCICommand);
|
||
WRITE_REGISTER_USHORT(&DMA_CONTROL->PCICommand, (commandValue & ~0x0200));
|
||
|
||
return Count;
|
||
|
||
}
|