OpenCores
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 562

Go to most recent revision | 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);
}
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.