Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  *
0003  *  This file contains the i8259/openpic-specific implementation of
0004  *  the function described in irq.h
0005  *
0006  *  Copyright (C) 1998, 1999 valette@crf.canon.fr
0007  *
0008  *  The license and distribution terms for this file may be
0009  *  found in the file LICENSE in this distribution or at
0010  *  http://www.rtems.org/license/LICENSE.
0011  */
0012 
0013 #include <stdlib.h>
0014 
0015 #include <bsp.h>
0016 #include <bsp/irq.h>
0017 #include <bsp/irq_supp.h>
0018 #include <bsp/irq-generic.h>
0019 #ifndef BSP_HAS_NO_VME
0020 #include <bsp/VMEConfig.h>
0021 #endif
0022 #if BSP_PCI_IRQ_NUMBER > 0
0023 #include <bsp/openpic.h>
0024 #endif
0025 #include <libcpu/io.h>
0026 #include <bsp/vectors.h>
0027 #include <stdlib.h>
0028 
0029 #include <rtems/bspIo.h> /* for printk */
0030 
0031 #ifndef qemu
0032 #define RAVEN_INTR_ACK_REG 0xfeff0030
0033 #else
0034 #define RAVEN_INTR_ACK_REG 0xbffffff0
0035 #endif
0036 
0037 #if BSP_ISA_IRQ_NUMBER > 0
0038 /*
0039  * pointer to the mask representing the additionnal irq vectors
0040  * that must be disabled when a particular entry is activated.
0041  * They will be dynamically computed from the priority table given
0042  * in BSP_rtems_irq_mngt_set();
0043  * CAUTION : this table is accessed directly by interrupt routine
0044  *       prologue.
0045  */
0046 rtems_i8259_masks   irq_mask_or_tbl[BSP_IRQ_NUMBER];
0047 #endif
0048 
0049 /*
0050  * default handler connected on each irq after bsp initialization
0051  */
0052 static rtems_irq_connect_data   default_rtems_entry;
0053 
0054 static rtems_irq_connect_data*      rtems_hdl_tbl;
0055 
0056 #if BSP_ISA_IRQ_NUMBER > 0
0057 /*
0058  * Check if IRQ is an ISA IRQ
0059  */
0060 static inline int is_isa_irq(const rtems_irq_number irqLine)
0061 {
0062   return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &&
0063       ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)
0064      );
0065 }
0066 #endif
0067 
0068 #if BSP_PCI_IRQ_NUMBER > 0
0069 /*
0070  * Check if IRQ is an OPENPIC IRQ
0071  */
0072 static inline int is_pci_irq(const rtems_irq_number irqLine)
0073 {
0074   return OpenPIC && (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &&
0075       ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)
0076      );
0077 }
0078 #endif
0079 
0080 /*
0081  * ------------------------ RTEMS Irq helper functions ----------------
0082  */
0083 
0084 #if BSP_ISA_IRQ_NUMBER > 0
0085 /*
0086  * Caution : this function assumes the variable "*config"
0087  * is already set and that the tables it contains are still valid
0088  * and accessible.
0089  */
0090 static void compute_i8259_masks_from_prio (rtems_irq_global_settings* config)
0091 {
0092   int i;
0093   int j;
0094   /*
0095    * Always mask at least current interrupt to prevent re-entrance
0096    */
0097   for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
0098     * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
0099     for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) {
0100       /*
0101        * Mask interrupts at i8259 level that have a lower priority
0102        */
0103       if (config->irqPrioTbl [i] > config->irqPrioTbl [j]) {
0104     * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
0105       }
0106     }
0107   }
0108 }
0109 #endif
0110 
0111 void
0112 BSP_enable_irq_at_pic(const rtems_irq_number name)
0113 {
0114 #if BSP_ISA_IRQ_NUMBER > 0
0115     if (is_isa_irq(name)) {
0116       /*
0117        * Enable interrupt at PIC level
0118        */
0119       BSP_irq_enable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET);
0120     }
0121 #endif
0122 
0123 #if BSP_PCI_IRQ_NUMBER > 0
0124     if (is_pci_irq(name)) {
0125       /*
0126        * Enable interrupt at OPENPIC level
0127        */
0128       openpic_enable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET);
0129     }
0130 #endif
0131 }
0132 
0133 int
0134 BSP_disable_irq_at_pic(const rtems_irq_number name)
0135 {
0136 #if BSP_ISA_IRQ_NUMBER > 0
0137     if (is_isa_irq(name)) {
0138       /*
0139        * disable interrupt at PIC level
0140        */
0141       return BSP_irq_disable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET);
0142     }
0143 #endif
0144 #if BSP_PCI_IRQ_NUMBER > 0
0145     if (is_pci_irq(name)) {
0146       /*
0147        * disable interrupt at OPENPIC level
0148        */
0149       return openpic_disable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET);
0150     }
0151 #endif
0152     return -1;
0153 }
0154 
0155 /*
0156  * RTEMS Global Interrupt Handler Management Routines
0157  */
0158 int BSP_setup_the_pic(rtems_irq_global_settings* config)
0159 {
0160     int i;
0161    /*
0162     * Store various code accelerators
0163     */
0164     default_rtems_entry = config->defaultEntry;
0165     rtems_hdl_tbl       = config->irqHdlTbl;
0166 
0167     /*
0168      * set up internal tables used by rtems interrupt prologue
0169      */
0170 
0171 #if BSP_ISA_IRQ_NUMBER > 0
0172     /*
0173      * start with ISA IRQ
0174      */
0175     compute_i8259_masks_from_prio (config);
0176 
0177     for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {
0178       if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
0179          BSP_irq_enable_at_i8259s (i);
0180       }
0181       else {
0182          BSP_irq_disable_at_i8259s (i);
0183       }
0184     }
0185 
0186     if ( BSP_ISA_IRQ_NUMBER > 0 ) {
0187         /*
0188          * must enable slave pic anyway
0189          */
0190         BSP_irq_enable_at_i8259s (2);
0191     }
0192 #endif
0193 
0194 #if BSP_PCI_IRQ_NUMBER > 0
0195     if ( ! OpenPIC )
0196         return 1;
0197     /*
0198      * continue with PCI IRQ
0199      */
0200     for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) {
0201       /*
0202        * Note that openpic_set_priority() sets the TASK priority of the PIC
0203        */
0204       openpic_set_source_priority(i - BSP_PCI_IRQ_LOWEST_OFFSET,
0205                   config->irqPrioTbl[i]);
0206       if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
0207          openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
0208       }
0209       else {
0210          openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET);
0211       }
0212     }
0213 
0214 #ifdef BSP_PCI_ISA_BRIDGE_IRQ
0215     /*
0216      * Must enable PCI/ISA bridge IRQ
0217      */
0218     openpic_enable_irq (BSP_PCI_ISA_BRIDGE_IRQ - BSP_PCI_IRQ_LOWEST_OFFSET);
0219 #endif
0220 #endif
0221 
0222     return 1;
0223 }
0224 
0225 int _BSP_vme_bridge_irq = -1;
0226 
0227 unsigned BSP_spuriousIntr = 0;
0228 
0229 /*
0230  * High level IRQ handler called from shared_raw_irq_code_entry
0231  */
0232 int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum)
0233 {
0234   register unsigned int irq;
0235 #if BSP_ISA_IRQ_NUMBER > 0
0236   register unsigned isaIntr;                  /* boolean */
0237   register unsigned oldMask = 0;          /* old isa pic masks */
0238 #endif
0239 
0240   if (excNum == ASM_DEC_VECTOR) {
0241 #ifdef BSP_POWERPC_IRQ_GENERIC_SUPPORT
0242     bsp_interrupt_handler_dispatch(BSP_DECREMENTER);
0243 #else
0244     bsp_irq_dispatch_list(rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_entry.hdl);
0245 #endif
0246     return 0;
0247   }
0248 
0249 #if BSP_PCI_IRQ_NUMBER > 0
0250   if ( OpenPIC ) {
0251     irq = openpic_irq(0);
0252     if (irq == OPENPIC_VEC_SPURIOUS) {
0253       ++BSP_spuriousIntr;
0254       return 0;
0255     }
0256 
0257     /* some BSPs might want to use a different numbering... */
0258     irq = irq - OPENPIC_VEC_SOURCE + BSP_PCI_IRQ_LOWEST_OFFSET;
0259   } else {
0260 #if BSP_ISA_IRQ_NUMBER > 0
0261 #ifdef BSP_PCI_ISA_BRIDGE_IRQ
0262     irq = BSP_PCI_ISA_BRIDGE_IRQ;
0263 #else
0264 #error "Configuration Error -- BSP with ISA + PCI IRQs MUST define BSP_PCI_ISA_BRIDGE_IRQ"
0265 #endif
0266 #else
0267     rtems_panic("MUST have an OpenPIC if BSP has PCI IRQs but no ISA IRQs");
0268     /* rtems_panic() never returns but the 'return' statement silences
0269      * a compiler warning about 'irq' possibly being used w/o initialization.
0270      */
0271     return -1;
0272 #endif
0273   }
0274 #endif
0275 
0276 #if BSP_ISA_IRQ_NUMBER > 0
0277 #ifdef BSP_PCI_ISA_BRIDGE_IRQ
0278 #if 0 == BSP_PCI_IRQ_NUMBER
0279 #error "Configuration Error -- BSP w/o PCI IRQs MUST NOT define BSP_PCI_ISA_BRIDGE_IRQ"
0280 #endif
0281   isaIntr = (irq == BSP_PCI_ISA_BRIDGE_IRQ);
0282 #else
0283   isaIntr = 1;
0284 #endif
0285   if (isaIntr)  {
0286     /*
0287      * Acknowledge and read 8259 vector
0288      */
0289     irq = (unsigned int) (*(unsigned char *) RAVEN_INTR_ACK_REG);
0290     /*
0291      * store current PIC mask
0292      */
0293     oldMask = BSP_irq_suspend_i8259s(irq_mask_or_tbl [irq]);
0294     BSP_irq_ack_at_i8259s (irq);
0295 #if BSP_PCI_IRQ_NUMBER > 0
0296     if ( OpenPIC )
0297       openpic_eoi(0);
0298 #endif
0299   }
0300 #endif
0301 
0302   /* dispatch handlers */
0303 #ifdef BSP_POWERPC_IRQ_GENERIC_SUPPORT
0304   bsp_interrupt_handler_dispatch(irq);
0305 #else
0306   bsp_irq_dispatch_list(rtems_hdl_tbl, irq, default_rtems_entry.hdl);
0307 #endif
0308 
0309 #if BSP_ISA_IRQ_NUMBER > 0
0310   if (isaIntr)  {
0311     BSP_irq_resume_i8259s(oldMask);
0312   }
0313   else
0314 #endif
0315   {
0316 #if BSP_PCI_IRQ_NUMBER > 0
0317 #ifdef BSP_PCI_VME_DRIVER_DOES_EOI
0318     /* leave it to the VME bridge driver to do EOI, so
0319      * it can re-enable the openpic while handling
0320      * VME interrupts (-> VME priorities in software)
0321      */
0322     if (_BSP_vme_bridge_irq != irq && OpenPIC)
0323 #endif
0324             openpic_eoi(0);
0325 #else
0326     do {} while (0);
0327 #endif
0328   }
0329   return 0;
0330 }