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

📄 kahluaepic.c

📁 vxworks mv2100 vxworks BSP
💻 C
字号:
/* kahluaEpic.c - EPIC Interrupt Controller driver *//* Copyright 1984-2002 Wind River Systems, Inc. *//* Copyright 1996,1997,1998,1999 Motorola, Inc., All Rights Reserved */#include "copyright_wrs.h"/*modification history--------------------01f,25apr02,dat  SPR 62758, incorrent timer setup, added comment about		 external src's not being active.01e,15jun00,dmw  updated following WRS code review.01d,28may99,dmw  Updated to WindRiver coding standards.01c,19feb99,dmw  Added code to wait for EPIC reset to complete.01b,17feb99,dmw  Changed sysIn/OutLongs to sysPciIn/OutLongs.01a,12feb99,dmw  Created.*//*DESCRIPTIONThis module implements the EPIC interrupt controller functionality.*//* includes */#include "kahlua.h"#include "kahluaEpic.h"/* defines *//* globals */IMPORT STATUS	      (*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);IMPORT int	      (*_func_intEnableRtn) (int);IMPORT int	      (*_func_intDisableRtn) (int);IMPORT UINT32 		sysPciInLong (UINT32);IMPORT void   		sysPciOutLong (UINT32, UINT32);IMPORT STATUS		excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);IMPORT UINT		sysGetMpuSpd(void);IMPORT void		sysDecDelay (UINT usDelay);void			sysEpicIntHandler (void);/* system interrupt table */#define SYSTEM_INTERRUPT_TABLE_SIZE     256INT_HANDLER_DESC * sysIntTbl [SYSTEM_INTERRUPT_TABLE_SIZE];#ifdef INCLUDE_INSTRUMENTATION    IMPORT	int             evtTimeStamp;#endif /* INCLUDE_INSTRUMENTATION *//* forward declarations */LOCAL int       getEpicVecAddr (int);LOCAL STATUS	sysEpicIntConnect (VOIDFUNCPTR * vector, VOIDFUNCPTR routine,                                   int parameter);LOCAL int	sysEpicIntEnable (int);LOCAL int	sysEpicIntDisable (int);#ifndef CPU_INT_LOCK#   define CPU_INT_LOCK(x) \	(*x = intLock ())#endif /* CPU_INT_LOCK */#ifndef CPU_INT_UNLOCK#   define CPU_INT_UNLOCK(data) \	(intUnlock (data))#endif /* CPU_INT_UNLOCK *//******************************************************************************** sysEpicInit - initialize the EPIC** This function initializes the Embedded Programmable Interrupt Controller * (EPIC) contained in the Kahlua chip.** It first initializes the system vector table, connects the EPIC interrupt* handler to the PPC external interrupt and attaches the local EPIC routines* for interrupt connecting, enabling and disabling to the corresponding system* routine pointers.** It then initializes the EPIC registers, clears any pending EPIC interrupts,* and enables interrupt handling by the EPIC.** RETURNS: OK always*/STATUS sysEpicInit (void)    {    int			i;    UINT32 temp = 0;    /* Initialize the interrupt table */    for (i = 0; i < SYSTEM_INTERRUPT_TABLE_SIZE; i++)        sysIntTbl[i] = NULL;     /* connect the interrupt demultiplexer to the PowerPC external interrupt */    excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysEpicIntHandler);    /* attach the BSP specific routines to the operating system.  */    _func_intConnectRtn = sysEpicIntConnect;    _func_intEnableRtn = sysEpicIntEnable;    _func_intDisableRtn = sysEpicIntDisable;    /* Initialze the global timer frequency to the MPU speed. */    sysPciOutLong((UINT32)EPIC_TIMER_FREQ_REG, sysGetMpuSpd());    /* Initialze the 4 global timer interrupt sources */    sysPciOutLong((UINT32)EPIC_TIMER0_VEC_PRI_REG, INIT_TMR_SRC0);    sysPciOutLong((UINT32)EPIC_TIMER1_VEC_PRI_REG, INIT_TMR_SRC1);    sysPciOutLong((UINT32)EPIC_TIMER2_VEC_PRI_REG, INIT_TMR_SRC2);    sysPciOutLong((UINT32)EPIC_TIMER3_VEC_PRI_REG, INIT_TMR_SRC3);    /* Initialize the 16 serial interrupt sources */    sysPciOutLong((UINT32)EPIC_SER_SRC0_VEC_PRI_REG, INIT_SER_SRC0);    sysPciOutLong((UINT32)EPIC_SER_SRC1_VEC_PRI_REG, INIT_SER_SRC1);    sysPciOutLong((UINT32)EPIC_SER_SRC2_VEC_PRI_REG, INIT_SER_SRC2);    sysPciOutLong((UINT32)EPIC_SER_SRC3_VEC_PRI_REG, INIT_SER_SRC3);    sysPciOutLong((UINT32)EPIC_SER_SRC4_VEC_PRI_REG, INIT_SER_SRC4);    sysPciOutLong((UINT32)EPIC_SER_SRC5_VEC_PRI_REG, INIT_SER_SRC5);    sysPciOutLong((UINT32)EPIC_SER_SRC6_VEC_PRI_REG, INIT_SER_SRC6);    sysPciOutLong((UINT32)EPIC_SER_SRC7_VEC_PRI_REG, INIT_SER_SRC7);    sysPciOutLong((UINT32)EPIC_SER_SRC8_VEC_PRI_REG, INIT_SER_SRC8);    sysPciOutLong((UINT32)EPIC_SER_SRC9_VEC_PRI_REG, INIT_SER_SRC9);    sysPciOutLong((UINT32)EPIC_SER_SRC10_VEC_PRI_REG, INIT_SER_SRC10);    sysPciOutLong((UINT32)EPIC_SER_SRC11_VEC_PRI_REG, INIT_SER_SRC11);    sysPciOutLong((UINT32)EPIC_SER_SRC12_VEC_PRI_REG, INIT_SER_SRC12);    sysPciOutLong((UINT32)EPIC_SER_SRC13_VEC_PRI_REG, INIT_SER_SRC13);    sysPciOutLong((UINT32)EPIC_SER_SRC14_VEC_PRI_REG, INIT_SER_SRC14);    sysPciOutLong((UINT32)EPIC_SER_SRC15_VEC_PRI_REG, INIT_SER_SRC15);    /* Initialize the 4 external interrupt sources */    /* These may not do anything since the device is in serial mode */    sysPciOutLong((UINT32)EPIC_EXT_SRC0_VEC_PRI_REG, INIT_EXT_SRC0);    sysPciOutLong((UINT32)EPIC_EXT_SRC1_VEC_PRI_REG, INIT_EXT_SRC1);    sysPciOutLong((UINT32)EPIC_EXT_SRC2_VEC_PRI_REG, INIT_EXT_SRC2);    sysPciOutLong((UINT32)EPIC_EXT_SRC3_VEC_PRI_REG, INIT_EXT_SRC3);    /* Initialize the 2 DMA interrupt sources */    sysPciOutLong((UINT32)EPIC_DMA_CHAN0_INTR_VEC_SRC, INIT_DMA_SRC0);    sysPciOutLong((UINT32)EPIC_DMA_CHAN1_INTR_VEC_SRC, INIT_DMA_SRC1);    /* Initialize the I2C unit interrupt source */    sysPciOutLong((UINT32)EPIC_I2C_INTR_VEC_SRC, INIT_I2C_SRC);    /* Initialize the message unit interrupt source. */    sysPciOutLong((UINT32)EPIC_MSG_UNIT_INTR_VEC_SRC, INIT_MSGUNIT_SRC);    /* Setup the EPIC to mixed mode. */    temp = sysPciInLong((UINT32)EPIC_GLOBAL_CONFIG_REG );    sysPciOutLong((UINT32)EPIC_GLOBAL_CONFIG_REG, (temp | EPIC_GC_MIXED));    /* Set to serial-interrupt mode (16 sources) and clock ratio to 4. */    temp = sysPciInLong((UINT32)EPIC_INTR_CONFIG_REG);    sysPciOutLong((UINT32)EPIC_INTR_CONFIG_REG, (temp |                                       (EPIC_IC_R_VALUE << EPIC_IC_R_SHFT) |                                       EPIC_IC_SIE));    /* Enable interrupts for this processor (1 and above). */    sysPciOutLong((UINT32)EPIC_CUR_TASK_PRI_REG, EPIC_TASK_PRI_1);    return(OK);    }/******************************************************************************** sysEpicIntConnect - connect an interrupt handler to the system vector table** This function connects an interrupt handler to the system vector table.** RETURNS: OK/ERROR.*/LOCAL STATUS sysEpicIntConnect    (    VOIDFUNCPTR *      vector,         /* interrupt vector to attach */    VOIDFUNCPTR        routine,        /* routine to be called */    int                parameter       /* parameter to be passed to routine */    )    {    INT_HANDLER_DESC * newHandler;    INT_HANDLER_DESC * currHandler;    LOCAL_INT_DATA     connect;    /* validate the vector */    if (((int)vector < 0) || ((int)vector > (SYSTEM_INTERRUPT_TABLE_SIZE - 1)))        return (ERROR);     /* create a new interrupt handler */    if ((newHandler = (INT_HANDLER_DESC *)calloc (1, sizeof (INT_HANDLER_DESC)))	 == NULL)        return (ERROR);     /* initialize the new handler */    newHandler->vec  = routine;    newHandler->arg  = parameter;    newHandler->next = NULL;    /* install the handler in the system interrupt table */    if (sysIntTbl[(int)vector] == NULL)        {        sysIntTbl[(int)vector] = newHandler; /* single int. handler case */        }    else        {        currHandler = sysIntTbl[(int)vector]; /* multiple int. handler case */        while (currHandler->next != NULL)            {            currHandler = currHandler->next;            }        currHandler->next = newHandler;        }    /*      * if the connect is for an EPIC interrupt,      * then store the vector into the appropriate EPIC vector register     */    connect.regAddr = getEpicVecAddr((int)vector);    if (connect.regAddr > 0)        {        /* read the vector register */        connect.regVal = sysPciInLong((UINT32)(connect.regAddr));        /* store the interrupt vector number */        connect.regVal |= (int)vector;        /* write the contents of the vector register back */        sysPciOutLong((UINT32)(connect.regAddr), connect.regVal);        }    return (OK);    }/******************************************************************************** sysEpicIntEnable - enable an Epic interrupt level** This routine enables a specified Epic interrupt level.** RETURNS: OK or ERROR if interrupt level not supported*/LOCAL int sysEpicIntEnable    (    int intLevel        /* interrupt level to enable */    )    {    LOCAL_INT_DATA	enable;    /* Validate vector.  */    if (intLevel < 0)        return (ERROR);    enable.regAddr = getEpicVecAddr(intLevel);    if (enable.regAddr > 0)        {        /* read the vector register */        enable.regVal = sysPciInLong((UINT32)(enable.regAddr));        /* enable the interrupt */        enable.regVal &= (~INT_MASK_BIT);        /* write the contents of the vector register back */        sysPciOutLong((UINT32)(enable.regAddr), enable.regVal);        }    return (OK);    }/******************************************************************************** sysEpicIntDisable - disable an Epic interrupt level** This routine disables a specified Epic interrupt level.** RETURNS: OK or ERROR if interrupt level not supported*/LOCAL int sysEpicIntDisable    (    int intLevel        /* interrupt level to disable */    )    {    LOCAL_INT_DATA      disable;     /* Validate vector.  */    if (intLevel < 0)        return (ERROR);    /* get the vector reg. offset value */    disable.regAddr = getEpicVecAddr(intLevel);     if (disable.regAddr > 0)        {        /* read the vector register */        disable.regVal = sysPciInLong((UINT32)(disable.regAddr));        /* disable the interrupt */        disable.regVal |= INT_MASK_BIT;        /* write the contents of the vector register back */        sysPciOutLong((UINT32)(disable.regAddr), disable.regVal);        }    return (OK);    }/******************************************************************************** sysEpicIntHandler - handle an interrupt received at the Epic* * This routine will process interrupts received from PCI or ISA devices as* these interrupts arrive via the EPIC.  This routine supports EPIC interrupt* nesting.** RETURNS: N/A*/void sysEpicIntHandler     (    void    )    {    INT_HANDLER_DESC *  currHandler;    UINT32		vecNum;    int			dontCare;    /* get the vector from the EPIC IACK reg. */    vecNum = sysPciInLong((UINT32)EPIC_IACK_REG);    vecNum &= VECTOR_MASK;    /* Check for spurious interrupt. */    if (vecNum == 0xFF)        {        logMsg ("EPIC Spurious Interrupt!\n", 0,0,0,0,0,0);        return;        }     /*     * Allow maskable interrupts to the CPU.  EPIC will hold off     * lower and equal interrupts until EPIC_EOI is performed.     */    CPU_INT_UNLOCK(_PPC_MSR_EE);#ifdef INCLUDE_INSTRUMENTATION    if (evtLogTIsOn)      (* _func_evtLogT1_noTS) (EVENT_INT_ENT((int)vecNum),			       evtTimeStamp);#endif /* INCLUDE_INSTRUMENTATION */    /* call the necessary interrupt handlers */    if ((currHandler = sysIntTbl[vecNum]) == NULL)        {        logMsg ("uninitialized EPIC interrupt %d\r\n", vecNum, 0,0,0,0,0);        }    else        {        /* Call EACH respective chained interrupt handler */        while (currHandler != NULL)            {            currHandler->vec (currHandler->arg);            currHandler = currHandler->next;            }        }    /* Disable external interrupts. */    CPU_INT_LOCK(&dontCare);    /*     * ERRATA FIX:     *   sysDecDelay() is needed for Kahlua(MPC8240) Revision 1.0/1.1     *   Errata #2, EPIC Serial Mode Interrupt Twice from Single Source.     *   See Kahlua Errata Sheet - Version 1.0.3     */    sysDecDelay(4);    /* Issue an end-of-interrupt to the EPIC */    sysPciOutLong((UINT32)EPIC_EOI_REG, 0);    return;    }/******************************************************************************** getEpicVecAddr - get the vector address of an EPIC register ** This routine returns the appropriate EPIC register address based on the* specified EPIC interrupt level.** RETURNS: EPIC register address or zero if not a supported level.*/LOCAL int getEpicVecAddr    (    int		intLevel	/* interrupt level to translate */    )     {    int 	offset = 0;    /* check for a timer interrupt level */    if ((intLevel >= TIMER_INTERRUPT_BASE) &&         (intLevel < EXTERNAL_INTERRUPT_BASE))        {        offset = intLevel - TIMER_INTERRUPT_BASE;        offset = (int)EPIC_TIMER0_VEC_PRI_REG + (offset * REG_OFFSET * 4);        }    /* check for external interrupt level */    if ((intLevel >= EXTERNAL_INTERRUPT_BASE) &&         (intLevel < INTERNAL_INTERRUPT_BASE))        {        offset = intLevel - EXTERNAL_INTERRUPT_BASE;        offset = (int)EPIC_EXT_SRC0_VEC_PRI_REG + (offset * REG_OFFSET * 2);        }     /* check for a serial interrupt level */    if (intLevel >= SERIAL_INTERRUPT_BASE)        {        offset = intLevel - SERIAL_INTERRUPT_BASE;        offset = (int)EPIC_SER_SRC0_VEC_PRI_REG + (offset * REG_OFFSET * 2);        }        return (offset);    }

⌨️ 快捷键说明

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