sysEpic.c
上传用户:dqzhongke1
上传日期:2022-06-26
资源大小:667k
文件大小:48k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* sysEpic.c - Driver for Embedded Programmable Interrupt Controller */
  2. /*
  3.  * Copyright (c) 2005-2006 Wind River Systems, Inc.
  4.  *
  5.  * The right to copy, distribute, modify, or otherwise make use
  6.  * of this software may be licensed only pursuant to the terms
  7.  * of an applicable Wind River license agreement.
  8.  */
  9. /*
  10. modification history
  11. --------------------
  12. 01b,27jan06,dtr  Tidyup and minor changes.
  13. 01a,08oct05,dtr  Created based on cds85xx/01h.
  14. */
  15. /*
  16. DESCRIPTION
  17. This module implements the Embedded Programmable Interrupt Controller (EPIC)
  18. driver for the MPC8548.
  19. The EPIC is an integrated interrupt controller in the 8548 which
  20. provides following major capabilities:
  21.   Support for twelve external interrupt sources and thirty-two internal
  22.   interrupt sources
  23.   Support for connection of external interrupt controller device e.g. 8259
  24.   like as implemented on a WinBond chip
  25.      
  26.   12 external interrupt sources
  27.   32 internal interrupt sources
  28.   16 programmable interrupt priority levels
  29.   Fully-nested interrupt delivery
  30.   Spurious vector generation
  31.   Route to critical interrupt destinations
  32.   Route to external pin
  33.   Configurable sense and polarity at initialization and runtime
  34. The current implementation of this EPIC controller does not support
  35. the following features or mode of operations:
  36.   PIC global timers
  37.   Inter-processor interrupts
  38.   Messaging interrupts
  39. EPIC features are customized by writing into general control registers
  40. or into interrupt level specific registers (IVPRs).
  41. This driver allows a basic interface to the EPIC such as initializing it,
  42. setting interrupt vectors, priorities, level/edge sense and interrupt
  43. polarities, as well as enabling and disabling specific interrupts.
  44. This driver implements a complete interrupt architecture system, complete
  45. with vector table.
  46. Since interrupt vectors can be shared, this driver does provide for
  47. overloading of interrupt routines (i.e. there is
  48. a list of interrupt routines for each interrupt vector (level)).  To service
  49. a vector requires that all connected interrupt routines be called in order
  50. of their connection.
  51. The following diagram shows an example of how interrupts can
  52. be configured in this system.
  53.     EPIC Vector table
  54. 0  |-------|  <-- external INT0 starts
  55.    |-------|
  56.    |-------|------------------------------+
  57.     ....                                  |
  58.    |-------|                              |
  59.    |-------|                              |
  60. 12 |-------| <-- internal INT0 starts     |   (EPIC_MAX_EXT_IRQS) = 12
  61.    |-------|                              |
  62.    |-------|                              |
  63.     ....                                  |
  64.    |-------|                              |
  65.    |-------|                              |
  66. 44 |-------| <-- global timer INT0 starts |   (EPIC_MAX_EXT_IRQS + 
  67.    |-------|                              |    EPIC_MAX_IN_IRQS) = 44
  68.    |-------|                              |
  69.    |-------|                              |
  70. 48 |-------| <-- message INT0 starts      |   (EPIC_MAX_EXT_IRQS + 
  71.    |-------|                              |    EPIC_MAX_IN_IRQS + 
  72.    |-------|                              |    EPIC_MAX_GT_IRQS) = 48
  73.    |-------|                              |
  74. 52 |-------| <-- IPI INT0 starts          |   (EPIC_MAX_EXT_IRQS + 
  75.    |-------|                              |    EPIC_MAX_IN_IRQS + 
  76.    |-------|                              |    EPIC_MAX_GT_IRQS + 
  77. 55 |-------|                              |    EPIC_MAX_MSG_IRQS) = 52
  78. 56 |-------|<-----------------------------+   sysVectorIRQ0 = 56 
  79.     ....         WinBond int handler      |   = 52 + EPIC_MAX_IPI_IRQS
  80.    |-------|                              +-------------+
  81.    |-------|                                            |
  82.    |-------|                                 PCI slot 3 int handler
  83.    |-------|
  84.    |-------|<----- Cascaded 8259s
  85.    |-------|
  86.    |-------|
  87.     ....
  88.    |-------|
  89.    |-------|
  90.    |-------|
  91.    |-------|
  92. 256|-------|
  93. The driver is designed to put external interrupts at the beginning of the
  94. vector table.  As a result, devices that route their interrupt to the EPIC
  95. on the MPC8540 does not need to translate the vector number.  Therefore,
  96. the macros IVEC_TO_INUM(x) and INUM_TO_IVEC(x) are not necessary.  For
  97. some existing drivers, it may be necessary to use the following defines:
  98.   #undef  INUM_TO_IVEC
  99.   #define INUM_TO_IVEC(x) (x)
  100.   #undef  IVEC_TO_INUM
  101.   #define IVEC_TO_INUM(x) (x)
  102. If there are other devices in the system capable of generating their own
  103. vectors then we presume that an appropriate interrupt handler is created
  104. and attached to the vector associated with the correct IRQ number.  That
  105. interrupt handler would get a new vector directly from the device and then
  106. call all of the handlers attached to that new vector.  Vector information is
  107. stored in a linked list of INT_HANDLER_DESC structures. The sysIntTbl array
  108. contains a pointer to the first entry for each vector.
  109. INITIALIZATION
  110. This driver is initialized from the BSP, usually as part of sysHwInit().
  111. The first routine to be called is sysEpicInit(). The routine resets the
  112. global configuration register and resets the epic registers to default
  113. values.
  114. The second routine to be called is sysEpicIntrInit().  This routine takes no
  115. arguments. This routine allocates the vector table and initializes the
  116. chips to a default state.  All individual interrupt sources are disabled.
  117. Each has to be individually enabled by intEnable() before it will be
  118. unmasked and allowed to generate an interrupt.
  119. CRITICAL INTERRUPT
  120. To enable the EPIC to handle also critical interrupt, or if a normal
  121. interrupt is to be rerouted to the critical input pin, INCLUDE_EPIC_CRT_INTR
  122. should be defined.  e.g. Define the following in config.h:
  123.   #define INCLUDE_EPIC_CRT_INTR     /@ include critical interrupt support @/
  124. The critical interrupt handler uses information from the summary registers
  125. CISR0 and CISR1.  The EPIC does not manage critical interrupts and hence
  126. Iack or EOI do not apply.  It was seen that the summary registers go
  127. through a transient state before settling on the result.  This causes
  128. spurious interrupts to be generated, and the vectors being called.
  129. A typical behavior is the printout of "uninitialized PIC interrupt
  130. vector 0xXX".  This is observed only when at least one source has been
  131. routed to critical pin.
  132. CUSTOMIZING THIS DRIVER
  133. The BSP can change the default polarity and sensitivity for the external
  134. interrupt and the internal interrupt independently.  They are:
  135.   EPIC_EX_DFT_SENSE /@ default to EPIC_SENSE_LVL @/
  136.   EPIC_EX_DFT_POLAR     /@ default to EPIC_INT_ACT_HIGH @/
  137.   EPIC_IN_DFT_POLAR     /@ default to EPIC_INT_ACT_HIGH @/
  138. If any of the above is defined before the inclusion of sysEpic.h, such as
  139. in config.h, the default will be overridden.  The available options are:
  140.   EPIC_EX_DFT_SENSE     EPIC_SENSE_LVL, EPIC_SENSE_EDG
  141.   EPIC_xx_DFT_POLAR     EPIC_INT_ACT_LOW, EPIC_INT_ACT_HIGH /@if level-sense @/
  142.                         EPIC_INT_EDG_NEG, EPIC_INT_EDG_POS  /@if edge-sense @/
  143. The macros CPU_INT_LOCK() and CPU_INT_UNLOCK provide the access
  144. to the CPU level interrupt lock/unlock routines.  We presume that there
  145. is a single interrupt line to the CPU.  By default these macros call
  146. intLock() and intUnlock() respectively.
  147. INCLUDE FILES:
  148. */
  149. /* includes */
  150. #include <vxWorks.h>
  151. #include "config.h"
  152. #include "sysEpic.h"
  153. #include <sysLib.h>
  154. #include <stdio.h>
  155. #include <string.h>
  156. #ifdef INCLUDE_WINDVIEW
  157. #include <private/eventP.h>
  158. #endif
  159. /* defines */
  160. #ifndef CPU_INT_LOCK
  161. #   define CPU_INT_LOCK(pData) 
  162. (*pData = intLock ())
  163. #endif
  164. #ifndef CPU_INT_UNLOCK
  165. #   define CPU_INT_UNLOCK(data) 
  166. (intUnlock (data))
  167. #endif
  168. /* externs */
  169. IMPORT STATUS  excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
  170. IMPORT STATUS  excIntCrtConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
  171. /* get the interrupt hook routines  prototypes*/
  172. IMPORT STATUS (*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);
  173. IMPORT int (*_func_intEnableRtn)  (int);
  174. IMPORT int (*_func_intdisableRtn) (int);
  175. /* globals */
  176. INT_HANDLER_DESC * sysIntTbl [INTERRUPT_TABLESIZE]; /* system interrupt tbl */
  177. /* locals */
  178. /* forward declarations */
  179. LOCAL int epicIntEnable (ULONG srcAddr);
  180. LOCAL int epicIntDisable (ULONG srcAddr);
  181. LOCAL int epicVecOptionsSet (ULONG srcAddr, UINT32 mask, UINT32 options);
  182. LOCAL UINT32 epicVecOptionsGet (ULONG srcAddr);
  183. LOCAL void sysEpicIntHandlerExec (int vector);
  184. LOCAL void  sysEpicIntHandler (void);
  185. #ifdef INCLUDE_EPIC_CRT_INTR
  186. LOCAL void  sysEpicCrtIntHandler (void);
  187. LOCAL int epicCrtIntSet (ULONG srcAddr);
  188. LOCAL int epicCrtIntUnset (ULONG srcAddr);
  189. LOCAL int epicCrtIntGet (ULONG srcAddr);
  190. #endif  /* INCLUDE_EPIC_CRT_INTR */
  191. LOCAL int       epicSrcAddrCheck (ULONG srcAddr);
  192. /*******************************************************************************
  193. *
  194. * sysEpicInit - initialize the epic controller
  195. *
  196. * This routine resets the global Configuration Register, thus it:
  197. *  -  disables all interrupts
  198. *  -  sets epic registers to reset values
  199. *
  200. * It then sets the EPIC operation mode to Mixed Mode (vs. Pass Through
  201. * mode). At this point only mixed mode is supported which means the EPIC
  202. * is not configured for the pass through mode.
  203. *
  204. * Only direct interrupt sources is supported by the PIC.  Serial 
  205. * stype interrupt is not available.
  206. *
  207. * NOMANUAL
  208. * RETURNS: N/A
  209. *
  210. * ERRNO: N/A
  211. */    
  212. void sysEpicInit (void)
  213.     {
  214.     ULONG  gcrVal;
  215.     int  irq;
  216.     gcrVal = sysEpicRegRead (EPIC_GLOBAL_REG);
  217.     gcrVal |= (EPIC_GCR_RESET);
  218.     
  219.     sysEpicRegWrite (EPIC_GLOBAL_REG, gcrVal);
  220.     /* wait for the reset sequence to be completed */
  221.     
  222.     while (sysEpicRegRead (EPIC_GLOBAL_REG) & EPIC_GCR_RESET)
  223.         {
  224.         ; /* do nothing */
  225.         }
  226.     gcrVal = sysEpicRegRead (EPIC_GLOBAL_REG);
  227.     gcrVal |= (EPIC_GCR_MODE_MIXED); /* configure for mixed mode */
  228.     
  229.     sysEpicRegWrite (EPIC_GLOBAL_REG, gcrVal);
  230.     /* Clear all pending interrupt */
  231.     while (((USHORT) epicIntAck()) != (USHORT) 0xffff)
  232.         {
  233.         /* do nothing */
  234. }
  235.     /* init all EIVPRs to sense = 1, polarity = defined, vec = 0, prio = 0 */
  236.     for (irq = 0; irq < EPIC_MAX_EXT_IRQS; irq++)
  237.         {
  238.         epicIntDisable (EPIC_EX_VEC_REG(irq));
  239.         epicIntSourceSet (EPIC_EX_VEC_REG(irq),
  240.                           EPIC_EX_DFT_POLAR, EPIC_EX_DFT_SENSE, 0x0, 0x0);
  241.         }
  242.     /* init all IIVPRs to polarity = defined, vec = 0, prio = 0 */
  243.     for (irq = 0; irq < EPIC_MAX_IN_IRQS; irq++)
  244.         {
  245.         epicIntDisable (EPIC_IN_VEC_REG(irq));
  246.         epicIntSourceSet (EPIC_IN_VEC_REG(irq),
  247.                           EPIC_IN_DFT_POLAR, 0x0, 0x0, 0x0);
  248.         }
  249.     /* init all GTVPRs to vec = 0, prio = 0 */
  250.     for (irq = 0; irq < EPIC_MAX_GT_IRQS; irq++)
  251.         {
  252.         epicIntDisable (EPIC_GT_VEC_REG(irq));
  253.         epicIntSourceSet (EPIC_GT_VEC_REG(irq),
  254.                           0x0, 0x0, 0x0, 0x0);
  255.         }
  256.     /* init all MIVPRs to vec = 0, prio = 0 */
  257.     for (irq = 0; irq < EPIC_MAX_MSG_IRQS; irq++)
  258.         {
  259.         epicIntDisable (EPIC_MSG_VEC_REG(irq));
  260.         epicIntSourceSet (EPIC_MSG_VEC_REG(irq),
  261.                           0x0, 0x0, 0x0, 0x0);
  262.         }
  263.     /* disable IPIs */
  264.     for (irq = 0; irq < EPIC_MAX_IPI_IRQS; irq++)
  265.         {
  266.         epicIntDisable (EPIC_IPI_VEC_REG(irq));
  267.         epicIntSourceSet (EPIC_IPI_VEC_REG(irq),
  268.                           0x0, 0x0, 0x0, 0x0);
  269.         }
  270.     epicCurTaskPrioSet (EPIC_PRIORITY_MAX); /* set it to highest priority */
  271.     }
  272. /*******************************************************************************
  273. *
  274. * sysEpicIntrInit - initialize the interrupt table
  275. *
  276. * This function initializes the interrupt mechanism of the board.
  277. *
  278. * RETURNS: OK, always.
  279. *
  280. * ERRNO: N/A
  281. */
  282. STATUS  sysEpicIntrInit (void)
  283.     {
  284.     int vector;
  285.     int rc;
  286.     /* initialize the interrupt table */
  287.     for (vector = 0; vector < INTERRUPT_TABLESIZE; vector++)
  288.         {
  289. sysIntTbl [vector] = NULL;
  290.         }
  291.     /*
  292.      * connect the interrupt demultiplexer to the PowerPC external 
  293.      * interrupt exception vector.
  294.      * i. e.  put the address of this interrupt handler in
  295.      * the PowerPC's only external interrupt exception vector
  296.      * which is  _EXC_OFF_INTR = 0x500
  297.      * Also connect critical input pin handler _EXC_OFF_CRTL = 0x100.
  298.      */
  299.     rc = excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysEpicIntHandler);
  300. #ifdef INCLUDE_EPIC_CRT_INTR
  301.     rc = excIntCrtConnect ((VOIDFUNCPTR *) _EXC_OFF_CRTL, sysEpicCrtIntHandler);
  302. #endif  /* INCLUDE_EPIC_CRT_INTR */
  303.     /*  
  304.      * set up the BSP specific interrupt routines
  305.      * Attach the local routines to the VxWorks system calls
  306.      *
  307.      */
  308.     _func_intConnectRtn  =  sysEpicIntConnect;
  309.     _func_intEnableRtn   =  sysEpicIntEnable;
  310.     _func_intDisableRtn  =  sysEpicIntDisable;
  311.     epicCurTaskPrioSet (EPIC_PRIORITY_MIN); /* set it to lowest priority */
  312.     
  313.     return (rc);
  314.     }
  315. /*******************************************************************************
  316. *
  317. * sysEpicIntEnable - enable a EPIC interrupt level
  318. *
  319. * This routine enables a specified EPIC interrupt level.
  320. *
  321. * NOMANUAL
  322. *
  323. * RETURNS: OK, ERROR, or EPIC_INV_INTER_SOURCE.
  324. *
  325. * NOTE: To allow compatibility, sysEpicIntEnable() can be used only for
  326. *       external and internal interrupts, and not GT, MSG, IPI.  It
  327. *       assumes there are more internal IRQs than external.  It also
  328. *       gives priority to external over internal given the same IRQ
  329. *       is valid for both external and internal.
  330. *
  331. * ERRNO: N/A
  332. */
  333. int sysEpicIntEnable
  334.     (
  335.     int vector
  336.     )
  337.     {
  338.     if ((vector < 0)  || (vector >= EPIC_MAX_ALL_IRQS))
  339.         return (ERROR);
  340.     /* enable interrupt on EPIC */
  341.     return epicIntEnable ( epicGetVecRegAdrs (vector) );
  342.     }
  343. /*******************************************************************************
  344. *
  345. * sysEpicIntDisable - disable a EPIC interrupt level
  346. *
  347. * This routine disables a specified EPIC interrupt level.
  348. *
  349. * NOMANUAL
  350. *
  351. * RETURNS: OK, ERROR, or EPIC_INV_INTER_SOURCE.
  352. *
  353. * NOTE: To allow compatibility, sysEpicIntDisable() can be used only for
  354. *       external and internal interrupts, and not GT, MSG, IPI.  It
  355. *       assumes there are more internal IRQs than external.  It also
  356. *       gives priority to external over internal given the same IRQ
  357. *       is valid for both external and internal.
  358. *
  359. * ERRNO: N/A
  360. */
  361. int  sysEpicIntDisable
  362.     (
  363.     int vector
  364.     )
  365.     {
  366.     if ((vector < 0) || (vector >= EPIC_MAX_ALL_IRQS))
  367.         return (ERROR);
  368.     /* disable interrupt on EPIC */
  369.     return epicIntDisable ( epicGetVecRegAdrs (vector) );
  370.     }
  371. /*******************************************************************************
  372. *
  373. * epicVecOptionsSet - set options for a vector
  374. *
  375. * <srcAddr> is the address offset of the Vector Priority register
  376. * <mask> is one of EPIC_OPT_EN_MSK, EPIC_OPT_POLAR_MSK, EPIC_OPT_SENSE_MSK,
  377. *                  EPIC_OPT_PRI_MSK, EPIC_OPT_EXPIN_MSK, EPIC_OPT_CRIT_MSK
  378. * <options> is one of 
  379. *   EPIC_OPT_EN_Y              interrupt enabled
  380. *   EPIC_OPT_EN_N              interrupt disabled
  381. *   EPIC_OPT_POLAR_ACT_LOW     polarity is active low
  382. *   EPIC_OPT_POLAR_ACT_HIGH    polarity is active high
  383. *   EPIC_OPT_POLAR_EDG_NEG     polarity is negative edge triggered
  384. *   EPIC_OPT_POLAR_EDG_POS     polarity is positive edge triggered
  385. *   EPIC_OPT_SENSE_EDG         edge sensitive
  386. *   EPIC_OPT_SENSE_LVL         level sensitive
  387. *   EPIC_OPT_PRI_VALUE(p)      set priority to p [0..15]
  388. *   EPIC_OPT_EXPIN_OFF         external pin off
  389. *   EPIC_OPT_EXPIN_ON          external pin on
  390. *   EPIC_OPT_CRIT_OFF          route to critical pin off
  391. *   EPIC_OPT_CRIT_ON           route to critical pin on
  392. *
  393. * NOMANUAL
  394. *
  395. * RETURNS: OK or an error code, can be one of the following:
  396. *          OK
  397. *          ERROR
  398. *          EPIC_VEC_OPTION_INV
  399. *          EPIC_INV_INTER_SOURCE
  400. *          EPIC_VEC_OPTION_NA
  401. *          EPIC_VEC_HAS_NO_IDR
  402. *          EPIC_INTER_IN_SERVICE
  403. *
  404. * ERRNO: N/A
  405. */
  406. LOCAL int epicVecOptionsSet
  407.     (
  408.     ULONG       srcAddr,
  409.     UINT32  mask,
  410.     UINT32  options
  411.     )
  412.     {
  413.     ULONG       vprVal;
  414.     ULONG       idrVal;
  415.     ULONG       vprFlag;
  416.     ULONG       idrFlag;
  417.     int         errCode;
  418.     int         idrOffset = 0;              /* offset of IDR from VPR */
  419.     if ((mask & ((0x3f30 << 16) | (0x3fff))) != 0)
  420.         return (EPIC_VEC_OPTION_INV);
  421.     errCode = epicSrcAddrCheck (srcAddr);
  422.     if (errCode == EPIC_INV_INTER_SOURCE)
  423.         {
  424.         return (errCode);
  425.         }
  426.     vprFlag = mask & 0xffff0000;            /* upper sets upper VPR */
  427.     idrFlag = (mask & 0x0000ffff) << 16;    /* lower sets upper IDR */
  428.     switch (errCode)
  429.         {
  430.         case EPIC_EX_INTERRUPT:
  431.             idrOffset = EPIC_EX_DEST_REG_VECREGOFF;
  432.         break;
  433.         case EPIC_IN_INTERRUPT:
  434.             idrOffset = EPIC_IN_DEST_REG_VECREGOFF;
  435.             if ((vprFlag & EPIC_OPT_SENSE_MSK) != 0)
  436.                 return (EPIC_VEC_OPTION_NA);
  437.         break;
  438.         case EPIC_GT_INTERRUPT:
  439.             if (idrFlag != 0)
  440.                 return (EPIC_VEC_HAS_NO_IDR);
  441.         break;
  442.         case EPIC_MSG_INTERRUPT:
  443.             idrOffset = EPIC_MSG_DEST_REG_VECREGOFF;
  444.             if ((vprFlag & (EPIC_OPT_POLAR_MSK | EPIC_OPT_SENSE_MSK)) != 0)
  445.                 return (EPIC_VEC_OPTION_NA);
  446.         break;
  447.         case EPIC_IPI_INTERRUPT:
  448.             if (idrFlag != 0)
  449.                 return (EPIC_VEC_HAS_NO_IDR);
  450.         break;
  451.         default:
  452.             return (ERROR);
  453.         }
  454.     vprVal = sysEpicRegRead (srcAddr);
  455.     if ((vprVal & EPIC_EIVPR_INTR_ACTIVE) != 0)
  456.         return (EPIC_INTER_IN_SERVICE);
  457.     if (vprFlag != 0)
  458.         {
  459.         vprVal &= ~(vprFlag);
  460.         vprVal |= (options & 0xffff0000);
  461.         sysEpicRegWrite (srcAddr, vprVal);
  462.         }
  463.     if ((idrFlag != 0) && (idrOffset != 0))
  464.         {
  465.         idrVal = sysEpicRegRead (srcAddr + idrOffset);
  466.         idrVal &= ~(idrFlag);
  467.         idrVal |= (options & 0xffff) << 16;
  468.         sysEpicRegWrite (srcAddr + idrOffset, idrVal);
  469.         }
  470.     return OK;
  471.     }
  472. /*******************************************************************************
  473. *
  474. * epicVecOptionsGet - get options for a vector
  475. *
  476. * <srcAddr> is the address offset of the Vector Priority register
  477. *
  478. * Use one or more of the following masks to extract the returned value:
  479. *   EPIC_OPT_EN_MSK
  480. *   EPIC_OPT_POLAR_MSK
  481. *   EPIC_OPT_SENSE_MSK
  482. *   EPIC_OPT_PRI_MSK
  483. *   EPIC_OPT_EXPIN_MSK
  484. *   EPIC_OPT_CRIT_MSK
  485. *
  486. * NOMANUAL
  487. *
  488. * RETURNS: OK, ERROR, or EPIC_INV_INTER_SOURCE
  489. *
  490. * ERRNO: N/A
  491. */
  492. LOCAL UINT32 epicVecOptionsGet
  493.     (
  494.     ULONG       srcAddr
  495.     )
  496.     {
  497.     ULONG       vprVal;
  498.     ULONG       idrVal;
  499.     int         errCode;
  500.     int         idrOffset = 0;              /* offset of IDR from VPR */
  501.     errCode = epicSrcAddrCheck (srcAddr);
  502.     if (errCode == EPIC_INV_INTER_SOURCE)
  503.         {
  504.         return (errCode);
  505.         }
  506.     switch (errCode)
  507.         {
  508.         case EPIC_EX_INTERRUPT:
  509.             idrOffset = EPIC_EX_DEST_REG_VECREGOFF;
  510.         break;
  511.         case EPIC_IN_INTERRUPT:
  512.             idrOffset = EPIC_IN_DEST_REG_VECREGOFF;
  513.         break;
  514.         case EPIC_GT_INTERRUPT:
  515.         break;
  516.         case EPIC_MSG_INTERRUPT:
  517.             idrOffset = EPIC_MSG_DEST_REG_VECREGOFF;
  518.         break;
  519.         case EPIC_IPI_INTERRUPT:
  520.         break;
  521.         default:
  522.             return ((UINT32) ERROR);
  523.         }
  524.     vprVal = sysEpicRegRead (srcAddr);
  525.     if (idrOffset != 0)
  526.         idrVal = sysEpicRegRead (srcAddr + idrOffset);
  527.     else
  528.         idrVal = 0;
  529.     return ((vprVal & 0xffff0000) | (idrVal >> 16));
  530.     }
  531. /*
  532. *
  533. * sysEpicVecOptionsSet - change options for a vector
  534. *
  535. */
  536. int sysEpicVecOptionsSet
  537.     (
  538.     int    vector,
  539.     UINT32 mask,
  540.     UINT32 options
  541.     )
  542.     {
  543.     if ((vector < 0) || (vector >= EPIC_MAX_ALL_IRQS))
  544.         return (ERROR);
  545.     /* set vector options on EPIC */
  546.     return epicVecOptionsSet ( epicGetVecRegAdrs (vector), mask, options );
  547.     }
  548. /*
  549. *
  550. * sysEpicVecOptionsGet - obtain options for a vector
  551. *
  552. */
  553. UINT32 sysEpicVecOptionsGet
  554.     (
  555.     int vector
  556.     )
  557.     {
  558.     if ((vector < 0) || (vector >= EPIC_MAX_ALL_IRQS))
  559.         return ((UINT32) ERROR);
  560.     /* get vector options on EPIC */
  561.     return epicVecOptionsGet ( epicGetVecRegAdrs (vector) );
  562.     }
  563. /*******************************************************************************
  564. *
  565. * sysEpicIntConnect - connect an interrupt handler to the system vector table
  566. *
  567. * This function connects an interrupt handler to the system vector table.
  568. *
  569. * RETURNS: OK or ERROR.
  570. *
  571. * ERRNO: N/A
  572. */
  573. STATUS sysEpicIntConnect
  574.     (
  575.     VOIDFUNCPTR *  vector, /* interrupt vector to attach */
  576.     VOIDFUNCPTR routine, /* routine to be called */
  577.     int parameter /* parameter to be passed to routine */
  578.     )
  579.     {
  580.     INT_HANDLER_DESC * pNewHandler;
  581.     INT_HANDLER_DESC * pCurrHandler;
  582.     int intVal;
  583.     BOOL sharing = FALSE;
  584.     if (((int)vector < 0)  || ((int) vector >= INTERRUPT_TABLESIZE)) 
  585. {
  586.         return (ERROR);   /*  out of range  */
  587. }
  588.     /* create a new interrupt handler */
  589.     pNewHandler = malloc (sizeof (INT_HANDLER_DESC));
  590.     /* check if the memory allocation succeed */
  591.     if (pNewHandler == NULL)
  592. return (ERROR);
  593.     /*  initialize the new handler  */
  594.     pNewHandler->vec = routine;
  595.     pNewHandler->arg = parameter;
  596.     pNewHandler->next = NULL;
  597.     /* install the handler in the system interrupt table  */
  598.     intVal = intLock (); /* lock interrupts to prevent races */
  599.     if (sysIntTbl [(int) vector] == NULL)
  600. {
  601.         sysIntTbl [(int) vector] = pNewHandler;  /* single int. handler case */
  602. }
  603.     else
  604. {
  605.         pCurrHandler = sysIntTbl[(int) vector];/* multiple int. handler case */
  606.         while (pCurrHandler->next != NULL)
  607.             {
  608.             pCurrHandler = pCurrHandler->next;
  609.             }
  610.         
  611.         pCurrHandler->next = pNewHandler;
  612.         sharing = TRUE;
  613. }
  614.     if ((int)vector >= 0 && (int)vector < EPIC_MAX_ALL_IRQS)
  615.         {
  616.         /* EPIC IRQ set EPIC registers */
  617.         if (!sharing)
  618.             {
  619.             if ((int) vector < EPIC_VEC_IN_IRQ0)        /* EX type */
  620.                 {
  621.                 epicIntSourceSet ( epicGetVecRegAdrs ((int) vector),
  622.                                EPIC_EX_DFT_POLAR, EPIC_EX_DFT_SENSE,
  623.                                EPIC_PRIORITY_DEFAULT, (int) vector);
  624.                 }
  625.             else if ((int) vector < EPIC_VEC_GT_IRQ0)   /* IN type */
  626.                 {
  627.                 epicIntSourceSet ( epicGetVecRegAdrs ((int) vector),
  628.                                EPIC_IN_DFT_POLAR, 0x0,
  629.                                EPIC_PRIORITY_DEFAULT, (int) vector);
  630.                 }
  631.             else                                        /* other types */
  632.                 {
  633.                 epicIntSourceSet ( epicGetVecRegAdrs ((int) vector),
  634.                                0x0, 0x0,
  635.                                EPIC_PRIORITY_DEFAULT, (int) vector);
  636.                 }
  637.             }
  638.         }
  639.     intUnlock (intVal);
  640.     return (OK);
  641.     }
  642. /*******************************************************************************
  643. *
  644. * sysEpicIntHandlerExec  - execute the handlers for a given vector
  645. * This routine executes all the handlers chained to a given vector.
  646. * If a vector has no handlers attached to it, a logMsg is generated.
  647. *
  648. * NOMANUAL
  649. *
  650. * RETURNS: N/A
  651. *
  652. * ERRNO: N/A
  653. */
  654. LOCAL void sysEpicIntHandlerExec
  655.     (
  656.     int vector
  657.     )
  658.     {    
  659.     INT_HANDLER_DESC * pCurrHandler;
  660.     /*  call each respective interrupt handler */
  661.     if ((pCurrHandler = sysIntTbl [vector]) == NULL)
  662.         {
  663. logMsg ("uninitialized PIC interrupt vector 0x%xrn",
  664.                 vector, 0,0,0,0,0);
  665.         }
  666.     else
  667.         {
  668. /* call Each respective chained interrupt handler  */
  669. while (pCurrHandler != NULL)
  670.             {
  671.        (*pCurrHandler->vec) (pCurrHandler->arg);
  672.     pCurrHandler = pCurrHandler->next;
  673.             }
  674.         }
  675.     }
  676. /*******************************************************************************
  677. *
  678. * sysEpicIntHandler - handles the EPIC interrupts to the CPU
  679. *
  680. * This routine handles interrupts originating from the embedded interrupt
  681. * controller on the MPC8540 PowerPC processor.
  682. * This handler is entered from the 0x500 exception.
  683. *
  684. * This routine is entered with CPU external interrupts enables.
  685. *
  686. * Since the EPIC is the primary interrupt controller this driver
  687. * first initiates an Epic acknowledge call and reads the vector
  688. * put out by the EPIC. Subsequent vectors have to be obtained if
  689. * an external interrupt controller is connected to one of the
  690. * epic handlers. 
  691. *
  692. * This routine then processes the interrupt by calling all the interrupt
  693. * service routines chained to the vector.
  694. *
  695. * Finally, this routine re-arms the interrupt at the PIC by performing an 
  696. * PIC EOI for both the EPIC and the 8259s.
  697. *
  698. * RETURNS:  N/A
  699. *
  700. * ERRNO: N/A
  701. */
  702. LOCAL void  sysEpicIntHandler (void)
  703.     {
  704.     int epicIntVec;
  705.     int oldkey;
  706.     epicIntVec = epicIntAck (); /* clear int, return the vec for highest IRQ */
  707. #ifdef INCLUDE_WINDVIEW
  708.     WV_EVT_INT_ENT (epicIntVec);
  709. #endif 
  710.     /* loop till all interrupts are cleared */
  711.     while (epicIntVec != 0xffff)
  712.         {
  713.         /* Allow external interrupts to the CPU. */
  714. CPU_INT_UNLOCK (_PPC_MSR_EE);
  715.         sysEpicIntHandlerExec (epicIntVec);
  716. CPU_INT_LOCK (&oldkey);
  717.         /*
  718.          * Disable External Interrupts
  719.          * External Interrupts will be re-enabled in the kernel's wrapper
  720.          * of this Interrupt.
  721.          */
  722.         WRS_ASM ("sync");
  723.         epicEOI(); /* signal end of interrupt on EPIC */
  724.         WRS_ASM ("sync");
  725.         epicIntVec = epicIntAck ();
  726.         } /* while */
  727.     }
  728. #ifdef INCLUDE_EPIC_CRT_INTR
  729. /*
  730. *
  731. * epicCisr0Get - get critical interrupt summary
  732. *
  733. */
  734. UINT32 epicCisr0Get (void)
  735.     {
  736.     volatile unsigned long val;
  737.     val = *(volatile unsigned long *) (CCSBAR | 0x41330);
  738.     return val;
  739.     }
  740. /*
  741. *
  742. * epicCisr1Get - get critical interrupt summary
  743. *
  744. */
  745. UINT32 epicCisr1Get (void)
  746.     {
  747.     volatile unsigned long val;
  748.     val = *(volatile unsigned long *) (CCSBAR | 0x41340);
  749.     return val;
  750.     }
  751. /*
  752. *
  753. * sysEpicCrtIntHandler
  754. *
  755. */
  756. LOCAL void  sysEpicCrtIntHandler (void)
  757.     {
  758.     int oldkey;
  759.     volatile unsigned long extSumm;
  760.     volatile unsigned long intSumm;
  761.     int i;
  762.     while (((extSumm = (epicCisr0Get() & 0xfff)) != 0) ||
  763.            ((intSumm = epicCisr1Get()) != 0))
  764.         {
  765.         /* service external first */
  766.         for (i = 0; i < 12; i++)
  767.             {
  768.             if (((extSumm >> i) & 0x1) == 0x1)
  769.                 {
  770.                 /* CPU_INT_UNLOCK (_PPC_MSR_CE); */
  771.                 sysEpicIntHandlerExec (11 - i);
  772.                 /* CPU_INT_LOCK (&oldkey); */
  773.                 }
  774.             }
  775.         /* service internal */
  776.         for (i = 0; i < 32; i++)
  777.             {
  778.             if (((intSumm >> i) & 0x1) == 0x1)
  779.                 {
  780.                 /* CPU_INT_UNLOCK (_PPC_MSR_CE); */
  781.                 sysEpicIntHandlerExec (EPIC_VEC_IN_IRQ0 + 31 - i);
  782.                 /* CPU_INT_LOCK (&oldkey); */
  783.                 }
  784.             }
  785.         }
  786.     }
  787. #endif  /* INCLUDE_EPIC_CRT_INTR */
  788. /*******************************************************************************
  789. *
  790. * epicCurTaskPrioSet - set the priority of the current task.
  791. *
  792. * NOTES
  793. *
  794. * epicCurTaskPrioSet sets the priority of the Processor Current Task
  795. * Priority register to the value of the prioNum parameter.  This function
  796. * should be called after sysEpicInit() to lower the priority of the processor
  797. * current task. Note that valid priority values are 0 through 15 (15 being
  798. * the highest priority)
  799. *
  800. * NOMANUAL
  801. * RETURNS: previous priority of the task.
  802. *
  803. * ERRNO: N/A
  804. */
  805. int epicCurTaskPrioSet
  806.     (
  807.     int prioNum
  808.     )
  809.     {
  810.     ULONG oldPrio;
  811.     if ((prioNum < EPIC_PRIORITY_MIN) || (prioNum > EPIC_PRIORITY_MAX))
  812.         {
  813.         return ((int) EPIC_INV_PRIO_ERROR);
  814. }
  815.     oldPrio = sysEpicRegRead (EPIC_CTASK_PRI_REG);
  816.     sysEpicRegWrite (EPIC_CTASK_PRI_REG, prioNum);
  817.     return (oldPrio);
  818.     }
  819. /*******************************************************************************
  820. *
  821. * epicIntEnable - enable an EPIC interrupt, given its IVPR
  822. *
  823. * This function clears the mask bit of an external, an internal or
  824. * a Timer register to enable the interrupt.
  825. *
  826. * <srcAddr> is the address offset of the Vector Priority register  
  827. *
  828. * NOMANUAL
  829. * RETURNS: OK or an error code if the IVPR passed in was invalid.
  830. *
  831. * ERRNO: N/A
  832. */
  833. LOCAL int epicIntEnable
  834.     (
  835.     ULONG  srcAddr
  836.     )
  837.     {
  838.     ULONG  srcVal;
  839.     int  errCode;
  840.   
  841.     errCode = epicSrcAddrCheck (srcAddr);
  842.     if (errCode == EPIC_INV_INTER_SOURCE)
  843.         {
  844.         return (errCode);
  845.         }
  846.     srcVal = sysEpicRegRead (srcAddr);
  847.     switch (errCode)
  848.         {
  849.         case EPIC_EX_INTERRUPT:
  850.             srcVal &= ~(EPIC_EIVPR_INTR_MSK);   /* clear the mask bit */
  851.         break;
  852.         case EPIC_IN_INTERRUPT:
  853.             srcVal &= ~(EPIC_IIVPR_INTR_MSK);   /* clear the mask bit */
  854.         break;
  855.         case EPIC_GT_INTERRUPT:
  856.             srcVal &= ~(EPIC_GTVPR_INTR_MSK);   /* clear the mask bit */
  857.         break;
  858.         case EPIC_MSG_INTERRUPT:
  859.             srcVal &= ~(EPIC_MIVPR_INTR_MSK);   /* clear the mask bit */
  860.         break;
  861.         case EPIC_IPI_INTERRUPT:
  862.             srcVal &= ~(EPIC_IPIVPR_INTR_MSK);  /* clear the mask bit */
  863.         break;
  864.         default:
  865.             return (ERROR);
  866.         }
  867.     sysEpicRegWrite (srcAddr, srcVal);
  868.     return OK;
  869.     }
  870. /*******************************************************************************
  871. *
  872. * epicIntDisable - disable an EPIC interrupt, given its IVPR
  873. *
  874. * This function sets the mask bit of an external, an internal,
  875. * a timer, a message, or an IPI register to disable the interrupt.
  876. * <srcAddr> is the address offset of the Vector Priority register.
  877. *
  878. * NOMANUAL
  879. * RETURNS: OK or an error code if the IVPR passed in was invalid.
  880. *
  881. * ERRNO: N/A
  882. */
  883.                
  884. LOCAL int epicIntDisable
  885.     (
  886.     ULONG  srcAddr
  887.     )
  888.     {
  889.     ULONG  srcVal;
  890.     int  errCode;
  891.   
  892.     errCode = epicSrcAddrCheck (srcAddr);
  893.     if (errCode == EPIC_INV_INTER_SOURCE)
  894.         {
  895.         return (errCode);
  896.         }
  897.     srcVal = sysEpicRegRead (srcAddr);
  898.     switch (errCode)
  899.         {
  900.         case EPIC_EX_INTERRUPT:
  901.             srcVal |= EPIC_EIVPR_INTR_MSK; /* set the mask bit */
  902.         break;
  903.         case EPIC_IN_INTERRUPT:
  904.             srcVal |= EPIC_IIVPR_INTR_MSK; /* set the mask bit */
  905.         break;
  906.         case EPIC_GT_INTERRUPT:
  907.             srcVal |= EPIC_GTVPR_INTR_MSK; /* set the mask bit */
  908.         break;
  909.         case EPIC_MSG_INTERRUPT:
  910.             srcVal |= EPIC_MIVPR_INTR_MSK; /* set the mask bit */
  911.         break;
  912.         case EPIC_IPI_INTERRUPT:
  913.             srcVal |= EPIC_IPIVPR_INTR_MSK; /* set the mask bit */
  914.         break;
  915.         default:
  916.             return (ERROR);
  917.         }
  918.     sysEpicRegWrite (srcAddr, srcVal);
  919.     return OK;
  920.     }
  921. #ifdef INCLUDE_EPIC_CRT_INTR
  922. /*
  923. *
  924. */
  925. LOCAL int epicCrtIntSet
  926.     (
  927.     ULONG  srcAddr
  928.     )
  929.     {
  930.     ULONG  srcVal;
  931.     int  errCode = EPIC_EX_INTERRUPT;    /* same bits for all types */
  932.   
  933.     srcVal = sysEpicRegRead (srcAddr);
  934.     switch (errCode)
  935.         {
  936.         case EPIC_EX_INTERRUPT:
  937.             srcVal |= EPIC_EIDR_CRIT_INT;       /* set critical bit */
  938.         break;
  939.         case EPIC_IN_INTERRUPT:
  940.             srcVal |= EPIC_IIDR_CRIT_INT;       /* set critical bit */
  941.         break;
  942.         case EPIC_GT_INTERRUPT:
  943.             return (ERROR);                     /* not supported */
  944.         break;
  945.         case EPIC_MSG_INTERRUPT:
  946.             srcVal |= EPIC_MIDR_CRIT_INT;       /* set critical bit */
  947.         break;
  948.         case EPIC_IPI_INTERRUPT:
  949.             return (ERROR);                     /* not supported */
  950.         break;
  951.         default:
  952.             return (ERROR);
  953.         }
  954.     sysEpicRegWrite (srcAddr, srcVal);
  955.     return OK;
  956.     }
  957. /*
  958. *
  959. */
  960. LOCAL int epicCrtIntUnset
  961.     (
  962.     ULONG  srcAddr
  963.     )
  964.     {
  965.     ULONG  srcVal;
  966.     int  errCode = EPIC_EX_INTERRUPT;    /* same bits for all types */
  967.   
  968.     srcVal = sysEpicRegRead (srcAddr);
  969.     switch (errCode)
  970.         {
  971.         case EPIC_EX_INTERRUPT:
  972.             srcVal &= ~(EPIC_EIDR_CRIT_INT);    /* set critical bit */
  973.         break;
  974.         case EPIC_IN_INTERRUPT:
  975.             srcVal &= ~(EPIC_IIDR_CRIT_INT);    /* set critical bit */
  976.         break;
  977.         case EPIC_GT_INTERRUPT:
  978.             return (ERROR);                     /* not supported */
  979.         break;
  980.         case EPIC_MSG_INTERRUPT:
  981.             srcVal &= ~(EPIC_MIDR_CRIT_INT);    /* set critical bit */
  982.         break;
  983.         case EPIC_IPI_INTERRUPT:
  984.             return (ERROR);                     /* not supported */
  985.         break;
  986.         default:
  987.             return (ERROR);
  988.         }
  989.     sysEpicRegWrite (srcAddr, srcVal);
  990.     return OK;
  991.     }
  992. /*
  993. *
  994. */
  995. LOCAL int epicCrtIntGet
  996.     (
  997.     ULONG  srcAddr
  998.     )
  999.     {
  1000.     ULONG  srcVal;
  1001.     int  errCode = EPIC_EX_INTERRUPT;    /* same bits for all types */
  1002.   
  1003.     srcVal = sysEpicRegRead (srcAddr);
  1004.     switch (errCode)
  1005.         {
  1006.         case EPIC_EX_INTERRUPT:
  1007.             srcVal = (srcVal >> 30) & 1;
  1008.         break;
  1009.         }
  1010.     return srcVal;
  1011. }
  1012. /*
  1013. *
  1014. */
  1015. int  sysEpicCrtIntSet
  1016.     (
  1017.     int vector
  1018.     )
  1019.     {
  1020.     if ((vector < 0)  || (vector >= EPIC_MAX_ALL_IRQS))
  1021.         return (ERROR);
  1022.     /* enable critical bit on EPIC */
  1023.     return epicCrtIntSet ( epicGetDestRegAdrs (vector) );
  1024.     }
  1025. /*
  1026. *
  1027. */
  1028. int  sysEpicCrtIntUnset
  1029.     (
  1030.     int vector
  1031.     )
  1032.     {
  1033.     if ((vector < 0)  || (vector >= EPIC_MAX_ALL_IRQS))
  1034.         return (ERROR);
  1035.     /* disable critical bit on EPIC */
  1036.     return epicCrtIntUnset ( epicGetDestRegAdrs (vector) );
  1037.     }
  1038. /*
  1039. *
  1040. */
  1041. int  sysEpicCrtIntGet
  1042.     (
  1043.     int vector
  1044.     )
  1045.     {
  1046.     if ((vector < 0)  || (vector >= EPIC_MAX_ALL_IRQS))
  1047.         return (ERROR);
  1048.     /* obtain critical bit on EPIC */
  1049.     return epicCrtIntGet ( epicGetDestRegAdrs (vector) );
  1050.     }
  1051. #endif  /* INCLUDE_EPIC_CRT_INTR */
  1052. /*******************************************************************************
  1053. *
  1054. * epicIntAck - read the IACK register and return vector
  1055. * NOTES
  1056. *
  1057. * epicIntAck reads the Interrupt acknowledge register and return
  1058. * the vector number of the highest pending interrupt.
  1059. *
  1060. * NOMANUAL
  1061. * RETURNS: the vector number of the highest priority pending interrupt.
  1062. *
  1063. * ERRNO: N/A
  1064. */
  1065. int epicIntAck(void)
  1066.     {
  1067.     int eumbVal;
  1068.     eumbVal = sysEpicRegRead (EPIC_INT_ACK_REG);
  1069.     WRS_ASM ("isync;sync");
  1070.     return eumbVal;
  1071.     }
  1072. /*******************************************************************************
  1073. *
  1074. * epic EOI 0 signal end of interrupt on the EPIC
  1075. *
  1076. * NOTES
  1077. *
  1078. * epicEOI writes 0x0 to the EOI register to signal end of interrupt.
  1079. * This function is usually called after an interrupt routine is served.
  1080. *
  1081. * NOMANUAL
  1082. * RETURNS: N/A
  1083. *
  1084. * ERRNO: N/A
  1085. */
  1086. void epicEOI(void)
  1087.     {
  1088.     sysEpicRegWrite (EPIC_EOI_REG, 0x0);
  1089.     }
  1090. /*******************************************************************************
  1091. *
  1092. * epicGetVecRegAdrs - translate a vector to vector reg address
  1093. *
  1094. * This routine translates a vector to vector reg address.
  1095. *
  1096. * NOMANUAL
  1097. *
  1098. * RETURNS: vector register address of the corresponding vector type
  1099. */
  1100. ULONG epicGetVecRegAdrs
  1101.     (
  1102.     int vector
  1103.     )
  1104.     {
  1105.     if ((vector < EPIC_VEC_EXT_IRQ0) || (vector >= EPIC_VEC_CTRL_EXT))
  1106.         return ((ULONG) ERROR);
  1107.     if (vector < EPIC_VEC_IN_IRQ0)    /* type EXT */
  1108.         {
  1109.         return (EPIC_EX_VEC_REG (vector - EPIC_VEC_EXT_IRQ0));
  1110.         }
  1111.     if (vector < EPIC_VEC_GT_IRQ0)    /* type IN */
  1112.         {
  1113.         return (EPIC_IN_VEC_REG (vector - EPIC_VEC_IN_IRQ0));
  1114.         }
  1115.     if (vector < EPIC_VEC_MSG_IRQ0)    /* type GT */
  1116.         {
  1117.         return (EPIC_GT_VEC_REG (vector - EPIC_VEC_GT_IRQ0));
  1118.         }
  1119.     if (vector < EPIC_VEC_IPI_IRQ0)    /* type MSG */
  1120.         {
  1121.         return (EPIC_MSG_VEC_REG (vector - EPIC_VEC_MSG_IRQ0));
  1122.         }
  1123.     if (vector < EPIC_VEC_CTRL_EXT)    /* type IPI */
  1124.         {
  1125.         return (EPIC_IPI_VEC_REG (vector - EPIC_VEC_IPI_IRQ0));
  1126.         }
  1127.     /* should not reach here */
  1128.     return ((ULONG) ERROR);
  1129.     }
  1130. /*******************************************************************************
  1131. *
  1132. * epicGetDestRegAdrs - translate a vector to destination reg address
  1133. *
  1134. * This routine translates a vector to destination reg address
  1135. *
  1136. * NOMANUAL
  1137. *
  1138. * RETURNS: the destination register address of the corresponding vector type
  1139. *
  1140. * ERRNO: N/A
  1141. */
  1142. ULONG epicGetDestRegAdrs
  1143.     (
  1144.     int vector
  1145.     )
  1146.     {
  1147.     if ((vector < EPIC_VEC_EXT_IRQ0) || (vector >= EPIC_VEC_CTRL_EXT))
  1148.         return ((ULONG) ERROR);
  1149.     if (vector < EPIC_VEC_IN_IRQ0)    /* type EXT */
  1150.         {
  1151.         return (EPIC_EX_DEST_REG (vector - EPIC_VEC_EXT_IRQ0));
  1152.         }
  1153.     if (vector < EPIC_VEC_GT_IRQ0)    /* type IN */
  1154.         {
  1155.         return (EPIC_IN_DEST_REG (vector - EPIC_VEC_IN_IRQ0));
  1156.         }
  1157.     if (vector < EPIC_VEC_MSG_IRQ0)    /* type GT */
  1158.         {
  1159.         return ((ULONG) ERROR);
  1160.         }
  1161.     if (vector < EPIC_VEC_IPI_IRQ0)    /* type MSG */
  1162.         {
  1163.         return (EPIC_MSG_DEST_REG (vector - EPIC_VEC_MSG_IRQ0));
  1164.         }
  1165.     if (vector < EPIC_VEC_CTRL_EXT)    /* type IPI */
  1166.         {
  1167.         return ((ULONG) ERROR);
  1168.         }
  1169.     /* should not reach here */
  1170.     return ((ULONG) ERROR);
  1171.     }
  1172. /*******************************************************************************
  1173. *
  1174. * epicSrcAddrCheck - check source of the VPR address
  1175. *
  1176. * This routine checks if the VPR address passed in is external, internal, 
  1177. * timer, message, or IPI.
  1178. *
  1179. * NOMANUAL
  1180. * RETURNS: EPIC_IN_INTERRUPT for internal interrupt sources, or
  1181. *          EPIC_EX_INTERRUPT for external ones, or
  1182. *          EPIC_GT_INTERRUPT for global timer ones, or
  1183. *          EPIC_MSG_INTERRUPT for message ones, or
  1184. *          EPIC_IPI_INTERRUPT for IPI ones, or
  1185. *          EPIC_INV_INTER_SOURCE if an invalid address was passed.
  1186. *
  1187. * ERRNO: N/A
  1188. */
  1189. LOCAL int epicSrcAddrCheck
  1190.     (
  1191.     ULONG srcAddr
  1192.     )
  1193.     {
  1194.     switch (srcAddr)
  1195.         {
  1196. case EPIC_EX_INT0_VEC_REG:
  1197. case EPIC_EX_INT1_VEC_REG:
  1198. case EPIC_EX_INT2_VEC_REG:
  1199. case EPIC_EX_INT3_VEC_REG:
  1200. case EPIC_EX_INT4_VEC_REG:
  1201. case EPIC_EX_INT5_VEC_REG:
  1202. case EPIC_EX_INT6_VEC_REG:
  1203. case EPIC_EX_INT7_VEC_REG:
  1204. case EPIC_EX_INT8_VEC_REG:
  1205. case EPIC_EX_INT9_VEC_REG:
  1206. case EPIC_EX_INT10_VEC_REG:
  1207. case EPIC_EX_INT11_VEC_REG:
  1208.             return (EPIC_EX_INTERRUPT);
  1209. break;
  1210. case EPIC_IN_INT0_VEC_REG:
  1211. case EPIC_IN_INT1_VEC_REG:
  1212. case EPIC_IN_INT2_VEC_REG:
  1213. case EPIC_IN_INT3_VEC_REG:
  1214. case EPIC_IN_INT4_VEC_REG:
  1215. case EPIC_IN_INT5_VEC_REG:
  1216. case EPIC_IN_INT6_VEC_REG:
  1217. case EPIC_IN_INT7_VEC_REG:
  1218. case EPIC_IN_INT8_VEC_REG:
  1219. case EPIC_IN_INT9_VEC_REG:
  1220. case EPIC_IN_INT10_VEC_REG:
  1221. case EPIC_IN_INT11_VEC_REG:
  1222. case EPIC_IN_INT12_VEC_REG:
  1223. case EPIC_IN_INT13_VEC_REG:
  1224. case EPIC_IN_INT14_VEC_REG:
  1225. case EPIC_IN_INT15_VEC_REG:
  1226. case EPIC_IN_INT16_VEC_REG:
  1227. case EPIC_IN_INT17_VEC_REG:
  1228. case EPIC_IN_INT18_VEC_REG:
  1229. case EPIC_IN_INT19_VEC_REG:
  1230. case EPIC_IN_INT20_VEC_REG:
  1231. case EPIC_IN_INT21_VEC_REG:
  1232. case EPIC_IN_INT22_VEC_REG:
  1233. case EPIC_IN_INT23_VEC_REG:
  1234. case EPIC_IN_INT24_VEC_REG:
  1235. case EPIC_IN_INT25_VEC_REG:
  1236. case EPIC_IN_INT26_VEC_REG:
  1237. case EPIC_IN_INT27_VEC_REG:
  1238. case EPIC_IN_INT28_VEC_REG:
  1239. case EPIC_IN_INT29_VEC_REG:
  1240. case EPIC_IN_INT30_VEC_REG:
  1241. case EPIC_IN_INT31_VEC_REG:
  1242. case EPIC_IN_INT32_VEC_REG:
  1243. case EPIC_IN_INT33_VEC_REG:
  1244. case EPIC_IN_INT34_VEC_REG:
  1245. case EPIC_IN_INT35_VEC_REG:
  1246. case EPIC_IN_INT36_VEC_REG:
  1247. case EPIC_IN_INT37_VEC_REG:
  1248. case EPIC_IN_INT38_VEC_REG:
  1249. case EPIC_IN_INT39_VEC_REG:
  1250. case EPIC_IN_INT40_VEC_REG:
  1251. case EPIC_IN_INT41_VEC_REG:
  1252. case EPIC_IN_INT42_VEC_REG:
  1253. case EPIC_IN_INT43_VEC_REG:
  1254. case EPIC_IN_INT44_VEC_REG:
  1255. case EPIC_IN_INT45_VEC_REG:
  1256. case EPIC_IN_INT46_VEC_REG:
  1257. case EPIC_IN_INT47_VEC_REG:
  1258.             return (EPIC_IN_INTERRUPT);
  1259. break;
  1260. case EPIC_TM0_VEC_REG:
  1261. case EPIC_TM1_VEC_REG:
  1262. case EPIC_TM2_VEC_REG:
  1263. case EPIC_TM3_VEC_REG:
  1264.             return (EPIC_GT_INTERRUPT);
  1265. break;
  1266. case EPIC_MSG_INT0_VEC_REG:
  1267. case EPIC_MSG_INT1_VEC_REG:
  1268. case EPIC_MSG_INT2_VEC_REG:
  1269. case EPIC_MSG_INT3_VEC_REG:
  1270.             return (EPIC_MSG_INTERRUPT);
  1271. break;
  1272. case EPIC_IPI_0_VEC_REG:
  1273. case EPIC_IPI_1_VEC_REG:
  1274. case EPIC_IPI_2_VEC_REG:
  1275. case EPIC_IPI_3_VEC_REG:
  1276.             return (EPIC_IPI_INTERRUPT);
  1277. break;
  1278.         default:
  1279.             return (EPIC_INV_INTER_SOURCE);
  1280.         }
  1281.     }
  1282. /*******************************************************************************
  1283. *
  1284. * epicIntSourceSet - set interrupt parameters for an interrupt register
  1285. *
  1286. * This function sets the interrupt parameters for:
  1287. *     External vector/priority register (EIVPR)
  1288. *     Internal vector/priority register (IIVPR)
  1289. *     Global Timer vector/priority register (GTVPR)
  1290. *     Message vector/priority register (MIVPR)
  1291. *     IPI vector/priority register (IPIVPR)
  1292. * The interrupt parameters can only be set when the current source is not
  1293. * in-request or in-service, which is determined by the Activity bit.  This
  1294. * routine reads the Activity bit; if the value of this bit is 1 (in-request
  1295. * or in-service), it returns error; otherwise, it sets the value of the
  1296. * parameters to the register offset defined in srcAddr.
  1297. *
  1298. * inputs:  srcAddr:   Address Offset of the source interrupt register.  This
  1299. *       routine assumes that the srcAddr passed in is an valid
  1300. *       Source Vector Priority address.
  1301. *          polarity: Use by external & internal interrupts only.
  1302. *                    1 -  Enable active high or positive edge
  1303. *                    0 -  Enable active low or negative edge
  1304. *          sense:    Use by external interrupts only.
  1305. *                    1 -  Enable level sensitive interrupts
  1306. *                    0 -  Enable edge sensitive interrupts
  1307. *          priority: valid number 0 to 15   
  1308. *          vector:   valid number 0 - 65535 (16 bits)
  1309. *
  1310. * Errors:  EPIC_INV_INTER_SOURCE Invalid Source Address,
  1311. *          EPIC_INTER_IN_SERVICE Interrupt currently in service
  1312. *          ERROR Unknown type
  1313. *
  1314. * NOMANUAL
  1315. * RETURNS: OK or one of errors above
  1316. *
  1317. * ERRNO: N/A
  1318. */
  1319. STATUS epicIntSourceSet
  1320.     (
  1321.     ULONG  srcAddr,     
  1322.     int  polarity,
  1323.     int  sense,
  1324.     int  priority,
  1325.     int  vector
  1326.     )
  1327.     {
  1328.     ULONG  srcVal;
  1329.     ULONG errCode;
  1330.   
  1331.     errCode = epicSrcAddrCheck(srcAddr);
  1332.     if (errCode == EPIC_INV_INTER_SOURCE)
  1333.         {
  1334.         return (errCode);
  1335.         }
  1336.     srcVal = sysEpicRegRead(srcAddr);
  1337.     switch (errCode)
  1338.         {
  1339.         case EPIC_EX_INTERRUPT:
  1340.             if (srcVal & EPIC_EIVPR_INTR_ACTIVE)
  1341.                 {
  1342.                 return (EPIC_INTER_IN_SERVICE);
  1343.                 }
  1344.             /* mask off current settings */
  1345.             srcVal &= ~(EPIC_EIVPR_INTR_POLARITY |
  1346.                         EPIC_EIVPR_INTR_SENSE |
  1347.                         EPIC_EIVPR_PRIORITY_MSK  |
  1348.                         EPIC_EIVPR_VECTOR_MSK);
  1349.             /* set new values */
  1350.             srcVal |= (EPIC_EIVPR_POLARITY (polarity) |
  1351.                        EPIC_EIVPR_SENS (sense) |
  1352.                        EPIC_EIVPR_PRIORITY (priority) |
  1353.                        EPIC_EIVPR_VECTOR (vector));
  1354.         break;
  1355.         case EPIC_IN_INTERRUPT:
  1356.             if (srcVal & EPIC_IIVPR_INTR_ACTIVE)
  1357.                 {
  1358.                 return (EPIC_INTER_IN_SERVICE);
  1359.                 }
  1360.             /* mask off current settings */
  1361.             srcVal &= ~(EPIC_IIVPR_INTR_POLARITY |
  1362.                         EPIC_IIVPR_PRIORITY_MSK  |
  1363.                         EPIC_IIVPR_VECTOR_MSK);
  1364.             /* set new values */
  1365.             srcVal |= (EPIC_IIVPR_POLARITY (polarity) |
  1366.                        EPIC_IIVPR_PRIORITY (priority) |
  1367.                        EPIC_IIVPR_VECTOR (vector));
  1368.         break;
  1369.         case EPIC_GT_INTERRUPT:
  1370.             if (srcVal & EPIC_GTVPR_INTR_ACTIVE)
  1371.                 {
  1372.                 return (EPIC_INTER_IN_SERVICE);
  1373.                 }
  1374.             /* mask off current settings */
  1375.             srcVal &= ~(EPIC_GTVPR_PRIORITY_MSK  |
  1376.                         EPIC_GTVPR_VECTOR_MSK);
  1377.             /* set new values */
  1378.             srcVal |= (EPIC_GTVPR_PRIORITY (priority) |
  1379.                        EPIC_GTVPR_VECTOR (vector));
  1380.         break;
  1381.         case EPIC_MSG_INTERRUPT:
  1382.             if (srcVal & EPIC_MIVPR_INTR_ACTIVE)
  1383.                 {
  1384.                 return (EPIC_INTER_IN_SERVICE);
  1385.                 }
  1386.             /* mask off current settings */
  1387.             srcVal &= ~(EPIC_MIVPR_PRIORITY_MSK  |
  1388.                         EPIC_MIVPR_VECTOR_MSK);
  1389.             /* set new values */
  1390.             srcVal |= (EPIC_MIVPR_PRIORITY (priority) |
  1391.                        EPIC_MIVPR_VECTOR (vector));
  1392.         break;
  1393.         case EPIC_IPI_INTERRUPT:
  1394.             if (srcVal & EPIC_IPIVPR_INTR_ACTIVE)
  1395.                 {
  1396.                 return (EPIC_INTER_IN_SERVICE);
  1397.                 }
  1398.             /* mask off current settings */
  1399.             srcVal &= ~(EPIC_IPIVPR_PRIORITY_MSK  |
  1400.                         EPIC_IPIVPR_VECTOR_MSK);
  1401.             /* set new values */
  1402.             srcVal |= (EPIC_IPIVPR_PRIORITY (priority) |
  1403.                        EPIC_IPIVPR_VECTOR (vector));
  1404.         break;
  1405.         default:
  1406.             return (ERROR);
  1407.         }
  1408.     sysEpicRegWrite(srcAddr, srcVal);
  1409.     return (OK);
  1410.     }
  1411. /*******************************************************************************
  1412. *
  1413. * epicIntSourceGet - retrieve information of an EPIC source vector register.
  1414. *
  1415. * This function retrieves information of an epic source vector register.
  1416. * The information includes the Enable bit, the polarity, sense bits, the
  1417. * interrupt priority and interrupt vector number.
  1418. * Input:  srcAddr   - address of the source vector register
  1419. * Output: enable    - whether the interrupt is enabled
  1420. *          polarity - interrupt polarity (high or low)
  1421. *          sense    - interrupt sense (level or edge)
  1422. *          Priority - interrupt priority
  1423. *          Vector   - interrupt vector number
  1424. *
  1425. * NOMANUAL
  1426. * RETURNS: OK or ERROR or EPIC_INV_INTER_SOURCE
  1427. *
  1428. * ERRNO: N/A
  1429. */
  1430. STATUS epicIntSourceGet
  1431.     (
  1432.     ULONG  srcAddr,
  1433.     int * pEnableMask,
  1434.     int * pPolarity,
  1435.     int * pSense,
  1436.     int * pPriority,
  1437.     int * pVector
  1438.     )
  1439.     {
  1440.     ULONG  srcVal;
  1441.     int  errCode;
  1442.   
  1443.     errCode = epicSrcAddrCheck (srcAddr);
  1444.     if (errCode == EPIC_INV_INTER_SOURCE)
  1445.         {
  1446.         return errCode;
  1447.         }
  1448.     srcVal = sysEpicRegRead(srcAddr);
  1449.     
  1450.     switch (errCode)
  1451.         {
  1452.         case EPIC_EX_INTERRUPT:
  1453.             *pEnableMask  = (srcVal & EPIC_EIVPR_INTR_MSK)      >> 31;
  1454.             *pPolarity    = (srcVal & EPIC_EIVPR_INTR_POLARITY) >> 23;
  1455.             *pSense       = (srcVal & EPIC_EIVPR_INTR_SENSE)    >> 22;
  1456.             *pPriority    = (srcVal & EPIC_EIVPR_PRIORITY_MSK)  >> 16;
  1457.             *pVector      = (srcVal & EPIC_EIVPR_VECTOR_MSK);
  1458.         break;
  1459.         case EPIC_IN_INTERRUPT:
  1460.             *pEnableMask  = (srcVal & EPIC_IIVPR_INTR_MSK)      >> 31;
  1461.             *pPolarity    = (srcVal & EPIC_IIVPR_INTR_POLARITY) >> 23;
  1462.             *pPriority    = (srcVal & EPIC_IIVPR_PRIORITY_MSK)  >> 16;
  1463.             *pVector      = (srcVal & EPIC_IIVPR_VECTOR_MSK);
  1464.         break;
  1465.         case EPIC_GT_INTERRUPT:
  1466.             *pEnableMask  = (srcVal & EPIC_GTVPR_INTR_MSK)      >> 31;
  1467.             *pPriority    = (srcVal & EPIC_GTVPR_PRIORITY_MSK)  >> 16;
  1468.             *pVector      = (srcVal & EPIC_GTVPR_VECTOR_MSK);
  1469.         break;
  1470.         case EPIC_MSG_INTERRUPT:
  1471.             *pEnableMask  = (srcVal & EPIC_MIVPR_INTR_MSK)      >> 31;
  1472.             *pPriority    = (srcVal & EPIC_MIVPR_PRIORITY_MSK)  >> 16;
  1473.             *pVector      = (srcVal & EPIC_MIVPR_VECTOR_MSK);
  1474.         break;
  1475.         case EPIC_IPI_INTERRUPT:
  1476.             *pEnableMask  = (srcVal & EPIC_IPIVPR_INTR_MSK)     >> 31;
  1477.             *pPriority    = (srcVal & EPIC_IPIVPR_PRIORITY_MSK) >> 16;
  1478.             *pVector      = (srcVal & EPIC_IPIVPR_VECTOR_MSK);
  1479.         break;
  1480.         default:
  1481.             return (ERROR);
  1482.         }
  1483.     return (OK);
  1484.     }
  1485. /*******************************************************************************
  1486. *
  1487. * sysEpicRegRead - read a register from the EPIC address space
  1488. *
  1489. * This function reads a register from the EPIC address space. The
  1490. * register number <regNum> is added to the offset of the EPIC base address
  1491. *
  1492. * NOMANUAL
  1493. *
  1494. * RETURNS:  the 32 bit little endian value of the register.
  1495. *
  1496. * ERRNO: N/A
  1497. */
  1498. UINT32 sysEpicRegRead
  1499.     (
  1500.     ULONG regNum
  1501.     )
  1502.     {
  1503.     UINT32 temp;
  1504.     WRS_ASM("isync;sync");
  1505.     temp = *(UINT32 *) ((UINT32)CCSBAR + (UINT32)regNum) ;
  1506.     return (temp);
  1507.     }
  1508. /*******************************************************************************
  1509. *
  1510. * sysEpicRegWrite -  write a register to the EPIC address space
  1511. *
  1512. * This function writes a register to the EPIC address space. The
  1513. * register number <regNum> is added to the offset of the EPIC base address
  1514. * and the resulting address is loaded with <regVal>
  1515. *
  1516. * NOMANUAL
  1517. *
  1518. * RETURNS: N/A
  1519. *
  1520. * ERRNO: N/A
  1521. */
  1522. void sysEpicRegWrite
  1523.     (
  1524.     ULONG regNum,
  1525.     UINT32 regVal
  1526.     )
  1527.     {
  1528.     *(UINT32 *) (CCSBAR + regNum) = regVal;
  1529.     WRS_ASM("eieio;sync");
  1530.     return ;
  1531.     }