📄 interrupts.c
字号:
//=============================================================================
//
// interrupts.c - Cyclone Diagnostics
//
//=============================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//=============================================================================
//#####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(void);
extern long _cspr_enable_irq_int(void);
extern long _read_cpsr(void);
extern long _scrub_ecc(unsigned);
extern void _flushICache(void);
#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
{
INTFUNCPTR 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(void);
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(void);
/*********************************
* PCI interrupt wrappers
*/
int sinta_handler(void)
{
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(void)
{
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(void)
{
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(void)
{
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(void)
{
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -