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

📄 ppc860intr.c

📁 操作系统vxworks平台下中断控制器设备的驱动程序,支持多种芯片,支持多种cpu
💻 C
字号:
/* ppc860Intr.c - PowerPC 800 series interrupt driver *//* Copyright 1984-2001 Wind River Systems, Inc. *//* Copyright 1997,1998 Motorola, Inc., All Rights Reserved */#include "copyright_wrs.h"/*modification history--------------------01i,28jan02,dtr  Removing diab warnings.01h,15sep01,dat  Removed special def of CACHE_PIPE_FLUSH01g,28apr99,dat  Merge from 2_0_001o,30jan99,cn   fixed SPR #22321.01n,24aug98,cjtc windview 2.0 event logging is now single step. Timestamp no                 longer stored by intEnt. Avoids out-of-sequence timestamps in                 event log (SPR 21868)0lm,12aug98,gls  corrected assignment of evtIntNum01l,04aug98,gls  fixed SPR #21239, kernel locks on boot when instrumented01k,16apr98,pr   added WindView 20 instrumentation.01j,30mar98,map  initialize _func_int{Enable,Disable}Rtn [SPR# 20447]01i,26mar98,map  added ppc860IntEnable, ppc860IntDisable, removed duplicate                 #ifdef'd code, reworked ppc860IntrInit(). [SPR# 20447]01h,11nov97,map  redo clearing CISR bits [SPR# 8781], and default SCC                 interrupt priority01g,23jun97,map  added default SCC interrupt priority [SPR# 8692]01f,19jun97,map  added IV_SCC[34] definitions [SPR# 8450]01e,17jun97,map  fixed clearing CISR bits [SPR# 8781]01d,06mar97,tpr  fixed properly SPR #8042.01c,21feb97,tpr  fixed interrupt bit clearing in CISR (SPR #8042).01b,18sep96,pr   added WindView instrumentation.01a,17feb96,tpr  written.*//*DESCRIPTIONThe PowerPC 800 CPU series is divided in three units: PowerPC core, SystemInterface Unit (SIU) and Communication Processor Unit (CPM). The PowerPCcore accepts only one external interrupt exception (vector 0x500). The SIUprovides an interrupt controller which provides 32 levels but only 16 areused. The Interrupt controller is connected to the PowerPC core external interrupt. The CPM unit also provides an interrupt controller which canbe connected to one of the SIU interrupt controler entries. This libraryprovides the routines to manage these interrupt controllersppc860IntrInit() connects the default demultiplexers, ppc860IntrDeMux() andppc860CpmIntrDeMux(), to the external interrupt vector and initializes a tablecontaining a function pointer and an associated parameter for each interruptsource. ppc860IntrInit() is called by sysHwInit() from sysLib.c.The default demultimplexer, ppc860IntrDeMux() detects which peripheral or controller has raised an interrupt and calls the associated routine with its parameter. If the interrupt comes from the CPM interrupt contoller, theppc860CpmIntDeMux() function is called. As ppc860IntrDeMux(), this functiondetects which peripheral or controller has raised an interrupt and calls theassociated routine with its parameter.INCLUDE FILES: drv/intrCtl/ppc860Intr.h, drv/multi/ppc860Siu.h,drv/multi/ppc860Cpm.h*//* includes */#include "intLib.h"#include "iv.h"#include "drv/intrCtl/ppc860Intr.h"#include "drv/multi/ppc860Siu.h"#include "drv/multi/ppc860Cpm.h"/* default SCC relative interrupt priority */#define	CICR_SCCP_DEF	(CICR_SCCDP_SCC4 | CICR_SCCCP_SCC3 | \                         CICR_SCCBP_SCC2 | CICR_SCCAP_SCC1 )#ifdef  INCLUDE_WINDVIEW#include "private/funcBindP.h"#include "private/eventP.h"LOCAL  int		cpmIntNum;LOCAL  int		cpmVecNum;#endif /* INCLUDE_WINDVIEW *//* local */LOCAL INTR_HANDLER	intrVecTable[NUM_VEC_MAX];	/*  Intr vector table *//* forward declarations */LOCAL void	ppc860IntrDeMux (void);LOCAL void	ppc860CpmIntrDeMux (int);LOCAL STATUS	ppc860IntConnect (VOIDFUNCPTR *, VOIDFUNCPTR, int);LOCAL int	ppc860IntEnable (int);LOCAL int	ppc860IntDisable (int);/********************************************************************************* ppc860IntrInit - initialize the interrupt manager for the PowerPC 800 series** This routine connects the default demultiplexers, ppc860IntrDeMux() and * ppc860CpmIntrDeMux, to the external interrupt vector and associates all * interrupt sources with the default interrupt handler.  This routine is* called by sysHwInit() in sysLib.c.** NOTE: All interrupt from the SIU and CPM unit are enabled, CICR is setup so* that SCC1 has the highest relative interrupt priority, through SCC4 with the* lowest.** RETURN : OK or ERROR if the SUI interrupt level to connect the CPM * interrupt contoller is wrong.*/STATUS ppc860IntrInit     (    VOIDFUNCPTR *	cpmIntrVec	/* Intr level of the CPM Intr ctrl */    )    {    VOIDFUNCPTR defaultVec;     	/* INTR3 default vector */    UINT32	regBase;		/* device register base address */    UINT32	cicrIntLevel;		/* CICR interupt level */    UINT32	simaskIntLevel;    int		vector;    /* Get the default vector connected to the External Interrupt (0x500) */    defaultVec = (VOIDFUNCPTR) excVecGet ((FUNCPTR *) _EXC_OFF_INTR);    /* Connect the interrupt demultiplexer to External Interrupt (0x500) */    excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, ppc860IntrDeMux);    /* Install `system' intConnect routine */    if (_func_intConnectRtn == NULL)        _func_intConnectRtn = ppc860IntConnect;    if (_func_intEnableRtn == NULL)        _func_intEnableRtn = ppc860IntEnable;    if (_func_intDisableRtn == NULL)        _func_intDisableRtn = ppc860IntDisable;    /* Set all vectors to default handler */    for (vector = 0; vector < NUM_VEC_MAX; vector++)	intConnect (INUM_TO_IVEC(vector), defaultVec, 0);    /* Get the CPM interrupt level */    switch (IVEC_TO_INUM(cpmIntrVec))	{	case IVEC_TO_INUM(IV_LEVEL0): 	    cicrIntLevel = CICR_IRL_LVL0;	    simaskIntLevel = SIMASK_LVM0;	    break; 	case IVEC_TO_INUM(IV_LEVEL1):	    cicrIntLevel = CICR_IRL_LVL1;	    simaskIntLevel = SIMASK_LVM1;	    break; 	case IVEC_TO_INUM(IV_LEVEL2):	    cicrIntLevel = CICR_IRL_LVL2;	    simaskIntLevel = SIMASK_LVM2;	    break; 	case IVEC_TO_INUM(IV_LEVEL3):	    cicrIntLevel = CICR_IRL_LVL3;	    simaskIntLevel = SIMASK_LVM3;	    break; 	case IVEC_TO_INUM(IV_LEVEL4):	    cicrIntLevel = CICR_IRL_LVL4;	    simaskIntLevel = SIMASK_LVM4;	    break; 	case IVEC_TO_INUM(IV_LEVEL5):	    cicrIntLevel = CICR_IRL_LVL5;	    simaskIntLevel = SIMASK_LVM5;	    break; 	case IVEC_TO_INUM(IV_LEVEL6):	    cicrIntLevel = CICR_IRL_LVL6;	    simaskIntLevel = SIMASK_LVM6;	    break; 	case IVEC_TO_INUM(IV_LEVEL7):	    cicrIntLevel = CICR_IRL_LVL7;	    simaskIntLevel = SIMASK_LVM7;	    break; 	default:	    return (ERROR);	}    /*     * Connect the CPM interrupt demultiplexer at the level specified by     * `cpmIntLevel'     */#ifdef  INCLUDE_WINDVIEW    cpmVecNum = IVEC_TO_INUM(cpmIntrVec);#endif /* INCLUDE_WINDVIEW */    intConnect (cpmIntrVec, ppc860CpmIntrDeMux, simaskIntLevel);    /* Get the register base address */    regBase = vxImmrGet();    /*      * Set the request interrupt level from the CPM and enable CPM interrupt     * generation.     */    * CICR(regBase) = (CICR_SCCP_DEF | cicrIntLevel | CICR_IEN | CICR_HP_MSK);         /* Enable required CPM interrupt */    * SIMASK(regBase) = simaskIntLevel;    return (OK);     }/********************************************************************************* ppc860IntConnect - connect a routine to an interrupt ** This routine connects any C or assembly routine to one of the multiple * sources of interrupts.** The connected routine can be any normal C code, except that it must not * invoke certain operating system functions that may block or perform I/O* operations.** <vector> types are defined in h/drv/intrClt/ppc860Intr.h.** RETURNS: OK, or ERROR if <vector> is unknown.** SEE ALSO: ppc860Intr.h*/LOCAL STATUS ppc860IntConnect    (    VOIDFUNCPTR *	vector,		/* interrupt vector to attach to */    VOIDFUNCPTR		routine,	/* routine to be called */    int 		parameter	/* parameter to be passed to routine */    )    {    /* test the vector */    if (IVEC_TO_INUM(vector) >= NUM_VEC_MAX)	return (ERROR);    intrVecTable[IVEC_TO_INUM(vector)].vec = routine;    intrVecTable[IVEC_TO_INUM(vector)].arg = parameter;    return (OK);    }/********************************************************************************* ppc860IntrDeMux - SIU interrupt demultiplexer ** This routine must be bound to external interrupt exception (vector 0x500). * It is used to call the appropriate handler with its argument when an* interrupt occurs. ** The interrupts are prioritized in the following order:** NOTE: when this function is called the interrupts are still locked. It's* this function responsability to unlock the interrupt.** RETURNS: N/A*/LOCAL void ppc860IntrDeMux (void)    {#ifdef	INCLUDE_WINDVIEW    UINT32 	evtIntNum;		/* windview interrupt vector */#endif /* INCLUDE_WINDVIEW */    UINT8 	intVec;			/* interrupt vector */    UINT32	regBase;		/* register Base Address */    UINT32	intMask;		/* current interrupt mask */    regBase = vxImmrGet();    /* read the interrupt vector register */    intVec = (* SIVEC(regBase)) >> 26;#ifdef  INCLUDE_WINDVIEW    /*      * if it is a cpm interrupt we need to know the corresponding cpm     * level, that we should get from the CPM demultiplexer. But we     * need the value here and the value can be read only once. We      * save the value here so that once the CPM demultiplexer is called,     * it will read the value from the global variable cpmIntNum.     *      * Since we do not know the CPM level a priori, we have to leave     * enough space for the cpm interrupts in the windview list.     * Therefore, any interrupt number bigger than the CPM level will     * be increased of 15 so to leave those spots to the corresponding     * CPM interrupts.     */    if (intVec == cpmVecNum)	{	/* acknowledge the interrupt */		*CIVR(regBase) = CIVR_IACK;    	CACHE_PIPE_FLUSH ();		cpmIntNum = * CIVR(regBase) >> 11; 	evtIntNum = cpmIntNum + 32;	}    else	evtIntNum = intVec;    WV_EVT_INT_ENT(evtIntNum)#endif /* INCLUDE_WINDVIEW */    /* save the current interrupt mask */     intMask = * SIMASK(regBase);    /* lock all levels inferior to the interrupt detected */    * SIMASK(regBase) &= (0xffffffff << (32 - intVec));    /* unlock the interrupt */    intUnlock (_PPC_MSR_EE);    /* call the Interrupt Handler */    intrVecTable[intVec].vec (intrVecTable[intVec].arg);    /* restore the interrupt mask */    * SIMASK(regBase) = intMask;    return;    }/********************************************************************************* ppc860CpmIntrDeMux - CPM interrupt demultiplexer ** This routine must be bound to external interrupt exception (vector 0x500). * It is used to call the appropriate handler with its argument when an* interrupt occurs. ** The interrupts are prioritized in the following order:** RETURNS: N/A*/LOCAL void ppc860CpmIntrDeMux     (    int simaskLevel    )    {    int		intNum;			/* interrupt number */    UINT32	regBase;		/* register Base Address */    UINT32	intOldMask;		/* interrupt mask before the interrupt*/    /* get the device register base address */    regBase = vxImmrGet();    /* get the interrupt vector */#ifdef  INCLUDE_WINDVIEW    intNum = cpmIntNum; #else    /* acknowledge the interrupt */    * CIVR(regBase) = CIVR_IACK;    intNum = * CIVR(regBase) >> 11; #endif /* INCLUDE_WINDVIEW */    /* save the interrupt mask before the interrupt */    intOldMask = * CIMR(regBase);    /* lock all levels inferior to the interrupt detected */    * CIMR(regBase) &= (0xffffffff << (intNum + 1));    /* enable the CPM interrupt in the SIU controller */    * SIMASK(regBase) |= simaskLevel;    /* call the Interrupt Handler */    intrVecTable[intNum + 32].vec (intrVecTable[intNum + 32].arg);    /* clear the bit in the CISR */    * CISR(regBase) = (1 << intNum);    /* restore the interrupt mask */        * CIMR(regBase) = intOldMask;    }/********************************************************************************* ppc860IntEnable - enable one of the Level or IRQ interrupts into the SIU** This routine will unmask the bit in the SIMASK register corresponding to* the requested interrupt level.  The interrupt level must be in the range* of 0 - 31.* * RETURNS: 0, always.*/LOCAL int ppc860IntEnable    (    int intNum		/* interrupt level to enable (0 - 31) */    )    {    UINT32 regBase;    regBase = vxImmrGet();    if ((intNum >= 0) && (intNum < 32))	* SIMASK(regBase) |= (1 << (31 - intNum));    return 0;    }/********************************************************************************* ppc860IntDisable - Disable one of the Level or IRQ interrupts into the SIU** This routine will mask the bit in the SIMASK register corresponding to* the requested interrupt level.  The interrupt level must be in the range* of 0 - 31.* * RETURNS: 0, always.*/LOCAL int ppc860IntDisable    (    int intNum          /* interrupt level to disable (0 - 31) */    )    {    UINT32 regBase;        regBase = vxImmrGet();    if ((intNum >= 0) && (intNum < 32))        * SIMASK(regBase) &= ~(1 << (31 - intNum));    return 0;    }

⌨️ 快捷键说明

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