?? universe.c
字號:
#endif }/********************************************************************************* sysIntDisable - disable a bus interrupt level** This routine disables reception of a specified VMEbus interrupt level.** NOTE: revision 1.0 Universe chips can fail and lockup if two or more interrupt* levels are enabled. For more details see Tundra Universe Errata sheet.** RETURNS: OK, or ERROR if <intLevel> is not in the range 1 - 7.** SEE ALSO: sysIntEnable()*/STATUS sysIntDisable ( int intLevel /* interrupt level to disable (1-7) */ ) { int mask; if (intLevel < 1 || intLevel > 7) return (ERROR); /* clear any pending intr. for this level */ mask = 1 << intLevel; UNIV_OUT_LONG(UNIVERSE_LINT_STAT, mask); /* disable the interrupt */ sysUnivIntsEnabled &= ~mask; UNIV_OUT_LONG(UNIVERSE_LINT_EN, sysUnivIntsEnabled); return (OK); }/********************************************************************************* sysIntEnable - enable a bus interrupt level** This routine enables reception of a specified VMEbus interrupt level.** NOTE: revision 1.0 Universe chips can fail and lockup if two or more interrupt* levels are enabled. For more details see Tundra Universe Errata sheet.** RETURNS: OK, or ERROR if <intLevel> is not in the range 1 - 7.** SEE ALSO: sysIntDisable()*/STATUS sysIntEnable ( int intLevel /* interrupt level to enable (1-7) */ ) { int mask; if (intLevel < 1 || intLevel > 7) return (ERROR); /* clear any pending intr. for this level */ mask = 1 << intLevel; UNIV_OUT_LONG(UNIVERSE_LINT_STAT, mask); /* enable the interrupt */ sysUnivIntsEnabled |= mask; UNIV_OUT_LONG(UNIVERSE_LINT_EN, sysUnivIntsEnabled); /* map the interrupt. Currently all VME ints are mapped to LINT#0 */ UNIV_OUT_LONG(UNIVERSE_LINT_MAP0, 0); return (OK); }/********************************************************************************* sysBusIntAck - acknowledge a bus interrupt** This routine acknowledges a specified VMEbus interrupt level.** NOTE: This routine is included for BSP compliance only. Since VMEbus* interrupts are re-enabled in the interrupt handler, and acknowledged* automatically by hardware, this routine is a no-op.** RETURNS: NULL.** SEE ALSO: sysBusIntGen()*/int sysBusIntAck ( int intLevel /* interrupt level to acknowledge */ ) { return (0); }/********************************************************************************* sysBusIntGen - generate a bus interrupt** This routine generates a VMEbus interrupt for a specified level with a* specified vector. Only one VME interrupt can be generated at a time and* none can be generated if a previously generated VME interrupt has not been* acknowledged, i.e., if no VME bus IACK cycle has completed.** RETURNS: OK, or ERROR if <level> or <vector> are out of range or if an* interrupt is already in progress.** SEE ALSO: sysBusIntAck()*/STATUS sysBusIntGen ( int level, /* interrupt level to generate */ int vector /* interrupt vector for interrupt */ ) { volatile ULONG enReg; volatile ULONG mapReg; volatile ULONG intReg; volatile ULONG statidReg; int lockKey; /* Validate interrupt level */ if (level < 1 || level > 7 || vector > 255 || vector < 2) return (ERROR); if (pciToVmeDev == UNIVERSE_I) { /* lock interrupts so there will be no interference */ EIEIO_SYNC; lockKey = intLock (); /* Ensure bus interrupt is not already asserted */ UNIV_IN_LONG(UNIVERSE_VINT_STAT, &intReg); if (intReg & VINT_STAT_SW_INT) { intUnlock (lockKey); return (ERROR); } /* map VME int level to SW_INT */ UNIV_IN_LONG(UNIVERSE_VINT_MAP1, &mapReg); mapReg &= ~VINT_MAP1_SW_INT_MASK; mapReg |= level << 16; UNIV_OUT_LONG(UNIVERSE_VINT_MAP1, mapReg); /* Clear bit before setting it */ UNIV_IN_LONG(UNIVERSE_VINT_EN, &enReg); enReg &= ~(VINT_EN_SW_INT); UNIV_OUT_LONG(UNIVERSE_VINT_EN, enReg); /* clear SW_INT bit */ /* store vector # (only 7 most significant bits accepted by Universe) */ UNIV_OUT_LONG(UNIVERSE_STATID, ((vector << 24) | STATID_MASK)); /* generate int on VME bus by setting the SW_INT bit */ enReg |= (VINT_EN_SW_INT); UNIV_OUT_LONG(UNIVERSE_VINT_EN, enReg); /* set SW_INT bit */ /* unlock the interrupt */ intUnlock (lockKey); EIEIO_SYNC; } else { /* pciToVmeDev == UNIVERSE_II */ /* lock interrupts so there will be no interference */ CPU_INT_LOCK(&lockKey); /* Ensure bus interrupt is not already asserted */ UNIV_IN_LONG(UNIVERSE_VINT_STAT, &intReg); if (intReg & ((1 << level) << 24)) { CPU_INT_UNLOCK(lockKey); return (ERROR); } /* * Clear Software Interrupt bit before setting it * It needs a 0 to 1 transition to generate an interrupt */ UNIV_IN_LONG(UNIVERSE_VINT_EN, &enReg); enReg &= ~((1 << level) << 24); UNIV_OUT_LONG(UNIVERSE_VINT_EN, enReg); /* * store vector number, wiping out LSB of vector number * This implies that only even number vectors should be used * (Universe FEATURE ?) */ UNIV_IN_LONG(UNIVERSE_STATID, &statidReg); vector >>= 1; statidReg = (statidReg & STATID_MASK) | (vector << 25); UNIV_OUT_LONG(UNIVERSE_STATID, statidReg); /* Generate a SW interrupt on the VMEbus at the requested level */ UNIV_IN_LONG(UNIVERSE_VINT_EN, &enReg); enReg |= ((1 << level) << 24); UNIV_OUT_LONG(UNIVERSE_VINT_EN, enReg); /* unlock the interrupt */ CPU_INT_UNLOCK(lockKey); } return (OK); }/********************************************************************************* sysUnivIntEnable - enable Universe-supported interrupt(s)** This routine enables the specified type(s) of interrupt supported by the* Universe VME-to-PCI bridge.** RETURNS: OK, or ERROR if invalid interrupt type(s).** SEE ALSO: sysUnivIntDisable()**/STATUS sysUnivIntEnable ( int univIntType /* interrupt type */ ) { /* make sure the interrupt type is valid */ if ((univIntType & UNIVERSE_INT_MASK) == 0 || (univIntType & UNIVERSE_RESERVED_INT) != 0 ) return(ERROR); /* clear any pending intr. for the type */ UNIV_OUT_LONG(UNIVERSE_LINT_STAT, univIntType); /* enable the interrupt */ sysUnivIntsEnabled |= univIntType; UNIV_OUT_LONG(UNIVERSE_LINT_EN, sysUnivIntsEnabled); /* map the interrupt. Currently all VME ints are mapped to LINT#0 */ UNIV_OUT_LONG(UNIVERSE_LINT_MAP1, 0); return (OK); }/********************************************************************************* sysUnivIntDisable - disable Universe-supported interrupt(s)** This routine disables the specified type(s) of interrupt supported by the * Universe VME-to-PCI bridge.** RETURNS: OK, or ERROR if invalid interrupt type(s).** SEE ALSO: sysUnivIntEnable()**/STATUS sysUnivIntDisable ( int univIntType /* interrupt type */ ) { /* make sure the interrupt type is valid */ if ((univIntType & UNIVERSE_INT_MASK) == 0 || (univIntType & UNIVERSE_RESERVED_INT) != 0 ) return (ERROR); /* disable the interrupt */ sysUnivIntsEnabled &= ~univIntType; UNIV_OUT_LONG(UNIVERSE_LINT_EN, sysUnivIntsEnabled); /* clear any pending intr. for the type */ UNIV_OUT_LONG(UNIVERSE_LINT_STAT, univIntType); return (OK); }/********************************************************************************* sysUnivIntLevelSet - set a Universe-supported interrupt level** This routine disables all interrupts supported by the Universe at and below* the specified level. The lowest level is 0, the highest is 15. The* priority mapping is:* .CS* 0 no interrupts masked* 1 UNIVERSE_VOWN_INT* 2 VMEBUS_LVL1* 3 VMEBUS_LVL2* 4 VMEBUS_LVL3* 5 VMEBUS_LVL4* 6 VMEBUS_LVL5* 7 VMEBUS_LVL6* 8 VMEBUS_LVL7* 9 UNIVERSE_DMA_INT* 10 UNIVERSE_LERR_INT* 11 UNIVERSE_VERR_INT* 12 UNIVERSE_VME_SW_IACK_INT* 13 UNIVERSE_PCI_SW_INT* 14 UNIVERSE_SYSFAIL_INT* 15 UNIVERSE_ACFAIL_INT* .CE** If the level specified is -1, the level is not changed, just the current* level is returned.** RETURNS: previous interrupt level.** SEE ALSO: sysUnivIntDisable(), sysUnivIntEnable()*/int sysUnivIntLevelSet ( int univIntLvl /* Universe interrupt level */ ) { int intLvl; int key; /* Just return current level if so requested */ if (univIntLvl == -1) return (sysUnivIntLevel); /* Lock out interrupts during level change */ CPU_INT_LOCK(&key); /* disable the interrupt levels at and below the current level */ intLvl = univIntTable[univIntLvl].intMask; intLvl &= sysUnivIntsEnabled; UNIV_OUT_LONG(UNIVERSE_LINT_EN, intLvl); /* save current level for return */ intLvl = sysUnivIntLevel; /* set new mask */ sysUnivIntLevel = univIntLvl; /* Unlock interrupts */ CPU_INT_UNLOCK(key); /* return previous mask */ return (intLvl); }/******************************************************************************** sysUnivIntConnect - connect an interrupt handler for an interrupt type** This routine connects an interrupt handler for a specified interrupt type * to the system vector table of the Universe VME-to-PCI bridge.** RETURNS: OK, or ERROR if any argument is invalid or memory cannot be* allocated.*/STATUS sysUnivIntConnect ( int univIntType, /* the interrupt type to connect with */ VOIDFUNCPTR routine, /* routine to be called */ int parameter /* parameter to be passed to routine */ ) { int univVecNum = 0; /* make sure the interrupt type is valid */ if ((univIntType & UNIVERSE_INT_MASK) == 0) return (ERROR); /* determine the vector number for the interrupt */ switch(univIntType) { case UNIVERSE_DMA_INT: univVecNum = UNIV_DMA_INT_VEC; break; case UNIVERSE_LERR_INT: univVecNum = UNIV_LERR_INT_VEC; break; case UNIVERSE_VERR_INT: univVecNum = UNIV_VERR_INT_VEC; break; case UNIVERSE_SYSFAIL_INT: univVecNum = UNIV_SYSFAIL_INT_VEC; break; case UNIVERSE_ACFAIL_INT: univVecNum = UNIV_ACFAIL_INT_VEC; break; case UNIVERSE_PCI_SW_INT: univVecNum = UNIV_PCI_SW_INT_VEC; break; case UNIVERSE_VME_SW_IACK_INT: univVecNum = UNIV_VME_SW_IACK_INT_VEC; break; case UNIVERSE_VOWN_INT: univVecNum = UNIV_VOWN_INT_VEC; break; default: /* doesn't match one of the intr. types, so return an error */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -