⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mot82xxpci.c

📁 该源码为mpc8248处理器的BSP
💻 C
📖 第 1 页 / 共 2 页
字号:
/* mot82xxPci.c - Motorola ads 82xx PCI Bridge functions *//* Copyright 1984-2003 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01c,01oct03,dee  changed structure element names for all dma buffer                 descriptors01b,08jan03,dtr  Added support for PCI DMA and Error Handling.                 Implemented workaround for PCI Bridge read errata.01a,04jul02,dtr  File created.*//* PCI Host Bridge setup File */#include "vxWorks.h"#include "config.h"#include "sysLib.h"#include "drv/pci/pciConfigLib.h" 	#include "drv/pci/pciIntLib.h" 	#include "drv/pci/pciAutoConfigLib.h"	#include "sysBusPci.h"#include "drv/mem/m8260Memc.h"#include "drv/intrCtl/m8260IntrCtl.h"#include "drv/mem/m8260Siu.h"#include "mot82xxPci.h"#ifdef PCI_BRIDGE_READ_ERRATA_WORKAROUND/* Anything above 0x3ffffff can be handled by IDMA */ #define PCI_ACCESS_MASK 0xfc000000 /* Global function called in sysLib.c */ void pciBridgeIdmaInit();IMPORT  USHORT  sysWord(int);IMPORT  UCHAR  sysByte(int);IMPORT  ULONG  sysLong(int);#endif /* PCI_BRIDGE_READ_ERRATA_WORKAROUND */#ifdef INCLUDE_PCI_DMASTATUS pciDmaTransfer(char*,char*,UINT32,UINT32 );LOCAL void pciDmaHandler();#endif/* These three arrays are for convenience and speed *//* Each interrupt line is wire OR'd to another on another slot  * Hence for first 4 bits - 8 is slot 0 INT A * links     second       - 4 is slot 1 INT B * links     third        - 2 is slot 2 INT C * All are the same interrupt effectively linked but they all * need to be cleared/masked in the interrupt register.  * Refer to the ADS8266 PCI Board Users Manual. */ LOCAL UINT32  pciSlotIntDisableMask[MAX_NUM_VECTORS] =         {0x84200000,     /* Slot 0 */	 0x18400000,     /* Slot 1 */	 0x21800000};    /* Slot 2 */LOCAL UINT32  pciSlotIntEnableMask[MAX_NUM_VECTORS] =         {0x7bd00000,	 0xe7b00000,	 0xde700000};LOCAL UINT32  pciSlotIntClearMask[MAX_NUM_VECTORS] =         {0x7bdfffff,	 0xe7bfffff,	 0xde7fffff};LOCAL INTR_HANDLER  pciDeviceIntTable[MAX_NUM_VECTORS] = { {NULL,0},							   {NULL,0},							   {NULL,0} };BOOL       firstTime = TRUE;LOCAL void pciDeviceIntHandler(void);STATUS pciDeviceIntConnect(int vector,VOIDFUNCPTR *handler,int arg);STATUS pciDeviceIntDisconnect(int vector,VOIDFUNCPTR *handler);STATUS pciDeviceIntEnable(int);STATUS pciDeviceIntDisable(int);LOCAL void pciMultiInterruptHandler();LOCAL void pciErrorHandler();LOCAL UINT32  pciIntEnabled = 0;VOIDFUNCPTR _func_pciDmaUserHandler[] = {NULL,NULL,NULL,NULL};typedef struct {    UINT32 nmi;        /* 60x error original initiated for PCI */    UINT32 ira;        /* Illegal register access */     UINT32 i2o_ipqo;   /* I2O Error queue overflow inbound */     UINT32 i2o_ofqo;   /* I2O Error queue overflow outbound*/    UINT32 perr_wr;    /* PCI Error Parity Error on write */    UINT32 perr_rd;    /* PCI Error Parity Error on read */    UINT32 serr;       /* PCI Error System error */    UINT32 tar_abt;    /* PCI Error configuration access device isn't available */    UINT32 no_rsp;     /* PCI Error no response */    UINT32 datapar_rd; /* PCI Error data parity error on read */    UINT32 datapar_wr; /* PCI Error data parity error on write */    UINT32 addrpar; /* PCI Error address parity error */} PCI_ERROR_COUNT;LOCAL PCI_ERROR_COUNT  pciErrorCount; IMPORT  UINT32  vxImmrGet  	(void);IMPORT  USHORT  sysPciInWord(int);LOCAL   UINT32  immrVal = INTERNAL_MEM_MAP_ADDR;#ifdef PCI_BRIDGE_READ_ERRATA_WORKAROUNDLOCAL BD_DMA *idmaBd;LOCAL IDMA_PARAM *pIdmaParam;#endif /* PCI_BRIDGE_READ_ERRATA_WORKAROUND *//************************************************************************* *  * mot82xxBridgeInit - This function performs all the initialisation  * required for the Bridge/Interrupts/PCI Bus to function. It does some * low level processor initialisation which might normally be done in  * romInit as it is optional to do use this and shows what the core  * changes required to bring up the bridge. *  * RETURNS : NONE * */void mot82xxBridgeInit()    {      STATUS result;      immrVal = (UINT32)vxImmrGet();      /* Set device to use IRQ6 (pci device interrupt number) */       *M8260_SIUMCR(INTERNAL_MEM_MAP_ADDR) = (UINT32)SIUMCR_PCI_SETTING;      /* Make PCI lowest priority */      /* Each 4 bits is a device bus request  and the MS 4bits          is highest priority */      /* Bus               4bit value 	 ---               ----------         CPM high          0b0000         CPM middle        0b0001	 CPM low           0b0010         PCI reguest       0b0011         Reserved          0b0100         Reserved          0b0101         Internal Core     0b0110         External Master 1 0b0111         External Master 2 0b1000         External Master 3 0b1001         The rest are reserved */      *M8260_PPC_ALRH (INTERNAL_MEM_MAP_ADDR) = 0x61207893;      /* Park bus on core while modifying PCI Bus accesses */      *M8260_PPC_ACR (INTERNAL_MEM_MAP_ADDR) = PPC_ACR_BUS_PARK_CORE;      /* Standard GPCM */      *(VUINT32*) M8260_OR3(INTERNAL_MEM_MAP_ADDR) = PCI_INT_MEM_OR8_SETTING;      *(VUINT32*) M8260_BR3(INTERNAL_MEM_MAP_ADDR) = PCI_INT_MEM_BR8_SETTING;      /* Set outbound translation window adresses */         sysPciOutLong((UINT32*)(PCI_OUTBOUND_BASE_ADRS_REG0(immrVal)),		    (CPU_PCI_MEM_ADRS>>12) & 0xfffff);      sysPciOutLong((UINT32*)(PCI_OUTBOUND_TRANS_ADRS_REG0(immrVal)),		    (PCI_MEM_ADRS>>12) & 0xfffff);      sysPciOutLong((UINT32*)(PCI_OUTBOUND_BASE_ADRS_REG1(immrVal)),		    (CPU_PCI_MEMIO_ADRS>>12) & 0xfffff);      sysPciOutLong((UINT32*)(PCI_OUTBOUND_TRANS_ADRS_REG1(immrVal)),		    (PCI_MEMIO_ADRS>>12) & 0xfffff);      sysPciOutLong((UINT32*)(PCI_OUTBOUND_BASE_ADRS_REG2(immrVal)),		    (CPU_PCI_IO_ADRS>>12) & 0xfffff);      sysPciOutLong((UINT32*)(PCI_OUTBOUND_TRANS_ADRS_REG2(immrVal)),		    (PCI_IO_ADRS>>12) & 0xfffff);      *(VUINT32*) PCIMSK_REG0 (INTERNAL_MEM_MAP_ADDR) = PCIMSK0_SETTING;      /* set mask for 128KBytes */      *(VUINT32*) PCIMSK_REG1 (INTERNAL_MEM_MAP_ADDR) = PCIMSK1_SETTING;      /* set start addresses and enable window*/      *(VUINT32*) PCIBR_REG0 (INTERNAL_MEM_MAP_ADDR) = PCIBR0_SETTING;      *(VUINT32*) PCIBR_REG1 (INTERNAL_MEM_MAP_ADDR) = PCIBR1_SETTING;      /* Switch on the outbound trnslation windows */      sysPciOutLong((UINT32*)(PCI_OUTBOUND_COMP_MASK_REG0(immrVal)),		    PCI_WINDOW_ENABLE_BIT | PCI_MEM_SIZE_MASK);      sysPciOutLong((UINT32*)(PCI_OUTBOUND_COMP_MASK_REG1(immrVal)),		    PCI_WINDOW_ENABLE_BIT | PCI_MEMIO_SIZE_MASK);      /* Set the PCI reset line high to switch on PCI bus */      sysPciOutLong((UINT32*)(immrVal| PCI_GCR_REG) , 		    0);       sysPciOutLong((UINT32*)(immrVal| PCI_GCR_REG) , 		    EXTERNAL_PCI_BUS_ENABLE);       sysMsDelay(1);           /* the bridge registers need to be accessed as little endian */      /* Set up inbound address translation registers */      /* Translation address is the locally mapped address */      sysPciOutLong((UINT32*)(immrVal| PCI_INBOUND_TRANS_ADRS_REG0),		    (PCI_LOCAL_MEM_BUS>>12) & 0xfffff);      /* Base Address is the PCI address */      sysPciOutLong((UINT32*)(immrVal| PCI_INBOUND_BASE_ADRS_REG0),		    (PCI_MSTR_MEM_BUS>>12) & 0xfffff);      /* This initialises the size of the window and enables it */      sysPciOutLong((UINT32*)(immrVal |PCI_INBOUND_COMP_MASK_REG0),		    PCI_MSTR_MEM_SIZE_MASK | PCI_WINDOW_ENABLE_BIT | PCI_SNOOP_ENABLE | PCI_PREFETCHABLE);      /* See above for description - puts PCI request as highest priority */      *M8260_PPC_ALRH (INTERNAL_MEM_MAP_ADDR) = 0x30126745;      /* Park the bus on the PCI */      *M8260_PPC_ACR (INTERNAL_MEM_MAP_ADDR) = PPC_ACR_BUS_PARK_PCI;      /* Setup The PIMMR PCI Base address */      result = sysPciConfigWrite(0,0,0,				 PIMMR_BASE_ADRS_REGISTER_OFFSET,				 PIMMR_BASE_ADRS_REGISTER_WIDTH,				 PCI_BRIDGE_PIMMR_BASE_ADRS);			             result = sysPciConfigWrite(0,0,0,				 CLASS_OFFSET,				 CLASS_WIDTH,				 BRIDGE_CLASS_TYPE);      /* configure the bridge as bus master */      result = sysPciConfigWrite(0,0,0,				 COMMAND_REGISTER_OFFSET,				 COMMAND_REGISTER_WIDTH,				 (BUS_MASTER_ENABLE_BIT|MEMORY_SPACE_ACCESS_ENABLE_BIT));    }/************************************************************************* *  *   pciDeviceIntConnect - This function connects a interrupt handler to *   the pci interrupt and pci interrupt vector. It disables the interrupt *   vector via the PCI interrupt mask register prior to initialisation *   in order to get it to a known state assuming the interrupt should be *   at this point.   * *   RETURNS : OK or ERROR * */STATUS pciDeviceIntConnect   (    int vector,    VOIDFUNCPTR *handler,    int arg    )    {      if (vector>=MAX_NUM_VECTORS)	  return (ERROR);      pciDeviceIntDisable(vector);      if (firstTime==TRUE) 	  {	    (void)_func_intConnectRtn((VOIDFUNCPTR *)INUM_IRQ2,(VOIDFUNCPTR)pciDeviceIntHandler,0);	    /* Initialise Interrupt Mask */	    firstTime=FALSE;	  }      pciDeviceIntTable[vector].vec = (VOIDFUNCPTR)handler;      pciDeviceIntTable[vector].arg = arg;      (void)m8260IntEnable(INUM_IRQ2);      return OK;     }/************************************************************************* *  *   pciDeviceIntDisconnect - This function disconnects the device  *   interrupt handler from the pci interrupt and disables the relevent  *   pci interrupt. * *   RETURNS : OK or ERROR * */STATUS pciDeviceIntDisconnect    (     int vector,     VOIDFUNCPTR *handler     )    {      if (vector>=MAX_NUM_VECTORS)          return (ERROR);      (void)pciDeviceIntDisable(vector);      pciDeviceIntTable[vector].vec = NULL;      pciDeviceIntTable[vector].arg = 0;#ifdef PCI_DEBUG      logMsg("PCI Interrupt disconnected %d\n",vector,0,0,0,0,0);#endif      firstTime=TRUE;      return OK;     }/************************************************************************* *  *   pciDeviceIntEnable - This function enables the specific pci  *   interrupt related to the vector.  * *   RETURNS : OK or ERROR */ STATUS pciDeviceIntEnable    (     int vector     )    {      if (vector>=MAX_NUM_VECTORS)	  return (ERROR);#ifdef PCI_DEBUG      logMsg("PCI Interrupt Enable %x\n",(int)vector,0,0,0,0,0);#endif /* PCI_DEBUG */      (void)m8260IntDisable(INUM_IRQ2);      *(UINT32*)PCI_INTERRUPT_MASK_REG &=pciSlotIntEnableMask[vector];      (void)m8260IntEnable(INUM_IRQ2);      return (OK);    }/************************************************************************* *  *   pciDeviceIntDisable - This function disables the specific pci  *   interrupt related to the vector.  * *   RETURNS : OK or ERROR * */STATUS pciDeviceIntDisable    (     int vector     )    {      if (vector>=MAX_NUM_VECTORS)	return (ERROR);#ifdef PCI_DEBUG      logMsg("PCI Interrupt disable %x\n",(int)vector,0,0,0,0,0);#endif /* PCI_DEBUG */      (void)m8260IntDisable(INUM_IRQ2);      *(UINT32*)PCI_INTERRUPT_MASK_REG |= pciSlotIntDisableMask[vector];      (void)m8260IntEnable(INUM_IRQ2);      return (OK);    }/************************************************************************* *  *   pciDeviceIntHandler - This is called from the 8260 interrupt  *   controller and is linked to IRQ6.  *   It finds which vectors have the corresponding interrupt set and  *   calls the relevent interrupt handler. The priority based on  *   slot and the slot<->vector are the effectively the same. The vector *   is based upon device number which for ADS board is : *                  0x16 -> slot 0 -> vector 0 *                  0x17 -> slot 1 -> vector 1 *                  0x18 -> slot 2 -> vector 2 *   For a custom board this may need to be modified. * *   RETURNS : N/A *  */LOCAL void pciDeviceIntHandler(void)     {      volatile int vector;      volatile UINT32 status;      status = *(VUINT32*)PCI_INTERRUPT_STATUS_REG;      for (vector=0;vector<MAX_NUM_VECTORS;vector++)	  {	    /* Check Interrupt routine available and interrupt vector is set */	    if ( (pciDeviceIntTable[vector].vec!=NULL)		 &&(pciDeviceIntTable[vector].arg!=0) &&		 ((status & pciSlotIntDisableMask[vector])!=0))	        {		  /* Call Interrupt Handler for specific vector */		  pciDeviceIntTable[vector].vec(pciDeviceIntTable[vector].arg);		  /* Clear the specific interrupt */		  *(VUINT32*)PCI_INTERRUPT_STATUS_REG &=pciSlotIntClearMask[vector];		}	  }#ifdef PCI_DEBUG      logMsg("PCI interrupt received %x\n",(int)status,0,0,0,0,0);#endif /* PCI_DEBUG */    }/**************************************************************** *    * pciErrorHandlingInit - This function sets up the error  * control and mask registers. It also connects the INUM_PCI to  * the interrupt handler and activates the interrupt. * * RETURNS : NONE * */void pciErrorHandlingInit()    {    volatile int loop;    /* Initialise ECR to include particular PCI Errors */    /* Not required as most useful errors already enabled on reset*/    /* Connect handler to INUM_PCI*/    (void)_func_intConnectRtn( (VOIDFUNCPTR *)INUM_PCI,                               (VOIDFUNCPTR)pciMultiInterruptHandler,                                0);      for (loop=0;loop<sizeof(pciErrorCount)/sizeof(UINT32);loop++)        {        *(UINT32*)((UINT32*)&pciErrorCount + loop) = 0;        }    /* Clear the Error Status register */    sysPciOutLong((UINT32*)PCI_ESR(INTERNAL_MEM_MAP_ADDR),0x0);    /* Activate/Initialise Mask/Control Registers */    sysPciOutLong((UINT32*)PCI_EMR(INTERNAL_MEM_MAP_ADDR),0xeff);    sysPciOutLong((UINT32*)PCI_ECR(INTERNAL_MEM_MAP_ADDR),0x0);    /* Allow the interrupt handler to process the interrupt */    pciIntEnabled|=PCI_ERROR_INT_ENABLED;    /* Enable Interrupts */    m8260IntEnable(INUM_PCI);    #ifdef PCI_DEBUG    logMsg("PCI Error Handling Initialised.\n",0,0,0,0,0,0);    #endif /* PCI_DEBUG */    }#ifdef INCLUDE_PCI_DMA/**************************************************************** *    * pciDmaInit - This function sets up the error  * control and mask registers. It also connects the INUM_PCI to  * the interrupt handler and activates the interrupt. * * RETURNS : NONE * */void pciDmaInit()    {    (void)_func_intConnectRtn( (VOIDFUNCPTR *)INUM_PCI,                               (VOIDFUNCPTR)pciMultiInterruptHandler,                                0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -