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

📄 sysepic.c

📁 vxworks 操作系统 824x bsp代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* sysEpic.c - Driver for Embedded Programmable Interrupt Controller *//* Copyright 1984-1999 Wind River Systems, Inc. */#include "copyright_wrs.h"/*modification history--------------------01b,01apr02,jnz   added support for 8245/8241 on chip duarts.01a,10oct99,mtl   written from SPS/Motorola by teamF1*//*DESCRIPTIONThis module implements the Embedded Programmable Interrupt Controller (EPIC)driver for the PPMC 8240 on the Sandpoint board.The EPIC is an integrated interrupt controller in the 8240 whichprovides following major capabilities:  Support for five external interrupt sources or one serial-style  interrupt (16 interrupt sources)  Support for connection of external interrupt controller device e.g. 8259  which is implemented as a part of a WinBond chip.        16 programmable interrupt priority levels  Fully-nested interrupt delivery  Spurious vector generationEPIC features are customized by writing into general control registersor into interrupt level specific registers (IVPRs).This driver allows a basic interface to the EPIC such as intializing it,setting interrupt vectors, priorities, level/edge sense and interruptpolarities, as well as enabling and disabling specific interrupts.This driver implements a complete interrupt architecture system, completewith vector table.This driver provides the vector table for the system.  It can supporta total of 256 vectors.  In this driver the EPIC controller device can onlygenerate 5 different vectors, one for each external interrupt.Other interrupt controllers such as the WINBOND on the Sandpoint 8240can be connected to one of the above external interrupts.The actual vector number corresponding to IRQ0is determined by the value in sysVectorIRQ0 at initialization time.  Theother vector numbers are generated by adding the IRQ number to this vectornumber. For the Sandpoint PMMC8240, the value of sysVectorIRQ0 isinitialized from a constant INT_NUM_IRQ0, which is = 0x10 (16). Soall IRQs above 16 are assumed to be controlled by an externalinterrupt controller such as a the WinBond w83553.Lower IRQ's are controlled by the 8240's embedded programmable interruptcontroller or EPIC.Although the EPIC has 5 external interrupts sources, only 4 are availablefrom the PPMC unit.Since interrupt vectors can be shared, this driver does provide foroverloading of interrupt routines (i.e. there isa list of interrupt routines for each interrupt vector (level)).  To servicea vector requires that all connected interrupt routines be called in orderof their connection.The following diagram shows an example of how interrupts canbe configured in this system.    EPIC Vector table0  |-------|   |-------|							     |-------|   |-------|---------------------   |-------|			|5  |-------|			|   |-------|			| IRQ 2 handler				|    ....	      -----------------------------------		      |			     		|    sysVectorIRQ0=16  |			     		|16 |-------|	      |			     		|   |-------|<--------WinBond Interrupt handler	   PCI slot 3 interrupt handler   |-------|		Cascaded 8259s   |-------|   |-------|   |-------|32 |-------|    ....		       |-------|   |-------|   |-------|   |-------|   |-------|   |-------|   |-------|256|-------|If there are other devices in the system capable of generating their ownvectors then we presume that an appropriate interrupt handler is createdand attached to the vector associated with the correct IRQ number.  Thatinterrupt handler would get a new vector directly from the device and thencall all of the handlers attached to that new vector.  Vector information isstored in a linked list of INT_HANDLER_DESC structures. The sysIntTbl arraycontains a pointer to the first entry for each vector.An example would be a VME interface chip.If the VME chip interrupts the CPU on IRQ8, then the BSP should createa special VME interrupt handler and attach it to vector # (sysVectorIRQ0 + 8).When the handler is called, it should get the new vector from the VMEdevice.  It will then use that new vector # to locate the specific VMEdevice handler routine from sysIntTbl.  The VME interrupt handler willcall each handler connected to the devices vector.  Note that the usermust insure that no VME device uses a vector that matches the vector usedby the VME interface chip itself.  This could cause an infinite loop tobe generated..CS/@ This is the sample VME interrupt handler (IRQ8) @/VOID sysVmeHandler (void)    {    INT_HANDLER_DEC * pVector;    int newVec;    newVec = ????; /@ get real vector from device @/    /@ if no VME interrupt is present, exit immediately @/    if (newVec < 0 || newVec > 255)	return;    /@ process all connected routines @/    pVector = sysIntTbl[newVec];    while (pVector != NULL)        {	(*pVector->vec) (pVector->arg);        pVector = pVector->next;        }    }/@ The BSP would connect the VME handler to the vector for IRQ 8 @/    #define SYS_VME_VEC  (sysVectorIRQ0 + 8) /@ IRQ8 @/    ...    intConnect (INUM_TO_IVEC(SYS_VME_VEC), sysVmeHandler, 0);    ....CE.SH INITIALIZATIONThis driver is initialized from the BSP, usually as part of sysHwInit().The first routine to be called is sysEpicInit(). The routine resets theglobal configuration register and resets the epic registers to defaultvalues.The second routine to be called is sysEpicIntrInit().  This routine takes noarguments. This routine allocates the vector table and initializes thechips to a default state.  All individual interrupt sources are disabled.Each has to be individually enabled by intEnable() before it will beunmasked and allowed to generate an interrupt..SH CUSTOMIZING THIS DRIVERThe macros CPU_INT_LOCK() and CPU_INT_UNLOCK provide the accessto the CPU level interrupt lock/unlock routines.  We presume that thereis a single interrupt line to the CPU.  By default these macros callintLock() and intUnlock() respectively.*//* includes */#include "vxWorks.h"#include "sysEpic.h"#include "mpc107.h"#include "sysLib.h"#include "stdio.h"#include "string.h"#ifdef INCLUDE_WINDVIEW#include "private/eventP.h"#endif/* defines */#ifndef CPU_INT_LOCK#   define CPU_INT_LOCK(pData) \	(*pData = intLock ())#endif#ifndef CPU_INT_UNLOCK#   define CPU_INT_UNLOCK(data) \	(intUnlock (data))#endif/* externs */IMPORT STATUS 	excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);#if FALSE /* defined(INCLUDE_WINDVIEW) || defined(INCLUDE_INSTRUMENTATION) */IMPORT	int	evtTimeStamp;  /* Windview 1.0 only */#endif/* get the interrupt hook routines  prototypes*/IMPORT STATUS	(*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);IMPORT int	(*_func_intEnableRtn) (int);IMPORT int	(*_func_intdisableRtn)  (int);/* globals */INT_HANDLER_DESC * sysIntTbl [INTERRUPT_TABLESIZE]; /* system interrupt tbl */int epicIntTrace = 0;   /* epic internal interrupts trace *//* locals *//* forward declarations */LOCAL STATUS  	sysEpicIntConnect (VOIDFUNCPTR * vector, VOIDFUNCPTR routine,                                   int parameter);LOCAL STATUS	sysEpicIntEnable (int intNum);LOCAL STATUS	sysEpicIntDisable (int intNum);LOCAL void 	sysEpicIntHandler (void);/********************************************************************************* sysEpicInit - initialize the epic controller** This routine resets the global Configuration Register, thus it:*  -  disables all interrupts*  -  sets epic registers to reset values** It then sets the EPIC operation mode to Mixed Mode (vs. Pass Through* mode). At this point only mixed mode is supported which means the EPIC* is not configured for the pass through mode.** Input:*    -  <irqType> is either Direct IRQs (0) or Serial Interrupt IRQs (1).*    -  <clkRatio> is clock frequency driving the serial interrupt*         interface.**   If irqType is Direct IRQs:*    - irqType is written to the SIE bit of the EPIC Interrupt*       Configuration register.*    - clkRatio is ignored.  **   If irqType is Serial IRQs:*    - both irqType and clkRatio will be written to the EPIC*      Interrupt Configuration register.** NOMANUAL* * RETURNS: N/A*/    void sysEpicInit    (    ULONG 	irqType, 	/* irq type to initialize with */    ULONG 	clkRatio	/* clock ratio */    )    {    ULONG 	gcrVal;    ULONG 	icrVal;    int 	irq;    gcrVal = sysEUMBBARRead (EPIC_GLOBAL_REG);    gcrVal |= (EPIC_GCR_RESET);        sysEUMBBARWrite (EPIC_GLOBAL_REG, gcrVal);    /* wait for the reset sequence to be completed */        while (sysEUMBBARRead (EPIC_GLOBAL_REG) & EPIC_GCR_RESET)        {        ; /* do nothing */        }    gcrVal = sysEUMBBARRead (EPIC_GLOBAL_REG);    gcrVal |= (EPIC_GCR_MODE_MIXED);	/* configure for mixed mode */        sysEUMBBARWrite (EPIC_GLOBAL_REG, gcrVal);    icrVal = sysEUMBBARRead (EPIC_INT_CONF_REG);	/* read EICR */    if (irqType == EPIC_DIRECT_IRQ)        {        icrVal &= ~(EPIC_ICR_SEI); /* disable serial mode interrupts */        }    else /* serial mode is configured */        {        if (clkRatio != 0)            {            icrVal |= EPIC_ICR_CLK_RATIO (clkRatio);            }        }    sysEUMBBARWrite (EPIC_INT_CONF_REG, icrVal);    while (epicIntAck() != 0xff)           /* Clear all pending interrupt */        {        /* do nothing */	}    /* init all IVPRs to sense = 1, polarity = defined, vec = 0, prio = 0 */    for (irq = 0; irq < EPIC_MAX_EXT_IRQS; irq++)        {        epicIntDisable (EPIC_VEC_REG(irq));        epicIntSourceSet (EPIC_VEC_REG(irq), EPIC_INT_POLARITY,                          EPIC_SENSE_LVL, 0x0, 0x0);        }#ifdef INCLUDE_DUART    /* init duart interrupts */    epicIntDisable (EPIC_DUART1_INT_VEC_REG);    epicIntSourceSet (EPIC_DUART1_INT_VEC_REG, EPIC_INT_POLARITY, \		      EPIC_SENSE_LVL, 0x0, EPIC_DUART1_INT_VECT);                         epicIntDisable (EPIC_DUART2_INT_VEC_REG);    epicIntSourceSet (EPIC_DUART2_INT_VEC_REG, EPIC_INT_POLARITY,  \		      EPIC_SENSE_LVL, 0x0, EPIC_DUART2_INT_VECT);#endif /* INCLUDE_DUART */    epicCurTaskPrioSet (EPIC_PRIORITY_MAX); /* set it to highest priority */    }/********************************************************************************* sysEpicIntrInit - initialize the interrupt table** This function initializes the interrupt mechanism of the board.** RETURNS: OK, always.*/STATUS  sysEpicIntrInit (void)    {    int vector;    /* initialize the interrupt table */    for (vector = 0; vector < INTERRUPT_TABLESIZE; vector++)        {	sysIntTbl [vector] = NULL;        }    /*     * connect the interrupt demultiplexer to the PowerPC external      * interrupt exception vector.     * i. e.  put the address of this interrupt handler in     * the PowerPC's only external interrupt exception vector     * which is  _EXC_OFF_INTR = 0x500     */    excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysEpicIntHandler);    /*       * set up the BSP specific interrupt routines     * Attach the local routines to the VxWorks system calls     *     */    _func_intConnectRtn  =  sysEpicIntConnect;    _func_intEnableRtn   =  sysEpicIntEnable;    _func_intDisableRtn  =  sysEpicIntDisable;    epicCurTaskPrioSet (EPIC_PRIORITY_MIN); /* set it to lowest priority */        return (OK);    }/********************************************************************************* sysEpicIntEnable - enable a EPIC interrupt level** This routine enables a specified EPIC interrupt level.** NOMANUAL** RETURNS: OK.*/LOCAL int  sysEpicIntEnable    (    int intNum    )    {    if ((intNum >= INT_NUM_IRQ0) && 	/* check of winBond IRQs */        (intNum != EPIC_DUART1_INT_VECT) && 	(intNum != EPIC_DUART2_INT_VECT))        {        intNum = intNum - INT_NUM_IRQ0;                if ((sysPciIbcIntEnable (intNum)) != OK)            {            return (ERROR);            }        return (OK);        }    /* enable interrupt on EPIC */    if (((0 <= intNum)  && (intNum < EPIC_MAX_EXT_IRQS))  ||        (intNum == EPIC_DUART1_INT_VECT)    ||         (intNum == EPIC_DUART2_INT_VECT))        {        epicIntEnable (EPIC_VEC_REG (intNum));        return OK;        }    else        return (ERROR);    }/********************************************************************************* sysEpicIntDisable - disable a EPIC interrupt level** This routine disables a specified EPIC interrupt level.** NOMANUAL** RETURNS: OK.*/LOCAL int  sysEpicIntDisable    (    int 	intNum    )    {    int 	mask;    if ((intNum >= INT_NUM_IRQ0) && 	/* check of winBond IRQs */        (intNum != EPIC_DUART1_INT_VECT) && 	(intNum != EPIC_DUART2_INT_VECT))        {        intNum = intNum - INT_NUM_IRQ0;        mask = sysPciIbcIntDisable (intNum);        if (mask == ERROR)            {            return (ERROR);            }        return (OK);        }      /* disable interrupt on EPIC */     if (((0 <= intNum)  && (intNum < EPIC_MAX_EXT_IRQS)) ||        (intNum == EPIC_DUART1_INT_VECT)    ||         (intNum == EPIC_DUART2_INT_VECT))        {        epicIntDisable (EPIC_VEC_REG(intNum));        return OK;        }    else        return (ERROR);    }/********************************************************************************* sysEpicIntConnect - connect an interrupt handler to the system vector table** This function connects an interrupt handler to the system vector table.** RETURNS: OK or 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 *	pNewHandler;    INT_HANDLER_DESC *	pCurrHandler;    int			intVal;    BOOL		sharing = FALSE;	    if (((int)vector < 0)  || ((int) vector > INTERRUPT_TABLESIZE)) 	{        return (ERROR);   /*  out of range  */	}    /* create a new interrupt handler */    pNewHandler = malloc (sizeof (INT_HANDLER_DESC));    /* check if the memory allocation succeed */    if (pNewHandler == NULL)	return (ERROR);    /*  initialize the new handler  */    pNewHandler->vec = routine;    pNewHandler->arg = parameter;    pNewHandler->next = NULL;    /* install the handler in the system interrupt table  */    intVal = intLock (); /* lock interrupts to prevent races */    if (sysIntTbl [(int) vector] == NULL)	{        sysIntTbl [(int) vector] = pNewHandler;  /* single int. handler case */	}    else	{        pCurrHandler = sysIntTbl[(int) vector];/* multiple int. handler case */        while (pCurrHandler->next != NULL)            {            pCurrHandler = pCurrHandler->next;            }

⌨️ 快捷键说明

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