pciIntLib.c
上传用户:yuanda199
上传日期:2022-06-26
资源大小:412k
文件大小:7k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* pciIntLib.c - PCI Shared Interrupt support */
  2. /* Copyright 1984-1998 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01c,30sep98, tm  moved PCI_INT_RTN typedef here from private header (SPR 22544)
  8. 01b,04mar98, tm  augmented pciIntConnect/Disconnect to do intConnect also
  9. 01a,20feb98, tm  derived from pciIomapLib.c of ebsa285 BSP v01m
  10. */
  11. /*
  12. DESCRIPTION
  13. This library is PCI Revision 2.1 compliant.
  14. The functions addressed here include:
  15. .IP "   -"
  16. Initialize the library.
  17. .IP "   -"
  18. Connect a shared interrupt handler.
  19. .IP "   -"
  20. Disconnect a shared interrupt handler.
  21. .IP "   -"
  22. Master shared interrupt handler.
  23. .LP
  24. Shared PCI interrupt are supported by three functions: pciInt(),
  25. pciIntConnect(), pciIntDisconnect().  pciIntConnect() adds the specified
  26. interrupt handler to the link list and pciIntDisconnect() removes it from
  27. the link list.  Master interrupt handler pciInt() executes these interrupt
  28. handlers in the link list for a PCI interrupt.  Each interrupt handler must
  29. check the device dependent interrupt status bit to determine the source of
  30. the interrupt, since it simply execute all interrupt handlers in the link
  31. list.  pciInt() should be attached by intConnect() function in the BSP 
  32. initialization with its parameter. The parameter is an IRQ associated 
  33. to the PCI interrupt.
  34. */
  35. #include "vxWorks.h"
  36. #include "config.h"
  37. #include "dllLib.h"
  38. #include "sysLib.h"
  39. #include "stdio.h"
  40. #include "stdlib.h"
  41. #include "string.h"
  42. #include "intLib.h"
  43. #include "drv/pci/pciIntLib.h"
  44. /*
  45.  * The following defines specify, by default, the maximum number of busses,
  46.  * devices and functions allowed by the PCI 2.1 Specification.
  47.  *
  48.  * Any or all may be overriden by defining them in config.h.
  49.  */
  50. /* macros */
  51. #ifndef INT_NUM_IRQ0
  52. #   define INT_NUM_IRQ0 0
  53. #endif /* INT_NUM_IRQ0 */
  54. /*
  55.  * Provide intConnect via a macro so that an alternate interrupt binding
  56.  * mechanism can be specified
  57.  *
  58.  */
  59. #ifndef PCI_INT_HANDLER_BIND
  60. #define PCI_INT_HANDLER_BIND(vector, routine, param, pResult)          
  61.     {                                                                  
  62.     IMPORT STATUS intConnect();                                        
  63.     *pResult = intConnect ( (vector),(routine), (int)(param) );        
  64.     }
  65.     
  66. #endif /* PCI_INT_HANDLER_BIND */
  67. /* typedefs */
  68. typedef struct pciIntRtn
  69.     {
  70.     DL_NODE node; /* double link list */
  71.     VOIDFUNCPTR routine; /* interrupt handler */
  72.     int parameter; /* parameter of the handler */
  73.     } PCI_INT_RTN;
  74. /* globals */
  75. DL_LIST pciIntList[PCI_IRQ_LINES]; /* linked list of int handlers */
  76. /* locals */
  77. LOCAL STATUS pciIntLibInitStatus = NONE;
  78. /*******************************************************************************
  79. *
  80. * pciIntLibInit - 
  81. *
  82. *
  83. */
  84. STATUS pciIntLibInit ( void )
  85.     {
  86.     int ix;
  87.     if (pciIntLibInitStatus != NONE)
  88. return (pciIntLibInitStatus);
  89.     /* Initialize shared interrupt handler chains */
  90.     for (ix = 0; ix < PCI_IRQ_LINES; ix++)
  91.         dllInit (&pciIntList[ix]);
  92.     return(pciIntLibInitStatus = OK);
  93.     }
  94. /*******************************************************************************
  95. *
  96. * pciInt - interrupt handler for shared PCI interrupt.
  97. *
  98. * This routine executes multiple interrupt handlers for a PCI interrupt.
  99. * Each interrupt handler must check the device dependent interrupt status bit
  100. * to determine the source of the interrupt, since it simply execute all
  101. * interrupt handlers in the link list.
  102. *
  103. * RETURNS: N/A
  104. *
  105. */
  106. VOID pciInt
  107.     (
  108.     int irq /* IRQ associated to the PCI interrupt */
  109.     )
  110.     {
  111.     PCI_INT_RTN *pRtn;
  112.     for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;
  113.  pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))
  114. (* pRtn->routine) (pRtn->parameter);
  115.     }
  116. /*******************************************************************************
  117. *
  118. * pciIntConnect - connect the interrupt handler to the PCI interrupt.
  119. *
  120. * This routine connects an interrupt handler to the PCI interrupt line(A - D).
  121. * Link list is created if multiple handlers are assigned to the single PCI
  122. * interrupt.
  123. *
  124. * RETURNS:
  125. * OK, or ERROR if the interrupt handler cannot be built.
  126. *
  127. */
  128. STATUS pciIntConnect
  129.     (
  130.     VOIDFUNCPTR *vector,        /* interrupt vector to attach to     */
  131.     VOIDFUNCPTR routine,        /* routine to be called              */
  132.     int parameter               /* parameter to be passed to routine */
  133.     )
  134.     {
  135.     int irq = (IVEC_TO_INUM(vector)) - INT_NUM_IRQ0;
  136.     PCI_INT_RTN *pRtn;
  137.     int oldLevel;
  138.     STATUS retStatus;
  139.     if (pciIntLibInitStatus != OK)
  140. return (ERROR);
  141.     /* If pciIntList[irq] is null, then bind the handler using intConnect */
  142.     if ( DLL_EMPTY(&pciIntList[irq]) )
  143.         {
  144.         PCI_INT_HANDLER_BIND(vector, pciInt, irq , &retStatus )
  145. if ( retStatus == ERROR )
  146.     {
  147.             return( ERROR );
  148.     }
  149.         }
  150.     if ((pRtn = (PCI_INT_RTN *)malloc (sizeof (PCI_INT_RTN))) == NULL)
  151.         {
  152. /* intDisconnect here ??????????? */
  153.         return (ERROR);
  154.         }
  155.     pRtn->routine   = routine;
  156.     pRtn->parameter = parameter;
  157.     oldLevel = intLock (); /* LOCK INTERRUPT */
  158.     dllAdd (&pciIntList[irq], &pRtn->node);
  159.     intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  160.     retStatus = ( (DLL_EMPTY(&pciIntList[irq])) ? ERROR : OK );
  161.     return (retStatus);
  162.     }
  163. /*******************************************************************************
  164. *
  165. * pciIntDisconnect - disconnect the interrupt handler from the PCI interrupt.
  166. *
  167. * This routine disconnects the interrupt handler from the PCI interrupt line.
  168. *
  169. * RETURNS:
  170. * OK, or ERROR if the interrupt handler cannot be removed.
  171. *
  172. */
  173. STATUS pciIntDisconnect
  174.     (
  175.     VOIDFUNCPTR *vector,        /* interrupt vector to attach to     */
  176.     VOIDFUNCPTR routine         /* routine to be called              */
  177.     )
  178.     {
  179.     int irq = IVEC_TO_INUM ((int)vector) - INT_NUM_IRQ0;
  180.     PCI_INT_RTN *pRtn;
  181.     int oldLevel;
  182.     STATUS retStatus = ERROR;
  183.     if (pciIntLibInitStatus != OK)
  184. return (ERROR);
  185.     for (pRtn = (PCI_INT_RTN *)DLL_FIRST (&pciIntList[irq]); pRtn != NULL;
  186.  pRtn = (PCI_INT_RTN *)DLL_NEXT (&pRtn->node))
  187. {
  188. if (pRtn->routine == routine)
  189.     {
  190.     oldLevel = intLock (); /* LOCK INTERRUPT */
  191.     dllRemove (&pciIntList[irq], &pRtn->node);
  192.     intUnlock (oldLevel); /* UNLOCK INTERRUPT */
  193.     free ((char *)pRtn);
  194.     /* If the last ISR was just removed, then do intDisconnect */
  195.             if ( DLL_EMPTY(&pciIntList[irq]) )
  196.         {
  197.                 /* Get the address of the synthesized handler and free the 
  198.  * block of allocated memory
  199.  */
  200. /* intDisconnect(); */
  201.  
  202.         }
  203.     retStatus = OK;
  204.     }
  205. }
  206.     return (retStatus);
  207.     }