* shared/irq/irq.h, shared/irq/irq.c, shared/irq/irq_init.c: Converted
	to use generic interrupt support.
	* shared/irq/irq-config.h: New file.
This commit is contained in:
Joel Sherrill
2009-07-03 15:08:54 +00:00
parent 2c8a9804a5
commit fc5490fe84
5 changed files with 115 additions and 367 deletions

View File

@@ -1,3 +1,9 @@
2009-07-01 Sebastian Huber <sebastian.huber@embedded-brains.de>
* shared/irq/irq.h, shared/irq/irq.c, shared/irq/irq_init.c: Converted
to use generic interrupt support.
* shared/irq/irq-config.h: New file.
2009-05-06 Joel Sherrill <joel.sherrill@oarcorp.com>
* shared/comm/i386-stub-glue.c, shared/comm/uart.c, shared/irq/irq.c,

View File

@@ -0,0 +1,39 @@
/**
* @file
*
* @ingroup bsp_interrupt
*
* @brief i386 interrupt support configuration.
*/
/*
* Copyright (c) 2009
* embedded brains GmbH
* Obere Lagerstr. 30
* D-82178 Puchheim
* Germany
* <rtems@embedded-brains.de>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.com/license/LICENSE.
*
* $Id$
*/
#ifndef LIBBSP_I386_SHARED_IRQ_CONFIG_H
#define LIBBSP_I386_SHARED_IRQ_CONFIG_H
#include <bsp/irq.h>
/**
* @brief Minimum vector number.
*/
#define BSP_INTERRUPT_VECTOR_MIN BSP_LOWEST_OFFSET
/**
* @brief Maximum vector number.
*/
#define BSP_INTERRUPT_VECTOR_MAX BSP_MAX_OFFSET
#endif /* LIBBSP_I386_SHARED_IRQ_CONFIG_H */

View File

@@ -2,6 +2,7 @@
*
* This file contains the implementation of the function described in irq.h
*
* Copyright (c) 2009 embedded brains GmbH
* Copyright (C) 1998 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
@@ -16,6 +17,8 @@
#include <bsp.h>
#include <bsp/irq.h>
#include <bsp/irq-generic.h>
#include <stdlib.h>
#include <rtems/score/apiext.h>
@@ -29,17 +32,6 @@
*/
rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_LINES_NUMBER];
/*
* 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;
rtems_irq_connect_data* rtems_hdl_tbl;
/*-------------------------------------------------------------------------+
| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register.
+--------------------------------------------------------------------------*/
@@ -160,287 +152,83 @@ int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine)
* ------------------------ 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 rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={
/*
* actual rpiorities for interrupt :
* 0 means that only current interrupt is masked
* 255 means all other interrupts are masked
* The second entry has a priority of 255 because
* it is the slave pic entry and is should always remain
* unmasked.
*/
0,0,
255,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static void compute_i8259_masks_from_prio (void)
{
rtems_interrupt_level level;
unsigned int i;
unsigned int j;
rtems_interrupt_disable(level); /* XXX */
/*
* Always mask at least current interrupt to prevent re-entrance
*/
for (i=0; i < internal_config->irqNb; i++) {
for (i=0; i < BSP_IRQ_LINES_NUMBER; i++) {
* ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);
for (j = 0; j < internal_config->irqNb; j++) {
for (j = 0; j < BSP_IRQ_LINES_NUMBER; j++) {
/*
* Mask interrupts at i8259 level that have a lower priority
*/
if (internal_config->irqPrioTbl [i] > internal_config->irqPrioTbl [j]) {
if (irqPrioTable [i] > irqPrioTable [j]) {
* ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j);
}
}
}
}
/*
* 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))
return 0;
return 1;
}
/*
* ------------------- RTEMS Shared Irq Handler Mngt Routines ------------
*/
int BSP_install_rtems_shared_irq_handler (const rtems_irq_connect_data* irq)
{
rtems_interrupt_level level;
rtems_irq_connect_data* vchain;
if (!isValidInterrupt(irq->name)) {
printk("Invalid interrupt vector %d\n",irq->name);
return 0;
}
rtems_interrupt_disable(level);
if ( (int)rtems_hdl_tbl[irq->name].next_handler == -1 ) {
rtems_interrupt_enable(level);
printk(
"IRQ vector %d already connected to an unshared handler\n",
irq->name
);
return 0;
}
vchain = (rtems_irq_connect_data*)malloc(sizeof(rtems_irq_connect_data));
/* save off topmost handler */
vchain[0]= rtems_hdl_tbl[irq->name];
/*
* store the data provided by user
*/
rtems_hdl_tbl[irq->name] = *irq;
/* link chain to new topmost handler */
rtems_hdl_tbl[irq->name].next_handler = (void *)vchain;
/*
* enable_irq_at_pic is supposed to ignore
* requests to disable interrupts outside
* of the range handled by the PIC
*/
BSP_irq_enable_at_i8259s (irq->name);
/*
* Enable interrupt on device
*/
if (irq->on)
irq->on(irq);
rtems_interrupt_enable(level);
return 1;
}
/*
* --------------- RTEMS Single Irq Handler Mngt Routines ---------------
*/
int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq)
rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
{
rtems_interrupt_level level;
BSP_irq_enable_at_i8259s(vector);
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.
*/
rtems_interrupt_disable(level);
if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {
rtems_interrupt_enable(level);
return 0;
}
/*
* store the data provided by user
*/
rtems_hdl_tbl[irq->name] = *irq;
rtems_hdl_tbl[irq->name].next_handler = (void *)-1;
/*
* Enable interrupt at PIC level
*/
BSP_irq_enable_at_i8259s (irq->name);
/*
* Enable interrupt on device
*/
if (irq->on)
irq->on(irq);
rtems_interrupt_enable(level);
return 1;
return RTEMS_SUCCESSFUL;
}
int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq)
rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
{
rtems_interrupt_level level;
BSP_irq_disable_at_i8259s(vector);
if (!isValidInterrupt(irq->name)) {
return 0;
}
rtems_interrupt_disable(level);
*irq = rtems_hdl_tbl[irq->name];
rtems_interrupt_enable(level);
return 1;
return RTEMS_SUCCESSFUL;
}
int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq)
rtems_status_code bsp_interrupt_facility_initialize(void)
{
rtems_interrupt_level level;
rtems_irq_connect_data *pchain= NULL, *vchain = NULL;
if (!isValidInterrupt(irq->name)) {
return 0;
}
/*
* set up internal tables used by rtems interrupt prologue
*/
compute_i8259_masks_from_prio();
/*
* 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.
* must enable slave pic anyway
*/
rtems_interrupt_disable(level);
if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
rtems_interrupt_enable(level);
return 0;
}
BSP_irq_enable_at_i8259s(2);
if ( (int)rtems_hdl_tbl[irq->name].next_handler != -1 ) {
int found = 0;
for( (pchain= NULL, vchain = &rtems_hdl_tbl[irq->name]);
(vchain->hdl != default_rtems_entry.hdl);
(pchain= vchain,
vchain = (rtems_irq_connect_data*)vchain->next_handler) ) {
if ( vchain->hdl == irq->hdl ) {
found = -1;
break;
}
}
if ( !found ) {
rtems_interrupt_enable(level);
return 0;
}
} else {
if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {
rtems_interrupt_enable(level);
return 0;
}
}
/*
* disable interrupt at PIC level
*/
BSP_irq_disable_at_i8259s (irq->name);
/*
* Disable interrupt on device
*/
if (irq->off)
irq->off(irq);
/*
* restore the default irq value
*/
if( !vchain ) {
/* single handler vector... */
rtems_hdl_tbl[irq->name] = default_rtems_entry;
} else {
if ( pchain ) {
/* non-first handler being removed */
pchain->next_handler = vchain->next_handler;
} else {
/* first handler isn't malloc'ed, so just overwrite it. Since
* the contents of vchain are being struct copied, vchain itself
* goes away
*/
vchain = vchain->next_handler;
rtems_hdl_tbl[irq->name]= *vchain;
}
free(vchain);
}
rtems_interrupt_enable(level);
return 1;
return RTEMS_SUCCESSFUL;
}
/*
* ------------------------ RTEMS Global Irq Handler Mngt Routines ----------------
*/
int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config)
void bsp_interrupt_handler_default(rtems_vector_number vector)
{
int i;
rtems_irq_connect_data* vchain;
rtems_interrupt_level level;
/*
* Store various code accelerators
*/
internal_config = config;
default_rtems_entry = config->defaultEntry;
rtems_hdl_tbl = config->irqHdlTbl;
rtems_interrupt_disable(level);
/*
* set up internal tables used by rtems interrupt prologue
*/
compute_i8259_masks_from_prio ();
for (i=0; i < internal_config->irqNb; i++) {
BSP_irq_disable_at_i8259s (i);
for( vchain = &rtems_hdl_tbl[i];
((int)vchain != -1 && vchain->hdl != default_rtems_entry.hdl);
vchain = (rtems_irq_connect_data*)vchain->next_handler ) {
BSP_irq_enable_at_i8259s (i);
if (vchain->on)
vchain->on(vchain);
}
}
/*
* must enable slave pic anyway
*/
BSP_irq_enable_at_i8259s (2);
rtems_interrupt_enable(level);
return 1;
printk("spurious interrupt: %u\n", vector);
}
int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config)
void C_dispatch_isr(int vector)
{
*config = internal_config;
return 0;
bsp_interrupt_handler_dispatch(vector);
}
void _ThreadProcessSignalsFromIrq (CPU_Exception_frame* ctx)
@@ -461,29 +249,3 @@ void _ThreadProcessSignalsFromIrq (CPU_Exception_frame* ctx)
* This will include DEBUG session requested from keyboard...
*/
}
void processIrq(unsigned index)
{
rtems_hdl_tbl[index].hdl(rtems_hdl_tbl[index].handle);
}
static inline void
bsp_irq_dispatch_list(
rtems_irq_connect_data *tbl,
unsigned irq,
rtems_irq_hdl sentinel
)
{
rtems_irq_connect_data* vchain;
for( vchain = &tbl[irq];
((int)vchain != -1 && vchain->hdl != sentinel);
vchain = (rtems_irq_connect_data*)vchain->next_handler ) {
vchain->hdl(vchain->handle);
}
}
void C_dispatch_isr(int irq)
{
bsp_irq_dispatch_list(rtems_hdl_tbl, irq, default_rtems_entry.hdl);
}

View File

@@ -33,6 +33,7 @@ extern "C" {
#include <rtems.h>
#define BSP_SHARED_HANDLER_SUPPORT 1
#include <rtems/irq.h>
#include <rtems/irq-extension.h>
/*-------------------------------------------------------------------------+
| Constants

View File

@@ -3,6 +3,7 @@
* This file contains the implementation of rtems initialization
* related to interrupt handling.
*
* Copyright (c) 2009 embedded brains GmbH
* CopyRight (C) 1998 valette@crf.canon.fr
*
* The license and distribution terms for this file may be
@@ -12,11 +13,14 @@
* $Id$
*/
#include <libcpu/cpu.h>
#include <bsp/irq.h>
#include <bsp.h>
#include <rtems/bspIo.h>
#include <libcpu/cpu.h>
#include <bsp.h>
#include <bsp/irq.h>
#include <bsp/irq-generic.h>
/*
* rtems prologue generated in irq_asm.S
*/
@@ -60,51 +64,23 @@ static int raw_not_connected(
static rtems_raw_irq_connect_data idtHdl[IDT_SIZE];
/*
* default IRQ handler
*/
static void irq_default_handler(rtems_irq_hdl_param unused)
{
}
/*
* default IRQ on/off function
*/
static void irq_nop_func(const struct __rtems_irq_connect_data__ *unused)
{
}
/*
* default irq isOn function
*/
static int irq_not_connected( const struct __rtems_irq_connect_data__ *unused)
{
return 0;
}
/*
* Table used to store rtems managed interrupt handlers.
* Borrow the table to store raw handler entries at the beginning.
* The table will be reinitialized before the call to BSP_rtems_irq_mngt_set().
*/
static rtems_irq_connect_data rtemsIrq[BSP_IRQ_LINES_NUMBER] = {
{0,(rtems_irq_hdl)rtems_irq_prologue_0},
{0,(rtems_irq_hdl)rtems_irq_prologue_1},
{0,(rtems_irq_hdl)rtems_irq_prologue_2},
{0,(rtems_irq_hdl)rtems_irq_prologue_3},
{0,(rtems_irq_hdl)rtems_irq_prologue_4},
{0,(rtems_irq_hdl)rtems_irq_prologue_5},
{0,(rtems_irq_hdl)rtems_irq_prologue_6},
{0,(rtems_irq_hdl)rtems_irq_prologue_7},
{0,(rtems_irq_hdl)rtems_irq_prologue_8},
{0,(rtems_irq_hdl)rtems_irq_prologue_9},
{0,(rtems_irq_hdl)rtems_irq_prologue_10},
{0,(rtems_irq_hdl)rtems_irq_prologue_11},
{0,(rtems_irq_hdl)rtems_irq_prologue_12},
{0,(rtems_irq_hdl)rtems_irq_prologue_13},
{0,(rtems_irq_hdl)rtems_irq_prologue_14},
{0,(rtems_irq_hdl)rtems_irq_prologue_15}
static rtems_raw_irq_hdl rtemsIrq[BSP_IRQ_LINES_NUMBER] = {
rtems_irq_prologue_0,
rtems_irq_prologue_1,
rtems_irq_prologue_2,
rtems_irq_prologue_3,
rtems_irq_prologue_4,
rtems_irq_prologue_5,
rtems_irq_prologue_6,
rtems_irq_prologue_7,
rtems_irq_prologue_8,
rtems_irq_prologue_9,
rtems_irq_prologue_10,
rtems_irq_prologue_11,
rtems_irq_prologue_12,
rtems_irq_prologue_13,
rtems_irq_prologue_14,
rtems_irq_prologue_15
};
static rtems_raw_irq_connect_data defaultRawIrq = {
@@ -115,32 +91,8 @@ static rtems_raw_irq_connect_data defaultRawIrq = {
raw_not_connected /* isOn */
};
static rtems_irq_connect_data defaultIrq = {
0, /* vectorIdex */
irq_default_handler, /* hdl */
0, /* handle */
irq_nop_func, /* on */
irq_nop_func, /* off */
irq_not_connected /* isOn */
};
static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={
/*
* actual rpiorities for interrupt :
* 0 means that only current interrupt is masked
* 255 means all other interrupts are masked
* The second entry has a priority of 255 because
* it is the slave pic entry and is should always remain
* unmasked.
*/
0,0,
255,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static interrupt_gate_descriptor idtEntry;
static rtems_irq_global_settings initial_config;
static rtems_raw_irq_global_settings raw_initial_config;
void raw_idt_notify(void)
@@ -191,7 +143,7 @@ void rtems_irq_mngt_init(void)
* with RTEMS prologue.
*/
for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++) {
create_interrupt_gate_descriptor(&idtEntry,(rtems_raw_irq_hdl) rtemsIrq[i].hdl);
create_interrupt_gate_descriptor(&idtEntry, rtemsIrq[i]);
idt_entry_tbl[i + BSP_ASM_IRQ_VECTOR_BASE] = idtEntry;
}
/*
@@ -199,23 +151,11 @@ void rtems_irq_mngt_init(void)
* with raw handlers. We must now initialize the higher level
* interrupt management.
*/
/*
* re-init the rtemsIrq table
*/
for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++) {
rtemsIrq[i] = defaultIrq;
rtemsIrq[i].name = i;
}
/*
* Init initial Interrupt management config
*/
initial_config.irqNb = BSP_IRQ_LINES_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)) {
if (bsp_interrupt_initialize() != RTEMS_SUCCESSFUL) {
/*
* put something here that will show the failure...
*/