i82378Ibc.c
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:13k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* i82378Ibc.c - Intel i82378 ISA Bridge Controller (IBC) driver */
  2. /* Copyright 1984-1996 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5. modification history
  6. --------------------
  7. 01q,24aug98,cjtc windview 2.0 event logging is now single step. Timestamp no
  8.                  longer stored by intEnt. Avoids out-of-sequence timestamps in
  9.                  event log (SPR 21868)
  10. 01p,16apr98,pr   moved triggering support from arch/ppc
  11. 01o,05mar98,pr   added WV_ON mask to WV 2.0 code
  12. 01n,22feb98,pr   modified windview support for WV 2.0
  13. 01m,22dec96,tpr  removed intUnlock() at the end of sysIbcIntHandler() SPR(#7679)
  14. 01l,08dec96,tpr  changed _func_intEnableRtn() return value from void to int.
  15. 01o,09jul97,dat  fixed SPR 8866, intDisable did not work for lvls 8 to 15.
  16. 01n,17jan97,mas  fixed IRQ number to IRQ level mapping (SPR 7752) and
  17.  deleted unused SEM_ID extIntHandlerSem.
  18. 01m,22dec96,tpr  removed intUnlock() at the end of sysIbcIntHandler() SPR(#7679)
  19. 01l,08dec96,tpr  changed _func_intEnableRtn() return value from void to int.
  20.  added sysIbcIntEnable() return value code.
  21. 01k,30oct96,dat  replaced sysInByte and sysOutByte by IBC_BYTE_READ and
  22.     tam  IBC_BYTE_WRITE macros (spr #7415). Added description.
  23. 01j,29oct96,wlf  doc: cleanup.
  24. 01i,24sep96,mas  changed MV1305 to MV1300.
  25. 01h,23jul96,tam  fixed sysIbcIntLevelSet() to mask int. level <intLevel> too
  26. 01g,08jul96,ms   merged in pr's WindView instrumentation
  27. 01f,01jul96,tam  added code to respect interrupt priorities (spr #6212). 
  28. 01e,11jun96,tam  fixed sysIbcIntConnect() to enable multiple int. handlers 
  29.  connected to a same vector (spr #6588).
  30. 01d,05may96,mas  fix IBC interrupt mappings for MV1305 vs. ULTRA/MV1600.
  31. 01c,16apr96,jds  fix IBC interrupt mappings for ULTRA vs. MV1600
  32. 01b,06mar96,tpr  clean-up
  33. 01a,29jan96,tam  written from i8259Pic.c.
  34. */
  35. /*
  36. DESCRIPTION
  37. This module implements the Intel i82378 ISA Bridge Controller (IBC) driver.
  38. The i82378 IBC chip includes many functions.  This driver only implements
  39. the interrupt control functions.  In fact this driver provides the
  40. complete interrupt architecture functionality (which it shouldn't).
  41. The macros IBC_BYTE_READ and IBC_BYTE_WRITE control the actual access
  42. to the PIC registers.  By default, these macros assume memory mapped
  43. access to the registers.  The default write macro includes an eieio
  44. instruction to insure write-ordering is preserved. The BSP can redefine
  45. these macros in config.h or <bsp>.h to specify some other access means
  46. such as i/o mapping.
  47. The IBC_BYTE_READ macro takes two arguments, the register address and
  48. the data address.  Data is read from the register address and stored
  49. at the data address. Defining the macro to return a value is not preferred
  50. because if the macro has to be defined within a code block, then data
  51. cannot easily be returned.
  52. The IBC_BYTE_WRITE macro also takes two arguments, the register address
  53. and the data to be written.  Including an eieio instruction after the
  54. actual data write is recommended.
  55. Neither macro returns any values.
  56. */
  57. #include "drv/intrCtl/i82378Ibc.h"
  58. #include "private/funcBindP.h"
  59. /* globals */
  60. IMPORT UINT sysVectorIRQ0;  /* vector for IRQ0 */
  61. IMPORT STATUS       (*_func_intConnectRtn) (VOIDFUNCPTR *, VOIDFUNCPTR, int);
  62. IMPORT int       (*_func_intEnableRtn) (int);
  63. IMPORT int       (*_func_intDisableRtn) (int);
  64. IMPORT STATUS excIntConnect (VOIDFUNCPTR *, VOIDFUNCPTR);
  65. #ifdef  INCLUDE_WINDVIEW
  66. #include "private/eventP.h"
  67. #endif
  68. /* system interrupt table */
  69. INT_HANDLER_DESC * sysIntTbl [256];
  70. /* locals */
  71. /* PIC1 & PIC2 IRQ masks ordered by IRQ# */
  72. UCHAR ibcIRQ2Pic1Mask[16] = {0xFB,0xFA,0xF8,0xF8,0xF0,0xE0,0xC0,0x80,
  73.      0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8};
  74. UCHAR ibcIRQ2Pic2Mask[16] = {0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,
  75.      0xFF,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x80};
  76. /* forward static functions */
  77. LOCAL void sysIbcEndOfInt (void);
  78. LOCAL STATUS sysIbcIntConnect (VOIDFUNCPTR * vector, VOIDFUNCPTR routine,
  79.   int parameter);
  80. LOCAL int sysIbcIntEnable (int);
  81. LOCAL int sysIbcIntDisable (int);
  82. LOCAL void sysIbcIntLevelSet (UCHAR intNumber, UCHAR  pic1Mask,
  83.    UCHAR  pic2Mask);
  84. void   sysIbcIntHandler (void);
  85. /*******************************************************************************
  86. *
  87. * sysIbcInit - initialize the ISA Bridge Controller 
  88. *
  89. * This routine initializes the Intel i82378 ISA Bridge Controller (IBC).
  90. *
  91. * RETURNS: OK, always.
  92. */
  93. STATUS sysIbcInit (void)
  94.     {
  95.     UINT vector;
  96.     UCHAR intVec;
  97.     /* initialize the interrupt table */
  98.     
  99.     for (vector = 0; vector < 256; vector++)
  100. sysIntTbl[vector] = NULL;
  101.     /* connect the interrupt demultiplexer to the PowerPC external interrupt */
  102.     excIntConnect ((VOIDFUNCPTR *) _EXC_OFF_INTR, sysIbcIntHandler);
  103. #ifdef ULTRA
  104.     /*
  105.      * route PCI interrupts to ISA IRQs and other initialization
  106.      * PCI IRQ0: routed to LN_INT_LVL
  107.      * PCI IRQ1: routed to NOTHING (no device supported)
  108.      * PCI IRQ2: routed to SCSI_INT_LVL
  109.      * PCI IRQ3: routed to NOTHING (no device supported)
  110.      */
  111.     *(ULONG *)(CNFG_IBC_ADRS + 0x60) = LONGSWAP((0x00000000 << 24) | 
  112. (SCSI_INT_LVL << 16) |
  113. (0x00000000 << 8) | 
  114. LN_INT_LVL);
  115.     /* make the IRQ 15,14,11,10, 9 level sensitive */
  116.     (*(char *)i82378_INT2_ELC) = 0x80 | 0x40 | 0x08 | 0x04 | 0x02 ;
  117. #endif  /* #ifdef ULTRA */
  118. #ifdef MV1300
  119.     /*
  120.      * route PCI interrupts to ISA IRQs and other initialization
  121.      * PCI IRQ0: routed to NOTHING (no device supported)
  122.      * PCI IRQ1: routed to VME2PCI_INT_LVL
  123.      * PCI IRQ2: routed to NOTHING (no device supported)
  124.      * PCI IRQ3: routed to IRQ15
  125.      */
  126.     *(ULONG *)(CNFG_IBC_ADRS + 0x60) = LONGSWAP(0x0f000000 | 
  127. (0x00000000 << 16) |
  128. (VME2PCI_INT_LVL << 8) | 
  129. 0x00000000);
  130.     /* make the IRQ 15,14,11,10, 9 level sensitive */
  131.     (*(char *)i82378_INT2_ELC) = 0x80 | 0x40 | 0x08 | 0x04 | 0x02 ;
  132. #endif  /* #ifdef MV1300 */
  133. #ifdef MV1600
  134.     /*
  135.      * route PCI interrupts to ISA IRQs and other initialization
  136.      * PCI IRQ0: routed to LN_INT_LVL
  137.      * PCI IRQ1: routed to VME2PCI_INT_LVL
  138.      * PCI IRQ2: routed to SCSI_INT_LVL
  139.      * PCI IRQ3: routed to IRQ15
  140.      */
  141.     *(ULONG *)(CNFG_IBC_ADRS + 0x60) = LONGSWAP(0x0f000000 | 
  142. (SCSI_INT_LVL << 16) |
  143. (VME2PCI_INT_LVL << 8) |
  144. LN_INT_LVL);
  145.     /* make the IRQ 15,14,11,10, 9 level sensitive */
  146.     (*(char *)i82378_INT2_ELC) = 0x80 | 0x40 | 0x08 | 0x04 | 0x02 ;
  147. #endif  /* #ifdef MV1600 */
  148.     /* initialize the IBC (ISA Bridge Controller) */
  149.     IBC_BYTE_WRITE (PIC_port1 (PIC1_BASE_ADR),0x11);        /* ICW1 */
  150.     IBC_BYTE_WRITE (PIC_port2 (PIC1_BASE_ADR),sysVectorIRQ0); /* ICW2 */
  151.     IBC_BYTE_WRITE (PIC_port2 (PIC1_BASE_ADR),0x04);        /* ICW3 */
  152.     IBC_BYTE_WRITE (PIC_port2 (PIC1_BASE_ADR),0x01);        /* ICW4 */
  153.     IBC_BYTE_WRITE (PIC_port1 (PIC2_BASE_ADR),0x11);        /* ICW1 */
  154.     IBC_BYTE_WRITE (PIC_port2 (PIC2_BASE_ADR),sysVectorIRQ0+8); /* ICW2 */
  155.     IBC_BYTE_WRITE (PIC_port2 (PIC2_BASE_ADR),0x02);        /* ICW3 */
  156.     IBC_BYTE_WRITE (PIC_port2 (PIC2_BASE_ADR),0x01);        /* ICW4 */
  157.     /* disable interrupts */
  158.     IBC_BYTE_WRITE (PIC_IMASK (PIC1_BASE_ADR),0xfb);
  159.     IBC_BYTE_WRITE (PIC_IMASK (PIC2_BASE_ADR),0xff);
  160.     /* set the BSP driver specific Interrupt Handler and intConnect routines */
  161.     _func_intConnectRtn = sysIbcIntConnect;
  162.     _func_intEnableRtn = sysIbcIntEnable;
  163.     _func_intDisableRtn = sysIbcIntDisable;
  164.     /* clear the pending interrupts */
  165.     intVec = (*(char *)ISA_INTR_ACK_REG);
  166.     sysIbcEndOfInt (); /* perform the end of interrupt procedure */
  167.     return (OK);
  168.     }
  169. /*******************************************************************************
  170. *
  171. * sysIbcIntEnable - enable an IBC interrupt number
  172. *
  173. * This routine enables a specified IBC interrupt number.
  174. *
  175. * RETURNS: OK.
  176. *
  177. * ARGSUSED0
  178. */
  179. LOCAL int sysIbcIntEnable
  180.     (
  181.     int intNumber        /* interrupt number to enable */
  182.     )
  183.     {
  184.     UINT8 temp;
  185.     UINT8 *pReg;
  186.     if (intNumber < 8)
  187. {
  188. pReg = (UINT8 *) PIC_IMASK (PIC1_BASE_ADR);
  189. }
  190.     else
  191. {
  192. pReg = (UINT8 *) PIC_IMASK (PIC2_BASE_ADR);
  193. intNumber -= 8;
  194. }
  195.     IBC_BYTE_READ (pReg, &temp);
  196.     IBC_BYTE_WRITE (pReg, temp & ~(1 << intNumber));
  197.     return (OK);
  198.     }
  199. /*******************************************************************************
  200. *
  201. * sysIbcIntDisable - disable an IBC interrupt number
  202. *
  203. * This routine disables a specified IBC interrupt number.
  204. *
  205. * RETURNS: OK.
  206. *
  207. * ARGSUSED0
  208. */
  209. LOCAL int sysIbcIntDisable
  210.     (
  211.     int intNumber        /* interrupt number to disable */
  212.     )
  213.     {
  214.     UINT8* pReg;
  215.     UINT8 temp;
  216.     if (intNumber < 8)
  217. {
  218. pReg = (UINT8 *) PIC_IMASK (PIC1_BASE_ADR);
  219. }
  220.     else
  221. {
  222. pReg = (UINT8 *) PIC_IMASK (PIC2_BASE_ADR);
  223. intNumber -= 8;
  224. }
  225.     IBC_BYTE_READ (pReg, &temp);
  226.     IBC_BYTE_WRITE (pReg, temp | (1 << intNumber));
  227.     return (OK);
  228.     }
  229. /******************************************************************************
  230. *
  231. * sysIbcIntConnect - connect an interrupt handler to the system vector table
  232. *
  233. * This function connects an interrupt handler to the system vector table.
  234. *
  235. * RETURNS: OK/ERROR.
  236. */
  237. LOCAL STATUS sysIbcIntConnect
  238.     (
  239.      VOIDFUNCPTR *  vector, /* interrupt vector to attach */
  240.      VOIDFUNCPTR    routine, /* routine to be called */
  241.      int         parameter /* parameter to be passed to routine */
  242.     )
  243.     {
  244.     INT_HANDLER_DESC * newHandler;
  245.     INT_HANDLER_DESC * currHandler;
  246.     if (((int)vector < 0) || ((int)vector > 0xff)) /* Out of Range? */
  247. return (ERROR);
  248.     /* create a new interrupt handler */
  249.     newHandler = malloc (sizeof (INT_HANDLER_DESC));
  250.     /* check if the memory allocation succeed */
  251.     if (newHandler == NULL)
  252. return (ERROR);
  253.     /* initialize the new handler */
  254.     newHandler->vec  = routine;
  255.     newHandler->arg  = parameter;
  256.     newHandler->next  = NULL;
  257.     if (sysIntTbl[(int) vector] == NULL)
  258. sysIntTbl [(int ) vector] = newHandler; /* single int. handler case */
  259.     else
  260. {
  261. currHandler = sysIntTbl[(int) vector]; /* multiple int. handler case */
  262. while (currHandler->next != NULL)
  263.     {
  264.     currHandler = currHandler->next;
  265.     }
  266. currHandler->next = newHandler;
  267. }
  268.     return (OK);
  269.     }
  270. /******************************************************************************
  271. *
  272. * sysIbcIntHandler - handle an i82378 IBC interrupt
  273. *
  274. * This routine is called to handle an Intel i82378 ISA Bridge Controller
  275. * (IBC) interrupt exception.  
  276. *
  277. * This routine generates the PCI IACK cycle to get the interrupt vector from
  278. * the PIC chips.  Once the vector is obtained, it is used as an index into
  279. * the system vector table to locate the user-defined interrupt routine for
  280. * that vector.  Each entry in the vector table is a part of a singly-linked
  281. * list and all routines on that list are executed in order.
  282. *
  283. * RETURNS: N/A
  284. */
  285. void sysIbcIntHandler (void)
  286.     {
  287.     UCHAR intVec;
  288.     INT_HANDLER_DESC * currHandler;
  289.     char                intReg1;
  290.     char                intReg2;
  291.     int  lock;
  292.     /* 
  293.      * Reading ISA_INTR_ACK_REG would generate PCI IACK cycles on the 
  294.      * PCI bus which would cause the IBC to put out vector from the 82378
  295.      * on the PCI bus. 
  296.      * Bit 5 of PCI control register in the IBC i82378 should be
  297.      * programmed to 1 (By default it is 1) if the IBC should respond with
  298.      * a vector when PCI IACK cycles are generated. 
  299.      */ 
  300.     intVec = (*(char *)ISA_INTR_ACK_REG);
  301. #ifdef INCLUDE_WINDVIEW
  302.     WV_EVT_INT_ENT(intVec)
  303. #endif
  304.     /* Record current interrupt mask settings */
  305.     IBC_BYTE_READ (PIC_IMASK (PIC1_BASE_ADR), &intReg1);
  306.     IBC_BYTE_READ (PIC_IMASK (PIC2_BASE_ADR), &intReg2);
  307.     /* Mask this and lower priority interrupt levels */
  308.     sysIbcIntLevelSet (intVec, intReg1, intReg2);
  309.     /* 
  310.      * Now the interrupt acknowledge is made, the interrupt can be re-enabled
  311.      */
  312.     intUnlock (_PPC_MSR_EE);
  313.     
  314.     /* call EACH respective interrupt handler */
  315.     if ((currHandler = sysIntTbl [intVec]) == NULL)
  316. logMsg ("uninitialized interrupt %dn", intVec, 0,0,0,0,0);
  317.     
  318.     else
  319. {
  320. while (currHandler != NULL)
  321.     {
  322.     currHandler->vec (currHandler->arg);
  323.     currHandler = currHandler->next;
  324.     }
  325. }
  326.     sysIbcEndOfInt (); /* perform the end of interrupt procedure */
  327.     /* Set the original interrupt masks back */
  328.     lock = intLock ();
  329.     IBC_BYTE_WRITE (PIC_IMASK (PIC1_BASE_ADR), intReg1);
  330.     IBC_BYTE_WRITE (PIC_IMASK (PIC2_BASE_ADR), intReg2);
  331.     }
  332. /*******************************************************************************
  333. *
  334. * sysIbcEndOfInt - send EOI(end of interrupt) signal.
  335. *
  336. * This routine is called at the end of the interrupt handler.
  337. *
  338. */
  339. LOCAL void sysIbcEndOfInt (void)
  340.     {
  341.     IBC_BYTE_WRITE (PIC_IACK (PIC1_BASE_ADR), 0x20);
  342.     IBC_BYTE_WRITE (PIC_IACK (PIC2_BASE_ADR), 0x20);
  343.     }
  344. /*******************************************************************************
  345. *
  346. * sysIbcIntLevelSet - set the interrupt mask
  347. *
  348. * This routine masks interrupts from the level of 'intNumber' to 15.
  349. *
  350. * RETURNS: N/A 
  351. */
  352. LOCAL void sysIbcIntLevelSet
  353.     (
  354.     UCHAR  intNumber, /* interrupt level where to mask from */
  355.     UCHAR  pic1Mask, /* state of Pic1 mask at IRQ */
  356.     UCHAR  pic2Mask /* state of Pic2 mask at IRQ */
  357.     )
  358.     {
  359.     pic1Mask |= ibcIRQ2Pic1Mask[intNumber];   /* make new masks */
  360.     pic2Mask |= ibcIRQ2Pic2Mask[intNumber];
  361.     IBC_BYTE_WRITE (PIC_IMASK (PIC1_BASE_ADR), pic1Mask); /* set new masks */
  362.     IBC_BYTE_WRITE (PIC_IMASK (PIC2_BASE_ADR), pic2Mask);
  363.     }