2001-04-11 Eric Valette <valette@crf.canon.fr>

* clock/.cvsignore, clock/Makefile.am, clock/p_clock.c,
	include/8xx_immap.h, include/commproc.h, irq/.cvsignore,
	irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_asm.S,
	irq/irq_init.c, vectors/.cvsignore, vectors/Makefile.am,
	vectors/vectors.S, vectors/vectors.h,
	vectors/vectors_init.c: New file.
	* Switch the eth_comm BSP to use the "new exception processing model."
This commit is contained in:
Joel Sherrill
2001-04-16 20:18:03 +00:00
parent 2cdde6d820
commit 4055e6f86f
17 changed files with 2929 additions and 0 deletions

View File

@@ -1,3 +1,13 @@
2001-04-11 Eric Valette <valette@crf.canon.fr>
* clock/.cvsignore, clock/Makefile.am, clock/p_clock.c,
include/8xx_immap.h, include/commproc.h, irq/.cvsignore,
irq/Makefile.am, irq/irq.c, irq/irq.h, irq/irq_asm.S,
irq/irq_init.c, vectors/.cvsignore, vectors/Makefile.am,
vectors/vectors.S, vectors/vectors.h,
vectors/vectors_init.c: New file.
* Switch the eth_comm BSP to use the "new exception processing model."
2001-04-11 Eric Valette <valette@crf.canon.fr>
* Makefile.am, configure.in, console/console.c,

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,26 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
VPATH = @srcdir@:@srcdir@/../../shared/clock
C_FILES = p_clock.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
OBJS = $(C_O_FILES)
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../../../automake/compile.am
include $(top_srcdir)/../../../../../../automake/lib.am
#
# (OPTIONAL) Add local stuff here using +=
#
# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
all-local: $(ARCH) $(OBJS)
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,70 @@
/*
* Clock Tick interrupt conexion code.
*
* COPYRIGHT (c) 1989-1997.
* On-Line Applications Research Corporation (OAR).
* Copyright assigned to U.S. Government, 1994.
*
* The license and distribution terms for this file may in
* the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* Modified to support the MPC750.
* Modifications Copyright (c) 1999 Eric Valette valette@crf.canon.fr
*
* $Id$
*/
#include <bsp.h>
#include <bsp/irq.h>
extern void clockOn(void*);
extern void clockOff (void*);
extern int clockIsOn(void*);
extern void Clock_isr();
static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER,
(rtems_irq_hdl)Clock_isr,
(rtems_irq_enable)clockOn,
(rtems_irq_disable)clockOff,
(rtems_irq_is_enabled)clockIsOn};
int BSP_get_clock_irq_level()
{
/*
* Caution : if you change this, you must change the
* definition of BSP_PERIODIC_TIMER accordingly
*/
return 6;
}
int BSP_disconnect_clock_handler (void)
{
if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) {
printk("Unable to stop system clock\n");
rtems_fatal_error_occurred(1);
}
return BSP_remove_rtems_irq_handler (&clockIrqData);
}
int BSP_connect_clock_handler (rtems_irq_hdl hdl)
{
if (!BSP_get_current_rtems_irq_handler(&clockIrqData)) {
printk("Unable to get system clock handler\n");
rtems_fatal_error_occurred(1);
}
if (!BSP_remove_rtems_irq_handler (&clockIrqData)) {
printk("Unable to remove current system clock handler\n");
rtems_fatal_error_occurred(1);
}
/*
* Reinit structure
*/
clockIrqData.name = BSP_PERIODIC_TIMER;
clockIrqData.hdl = (rtems_irq_hdl) hdl;
clockIrqData.on = (rtems_irq_enable)clockOn;
clockIrqData.off = (rtems_irq_enable)clockOff;
clockIrqData.isOn = (rtems_irq_is_enabled)clockIsOn;
return BSP_install_rtems_irq_handler (&clockIrqData);
}

View File

@@ -0,0 +1,455 @@
/*
* MPC8xx Internal Memory Map
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
*
* The I/O on the MPC860 is comprised of blocks of special registers
* and the dual port ram for the Communication Processor Module.
* Within this space are functional units such as the SIU, memory
* controller, system timers, and other control functions. It is
* a combination that I found difficult to separate into logical
* functional files.....but anyone else is welcome to try. -- Dan
*/
#ifndef __IMMAP_8XX__
#define __IMMAP_8XX__
/* System configuration registers.
*/
typedef struct sys_conf {
unsigned int sc_siumcr;
unsigned int sc_sypcr;
unsigned int sc_swt;
char res1[2];
unsigned short sc_swsr;
unsigned int sc_sipend;
unsigned int sc_simask;
unsigned int sc_siel;
unsigned int sc_sivec;
unsigned int sc_tesr;
char res2[0xc];
unsigned int sc_sdcr;
char res3[0x4c];
} sysconf8xx_t;
/* PCMCIA configuration registers.
*/
typedef struct pcmcia_conf {
unsigned int pcmc_pbr0;
unsigned int pcmc_por0;
unsigned int pcmc_pbr1;
unsigned int pcmc_por1;
unsigned int pcmc_pbr2;
unsigned int pcmc_por2;
unsigned int pcmc_pbr3;
unsigned int pcmc_por3;
unsigned int pcmc_pbr4;
unsigned int pcmc_por4;
unsigned int pcmc_pbr5;
unsigned int pcmc_por5;
unsigned int pcmc_pbr6;
unsigned int pcmc_por6;
unsigned int pcmc_pbr7;
unsigned int pcmc_por7;
char res1[0x20];
unsigned int pcmc_pgcra;
unsigned int pcmc_pgcrb;
unsigned int pcmc_pscr;
char res2[4];
unsigned int pcmc_pipr;
char res3[4];
unsigned int pcmc_per;
char res4[4];
} pcmconf8xx_t;
/* Memory controller registers.
*/
typedef struct mem_ctlr {
unsigned int memc_br0;
unsigned int memc_or0;
unsigned int memc_br1;
unsigned int memc_or1;
unsigned int memc_br2;
unsigned int memc_or2;
unsigned int memc_br3;
unsigned int memc_or3;
unsigned int memc_br4;
unsigned int memc_or4;
unsigned int memc_br5;
unsigned int memc_or5;
unsigned int memc_br6;
unsigned int memc_or6;
unsigned int memc_br7;
unsigned int memc_or7;
char res1[0x24];
unsigned int memc_mar;
unsigned int memc_mcr;
char res2[4];
unsigned int memc_mamr;
unsigned int memc_mbmr;
unsigned short memc_mstat;
unsigned short memc_mptpr;
unsigned int memc_mdr;
char res3[0x80];
} memctl8xx_t;
/* System Integration Timers.
*/
typedef struct sys_int_timers {
unsigned short sit_tbscr;
unsigned int sit_tbreff0;
unsigned int sit_tbreff1;
char res1[0x14];
unsigned short sit_rtcsc;
unsigned int sit_rtc;
unsigned int sit_rtsec;
unsigned int sit_rtcal;
char res2[0x10];
unsigned short sit_piscr;
char res3[2];
unsigned int sit_pitc;
unsigned int sit_pitr;
char res4[0x34];
} sit8xx_t;
#define TBSCR_TBIRQ_MASK ((unsigned short)0xff00)
#define TBSCR_REFA ((unsigned short)0x0080)
#define TBSCR_REFB ((unsigned short)0x0040)
#define TBSCR_REFAE ((unsigned short)0x0008)
#define TBSCR_REFBE ((unsigned short)0x0004)
#define TBSCR_TBF ((unsigned short)0x0002)
#define TBSCR_TBE ((unsigned short)0x0001)
#define RTCSC_RTCIRQ_MASK ((unsigned short)0xff00)
#define RTCSC_SEC ((unsigned short)0x0080)
#define RTCSC_ALR ((unsigned short)0x0040)
#define RTCSC_38K ((unsigned short)0x0010)
#define RTCSC_SIE ((unsigned short)0x0008)
#define RTCSC_ALE ((unsigned short)0x0004)
#define RTCSC_RTF ((unsigned short)0x0002)
#define RTCSC_RTE ((unsigned short)0x0001)
#define PISCR_PIRQ_MASK ((unsigned short)0xff00)
#define PISCR_PS ((unsigned short)0x0080)
#define PISCR_PIE ((unsigned short)0x0004)
#define PISCR_PTF ((unsigned short)0x0002)
#define PISCR_PTE ((unsigned short)0x0001)
/* Clocks and Reset.
*/
typedef struct clk_and_reset {
unsigned int car_sccr;
unsigned int car_plprcr;
unsigned int car_rsr;
char res[0x74]; /* Reserved area */
} car8xx_t;
/* System Integration Timers keys.
*/
typedef struct sitk {
unsigned int sitk_tbscrk;
unsigned int sitk_tbreff0k;
unsigned int sitk_tbreff1k;
unsigned int sitk_tbk;
char res1[0x10];
unsigned int sitk_rtcsck;
unsigned int sitk_rtck;
unsigned int sitk_rtseck;
unsigned int sitk_rtcalk;
char res2[0x10];
unsigned int sitk_piscrk;
unsigned int sitk_pitck;
char res3[0x38];
} sitk8xx_t;
/* Clocks and reset keys.
*/
typedef struct cark {
unsigned int cark_sccrk;
unsigned int cark_plprcrk;
unsigned int cark_rsrk;
char res[0x474];
} cark8xx_t;
/* The key to unlock registers maintained by keep-alive power.
*/
#define KAPWR_KEY ((unsigned int)0x55ccaa33)
/* LCD interface. MPC821 Only.
*/
typedef struct lcd {
unsigned short lcd_lcolr[16];
char res[0x20];
unsigned int lcd_lccr;
unsigned int lcd_lchcr;
unsigned int lcd_lcvcr;
char res2[4];
unsigned int lcd_lcfaa;
unsigned int lcd_lcfba;
char lcd_lcsr;
char res3[0x7];
} lcd8xx_t;
/* I2C
*/
typedef struct i2c {
unsigned char i2c_i2mod;
char res1[3];
unsigned char i2c_i2add;
char res2[3];
unsigned char i2c_i2brg;
char res3[3];
unsigned char i2c_i2com;
char res4[3];
unsigned char i2c_i2cer;
char res5[3];
unsigned char i2c_i2cmr;
char res6[0x8b];
} i2c8xx_t;
/* DMA control/status registers.
*/
typedef struct sdma_csr {
char res1[4];
unsigned int sdma_sdar;
unsigned char sdma_sdsr;
char res3[3];
unsigned char sdma_sdmr;
char res4[3];
unsigned char sdma_idsr1;
char res5[3];
unsigned char sdma_idmr1;
char res6[3];
unsigned char sdma_idsr2;
char res7[3];
unsigned char sdma_idmr2;
char res8[0x13];
} sdma8xx_t;
/* Communication Processor Module Interrupt Controller.
*/
typedef struct cpm_ic {
unsigned short cpic_civr;
char res[0xe];
unsigned int cpic_cicr;
unsigned int cpic_cipr;
unsigned int cpic_cimr;
unsigned int cpic_cisr;
} cpic8xx_t;
/* Input/Output Port control/status registers.
*/
typedef struct io_port {
unsigned short iop_padir;
unsigned short iop_papar;
unsigned short iop_paodr;
unsigned short iop_padat;
char res1[8];
unsigned short iop_pcdir;
unsigned short iop_pcpar;
unsigned short iop_pcso;
unsigned short iop_pcdat;
unsigned short iop_pcint;
char res2[6];
unsigned short iop_pddir;
unsigned short iop_pdpar;
char res3[2];
unsigned short iop_pddat;
char res4[8];
} iop8xx_t;
/* Communication Processor Module Timers
*/
typedef struct cpm_timers {
unsigned short cpmt_tgcr;
char res1[0xe];
unsigned short cpmt_tmr1;
unsigned short cpmt_tmr2;
unsigned short cpmt_trr1;
unsigned short cpmt_trr2;
unsigned short cpmt_tcr1;
unsigned short cpmt_tcr2;
unsigned short cpmt_tcn1;
unsigned short cpmt_tcn2;
unsigned short cpmt_tmr3;
unsigned short cpmt_tmr4;
unsigned short cpmt_trr3;
unsigned short cpmt_trr4;
unsigned short cpmt_tcr3;
unsigned short cpmt_tcr4;
unsigned short cpmt_tcn3;
unsigned short cpmt_tcn4;
unsigned short cpmt_ter1;
unsigned short cpmt_ter2;
unsigned short cpmt_ter3;
unsigned short cpmt_ter4;
char res2[8];
} cpmtimer8xx_t;
/* Finally, the Communication Processor stuff.....
*/
typedef struct scc { /* Serial communication channels */
unsigned int scc_gsmrl;
unsigned int scc_gsmrh;
unsigned short scc_pmsr;
char res1[2];
unsigned short scc_todr;
unsigned short scc_dsr;
unsigned short scc_scce;
char res2[2];
unsigned short scc_sccm;
char res3;
unsigned char scc_sccs;
char res4[8];
} scc_t;
typedef struct smc { /* Serial management channels */
char res1[2];
unsigned short smc_smcmr;
char res2[2];
unsigned char smc_smce;
char res3[3];
unsigned char smc_smcm;
char res4[5];
} smc_t;
/* MPC860T Fast Ethernet Controller. It isn't part of the CPM, but
* it fits within the address space.
*/
typedef struct fec {
unsigned int fec_addr_low; /* LS 32 bits of station address */
unsigned short fec_addr_high; /* MS 16 bits of address */
unsigned short res1;
unsigned int fec_hash_table_high;
unsigned int fec_hash_table_low;
unsigned int fec_r_des_start;
unsigned int fec_x_des_start;
unsigned int fec_r_buff_size;
unsigned int res2[9];
unsigned int fec_ecntrl;
unsigned int fec_ievent;
unsigned int fec_imask;
unsigned int fec_ivec;
unsigned int fec_r_des_active;
unsigned int fec_x_des_active;
unsigned int res3[10];
unsigned int fec_mii_data;
unsigned int fec_mii_speed;
unsigned int res4[17];
unsigned int fec_r_bound;
unsigned int fec_r_fstart;
unsigned int res5[6];
unsigned int fec_x_fstart;
unsigned int res6[17];
unsigned int fec_fun_code;
unsigned int res7[3];
unsigned int fec_r_cntrl;
unsigned int fec_r_hash;
unsigned int res8[14];
unsigned int fec_x_cntrl;
unsigned int res9[0x1e];
} fec_t;
typedef struct comm_proc {
/* General control and status registers.
*/
unsigned short cp_cpcr;
char res1[2];
unsigned short cp_rccr;
char res2[6];
unsigned short cp_cpmcr1;
unsigned short cp_cpmcr2;
unsigned short cp_cpmcr3;
unsigned short cp_cpmcr4;
char res3[2];
unsigned short cp_rter;
char res4[2];
unsigned short cp_rtmr;
char res5[0x14];
/* Baud rate generators.
*/
unsigned int cp_brgc1;
unsigned int cp_brgc2;
unsigned int cp_brgc3;
unsigned int cp_brgc4;
/* Serial Communication Channels.
*/
scc_t cp_scc[4];
/* Serial Management Channels.
*/
smc_t cp_smc[2];
/* Serial Peripheral Interface.
*/
unsigned short cp_spmode;
char res6[4];
unsigned char cp_spie;
char res7[3];
unsigned char cp_spim;
char res8[2];
unsigned char cp_spcom;
char res9[2];
/* Parallel Interface Port.
*/
char res10[2];
unsigned short cp_pipc;
char res11[2];
unsigned short cp_ptpr;
unsigned int cp_pbdir;
unsigned int cp_pbpar;
char res12[2];
unsigned short cp_pbodr;
unsigned int cp_pbdat;
char res13[0x18];
/* Serial Interface and Time Slot Assignment.
*/
unsigned int cp_simode;
unsigned char cp_sigmr;
char res14;
unsigned char cp_sistr;
unsigned char cp_sicmr;
char res15[4];
unsigned int cp_sicr;
unsigned int cp_sirp;
char res16[0x10c];
unsigned char cp_siram[0x200];
/* The fast ethernet controller is not really part of the CPM,
* but it resides in the address space.
*/
fec_t cp_fec;
char res18[0x1000];
/* Dual Ported RAM follows.
* There are many different formats for this memory area
* depending upon the devices used and options chosen.
*/
unsigned char cp_dpmem[0x1000]; /* BD / Data / ucode */
unsigned char res19[0xc00];
unsigned char cp_dparam[0x400]; /* Parameter RAM */
} cpm8xx_t;
/* Internal memory map.
*/
typedef struct immap {
sysconf8xx_t im_siu_conf; /* SIU Configuration */
pcmconf8xx_t im_pcmcia; /* PCMCIA Configuration */
memctl8xx_t im_memctl; /* Memory Controller */
sit8xx_t im_sit; /* System integration timers */
car8xx_t im_clkrst; /* Clocks and reset */
sitk8xx_t im_sitk; /* Sys int timer keys */
cark8xx_t im_clkrstk; /* Clocks and reset keys */
lcd8xx_t im_lcd; /* LCD (821 only) */
i2c8xx_t im_i2c; /* I2C control/status */
sdma8xx_t im_sdma; /* SDMA control/status */
cpic8xx_t im_cpic; /* CPM Interrupt Controller */
iop8xx_t im_ioport; /* IO Port control/status */
cpmtimer8xx_t im_cpmtimer; /* CPM timers */
cpm8xx_t im_cpm; /* Communication processor */
} immap_t;
#endif /* __IMMAP_8XX__ */

View File

@@ -0,0 +1,529 @@
/*
* MPC8xx Communication Processor Module.
* Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
*
* This file contains structures and information for the communication
* processor channels. Some CPM control and status is available
* throught the MPC8xx internal memory map. See immap.h for details.
* This file only contains what I need for the moment, not the total
* CPM capabilities. I (or someone else) will add definitions as they
* are needed. -- Dan
*
* On the MBX board, EPPC-Bug loads CPM microcode into the first 512
* bytes of the DP RAM and relocates the I2C parameter area to the
* IDMA1 space. The remaining DP RAM is available for buffer descriptors
* or other use.
*/
#ifndef __CPM_8XX__
#define __CPM_8XX__
#include <bsp/8xx_immap.h>
/* CPM Command register.
*/
#define CPM_CR_RST ((ushort)0x8000)
#define CPM_CR_OPCODE ((ushort)0x0f00)
#define CPM_CR_CHAN ((ushort)0x00f0)
#define CPM_CR_FLG ((ushort)0x0001)
/* Some commands (there are more...later)
*/
#define CPM_CR_INIT_TRX ((ushort)0x0000)
#define CPM_CR_INIT_RX ((ushort)0x0001)
#define CPM_CR_INIT_TX ((ushort)0x0002)
#define CPM_CR_STOP_TX ((ushort)0x0004)
#define CPM_CR_RESTART_TX ((ushort)0x0006)
#define CPM_CR_SET_GADDR ((ushort)0x0008)
/* Channel numbers.
*/
#define CPM_CR_CH_SCC1 ((ushort)0x0000)
#define CPM_CR_CH_I2C ((ushort)0x0001) /* I2C and IDMA1 */
#define CPM_CR_CH_SCC2 ((ushort)0x0004)
#define CPM_CR_CH_SPI ((ushort)0x0005) /* SPI / IDMA2 / Timers */
#define CPM_CR_CH_SCC3 ((ushort)0x0008)
#define CPM_CR_CH_SMC1 ((ushort)0x0009) /* SMC1 / DSP1 */
#define CPM_CR_CH_SCC4 ((ushort)0x000c)
#define CPM_CR_CH_SMC2 ((ushort)0x000d) /* SMC2 / DSP2 */
#define mk_cr_cmd(CH, CMD) ((CMD << 8) | (CH << 4))
/* The dual ported RAM is multi-functional. Some areas can be (and are
* being) used for microcode. There is an area that can only be used
* as data ram for buffer descriptors, which is all we use right now.
* Currently the first 512 and last 256 bytes are used for microcode.
*/
#define CPM_DATAONLY_BASE ((uint)0x0800)
#define CPM_DATAONLY_SIZE ((uint)0x0700)
#define CPM_DP_NOSPACE ((uint)0x7fffffff)
/* Export the base address of the communication processor registers
* and dual port ram.
*/
extern cpm8xx_t *cpmp; /* Pointer to comm processor */
uint m8xx_cpm_dpalloc(uint size);
uint m8xx_cpm_hostalloc(uint size);
void m8xx_cpm_setbrg(uint brg, uint rate);
/* Buffer descriptors used by many of the CPM protocols.
*/
typedef struct cpm_buf_desc {
ushort cbd_sc; /* Status and Control */
ushort cbd_datlen; /* Data length in buffer */
uint cbd_bufaddr; /* Buffer address in host memory */
} cbd_t;
#define BD_SC_EMPTY ((ushort)0x8000) /* Recieve is empty */
#define BD_SC_READY ((ushort)0x8000) /* Transmit is ready */
#define BD_SC_WRAP ((ushort)0x2000) /* Last buffer descriptor */
#define BD_SC_INTRPT ((ushort)0x1000) /* Interrupt on change */
#define BD_SC_CM ((ushort)0x0200) /* Continous mode */
#define BD_SC_ID ((ushort)0x0100) /* Rec'd too many idles */
#define BD_SC_P ((ushort)0x0100) /* xmt preamble */
#define BD_SC_BR ((ushort)0x0020) /* Break received */
#define BD_SC_FR ((ushort)0x0010) /* Framing error */
#define BD_SC_PR ((ushort)0x0008) /* Parity error */
#define BD_SC_OV ((ushort)0x0002) /* Overrun */
#define BD_SC_CD ((ushort)0x0001) /* ?? */
/* Parameter RAM offsets.
*/
#define PROFF_SCC1 ((uint)0x0000)
#define PROFF_SCC2 ((uint)0x0100)
#define PROFF_SCC3 ((uint)0x0200)
#define PROFF_SMC1 ((uint)0x0280)
#define PROFF_SCC4 ((uint)0x0300)
#define PROFF_SMC2 ((uint)0x0380)
/* Define enough so I can at least use the serial port as a UART.
*/
typedef struct smc_uart {
ushort smc_rbase; /* Rx Buffer descriptor base address */
ushort smc_tbase; /* Tx Buffer descriptor base address */
u_char smc_rfcr; /* Rx function code */
u_char smc_tfcr; /* Tx function code */
ushort smc_mrblr; /* Max receive buffer length */
uint smc_rstate; /* Internal */
uint smc_idp; /* Internal */
ushort smc_rbptr; /* Internal */
ushort smc_ibc; /* Internal */
uint smc_rxtmp; /* Internal */
uint smc_tstate; /* Internal */
uint smc_tdp; /* Internal */
ushort smc_tbptr; /* Internal */
ushort smc_tbc; /* Internal */
uint smc_txtmp; /* Internal */
ushort smc_maxidl; /* Maximum idle characters */
ushort smc_tmpidl; /* Temporary idle counter */
ushort smc_brklen; /* Last received break length */
ushort smc_brkec; /* rcv'd break condition counter */
ushort smc_brkcr; /* xmt break count register */
ushort smc_rmask; /* Temporary bit mask */
} smc_uart_t;
/* Function code bits.
*/
#define SMC_EB ((u_char)0x10) /* Set big endian byte order */
/* SMC uart mode register.
*/
#define SMCMR_REN ((ushort)0x0001)
#define SMCMR_TEN ((ushort)0x0002)
#define SMCMR_DM ((ushort)0x000c)
#define SMCMR_SM_GCI ((ushort)0x0000)
#define SMCMR_SM_UART ((ushort)0x0020)
#define SMCMR_SM_TRANS ((ushort)0x0030)
#define SMCMR_SM_MASK ((ushort)0x0030)
#define SMCMR_PM_EVEN ((ushort)0x0100) /* Even parity, else odd */
#define SMCMR_PEN ((ushort)0x0200) /* Parity enable */
#define SMCMR_SL ((ushort)0x0400) /* Two stops, else one */
#define SMCR_CLEN_MASK ((ushort)0x7800) /* Character length */
#define smcr_mk_clen(C) (((C) << 11) & SMCR_CLEN_MASK)
/* SMC Event and Mask register.
*/
#define SMCM_TXE ((unsigned char)0x10)
#define SMCM_BSY ((unsigned char)0x04)
#define SMCM_TX ((unsigned char)0x02)
#define SMCM_RX ((unsigned char)0x01)
/* Baud rate generators.
*/
#define CPM_BRG_RST ((uint)0x00020000)
#define CPM_BRG_EN ((uint)0x00010000)
#define CPM_BRG_EXTC_INT ((uint)0x00000000)
#define CPM_BRG_EXTC_CLK2 ((uint)0x00004000)
#define CPM_BRG_EXTC_CLK6 ((uint)0x00008000)
#define CPM_BRG_ATB ((uint)0x00002000)
#define CPM_BRG_CD_MASK ((uint)0x00001ffe)
#define CPM_BRG_DIV16 ((uint)0x00000001)
/* SCCs.
*/
#define SCC_GSMRH_IRP ((uint)0x00040000)
#define SCC_GSMRH_GDE ((uint)0x00010000)
#define SCC_GSMRH_TCRC_CCITT ((uint)0x00008000)
#define SCC_GSMRH_TCRC_BISYNC ((uint)0x00004000)
#define SCC_GSMRH_TCRC_HDLC ((uint)0x00000000)
#define SCC_GSMRH_REVD ((uint)0x00002000)
#define SCC_GSMRH_TRX ((uint)0x00001000)
#define SCC_GSMRH_TTX ((uint)0x00000800)
#define SCC_GSMRH_CDP ((uint)0x00000400)
#define SCC_GSMRH_CTSP ((uint)0x00000200)
#define SCC_GSMRH_CDS ((uint)0x00000100)
#define SCC_GSMRH_CTSS ((uint)0x00000080)
#define SCC_GSMRH_TFL ((uint)0x00000040)
#define SCC_GSMRH_RFW ((uint)0x00000020)
#define SCC_GSMRH_TXSY ((uint)0x00000010)
#define SCC_GSMRH_SYNL16 ((uint)0x0000000c)
#define SCC_GSMRH_SYNL8 ((uint)0x00000008)
#define SCC_GSMRH_SYNL4 ((uint)0x00000004)
#define SCC_GSMRH_RTSM ((uint)0x00000002)
#define SCC_GSMRH_RSYN ((uint)0x00000001)
#define SCC_GSMRL_SIR ((uint)0x80000000) /* SCC2 only */
#define SCC_GSMRL_EDGE_NONE ((uint)0x60000000)
#define SCC_GSMRL_EDGE_NEG ((uint)0x40000000)
#define SCC_GSMRL_EDGE_POS ((uint)0x20000000)
#define SCC_GSMRL_EDGE_BOTH ((uint)0x00000000)
#define SCC_GSMRL_TCI ((uint)0x10000000)
#define SCC_GSMRL_TSNC_3 ((uint)0x0c000000)
#define SCC_GSMRL_TSNC_4 ((uint)0x08000000)
#define SCC_GSMRL_TSNC_14 ((uint)0x04000000)
#define SCC_GSMRL_TSNC_INF ((uint)0x00000000)
#define SCC_GSMRL_RINV ((uint)0x02000000)
#define SCC_GSMRL_TINV ((uint)0x01000000)
#define SCC_GSMRL_TPL_128 ((uint)0x00c00000)
#define SCC_GSMRL_TPL_64 ((uint)0x00a00000)
#define SCC_GSMRL_TPL_48 ((uint)0x00800000)
#define SCC_GSMRL_TPL_32 ((uint)0x00600000)
#define SCC_GSMRL_TPL_16 ((uint)0x00400000)
#define SCC_GSMRL_TPL_8 ((uint)0x00200000)
#define SCC_GSMRL_TPL_NONE ((uint)0x00000000)
#define SCC_GSMRL_TPP_ALL1 ((uint)0x00180000)
#define SCC_GSMRL_TPP_01 ((uint)0x00100000)
#define SCC_GSMRL_TPP_10 ((uint)0x00080000)
#define SCC_GSMRL_TPP_ZEROS ((uint)0x00000000)
#define SCC_GSMRL_TEND ((uint)0x00040000)
#define SCC_GSMRL_TDCR_32 ((uint)0x00030000)
#define SCC_GSMRL_TDCR_16 ((uint)0x00020000)
#define SCC_GSMRL_TDCR_8 ((uint)0x00010000)
#define SCC_GSMRL_TDCR_1 ((uint)0x00000000)
#define SCC_GSMRL_RDCR_32 ((uint)0x0000c000)
#define SCC_GSMRL_RDCR_16 ((uint)0x00008000)
#define SCC_GSMRL_RDCR_8 ((uint)0x00004000)
#define SCC_GSMRL_RDCR_1 ((uint)0x00000000)
#define SCC_GSMRL_RENC_DFMAN ((uint)0x00003000)
#define SCC_GSMRL_RENC_MANCH ((uint)0x00002000)
#define SCC_GSMRL_RENC_FM0 ((uint)0x00001000)
#define SCC_GSMRL_RENC_NRZI ((uint)0x00000800)
#define SCC_GSMRL_RENC_NRZ ((uint)0x00000000)
#define SCC_GSMRL_TENC_DFMAN ((uint)0x00000600)
#define SCC_GSMRL_TENC_MANCH ((uint)0x00000400)
#define SCC_GSMRL_TENC_FM0 ((uint)0x00000200)
#define SCC_GSMRL_TENC_NRZI ((uint)0x00000100)
#define SCC_GSMRL_TENC_NRZ ((uint)0x00000000)
#define SCC_GSMRL_DIAG_LE ((uint)0x000000c0) /* Loop and echo */
#define SCC_GSMRL_DIAG_ECHO ((uint)0x00000080)
#define SCC_GSMRL_DIAG_LOOP ((uint)0x00000040)
#define SCC_GSMRL_DIAG_NORM ((uint)0x00000000)
#define SCC_GSMRL_ENR ((uint)0x00000020)
#define SCC_GSMRL_ENT ((uint)0x00000010)
#define SCC_GSMRL_MODE_ENET ((uint)0x0000000c)
#define SCC_GSMRL_MODE_DDCMP ((uint)0x00000009)
#define SCC_GSMRL_MODE_BISYNC ((uint)0x00000008)
#define SCC_GSMRL_MODE_V14 ((uint)0x00000007)
#define SCC_GSMRL_MODE_AHDLC ((uint)0x00000006)
#define SCC_GSMRL_MODE_PROFIBUS ((uint)0x00000005)
#define SCC_GSMRL_MODE_UART ((uint)0x00000004)
#define SCC_GSMRL_MODE_SS7 ((uint)0x00000003)
#define SCC_GSMRL_MODE_ATALK ((uint)0x00000002)
#define SCC_GSMRL_MODE_HDLC ((uint)0x00000000)
#define SCC_TODR_TOD ((ushort)0x8000)
/* SCC Event and Mask register.
*/
#define SCCM_TXE ((unsigned char)0x10)
#define SCCM_BSY ((unsigned char)0x04)
#define SCCM_TX ((unsigned char)0x02)
#define SCCM_RX ((unsigned char)0x01)
typedef struct scc_param {
ushort scc_rbase; /* Rx Buffer descriptor base address */
ushort scc_tbase; /* Tx Buffer descriptor base address */
u_char scc_rfcr; /* Rx function code */
u_char scc_tfcr; /* Tx function code */
ushort scc_mrblr; /* Max receive buffer length */
uint scc_rstate; /* Internal */
uint scc_idp; /* Internal */
ushort scc_rbptr; /* Internal */
ushort scc_ibc; /* Internal */
uint scc_rxtmp; /* Internal */
uint scc_tstate; /* Internal */
uint scc_tdp; /* Internal */
ushort scc_tbptr; /* Internal */
ushort scc_tbc; /* Internal */
uint scc_txtmp; /* Internal */
uint scc_rcrc; /* Internal */
uint scc_tcrc; /* Internal */
} sccp_t;
/* Function code bits.
*/
#define SCC_EB ((u_char)0x10) /* Set big endian byte order */
/* CPM Ethernet through SCC1.
*/
typedef struct scc_enet {
sccp_t sen_genscc;
uint sen_cpres; /* Preset CRC */
uint sen_cmask; /* Constant mask for CRC */
uint sen_crcec; /* CRC Error counter */
uint sen_alec; /* alignment error counter */
uint sen_disfc; /* discard frame counter */
ushort sen_pads; /* Tx short frame pad character */
ushort sen_retlim; /* Retry limit threshold */
ushort sen_retcnt; /* Retry limit counter */
ushort sen_maxflr; /* maximum frame length register */
ushort sen_minflr; /* minimum frame length register */
ushort sen_maxd1; /* maximum DMA1 length */
ushort sen_maxd2; /* maximum DMA2 length */
ushort sen_maxd; /* Rx max DMA */
ushort sen_dmacnt; /* Rx DMA counter */
ushort sen_maxb; /* Max BD byte count */
ushort sen_gaddr1; /* Group address filter */
ushort sen_gaddr2;
ushort sen_gaddr3;
ushort sen_gaddr4;
uint sen_tbuf0data0; /* Save area 0 - current frame */
uint sen_tbuf0data1; /* Save area 1 - current frame */
uint sen_tbuf0rba; /* Internal */
uint sen_tbuf0crc; /* Internal */
ushort sen_tbuf0bcnt; /* Internal */
ushort sen_paddrh; /* physical address (MSB) */
ushort sen_paddrm;
ushort sen_paddrl; /* physical address (LSB) */
ushort sen_pper; /* persistence */
ushort sen_rfbdptr; /* Rx first BD pointer */
ushort sen_tfbdptr; /* Tx first BD pointer */
ushort sen_tlbdptr; /* Tx last BD pointer */
uint sen_tbuf1data0; /* Save area 0 - current frame */
uint sen_tbuf1data1; /* Save area 1 - current frame */
uint sen_tbuf1rba; /* Internal */
uint sen_tbuf1crc; /* Internal */
ushort sen_tbuf1bcnt; /* Internal */
ushort sen_txlen; /* Tx Frame length counter */
ushort sen_iaddr1; /* Individual address filter */
ushort sen_iaddr2;
ushort sen_iaddr3;
ushort sen_iaddr4;
ushort sen_boffcnt; /* Backoff counter */
/* NOTE: Some versions of the manual have the following items
* incorrectly documented. Below is the proper order.
*/
ushort sen_taddrh; /* temp address (MSB) */
ushort sen_taddrm;
ushort sen_taddrl; /* temp address (LSB) */
} scc_enet_t;
/* Bits in parallel I/O port registers that have to be set/cleared
* to configure the pins for SCC1 use. The TCLK and RCLK seem unique
* to the MBX860 board. Any two of the four available clocks could be
* used, and the MPC860 cookbook manual has an example using different
* clock pins.
*/
#define PA_ENET_RXD ((ushort)0x0001)
#define PA_ENET_TXD ((ushort)0x0002)
#define PA_ENET_TCLK ((ushort)0x0200)
#define PA_ENET_RCLK ((ushort)0x0800)
#define PC_ENET_TENA ((ushort)0x0001)
#define PC_ENET_CLSN ((ushort)0x0010)
#define PC_ENET_RENA ((ushort)0x0020)
/* Control bits in the SICR to route TCLK (CLK2) and RCLK (CLK4) to
* SCC1. Also, make sure GR1 (bit 24) and SC1 (bit 25) are zero.
*/
#define SICR_ENET_MASK ((uint)0x000000ff)
#define SICR_ENET_CLKRT ((uint)0x0000003d)
/* SCC Event register as used by Ethernet.
*/
#define SCCE_ENET_GRA ((ushort)0x0080) /* Graceful stop complete */
#define SCCE_ENET_TXE ((ushort)0x0010) /* Transmit Error */
#define SCCE_ENET_RXF ((ushort)0x0008) /* Full frame received */
#define SCCE_ENET_BSY ((ushort)0x0004) /* All incoming buffers full */
#define SCCE_ENET_TXB ((ushort)0x0002) /* A buffer was transmitted */
#define SCCE_ENET_RXB ((ushort)0x0001) /* A buffer was received */
/* SCC Mode Register (PMSR) as used by Ethernet.
*/
#define SCC_PMSR_HBC ((ushort)0x8000) /* Enable heartbeat */
#define SCC_PMSR_FC ((ushort)0x4000) /* Force collision */
#define SCC_PMSR_RSH ((ushort)0x2000) /* Receive short frames */
#define SCC_PMSR_IAM ((ushort)0x1000) /* Check individual hash */
#define SCC_PMSR_ENCRC ((ushort)0x0800) /* Ethernet CRC mode */
#define SCC_PMSR_PRO ((ushort)0x0200) /* Promiscuous mode */
#define SCC_PMSR_BRO ((ushort)0x0100) /* Catch broadcast pkts */
#define SCC_PMSR_SBT ((ushort)0x0080) /* Special backoff timer */
#define SCC_PMSR_LPB ((ushort)0x0040) /* Set Loopback mode */
#define SCC_PMSR_SIP ((ushort)0x0020) /* Sample Input Pins */
#define SCC_PMSR_LCW ((ushort)0x0010) /* Late collision window */
#define SCC_PMSR_NIB22 ((ushort)0x000a) /* Start frame search */
#define SCC_PMSR_FDE ((ushort)0x0001) /* Full duplex enable */
/* Buffer descriptor control/status used by Ethernet receive.
*/
#define BD_ENET_RX_EMPTY ((ushort)0x8000)
#define BD_ENET_RX_WRAP ((ushort)0x2000)
#define BD_ENET_RX_INTR ((ushort)0x1000)
#define BD_ENET_RX_LAST ((ushort)0x0800)
#define BD_ENET_RX_FIRST ((ushort)0x0400)
#define BD_ENET_RX_MISS ((ushort)0x0100)
#define BD_ENET_RX_LG ((ushort)0x0020)
#define BD_ENET_RX_NO ((ushort)0x0010)
#define BD_ENET_RX_SH ((ushort)0x0008)
#define BD_ENET_RX_CR ((ushort)0x0004)
#define BD_ENET_RX_OV ((ushort)0x0002)
#define BD_ENET_RX_CL ((ushort)0x0001)
#define BD_ENET_RX_STATS ((ushort)0x013f) /* All status bits */
/* Buffer descriptor control/status used by Ethernet transmit.
*/
#define BD_ENET_TX_READY ((ushort)0x8000)
#define BD_ENET_TX_PAD ((ushort)0x4000)
#define BD_ENET_TX_WRAP ((ushort)0x2000)
#define BD_ENET_TX_INTR ((ushort)0x1000)
#define BD_ENET_TX_LAST ((ushort)0x0800)
#define BD_ENET_TX_TC ((ushort)0x0400)
#define BD_ENET_TX_DEF ((ushort)0x0200)
#define BD_ENET_TX_HB ((ushort)0x0100)
#define BD_ENET_TX_LC ((ushort)0x0080)
#define BD_ENET_TX_RL ((ushort)0x0040)
#define BD_ENET_TX_RCMASK ((ushort)0x003c)
#define BD_ENET_TX_UN ((ushort)0x0002)
#define BD_ENET_TX_CSL ((ushort)0x0001)
#define BD_ENET_TX_STATS ((ushort)0x03ff) /* All status bits */
/* SCC as UART
*/
typedef struct scc_uart {
sccp_t scc_genscc;
uint scc_res1; /* Reserved */
uint scc_res2; /* Reserved */
ushort scc_maxidl; /* Maximum idle chars */
ushort scc_idlc; /* temp idle counter */
ushort scc_brkcr; /* Break count register */
ushort scc_parec; /* receive parity error counter */
ushort scc_frmec; /* receive framing error counter */
ushort scc_nosec; /* receive noise counter */
ushort scc_brkec; /* receive break condition counter */
ushort scc_brkln; /* last received break length */
ushort scc_uaddr1; /* UART address character 1 */
ushort scc_uaddr2; /* UART address character 2 */
ushort scc_rtemp; /* Temp storage */
ushort scc_toseq; /* Transmit out of sequence char */
ushort scc_char1; /* control character 1 */
ushort scc_char2; /* control character 2 */
ushort scc_char3; /* control character 3 */
ushort scc_char4; /* control character 4 */
ushort scc_char5; /* control character 5 */
ushort scc_char6; /* control character 6 */
ushort scc_char7; /* control character 7 */
ushort scc_char8; /* control character 8 */
ushort scc_rccm; /* receive control character mask */
ushort scc_rccr; /* receive control character register */
ushort scc_rlbc; /* receive last break character */
} scc_uart_t;
/* SCC Event and Mask registers when it is used as a UART.
*/
#define UART_SCCM_GLR ((ushort)0x1000)
#define UART_SCCM_GLT ((ushort)0x0800)
#define UART_SCCM_AB ((ushort)0x0200)
#define UART_SCCM_IDL ((ushort)0x0100)
#define UART_SCCM_GRA ((ushort)0x0080)
#define UART_SCCM_BRKE ((ushort)0x0040)
#define UART_SCCM_BRKS ((ushort)0x0020)
#define UART_SCCM_CCR ((ushort)0x0008)
#define UART_SCCM_BSY ((ushort)0x0004)
#define UART_SCCM_TX ((ushort)0x0002)
#define UART_SCCM_RX ((ushort)0x0001)
/* The SCC PMSR when used as a UART.
*/
#define SCU_PMSR_FLC ((ushort)0x8000)
#define SCU_PMSR_SL ((ushort)0x4000)
#define SCU_PMSR_CL ((ushort)0x3000)
#define SCU_PMSR_UM ((ushort)0x0c00)
#define SCU_PMSR_FRZ ((ushort)0x0200)
#define SCU_PMSR_RZS ((ushort)0x0100)
#define SCU_PMSR_SYN ((ushort)0x0080)
#define SCU_PMSR_DRT ((ushort)0x0040)
#define SCU_PMSR_PEN ((ushort)0x0010)
#define SCU_PMSR_RPM ((ushort)0x000c)
#define SCU_PMSR_REVP ((ushort)0x0008)
#define SCU_PMSR_TPM ((ushort)0x0003)
#define SCU_PMSR_TEVP ((ushort)0x0003)
/* CPM Transparent mode SCC.
*/
typedef struct scc_trans {
sccp_t st_genscc;
uint st_cpres; /* Preset CRC */
uint st_cmask; /* Constant mask for CRC */
} scc_trans_t;
/* CPM interrupts. There are nearly 32 interrupts generated by CPM
* channels or devices. All of these are presented to the PPC core
* as a single interrupt. The CPM interrupt handler dispatches its
* own handlers, in a similar fashion to the PPC core handler. We
* use the table as defined in the manuals (i.e. no special high
* priority and SCC1 == SCCa, etc...).
*/
#define CPMVEC_NR 32
#define CPMVEC_PIO_PC15 ((ushort)0x1f)
#define CPMVEC_SCC1 ((ushort)0x1e)
#define CPMVEC_SCC2 ((ushort)0x1d)
#define CPMVEC_SCC3 ((ushort)0x1c)
#define CPMVEC_SCC4 ((ushort)0x1b)
#define CPMVEC_PIO_PC14 ((ushort)0x1a)
#define CPMVEC_TIMER1 ((ushort)0x19)
#define CPMVEC_PIO_PC13 ((ushort)0x18)
#define CPMVEC_PIO_PC12 ((ushort)0x17)
#define CPMVEC_SDMA_CB_ERR ((ushort)0x16)
#define CPMVEC_IDMA1 ((ushort)0x15)
#define CPMVEC_IDMA2 ((ushort)0x14)
#define CPMVEC_TIMER2 ((ushort)0x12)
#define CPMVEC_RISCTIMER ((ushort)0x11)
#define CPMVEC_I2C ((ushort)0x10)
#define CPMVEC_PIO_PC11 ((ushort)0x0f)
#define CPMVEC_PIO_PC10 ((ushort)0x0e)
#define CPMVEC_TIMER3 ((ushort)0x0c)
#define CPMVEC_PIO_PC9 ((ushort)0x0b)
#define CPMVEC_PIO_PC8 ((ushort)0x0a)
#define CPMVEC_PIO_PC7 ((ushort)0x09)
#define CPMVEC_TIMER4 ((ushort)0x07)
#define CPMVEC_PIO_PC6 ((ushort)0x06)
#define CPMVEC_SPI ((ushort)0x05)
#define CPMVEC_SMC1 ((ushort)0x04)
#define CPMVEC_SMC2 ((ushort)0x03)
#define CPMVEC_PIO_PC5 ((ushort)0x02)
#define CPMVEC_PIO_PC4 ((ushort)0x01)
#define CPMVEC_ERROR ((ushort)0x00)
extern void cpm_install_handler(int vec, void (*handler)(void *), void *dev_id);
/* CPM interrupt configuration vector.
*/
#define CICR_SCD_SCC4 ((uint)0x00c00000) /* SCC4 @ SCCd */
#define CICR_SCC_SCC3 ((uint)0x00200000) /* SCC3 @ SCCc */
#define CICR_SCB_SCC2 ((uint)0x00040000) /* SCC2 @ SCCb */
#define CICR_SCA_SCC1 ((uint)0x00000000) /* SCC1 @ SCCa */
#define CICR_IRL_MASK ((uint)0x0000e000) /* Core interrrupt */
#define CICR_HP_MASK ((uint)0x00001f00) /* Hi-pri int. */
#define CICR_IEN ((uint)0x00000080) /* Int. enable */
#define CICR_SPS ((uint)0x00000001) /* SCC Spread */
#endif /* __CPM_8XX__ */

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,46 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
C_FILES = irq.c irq_init.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
H_FILES = irq.h
S_FILES = irq_asm.S
S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o)
OBJS = $(C_O_FILES) $(S_O_FILES)
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../../../automake/compile.am
include $(top_srcdir)/../../../../../../automake/lib.am
SORDID_HACK:
rm -f $(PROJECT_INCLUDE)/bsp/irq.h
$(PROJECT_INCLUDE)/bsp:
$(mkinstalldirs) $@
$(PROJECT_INCLUDE)/bsp/%.h: %.h
$(INSTALL_DATA) $< $@
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp \
$(H_FILES:%.h=$(PROJECT_INCLUDE)/bsp/%.h)
#
# (OPTIONAL) Add local stuff here using +=
#
$(PGM): $(OBJS)
$(make-rel)
# the .rel file built here will be put into libbsp.a by ../wrapup/Makefile
all-local: SORDID_HACK $(PREINSTALL_FILES) $(ARCH) $(OBJS) $(PGM)
EXTRA_DIST = irq.c irq.h irq_asm.S irq_init.c
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,505 @@
/*
*
* This file contains the implementation of the function described in irq.h
*
* Copyright (C) 1998, 1999 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <bsp.h>
#include <bsp/irq.h>
#include <rtems/score/thread.h>
#include <rtems/score/apiext.h>
#include <libcpu/raw_exception.h>
#include <bsp/vectors.h>
#include <libcpu/cpu.h>
#include <bsp/8xx_immap.h>
#include <bsp/commproc.h>
/*
* default handler connected on each irq after bsp initialization
*/
static rtems_irq_connect_data default_rtems_entry;
/*
* location used to store initial tables used for interrupt
* management.
*/
static rtems_irq_global_settings* internal_config;
static rtems_irq_connect_data* rtems_hdl_tbl;
/*
* Check if symbolic IRQ name is an SIU IRQ
*/
static inline int is_siu_irq(const rtems_irq_symbolic_name irqLine)
{
return (((int) irqLine <= BSP_SIU_IRQ_MAX_OFFSET) &
((int) irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET)
);
}
/*
* Check if symbolic IRQ name is an CPM IRQ
*/
static inline int is_cpm_irq(const rtems_irq_symbolic_name irqLine)
{
return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) &
((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET)
);
}
/*
* Check if symbolic IRQ name is a Processor IRQ
*/
static inline int is_processor_irq(const rtems_irq_symbolic_name irqLine)
{
return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) &
((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)
);
}
/*
* masks used to mask off the interrupts. For exmaple, for ILVL2, the
* mask is used to mask off interrupts ILVL2, IRQ3, ILVL3, ... IRQ7
* and ILVL7.
*
*/
const static unsigned int SIU_IvectMask[BSP_SIU_IRQ_NUMBER] =
{
/* IRQ0 ILVL0 IRQ1 ILVL1 */
0x00000000, 0x80000000, 0xC0000000, 0xE0000000,
/* IRQ2 ILVL2 IRQ3 ILVL3 */
0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000,
/* IRQ4 ILVL4 IRQ5 ILVL5 */
0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
/* IRQ6 ILVL6 IRQ7 ILVL7 */
0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000
};
/*
* ------------------------ RTEMS Irq helper functions ----------------
*/
/*
* Caution : this function assumes the variable "internal_config"
* is already set and that the tables it contains are still valid
* and accessible.
*/
static void compute_SIU_IvectMask_from_prio ()
{
/*
* In theory this is feasible. No time to code it yet. See i386/shared/irq.c
* for an example based on 8259 controller mask. The actual masks defined
* correspond to the priorities defined for the SIU in irq_init.c.
*/
}
/*
* This function check that the value given for the irq line
* is valid.
*/
static int isValidInterrupt(int irq)
{
if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET) || (irq == BSP_CPM_INTERRUPT) )
return 0;
return 1;
}
int BSP_irq_enable_at_cpm(const rtems_irq_symbolic_name irqLine)
{
int cpm_irq_index;
if (!is_cpm_irq(irqLine))
return 1;
cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << cpm_irq_index);
return 0;
}
int BSP_irq_disable_at_cpm(const rtems_irq_symbolic_name irqLine)
{
int cpm_irq_index;
if (!is_cpm_irq(irqLine))
return 1;
cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << cpm_irq_index);
return 0;
}
int BSP_irq_enabled_at_cpm(const rtems_irq_symbolic_name irqLine)
{
int cpm_irq_index;
if (!is_cpm_irq(irqLine))
return 0;
cpm_irq_index = ((int) (irqLine) - BSP_CPM_IRQ_LOWEST_OFFSET);
return (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr & (1 << cpm_irq_index));
}
int BSP_irq_enable_at_siu(const rtems_irq_symbolic_name irqLine)
{
int siu_irq_index;
if (!is_siu_irq(irqLine))
return 1;
siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
ppc_cached_irq_mask |= (1 << (31-siu_irq_index));
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
return 0;
}
int BSP_irq_disable_at_siu(const rtems_irq_symbolic_name irqLine)
{
int siu_irq_index;
if (!is_siu_irq(irqLine))
return 1;
siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
ppc_cached_irq_mask &= ~(1 << (31-siu_irq_index));
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
return 0;
}
int BSP_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine)
{
int siu_irq_index;
if (!is_siu_irq(irqLine))
return 0;
siu_irq_index = ((int) (irqLine) - BSP_SIU_IRQ_LOWEST_OFFSET);
return ppc_cached_irq_mask & (1 << (31-siu_irq_index));
}
/*
* ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
*/
int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
{
unsigned int level;
if (!isValidInterrupt(irq->name)) {
return 0;
}
/*
* Check if default handler is actually connected. If not issue an error.
* You must first get the current handler via i386_get_current_idt_entry
* and then disconnect it using i386_delete_idt_entry.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
return 0;
}
_CPU_ISR_Disable(level);
/*
* store the data provided by user
*/
rtems_hdl_tbl[irq->name] = *irq;
if (is_cpm_irq(irq->name)) {
/*
* Enable interrupt at PIC level
*/
BSP_irq_enable_at_cpm (irq->name);
}
if (is_siu_irq(irq->name)) {
/*
* Enable interrupt at SIU level
*/
BSP_irq_enable_at_siu (irq->name);
}
if (is_processor_irq(irq->name)) {
/*
* Should Enable exception at processor level but not needed. Will restore
* EE flags at the end of the routine anyway.
*/
}
/*
* Enable interrupt on device
*/
irq->on(irq);
_CPU_ISR_Enable(level);
return 1;
}
int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
{
if (!isValidInterrupt(irq->name)) {
return 0;
}
*irq = rtems_hdl_tbl[irq->name];
return 1;
}
int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
{
unsigned int level;
if (!isValidInterrupt(irq->name)) {
return 0;
}
/*
* Check if default handler is actually connected. If not issue an error.
* You must first get the current handler via i386_get_current_idt_entry
* and then disconnect it using i386_delete_idt_entry.
* RATIONALE : to always have the same transition by forcing the user
* to get the previous handler before accepting to disconnect.
*/
if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
return 0;
}
_CPU_ISR_Disable(level);
if (is_cpm_irq(irq->name)) {
/*
* disable interrupt at PIC level
*/
BSP_irq_disable_at_cpm (irq->name);
}
if (is_siu_irq(irq->name)) {
/*
* disable interrupt at OPENPIC level
*/
BSP_irq_disable_at_siu (irq->name);
}
if (is_processor_irq(irq->name)) {
/*
* disable exception at processor level
*/
}
/*
* Disable interrupt on device
*/
irq->off(irq);
/*
* restore the default irq value
*/
rtems_hdl_tbl[irq->name] = default_rtems_entry;
_CPU_ISR_Enable(level);
return 1;
}
/*
* ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
*/
int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
{
int i;
unsigned int level;
/*
* Store various code accelerators
*/
internal_config = config;
default_rtems_entry = config->defaultEntry;
rtems_hdl_tbl = config->irqHdlTbl;
_CPU_ISR_Disable(level);
/*
* start with CPM IRQ
*/
for (i=BSP_CPM_IRQ_LOWEST_OFFSET; i < BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER ; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
BSP_irq_enable_at_cpm (i);
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
}
else {
rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
BSP_irq_disable_at_cpm (i);
}
}
/*
* continue with PCI IRQ
*/
/*
* set up internal tables used by rtems interrupt prologue
*/
compute_SIU_IvectMask_from_prio ();
for (i=BSP_SIU_IRQ_LOWEST_OFFSET; i < BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER ; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
BSP_irq_enable_at_siu (i);
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
}
else {
rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
BSP_irq_disable_at_siu (i);
}
}
/*
* Must enable CPM interrupt on SIU. CPM on SIU Interrupt level has already been
* set up in BSP_CPM_irq_init.
*/
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
BSP_irq_enable_at_siu (BSP_CPM_INTERRUPT);
/*
* finish with Processor exceptions handled like IRQ
*/
for (i=BSP_PROCESSOR_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER; i++) {
if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) {
rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]);
}
else {
rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]);
}
}
_CPU_ISR_Enable(level);
return 1;
}
int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
{
*config = internal_config;
return 0;
}
#ifdef DISPATCH_HANDLER_STAT
volatile unsigned int maxLoop = 0;
#endif
/*
* High level IRQ handler called from shared_raw_irq_code_entry
*/
void C_dispatch_irq_handler (CPU_Interrupt_frame *frame, unsigned int excNum)
{
register unsigned int irq;
register unsigned cpmIntr; /* boolean */
register unsigned oldMask; /* old siu pic masks */
register unsigned msr;
register unsigned new_msr;
unsigned loopCounter;
/*
* Handle decrementer interrupt
*/
if (excNum == ASM_DEC_VECTOR) {
_CPU_MSR_GET(msr);
new_msr = msr | MSR_EE;
_CPU_MSR_SET(new_msr);
rtems_hdl_tbl[BSP_DECREMENTER].hdl();
_CPU_MSR_SET(msr);
return;
}
/*
* Handle external interrupt generated by SIU on PPC core
*/
#ifdef DISPATCH_HANDLER_STAT
loopCounter = 0;
#endif
while (1) {
if ((ppc_cached_irq_mask & ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend) == 0) {
#ifdef DISPATCH_HANDLER_STAT
if (loopCounter > maxLoop) maxLoop = loopCounter;
#endif
break;
}
irq = (((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sivec >> 26);
cpmIntr = (irq == BSP_CPM_INTERRUPT);
/*
* Disable the interrupt of the same and lower priority.
*/
oldMask = ppc_cached_irq_mask;
ppc_cached_irq_mask = oldMask & SIU_IvectMask[irq];
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
/*
* Acknowledge current interrupt. This has no effect on internal level interrupt.
*/
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = (1 << (31 - irq));
if (cpmIntr) {
/*
* We will reenable the SIU CPM interrupt to allow nesting of CPM interrupt.
* We must before acknowledege the current irq at CPM level to avoid trigerring
* the interrupt again.
*/
/*
* Acknowledge and get the vector.
*/
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
irq = (((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr >> 11);
/*
* transform IRQ to normalized irq table index.
*/
irq += BSP_CPM_IRQ_LOWEST_OFFSET;
/*
* Unmask CPM interrupt at SIU level
*/
ppc_cached_irq_mask |= (1 << (31 - BSP_CPM_INTERRUPT));
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
}
_CPU_MSR_GET(msr);
new_msr = msr | MSR_EE;
_CPU_MSR_SET(new_msr);
rtems_hdl_tbl[irq].hdl();
_CPU_MSR_SET(msr);
if (cpmIntr) {
irq -= BSP_CPM_IRQ_LOWEST_OFFSET;
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr = (1 << irq);
}
ppc_cached_irq_mask |= (oldMask & ~(SIU_IvectMask[irq]));
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = ppc_cached_irq_mask;
#ifdef DISPATCH_HANDLER_STAT
++ loopCounter;
#endif
}
}
void _ThreadProcessSignalsFromIrq (BSP_Exception_frame* ctx)
{
/*
* Process pending signals that have not already been
* processed by _Thread_Displatch. This happens quite
* unfrequently : the ISR must have posted an action
* to the current running thread.
*/
if ( _Thread_Do_post_task_switch_extension ||
_Thread_Executing->do_post_task_switch_extension ) {
_Thread_Executing->do_post_task_switch_extension = FALSE;
_API_extensions_Run_postswitch();
}
/*
* I plan to process other thread related events here.
* This will include DEBUG session requested from keyboard...
*/
}

View File

@@ -0,0 +1,331 @@
/* irq.h
*
* This include file describe the data structure and the functions implemented
* by rtems to write interrupt handlers.
*
* CopyRight (C) 1999 valette@crf.canon.fr
*
* This code is heavilly inspired by the public specification of STREAM V2
* that can be found at :
*
* <http://www.chorus.com/Documentation/index.html> by following
* the STREAM API Specification Document link.
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#ifndef LIBBSP_POWERPC_ETH_COMM_IRQ_IRQ_H
#define LIBBSP_POWERPC_ETH_COMM_IRQ_IRQ_H
#define BSP_ASM_IRQ_VECTOR_BASE 0x0
#ifndef ASM
extern volatile unsigned int ppc_cached_irq_mask;
/*
* Symblolic IRQ names and related definitions.
*/
typedef enum {
/* Base vector for our SIU IRQ handlers. */
BSP_SIU_VECTOR_BASE = BSP_ASM_IRQ_VECTOR_BASE,
/*
* SIU IRQ handler related definitions
*/
BSP_SIU_IRQ_NUMBER = 16, /* 16 reserved but in the future... */
BSP_SIU_IRQ_LOWEST_OFFSET = 0,
BSP_SIU_IRQ_MAX_OFFSET = BSP_SIU_IRQ_LOWEST_OFFSET + BSP_SIU_IRQ_NUMBER - 1,
/*
* CPM IRQ handlers related definitions
* CAUTION : BSP_CPM_IRQ_LOWEST_OFFSET should be equal to OPENPIC_VEC_SOURCE
*/
BSP_CPM_IRQ_NUMBER = 32,
BSP_CPM_IRQ_LOWEST_OFFSET = BSP_SIU_IRQ_NUMBER + BSP_SIU_VECTOR_BASE,
BSP_CPM_IRQ_MAX_OFFSET = BSP_CPM_IRQ_LOWEST_OFFSET + BSP_CPM_IRQ_NUMBER - 1,
/*
* PowerPc exceptions handled as interrupt where a rtems managed interrupt
* handler might be connected
*/
BSP_PROCESSOR_IRQ_NUMBER = 1,
BSP_PROCESSOR_IRQ_LOWEST_OFFSET = BSP_CPM_IRQ_MAX_OFFSET + 1,
BSP_PROCESSOR_IRQ_MAX_OFFSET = BSP_PROCESSOR_IRQ_LOWEST_OFFSET + BSP_PROCESSOR_IRQ_NUMBER - 1,
/*
* Summary
*/
BSP_IRQ_NUMBER = BSP_PROCESSOR_IRQ_MAX_OFFSET + 1,
BSP_LOWEST_OFFSET = BSP_SIU_IRQ_LOWEST_OFFSET,
BSP_MAX_OFFSET = BSP_PROCESSOR_IRQ_MAX_OFFSET,
/*
* Some SIU IRQ symbolic name definition. Please note that
* INT IRQ are defined but a single one will be used to
* redirect all CPM interrupt.
*/
BSP_SIU_EXT_IRQ_0 = 0,
BSP_SIU_INT_IRQ_0 = 1,
BSP_SIU_EXT_IRQ_1 = 2,
BSP_SIU_INT_IRQ_1 = 3,
BSP_SIU_EXT_IRQ_2 = 4,
BSP_SIU_INT_IRQ_2 = 5,
BSP_SIU_EXT_IRQ_3 = 6,
BSP_SIU_INT_IRQ_3 = 7,
BSP_SIU_EXT_IRQ_4 = 8,
BSP_SIU_INT_IRQ_4 = 9,
BSP_SIU_EXT_IRQ_5 = 10,
BSP_SIU_INT_IRQ_5 = 11,
BSP_SIU_EXT_IRQ_6 = 12,
BSP_SIU_INT_IRQ_6 = 13,
BSP_SIU_EXT_IRQ_7 = 14,
BSP_SIU_INT_IRQ_7 = 15,
/*
* Symbolic name for CPM interrupt on SIU Internal level 2
*/
BSP_CPM_INTERRUPT = BSP_SIU_INT_IRQ_2,
BSP_PERIODIC_TIMER = BSP_SIU_INT_IRQ_6,
BSP_FAST_ETHERNET_CTRL = BSP_SIU_INT_IRQ_3,
/*
* Some CPM IRQ symbolic name definition
*/
BSP_CPM_IRQ_ERROR = BSP_CPM_IRQ_LOWEST_OFFSET,
BSP_CPM_IRQ_PARALLEL_IO_PC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 1,
BSP_CPM_IRQ_PARALLEL_IO_PC5 = BSP_CPM_IRQ_LOWEST_OFFSET + 2,
BSP_CPM_IRQ_SMC2_OR_PIP = BSP_CPM_IRQ_LOWEST_OFFSET + 3,
BSP_CPM_IRQ_SMC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 4,
BSP_CPM_IRQ_SPI = BSP_CPM_IRQ_LOWEST_OFFSET + 5,
BSP_CPM_IRQ_PARALLEL_IO_PC6 = BSP_CPM_IRQ_LOWEST_OFFSET + 6,
BSP_CPM_IRQ_TIMER_4 = BSP_CPM_IRQ_LOWEST_OFFSET + 7,
BSP_CPM_IRQ_PARALLEL_IO_PC7 = BSP_CPM_IRQ_LOWEST_OFFSET + 9,
BSP_CPM_IRQ_PARALLEL_IO_PC8 = BSP_CPM_IRQ_LOWEST_OFFSET + 10,
BSP_CPM_IRQ_PARALLEL_IO_PC9 = BSP_CPM_IRQ_LOWEST_OFFSET + 11,
BSP_CPM_IRQ_TIMER_3 = BSP_CPM_IRQ_LOWEST_OFFSET + 12,
BSP_CPM_IRQ_PARALLEL_IO_PC10 = BSP_CPM_IRQ_LOWEST_OFFSET + 14,
BSP_CPM_IRQ_PARALLEL_IO_PC11 = BSP_CPM_IRQ_LOWEST_OFFSET + 15,
BSP_CPM_I2C = BSP_CPM_IRQ_LOWEST_OFFSET + 16,
BSP_CPM_RISC_TIMER_TABLE = BSP_CPM_IRQ_LOWEST_OFFSET + 17,
BSP_CPM_IRQ_TIMER_2 = BSP_CPM_IRQ_LOWEST_OFFSET + 18,
BSP_CPM_IDMA2 = BSP_CPM_IRQ_LOWEST_OFFSET + 20,
BSP_CPM_IDMA1 = BSP_CPM_IRQ_LOWEST_OFFSET + 21,
BSP_CPM_SDMA_CHANNEL_BUS_ERR = BSP_CPM_IRQ_LOWEST_OFFSET + 22,
BSP_CPM_IRQ_PARALLEL_IO_PC12 = BSP_CPM_IRQ_LOWEST_OFFSET + 23,
BSP_CPM_IRQ_PARALLEL_IO_PC13 = BSP_CPM_IRQ_LOWEST_OFFSET + 24,
BSP_CPM_IRQ_TIMER_1 = BSP_CPM_IRQ_LOWEST_OFFSET + 25,
BSP_CPM_IRQ_PARALLEL_IO_PC14 = BSP_CPM_IRQ_LOWEST_OFFSET + 26,
BSP_CPM_IRQ_SCC4 = BSP_CPM_IRQ_LOWEST_OFFSET + 27,
BSP_CPM_IRQ_SCC3 = BSP_CPM_IRQ_LOWEST_OFFSET + 28,
BSP_CPM_IRQ_SCC2 = BSP_CPM_IRQ_LOWEST_OFFSET + 29,
BSP_CPM_IRQ_SCC1 = BSP_CPM_IRQ_LOWEST_OFFSET + 30,
BSP_CPM_IRQ_PARALLEL_IO_PC15 = BSP_CPM_IRQ_LOWEST_OFFSET + 31,
/*
* Some Processor exception handled as rtems IRQ symbolic name definition
*/
BSP_DECREMENTER = BSP_PROCESSOR_IRQ_LOWEST_OFFSET
}rtems_irq_symbolic_name;
#define CPM_INTERRUPT
/*
* Type definition for RTEMS managed interrupts
*/
typedef unsigned char rtems_irq_prio;
struct __rtems_irq_connect_data__; /* forward declaratiuon */
typedef void (*rtems_irq_hdl) (void);
typedef void (*rtems_irq_enable) (const struct __rtems_irq_connect_data__*);
typedef void (*rtems_irq_disable) (const struct __rtems_irq_connect_data__*);
typedef int (*rtems_irq_is_enabled) (const struct __rtems_irq_connect_data__*);
typedef struct __rtems_irq_connect_data__ {
/*
* IRQ line
*/
rtems_irq_symbolic_name name;
/*
* handler. See comment on handler properties below in function prototype.
*/
rtems_irq_hdl hdl;
/*
* function for enabling interrupts at device level (ONLY!).
* The BSP code will automatically enable it at SIU level and CPM level.
* RATIONALE : anyway such code has to exist in current driver code.
* It is usually called immediately AFTER connecting the interrupt handler.
* RTEMS may well need such a function when restoring normal interrupt
* processing after a debug session.
*
*/
rtems_irq_enable on;
/*
* function for disabling interrupts at device level (ONLY!).
* The code will disable it at SIU and CPM level. RATIONALE : anyway
* such code has to exist for clean shutdown. It is usually called
* BEFORE disconnecting the interrupt. RTEMS may well need such
* a function when disabling normal interrupt processing for
* a debug session. May well be a NOP function.
*/
rtems_irq_disable off;
/*
* function enabling to know what interrupt may currently occur
* if someone manipulates the i8259s interrupt mask without care...
*/
rtems_irq_is_enabled isOn;
}rtems_irq_connect_data;
typedef struct {
/*
* size of all the table fields (*Tbl) described below.
*/
unsigned int irqNb;
/*
* Default handler used when disconnecting interrupts.
*/
rtems_irq_connect_data defaultEntry;
/*
* Table containing initials/current value.
*/
rtems_irq_connect_data* irqHdlTbl;
/*
* actual value of BSP_SIU_IRQ_VECTOR_BASE...
*/
rtems_irq_symbolic_name irqBase;
/*
* software priorities associated with interrupts.
* if irqPrio [i] > intrPrio [j] it means that
* interrupt handler hdl connected for interrupt name i
* will not be interrupted by the handler connected for interrupt j
* The interrupt source will be physically masked at i8259 level.
*/
rtems_irq_prio* irqPrioTbl;
}rtems_irq_global_settings;
/*-------------------------------------------------------------------------+
| Function Prototypes.
+--------------------------------------------------------------------------*/
/*
* ------------------------ PPC SIU Mngt Routines -------
*/
/*
* function to disable a particular irq at 8259 level. After calling
* this function, even if the device asserts the interrupt line it will
* not be propagated further to the processor
*/
int BSP_irq_disable_at_siu (const rtems_irq_symbolic_name irqLine);
/*
* function to enable a particular irq at 8259 level. After calling
* this function, if the device asserts the interrupt line it will
* be propagated further to the processor
*/
int BSP_irq_enable_at_siu (const rtems_irq_symbolic_name irqLine);
/*
* function to acknoledge a particular irq at 8259 level. After calling
* this function, if a device asserts an enabled interrupt line it will
* be propagated further to the processor. Mainly usefull for people
* writting raw handlers as this is automagically done for rtems managed
* handlers.
*/
int BSP_irq_ack_at_siu (const rtems_irq_symbolic_name irqLine);
/*
* function to check if a particular irq is enabled at 8259 level. After calling
*/
int BSP_irq_enabled_at_siu (const rtems_irq_symbolic_name irqLine);
/*
* ------------------------ RTEMS Single Irq Handler Mngt Routines ----------------
*/
/*
* function to connect a particular irq handler. This hanlder will NOT be called
* directly as the result of the corresponding interrupt. Instead, a RTEMS
* irq prologue will be called that will :
*
* 1) save the C scratch registers,
* 2) switch to a interrupt stack if the interrupt is not nested,
* 4) modify them to disable the current interrupt at SIU level (and may
* be others depending on software priorities)
* 5) aknowledge the SIU',
* 6) demask the processor,
* 7) call the application handler
*
* As a result the hdl function provided
*
* a) can perfectly be written is C,
* b) may also well directly call the part of the RTEMS API that can be used
* from interrupt level,
* c) It only responsible for handling the jobs that need to be done at
* the device level including (aknowledging/re-enabling the interrupt at device,
* level, getting the data,...)
*
* When returning from the function, the following will be performed by
* the RTEMS irq epilogue :
*
* 1) masks the interrupts again,
* 2) restore the original SIU interrupt masks
* 3) switch back on the orinal stack if needed,
* 4) perform rescheduling when necessary,
* 5) restore the C scratch registers...
* 6) restore initial execution flow
*
*/
int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*);
/*
* function to get the current RTEMS irq handler for ptr->name. It enables to
* define hanlder chain...
*/
int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr);
/*
* function to get disconnect the RTEMS irq handler for ptr->name.
* This function checks that the value given is the current one for safety reason.
* The user can use the previous function to get it.
*/
int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*);
/*
* ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
*/
/*
* (Re) Initialize the RTEMS interrupt management.
*
* The result of calling this function will be the same as if each individual
* handler (config->irqHdlTbl[i].hdl) different from "config->defaultEntry.hdl"
* has been individualy connected via
* BSP_install_rtems_irq_handler(&config->irqHdlTbl[i])
* And each handler currently equal to config->defaultEntry.hdl
* has been previously disconnected via
* BSP_remove_rtems_irq_handler (&config->irqHdlTbl[i])
*
* This is to say that all information given will be used and not just
* only the space.
*
* CAUTION : the various table address contained in config will be used
* directly by the interrupt mangement code in order to save
* data size so they must stay valid after the call => they should
* not be modified or declared on a stack.
*/
int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config);
/*
* (Re) get info on current RTEMS interrupt management.
*/
int BSP_rtems_irq_mngt_get(rtems_irq_global_settings**);
extern void BSP_rtems_irq_mng_init(unsigned cpuId);
#endif
#endif

View File

@@ -0,0 +1,329 @@
/*
* This file contains the assembly code for the PowerPC
* IRQ veneers for RTEMS.
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* Modified to support the MCP750.
* Modifications Copyright (C) 1999 Eric Valette. valette@crf.canon.fr
*
*
* $Id$
*/
#include <bsp/vectors.h>
#include <libcpu/cpu.h>
#include <libcpu/raw_exception.h>
#include <rtems/score/cpuopts.h> /* for PPC_HAS_FPU */
#include "asm.h"
#define SYNC \
sync; \
isync
.text
.p2align 5
PUBLIC_VAR(decrementer_exception_vector_prolog_code)
SYM (decrementer_exception_vector_prolog_code):
/*
* let room for exception frame
*/
stwu r1, - (EXCEPTION_FRAME_END)(r1)
stw r4, GPR4_OFFSET(r1)
li r4, ASM_DEC_VECTOR
ba shared_raw_irq_code_entry
PUBLIC_VAR (decrementer_exception_vector_prolog_code_size)
decrementer_exception_vector_prolog_code_size = . - decrementer_exception_vector_prolog_code
PUBLIC_VAR(external_exception_vector_prolog_code)
SYM (external_exception_vector_prolog_code):
/*
* let room for exception frame
*/
stwu r1, - (EXCEPTION_FRAME_END)(r1)
stw r4, GPR4_OFFSET(r1)
li r4, ASM_EXT_VECTOR
ba shared_raw_irq_code_entry
PUBLIC_VAR (external_exception_vector_prolog_code_size)
external_exception_vector_prolog_code_size = . - external_exception_vector_prolog_code
PUBLIC_VAR(shared_raw_irq_code_entry)
PUBLIC_VAR(C_dispatch_irq_handler)
.p2align 5
SYM (shared_raw_irq_code_entry):
/*
* Entry conditions :
* Registers already saved : R1, R4
* R1 : points to a location with enough room for the
* interrupt frame
* R4 : vector number
*/
/*
* Save SRR0/SRR1 As soon As possible as it is the minimal needed
* to reenable exception processing
*/
stw r0, GPR0_OFFSET(r1)
stw r2, GPR2_OFFSET(r1)
stw r3, GPR3_OFFSET(r1)
mfsrr0 r0
mfsrr1 r2
mfmsr r3
stw r0, SRR0_FRAME_OFFSET(r1)
stw r2, SRR1_FRAME_OFFSET(r1)
/*
* Enable data and instruction address translation, exception recovery
*
* also, on CPUs with FP, enable FP so that FP context can be
* saved and restored (using FP instructions)
*/
#if (PPC_HAS_FPU == 0)
ori r3, r3, MSR_RI | MSR_IR | MSR_DR
#else
ori r3, r3, MSR_RI | MSR_IR | MSR_DR | MSR_FP
#endif
mtmsr r3
SYNC
/*
* Push C scratch registers on the current stack. It may
* actually be the thread stack or the interrupt stack.
* Anyway we have to make it in order to be able to call C/C++
* functions. Depending on the nesting interrupt level, we will
* switch to the right stack later.
*/
stw r5, GPR5_OFFSET(r1)
stw r6, GPR6_OFFSET(r1)
stw r7, GPR7_OFFSET(r1)
stw r8, GPR8_OFFSET(r1)
stw r9, GPR9_OFFSET(r1)
stw r10, GPR10_OFFSET(r1)
stw r11, GPR11_OFFSET(r1)
stw r12, GPR12_OFFSET(r1)
stw r13, GPR13_OFFSET(r1)
mfcr r5
mfctr r6
mfxer r7
mflr r8
stw r5, EXC_CR_OFFSET(r1)
stw r6, EXC_CTR_OFFSET(r1)
stw r7, EXC_XER_OFFSET(r1)
stw r8, EXC_LR_OFFSET(r1)
/*
* Add some non volatile registers to store information
* that will be used when returning from C handler
*/
stw r14, GPR14_OFFSET(r1)
stw r15, GPR15_OFFSET(r1)
/*
* save current stack pointer location in R14
*/
addi r14, r1, 0
/*
* store part of _Thread_Dispatch_disable_level address in R15
*/
addis r15,0, _Thread_Dispatch_disable_level@ha
/*
* Get current nesting level in R2
*/
mfspr r2, SPRG0
/*
* Check if stack switch is necessary
*/
cmpwi r2,0
bne nested
mfspr r1, SPRG1
nested:
/*
* Start Incrementing nesting level in R2
*/
addi r2,r2,1
/*
* Start Incrementing _Thread_Dispatch_disable_level R4 = _Thread_Dispatch_disable_level
*/
lwz r6,_Thread_Dispatch_disable_level@l(r15)
/*
* store new nesting level in SPRG0
*/
mtspr SPRG0, r2
addi r6, r6, 1
mfmsr r5
/*
* store new _Thread_Dispatch_disable_level value
*/
stw r6, _Thread_Dispatch_disable_level@l(r15)
/*
* We are now running on the interrupt stack. External and decrementer
* exceptions are still disabled. I see no purpose trying to optimize
* further assembler code.
*/
/*
* Call C exception handler for decrementer Interrupt frame is passed just
* in case...
*/
addi r3, r14, 0x8
bl C_dispatch_irq_handler /* C_dispatch_irq_handler(cpu_interrupt_frame* r3, vector r4) */
/*
* start decrementing nesting level. Note : do not test result against 0
* value as an easy exit condition because if interrupt nesting level > 1
* then _Thread_Dispatch_disable_level > 1
*/
mfspr r2, SPRG0
/*
* start decrementing _Thread_Dispatch_disable_level
*/
lwz r3,_Thread_Dispatch_disable_level@l(r15)
addi r2, r2, -1 /* Continue decrementing nesting level */
addi r3, r3, -1 /* Continue decrementing _Thread_Dispatch_disable_level */
mtspr SPRG0, r2 /* End decrementing nesting level */
stw r3,_Thread_Dispatch_disable_level@l(r15) /* End decrementing _Thread_Dispatch_disable_level */
cmpwi r3, 0
/*
* switch back to original stack (done here just optimize registers
* contention. Could have been done before...)
*/
addi r1, r14, 0
bne easy_exit /* if (_Thread_Dispatch_disable_level != 0) goto easy_exit */
/*
* Here we are running again on the thread system stack.
* We have interrupt nesting level = _Thread_Dispatch_disable_level = 0.
* Interrupt are still disabled. Time to check if scheduler request to
* do something with the current thread...
*/
addis r4, 0, _Context_Switch_necessary@ha
lwz r5, _Context_Switch_necessary@l(r4)
cmpwi r5, 0
bne switch
addis r6, 0, _ISR_Signals_to_thread_executing@ha
lwz r7, _ISR_Signals_to_thread_executing@l(r6)
cmpwi r7, 0
li r8, 0
beq easy_exit
stw r8, _ISR_Signals_to_thread_executing@l(r6)
/*
* going to call _ThreadProcessSignalsFromIrq
* Push a complete exception like frame...
*/
stmw r16, GPR16_OFFSET(r1)
addi r3, r1, 0x8
/*
* compute SP at exception entry
*/
addi r2, r1, EXCEPTION_FRAME_END
/*
* store it at the right place
*/
stw r2, GPR1_OFFSET(r1)
/*
* Call High Level signal handling code
*/
bl _ThreadProcessSignalsFromIrq
/*
* start restoring exception like frame
*/
lwz r31, EXC_CTR_OFFSET(r1)
lwz r30, EXC_XER_OFFSET(r1)
lwz r29, EXC_CR_OFFSET(r1)
lwz r28, EXC_LR_OFFSET(r1)
mtctr r31
mtxer r30
mtcr r29
mtlr r28
lmw r4, GPR4_OFFSET(r1)
lwz r2, GPR2_OFFSET(r1)
lwz r0, GPR0_OFFSET(r1)
/*
* Disable data and instruction translation. Make path non recoverable...
*/
mfmsr r3
xori r3, r3, MSR_RI | MSR_IR | MSR_DR
mtmsr r3
SYNC
/*
* Restore rfi related settings
*/
lwz r3, SRR1_FRAME_OFFSET(r1)
mtsrr1 r3
lwz r3, SRR0_FRAME_OFFSET(r1)
mtsrr0 r3
lwz r3, GPR3_OFFSET(r1)
addi r1,r1, EXCEPTION_FRAME_END
SYNC
rfi
switch:
bl SYM (_Thread_Dispatch)
easy_exit:
/*
* start restoring interrupt frame
*/
lwz r3, EXC_CTR_OFFSET(r1)
lwz r4, EXC_XER_OFFSET(r1)
lwz r5, EXC_CR_OFFSET(r1)
lwz r6, EXC_LR_OFFSET(r1)
mtctr r3
mtxer r4
mtcr r5
mtlr r6
lwz r15, GPR15_OFFSET(r1)
lwz r14, GPR14_OFFSET(r1)
lwz r13, GPR13_OFFSET(r1)
lwz r12, GPR12_OFFSET(r1)
lwz r11, GPR11_OFFSET(r1)
lwz r10, GPR10_OFFSET(r1)
lwz r9, GPR9_OFFSET(r1)
lwz r8, GPR8_OFFSET(r1)
lwz r7, GPR7_OFFSET(r1)
lwz r6, GPR6_OFFSET(r1)
lwz r5, GPR5_OFFSET(r1)
/*
* Disable nested exception processing, data and instruction
* translation.
*/
mfmsr r3
xori r3, r3, MSR_RI | MSR_IR | MSR_DR
mtmsr r3
SYNC
/*
* Restore rfi related settings
*/
lwz r4, SRR1_FRAME_OFFSET(r1)
lwz r2, SRR0_FRAME_OFFSET(r1)
lwz r3, GPR3_OFFSET(r1)
lwz r0, GPR0_OFFSET(r1)
mtsrr1 r4
mtsrr0 r2
lwz r4, GPR4_OFFSET(r1)
lwz r2, GPR2_OFFSET(r1)
addi r1,r1, EXCEPTION_FRAME_END
SYNC
rfi

View File

@@ -0,0 +1,161 @@
/* irq_init.c
*
* This file contains the implementation of rtems initialization
* related to interrupt handling.
*
* CopyRight (C) 2001 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <bsp/irq.h>
#include <bsp.h>
#include <libcpu/raw_exception.h>
#include <bsp/8xx_immap.h>
#include <bsp/commproc.h>
extern unsigned int external_exception_vector_prolog_code_size;
extern void external_exception_vector_prolog_code();
extern unsigned int decrementer_exception_vector_prolog_code_size;
extern void decrementer_exception_vector_prolog_code();
volatile unsigned int ppc_cached_irq_mask;
/*
* default on/off function
*/
static void nop_func(){}
/*
* default isOn function
*/
static int not_connected() {return 0;}
/*
* default possible isOn function
*/
static int connected() {return 1;}
static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER];
static rtems_irq_global_settings initial_config;
static rtems_irq_connect_data defaultIrq = {
/* vectorIdex, hdl , on , off , isOn */
0, nop_func , nop_func , nop_func , not_connected
};
static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={
/*
* actual rpiorities for interrupt :
* 0 means that only current interrupt is masked
* 255 means all other interrupts are masked
*/
/*
* SIU interrupts.
*/
7,7, 6,6, 5,5, 4,4, 3,3, 2,2, 1,1, 0,0,
/*
* CPM Interrupts
*/
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
/*
* Processor exceptions handled as interrupts
*/
0
};
void BSP_SIU_irq_init()
{
/*
* In theory we should initialize two registers at least :
* SIMASK, SIEL. SIMASK is reset at 0 value meaning no interrupt. But
* we should take care that a monitor may have restoreed to another value.
* If someone find a reasonnable value for SIEL, AND THE NEED TO CHANGE IT
* please feel free to add it here.
*/
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_simask = 0;
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_sipend = 0xffff0000;
ppc_cached_irq_mask = 0;
((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel = ((volatile immap_t *)IMAP_ADDR)->im_siu_conf.sc_siel;
}
/*
* Initialize CPM interrupt management
*/
void
BSP_CPM_irq_init(void)
{
/*
* Initialize the CPM interrupt controller.
*/
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr =
#ifdef mpc860
(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
#else
(CICR_SCB_SCC2 | CICR_SCA_SCC1) |
#endif
((BSP_CPM_INTERRUPT/2) << 13) | CICR_HP_MASK;
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr = 0;
((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_cicr |= CICR_IEN;
}
void BSP_rtems_irq_mng_init(unsigned cpuId)
{
rtems_raw_except_connect_data vectorDesc;
int i;
BSP_SIU_irq_init();
BSP_CPM_irq_init();
/*
* Initialize Rtems management interrupt table
*/
/*
* re-init the rtemsIrq table
*/
for (i = 0; i < BSP_IRQ_NUMBER; i++) {
rtemsIrq[i] = defaultIrq;
rtemsIrq[i].name = i;
}
/*
* Init initial Interrupt management config
*/
initial_config.irqNb = BSP_IRQ_NUMBER;
initial_config.defaultEntry = defaultIrq;
initial_config.irqHdlTbl = rtemsIrq;
initial_config.irqBase = BSP_ASM_IRQ_VECTOR_BASE;
initial_config.irqPrioTbl = irqPrioTable;
if (!BSP_rtems_irq_mngt_set(&initial_config)) {
/*
* put something here that will show the failure...
*/
BSP_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n");
}
/*
* We must connect the raw irq handler for the two
* expected interrupt sources : decrementer and external interrupts.
*/
vectorDesc.exceptIndex = ASM_DEC_VECTOR;
vectorDesc.hdl.vector = ASM_DEC_VECTOR;
vectorDesc.hdl.raw_hdl = decrementer_exception_vector_prolog_code;
vectorDesc.hdl.raw_hdl_size = (unsigned) &decrementer_exception_vector_prolog_code_size;
vectorDesc.on = nop_func;
vectorDesc.off = nop_func;
vectorDesc.isOn = connected;
if (!mpc8xx_set_exception (&vectorDesc)) {
BSP_panic("Unable to initialize RTEMS decrementer raw exception\n");
}
vectorDesc.exceptIndex = ASM_EXT_VECTOR;
vectorDesc.hdl.vector = ASM_EXT_VECTOR;
vectorDesc.hdl.raw_hdl = external_exception_vector_prolog_code;
vectorDesc.hdl.raw_hdl_size = (unsigned) &external_exception_vector_prolog_code_size;
if (!mpc8xx_set_exception (&vectorDesc)) {
BSP_panic("Unable to initialize RTEMS external raw exception\n");
}
#ifdef TRACE_IRQ_INIT
printk("RTEMS IRQ management is now operationnal\n");
#endif
}

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,40 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
VPATH = @srcdir@:
C_FILES = vectors_init.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
H_FILES = vectors.h
S_FILES = vectors.S
S_O_FILES = $(S_FILES:%.S=$(ARCH)/%.o)
OBJS = $(S_O_FILES) $(C_O_FILES)
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../../../automake/compile.am
include $(top_srcdir)/../../../../../../automake/lib.am
#
# (OPTIONAL) Add local stuff here using +=
#
$(PGM): $(OBJS)
$(make-rel)
$(PROJECT_INCLUDE)/bsp:
$(mkinstalldirs) $@
$(PROJECT_INCLUDE)/bsp/vectors.h: vectors.h
$(INSTALL_DATA) $< $@
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp $(PROJECT_INCLUDE)/bsp/vectors.h
all-local: $(ARCH) $(PREINSTALL_FILES) $(OBJS)
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,143 @@
/*
* (c) 1999, Eric Valette valette@crf.canon.fr
*
*
* This file contains the assembly code for the PowerPC
* exception veneers for RTEMS.
*
* $Id$
*/
#include <bsp/vectors.h>
#include <libcpu/cpu.h>
#include <rtems/score/targopts.h>
#include "asm.h"
#define SYNC \
sync; \
isync
.text
.p2align 5
PUBLIC_VAR(default_exception_vector_code_prolog)
SYM (default_exception_vector_code_prolog):
/*
* let room for exception frame
*/
stwu r1, - (EXCEPTION_FRAME_END)(r1)
stw r3, GPR3_OFFSET(r1)
stw r2, GPR2_OFFSET(r1)
mflr r2
stw r2, EXC_LR_OFFSET(r1)
bl 0f
0: /*
* r3 = exception vector entry point
* (256 * vector number) + few instructions
*/
mflr r3
/*
* r3 = r3 >> 8 = vector
*/
srwi r3,r3,8
ba push_normalized_frame
PUBLIC_VAR (default_exception_vector_code_prolog_size)
default_exception_vector_code_prolog_size= . - default_exception_vector_code_prolog
.p2align 5
PUBLIC_VAR (push_normalized_frame)
SYM (push_normalized_frame):
stw r3, EXCEPTION_NUMBER_OFFSET(r1)
stw r0, GPR0_OFFSET(r1)
mfsrr0 r2
stw r2, SRR0_FRAME_OFFSET(r1)
mfsrr1 r3
stw r3, SRR1_FRAME_OFFSET(r1)
/*
* Save general purpose registers
* Already saved in prolog : R1, R2, R3, LR.
* Saved a few line above : R0
*
* Manual says that "stmw" instruction may be slower than
* series of individual "stw" but who cares about performance
* for the DEFAULT exception handler?
*/
stmw r4, GPR4_OFFSET(r1) /* save R4->R31 */
mfcr r31
stw r31, EXC_CR_OFFSET(r1)
mfctr r30
stw r30, EXC_CTR_OFFSET(r1)
mfxer r28
stw r28, EXC_XER_OFFSET(r1)
/*
* compute SP at exception entry
*/
addi r2, r1, EXCEPTION_FRAME_END
/*
* store it at the right place
*/
stw r2, GPR1_OFFSET(r1)
/*
* Enable data and instruction address translation, exception nesting
*/
mfmsr r3
ori r3,r3, MSR_RI | MSR_IR | MSR_DR
mtmsr r3
SYNC
/*
* Call C exception handler
*/
/*
* store the execption frame address in r3 (first param)
*/
addi r3, r1, 0x8
/*
* globalExceptHdl(r3)
*/
addis r4, 0, globalExceptHdl@ha
lwz r5, globalExceptHdl@l(r4)
mtlr r5
blrl
/*
* Restore registers status
*/
lwz r31, EXC_CR_OFFSET(r1)
mtcr r31
lwz r30, EXC_CTR_OFFSET(r1)
mtctr r30
lwz r29, EXC_LR_OFFSET(r1)
mtlr r29
lwz r28, EXC_XER_OFFSET(r1)
mtxer r28
lmw r4, GPR4_OFFSET(r1)
lwz r2, GPR2_OFFSET(r1)
lwz r0, GPR0_OFFSET(r1)
/*
* Disable data and instruction translation. Make path non recoverable...
*/
mfmsr r3
xori r3, r3, MSR_RI | MSR_IR | MSR_DR
mtmsr r3
SYNC
/*
* Restore rfi related settings
*/
lwz r3, SRR1_FRAME_OFFSET(r1)
mtsrr1 r3
lwz r3, SRR0_FRAME_OFFSET(r1)
mtsrr0 r3
lwz r3, GPR3_OFFSET(r1)
addi r1,r1, EXCEPTION_FRAME_END
SYNC
rfi

View File

@@ -0,0 +1,144 @@
/*
* vectors.h Exception frame related contant and API.
*
* This include file describe the data structure and the functions implemented
* by rtems to handle exceptions.
*
* CopyRight (C) 1999 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#ifndef LIBBSP_POWERPC_ETH_COMM_VECTORS_H
#define LIBBSP_POWERPC_Eth_Comm_VECTORS_H
/*
* The callee (high level exception code written in C)
* will store the Link Registers (return address) at entry r1 + 4 !!!.
* So let room for it!!!.
*/
#define LINK_REGISTER_CALLEE_UPDATE_ROOM 4
#define SRR0_FRAME_OFFSET 8
#define SRR1_FRAME_OFFSET 12
#define EXCEPTION_NUMBER_OFFSET 16
#define GPR0_OFFSET 20
#define GPR1_OFFSET 24
#define GPR2_OFFSET 28
#define GPR3_OFFSET 32
#define GPR4_OFFSET 36
#define GPR5_OFFSET 40
#define GPR6_OFFSET 44
#define GPR7_OFFSET 48
#define GPR8_OFFSET 52
#define GPR9_OFFSET 56
#define GPR10_OFFSET 60
#define GPR11_OFFSET 64
#define GPR12_OFFSET 68
#define GPR13_OFFSET 72
#define GPR14_OFFSET 76
#define GPR15_OFFSET 80
#define GPR16_OFFSET 84
#define GPR17_OFFSET 88
#define GPR18_OFFSET 92
#define GPR19_OFFSET 96
#define GPR20_OFFSET 100
#define GPR21_OFFSET 104
#define GPR22_OFFSET 108
#define GPR23_OFFSET 112
#define GPR24_OFFSET 116
#define GPR25_OFFSET 120
#define GPR26_OFFSET 124
#define GPR27_OFFSET 128
#define GPR28_OFFSET 132
#define GPR29_OFFSET 136
#define GPR30_OFFSET 140
#define GPR31_OFFSET 144
#define EXC_CR_OFFSET 148
#define EXC_CTR_OFFSET 152
#define EXC_XER_OFFSET 156
#define EXC_LR_OFFSET 160
#define EXC_DAR_OFFSET 164
/*
* maintain the EABI requested 8 bytes aligment
* As SVR4 ABI requires 16, make it 16 (as some
* exception may need more registers to be processed...)
*/
#define EXCEPTION_FRAME_END 176
#ifndef ASM
/*
* default raw exception handlers
*/
extern void default_exception_vector_code_prolog();
extern int default_exception_vector_code_prolog_size;
/* codemove is like memmove, but it also gets the cache line size
* as 4th parameter to synchronize them. If this last parameter is
* zero, it performs more or less like memmove. No copy is performed if
* source and destination addresses are equal. However the caches
* are synchronized. Note that the size is always rounded up to the
* next mutiple of 4.
*/
extern void * codemove(void *, const void *, unsigned int, unsigned long);
extern void initialize_exceptions();
typedef struct {
unsigned EXC_SRR0;
unsigned EXC_SRR1;
unsigned _EXC_number;
unsigned GPR0;
unsigned GPR1;
unsigned GPR2;
unsigned GPR3;
unsigned GPR4;
unsigned GPR5;
unsigned GPR6;
unsigned GPR7;
unsigned GPR8;
unsigned GPR9;
unsigned GPR10;
unsigned GPR11;
unsigned GPR12;
unsigned GPR13;
unsigned GPR14;
unsigned GPR15;
unsigned GPR16;
unsigned GPR17;
unsigned GPR18;
unsigned GPR19;
unsigned GPR20;
unsigned GPR21;
unsigned GPR22;
unsigned GPR23;
unsigned GPR24;
unsigned GPR25;
unsigned GPR26;
unsigned GPR27;
unsigned GPR28;
unsigned GPR29;
unsigned GPR30;
unsigned GPR31;
unsigned EXC_CR;
unsigned EXC_CTR;
unsigned EXC_XER;
unsigned EXC_LR;
unsigned EXC_MSR;
unsigned EXC_DAR;
}BSP_Exception_frame;
typedef void (*exception_handler_t) (BSP_Exception_frame* excPtr);
extern exception_handler_t globalExceptHdl;
/*
* Compatibility with pc386
*/
typedef BSP_Exception_frame CPU_Exception_frame;
typedef exception_handler_t cpuExcHandlerType;
#endif /* ASM */
#endif /* LIBBSP_POWERPC_MCP750_VECTORS_H */

View File

@@ -0,0 +1,134 @@
/*
* vectors_init.c Exception hanlding initialisation (and generic handler).
*
* This include file describe the data structure and the functions implemented
* by rtems to handle exceptions.
*
* CopyRight (C) 1999 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
* found in found in the file LICENSE in this distribution or at
* http://www.OARcorp.com/rtems/license.html.
*
* $Id$
*/
#include <bsp/vectors.h>
#include <libcpu/raw_exception.h>
#include <bsp.h>
static rtems_raw_except_global_settings exception_config;
static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1];
exception_handler_t globalExceptHdl;
void C_exception_handler(BSP_Exception_frame* excPtr)
{
int recoverable = 0;
printk("exception handler called for exception %d\n", excPtr->_EXC_number);
printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0);
printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1);
printk("\t R0 = %x\n", excPtr->GPR0);
printk("\t R1 = %x\n", excPtr->GPR1);
printk("\t R2 = %x\n", excPtr->GPR2);
printk("\t R3 = %x\n", excPtr->GPR3);
printk("\t R4 = %x\n", excPtr->GPR4);
printk("\t R5 = %x\n", excPtr->GPR5);
printk("\t R6 = %x\n", excPtr->GPR6);
printk("\t R7 = %x\n", excPtr->GPR7);
printk("\t R8 = %x\n", excPtr->GPR8);
printk("\t R9 = %x\n", excPtr->GPR9);
printk("\t R10 = %x\n", excPtr->GPR10);
printk("\t R11 = %x\n", excPtr->GPR11);
printk("\t R12 = %x\n", excPtr->GPR12);
printk("\t R13 = %x\n", excPtr->GPR13);
printk("\t R14 = %x\n", excPtr->GPR14);
printk("\t R15 = %x\n", excPtr->GPR15);
printk("\t R16 = %x\n", excPtr->GPR16);
printk("\t R17 = %x\n", excPtr->GPR17);
printk("\t R18 = %x\n", excPtr->GPR18);
printk("\t R19 = %x\n", excPtr->GPR19);
printk("\t R20 = %x\n", excPtr->GPR20);
printk("\t R21 = %x\n", excPtr->GPR21);
printk("\t R22 = %x\n", excPtr->GPR22);
printk("\t R23 = %x\n", excPtr->GPR23);
printk("\t R24 = %x\n", excPtr->GPR24);
printk("\t R25 = %x\n", excPtr->GPR25);
printk("\t R26 = %x\n", excPtr->GPR26);
printk("\t R27 = %x\n", excPtr->GPR27);
printk("\t R28 = %x\n", excPtr->GPR28);
printk("\t R29 = %x\n", excPtr->GPR29);
printk("\t R30 = %x\n", excPtr->GPR30);
printk("\t R31 = %x\n", excPtr->GPR31);
printk("\t CR = %x\n", excPtr->EXC_CR);
printk("\t CTR = %x\n", excPtr->EXC_CTR);
printk("\t XER = %x\n", excPtr->EXC_XER);
printk("\t LR = %x\n", excPtr->EXC_LR);
printk("\t MSR = %x\n", excPtr->EXC_MSR);
if (excPtr->_EXC_number == ASM_DEC_VECTOR)
recoverable = 1;
if (excPtr->_EXC_number == ASM_SYS_VECTOR)
#ifdef TEST_RAW_EXCEPTION_CODE
recoverable = 1;
#else
recoverable = 0;
#endif
if (!recoverable) {
printk("unrecoverable exception!!! Push reset button\n");
while(1);
}
}
void nop_except_enable(const rtems_raw_except_connect_data* ptr)
{
}
int except_always_enabled(const rtems_raw_except_connect_data* ptr)
{
return 1;
}
void initialize_exceptions()
{
int i;
/*
* Initialize pointer used by low level execption handling
*/
globalExceptHdl = C_exception_handler;
/*
* Put default_exception_vector_code_prolog at relevant exception
* code entry addresses
*/
exception_config.exceptSize = LAST_VALID_EXC + 1;
exception_config.rawExceptHdlTbl = &exception_table[0];
exception_config.defaultRawEntry.exceptIndex = 0;
exception_config.defaultRawEntry.hdl.vector = 0;
exception_config.defaultRawEntry.hdl.raw_hdl = default_exception_vector_code_prolog;
/*
* Note that next line the '&' before default_exception_vector_code_prolog_size
* is not a bug as it is defined a .set directly in asm...
*/
exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned) &default_exception_vector_code_prolog_size;
for (i=0; i <= exception_config.exceptSize; i++) {
printk("installing exception number %d\n", i);
if (!mpc8xx_vector_is_valid (i)) {
continue;
}
exception_table[i].exceptIndex = i;
exception_table[i].hdl = exception_config.defaultRawEntry.hdl;
exception_table[i].hdl.vector = i;
exception_table[i].on = nop_except_enable;
exception_table[i].off = nop_except_enable;
exception_table[i].isOn = except_always_enabled;
}
if (!mpc8xx_init_exceptions(&exception_config)) {
/*
* At this stage we may not call BSP_Panic because it uses exceptions!!!
*/
printk("Exception handling initialization failed\n");
printk("System locked\n"); while(1);
}
else {
printk("Exception handling initialization done\n");
}
}