📄 interrupts.c
字号:
//=============================================================================
//
// interrupts.c - Cyclone Diagnostics
//
//=============================================================================
//####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
//####COPYRIGHTEND####
//=============================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
// Contributors:
// Date: 2001-01-25
// Purpose:
// Description:
//
//####DESCRIPTIONEND####
//
//===========================================================================*/
/******************************************************************************/
/* interrupts.c - Interrupt dispatcher routines for IQ80310 Board */
/* */
/* modification history */
/* -------------------- */
/* 07sep00, ejb, Written for IQ80310 Cygmon diagnostics */
/* 11oct00, ejb, Switched FIQ and IRQ interrupt handlers */
/* 18dec00 snc and jwf */
/* 02feb01 jwf for snc */
/******************************************************************************/
#include "iq80310.h"
#include "pci_bios.h"
#include "7_segment_displays.h"
extern int(*board_fiq_handler)(void);
extern int(*board_irq_handler)(void);
extern long _cspr_enable_fiq_int();
extern long _cspr_enable_irq_int();
extern long _read_cpsr();
extern long _scrub_ecc();
#define AND_WORD(addr,val) *addr = *addr & val
void error_print(char *fmt, int arg0, int arg1, int arg2, int arg3);
extern int nmi_verbose; /* for NMI, only print NMI info if this is TRUE */
extern int pci_config_cycle; /* don't handle NMI if in a config cycle */
extern int pci_config_error;
typedef struct
{
FUNCPTR handler;
int arg;
int bus;
int device;
} INT_HANDLER;
extern UINT secondary_busno;
extern UINT primary_busno;
extern STATUS pci_to_xint(int device, int intpin, int *xint);
extern int isHost();
extern int off_ppci_bus (int busno);
#define MAX_SPURIOUS_CNT 5
#define NUM_PCI_XINTS 4 /* SINTA - SINTD */
#define MAX_PCI_HANDLERS 8 /* maximum handlers per PCI Xint */
/* 02/02/01 jwf */
int ecc_error_reported = FALSE;
static int isr_xint0_spurious = 0;
static int isr_xint1_spurious = 0;
static int isr_xint2_spurious = 0;
static int isr_xint3_spurious = 0;
/* Table where the interrupt handler addresses are stored. */
INT_HANDLER pci_int_handlers[4][MAX_PCI_HANDLERS];
/* Other User Interrupt Service Routines */
void (*usr_timer_isr)(int) = NULL;
int usr_timer_arg = 0;
void (*usr_enet_isr)(int) = NULL;
int usr_enet_arg = 0;
void (*usr_uart1_isr)(int) = NULL;
int usr_uart1_arg = 0;
void (*usr_uart2_isr)(int) = NULL;
int usr_uart2_arg = 0;
void (*usr_dma0_isr)(int) = NULL;
int usr_dma0_arg = 0;
void (*usr_dma1_isr)(int) = NULL;
int usr_dma1_arg = 0;
void (*usr_dma2_isr)(int) = NULL;
int usr_dma2_arg = 0;
void (*usr_pm_isr)(int) = NULL;
int usr_pm_arg = 0;
void (*usr_aa_isr)(int) = NULL;
int usr_aa_arg = 0;
void (*usr_i2c_isr)(int) = NULL;
int usr_i2c_arg = 0;
void (*usr_mu_isr)(int) = NULL;
int usr_mu_arg = 0;
void (*usr_patu_isr)(int) = NULL;
int usr_patu_arg = 0;
int ecc_int_handler();
/*********************************
* PCI interrupt wrappers
*/
int sinta_handler()
{
int x, serviced = 0;
/* cycle through connected interrupt handlers to determine which caused int */
for (x = 0; x < MAX_PCI_HANDLERS; x++)
{
if (pci_int_handlers[0][x].handler != NULL) /* Is a routine installed */
if ((*pci_int_handlers[0][x].handler)(pci_int_handlers[0][x].arg) == 1)
{
serviced = 1;
break;
}
}
if (serviced == 0)
{
isr_xint0_spurious++;
if (isr_xint0_spurious > MAX_SPURIOUS_CNT)
;
}
else
isr_xint0_spurious = 0;
return (serviced);
}
int sintb_handler()
{
int x, serviced = 0;
/* cycle through connected interrupt handlers to determine which caused int */
for (x = 0; x < MAX_PCI_HANDLERS; x++)
{
if (pci_int_handlers[1][x].handler != NULL) /* Is a routine installed */
if ((*pci_int_handlers[1][x].handler)(pci_int_handlers[1][x].arg) == 1)
{
serviced = 1;
break;
}
}
if (serviced == 0)
{
isr_xint1_spurious++;
if (isr_xint1_spurious > MAX_SPURIOUS_CNT)
;
}
else
isr_xint1_spurious = 0;
return (serviced);
}
int sintc_handler()
{
int x, serviced = 0;
/* cycle through connected interrupt handlers to determine which caused int */
for (x = 0; x < MAX_PCI_HANDLERS; x++)
{
if (pci_int_handlers[2][x].handler != NULL) /* Is a routine installed */
if ((*pci_int_handlers[2][x].handler)(pci_int_handlers[2][x].arg) == 1)
{
serviced = 1;
break;
}
}
if (serviced == 0)
{
isr_xint2_spurious++;
if (isr_xint2_spurious > MAX_SPURIOUS_CNT)
;
}
else
isr_xint2_spurious = 0;
return (serviced);
}
int sintd_handler()
{
int x, serviced = 0;
/* cycle through connected interrupt handlers to determine which caused int */
for (x = 0; x < MAX_PCI_HANDLERS; x++)
{
if (pci_int_handlers[3][x].handler != NULL) /* Is a routine installed */
if ((*pci_int_handlers[3][x].handler)(pci_int_handlers[3][x].arg) == 1)
{
serviced = 1;
break;
}
}
if (serviced == 0)
{
isr_xint3_spurious++;
if (isr_xint3_spurious > MAX_SPURIOUS_CNT)
;
}
else
isr_xint3_spurious = 0;
return (serviced);
}
/******************************************************************************
*
* Installs an interrupt handler in the PCI dispatch table, to be called
* by the appropriate PCI isr (above) when an interrupt occurs.
*
* Note: the intline parameter refers to which PCI interrupt INT A - INT D
*
* device identifies the PCI device number
*
* Note: isrs connected with this function must return 1 if an interrupt is
* serviced in order to support the PCI interrupt sharing mechanism
*
*/
STATUS pci_isr_connect (int intline, int bus, int device, int (*handler)(int), int arg)
{
int which_xint;
int handler_index;
/* check to see if we are attempting to connect to a PPCI interrupt and we are not
a host card */
if ((isHost() == FALSE) && (off_ppci_bus(bus) == TRUE))
return (ERROR);
if ((intline < INTA) || (intline > INTD))
return (ERROR);
(void)pci_to_xint(device, intline, &which_xint);
for (handler_index = 0; handler_index < MAX_PCI_HANDLERS; handler_index++)
{
if (pci_int_handlers[which_xint][handler_index].handler == NULL)
{
pci_int_handlers[which_xint][handler_index].handler = handler;
pci_int_handlers[which_xint][handler_index].arg = arg;
pci_int_handlers[which_xint][handler_index].bus = bus;
pci_int_handlers[which_xint][handler_index].device = device;
break;
}
}
/* if there is no more room in the table return an error */
if (handler_index == MAX_PCI_HANDLERS)
return (ERROR);
return (OK);
}
/******************************************************************************
*
* Uninstalls an interrupt handler in the PCI dispatch table
*
* Note: the intline parameter refers to which PCI interrupt INTA - INTD
*
* the device parameter refers to which SPCI device number is sourcing the
* interrupt
*
*/
STATUS pci_isr_disconnect (int intline, int bus, int device)
{
int which_xint;
int handler_index;
/* check to see if we are attempting to disconnect a PPCI interrupt and we are not
a host card */
if ((isHost() == FALSE) && (off_ppci_bus(bus) == TRUE))
return (ERROR);
if ((intline < INTA) || (intline > INTD))
return (ERROR);
(void)pci_to_xint(device, intline, &which_xint);
for (handler_index = 0; handler_index < MAX_PCI_HANDLERS; handler_index++)
{
if ((pci_int_handlers[which_xint][handler_index].bus == bus) &&
(pci_int_handlers[which_xint][handler_index].device == device))
{
pci_int_handlers[which_xint][handler_index].handler = NULL;
pci_int_handlers[which_xint][handler_index].arg = (int)NULL;
pci_int_handlers[which_xint][handler_index].bus = (int)NULL;
pci_int_handlers[which_xint][handler_index].device = (int)NULL;
}
}
/* if the handler was not found in the table return an error */
if (handler_index == MAX_PCI_HANDLERS)
return (ERROR);
return (OK);
}
/**********************************************************************************
* iq80310_irq_handler - Interrupt dispatcher for IQ80310 IRQ Interrupts
*
* This function determines the source of the IRQ Interrupt, and calls the
* corresponding interrupt service routine. If multiple sources are interrupting
* the dispatcher will call all interrupt handles. Users must clear the interrupt
* within the interrupt service routine before exiting.
*
* IRQ Interrupts are multiplexed from SPCI INTA - INTD, External Device Interrupts,
* and XINT6 and XINT7 Internal device interrupts.
*/
int iq80310_irq_handler()
{
UINT8* int_status_reg;
UINT8 int_status;
int num_sources = 0;
/* 12/18/00 jwf */
unsigned char ri_state;
unsigned char board_rev;
unsigned char sint_status; /* holds interrupt status for SINTA-SINTC */
ri_state = *( unsigned char * ) 0xfe810006; /* access uart u2 msr reg at addr fe810006 */
ri_state &= RI_MASK;
if(ri_state == RI_MASK) /* RI# pin on UART2 is grounded */
{
board_rev = *BOARD_REV_REG_ADDR; /* read Board Revision register */
board_rev &= BOARD_REV_MASK; /* isolate LSN */
if (board_rev >= BOARD_REV_E) /* Board Rev is at E or higher */
{
sint_status = *SINT_REG_ADDR; /* read current secondary pci interrupt status */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -