📄 pci.c
字号:
/*++
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
Module Name: pci.c
Abstract: Boot loader PCI access routines.
Functions:
PCIReadBusData
PCIInitBusInfo
PCIGetBusDataByOffset
PCISetBusDataByOffset
Notes:
--*/
#define WINCEMACRO 1
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include "bldr.h"
// Preprocessor definitions.
//
#define MAX_SUPPORTED_PCI_BUS 8
#define PCI_TYPE1_ADDRESS 0x0CF8
#define PCI_TYPE1_DATA 0x0CFC
// Type definitions.
//
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;
// Global variables.
//
UCHAR ucPCIMaxBus = 0; // 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
BOOL bPCIInitialized = FALSE;
const LPSTR BaseClass[] =
{
TEXT("PRE_20"),
TEXT("MASS_STORAGE_CTLR"),
TEXT("NETWORK_CTLR"),
TEXT("DISPLAY_CTLR"),
TEXT("MULTIMEDIA_DEV"),
TEXT("MEMORY_CTLR"),
TEXT("BRIDGE_DEV"),
TEXT("SIMPLE_COMMS_CTLR"),
TEXT("BASE_SYSTEM_DEV"),
TEXT("INPUT_DEV"),
TEXT("DOCKING_STATION"),
TEXT("PROCESSOR"),
TEXT("SERIAL_BUS_CTLR")
};
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;
TYPE1_PCI_ADDRESS type1Address;
registerOffset = Offset / sizeof(ULONG);
endOffset = registerOffset + (Length + sizeof(ULONG) - 1) / sizeof(ULONG);
pBuffer = Buffer;
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);
}
return(Length);
}
void PCIInitBusInfo(void)
{
if ( bPCIInitialized ) {
return;
}
bPCIInitialized = TRUE;
ucPCIMaxBus = 8;
DEBUGMSG(ZONE_INFO, (TEXT("PCI devices = %d\r\n"), ucPCIMaxBus));
if ( ucPCIMaxBus == 1 && ucPCIMaxDevice[0] == 0 ) {
ucPCIMaxBus = (UCHAR)~0;
}
}
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);
}
Length = PCIReadBusData(
BusNumber, slotNumber.u.bits.DeviceNumber,
slotNumber.u.bits.FunctionNumber, Buffer, Offset, Length);
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;
TYPE1_PCI_ADDRESS type1Address;
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);
}
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++);
}
return(Length);
}
BYTE GetMaxBusNumber(void)
{
PCI_SLOT_NUMBER slotNumber;
PCI_COMMON_CONFIG pciConfig;
int bus, device, function;
int length;
BYTE bMaxBus = 0;
//
// Scan bus 0 for bridges. They'll tell us the number of buses
//
bus = 0;
for (device = 0; device < PCI_MAX_DEVICES; device++)
{
slotNumber.u.bits.DeviceNumber = device;
for (function = 0; function < PCI_MAX_FUNCTION; function++)
{
slotNumber.u.bits.FunctionNumber = function;
length = PCIGetBusDataByOffset(bus, slotNumber.u.AsULONG,
&pciConfig, 0, sizeof(pciConfig));
if (length == 0 || pciConfig.VendorID == 0xFFFF)
break;
if (pciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV && pciConfig.SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)
{
if (pciConfig.u.type1.SubordinateBusNumber > bMaxBus)
{
bMaxBus = pciConfig.u.type1.SubordinateBusNumber;
}
}
if (function == 0 && !(pciConfig.HeaderType & 0x80))
break;
}
if (length == 0)
break;
}
return(bMaxBus);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -