pci.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 394 行
C
394 行
// -----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// Copyright (c) 1995-2000 Microsoft Corporation. All rights reserved.
//
// -----------------------------------------------------------------------------
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <pc_ddk.h>
int __cdecl _inp (unsigned short);
unsigned short __cdecl _inpw (unsigned short);
unsigned long __cdecl _inpd (unsigned short);
int __cdecl _outp (unsigned short, int);
unsigned short __cdecl _outpw(unsigned short, unsigned short);
unsigned long __cdecl _outpd(unsigned short, unsigned long);
#define MAX_SUPPORTED_PCI_BUS 8
#define PCI_TYPE1_ADDRESS 0x0CF8
#define PCI_TYPE1_DATA 0x0CFC
#define PCI_TYPE2_FORWARD 0x0CFA
#define PCI_TYPE2_CSE 0x0CF8
// -------------------------------------
typedef struct _TYPE1_PCI_ADDRESS {
union {
struct {
ULONG Reserved:2;
ULONG Register:6;
ULONG Function:3;
ULONG Device:5;
ULONG Bus:8;
ULONG Reserved2:7;
ULONG ConfigurationAccess:1;
} bits;
ULONG AsULONG;
} u;
} TYPE1_PCI_ADDRESS, *PTYPE1_PCI_ADDRESS;
typedef struct _TYPE2_PCI_CSE {
union {
struct {
UCHAR SCE:1;
UCHAR Function:3;
UCHAR Key:4;
} bits;
UCHAR AsUCHAR;
} u;
} TYPE2_PCI_CSE, *PTYPE2_PCI_CSE;
typedef struct _TYPE2_PCI_ADDRESS {
union {
struct {
USHORT Reserved:2;
USHORT Register:6;
USHORT Device:4;
USHORT PCIConfigSpace:4; // Must be 0xC
} bits;
USHORT AsUSHORT;
} u;
} TYPE2_PCI_ADDRESS, *PTYPE2_PCI_ADDRESS;
// -------------------------------------
UCHAR ucPCIConfigMechanism;
UCHAR ucPCIMaxBus; // Highest Bus #+1, Inited to 0 on load
UCHAR ucPCIMaxDeviceNumber = PCI_MAX_DEVICES;
UCHAR ucPCIMaxDevice[MAX_SUPPORTED_PCI_BUS]; // For Each Bus, Highest Device Number + 1
CRITICAL_SECTION csPCIConfig;
BOOL bPCIInitialized;
// -------------------------------------
ULONG
PCIReadBusData(
IN ULONG BusNumber,
IN ULONG DeviceNumber,
IN ULONG FunctionNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
VOID
PCIInitBusInfo()
{
PCI_COMMON_CONFIG pciCommonConfig;
int bus, device;
DWORD dwResult;
if ( bPCIInitialized ) {
return;
}
bPCIInitialized = TRUE;
InitializeCriticalSection(&csPCIConfig);
if ( ucPCIConfigMechanism == 0 ) {
PBYTE pArgs;
pArgs = *(PBYTE *)0x801FFFFC;
if ( pArgs != 0 ) {
(ULONG)pArgs |= 0x80000000;
ucPCIConfigMechanism = pArgs[3] & 0x03;
ucPCIMaxBus = pArgs[3] >> 2;
}
if ( ucPCIConfigMechanism == 2 ) {
ucPCIMaxDeviceNumber = 16;
}
}
if ( ucPCIConfigMechanism == 0 ) {
RETAILMSG(1, (TEXT("No PCI bus\r\n")));
ucPCIConfigMechanism = (UCHAR)~0;
return;
}
//
// Enumerate the PCI busses
//
ucPCIMaxBus = 1;
for ( bus = 0; bus < ucPCIMaxBus; bus++ ) {
for ( device = 0; device < ucPCIMaxDeviceNumber; device++ ) {
dwResult = PCIReadBusData(
bus, device, 0, &pciCommonConfig, 0,
offsetof(PCI_COMMON_CONFIG, u.type1.IOBase));
if ( pciCommonConfig.VendorID != 0xFFFF ) {
if ( ucPCIMaxDevice[bus] <= device ) {
ucPCIMaxDevice[bus] = device + 1;
}
if ( bus == 0 && (pciCommonConfig.HeaderType & 0x7F) == 1 ) {
// Its a bridge
if ( ucPCIMaxBus <= pciCommonConfig.u.type1.SubordinateBusNumber ) {
ucPCIMaxBus = pciCommonConfig.u.type1.SubordinateBusNumber + 1;
if ( ucPCIMaxBus > (MAX_SUPPORTED_PCI_BUS + 1) ) {
RETAILMSG(1, (TEXT("Error: Too many PCI busses\r\n")));
ucPCIMaxBus = MAX_SUPPORTED_PCI_BUS + 1;
}
}
}
}
}
}
if ( ucPCIMaxBus == 1 && ucPCIMaxDevice[0] == 0 ) {
ucPCIMaxBus = (UCHAR)~0;
}
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ULONG
PCIReadBusData(
IN ULONG BusNumber,
IN ULONG DeviceNumber,
IN ULONG FunctionNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
{
PULONG pBuffer;
int registerOffset, endOffset;
registerOffset = Offset / sizeof(ULONG);
endOffset = registerOffset + (Length + sizeof(ULONG) - 1) / sizeof(ULONG);
pBuffer = Buffer;
if ( ucPCIConfigMechanism == 1 ) {
TYPE1_PCI_ADDRESS type1Address;
type1Address.u.AsULONG = 0;
type1Address.u.bits.ConfigurationAccess = 1;
type1Address.u.bits.Bus = BusNumber;
type1Address.u.bits.Device = DeviceNumber;
type1Address.u.bits.Function = FunctionNumber;
for ( ; registerOffset < endOffset; registerOffset++ ) {
type1Address.u.bits.Register = registerOffset;
_outpd((USHORT)PCI_TYPE1_ADDRESS, type1Address.u.AsULONG);
*pBuffer++ = _inpd((USHORT)PCI_TYPE1_DATA);
}
} else if ( ucPCIConfigMechanism == 2 ) {
TYPE2_PCI_CSE type2CSE;
TYPE2_PCI_ADDRESS type2Address;
type2CSE.u.bits.Key = type2CSE.u.bits.SCE = 0xFF;
type2CSE.u.bits.Function = (UCHAR)FunctionNumber;
type2Address.u.AsUSHORT = 0;
type2Address.u.bits.PCIConfigSpace = 0xC;
type2Address.u.bits.Device = (USHORT)DeviceNumber;
_outp((USHORT)PCI_TYPE2_FORWARD, (UCHAR)BusNumber);
INTERRUPTS_OFF();
_outp((USHORT)PCI_TYPE2_CSE, type2CSE.u.AsUCHAR);
for ( ; registerOffset < endOffset; registerOffset++ ) {
type2Address.u.bits.Register = registerOffset;
*pBuffer++ = _inpd((USHORT)type2Address.u.AsUSHORT);
}
_outp((USHORT)PCI_TYPE2_CSE, 0);
_outp((USHORT)PCI_TYPE2_FORWARD, 0);
INTERRUPTS_ON();
} else {
if ( ucPCIConfigMechanism == (UCHAR)~0 ) {
// No PCI bus
RETAILMSG(1, (TEXT("HalpReadBusData: No PCI bus\r\n")));
} else {
RETAILMSG(1, (TEXT("HalpReadBusData: Unknown config mechanism = 0x%2.2X\r\n"),
ucPCIConfigMechanism));
}
Length = 0;
}
return (Length);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ULONG
PCIGetBusDataByOffset(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
{
PCI_SLOT_NUMBER slotNumber;
if ( bPCIInitialized == FALSE )
PCIInitBusInfo();
if ( ucPCIMaxBus == (UCHAR)~0U || BusNumber >= ucPCIMaxBus ) {
RETAILMSG(1, (TEXT("Invalid bus number passed (%d >= %d)\r\n"),
BusNumber, ucPCIMaxBus));
return (0);
}
slotNumber.u.AsULONG = SlotNumber;
if ( slotNumber.u.bits.DeviceNumber >= ucPCIMaxDeviceNumber ) {
return (0);
}
EnterCriticalSection(&csPCIConfig);
Length = PCIReadBusData(
BusNumber, slotNumber.u.bits.DeviceNumber,
slotNumber.u.bits.FunctionNumber, Buffer, Offset, Length);
LeaveCriticalSection(&csPCIConfig);
return (Length);
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
ULONG
PCISetBusDataByOffset(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
{
PCI_SLOT_NUMBER slotNumber;
PULONG pBuffer;
int registerOffset, endOffset;
if ( bPCIInitialized == FALSE )
PCIInitBusInfo();
if ( ucPCIMaxBus == (UCHAR)~0U || BusNumber >= ucPCIMaxBus ) {
RETAILMSG(1, (TEXT("Invalid bus number passed (%d >= %d)\r\n"),
BusNumber, ucPCIMaxBus));
return (0);
}
slotNumber.u.AsULONG = SlotNumber;
if ( slotNumber.u.bits.DeviceNumber >= ucPCIMaxDeviceNumber ) {
return (0);
}
EnterCriticalSection(&csPCIConfig);
if ( ucPCIConfigMechanism == 1 ) {
TYPE1_PCI_ADDRESS type1Address;
type1Address.u.AsULONG = 0;
type1Address.u.bits.ConfigurationAccess = 1;
type1Address.u.bits.Bus = BusNumber;
type1Address.u.bits.Device = slotNumber.u.bits.DeviceNumber;
type1Address.u.bits.Function = slotNumber.u.bits.FunctionNumber;
registerOffset = Offset / sizeof(ULONG);
endOffset = registerOffset + (Length + 3) / sizeof(ULONG);
pBuffer = Buffer;
for ( ; registerOffset < endOffset; registerOffset++ ) {
type1Address.u.bits.Register = registerOffset;
_outpd((USHORT)PCI_TYPE1_ADDRESS, type1Address.u.AsULONG);
_outpd((USHORT)PCI_TYPE1_DATA, *pBuffer++);
}
} else if ( ucPCIConfigMechanism == 2 ) {
TYPE2_PCI_CSE type2CSE;
TYPE2_PCI_ADDRESS type2Address;
type2CSE.u.bits.Key = type2CSE.u.bits.SCE = 0xFF;
type2CSE.u.bits.Function = (UCHAR)slotNumber.u.bits.FunctionNumber;
type2Address.u.AsUSHORT = 0;
type2Address.u.bits.PCIConfigSpace = 0xC;
type2Address.u.bits.Device = (USHORT)slotNumber.u.bits.DeviceNumber;
_outp((USHORT)PCI_TYPE2_FORWARD, (UCHAR)BusNumber);
registerOffset = Offset >> 2;
endOffset = (registerOffset + Length + 3) >> 2;
pBuffer = Buffer;
INTERRUPTS_OFF();
_outp((USHORT)PCI_TYPE2_CSE, type2CSE.u.AsUCHAR);
for ( ; registerOffset < endOffset; registerOffset++ ) {
type2Address.u.bits.Register = registerOffset;
_outpd((USHORT)type2Address.u.AsUSHORT, *pBuffer++);
}
_outp((USHORT)PCI_TYPE2_CSE, 0);
_outp((USHORT)PCI_TYPE2_FORWARD, 0);
INTERRUPTS_ON();
} else if ( ucPCIConfigMechanism == (UCHAR)~0 ) {
// No PCI bus
RETAILMSG(1, (TEXT("HalGetBusDataByOffset: No PCI bus\r\n")));
return (0);
} else {
RETAILMSG(1, (TEXT("HalGetBusDataByOffset: Unknown config mechanism = 0x%2.2X\r\n"), ucPCIConfigMechanism));
return (0);
}
LeaveCriticalSection(&csPCIConfig);
return (Length);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?