746 lines
22 KiB
C
746 lines
22 KiB
C
//#pragma comment(exestr, "$Header: /usr4/winnt/SOURCES/halpcims/src/hal/halsnipm/mips/RCS/mpagent.c,v 1.7 1996/02/23 17:55:12 pierre Exp $")
|
||
|
||
/*++
|
||
|
||
Copyright (c) 1993-94 Siemens Nixdorf Informationssysteme AG
|
||
Copyright (c) 1991 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
mpagent.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the routines dealing with the SNI MP Agent on
|
||
SNI system.
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
#include "MPagent.h"
|
||
|
||
extern VOID
|
||
KeUpdateRunTime(
|
||
IN struct _KTRAP_FRAME *TrapFrame
|
||
);
|
||
|
||
|
||
VOID
|
||
HalpInitMPAgent(
|
||
IN ULONG Number
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the MutiProcessor_Agent chipset:
|
||
- reset an eventual MP_Agent fatal error,
|
||
- enable message passing (send/receive),
|
||
- fix routage for internal IT -> external IT,
|
||
- enable the internal interrupts,
|
||
- fix the mask for wanted external interrupts,
|
||
- disable Low Process Priority mode for
|
||
external interrupts,
|
||
- enable cache replace operator and update the
|
||
'cache_rpl_buffer' global variable with a KSEG0
|
||
4 Mb reserved address.
|
||
|
||
Arguments:
|
||
|
||
Number : Logical number of the processor to be initialised
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
|
||
ULONG reg;
|
||
|
||
|
||
|
||
//
|
||
// set up the snooper register
|
||
//
|
||
|
||
reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
|
||
reg |= (MPA_ENRCVMESS | /* enable message receiving */
|
||
MPA_RSTSNPERR | /* reset an eventual old MP_Agent fatal error */
|
||
MPA_ENLINK | /* enable read and link command */
|
||
MPA_ENCOHREQ | /* enable coherency on the MP bus for this agent */
|
||
0); /* keep other fields */
|
||
WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
|
||
|
||
// RM300 with mono-processors boards with mp-agent can be configured with 1Mb cache,
|
||
// but the MP-agent tag RAM can be configured with 4Mb or 2MB. So we disable the MPbus error.
|
||
// (With monoprocessor machine the MP-agent tag ram is not useful at all ...)
|
||
|
||
if ((HalpIsMulti) || (HalpIsTowerPci))
|
||
reg &= ~(MPA_RSTSNPERR); /* enable new interrupt for MP_Agent fatal error */
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->snooper), reg);
|
||
|
||
|
||
//
|
||
// cpu1reg register
|
||
//
|
||
|
||
reg = READ_REGISTER_ULONG(&(mpagent->cpuda1reg)); /* read the current value */
|
||
reg &= ~(MPA_ENDIRECT | /* disable LPP mechanism */
|
||
MPA_ENTESTIT | /* disable interrupt test mode (interrupts from MPBus) */
|
||
MPA_SELITI_MASK | /* reset old internal interrupt routage */
|
||
0); /* keep other fields */
|
||
|
||
reg |= MPA_SELITI_SR_IP7; /* send internal interrupts on external interrupt SR_IP7*/
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpuda1reg), reg);
|
||
|
||
//
|
||
// cpureg register
|
||
//
|
||
|
||
reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
|
||
reg &= ~(MPA_ENINT_MASK | /* reset old values for interrupts */
|
||
MPA_INTCONF_MASK| /* force falling edge for all interrupts */
|
||
MPA_ENSHARED | /* don't put optimal mode for KERNEL */
|
||
0);
|
||
reg |= (MPA_ENSENDMSG | /* enable sending message */
|
||
MPA_ENINT_MPBERR | /* enable internal interrupt for MP_Agent fatal error */
|
||
MPA_ENINT_ITMSG1 | /* enable internal interrupt for message1 register */
|
||
MPA_ENINT_ITMSG2 | /* enable internal interrupt for message2 register */
|
||
MPA_ENINT_ITMSG3 | /* enable internal interrupt for message3 register */
|
||
MPA_INTMSK | /* mask sent during external request stage */
|
||
0); /* keep other fields */
|
||
|
||
//
|
||
// external Interrupts routing in the MP Agent
|
||
//
|
||
|
||
// pci tower -> force raising edges for all interrupts
|
||
|
||
if (HalpIsTowerPci) reg |= MPA_INTCONF_MASK;
|
||
|
||
// pci multi-processor machines => interrupts are centralized.
|
||
|
||
if (Number == 0) reg |= MPA_ENINT_SR_IP3; // device interrupts are only processed by bootcpu.
|
||
// Timer processor 1 : IP5 for RM300 - IP6 for RM400
|
||
|
||
if (Number == 1)
|
||
if (!HalpIsTowerPci) reg |= MPA_ENINT_SR_IP5;
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
|
||
|
||
//
|
||
// clear pending interrupts by reading of the message registers
|
||
//
|
||
|
||
reg = READ_REGISTER_ULONG(&(mpagent->datamsg1));
|
||
reg = READ_REGISTER_ULONG(&(mpagent->datamsg2));
|
||
reg = READ_REGISTER_ULONG(&(mpagent->datamsg3));
|
||
|
||
// Modif PS 20 June -> Don't use the operator with ASIC PCI -> BUGBUG
|
||
|
||
if (HalpMpaCacheReplace == MPAGENT_RESERVED | KSEG0_BASE) {
|
||
reg = ((MPAGENT_RESERVED & // put the reserved physical address (4Mb long)
|
||
MPA_OP_ADDR_MASK) |
|
||
MPA_OP_ENABLE); // enable the operator
|
||
} else {
|
||
reg = 0;
|
||
}
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->mem_operator), reg); // for all procs (done for proc 0 in xxcache)
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
HalpInitMAUIMPAgent(
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes the MutiProcessor_Agent chipset:
|
||
- enable MAUI interrupt on the current processor
|
||
|
||
Arguments:
|
||
|
||
None
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
|
||
ULONG reg;
|
||
|
||
//
|
||
// cpureg register
|
||
//
|
||
|
||
reg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
|
||
|
||
reg |= MPA_ENINT_SR_IP6;
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), reg);
|
||
}
|
||
|
||
|
||
VOID
|
||
HalRequestIpi(
|
||
IN ULONG CpuMask
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine requests an interprocessor interrupt on a set of processors.
|
||
That is done by using the message passing facility of the MPagent.
|
||
|
||
N.B. This routine must ensure that the interrupt is posted at the target
|
||
processor(s) before returning.
|
||
|
||
Arguments:
|
||
|
||
Mask - Supplies the set of processors that are sent an interprocessor
|
||
interrupt.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ULONG physmask, cpt;
|
||
PRESTART_BLOCK NextRestartBlock;
|
||
|
||
// CpuMask is a logical mask. We must use a mask with the physical
|
||
// numbers of cpus to communicate with the MP_Agent.
|
||
|
||
physmask = 0;cpt = 0;
|
||
NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
|
||
while (NextRestartBlock != NULL) {
|
||
|
||
if (CpuMask & ( 1 << cpt)) {
|
||
physmask = (1 << (NextRestartBlock->ProcessorId));
|
||
HalpSendIpi(physmask,MPA_KERNEL_MESSAGE);
|
||
}
|
||
++cpt ; NextRestartBlock = NextRestartBlock->NextRestartBlock;
|
||
}
|
||
|
||
}
|
||
|
||
VOID
|
||
HalpRequestIpi(
|
||
IN ULONG CpuMask,
|
||
IN ULONG msg_data
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine requests an interprocessor interrupt on a set of processors.
|
||
That is done by using the message passing facility of the MPagent.
|
||
|
||
N.B. This routine must ensure that the interrupt is posted at the target
|
||
processor(s) before returning.
|
||
|
||
Arguments:
|
||
|
||
Mask - Supplies the set of processors that are sent an interprocessor
|
||
interrupt.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
ULONG physmask, cpt;
|
||
PRESTART_BLOCK NextRestartBlock;
|
||
|
||
// CpuMask is a logical mask. We must use a mask with the physical
|
||
// numbers of cpus to communicate with the MP_Agent.
|
||
|
||
physmask = 0;cpt = 0;
|
||
NextRestartBlock = SYSTEM_BLOCK->RestartBlock;
|
||
while (NextRestartBlock != NULL) {
|
||
|
||
if (CpuMask & ( 1 << cpt)) {
|
||
physmask = (1 << (NextRestartBlock->ProcessorId));
|
||
HalpSendIpi(physmask,msg_data);
|
||
}
|
||
++cpt ; NextRestartBlock = NextRestartBlock->NextRestartBlock;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
HalpSendIpi(
|
||
IN ULONG pcpumask,
|
||
IN ULONG msg_data
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine sends an interprocessor interrupt on a set of processors.
|
||
That is done by using the message passing facility of the MPagent.
|
||
|
||
N.B. This routine must ensure that the interrupt is posted at the target
|
||
processor(s) before returning.
|
||
|
||
Arguments:
|
||
|
||
pcpumask - Supplies the set of processors that are sent an interprocessor
|
||
interrupt. It contains physical numbers.
|
||
|
||
msg_data _ Supplies the kind of message to be send : kernel demand or HAL internal demand.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
|
||
KIRQL OldIrql;
|
||
LONG msg_retries, watchdog;
|
||
ULONG msg_address, msg_status, itpend;
|
||
|
||
|
||
if (!pcpumask || !HalpIsMulti) {
|
||
|
||
return;
|
||
|
||
}
|
||
|
||
//
|
||
// Raise IRQL to ??? level.
|
||
//
|
||
|
||
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
|
||
|
||
//
|
||
// form the Message Address register (Message register 1 / 2, CPUMask)
|
||
// The SNI MP Agent supports up to 4 CPU's
|
||
//
|
||
|
||
if (msg_data ==MPA_TIMER_MESSAGE )
|
||
msg_address = (pcpumask & MPA_CPUTARGET_MASK) | MPA_REGTARGET_MSG2;
|
||
else
|
||
msg_address = (pcpumask & MPA_CPUTARGET_MASK) | MPA_REGTARGET_MSG1;
|
||
|
||
msg_data = ((msg_data << 24) | (pcpumask & MPA_CPUTARGET_MASK));
|
||
|
||
msg_retries = MPA_MSG_RETRY;
|
||
|
||
/*
|
||
* Go on, just do it.
|
||
* If at first you don't succeed, then try, try and try again...
|
||
*/
|
||
|
||
do {
|
||
|
||
watchdog = 10;
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->msgaddress), msg_address);
|
||
WRITE_REGISTER_ULONG(&(mpagent->msgdata), msg_data);
|
||
|
||
/*
|
||
* so, what happened? poll either until we know or the watchdog counter runs out
|
||
*/
|
||
do {
|
||
|
||
KeStallExecutionProcessor(5);
|
||
|
||
//
|
||
// read the message status register
|
||
//
|
||
msg_status = READ_REGISTER_ULONG(&(mpagent->msgstatus));
|
||
|
||
} while (((msg_status & MPA_VALSTAT) == 0) && watchdog--);
|
||
|
||
|
||
// KeLowerIrql(OldIrql);
|
||
|
||
|
||
if ((msg_status & MPA_VALSTAT) != MPA_VALSTAT) {
|
||
|
||
|
||
KeStallExecutionProcessor(100);
|
||
// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
continue;
|
||
|
||
} else {
|
||
|
||
//
|
||
// okay, we have a Valid status bit
|
||
// so test of busy
|
||
|
||
if ((msg_status & MPA_ERRMSG) == 0) {
|
||
|
||
//
|
||
// all is fine
|
||
//
|
||
KeLowerIrql(OldIrql);
|
||
return;
|
||
|
||
} else {
|
||
|
||
// we have to verify that it is not a MPA_RETRY error.
|
||
|
||
itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* first read the interrupt pending MP_Agent register */
|
||
|
||
if (itpend & MPA_INTN_MPBERR) {
|
||
|
||
ULONG snooper, cpureg, tmp ;
|
||
|
||
cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
|
||
cpureg &= ~(MPA_ENINT_MPBERR /* disable interrupt for MP_Agent fatal error */
|
||
); /* keep other fields */
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
|
||
snooper = READ_REGISTER_ULONG(&(mpagent->snooper)); // read the current snooper register value/
|
||
|
||
tmp = READ_REGISTER_ULONG(&(mpagent->snpadreg)); /* read the current value */
|
||
snooper |= MPA_RSTSNPERR; /* reset this MP_Agent fatal error */
|
||
WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
|
||
|
||
if ((snooper & MPA_MSEQERR == MPA_RETRYERR) || (snooper & MPA_MSEQERR ==0)) {
|
||
snooper &= ~(MPA_RSTSNPERR); /* stop reseting this MP_Agent fatal error */
|
||
WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
|
||
cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
|
||
cpureg |= (MPA_ENINT_MPBERR); /* enable interrupt for MP_Agent fatal error */
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
|
||
|
||
}
|
||
}
|
||
|
||
// msg_retries = MPA_MSG_RETRY;
|
||
KeStallExecutionProcessor(100);
|
||
// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
|
||
if (itpend & MPA_INTN_MPBERR) {
|
||
continue;
|
||
} else {
|
||
KeLowerIrql(OldIrql);
|
||
return;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
// KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
||
KeStallExecutionProcessor(10);
|
||
|
||
} while (--msg_retries); /* message aborted, try again */
|
||
|
||
KeLowerIrql(OldIrql);
|
||
return;
|
||
|
||
}
|
||
|
||
|
||
VOID
|
||
HalpProcessIpi(
|
||
IN struct _KTRAP_FRAME *TrapFrame
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is entered as the result of an IP5 interrupt. This function
|
||
will looks at the MPagent to see if an IPI has just occurred.
|
||
|
||
Arguments:
|
||
|
||
None.
|
||
|
||
Return Value:
|
||
|
||
|
||
--*/
|
||
{
|
||
ULONG itpend, msg_data;
|
||
|
||
itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* first read the interrupt pending MP_Agent register */
|
||
|
||
if (itpend & (MPA_INTN_ITMSG1 | MPA_INTN_ITMSG2)) {
|
||
|
||
//
|
||
// reading the message register clears the interrupt from the MP Agent
|
||
//
|
||
|
||
if (itpend & MPA_INTN_ITMSG1) {
|
||
msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg1)) >> 24);
|
||
if (msg_data == MPA_KERNEL_MESSAGE) {
|
||
KeIpiInterrupt(TrapFrame);
|
||
} else {
|
||
// remove this processor from the list of active processors
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->ActiveProcessor[PCR->Number]=0;
|
||
if (PCR->Number) {
|
||
|
||
// call a firmware funtion to stop slave cpu's which will break the caches
|
||
|
||
((SNI_PRIVATE_VECTOR *)(SYSTEM_BLOCK->VendorVector))->reinit_slave();
|
||
|
||
} else {
|
||
|
||
HalpBootCpuRestart();
|
||
}
|
||
}
|
||
}
|
||
|
||
if (itpend & MPA_INTN_ITMSG2) {
|
||
msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg2)) >> 24);
|
||
KeUpdateRunTime(TrapFrame);
|
||
}
|
||
|
||
HalpCheckSpuriousInt(0);
|
||
|
||
return ;
|
||
}
|
||
|
||
if ((itpend & MPA_INTN_INT_MASK) == 0) {
|
||
|
||
ULONG snooper = READ_REGISTER_ULONG(&(mpagent->snooper));
|
||
|
||
//
|
||
// None of the MP Agent internal Interrupts was pending --> just return
|
||
//
|
||
|
||
HalpCheckSpuriousInt(0);
|
||
|
||
|
||
return ;
|
||
}
|
||
|
||
if (itpend & MPA_INTN_MPBERR) {
|
||
|
||
//
|
||
// Fatal Error
|
||
//
|
||
|
||
ULONG snooper, cpureg, tmp ;
|
||
|
||
cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
|
||
cpureg &= ~(MPA_ENINT_MPBERR /* disable interrupt for MP_Agent fatal error */
|
||
); /* keep other fields */
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
|
||
snooper = READ_REGISTER_ULONG(&(mpagent->snooper)); // read the current snooper register value/
|
||
|
||
tmp = READ_REGISTER_ULONG(&(mpagent->snpadreg)); /* read the current value */
|
||
snooper |= MPA_RSTSNPERR; /* reset this MP_Agent fatal error */
|
||
WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
|
||
|
||
if ((snooper & MPA_MSEQERR == MPA_RETRYERR) || (snooper & MPA_MSEQERR ==0)) {
|
||
snooper &= ~(MPA_RSTSNPERR); /* stop reseting this MP_Agent fatal error */
|
||
WRITE_REGISTER_ULONG(&(mpagent->snooper), snooper); /* write the new value in the MP_Agent register */
|
||
cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read the current value */
|
||
cpureg |= (MPA_ENINT_MPBERR); /* enable interrupt for MP_Agent fatal error */
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // write the new value in the MP_Agent register /
|
||
|
||
} else {
|
||
#if DBG
|
||
DebugPrint(("MP_Agent fatal error : adresse=0x%x snooper=0x%x\n",tmp,snooper));
|
||
DbgBreakPoint();
|
||
#else
|
||
HalpDisableInterrupts(); // for the MATROX boards...
|
||
HalpColumn = 0;HalpRow = 0; // if we already were in VGA mode
|
||
HalDisplayString("\n");
|
||
HalpClearVGADisplay();
|
||
HalpBugCheckNumber = 0;
|
||
HalDisplayString(HalpBugCheckMessage[0]); // "MP_Agent fatal error\n"
|
||
HalpKeBugCheckEx(NMI_HARDWARE_FAILURE,HalpBugCheckNumber,snooper,tmp,0);
|
||
#endif
|
||
|
||
}
|
||
|
||
HalpCheckSpuriousInt(0);
|
||
|
||
return ;
|
||
}
|
||
|
||
if (itpend & MPA_INTN_ITMSG3) {
|
||
|
||
|
||
//
|
||
// reading the message register clears the interrupt from the MP Agent
|
||
//
|
||
|
||
msg_data = (READ_REGISTER_ULONG(&(mpagent->datamsg3)) >> 24);
|
||
HalpCheckSpuriousInt(0);
|
||
|
||
return ;
|
||
}
|
||
}
|
||
|
||
ULONG
|
||
HalpGetMyAgent(
|
||
VOID
|
||
)
|
||
{
|
||
ULONG reg;
|
||
reg = READ_REGISTER_ULONG(&(mpagent->snooper)); /* read the current value */
|
||
return( (reg & MPA_ADAGT_MASK) >> MPA_ADAGT_SHIFT);
|
||
}
|
||
|
||
|
||
|
||
/*
|
||
* ======================================================================
|
||
*
|
||
* NAME: mpa_check_spurious_intr
|
||
*
|
||
* PURPOSE: Fix a bug in the MP_Agent which sometimes make a bad
|
||
* update of the cause register.
|
||
*
|
||
* PARAMETERS: none
|
||
*
|
||
* RETURNS: = 0 no possible spurious interrupt
|
||
* 1 possible spurious interrupt
|
||
*
|
||
* ======================================================================
|
||
*/
|
||
BOOLEAN HalpCheckSpuriousInt(ULONG mask)
|
||
{
|
||
|
||
ULONG itpend, causeit, pending;
|
||
ULONG cpureg, tempreg, reg;
|
||
|
||
if ( HalpProcessorId != MPAGENT) {
|
||
return 0;
|
||
}
|
||
|
||
|
||
|
||
itpend = READ_REGISTER_ULONG(&(mpagent->itpend)); /* read the interrupt pending MP_Agent register */
|
||
|
||
causeit = (itpend & MPA_OINTN_MASKGEN) >> MPA_OINTN_SHIFT;
|
||
pending = (itpend & MPA_INTN_MASKGEN );
|
||
|
||
if (causeit != pending) {
|
||
|
||
/*
|
||
* Need a second filter for pending interrupt which don't take care
|
||
* of real enabled interrupt mask of cpureg.
|
||
*/
|
||
cpureg = READ_REGISTER_ULONG(&(mpagent->cpureg)); /* read interrupt enable mask for this cpu */
|
||
|
||
if (PCR->Prcb->Number == 0) {
|
||
if (HalpIsTowerPci && HalpIsMulti == 0)
|
||
pending &= (
|
||
((cpureg & (MPA_ENINT_SR_IP3 | MPA_ENINT_SR_IP6 |
|
||
MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
|
||
|
|
||
((cpureg & (MPA_ENINT_ITMSG1 |
|
||
MPA_ENINT_ITMSG2 |
|
||
MPA_ENINT_ITMSG3 |
|
||
MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
|
||
);
|
||
else
|
||
pending &= (
|
||
((cpureg & (MPA_ENINT_SR_IP3 |
|
||
MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
|
||
|
|
||
((cpureg & (MPA_ENINT_ITMSG1 |
|
||
MPA_ENINT_ITMSG2 |
|
||
MPA_ENINT_ITMSG3 |
|
||
MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
|
||
);
|
||
} else if (PCR->Prcb->Number == 1){
|
||
if (HalpIsTowerPci){
|
||
pending &= (
|
||
((cpureg & (MPA_ENINT_SR_IP6 |
|
||
MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
|
||
|
|
||
((cpureg & (MPA_ENINT_ITMSG1 |
|
||
MPA_ENINT_ITMSG2 |
|
||
MPA_ENINT_ITMSG3 |
|
||
MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
|
||
);
|
||
}else{
|
||
pending &= (
|
||
((cpureg & (MPA_ENINT_SR_IP5 |
|
||
MPA_ENINT_SR_IP7 )) >> MPA_ENINT_MASKSHIFT)
|
||
|
|
||
((cpureg & (MPA_ENINT_ITMSG1 |
|
||
MPA_ENINT_ITMSG2 |
|
||
MPA_ENINT_ITMSG3 |
|
||
MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
|
||
);
|
||
}
|
||
} else {
|
||
pending &= (
|
||
((cpureg & MPA_ENINT_SR_IP7 ) >> MPA_ENINT_MASKSHIFT)
|
||
|
||
|
|
||
((cpureg & (MPA_ENINT_ITMSG1 |
|
||
MPA_ENINT_ITMSG2 |
|
||
MPA_ENINT_ITMSG3 |
|
||
MPA_ENINT_MPBERR)) >> (MPA_ENINT_MASKSHIFT-1))
|
||
);
|
||
|
||
}
|
||
|
||
if (causeit != pending) {
|
||
|
||
/*
|
||
* There is sometimes an MP_Agent interrupt with values different in
|
||
* MPA_INTN_... = 0 and MPA_OINTN_....
|
||
* That means : The cause register has been updated with a wrong value!
|
||
* We need to force a new update of the cause register to avoid looping
|
||
* on this interrupt until a new external interrupt happens.
|
||
*/
|
||
if (cpureg & MPA_INTCONF_SR_IP8) {
|
||
tempreg = (cpureg & (~MPA_INTCONF_SR_IP8)) | MPA_ENINT_SR_IP8;
|
||
} else {
|
||
tempreg = (cpureg | MPA_INTCONF_SR_IP8 | MPA_ENINT_SR_IP8);
|
||
}
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), tempreg); // write the new value in the MP_Agent register /
|
||
|
||
|
||
WRITE_REGISTER_ULONG(&(mpagent->cpureg), cpureg); // Restore initial value
|
||
|
||
|
||
if (mask <= 1) {
|
||
|
||
|
||
|
||
return 0;
|
||
}
|
||
|
||
reg = HalpGetCauseRegister();
|
||
if ( reg & mask ) {
|
||
|
||
|
||
return 0;
|
||
} else {
|
||
|
||
|
||
return 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
return 0; /* No possible spurious ! */
|
||
|
||
}
|
||
|
||
|