548 lines
19 KiB
C
548 lines
19 KiB
C
/*++
|
|
|
|
Copyright (c) 1994 Kobe NEC Software
|
|
|
|
Module Name:
|
|
|
|
rxdspt.c
|
|
|
|
Abstract:
|
|
|
|
This module implements the interrupt dispatch routines for R98
|
|
|
|
Author:
|
|
|
|
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
|
|
#include "halp.h"
|
|
|
|
#include "bugcodes.h"
|
|
|
|
//
|
|
// Define the context structure for use by the interrupt routine.
|
|
//
|
|
|
|
typedef BOOLEAN (*PSECONDARY_DISPATCH)(
|
|
PVOID InterruptRoutine
|
|
);
|
|
|
|
typedef BOOLEAN (*PTIMER_DISPATCH)(
|
|
ULONG TrapFrame
|
|
);
|
|
|
|
|
|
//
|
|
// Dummy Read Registers
|
|
//
|
|
//
|
|
volatile ULONG DUMMYADDRS[]={
|
|
0x1c0003f1|KSEG1_BASE, //FDC37C665 config register
|
|
0x1c4033c7|KSEG1_BASE, //VGA DAC STATE register
|
|
0x1c0003f1|KSEG1_BASE, //FDC37C665 config register
|
|
0x1c000023|KSEG1_BASE, //ESC Configuration register
|
|
0x1c4033c7|KSEG1_BASE, //VGA DAC STATE register
|
|
0x19800610|KSEG1_BASE //Err node register
|
|
|
|
};
|
|
|
|
//
|
|
// Following structures will be changed by HalAllProcessorsStarted() on
|
|
// boot up HAL.
|
|
// Because each interrupt connects each processor on boot up HAL.
|
|
// v-masank@microsoft.com
|
|
//
|
|
|
|
INT_ENTRY HalpIntEntry[R98_CPU_NUM_TYPE][R98B_MAX_CPU][NUMBER_OF_INT]={
|
|
|
|
{// For R4400 [CPU][INT x] {StartBit, NumberOfBit,Arbitar,Enable,Open}
|
|
|
|
{ // For CPU #0
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
|
|
{32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
|
|
},
|
|
{ // For CPU #1
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
|
|
{32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
|
|
},
|
|
{ // For CPU #2
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
|
|
{32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
|
|
},
|
|
{ // For CPU #3
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 16 ,0,(ULONGLONG)0x00000000e3f00000,0}, //INT1
|
|
{32, 12 ,0,(ULONGLONG)0x000000f800000000,0}, //INT2
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT3
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT4
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0} //INT5
|
|
}
|
|
|
|
},
|
|
|
|
{// For R10000 [CPU][INT x] {StartBit, NumberOfBit,Arbitar,Enable,Open}
|
|
|
|
|
|
{
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
|
|
{NONE, 0 ,0,(ULONGLONG)0,0} //INT5
|
|
},
|
|
{
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
|
|
{NONE, 0 ,0,(ULONGLONG)0,0} //INT5
|
|
},
|
|
{
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
|
|
{NONE, 0 ,0,(ULONGLONG)0,0} //INT5
|
|
},
|
|
{
|
|
{0, 16 ,0,(ULONGLONG)0x000000000000e1b6,0}, //INT0
|
|
{16, 28 ,0,(ULONGLONG)0x000000f8e3f00000,0}, //INT1
|
|
{56, 2 ,0,(ULONGLONG)0x0300000000000000,0}, //INT2
|
|
{48, 4 ,0,(ULONGLONG)0x000f000000000000,0}, //INT3
|
|
{61, 2 ,0,(ULONGLONG)0x6000000000000000,0}, //INT4
|
|
{NONE, 0 ,0,(ULONGLONG)0,0} //INT5
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
RESET_REGISTER HalpResetValue[NUMBER_OF_IPR_BIT]={
|
|
{0,0,0,0}, //Bit 0
|
|
{PONCE1,PCIINTD,0,DUMMY_A4}, //Bit 1 PCI I/O Slot#8-#10 INTD
|
|
{PONCE0,PCIINTD,0,DUMMY_A3}, //Bit 2 PCI I/O Slot#4-#7 INTD
|
|
{0x0,0x0,0,0}, //Bit 3
|
|
|
|
{PONCE1,PCIINTC,0,DUMMY_A4}, //Bit 4 PCI I/O Slot#8-#10 INTC
|
|
{PONCE0,PCIINTC,0,DUMMY_A3}, //Bit 5 PCI I/O Slot#4-#7 INTC
|
|
{0x0,0x0,0,0} , //Bit 6
|
|
{PONCE1,PCIINTB,0,DUMMY_A4}, //Bit 7 PCI I/O Slot#8-#10 INTB
|
|
|
|
{PONCE0,PCIINTB,0,DUMMY_A3}, //Bit8 PCI I/O Slot#4-#7 INTB
|
|
{0x0,0x0,0,0}, //Bit9
|
|
{0x0,0x0,0,0}, //Bit10
|
|
{0x0,0x0,0,0}, //Bit11
|
|
|
|
{0x0,0x0,0,0}, //Bit12
|
|
{PONCE0,INTSA0,0x0,DUMMY_A3}, //Bit13 EISA Bridge
|
|
{PONCE1,INTSB0,0x0,DUMMY_A2}, //Bit14 Parallel
|
|
{PONCE0,INTSB0,0x0,DUMMY_A2}, //Bit15 FDC
|
|
|
|
{0x0,0x0,0,0}, //Bit16
|
|
{0x0,0x0,0,0}, //Bit17
|
|
{0x0,0x0,0,0}, //Bit18
|
|
{0x0,0x0,0,0}, //Bit19
|
|
|
|
{PONCE1,PCIINTA1,0x0,DUMMY_A4}, //Bit20 PCI I/O Slot#8 INTA
|
|
{PONCE1,PCIINTA0,0x0,DUMMY_A4}, //Bit21 PCI I/O Slot#9 INTA
|
|
{PONCE0,PCIINTA3,0x0,DUMMY_A3}, //Bit22 PCI I/O Slot#4 INTA
|
|
{PONCE0,PCIINTA2,0x0,DUMMY_A3}, //Bit23 PCI I/O Slot#5 INTA
|
|
|
|
{PONCE0,PCIINTA1,0,DUMMY_A3}, //Bit24 PCI I/O Slot#6 INTA
|
|
{PONCE0,PCIINTA0,0,DUMMY_A3}, //Bit25 PCI I/O Slot#7 INTA
|
|
{0x0,0x0,0,0}, //Bit26
|
|
{0x0,0x0,0,0}, //Bit27
|
|
|
|
{0x0,0x0,0,0}, //Bit28
|
|
{PONCE1,INTSA0,0x0,DUMMY_A1}, //Bit29 LAN(Ethernet)
|
|
{PONCE1,PCIINTA3,0x0,DUMMY_A1}, //Bit30 SCSI#1(Narrow)
|
|
{PONCE1,PCIINTA2,0x0,DUMMY_A1}, //Bit31 SCSI#0(Wide)
|
|
|
|
{0x0,0x0,0,0}, //Bit32
|
|
{0x0,0x0,0,0}, //Bit33
|
|
{0x0,0x0,0,0}, //Bit34 Tracer ponce Internal
|
|
{0x0,0x0,0,0}, //Bit35 TLB Undefine Address
|
|
|
|
{PONCE1,INTSB1,0,DUMMY_A0}, //Bit36 Mouse
|
|
{PONCE1,INTSA1,0,DUMMY_A0}, //Bit37 KeyBoard
|
|
{PONCE0,INTSB1,0,DUMMY_A0}, //Bit38 SIO#1
|
|
{PONCE0,INTSA1,0,DUMMY_A0}, //Bit39 SIO#0
|
|
|
|
{ RFU,0,0,0}, //Bit40
|
|
{ RFU,0,0,0}, //Bit41
|
|
{ RFU,0,0,0}, //Bit42
|
|
{ RFU,0,0,0}, //Bit43
|
|
|
|
// Never Used This is no Device Interrupt.
|
|
|
|
{ RFU,0,0,0}, //Bit44
|
|
{ RFU,0,0,0}, //Bit45
|
|
{ RFU,0,0,0}, //Bit46
|
|
{ RFU,0,0,0}, //Bit47
|
|
|
|
{ RFU,0,0,0}, //Bit48 From CPU#3 IPI
|
|
{ RFU,0,0,0}, //Bit49 From CPU#2 IPI
|
|
{ RFU,0,0,0}, //Bit50 From CPU#1 IPI
|
|
{ RFU,0,0,0}, //Bit51 From CPU#0 IPI
|
|
|
|
{ RFU,0,0,0}, //Bit52
|
|
{ RFU,0,0,0}, //Bit53
|
|
{ RFU,0,0,0}, //Bit54
|
|
{ RFU,0,0,0}, //Bit55
|
|
|
|
{ RFU,0,0,0}, //Bit56 Interval timer 2 Profile
|
|
{ RFU,0,0,0}, //Bit57 Interval timer 1 Clock
|
|
{ RFU,0,0,0}, //Bit58
|
|
{ RFU,0,0,0}, //Bit59
|
|
|
|
{ RFU,0,0,0}, //Bit60
|
|
{ RFU,0,0,0}, //Bit61 EIF+MRCINT
|
|
{ RFU,0,0,0}, //Bit62 Memory 1Bit Error
|
|
{ RFU,0,0,0} //Bit63
|
|
|
|
};
|
|
|
|
// Thanks very much for pete-san's cooporation.
|
|
// Pete-san write most of following source code.
|
|
// v-masak@microsoft.com
|
|
// 5/17/96
|
|
|
|
#define HalpFindFirstSetMember(Set) \
|
|
((Set & 0xFF) ? HalpFindFirstSet[Set & 0xFF] : \
|
|
((Set & 0xFF00) ? HalpFindFirstSet[(Set >> 8) & 0xFF] + 8 : \
|
|
((Set & 0xFF0000) ? HalpFindFirstSet[(Set >> 16) & 0xFF] + 16 : \
|
|
HalpFindFirstSet[(Set >> 24) & 0xff] + 24)))
|
|
|
|
ULONG HalpFindFirstSet[256] = {
|
|
0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
|
|
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7};
|
|
|
|
PINT_ENTRY HalpIntEntryPointer;
|
|
|
|
//
|
|
// I use LargeReigester access function for performance
|
|
// v-masank@microsoft.com
|
|
// I used 64 bit shift.
|
|
// v-masank@microsoft.com
|
|
//
|
|
|
|
VOID
|
|
HalpGeneralDispatch(
|
|
IN ULONG TrapFrame,
|
|
IN ULONG IntNo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This is the general hal interrupt dispatch routine. This services hardware interrupts
|
|
for range ip[3..8]
|
|
|
|
|
|
Arguments:
|
|
|
|
IN ULONG TrapFrame - This interrupts trapframe
|
|
IN ULONG IntNo - The current Interrupt Number range IntNo[0..5] maps to IP[3..8]
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
|
|
volatile PULONGLONG Register;
|
|
ULONGLONG Enable;
|
|
volatile ULONGLONG IPR;
|
|
ULONGLONG IprBit;
|
|
ULONG ULIPR;
|
|
ULONG CpuNumber;
|
|
ULONG cnt;
|
|
ULONG IprBitNumber;
|
|
ULONG Ponce;
|
|
UCHAR Data;
|
|
ULONG StartBit;
|
|
//
|
|
// Get CpuNumber
|
|
//
|
|
CpuNumber = PCR->Number;
|
|
|
|
//
|
|
// Get Enable table offset
|
|
//
|
|
cnt = CpuNumber * NUMBER_OF_INT;
|
|
//
|
|
// The interrupt controller on the R98A/B occasionally (rarely) sends
|
|
// an interrupt to multiple processors. One is the correct processor to
|
|
// handle the interrupt the other is not. The enable bit
|
|
// determines if this processor handles this interrupt.
|
|
//
|
|
// The table HalpIntEntryPointer gets initalized for the correct processor at boot
|
|
// (i.e., R98A or R98B).
|
|
|
|
Enable=HalpIntEntryPointer[cnt+IntNo].Enable;
|
|
StartBit = HalpIntEntryPointer[cnt+IntNo].StartBitNo;
|
|
//
|
|
// Do until no more interrupts pending
|
|
//
|
|
do {
|
|
|
|
//
|
|
// IPR register read
|
|
//
|
|
Register = (PULONGLONG)&((COLUMNBS_LCNTL)->IPR);
|
|
HalpReadLargeRegister(Register,(PULONGLONG)&IPR);
|
|
|
|
// MASK
|
|
//
|
|
// Determine if this Interrupt enabled for this processor
|
|
//
|
|
IPR = IPR & Enable;
|
|
//
|
|
// 28 is the largest interrupt bit vector possible on these machines
|
|
// StartBit is the starting bit position for this interrupt level
|
|
// Shift the 64 bit interrupt register into a 32 bit field
|
|
// to make the find first bit set operation easier
|
|
ULIPR = (ULONG) (IPR >> StartBit);
|
|
if(ULIPR==0){
|
|
continue; // No interrupts handled by this processor
|
|
}
|
|
do{
|
|
//
|
|
// Service all pending interrupts for this ip level
|
|
//
|
|
while(ULIPR!=0){
|
|
|
|
//
|
|
// Get Interrupt bit set No. on IPR.
|
|
//
|
|
IprBitNumber = HalpFindFirstSetMember(ULIPR) + StartBit;
|
|
IprBit = 1UI64 << IprBitNumber; // Save this value for clearing INT
|
|
//
|
|
// IPR register read
|
|
// IntNo 0 1 2 3 4 5
|
|
//
|
|
// R98A Starting bit pos 0 16 32 56 48 61
|
|
// R98B Starting bit pos 0 16 56 48 61 NA
|
|
//
|
|
// On the R98A/B Each interrupt level can have multiple
|
|
// concurrentinterrupt sources
|
|
// (e.g., the read of IPR can have more than 1 bit set
|
|
//
|
|
//
|
|
// Hardware Ip #of possible interrupt sources
|
|
// R98A R98B
|
|
// ip[3] 16 16
|
|
// ip[4] 16 28
|
|
// ip[5] 12 2
|
|
// ip[6] 2 4
|
|
// ip[7] 4 2
|
|
// ip[8] 2 0
|
|
//
|
|
// During initialization the HAL assigns affinity to interrupt sources. So that
|
|
// the interrupt always gets serviced on the same processor
|
|
|
|
|
|
|
|
switch (IprBitNumber) {
|
|
|
|
case 62:
|
|
//
|
|
// call Ecc Error service routine
|
|
//
|
|
((PSECONDARY_DISPATCH)PCR->InterruptRoutine[62+DEVICE_VECTORS])
|
|
(PCR->InterruptRoutine[62+DEVICE_VECTORS]);
|
|
//
|
|
// Clear IPR
|
|
//
|
|
Register=(PULONGLONG) &((COLUMNBS_LCNTL)->IPRR);
|
|
HalpWriteLargeRegister(Register,&IprBit);
|
|
break;
|
|
case 61:
|
|
//
|
|
// This interrupt gets sent to all processors.
|
|
// Our friend the HalpDieLock controls exclusive access
|
|
// protecting the power switch interrupt service routine
|
|
// and for some reason the read/write of the Power interrupt
|
|
// register.
|
|
//
|
|
//
|
|
KiAcquireSpinLock(&HalpDieLock);
|
|
//
|
|
// It's EIF or MRC INT
|
|
//
|
|
((PSECONDARY_DISPATCH)PCR->InterruptRoutine[61+DEVICE_VECTORS])
|
|
(PCR->InterruptRoutine[61+DEVICE_VECTORS]);
|
|
|
|
|
|
// HACK HACK HACK !!
|
|
HalpLocalDeviceReadWrite(MRCINT,&Data,LOCALDEV_OP_READ);
|
|
if( Data & 0x04){
|
|
//
|
|
// At This time If MRCINT Register reported Power Interrupt.
|
|
// Power Driver failed or happenig ocurred.
|
|
// if anyone push DUMP KEY. Hal may be system reset.
|
|
// So Reset Power Interrupt.
|
|
//
|
|
|
|
Data = 0x0;
|
|
HalpLocalDeviceReadWrite(MRCINT, &Data, LOCALDEV_OP_WRITE);
|
|
}
|
|
|
|
KiReleaseSpinLock(&HalpDieLock);
|
|
|
|
//
|
|
//Clear IPR
|
|
//
|
|
|
|
Register= (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR;
|
|
HalpWriteLargeRegister(Register,&IprBit);
|
|
break;
|
|
case 56:
|
|
case 57:
|
|
//
|
|
// Profile or Clock
|
|
//
|
|
((PTIMER_DISPATCH)PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(TrapFrame);
|
|
//
|
|
//Clear IPR
|
|
//
|
|
|
|
Register= (PULONGLONG)&(COLUMNBS_LCNTL)->IPRR;
|
|
HalpWriteLargeRegister(Register,&IprBit);
|
|
break;
|
|
case 48:
|
|
case 49:
|
|
case 50:
|
|
case 51:
|
|
|
|
//
|
|
// Clear IPR
|
|
//
|
|
|
|
Register= (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR;
|
|
HalpWriteLargeRegister(Register,&IprBit);
|
|
|
|
//
|
|
// IPI interrupts. One for each possible CPU
|
|
//
|
|
((PTIMER_DISPATCH) PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(TrapFrame);
|
|
break;
|
|
default:
|
|
//
|
|
// Device Interrupt !!
|
|
//
|
|
Ponce = HalpResetValue[IprBitNumber].Ponce;
|
|
|
|
|
|
//
|
|
// 1. Clear INTRG register of PONCE
|
|
//
|
|
WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->INTRG,
|
|
0x1 << HalpResetValue[IprBitNumber].IntGResetBit);
|
|
|
|
//
|
|
// 2. Call interrupt service routine
|
|
//
|
|
((PSECONDARY_DISPATCH)PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS])(
|
|
PCR->InterruptRoutine[IprBitNumber+DEVICE_VECTORS]);
|
|
|
|
//
|
|
// 3. Dummy Read execute
|
|
//
|
|
|
|
READ_REGISTER_UCHAR( DUMMYADDRS[HalpResetValue[IprBitNumber].Dummy]);
|
|
READ_REGISTER_UCHAR( DUMMYADDRS[HalpResetValue[IprBitNumber].Dummy]);
|
|
|
|
//
|
|
// 4. Clear IPR Bit By IPRR Register
|
|
//
|
|
|
|
Register = (PULONGLONG) &(COLUMNBS_LCNTL)->IPRR;
|
|
HalpWriteLargeRegister(Register,&IprBit);
|
|
|
|
//
|
|
// 5.Clear INTRG register of PONCE
|
|
//
|
|
|
|
|
|
WRITE_REGISTER_ULONG((PULONG)&PONCE_CNTL(Ponce)->INTRG,
|
|
0x1 << (HalpResetValue[IprBitNumber].IntGResetBit + 21));
|
|
|
|
} // End Switch
|
|
//
|
|
// Clear the bit in the interrupt register
|
|
// that we just serviced
|
|
//
|
|
ULIPR = ULIPR & ~(1 << (IprBitNumber - StartBit));
|
|
} // End while servicing current interrupt. Check for more
|
|
//
|
|
// Determine if another interrupt pending at the same level before leaving
|
|
// this dispatch routine. The hardware spec implies that there is
|
|
// a small window that the interrupt register has bits set before the
|
|
// cause register. So it suggests checking the interrupt register
|
|
// before the cause
|
|
//
|
|
//
|
|
// check new interrupt
|
|
//
|
|
//
|
|
// IPR register read
|
|
//
|
|
Register = (PULONGLONG)&((COLUMNBS_LCNTL)->IPR);
|
|
HalpReadLargeRegister(Register,(PULONGLONG)&IPR);
|
|
|
|
// MASK
|
|
//
|
|
// Determine if this Interrupt enabled for this processor
|
|
//
|
|
|
|
IPR = IPR & Enable;
|
|
ULIPR = (ULONG) (IPR >> StartBit);
|
|
}while(ULIPR!=0); // End do-while
|
|
//
|
|
// Check cause register to see if an interrupt pending for the current level
|
|
//
|
|
} while(HalpGetCause() & (1 << CAUSE_INT_PEND_BIT+IntNo));
|
|
}
|
|
|