📄 405gp_pci.c
字号:
int BusDevFunc;
/*--------------------------------------------------------------------------+
| Start with device 1, the 405GP is device 0. MCG 01/04/99
+--------------------------------------------------------------------------*/
for (Device = 1; Device < MAX_PCI_DEVICES; Device++)
{
BusDevFunc = (BusNum << 16) | (Device << 11);
if (PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2) != 0xFFFF)
{
#ifdef DEBUG
printf("Device %d is present\n",Device);
#endif
switch( PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE, 2) )
{
case 0x0604: /* PCI-PCI Bridge */
PCI_Config_Device(BusDevFunc, 2);
PCI_Config_Bridge(BusDevFunc);
break;
case 0x0300: /* VGA Display controller */
case 0x0001: /* VGA Display controller (pre PCI rev 2.0)*/
PCI_Config_VGA_Device(BusDevFunc, 6);
break;
default:
PCI_Config_Device(BusDevFunc, 6);
}
}
else
{
#ifdef DEBUG
printf("Device %d not present\n",Device);
#endif
}
}
}
/*-----------------------------------------------------------------------
| Subroutine: PCI_Config_Device
|
| Description: Configure a PCI device by examining its I/O and memory
| address space needs and allocating address space to it by
| programming the address decoders in the Base Address Registers.
|
| Inputs:
| BusDevFunc Bus+Device+Function number
| NumBaseAddr Number of base address registers to
| configure
| Return value:
| None
+----------------------------------------------------------------------*/
void PCI_Config_Device(int BusDevFunc, int NumBaseAddr)
{
int AddrSlot, i;
unsigned long AddrDesc, AddrProg, Min_Gnt_Val, int_line;
for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++)
{
PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4);
AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4);
if (AddrDesc == 0) /* unimplemented, stop looking */
continue; /* 01/04/99 MCG */
#ifdef DEBUG
printf("Read Base Addr Reg %d = 0x%08x\n",AddrSlot,AddrDesc);
#endif
if ((AddrDesc & 1) == 0) /* Memory */
{
AddrDesc &= 0xFFFFFFF0;
for (i = 0; (AddrDesc & 1) != 1; i++)
AddrDesc = AddrDesc >> 1;
AddrDesc = 1 << i;
if ((unsigned long)AddrDesc < 4096)
AddrDesc = 4096;
#ifdef DEBUG
printf(" PCI Memory space = 0x%x bytes \n",AddrDesc);
#endif
for (AddrProg = MIN_PCI_MEMADDR1; AddrProg < LowestMemAddr1; AddrProg += AddrDesc);
PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
LowestMemAddr1 = AddrProg + AddrDesc;
}
else /* I/O */
{
AddrDesc &= 0xFFFFFFFC;
for (i = 0; (AddrDesc & 1) != 1; i++)
AddrDesc = AddrDesc >> 1;
AddrDesc = 1 << i;
#ifdef DEBUG
printf(" PCI I/O space = 0x%x bytes \n",AddrDesc);
#endif
for (AddrProg = MIN_PCI_PCI_IOADDR; AddrProg < LowestIOAddr; AddrProg += AddrDesc);
PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
LowestIOAddr = AddrProg + AddrDesc;
}
}
Min_Gnt_Val = 0x80;
PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1);
/*
* Write pci interrupt line register (cpci405 specific)
*/
switch ((BusDevFunc >> 11) & 0x03)
{
case 0:
int_line = 27 + 2;
break;
case 1:
int_line = 27 + 3;
break;
case 2:
int_line = 27 + 0;
break;
case 3:
int_line = 27 + 1;
break;
}
PCI_Write_CFG_Reg(BusDevFunc, PCIINTLINE, int_line, 1);
/*
* Enable i/o space, memory space and master on this device
*/
PCI_Write_CFG_Reg(BusDevFunc, PCICMD, 7, 2);
}
/*-----------------------------------------------------------------------
| Subroutine: PCI_Config_VGA_Device
|
| Description: Configure a PCI VGA device by examining its I/O and memory
| address space needs and allocating address space to it by
| programming the address decoders in the Base Address Registers.
|
| Inputs:
| BusDevFunc Bus+Device+Function number
| NumBaseAddr Number of base address registers to
| configure
| Return value:
| None
+----------------------------------------------------------------------*/
void PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr)
{
int AddrSlot, i;
unsigned long AddrDesc, AddrProg, Min_Gnt_Val;
for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++)
{
PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4);
AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4);
if (AddrDesc == 0) /* unimplemented, stop looking */
continue; /* 01/04/99 MCG */
#ifdef DEBUG
printf("Read Base Addr Reg %d = 0x%08x\n",AddrSlot,AddrDesc);
#endif
if ((AddrDesc & 1) == 0) /* Memory */
{
AddrDesc &= 0xFFFFFFF0;
for (i = 0; (AddrDesc & 1) != 1; i++)
AddrDesc = AddrDesc >> 1;
AddrDesc = 1 << i;
if ((unsigned long)AddrDesc < 4096)
AddrDesc = 4096;
#ifdef DEBUG
printf(" PCI Memory space = 0x%x bytes \n",AddrDesc);
#endif
for (AddrProg = MIN_PCI_MEMADDR2; AddrProg < LowestMemAddr2; AddrProg += AddrDesc);
PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
LowestMemAddr2 = AddrProg + AddrDesc;
}
else /* I/O */
{
AddrDesc &= 0xFFFFFFFC;
for (i = 0; (AddrDesc & 1) != 1; i++)
AddrDesc = AddrDesc >> 1;
AddrDesc = 1 << i;
#ifdef DEBUG
printf(" PCI I/O space = 0x%x bytes \n",AddrDesc);
#endif
for (AddrProg = MIN_PCI_PCI_IOADDR; AddrProg < LowestIOAddr; AddrProg
+= AddrDesc);
PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
LowestIOAddr = AddrProg + AddrDesc;
}
}
Min_Gnt_Val = 0x80;
PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1);
}
/*-----------------------------------------------------------------------
|
| Subroutine: PCI_Config_Bridge
|
| Prototype: void PCI_Config_Bridge(int BusDevFunc)
|
| Description: Configure a PCI-PCI bridge
|
| Inputs:
| BusDevFunc Bus+Device+Function number
|
| Return value:
| None
|
+----------------------------------------------------------------------*/
void PCI_Config_Bridge(int BusDevFunc)
{
int SecondaryBus;
int PrimaryBus;
int CommandReg_Val;
int InitialLowestIOAddr, InitialLowestMemAddr;
int IOBase, MemBase;
int IOLimit, MemLimit;
InitialLowestIOAddr = LowestIOAddr;
InitialLowestMemAddr = LowestMemAddr1;
CommandReg_Val = PCI_Read_CFG_Reg(BusDevFunc, PCICMD, 2);
/* Configure bridge's base address registers */
PCI_Config_Device(BusDevFunc, 2);
if ( LowestIOAddr > InitialLowestIOAddr ) /* bridge uses IO space? */
CommandReg_Val |= 0x01; /* enable I/O Space */
if ( LowestMemAddr1 > InitialLowestMemAddr ) /* bridge uses memory space? */
CommandReg_Val |= 0x02; /* enable Memory Space */
PrimaryBus = (BusDevFunc >> 16) & 0xFF;
PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_PRIMARYBUS, PrimaryBus, 1);
SecondaryBus = ++MaxBusNum;
PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SECONDARYBUS, SecondaryBus, 1);
/* Start with max. possible value for subordinate bus number */
/* Later, after any additional child busses are found, we'll update this */
PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, 0xFF, 1);
/* IO Base must be on 4Kb boundary. Adjust if needed */
if ((LowestIOAddr % 4096) != 0)
LowestIOAddr += 4096 - (LowestIOAddr % 4096);
PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASE, (LowestIOAddr>>8) & 0xF0, 1);
PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASEUPPER16, (LowestIOAddr>>16) & 0xFFFF, 2);
IOBase = LowestIOAddr;
/* Mem Base must be on 1 MB boundary. adjust if needed */
if ((LowestMemAddr1 % 0x100000) != 0)
LowestMemAddr1 += 0x100000 - (LowestMemAddr1 % 0x100000);
PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_MEMBASE, (LowestMemAddr1>>16) & 0xFFF0, 2);
MemBase = LowestMemAddr1;
PCI_Scan(SecondaryBus);
PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, MaxBusNum, 1);
IOLimit = LowestIOAddr;
if (LowestIOAddr > IOBase) /* IO space used on secondary bus? */
{
CommandReg_Val |= 0x01; /* enable IO Space */
IOLimit--; /* IOLimit is highest used address */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -