URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [powerpc/] [ppcn_60x/] [startup/] [genpvec.c] - Rev 173
Compare with Previous | Blame | View Log
/* * COPYRIGHT (c) 1998 by Radstone Technology * * * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU. * * You are hereby granted permission to use, copy, modify, and distribute * this file, provided that this notice, plus the above copyright notice * and disclaimer, appears in all copies. Radstone Technology will provide * no support for this code. * */ /* genpvec.c * * These routines handle the external exception. Multiple ISRs occur off * of this one interrupt. * * COPYRIGHT (c) 1989-1997. * On-Line Applications Research Corporation (OAR). * Copyright assigned to U.S. Government, 1994. * * The license and distribution terms for this file may in * the file LICENSE in this distribution or at * http://www.OARcorp.com/rtems/license.html. * * $Id: */ #include <bsp.h> #include "chain.h" #include <assert.h> /* * Proto types for this file */ rtems_isr external_exception_ISR ( rtems_vector_number vector /* IN */ ); #define NUM_LIRQ_HANDLERS 20 #define NUM_LIRQ ( MAX_BOARD_IRQS - PPC_IRQ_LAST ) /* * Current 8259 masks */ unsigned8 ucMaster8259Mask; unsigned8 ucSlave8259Mask; /* * Structure to for one of possible multiple interrupt handlers for * a given interrupt. */ typedef struct { Chain_Node Node; rtems_isr_entry handler; /* isr routine */ rtems_vector_number vector; /* vector number */ } EE_ISR_Type; /* Note: The following will not work if we add a method to remove * handlers at a later time. */ EE_ISR_Type ISR_Nodes [NUM_LIRQ_HANDLERS]; rtems_unsigned16 Nodes_Used; Chain_Control ISR_Array [NUM_LIRQ]; void initialize_external_exception_vector() { rtems_isr_entry previous_isr; rtems_status_code status; int i; Nodes_Used = 0; for (i=0; i <NUM_LIRQ; i++) { Chain_Initialize_empty( &ISR_Array[i] ); } /* * Initialise the 8259s */ outport_byte(ISA8259_M_CTRL, 0x11); /* ICW1 */ outport_byte(ISA8259_S_CTRL, 0x11); /* ICW1 */ outport_byte(ISA8259_M_MASK, 0x00); /* ICW2 vectors 0-7 */ outport_byte(ISA8259_S_MASK, 0x08); /* ICW2 vectors 8-15 */ outport_byte(ISA8259_M_MASK, 0x04); /* ICW3 cascade on IRQ2 */ outport_byte(ISA8259_S_MASK, 0x02); /* ICW3 cascade on IRQ2 */ outport_byte(ISA8259_M_MASK, 0x01); /* ICW4 x86 normal EOI */ outport_byte(ISA8259_S_MASK, 0x01); /* ICW4 x86 normal EOI */ /* * Enable IRQ2 cascade and disable all other interrupts */ ucMaster8259Mask=0xfb; ucSlave8259Mask=0xff; outport_byte(ISA8259_M_MASK, ucMaster8259Mask); outport_byte(ISA8259_S_MASK, ucSlave8259Mask); /* * Set up edge/level */ switch(ucSystemType) { case SYS_TYPE_PPC1: { if(ucBoardRevMaj<5) { outport_byte(ISA8259_S_ELCR, ELCRS_INT15_LVL); } else { outport_byte(ISA8259_S_ELCR, ELCRS_INT9_LVL | ELCRS_INT11_LVL | ELCRS_INT14_LVL | ELCRS_INT15_LVL); } outport_byte(ISA8259_M_ELCR, ELCRM_INT5_LVL | ELCRM_INT7_LVL); break; } case SYS_TYPE_PPC1a: { outport_byte(ISA8259_S_ELCR, ELCRS_INT9_LVL | ELCRS_INT11_LVL | ELCRS_INT14_LVL | ELCRS_INT15_LVL); outport_byte(ISA8259_M_ELCR, ELCRM_INT5_LVL); break; } case SYS_TYPE_PPC2: case SYS_TYPE_PPC2a: case SYS_TYPE_PPC4: default: { outport_byte(ISA8259_S_ELCR, ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL | ELCRS_INT14_LVL | ELCRS_INT15_LVL); outport_byte(ISA8259_M_ELCR, ELCRM_INT5_LVL | ELCRM_INT7_LVL); break; } } /* * Install external_exception_ISR () as the handler for * the General Purpose Interrupt. */ status = rtems_interrupt_catch( external_exception_ISR, PPC_IRQ_EXTERNAL, (rtems_isr_entry *) &previous_isr ); } /* * This routine installs one of multiple ISRs for the general purpose * inerrupt. */ void set_EE_vector( rtems_isr_entry handler, /* isr routine */ rtems_vector_number vector /* vector number */ ) { rtems_unsigned16 vec_idx = vector - PPCN_60X_8259_IRQ_BASE; rtems_unsigned32 index; assert (Nodes_Used < NUM_LIRQ_HANDLERS); /* * If we have already installed this handler for this vector, then * just reset it. */ for ( index=0 ; index < Nodes_Used ; index++ ) { if(ISR_Nodes[index].vector == vector && ISR_Nodes[index].handler == handler) { return; } } /* * Doing things in this order makes them more atomic */ Nodes_Used++; index = Nodes_Used - 1; ISR_Nodes[index].handler = handler; ISR_Nodes[index].vector = vector; Chain_Append( &ISR_Array[vec_idx], &ISR_Nodes[index].Node ); /* * Enable the interrupt */ En_Ext_Interrupt(vector); } /* * This interrupt service routine is called for an External Exception. */ rtems_isr external_exception_ISR ( rtems_vector_number vector /* IN */ ) { unsigned16 index; unsigned8 ucISr; EE_ISR_Type *node; index = *((volatile unsigned8 *)IRQ_VECTOR_BASE); /* * check for spurious interrupt */ if(index==7) { /* * OCW3 select IS register */ outport_byte(ISA8259_M_CTRL, 0x0b); /* * Read IS register */ inport_byte(ISA8259_M_CTRL, ucISr); if(!(ucISr & 0x80)) { /* * Spurious interrupt */ return; } } node=(EE_ISR_Type *)ISR_Array[index].first; while(!_Chain_Is_tail(&ISR_Array[index], (Chain_Node *)node)) { (*node->handler)( node->vector ); node = (EE_ISR_Type *)node->Node.next; } /* * Dismiss the interrupt */ if(index&8) { /* * Dismiss the interrupt in Slave first as it * is cascaded */ outport_byte(ISA8259_S_CTRL, NONSPECIFIC_EOI); } /* * Dismiss the interrupt in Master */ outport_byte(ISA8259_M_CTRL, NONSPECIFIC_EOI); } void Dis_Ext_Interrupt(int level) { ISR_Level Irql; level-=PPCN_60X_8259_IRQ_BASE; if(level==2) { /* * Level 2 is for cascade and must not be fiddled with */ return; } /* * Ensure that accesses to the mask are indivisible */ _ISR_Disable(Irql); if(level<8) { /* * Interrupt is handled by Master */ ucMaster8259Mask|=1<<level; outport_byte(ISA8259_M_MASK, ucMaster8259Mask); } else { /* * Interrupt is handled by Slave */ ucSlave8259Mask|=1<<(level-8); outport_byte(ISA8259_S_MASK, ucSlave8259Mask); } _ISR_Enable(Irql); } void En_Ext_Interrupt(int level) { ISR_Level Irql; level-=PPCN_60X_8259_IRQ_BASE; if(level==2) { /* * Level 2 is for cascade and must not be fiddled with */ return; } /* * Ensure that accesses to the mask are indivisible */ _ISR_Disable(Irql); if(level<8) { /* * Interrupt is handled by Master */ ucMaster8259Mask&=~(1<<level); outport_byte(ISA8259_M_MASK, ucMaster8259Mask); } else { /* * Interrupt is handled by Slave */ ucSlave8259Mask&=~(1<<(level-8)); outport_byte(ISA8259_S_MASK, ucSlave8259Mask); } _ISR_Enable(Irql); }