pciinit.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,086 行 · 第 1/2 页
C
1,086 行
/*++
Copyright (c) 1998 Microsoft Corporation
Module Name:
Filename
Abstract:
Routines to initialize PCI bus
Author:
John Cooper (johncoop) 98-Jan-12
Environment:
Wince Boot rom
Revision History:
--*/
#include <windows.h>
#include <alt_def.h>
#include <oalintr.h>
#include "romdef.h"
#include "rev.h"
#include "..\..\kernel\hal\ethernet.h"
#include <eglobal.h>
#include "ether.h"
#include "pciinit.h"
#include "vrc5074.h"
BOOL
PciInitBus(
ULONG Bus,
PULONG pSubordinateBus,
PULONG pMemSize,
PULONG pIoSize
);
BOOL
PciInitDevice(
ULONG Bus,
ULONG Device,
ULONG Function,
PULONG pMemSize,
PULONG pIoSize
);
BOOL
PciInitBridge(
ULONG Bus,
ULONG Device,
ULONG Function,
PULONG pSubordinateBus,
PULONG pMemSize,
PULONG pIoSize
);
BOOL
PciInitCheckBARs(
ULONG Bus,
ULONG Device,
ULONG Function,
ULONG NumberOfRegs,
PULONG pMemSize,
PULONG pIoSize
);
BOOL
PciInitAllocateMemSpace(
ULONG MemUpperBound,
ULONG MemLowerBound,
ULONG Bus
);
BOOL
PciInitAllocateIoSpace(
ULONG IoUpperBound,
ULONG IoLowerBound,
ULONG Bus
);
#define MAX_SPACE 120
#define MAX_DEVICE 32
#define PCIBRIDGE_CNTRL (0xf << 2) //sudhakar
#pragma warning (disable: 4002)
#define pci_printf()
//#define pci_printf EdbgOutputDebugString
ULONG nSpaceDesc;
SPACE_DESC SpaceDesc[MAX_SPACE];
ULONG nDev;
ULONG SortOrder;
PCI_DEVICE pDev[MAX_DEVICE];
// *** Permedia3 special case ***
#define PERM3_VENDEVID 0x000A3D3D
BOOL
PciInit(
)
/*++
Routine Description:
Initialize all PCI
Arguments:
None.
Return Value:
None.
--*/
{
ULONG SubordinateBus = 0;
ULONG MemSize = 0;
ULONG IoSize = 0;
BOOL Status = TRUE;
ULONG Reg;
SortOrder = 0;
nSpaceDesc = 0;
nDev = 0;
if (!PciInitBus(0,&SubordinateBus,&MemSize,&IoSize)) {
EdbgOutputDebugString("Too many PCI devices initializing PCI Bus\r\n");
return FALSE;
}
if (MemSize > (PCI_BUS0_MEM_LIMIT - PCI_BUS0_MEM_BASE)) {
EdbgOutputDebugString("Not enough memory space allocated for PCI Bus (0x%x requested)\r\n", MemSize);
Status = FALSE;
}
if (IoSize > (PCI_BUS0_IO_LIMIT - PCI_BUS0_IO_BASE)) {
EdbgOutputDebugString("Not enough I/O space allocated for PCI Bus (0x%x requested)\r\n", IoSize);
Status = FALSE;
}
if (!PciInitAllocateMemSpace(PCI_BUS0_MEM_LIMIT, PCI_BUS0_MEM_BASE, 0)) {
Status = FALSE;
EdbgOutputDebugString("Failure allocating PCI memory space\r\n");
}
if (!PciInitAllocateIoSpace(PCI_BUS0_IO_LIMIT, PCI_BUS0_IO_BASE, 0)) {
Status = FALSE;
EdbgOutputDebugString("Failure allocation PCI IO space\r\n");
}
//
// Altoona specific interrupt routing
//
Reg = PCIConfig_Read(0,IDSEL_USB,0,0x3C);
PCIConfig_Write(0,IDSEL_USB,0,0x3C,(Reg & 0xFFFFFF00) | ALNINTR_IRQ5);
Reg = PCIConfig_Read(0,IDSEL_IDE,0,0x3C);
PCIConfig_Write(0,IDSEL_IDE,0,0x3C,(Reg & 0xFFFFFF00) | ALNINTR_IRQ14);
Reg = PCIConfig_Read(0,IDSEL_ENET,0,0x3C);
PCIConfig_Write(0,IDSEL_ENET,0,0x3C,(Reg & 0xFFFFFF00) | ALNINTR_PCI_INTB);
Reg = PCIConfig_Read(0,IDSEL_SLOT2,0,0x3C);
PCIConfig_Write(0,IDSEL_SLOT2,0,0x3C,(Reg & 0xFFFFFF00) | ALNINTR_PCI_INTD);
Reg = PCIConfig_Read(0,IDSEL_SLOT3,0,0x3C);
PCIConfig_Write(0,IDSEL_SLOT3,0,0x3C,(Reg & 0xFFFFFF00) | ALNINTR_PCI_INTA);
Reg = PCIConfig_Read(0,IDSEL_ISABRIDGE,0,0x3C);
PCIConfig_Write(0,IDSEL_PMU,0,0x3C,(Reg & 0xFFFFFF00) | ALNINTR_PCI_INTC);
Reg = PCIConfig_Read(0,IDSEL_PMU,0,0x3C);
PCIConfig_Write(0,IDSEL_PMU,0,0x3C,(Reg & 0xFFFFFF00) | ALNINTR_NULL);
//
// Vrc5074 was excluded from everything that happened so far.
// Come back now and do it manually
//
PciInitDevice(0,IDSEL_VRC5074,0,&MemSize,&IoSize);
PCIConfig_Write(0,IDSEL_VRC5074,0,0x18,0);
pDev[nDev].Bus = 0;
pDev[nDev].Device = IDSEL_VRC5074;
pDev[nDev].Function = 0;
pDev[nDev].VendorID = VRC5074_PCIVID;
nDev++;
nSpaceDesc--;
SpaceDesc[nSpaceDesc].Bus = 0;
SpaceDesc[nSpaceDesc].Device = IDSEL_VRC5074;
SpaceDesc[nSpaceDesc].Function = 0;
SpaceDesc[nSpaceDesc].Offset = 0x18;
SpaceDesc[nSpaceDesc].Bridge = 0;
SpaceDesc[nSpaceDesc].IoSize = 0;
SpaceDesc[nSpaceDesc].MemSize = 0x04000000;
SpaceDesc[nSpaceDesc].SortOrder = SortOrder++;
nSpaceDesc++;
return Status;
}
BOOL
PciInitBus(
ULONG Bus,
PULONG pSubordinateBus,
PULONG pMemSize,
PULONG pIoSize
)
/*++
Routine Description:
Search for devices on bus to initialize
Arguments:
Bus - supplies bus number
Return Value:
None.
--*/
{
ULONG Device;
ULONG VendorID;
ULONG HeaderType;
ULONG Function;
pci_printf("InitBus %d\r\n",Bus);
//
// Loop through all device numbers (slots)
//
for (Device = 0; Device < 32; Device++) {
//
// Loop through all functions
//
for (Function = 0; Function < 8; Function++) {
//
// Check Device Present
//
PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_BASE0,0xFFFFFFFF);
VendorID = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_ID);
if (((VendorID & 0xFFFF0000) != 0xFFFF0000) &&
((VendorID & 0x0000FFFF) != 0x0000FFFF) &&
((VendorID & 0x0000FFFF) != 0x00000000) &&
(VendorID != VRC5074_PCIVID)) {
pDev[nDev].Bus = Bus;
pDev[nDev].Device = Device;
pDev[nDev].Function = Function;
pDev[nDev].VendorID = VendorID;
nDev++;
if (nDev == MAX_DEVICE) {
return FALSE;
}
//
// Check header type
//
HeaderType = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_HEAD);
if (((PPCI_BHLC)(&HeaderType))->HeadType.HeadType == 0x00) {
//
// regular device
//
if (!PciInitDevice(Bus,Device,Function,pMemSize,pIoSize)) {
return FALSE;
}
} else {
//
// Bridge device
//
if (!PciInitBridge(Bus,
Device,
Function,
pSubordinateBus,
pMemSize,
pIoSize)) {
return FALSE;
}
}
//
// if not a multifunction device, break out of function loop
// and continue with next device.
//
if (((PPCI_BHLC)(&HeaderType))->HeadType.MultiFunctionDevice == 0) {
break;
}
} else {
break;
}
}
}
return TRUE;
}
BOOL
PciInitDevice(
ULONG Bus,
ULONG Device,
ULONG Function,
PULONG pMemSize,
PULONG pIoSize
)
/*++
Routine Description:
Initialize a pci device
Arguments:
Bus,Device,Function uniquely define device
Return Value:
None.
--*/
{
ULONG Reg;
pci_printf("InitDevice %d %d %d %X\r\n",Bus,Device,Function,PCIConfig_Read(Bus,Device,Function,0));
//
// read the base address registers to determine space to allocate
//
if (!PciInitCheckBARs(Bus,Device,Function,6,pMemSize,pIoSize)) {
return FALSE;
}
//
// disable expansion ROM
// Enable device
//
PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_ROM,0);
PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_COMMAND_STATUS,0x7);
Reg = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_INTERRUPT);
((PPCI_INT)(&Reg))->InterruptLine = 0xFF;
PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_INTERRUPT,Reg);
return TRUE;
}
BOOL
PciInitBridge(
ULONG Bus,
ULONG Device,
ULONG Function,
PULONG pSubordinateBus,
PULONG pMemSize,
PULONG pIoSize
)
/*++
Routine Description:
Initialize bridge device
Arguments:
None.
Return Value:
None.
--*/
{
ULONG BusReg;
ULONG SecondaryMemSize;
ULONG SecondaryIoSize;
ULONG i;
ULONG Reg;
//
// read the base address registers to determine space to allocate
//
if (!PciInitCheckBARs(Bus,Device,Function,2,pMemSize,pIoSize)) {
return FALSE;
}
//
// Enable bridge
// disable expansion ROM
// zero all the base and limit registers - these will get written later
// zero the IRQ register
//
// PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_COMMAND_STATUS,0x7);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_ROM,0x0);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_PREFETCHABLE,0xffff);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_BASE_UPPER32,0xffffffff);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_LIMIT_UPPER32,0xffffffff);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_MEMORY,0xffffffff);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_IO_UPPER16,0xffff);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_CNTRL,0x00040000);//sudhakar ISA device present
Reg = PCIConfig_Read(Bus,Device,Function,PCIBRIDGE_IO);
((PBRIDGE_IO)(&Reg))->IoLimit.Address = 0xff;
((PBRIDGE_IO)(&Reg))->IoBase.Address = 0xff;
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_IO,Reg);
Reg = PCIConfig_Read(Bus,Device,Function,PCI_CONFIG_INTERRUPT);
((PPCI_INT)(&Reg))->InterruptLine = 0xFF;
PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_INTERRUPT,Reg);
PCIConfig_Write(Bus,Device,Function,PCI_CONFIG_COMMAND_STATUS,0xffff0007);//sudhakar moved to end
//
// Set the bus numbers
// Need to set the subordinate bus as max for now, then write
// actual number after found all downstream busses
//
(*pSubordinateBus)++;
BusReg = PCIConfig_Read(Bus,Device,Function,PCIBRIDGE_BUS_NUMBER);
((PBRIDGE_BUS)(&BusReg))->PrimaryBusNumber = (BYTE)Bus;
((PBRIDGE_BUS)(&BusReg))->SecondaryBusNumber = (BYTE)(*pSubordinateBus);
((PBRIDGE_BUS)(&BusReg))->SubordinateBusNumber = 0xFF;
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_BUS_NUMBER,BusReg);
pci_printf("InitBridge %d %d %d %d %X\r\n",Bus,Device,Function,*pSubordinateBus,PCIConfig_Read(Bus,Device,Function,0));
//
// Call initbus routine recursively
//
SecondaryMemSize = 0;
SecondaryIoSize = 0;
if (!PciInitBus(*pSubordinateBus,
pSubordinateBus,
&SecondaryMemSize,
&SecondaryIoSize)) {
return FALSE;
}
//
// fill in the proper value for subordinate bus
//
((PBRIDGE_BUS)(&BusReg))->SubordinateBusNumber = (BYTE)(*pSubordinateBus);
PCIConfig_Write(Bus,Device,Function,PCIBRIDGE_BUS_NUMBER,BusReg);
//
// Add bridge to list to come back later and fill in limit registers
// Round up space required by secondary bus to 1MB boundary and then
// align to proper boundary after that
//
SecondaryMemSize = (SecondaryMemSize + 0x000FFFFF) & 0xFFF00000;
if (((SecondaryMemSize - 1) & (SecondaryMemSize)) != 0) {
for (i = 31; i > 1; i--) {
if (SecondaryMemSize & (1 << i)) {
SecondaryMemSize = (1 << (i+1));
break;
}
}
}
SecondaryIoSize = (SecondaryIoSize + 0x00000FFF) & 0xFFFFF000;
if (((SecondaryIoSize - 1) & (SecondaryIoSize)) != 0) {
for (i = 31; i > 1; i--) {
if (SecondaryIoSize & (1 << i)) {
SecondaryIoSize = (1 << (i+1));
break;
}
}
}
pci_printf("Bridgespace %08x %08x %08x\r\n",SecondaryMemSize,SecondaryIoSize,BusReg);
SpaceDesc[nSpaceDesc].Bus = Bus;
SpaceDesc[nSpaceDesc].Device = Device;
SpaceDesc[nSpaceDesc].Function = Function;
SpaceDesc[nSpaceDesc].MemSize = SecondaryMemSize;
SpaceDesc[nSpaceDesc].IoSize = SecondaryIoSize;
SpaceDesc[nSpaceDesc].Bridge = 1;
SpaceDesc[nSpaceDesc].SecondaryBus =
((PBRIDGE_BUS)(&BusReg))->SecondaryBusNumber;
nSpaceDesc++;
if (nSpaceDesc == MAX_SPACE) {
return FALSE;
}
*pMemSize += SecondaryMemSize;
*pIoSize += SecondaryIoSize;
return TRUE;
}
BOOL
PciInitCheckBARs(
ULONG Bus,
ULONG Device,
ULONG Function,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?