summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/halr98mp/mips/r98dspt.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/halr98mp/mips/r98dspt.c')
-rw-r--r--private/ntos/nthals/halr98mp/mips/r98dspt.c704
1 files changed, 704 insertions, 0 deletions
diff --git a/private/ntos/nthals/halr98mp/mips/r98dspt.c b/private/ntos/nthals/halr98mp/mips/r98dspt.c
new file mode 100644
index 000000000..3c89949ec
--- /dev/null
+++ b/private/ntos/nthals/halr98mp/mips/r98dspt.c
@@ -0,0 +1,704 @@
+#ident "@(#) NEC r98dspt.c 1.14 95/03/17 11:55:28"
+/*++
+
+Copyright (c) 1994 Kobe NEC Software
+
+Module Name:
+
+ r98dspt.c
+
+Abstract:
+
+ This module implements the interrupt dispatch routines for R98
+
+Author:
+
+
+
+Environment:
+
+ Kernel mode
+
+Revision History:
+
+
+--*/
+
+/*
+ ***********************************************************************
+ *
+ * S001 7/7 T.Samezima
+ *
+ * Chg all alteration Int0-2 dispach routine
+ *
+ * Del move some define in r98def.h
+ *
+ ***********************************************************************
+ *
+ * S002 8/22 T.Samezima on SNES
+ *
+ * Add Buffer for register save when unknown interrupt
+ * Count up at loop counter
+ *
+ * Chg Modify loop logic
+ *
+ ***********************************************************************
+ *
+ * S003 9/30 T.Samezima
+ *
+ * Bug define miss on Int1 dispatch table.
+ *
+ * S004 '94.10/14 T.Samezima
+ * Chg Display IPR and iRSF register on bugcheck
+ *
+ * S005 '94.11/8 T.Samezima
+ * Del Delete call of KeBugCheck. because of wrong interrupt ocure
+ * of LR4360 bug
+ *
+ * S006 '94.11/21 T.Samezima
+ * Chg Change size of dummy read
+ *
+ * S007 '94.12/28 T.Samezima
+ * Add interrupt clear Broadcast in Unknown interrupt
+ *
+ * S009 '95.01/11 T.Samezima
+ * Add Dummy single read on EIF interrupt.
+ *
+ * S00a '95.03/13 T.Samezima
+ * Del PIO interrupt check.
+ * Add LR4360 error check.
+ * check dummy single read
+ *
+ */
+
+#include "halp.h"
+//#include "halmips.h"
+#include "bugcodes.h"
+
+/* Start S001 */
+//
+// Define table in use interrupt dispatch routine
+//
+#define INT2_DATA_TABLE_SIZE 5
+#define INT1_DATA_TABLE_SIZE 6
+
+enum _INT_DISP_TABLE {
+ iRSF_BIT=0,
+ IPR_BIT,
+ IDT_VECTOR,
+ DUMMY_READ_ADDR,
+ DUMMY_READ_SIZE,
+ NA_CODE
+ };
+
+typedef struct _DISPATCH_DATA_TABLE {
+ ULONG IrsfMask;
+ ULONG IprMask;
+ ULONG IdtVector;
+ ULONG DummyReadAddr;
+ ULONG DummyReadSize;
+ ULONG NaCode;
+} DISPATCH_DATA_TABLE, *PDISPATCH_DATA_TABLE;
+
+DISPATCH_DATA_TABLE HalpInt2DispatchDataTable[] = {
+ {iRSF_KBMS_BIT, IPR_KB_MS_BIT_LOW, KBMS_VECTOR,
+ KBMS_DUMMY_READ_ADDR, 1, NACODE_KB_MS},
+// {iRSF_PIO_BIT, IPR_FDC_PIO_BIT_LOW, PIO_VECTOR,
+// PIO_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a
+ {iRSF_LR_ERR_BIT,IPR_DMA_BIT_LOW, LR_ERR_VECTOR,
+ DMA_DUMMY_READ_ADDR, 4, NACODE_DMA}, // S00a
+ {iRSF_FDC_BIT, IPR_FDC_PIO_BIT_LOW, FDC_VECTOR,
+ FDC_DUMMY_READ_ADDR, 1, NACODE_FDC_PIO}, // S00a
+ {iRSF_SIO_BIT, IPR_SIO_BIT_LOW, SIO_VECTOR,
+ SIO_DUMMY_READ_ADDR, 1, NACODE_SIO},
+ {iRSF_DMA_BIT, IPR_DMA_BIT_LOW, DMA_VECTOR,
+ DMA_DUMMY_READ_ADDR, 4, NACODE_DMA}
+};
+
+DISPATCH_DATA_TABLE HalpInt1DispatchDataTable[] = {
+ {iRSF_EISA_BIT, IPR_EISA_BIT_LOW, EISA_DEVICE_VECTOR,
+ EISA_DUMMY_READ_ADDR, 1, NACODE_EISA},
+ {iRSF_SCSI1_BIT, IPR_SCSI_BIT_LOW, SCSI1_VECTOR,
+ SCSI1_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006
+ {iRSF_ETHER_BIT, IPR_ETHER_BIT_LOW, ETHER_VECTOR,
+ ETHER_DUMMY_READ_ADDR, 2, NACODE_ETHER},
+ {iRSF_PCI_BIT, IPR_PCI_BIT_LOW, PCI_DEVICE_VECTOR,
+ PCI_DUMMY_READ_ADDR, 4, NACODE_PCI}, // S003
+ {iRSF_SCSI0_BIT, IPR_SCSI_BIT_LOW, SCSI0_VECTOR,
+ SCSI0_DUMMY_READ_ADDR, 4, NACODE_SCSI}, // S006, S00a
+ {iRSF_ERRPCI_BIT,IPR_PCI_BIT_LOW, PCI_ERR_VECTOR,
+ PCI_DUMMY_READ_ADDR, 4, NACODE_PCI} // S003
+};
+
+// DISPATCH_DATA_TABLE HalpInt0DispatchDataTable[];
+
+enum _INT_TABLE_DATA{
+ TABLE_SIZE=0,
+ MKR_MASK,
+ INT_LEVEL
+ };
+
+ULONG HalpIntData[3][3] = {
+ {0, MKR_INT0_ENABLE_LOW, INT0_LEVEL},
+ {INT1_DATA_TABLE_SIZE, MKR_INT1_ENABLE_LOW, INT1_LEVEL},
+ {INT2_DATA_TABLE_SIZE, MKR_INT2_ENABLE_LOW, INT2_LEVEL}
+};
+
+//
+// Define pointer of interrupt arbitration
+//
+ULONG HalpInt2ArbitrationPoint = 0;
+ULONG HalpInt1ArbitrationPoint = 0;
+ULONG HalpInt0ArbitrationPoint = 0;
+/* End S001 */
+
+#if DBG
+//
+// Register buffer
+//
+
+ULONG HalpUnknownCause = 0; // S002
+ULONG HalpUnknownIPRUpper = 0;
+ULONG HalpUnknownIPRLower = 0;
+ULONG HalpUnknownMKRUpper = 0;
+ULONG HalpUnknownMKRLower = 0;
+ULONG HalpUnknowniRRE = 0; // S002
+ULONG HalpUnknowniREN = 0; // S002
+ULONG HalpUnknowniRSF = 0; // S002
+ULONG HalpUnknownIprUpperBuf = 0; // S002
+ULONG HalpUnknownIprLowerBuf = 0; // S002
+ULONG HalpIoIntLoopCounter; // S002
+
+#endif
+
+//
+// Define the context structure for use by the interrupt routine.
+//
+
+typedef BOOLEAN (*PSECONDARY_DISPATCH)(
+ PVOID InterruptRoutine
+ );
+
+typedef BOOLEAN (*PTIMER_DISPATCH)(
+ ULONG TrapFrame
+ );
+
+
+VOID
+HalpUnknownInterrupt(
+ IN ULONG IprUpper,
+ IN ULONG IprLower
+ )
+/*++
+
+Routine Description:
+
+ This function is reset of unknown interrupt.
+
+Argments:
+
+ IprUpper (a0) - Supplies upper 32bit of result of "IPR & MKR" in present INT level.
+
+ IprLower (a1) - Supplies lower 32bit of result of "IPR & MKR" in present INT level.
+
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG i;
+
+// Start S002
+#if DBG
+ HalpUnknownCause = HalpGetCause();
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &HalpUnknownIPRUpper,
+ &HalpUnknownIPRLower
+ );
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &HalpUnknownMKRUpper,
+ &HalpUnknownMKRLower
+ );
+
+ HalpUnknownIprUpperBuf = IprUpper;
+ HalpUnknownIprLowerBuf = IprLower;
+
+ HalpUnknowniRRE = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRRE );
+ HalpUnknowniREN = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iREN );
+ HalpUnknowniRSF = READ_REGISTER_ULONG( &( LR_CONTROL2 )->iRSF );
+
+#if 0 // S005 vvv
+ KeBugCheckEx(INTERRUPT_EXCEPTION_NOT_HANDLED,
+ IprUpper,
+ IprLower,
+ HalpUnknowniRSF,
+ HalpUnknowniRRE
+ ); // S004
+#endif // S005 ^^^
+
+#endif
+// End S002
+
+ //
+ // clear interrupt pending bit
+ //
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &IprUpper,
+ &IprLower
+ );
+ // S007 vvv
+ //
+ // issue broadcast of unknown interrupt clear
+ //
+
+ if( IprLower != 0 ) {
+ PDISPATCH_DATA_TABLE dataTable;
+ ULONG tableSize;
+
+ if( IprLower & MKR_INT2_ENABLE_LOW ) {
+ dataTable = HalpInt2DispatchDataTable;
+ tableSize = INT2_DATA_TABLE_SIZE;
+ } else if( IprLower & MKR_INT1_ENABLE_LOW ) {
+ dataTable = HalpInt1DispatchDataTable;
+ tableSize = INT1_DATA_TABLE_SIZE;
+ }
+
+ for( i=0; i<tableSize; i++) {
+ if( i == 1 )
+ continue;
+ if( (IprLower & dataTable[i].IprMask) != 0 ) {
+ WRITE_REGISTER_ULONG( (ULONG)( &(IOB_CONTROL)->AIMR ),
+ dataTable[i].NaCode );
+ }
+ }
+ }
+ // S007 ^^^
+
+ //
+ // count up unknown interrupt
+ //
+
+ for ( i=0 ; i < 32 ; i++ ) {
+ HalpUnknownInterruptCount[i] += (IprUpper >> i) & 1;
+ HalpUnknownInterruptCount[i+32] += (IprLower >> i) & 1;
+ }
+}
+
+VOID
+HalpEifDispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an eif interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG zero=0;
+ ULONG buffer;
+
+ //
+ // Get interrpt pending bit
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+Loop:
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterUpperPart &= pmcIPRRegisterUpperPart;
+
+ //
+ // Check eif interrupt
+ //
+
+ buffer=pmcRegisterUpperPart & IPR_EIF_BIT_HIGH;
+
+ if( buffer ){
+ //
+ // issue dummy single read
+ //
+
+ READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+ READ_REGISTER_ULONG( &( IOB_CONTROL )->EIFR.Long );
+
+ HalpHandleEif();
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ } else {
+ HalpUnknownInterrupt( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH,
+ 0 );
+ }
+
+ //
+ // Check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ if( pmcIPRRegisterUpperPart & MKR_INT5_ENABLE_HIGH ){
+ goto Loop;
+ }
+ } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + EIF_LEVEL - 1)) );
+
+ return;
+}
+
+
+VOID
+HalpTimerScDispatch(
+ IN ULONG TrapFrame
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an timer interrupt.
+
+Argments:
+
+ TrapFrame - Supplies a pointer to a trap frame.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG zero=0;
+ ULONG buffer;
+
+ //
+ // read IPR register
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ //
+ // read MKR register
+ //
+
+Loop:
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterUpperPart &= pmcIPRRegisterUpperPart;
+
+ //
+ // check profile and clock interrupt
+ //
+
+ buffer=pmcRegisterUpperPart & IPR_PROFILE_BIT_HIGH;
+
+ if( buffer ){
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT2.Long), 0x0 ); // S002
+
+ ((PTIMER_DISPATCH) PCR->InterruptRoutine[PROFILE_VECTOR])(TrapFrame);
+ } else {
+ buffer=pmcRegisterUpperPart & IPR_CLOCK_BIT_HIGH;
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &buffer,
+ &zero );
+ WRITE_REGISTER_ULONG( (ULONG)( &(PMC_CONTROL1)->TOVCT1.Long), 0x0 ); // S002
+
+ ((PTIMER_DISPATCH) PCR->InterruptRoutine[CLOCK_VECTOR])(TrapFrame);
+ }
+
+ //
+ // Check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ if( pmcIPRRegisterUpperPart & MKR_INT3_ENABLE_HIGH ){
+ goto Loop;
+ }
+ } while( HalpGetCause() & (1 << (CAUSE_INT_PEND_BIT + TIMER_LEVEL - 1)) );
+
+ return;
+}
+
+
+/* Start S001 */
+VOID
+HalpIoIntDispatch(
+ IN PDISPATCH_DATA_TABLE DataTable,
+ IN OUT PULONG ArbitrationPoint,
+ IN ULONG IntNo
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int0, int1, and int2 interrupt.
+
+Argments:
+
+ DataTable - Supplies a table useing judge interrupt factor.
+
+ ArbitrationPoint - Supplies a start point of checking interrupt.
+
+ IntNo - Supplies interrupt level.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ ULONG pmcRegisterUpperPart;
+ ULONG pmcRegisterLowerPart;
+ ULONG pmcIPRRegisterUpperPart;
+ ULONG pmcIPRRegisterLowerPart;
+ ULONG buffer;
+ ULONG counter;
+ ULONG position;
+ ULONG zero=0;
+ ULONG flag;
+
+ // Start S002
+#if DBG
+ HalpIoIntLoopCounter = 0;
+#endif
+ // End S002
+
+ //
+ // Get interrpt pending bit
+ //
+
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+//Loop: // S002
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterLowerPart &= pmcIPRRegisterLowerPart;
+
+Loop: // S002
+ buffer = READ_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF) );
+
+ (*ArbitrationPoint)++;
+
+ flag = FALSE;
+
+ for(counter = 0; counter < HalpIntData[IntNo][TABLE_SIZE] ; counter++){
+
+ position = ( (*ArbitrationPoint + counter) % HalpIntData[IntNo][TABLE_SIZE]);
+
+ //
+ // check interrupt
+ //
+
+ if( ((buffer & DataTable[position].IrsfMask) == 0) ||
+ ((pmcRegisterLowerPart & DataTable[position].IprMask) == 0) ) {
+ continue;
+ }
+
+ flag = TRUE;
+
+ HalpWriteLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPRR ),
+ &zero,
+ &(DataTable[position].IprMask)
+ );
+ ((PSECONDARY_DISPATCH)PCR->InterruptRoutine[DataTable[position].IdtVector])(
+ PCR->InterruptRoutine[DataTable[position].IdtVector]
+ );
+
+ // Start S002
+ //
+ // Clear Interrupt pending bit in iRSF register
+ //
+
+ WRITE_REGISTER_ULONG( (ULONG)(&(LR_CONTROL2)->iRSF),
+ DataTable[position].IrsfMask );
+ // End S002
+
+ //
+ // issue dummy single read
+ //
+
+ switch(DataTable[position].DummyReadSize){
+ case 1:
+ READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr );
+ READ_REGISTER_UCHAR( DataTable[position].DummyReadAddr );
+ break;
+ case 2:
+ READ_REGISTER_USHORT( DataTable[position].DummyReadAddr );
+ READ_REGISTER_USHORT( DataTable[position].DummyReadAddr );
+ break;
+ case 4:
+ READ_REGISTER_ULONG( DataTable[position].DummyReadAddr );
+ READ_REGISTER_ULONG( DataTable[position].DummyReadAddr );
+ break;
+ }
+
+ //
+ // issue broadcast of interrupt clear
+ //
+
+ WRITE_REGISTER_ULONG( (ULONG)( &(IOB_CONTROL)->AIMR ),
+ DataTable[position].NaCode );
+
+ break; // S006
+ }
+
+ if (flag == FALSE){
+ HalpUnknownInterrupt( 0,
+ pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK]
+ );
+ }
+
+ //
+ // check new interrupt
+ //
+
+ do {
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->IPR ),
+ &pmcIPRRegisterUpperPart,
+ &pmcIPRRegisterLowerPart );
+
+ // Start S002
+ HalpReadLargeRegister( (ULONG)( &(PMC_CONTROL1)->MKR ),
+ &pmcRegisterUpperPart,
+ &pmcRegisterLowerPart );
+
+ pmcRegisterLowerPart &= pmcIPRRegisterLowerPart;
+ // end S002
+
+ if( pmcIPRRegisterLowerPart & HalpIntData[IntNo][MKR_MASK] ){
+ // Start S002
+#if DBG
+ HalpIoIntLoopCounter++;
+#endif
+ // End S002
+ goto Loop;
+ }
+ } while(HalpGetCause() & (1 << CAUSE_INT_PEND_BIT+HalpIntData[IntNo][INT_LEVEL]-1));
+
+ return;
+}
+
+
+VOID
+HalpInt2Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int2 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( HalpInt2DispatchDataTable,
+ &HalpInt2ArbitrationPoint,
+ 2
+ );
+}
+
+
+VOID
+HalpInt1Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int1 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( HalpInt1DispatchDataTable,
+ &HalpInt1ArbitrationPoint,
+ 1
+ );
+}
+
+
+VOID
+HalpInt0Dispatch(
+ VOID
+ )
+/*++
+
+Routine Description:
+
+ This routine is enterd as the result of an int0 interrupt.
+
+Argments:
+
+ None.
+
+Return Value:
+
+ None.
+
+--*/
+{
+ HalpIoIntDispatch( (PDISPATCH_DATA_TABLE)NULL,
+ &HalpInt0ArbitrationPoint,
+ 0
+ );
+}
+/* End S001 */