pciinit.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,086 行 · 第 1/2 页
C
1,086 行
ULONG NumberOfRegs,
PULONG pMemSize,
PULONG pIoSize
)
/*++
Routine Description:
Read base address registers
Arguments:
None.
Return Value:
None.
--*/
{
ULONG Offset;
ULONG i;
ULONG BaseAddress;
ULONG Size;
ULONG Type;
BOOL LimitMem = FALSE;
BOOL SetExpROM = FALSE;
ULONG nRomSize = 0;
Offset = 0x10;
for (i = 0; i < NumberOfRegs; i++) {
PCIConfig_Write(Bus,Device,Function,Offset,0xFFFFFFFF);
BaseAddress = PCIConfig_Read(Bus,Device,Function,Offset);
if (BaseAddress & 1) {
//
// IO space
//
Size = ~(BaseAddress & 0xFFFFFFFC);
Type = PCI_TYPE_IO;
} else {
//
// memory space
// BUGBUG - don't properly handle the MEM20 case
//
Size = ~(BaseAddress & 0xFFFFFFF0);
Type = PCI_TYPE_MEM;
}
//
// check that the register is valid format
// should have consecutive high 1's and consecutive low 0's
//
if ((BaseAddress != 0) &&
(BaseAddress != 0xFFFFFFFF) &&
((Size + 1) & Size) == 0) {
// ***************************************************************
//
// Permedia3 hack
//
// The card asks for a lot of PCI memory. Limit the total memory
// allocated since we don't have much to dole out. We'll allow the
// smaller mappings (card registers, etc.) and at least one
// reasonably-sized mapping for the framebuffer/aperature. Any
// additional large mappings will be located outside the system
// bridge-reachable range (effectively disabling the mapping). This
// means the video driver must take steps to not use that range of
// PCI memory addresses. Because the driver need be aware of the
// situation, this code is card-specific.
//
if (PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_ID) == PERM3_VENDEVID)
{
if (LimitMem)
{
PCIConfig_Write(Bus,Device,Function,Offset,0xFFFFFFFF);
goto NextDev;
}
// Let's consider anything above 32MB large and assume that
// all the smaller buffers were first in the BAR line-up.
// After this, we'll "disable" any BARs that request PCI memory.
if (Size > (32 * 1024 * 1024))
LimitMem = TRUE;
// The Permedia3 needs a card-specific 64KB mapping for the
// expansion ROM (details the cards memory setup sequence).
if (!SetExpROM)
{
SetExpROM = TRUE;
// Determine the required ROM expansion mapping size.
//
PCIConfig_Write(Bus,Device,Function,0x30,0xFFFFFFFF);
BaseAddress = PCIConfig_Read(Bus,Device,Function,Offset);
nRomSize = ~(BaseAddress & 0xFFFFFFF0);
SpaceDesc[nSpaceDesc].Bus = Bus;
SpaceDesc[nSpaceDesc].Device = Device;
SpaceDesc[nSpaceDesc].Function = Function;
SpaceDesc[nSpaceDesc].Offset = 0x30; // Exp ROM Offset
SpaceDesc[nSpaceDesc].Bridge = 0;
SpaceDesc[nSpaceDesc].IoSize = 0;
SpaceDesc[nSpaceDesc].MemSize = nRomSize;
*pMemSize += nRomSize + 1;
++nSpaceDesc;
if (nSpaceDesc == MAX_SPACE)
return FALSE;
}
}
//
// Add to list so allocate space later
//
SpaceDesc[nSpaceDesc].Bus = Bus;
SpaceDesc[nSpaceDesc].Device = Device;
SpaceDesc[nSpaceDesc].Function = Function;
SpaceDesc[nSpaceDesc].Offset = Offset;
SpaceDesc[nSpaceDesc].Bridge = 0;
SpaceDesc[nSpaceDesc].IoSize = 0;
SpaceDesc[nSpaceDesc].MemSize = 0;
if (Type == PCI_TYPE_IO) {
*pIoSize += Size + 1;
SpaceDesc[nSpaceDesc].IoSize = Size + 1;
} else {
*pMemSize += Size + 1;
SpaceDesc[nSpaceDesc].MemSize = Size + 1;
}
pci_printf("BAR %d %d %d 0x%x %d 0x%X %s\r\n",Bus,Device,Function,Offset,Type,Size+1,(Type == PCI_TYPE_IO)? "IO":"MEM");
nSpaceDesc++;
if (nSpaceDesc == MAX_SPACE) {
return FALSE;
}
}
NextDev:
//
// check for 64 bit device - BAR is twice as big
//
if ((BaseAddress & 0x7) == 0x4) {
//
// 64 bit device - BAR is twice as wide - zero out high part
//
Offset += 4;
PCIConfig_Write(Bus,Device,Function,Offset,0x0);
}
Offset += 4;
}
return TRUE;
}
BOOL
PciInitAllocateIoSpace(
ULONG IoUpperBound,
ULONG IoLowerBound,
ULONG Bus
)
/*++
Routine Description:
Description.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG i;
ULONG j;
ULONG IoBase;
PSPACE_DESC pSpace;
pci_printf("AllocateIo %d %X %X\r\n",Bus,IoUpperBound,IoLowerBound);
//
// Sort the space descriptors for a given bus by size
//
for (i = 31; i >= 1; i--) {
for (j = 0; j < nSpaceDesc; j++) {
pSpace = &SpaceDesc[j];
if ((pSpace->Bus == Bus) && ((pSpace->IoSize) & (1 << i))) {
if (pSpace->Bridge == 0) {
IoUpperBound -= pSpace->IoSize;
PCIConfig_Write(pSpace->Bus,
pSpace->Device,
pSpace->Function,
pSpace->Offset,
IoUpperBound);
pSpace->IoBase = IoUpperBound;
pSpace->SortOrder = SortOrder++;
pci_printf("AllocateIO %d %d %d %x %x (%X)\r\n",pSpace->Bus, pSpace->Device, pSpace->Function, pSpace->Offset, IoUpperBound,pSpace->IoSize);
} else {
if (!PciInitAllocateIoSpace(
IoUpperBound,
IoUpperBound - pSpace->IoSize,
pSpace->SecondaryBus)) {
return FALSE;
}
//
// init I/O base and limit registers
//
IoBase = PCIConfig_Read(pSpace->Bus,
pSpace->Device,
pSpace->Function,
PCIBRIDGE_IO);
((PBRIDGE_IO)(&IoBase))->IoLimit.Address =
(BYTE)(((IoUpperBound - 1) & 0xF000) >> 12);
//((PBRIDGE_IO)(&IoBase))->IoLimit.DecodeType = Something;
IoUpperBound -= pSpace->IoSize;
((PBRIDGE_IO)(&IoBase))->IoBase.Address =
(BYTE)(((IoUpperBound) & 0xF000) >> 12);
//((PBRIDGE_IO)(&IoBase))->IoBase.DecodeType = Something;
pci_printf("AllocateIOLimit %d %d %d %x %x (%X)\r\n",pSpace->Bus, pSpace->Device, pSpace->Function, pSpace->Offset, IoBase,pSpace->IoSize);
PCIConfig_Write(pSpace->Bus,
pSpace->Device,
pSpace->Function,
PCIBRIDGE_IO,
IoBase);
pSpace->IoBase = IoBase;
pSpace->SortOrder = SortOrder++;
}
}
if (IoUpperBound < IoLowerBound) {
return FALSE;
}
}
}
return TRUE;
}
BOOL
PciInitAllocateMemSpace(
ULONG MemUpperBound,
ULONG MemLowerBound,
ULONG Bus
)
/*++
Routine Description:
Description.
Arguments:
None.
Return Value:
None.
--*/
{
ULONG i;
ULONG j;
ULONG MemBase;
PSPACE_DESC pSpace;
pci_printf("AllocateMem %d %X %X\r\n",Bus,MemUpperBound,MemLowerBound);
//
// Sort the space descriptors for a given bus by size
//
for (i = 31; i >= 1; i--) {
for (j = 0; j < nSpaceDesc; j++) {
pSpace = &SpaceDesc[j];
if ((pSpace->Bus == Bus) && ((pSpace->MemSize) & (1 << i))) {
if (pSpace->Bridge == 0) {
MemUpperBound -= pSpace->MemSize;
PCIConfig_Write(pSpace->Bus,
pSpace->Device,
pSpace->Function,
pSpace->Offset,
MemUpperBound);
pSpace->MemBase = MemUpperBound;
pSpace->SortOrder = SortOrder++;
pci_printf("AllocateMem %d %d %d %x %x (%X)\r\n",pSpace->Bus, pSpace->Device, pSpace->Function, pSpace->Offset, MemUpperBound,pSpace->MemSize);
} else {
if (!PciInitAllocateMemSpace(
MemUpperBound,
MemUpperBound - pSpace->MemSize,
pSpace->SecondaryBus)) {
return FALSE;
}
//
// Init mem base and limit registers
//
((PBRIDGE_MEM)(&MemBase))->MemoryLimit.Address =
(WORD)(((MemUpperBound - 1) & 0xFFF00000) >> 20);
//((PBRIDGE_MEM)(&MemBase))->MemoryLimit.DecodeType = Something;
MemUpperBound -= pSpace->MemSize;
((PBRIDGE_MEM)(&MemBase))->MemoryBase.Address =
(WORD)(((MemUpperBound) & 0xFFF00000) >> 20);
//((PBRIDGE_MEM)(&MemBase))->MemoryBase.DecodeType = Something;
pci_printf("AllocateMemLimit %d %d %d %x %x (%X)\r\n",pSpace->Bus, pSpace->Device, pSpace->Function, pSpace->Offset, MemBase,pSpace->MemSize);
PCIConfig_Write(pSpace->Bus,
pSpace->Device,
pSpace->Function,
PCIBRIDGE_MEMORY,
MemBase);
pSpace->MemBase = MemBase;
pSpace->SortOrder = SortOrder++;
}
}
if (MemUpperBound < MemLowerBound) {
return FALSE;
}
}
}
return TRUE;
}
VOID
PciInitListDevices(
)
/*++
Routine Description:
Routine to list all PCI devices found
Arguments:
None.
Return Value:
None.
--*/
{
ULONG i,j;
EdbgOutputDebugString("\n\rList of Detected PCI Devices");
EdbgOutputDebugString("\n\r-----------------------------------------------------------\n\r");
for (i = 0; i < nDev; i++) {
EdbgOutputDebugString("ID:%X Bus:%X IDSEL:%d Funct:%d Class:%X IRQ:%X ",
pDev[i].VendorID,
pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCI_CONFIG_CLASS_REVISION),
PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCI_CONFIG_INTERRUPT) & 0xff);
if (pDev[i].Bus == 0) {
switch (pDev[i].Device) {
case IDSEL_SLOT1:
EdbgOutputDebugString("PCI_PCI Bridge");
break;
case IDSEL_SLOT2:
EdbgOutputDebugString("PCI Slot #3");
break;
case IDSEL_SLOT3:
EdbgOutputDebugString("PCI Slot #4");
break;
case IDSEL_VRC5074:
EdbgOutputDebugString("Vrc5476");
break;
case IDSEL_ENET:
EdbgOutputDebugString("Ethernet");
break;
case IDSEL_M1543:
EdbgOutputDebugString("ISA Bridge");
break;
case IDSEL_IDE:
EdbgOutputDebugString("IDE Controller");
break;
case IDSEL_PMU:
EdbgOutputDebugString("PMU Controller");
break;
case IDSEL_USB:
EdbgOutputDebugString("USB Controller");
break;
}
}
EdbgOutputDebugString("\r\n");
if ( PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCI_CONFIG_HEAD) & 0x00010000) {
EdbgOutputDebugString("BARs %X %X MemBase: %X IoBase: %X",
PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCI_CONFIG_BASE0),
PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCI_CONFIG_BASE1),
PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCIBRIDGE_MEMORY),
PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
PCIBRIDGE_IO));
} else {
EdbgOutputDebugString("BARs:");
for (j = PCI_CONFIG_BASE0; j <= PCI_CONFIG_BASE5; j += 4 ) {
//EdbgOutputDebugString(" %08lx",
EdbgOutputDebugString(" %x",
PCIConfig_Read(pDev[i].Bus,
pDev[i].Device,
pDev[i].Function,
j));
}
}
EdbgOutputDebugString("\n\r\n\r");
}
EdbgOutputDebugString("Bus Dev Fnct Off MemBase MemSize IoBase IoSize\r\n");
for (i = 0; i < SortOrder; i++) {
for (j = 0; j < nSpaceDesc; j++) {
if (SpaceDesc[j].SortOrder == i) {
EdbgOutputDebugString("%d %d %d %X %X %X %X %X\r\n",
SpaceDesc[j].Bus,
SpaceDesc[j].Device,
SpaceDesc[j].Function,
SpaceDesc[j].Offset,
SpaceDesc[j].MemBase,
SpaceDesc[j].MemSize,
SpaceDesc[j].IoBase,
SpaceDesc[j].IoSize);
}
}
}
}
BOOL
PciInitSearchForDevice(
ULONG VendorID,
PULONG Bus,
PULONG Device,
PULONG Function
)
/*++
Routine Description:
Search for device by vendorId
Arguments:
VendorId - supplies key for search
Return Value:
Bus,Device,Function return location of device
--*/
{
ULONG i;
for (i = 0; i < nDev; i++) {
if (pDev[i].VendorID == VendorID) {
*Bus = pDev[i].Bus;
*Device = pDev[i].Device;
*Function = pDev[i].Function;
return TRUE;
}
}
return FALSE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?