pci.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 351 行
C
351 行
/*++
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, 1996, 1997 Microsoft Corporation
Module Name:
pci.c
Abstract:
This file implements the platform specific WDM routines for accessing PCI
configuration.
Notes:
--*/
#define WINCEMACRO 1
#include <windows.h>
#include <nkintr.h>
#undef DeviceIoControl
#include <oalio.h>
#include <wdmhal.h>
#include <altoona.h>
#include <hal.h>
#define MAX_SUPPORTED_PCI_BUS 8
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;
// Initialized to 0 on load
UCHAR ucPCIMaxBus; // Highest Bus number + 1
UCHAR ucPCIMaxDevice[MAX_SUPPORTED_PCI_BUS]; // For Each Bus, Highest Device Number + 1
//CRITICAL_SECTION csPCIConfig;
ULONG
PCIReadBusData(
IN TYPE1_PCI_ADDRESS Type1Address,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
);
VOID
PCIInitBusInfo()
{
PCI_COMMON_CONFIG pciCommonConfig;
TYPE1_PCI_ADDRESS type1Address;
int bus, device;
DWORD dwResult;
// InitializeCriticalSection(&csPCIConfig);
//
// Enumerate the PCI busses
//
ucPCIMaxBus = 1;
for (bus = 0; bus < ucPCIMaxBus; bus++)
{
for (device = 0; device < PCI_MAX_DEVICES; device++)
{
type1Address.u.AsULONG = 0;
type1Address.u.bits.ConfigurationAccess = 1;
type1Address.u.bits.Bus = bus;
type1Address.u.bits.Device = device;
type1Address.u.bits.Function = 0;
dwResult = PCIReadBusData(
type1Address, &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))
{
OEMWriteDebugString(
TEXT("Error: Too many PCI busses\r\n"));
ucPCIMaxBus = MAX_SUPPORTED_PCI_BUS + 1;
}
}
}
}
}
}
if (ucPCIMaxBus == 1 && ucPCIMaxDevice[0] == 0)
{
OEMWriteDebugString(TEXT("No PCI device detected\r\n"));
ucPCIMaxBus = (UCHAR)~0;
}
}
ULONG
PCIReadBusData(
IN TYPE1_PCI_ADDRESS Type1Address,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
{
PULONG pBuffer;
int registerOffset, endOffset;
ULONG InitSaveLo;
ULONG InitSaveHi;
ULONG Slot = Type1Address.u.bits.Device + 11;
registerOffset = Offset / sizeof(ULONG);
endOffset = registerOffset + (Length + (sizeof(ULONG) - 1)) / sizeof(ULONG);
pBuffer = Buffer;
//
// Can't access Vrc5074's config registers via PCI bus
//
if (Type1Address.u.bits.Bus == 0)
if (Slot == IDSEL_VRC5074 ) {
*pBuffer = 0xffff;
return sizeof(SHORT);
}
else if ( Slot > 31) {
*pBuffer = 0xffff;
return sizeof(SHORT);
}
for ( ; registerOffset < endOffset; registerOffset++)
{
Type1Address.u.bits.Register = registerOffset;
INTERRUPTS_OFF();
InitSaveLo = pVRC5074->PCIINIT1.Low;
InitSaveHi = pVRC5074->PCIINIT1.Hi;
pVRC5074->PCIINIT1.Hi = 0;
pVRC5074->PCIINIT1.Lo = PCIINIT_TYPE_CONFIG |
PCIINIT_ACCESS_32 |
((Type1Address.u.bits.Bus == 0)
? PCIINIT_CONFIGTYPE0 : PCIINIT_CONFIGTYPE1);
if (Type1Address.u.bits.Bus == 0) {
//
// If slot number is greater than the config space size,
// then the PCIADD field of the PCIINIT register must be used
//
if ((1 << Slot) >= PCI_CONFIG_SIZE) {
pVRC5074->PCIINIT1.Lo |= (1 << Slot);
if (registerOffset == 0)
*(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
KSEG1_BASE
) = 0;
*pBuffer++ = *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
KSEG1_BASE |
(Type1Address.u.bits.Function << 8) |
(registerOffset<<2)
);
} else {
if (registerOffset == 0)
*(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
KSEG1_BASE |
(1 << Slot)
) = 0;
*pBuffer++ = *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
KSEG1_BASE |
(1 << Slot) |
(Type1Address.u.bits.Function << 8) |
(registerOffset<<2)
);
}
}
else {
if (registerOffset == 0)
*(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
KSEG1_BASE |
(Type1Address.u.AsULONG & 0x00ffffff)
) = 0;
*pBuffer++ = *(PULONG)( PHYS_ADDR_PCI_CFG_BASE |
KSEG1_BASE |
(Type1Address.u.AsULONG & 0x00ffffff)
);
}
pVRC5074->PCIINIT1.Lo = InitSaveLo;
pVRC5074->PCIINIT1.Hi = InitSaveHi;
INTERRUPTS_ON();
if (registerOffset == 0)
{
PUSHORT pVendorID = (PUSHORT)(pBuffer - 1);
if ((*pVendorID & 0xFF) == 0xFF || *pVendorID == 0)
{
*pVendorID = 0xFFFF;
}
if (*pVendorID == 0xFFFF)
{
Length = 2;
break;
}
}
}
return Length;
}
ULONG
PCIGetBusDataByOffset(
IN ULONG BusNumber,
IN ULONG SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
)
{
TYPE1_PCI_ADDRESS type1Address;
type1Address.u.AsULONG = 0;
type1Address.u.bits.ConfigurationAccess = 1;
type1Address.u.bits.Bus = BusNumber;
type1Address.u.bits.Device = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.DeviceNumber;
type1Address.u.bits.Function = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.FunctionNumber;
return PCIReadBusData(type1Address, Buffer, Offset, 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;
TYPE1_PCI_ADDRESS type1Address;
ULONG InitSaveLo;
ULONG InitSaveHi;
slotNumber.u.AsULONG = SlotNumber;
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 + (sizeof(ULONG) - 1)) / sizeof(ULONG);
pBuffer = Buffer;
for ( ; registerOffset < endOffset; registerOffset++) {
type1Address.u.bits.Register = registerOffset;
INTERRUPTS_OFF();
InitSaveLo = pVRC5074->PCIINIT1.Low;
InitSaveHi = pVRC5074->PCIINIT1.Hi;
pVRC5074->PCIINIT1.Hi = 0;
pVRC5074->PCIINIT1.Lo = PCIINIT_TYPE_CONFIG | PCIINIT_ACCESS_32 | ((type1Address.u.bits.Bus == 0) ? PCIINIT_CONFIGTYPE0 : PCIINIT_CONFIGTYPE1);
if (type1Address.u.bits.Bus == 0) {
//
// If slot number is greater than the config space size,
// then the PCIADD field of the PCIINIT register must be used
//
if ((1 << (type1Address.u.bits.Device+11)) >= PCI_CONFIG_SIZE) {
pVRC5074->PCIINIT1.Lo |= 1 << (type1Address.u.bits.Device+11);
*(PULONG)(PHYS_ADDR_PCI_CFG_BASE | (type1Address.u.bits.Function << 8) | KSEG1_BASE | (registerOffset<<2)) = *pBuffer++;
} else {
*(PULONG)(PHYS_ADDR_PCI_CFG_BASE | KSEG1_BASE | (type1Address.u.bits.Function << 8) | (1 << (type1Address.u.bits.Device+11)) | (registerOffset<<2)) = *pBuffer++;
}
} else {
*(PULONG)( PHYS_ADDR_PCI_CFG_BASE | KSEG1_BASE | (type1Address.u.AsULONG & 0x00ffffff)) = *pBuffer++;
}
pVRC5074->PCIINIT1.Lo = InitSaveLo;
pVRC5074->PCIINIT1.Hi = InitSaveHi;
INTERRUPTS_ON();
}
return Length;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?