📄 i80312pcilib.c
字号:
/* i80312PciLib.c - i80312 PCI support library *//* Copyright 2000 Wind River Systems, Inc. *//*modification history--------------------01q,07feb02,scm remove DIAB warnings...01p,23may01,scm removed unused code01o,16may01,jb Removing FIQ support01n,15may01,jb Adding limited FIQ Support01m,10may01,scm add detection of PCI cards in backplane01l,27apr01,scm pci interrupt debug...01k,23feb01,jb Primary PCI Interface cleanup01j,15feb01,jb Fixes Secondary PCI support bug(s)01i,15feb01,jb Fixed PC Bios reconfigure problem01h,29jan01,jb Adding switch enable for startup delay01g,22jan01,jb Minor cleanup01f,16jan01,jb Adding Auto PCI Init01e,11jan01,jb Handle forced bus number change01d,05jan01,jb Fix Mapping01c,19dec00,jb Minor cleanup01b,06dec00,jb Removing dependency on sysEeprom.h01a,10oct00,kjb written based on i960rp/rpPciLib.c*//*DESCRIPTIONThis library provides routines to initialize the PCI-to-PCI Bridge and ATUunit on the i80310 Eval Board. It configures the private devices sitting onthe secondary PCI bus. This library also provides routines to access thePCI configuration space and translate the memory address between PCI spaceand local space.PCI-to-PCI BridgeThe i80312 chip's PCI-to-PCI bridge unit complies with the PCI-to-PCIBridge Architecture Specification, Revision 1.0 and the PCI Local BusSpecification, Revision 2.1. The bridge unit consists of a primary andsecondary PCI interface between the two PCI buses which the i80312 chipinterconnects: The primary interface connects to the lower numbered PCIbus. The secondary interface connects to the higher numbered PCI bus.All the private device's PCI address space will be configured within theSMBR/SMLR range, and is neither claimed nor forwarded by the PCI Bridge.The current setting of the Secondary Outbound Memory Window Value Register(SOMWVR) is based on the value of SMBR. Both of these registers must notbe changed by the application programs. The Primary Outbound MemoryWindow Value Register(POMWVR) currently is not set by this library. Theapplication program should set it before calling the address translationfunctions. It must be set only once.The PCI interrupt routing mechanism allows software to route secondaryPCI interrupts to either the i80200 core or the P_INTA#, P_INTB#, PINT_C#,and PINT_D# output pins. Currently it is configured to route to thei80312 core's XINT0-3 pins. Note that each P_INT pin can be routed to anyone of the XINT pins. There is a default routing table in thislibrary.Address Translation Unit (ATU)The ATU is the interface between the PCI buses and the i80312 local bus. Itconsists of primary and secondary ATUs. It supports both inbound and outboundaddress translation. The algorithm for inbound translation is:i80312 Local Address = (PCI_Address & ~Limit_Register) | ATU_Translate_Value_RegThe algorithm for outbound translation is:PCI Address=(i80312 & 0x03FF FFFF) | Window_Value_RegisterThere is also a Direct Addressing Window.Currently the Primary Inbound ATU Base Address is configured by the hostBIOS software based on the value in the ATU Limit Register. The SecondaryInbound ATU Base Address is set the same as the primary by this library'sinitialization routines. The outbound direct addressing window is enabled onthe primary side and disabled on the secondary side. It cannot beenabled on both sides at the same time.*/ #include "vxWorks.h"#include "config.h"#include "logLib.h"#include "dllLib.h"#include "i80312Pci.h"#include "i80312IntrCtl.h"/* REVISIT */#undef LOCAL#define LOCAL#define CLASS_BRIDGE_DEV 0x06 /* bridge device */#define PCI_IDX_ST_CMD 0x1 /* status, command */#define PCI_IDX_BAR_0 0x4 /* base addr reg 0 */#define CSR_IO_EN 0x00000001 /* I/O address space enable */#define CSR_MEM_EN 0x00000002 /* memory space enable */#define CSR_BM_EN 0x00000004 /* bus master enable */#define I80312_OUTB_BASE_MASK 0xfc000000#define DRV_LOG(X0, X1, X2, X3, X4, X5, X6) \ do { \ if (_func_logMsg != NULL) \ _func_logMsg (X0, (int)X1, (int)X2, (int)X3, (int)X4, \ (int)X5, (int)X6); \ } while (0)/* globals */struct pciConfigInfo { unsigned int busNo, deviceNo, funcNo, vendorId, deviceId; unsigned int pci_addr[5]; unsigned int pci_size[5];};struct pciConfigInfo pciCfg[10];int cur_pciCfg = 0;/* Forward declarations */IMPORT char * sysPhysMemTop (void);LOCAL void i80312PrimaryAtuInit(void);LOCAL void i80312PciBridgeInit(void);LOCAL STATUS i80312PciAbortsClear(int);LOCAL void i80312SecondaryAtuInit(void);LOCAL STATUS i80310SecondaryBridgeInit(void);LOCAL void i80310EthInit(void);LOCAL void i80312PciSecondaryBusInit(void);LOCAL void i80312PrivateDevInit();STATUS i80312PciChkBusNumbers(UINT32);/* Outbound and Inbound address translation data structure */LOCAL OUTBOUND_ADDRESS_TRAN i80312BusOut [2] = { {ATU_POMWVR, I80312_POUTB_SIZE, I80312_POUTB_BASE, I80312_POUTB_SIZE + I80312_POUTB_BASE, TRUE,I80312_DOUTB_BASE,I80312_DOUTB_TOP, I80312_DOUTB_TOP, ATU_POIOWVR,I80312_POUTB_IO_SIZE,I80312_POUTB_IO_BASE, I80312_POUTB_IO_SIZE + I80312_POUTB_IO_BASE, ATU_PODWVR,I80312_POUTB_DAC_SIZE,I80312_POUTB_DAC_BASE, I80312_POUTB_DAC_SIZE + I80312_POUTB_DAC_BASE}, {ATU_SOMWVR, I80312_SOUTB_SIZE, I80312_SOUTB_BASE, I80312_SOUTB_SIZE + I80312_SOUTB_BASE, FALSE,0x0,0x0,0x0, ATU_SOIOWVR,I80312_SOUTB_IO_SIZE,I80312_SOUTB_IO_BASE,I80312_SOUTB_IO_SIZE + I80312_SOUTB_IO_BASE, ATU_SODWVR,I80312_SOUTB_DAC_SIZE,I80312_SOUTB_DAC_BASE ,I80312_SOUTB_DAC_SIZE + I80312_SOUTB_DAC_BASE} };LOCAL INBOUND_ADDRESS_TRAN i80312BusIn [2] = { {ATU_PIATVR,ATU_PIALR,ATU_PIABAR}, {ATU_SIATVR,ATU_SIALR,ATU_SIABAR} };/* PCI configuration cycle address and data registers */LOCAL I80312_PCI_CFG_REGS i80312CfgRegs [] = { {ATU_POCCAR, (UINT32)ATU_POCCDR}, {ATU_SOCCAR, (UINT32)ATU_SOCCDR}, { 0, 0 }, };LOCAL UINT32 i80312_LedSegValues[] = { L7SEG_0, L7SEG_1, L7SEG_2, L7SEG_3, L7SEG_4, L7SEG_5, L7SEG_6, L7SEG_7, L7SEG_8, L7SEG_9, L7SEG_A, L7SEG_B, L7SEG_C, L7SEG_D, L7SEG_E, L7SEG_F, };LOCAL UINT32 i80312DefaultPomwvr;LOCAL UINT32 i80312DefaultSomwvr;UINT32 i80312_PriBusNumber;UINT32 i80312_SecBusNumber;UINT32 i80312_SubBusNumber;UINT32 i80312_BusNumbers[4];LOCAL UINT16 reverseBits ( int data, /* data to operate on */ int numOfBits /* number of bits to be reversed */ ) { int i; UINT16 result = 0; for (i = 0; i < numOfBits; i++) { if (data & (1 << ((numOfBits - 1) - i))) result |= 1 << i; } return (result); }/*************************************************************************** sysPciInit - initialize the I80312 PCI-to-PCI bridge unit and ATU** This routine initializes the I80312 PCI-to-PCI bridge unit and Address* Translation Unit (ATU), before allowing host configuration command* access. This is in preparation for host BIOS configuration.** This routine is called from sysHwInit().** RETURNS: N/A** SEE ALSO: sysHwInit()*/void sysPciInit (void) { volatile UINT32 tmp, x1; UINT8 rotary = I80310_ROT_STAT_REG_RD(); if (rotary == 0x7) /* rotary switch in position 7 - PC backplane */ { IQ80310_SEVEN_SEG_WRITE_MSB(L7SEG_P & L7SEG_Dot); IQ80310_SEVEN_SEG_WRITE_LSB(L7SEG_0); /* Delay until bios inits pci interface */ while(rotary == 0x07 && *BRIDGE_PCR == 0) { for(x1 = 0, tmp = 0; tmp < 0x500000; tmp++) { if(tmp%0x40000 == 0) IQ80310_SEVEN_SEG_WRITE_LSB(i80312_LedSegValues[(++x1)&0xF]); } } /* A short delay here */ for(x1 = 0; x1 < 0x10000; x1++) ; /* Get the Bus Numbers */ i80312_PriBusNumber = *BRIDGE_PBNR; i80312_SecBusNumber = *BRIDGE_SBNR; i80312_SubBusNumber = i80312_SecBusNumber + 1; }else{ i80312_PriBusNumber = 0; i80312_SecBusNumber = 1; i80312_SubBusNumber = 2; } /* Store Bus Numbers */ i80312_BusNumbers[0] = i80312_PriBusNumber; i80312_BusNumbers[1] = i80312_SecBusNumber; i80312_BusNumbers[2] = i80312_SubBusNumber; i80312_BusNumbers[3] = i80312_SubBusNumber; /* Set Bus Numbers */ *BRIDGE_PBNR = (UINT8)i80312_PriBusNumber; *BRIDGE_SBNR = (UINT8)i80312_SecBusNumber; *BRIDGE_SubBNR = (UINT8)i80312_SubBusNumber; *BRIDGE_SDER = 0xfff2; if (rotary != 0x07) /* rotary switch not in position 7 - stand-alone backplane */ { i80312PrimaryAtuInit(); *BRIDGE_PCR = 0x00000000; /* * Set Primary I/O and memory space -must be done before PCR set */ *BRIDGE_IOBR = 0x00; *BRIDGE_IOLR = 0xf0; *BRIDGE_MBR = 0x0000; *BRIDGE_MLR = 0xfff0; i80312BusOut[0].ioCurrent = 0xFFFFF000; i80312BusOut[0].ioBase = 0xFFFF0000; /* set database to point to first avail Memory */ i80312BusOut[0].current = 0xFFFFF000; i80312BusOut[0].base = 0xFC000000; *BRIDGE_PCR = 0x00000007; } i80312PciBridgeInit(); i80312PciSecondaryBusInit(); /* initialize secondary ATU interface */ i80312SecondaryAtuInit(); /* Init the 21154 Bridge */ if(i80310SecondaryBridgeInit() == OK) { /* Init the 82559ER Ethernet chip */ i80310EthInit(); } IQ80310_SEVEN_SEG_WRITE_MSB(L7SEG_P & L7SEG_Dot); IQ80310_SEVEN_SEG_WRITE_LSB(L7SEG_P & L7SEG_Dot); /* Configure PCI Devices */ i80312PrivateDevInit(); IQ80310_SEVEN_SEG_WRITE_LSB(L7SEG_P); }/******************************************************************* i80312PciBridgeInit - initialize YP bridge unit** This routine initializes the I80312 bridge unit.**/LOCAL void i80312PciBridgeInit(void) { /* Clear any Aborts */ i80312PciAbortsClear(i80312_BusNumbers[PRIMARY_BUS_INDEX]); i80312PciAbortsClear(i80312_BusNumbers[SECONDARY_BUS_INDEX]); /* Route secondary interrupts to core processor */ *BRIDGE_PIRSR = 0xF; /* set private device slots for this platform */ *BRIDGE_SISR = reverseBits(I80312_PRIVATE_DEVICE_SELECT,I80312_NUM_PRIVATE_SELECT); *BRIDGE_SACR = I80312_SECONDARY_ARBITRATION_MASK; *BRIDGE_BCR = SERR_ENABLE | MASTER_ABORT_MODE; /* Enable secondary pci resets */ *BRIDGE_SDER &= ~(SDER_SECONDARY_BUS_RESET_INT_MASK); *BRIDGE_PMBR = 0; *BRIDGE_PMLR = 0; }/********************************************************************** i80312PrimaryAtuInit - initialize primary ATU** This routine initializes the primary ATU, allowing I80312 DRAM to be* accessible from the system bus. The range requested is based on DRAM* size. The sysPhysMemTop() routine dynamically determines the amount of* DRAM available and returns the top.** RETURNS: N/A*/LOCAL void i80312PrimaryAtuInit(void) { UINT32 memSize; /* get top of system memory pool. */ memSize = (UINT32)(sysPhysMemTop() - LOCAL_MEM_LOCAL_ADRS); /* expose all of DRAM for now. */ *ATU_PIALR = ~(memSize - 1); *ATU_PIABAR = LOCAL_MEM_LOCAL_ADRS; /* set translate value to start of DRAM */ *ATU_PIATVR = LOCAL_MEM_LOCAL_ADRS; /* Private PCI Memory space starts at 0xFC000000 */ *ATU_POMWVR = 0xFC000000; *ATU_POIOWVR = 0xFFFF0000; *ATU_PATUCMD = 0x00000006; /* enable outbound transactions */ *ATU_ATUCR |= 0x02; /* mask off SATU error ints */ *ATU_PATUIMR = PATUIMR_MASK | ATUIMR_TARGET_ABORT_ENABLE; }/********************************************************************** i80312PciSecondaryBusInit - performs secondary bus setup** This routine performs the secondary bus initialization that is
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -