Back to home page

LXR

 
 

    


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

0001 /**
0002  *  @file
0003  *  
0004  *  This file was based upon the powerpc and the i386.
0005  */
0006 
0007 /*
0008  *  COPYRIGHT (c) 1989-2012.
0009  *  On-Line Applications Research Corporation (OAR).
0010  *
0011  *  The license and distribution terms for this file may be
0012  *  found in the file LICENSE in this distribution or at
0013  *  http://www.rtems.org/license/LICENSE.
0014  */
0015 
0016 /*
0017  *  Copyright (C) 1998, 1999 valette@crf.canon.fr
0018  */
0019 
0020 #include <bsp.h>
0021 #include <bsp/irq.h>
0022 #include <bsp/i8259.h>
0023 #include <bsp/pci.h>
0024 #include <bsp/irq-generic.h>
0025 #include <rtems/bspIo.h>
0026 
0027 
0028 #define DEBUG_8259      1
0029 
0030 #define ValidateIrqLine( _irq ) \
0031    if ( ((int)_irq < 0) ||((int)_irq > 16)) return 1;
0032 
0033 /*-------------------------------------------------------------------------+
0034 | Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register.
0035 +--------------------------------------------------------------------------*/
0036 /*
0037  * lower byte is interrupt mask on the master PIC.
0038  * while upper bits are interrupt on the slave PIC.
0039  */
0040 volatile rtems_i8259_masks i8259s_cache = 0xfffb;
0041 
0042 /*-------------------------------------------------------------------------+
0043 |         Function:  BSP_irq_disable_at_i8259s
0044 |      Description: Mask IRQ line in appropriate PIC chip.
0045 | Global Variables: i8259s_cache
0046 |        Arguments: vector_offset - number of IRQ line to mask.
0047 |          Returns: original state or -1 on error.
0048 +--------------------------------------------------------------------------*/
0049 int BSP_irq_disable_at_i8259s    (const rtems_irq_number irqLine)
0050 {
0051   unsigned short        mask;
0052   rtems_interrupt_level level;
0053   int                   rval;
0054 
0055   ValidateIrqLine(irqLine);
0056 
0057   rtems_interrupt_disable(level);
0058 
0059   /* Recalculate the value */
0060   mask = 1 << irqLine;
0061   rval = i8259s_cache & mask ? 0 : 1;
0062   i8259s_cache |= mask;
0063 
0064   /* Determine which chip and write the value. */
0065   if (irqLine < 8) {
0066     simple_out_8(
0067       BSP_8259_BASE_ADDRESS, 
0068       PIC_MASTER_IMR_IO_PORT, 
0069       i8259s_cache & 0xff
0070     );
0071   } else {
0072     simple_out_8(
0073       BSP_8259_BASE_ADDRESS, 
0074       PIC_SLAVE_IMR_IO_PORT, 
0075       ((i8259s_cache & 0xff00) >> 8)
0076     );
0077   }
0078 
0079   rtems_interrupt_enable(level);
0080 
0081   return rval;
0082 }
0083 
0084 /*-------------------------------------------------------------------------+
0085 |         Function:  BSP_irq_enable_at_i8259s
0086 |      Description: Unmask IRQ line in appropriate PIC chip.
0087 | Global Variables: i8259s_cache
0088 |        Arguments: irqLine - number of IRQ line to mask.
0089 |          Returns: Nothing.
0090 +--------------------------------------------------------------------------*/
0091 int BSP_irq_enable_at_i8259s    (const rtems_irq_number irqLine)
0092 {
0093   unsigned short        mask;
0094   rtems_interrupt_level level;
0095   
0096   ValidateIrqLine( irqLine );
0097 
0098   rtems_interrupt_disable(level);
0099 
0100   /* Calculate the value */
0101   mask = ~(1 << irqLine);
0102   i8259s_cache &= mask;
0103 
0104   /* Determine which chip and write the value */
0105   if (irqLine < 8) {
0106     simple_out_8(
0107       BSP_8259_BASE_ADDRESS, 
0108       PIC_MASTER_IMR_IO_PORT, 
0109       i8259s_cache & 0xff
0110     );
0111   } else {
0112     simple_out_8(
0113       BSP_8259_BASE_ADDRESS, 
0114       PIC_SLAVE_IMR_IO_PORT, 
0115       ((i8259s_cache & 0xff00) >> 8)
0116     );
0117   }
0118 
0119   rtems_interrupt_enable(level);
0120 
0121   return 0;
0122 } /* mask_irq */
0123 
0124 
0125 int BSP_irq_enabled_at_i8259s(const rtems_irq_number irqLine)
0126 {
0127   unsigned short mask;
0128 
0129   ValidateIrqLine( irqLine );
0130 
0131   mask = (1 << irqLine);
0132 
0133   return  (~(i8259s_cache & mask));
0134 }
0135 
0136 /*-------------------------------------------------------------------------+
0137 |         Function: BSP_irq_ack_at_i8259s
0138 |      Description: Signal generic End Of Interrupt (EOI) to appropriate PIC.
0139 | Global Variables: None.
0140 |        Arguments: irqLine - number of IRQ line to acknowledge.
0141 |          Returns: Nothing.
0142 +--------------------------------------------------------------------------*/
0143 int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine)
0144 {
0145   if (irqLine >= 8) {
0146     simple_out_8(
0147       BSP_8259_BASE_ADDRESS, 
0148       PIC_MASTER_COMMAND_IO_PORT, 
0149       SLAVE_PIC_EOSI
0150     );
0151     simple_out_8(
0152       BSP_8259_BASE_ADDRESS, 
0153       PIC_SLAVE_COMMAND_IO_PORT, 
0154       (PIC_EOSI | (irqLine - 8))
0155     );
0156   }else {
0157     simple_out_8(
0158       BSP_8259_BASE_ADDRESS, 
0159       PIC_MASTER_COMMAND_IO_PORT, 
0160       (PIC_EOSI | irqLine)
0161     );
0162   }
0163 
0164   return 0;
0165 
0166 } /* ackIRQ */
0167 
0168 void BSP_i8259s_init(void)
0169 {
0170   volatile uint32_t i;
0171 
0172   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xff );
0173   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT,  0xff );
0174   
0175 
0176   /*
0177    * init master 8259 interrupt controller
0178    */
0179 
0180   /* Start init sequence */
0181   simple_out_8(
0182     BSP_8259_BASE_ADDRESS, 
0183     PIC_MASTER_COMMAND_IO_PORT, 
0184     0x11
0185   );
0186   /* Vector base  = 0 */
0187   simple_out_8(
0188     BSP_8259_BASE_ADDRESS, 
0189     PIC_MASTER_IMR_IO_PORT, 
0190     0x00
0191   );
0192 
0193   /* edge tiggered, Cascade (slave) on IRQ2 */
0194   simple_out_8(
0195     BSP_8259_BASE_ADDRESS, 
0196     PIC_MASTER_IMR_IO_PORT, 
0197     0x04
0198   );
0199 
0200   /* Select 8086 mode */
0201   simple_out_8(
0202     BSP_8259_BASE_ADDRESS, 
0203     PIC_MASTER_IMR_IO_PORT, 
0204     0x01
0205   );
0206 
0207   /*
0208    * init slave  interrupt controller
0209    */
0210 
0211   /* Start init sequence */
0212   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT, 0x11); 
0213 
0214   /* Vector base  = 8 */
0215   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x08);
0216 
0217   /* edge triggered, Cascade (slave) on IRQ2 */
0218   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x02);
0219 
0220   /* Select 8086 mode */
0221   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x01); 
0222 
0223   /* Mask all except cascade */
0224   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB); 
0225 
0226   /* Mask all */
0227   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); 
0228 
0229   /*
0230    * Enable all interrupts in debug mode.
0231    */
0232 
0233   if ( DEBUG_8259 ) {
0234      i8259s_cache = 0x0101;
0235   }
0236 
0237   simple_out_8(
0238     BSP_8259_BASE_ADDRESS, 
0239     PIC_MASTER_IMR_IO_PORT, 
0240     i8259s_cache & 0xff
0241   );
0242   simple_out_8(
0243     BSP_8259_BASE_ADDRESS, 
0244     PIC_SLAVE_IMR_IO_PORT, 
0245     ((i8259s_cache & 0xff00) >> 8)
0246   );
0247 
0248   for (i=0; i<10000; i++);
0249 }
0250 
0251 #define PCI__GEN(bus, off, num)     (((off)^((bus) << 7))+((num) << 4))
0252 #define PCI_INTR_ACK(bus)       PCI__GEN(bus, 0x0c34, 0)
0253 
0254 static volatile uint8_t  master;
0255 static volatile uint8_t  slave;
0256 
0257 void bsp_show_interrupt_regs(void);
0258 void bsp_show_interrupt_regs() {
0259   unsigned int sr;
0260   unsigned int cause;
0261   unsigned int pending;
0262 
0263   mips_get_sr( sr ); 
0264   mips_get_cause( cause );
0265   pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT;
0266 
0267   master = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_COMMAND_IO_PORT);
0268   slave  = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT);
0269 
0270   printk("sr: 0x%x cause: 0x%x pending: 0x%x  master: 0x%x slave: 0x%x\n", 
0271     sr, cause, pending, master, slave 
0272   );
0273 }
0274 
0275 int BSP_i8259s_int_process()
0276 {
0277   uint8_t           irq;
0278   volatile uint32_t temp;
0279 
0280   /* Get the Interrupt */
0281   irq = simple_in_le32(BSP_PCI_BASE_ADDRESS, PCI_INTR_ACK(0) );
0282 
0283   /*
0284    *  Mask interrupts
0285    *   + Mask all except cascade on master
0286    *   + Mask all on slave
0287    */
0288   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB);
0289   simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF);
0290 
0291   /* Call the Handler */
0292   temp = irq + MALTA_SB_IRQ_0;
0293   bsp_interrupt_handler_dispatch( temp );
0294 
0295   /* Reset the interrupt on the 8259 either the master or the slave chip */
0296   if (irq & 8) {
0297     temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT);
0298 
0299     /* Mask all */
0300     simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); 
0301     simple_out_8(
0302       BSP_8259_BASE_ADDRESS, 
0303       PIC_SLAVE_COMMAND_IO_PORT, 
0304       (PIC_EOSI + (irq&7))
0305     );
0306     simple_out_8(
0307       BSP_8259_BASE_ADDRESS, 
0308       PIC_MASTER_COMMAND_IO_PORT, 
0309       SLAVE_PIC_EOSI 
0310     );
0311   } else {
0312     temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT);
0313     /* Mask all except cascade */
0314     simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB);
0315     simple_out_8(
0316       BSP_8259_BASE_ADDRESS, 
0317       PIC_MASTER_COMMAND_IO_PORT, 
0318       (PIC_EOSI+irq)
0319     );
0320   }
0321 
0322   /* Restore the interrupts */
0323   simple_out_8(BSP_8259_BASE_ADDRESS,PIC_MASTER_IMR_IO_PORT,i8259s_cache&0xff);
0324   simple_out_8(
0325     BSP_8259_BASE_ADDRESS, 
0326     PIC_SLAVE_IMR_IO_PORT, 
0327     ((i8259s_cache & 0xff00) >> 8)
0328   );
0329 
0330   return 0;
0331 }