2021-10-11 22:19:34 -03:00

220 lines
5.9 KiB
C

static char sccsid[] = "@(#)13 1.14 src/bos/kernel/ios/intr_init.c, sysios, bos41J, 9511A_all 3/7/95 13:13:10";
/*
* COMPONENT_NAME: (SYSIOS) IO subsystem
*
* FUNCTIONS: intr_init
*
* ORIGINS: 27, 83
*
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
* combined with the aggregated modules for this product)
* SOURCE MATERIALS
* (C) COPYRIGHT International Business Machines Corp. 1988, 1995
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/*
* LEVEL 1, 5 Years Bull Confidential Information
*/
#include <sys/types.h>
#include <sys/intr.h>
#include <sys/syspest.h>
#include <sys/ppda.h>
#include <sys/malloc.h>
#include "interrupt.h"
#include "intr_hw.h"
extern struct i_data i_data;
extern struct ppda ppda[];
extern int soft_int_model;
extern short (*i_lvlmap)[MAX_LVL_PER_PRI];
#ifdef _RS6K
extern int next_poll_grp;
extern ushort buid_map[];
#endif /* _RS6K */
#ifdef _POWER_RS
extern struct intr off_lvlhand;
#endif /* _POWER_RS */
#ifdef _POWER_MP
extern struct intr intmax_lvlhand;
#endif /* _POWER_MP */
/*
* NAME: intr_init
*
* FUNCTION: Initialize interrupt management data structures and define
* off-level interrupt handlers.
*
* EXECUTION ENVIRONMENT:
* This routine is called during system initialization. It must
* be called before any interrupt handlers are defined or any
* interrupts taken.
*
* NOTES:
* This routine must be called before the first interrupt is taken.
*
* This routine is split out of intr.c so that it can be separated
* from the rest of interrupt management and put with other system
* initialization routines. This removes it from the working set
* for normal operation.
*
* This routine does not define all of the system interrupt handlers.
* It is expected that each component will define theirs. For example,
* it is expected that the timer component will define the timer
* interrupt handler and the block I/O component will define the
* I/O done off-level interrupt handler.
*
* RETURN VALUE DESCRIPTION:
* none
*
* EXTERNAL PROCEDURES CALLED:
* i_init
* init_misc
* PPDA
*/
void
intr_init( )
{
int ipri; /* interrupt priority */
int level; /* interrupt level */
int index; /* off-level array index */
int rc; /* i_init return code */
struct ppda *ppda_ptr; /* ptr to ppda */
extern int i_softoff(); /* off-level interrupt handler */
#ifdef _POWER_MP
extern int i_hwassist_int();
extern void ipoll_excl_serv();
extern mpc_msg_t ipoll_mpc_msg;
#endif /* _POWER_MP */
extern void init_misc(); /* machine dependent initialization */
#ifdef _POWER_RS
/*
* Initialize the external interrupt masks that control interrupt
* priority.
*/
#if defined(_POWER_RS1) || defined(_POWER_RSC)
if( __power_set( POWER_RS1 | POWER_RSC )) {
for ( ipri = INTMAX; ipri < NUM_INTR_PRIORITY; ipri++ )
{
i_data.i_pri_map.eim[ipri].eim0 = 0;
i_data.i_pri_map.eim[ipri].eim1 = 0;
}
}
#endif /* _POWER_RS1 || _POWER_RSC */
#ifdef _POWER_RS2
if( __power_rs2() ) {
i_data.i_pri_map.cil[INTMAX] = PRI0_TO_LVL;
i_data.i_pri_map.cil[INTCLASS0] = PRI1_TO_LVL;
i_data.i_pri_map.cil[INTCLASS1] = PRI2_TO_LVL;
i_data.i_pri_map.cil[INTCLASS2] = PRI3_TO_LVL;
i_data.i_pri_map.cil[INTCLASS3] = PRI4_TO_LVL;
i_data.i_pri_map.cil[INTTIMER] = PRI5_TO_LVL;
i_data.i_pri_map.cil[INTOFFL0] = PRI6_TO_LVL;
i_data.i_pri_map.cil[INTOFFL1] = PRI7_TO_LVL;
i_data.i_pri_map.cil[INTOFFL2] = PRI8_TO_LVL;
i_data.i_pri_map.cil[INTOFFL3] = PRI9_TO_LVL;
i_data.i_pri_map.cil[INTIODONE] = PRI10_TO_LVL;
i_data.i_pri_map.cil[INTBASE] = PRI11_TO_LVL;
}
#endif /* _POWER_RS2 */
#endif /* _POWER_RS */
#ifdef _RS6K
/*
* Initialize the buid_map array.
*
* next_poll_grp is basically an index that indicates
* the next group of 16 levels to be allocated out of the
* poll array.
*/
if( __rs6k() ) {
for( ipri=1; ipri<=MAX_BUID; ipri++ ) {
buid_map[ipri] = -1;
}
buid_map[0] = 0;
next_poll_grp = 1;
}
#endif /* _RS6K */
/*
* Initialize the poll array such that there are no interrupt
* handlers defined.
*/
for ( level = 0; level < NUM_INTR_SOURCE; level++ )
{
i_data.i_poll[level].poll = (struct intr *)NULL;
}
/* Set up i_lvlmap[][] memory, used by SW managed model */
i_lvlmap = ( void * )xmalloc(
sizeof(short) * (INTTIMER * MAX_LVL_PER_PRI), 2, pinned_heap);
assert( i_lvlmap != NULL );
for( rc=0; rc<INTTIMER; rc++ ) {
for( index=0; index<MAX_LVL_PER_PRI; index++ ) {
i_lvlmap[rc][index] = -1;
}
}
/* No need for a off level handler in software managed model */
#ifdef _POWER_RS
if( !soft_int_model && __power_rs() ) {
/* Now set up any off-level handler */
off_lvlhand.next = (struct intr *)NULL;
off_lvlhand.handler = i_softoff;
off_lvlhand.bus_type = BUS_PLANAR;
off_lvlhand.flags = INTR_NOT_SHARED | INTR_MPSAFE;
off_lvlhand.level = INT_OFFLVL;
off_lvlhand.priority = INTOFFLVL;
off_lvlhand.bid = 0;
rc = i_init(&off_lvlhand);
assert( rc == INTR_SUCC );
}
#endif /* _POWER_RS */
#ifdef _POWER_MP
if( __rs6k() ) {
intmax_lvlhand.next = (struct intr *)NULL;
intmax_lvlhand.handler = i_hwassist_int;
intmax_lvlhand.bus_type = BUS_PLANAR;
intmax_lvlhand.flags = INTR_NOT_SHARED | INTR_MPSAFE;
intmax_lvlhand.level = INT_MFRR;
intmax_lvlhand.priority = INTMAX;
intmax_lvlhand.bid = 0;
rc = i_init(&intmax_lvlhand);
assert( rc == INTR_SUCC );
if ( __power_mp() )
ipoll_mpc_msg = mpc_register(INTIODONE, ipoll_excl_serv);
}
#endif
/*
* Initialize the machine dependent system interrupt handlers.
*/
init_misc();
#if defined(_RS6K)
if (__rs6k()) {
/*
* If we are on a box with a XIRR, write INTBASE out as the CPPR
* so that interrupts can occur.
*
*/
volatile struct ppcint *intr;
intr = (volatile struct ppcint *)(PPDA->intr);
intr->i_cppr = INTBASE;
__iospace_sync();
}
#endif
}