diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2009-07-03 15:08:54 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2009-07-03 15:08:54 +0000 |
commit | fc5490fe84850d51e7cbfc43377ec6844d793b87 (patch) | |
tree | 936bfb0a3056da3936d7ab0867c40f3e130304db /c/src/lib/libbsp/i386/shared/irq/irq.c | |
parent | 2009-07-01 Sebastian Huber <sebastian.huber@embedded-brains.de> (diff) | |
download | rtems-fc5490fe84850d51e7cbfc43377ec6844d793b87.tar.bz2 |
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.
Diffstat (limited to 'c/src/lib/libbsp/i386/shared/irq/irq.c')
-rw-r--r-- | c/src/lib/libbsp/i386/shared/irq/irq.c | 318 |
1 files changed, 40 insertions, 278 deletions
diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.c b/c/src/lib/libbsp/i386/shared/irq/irq.c index 325c53b79f..5e546a3309 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq.c +++ b/c/src/lib/libbsp/i386/shared/irq/irq.c @@ -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; - } - /* - * 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. + * set up internal tables used by rtems interrupt prologue */ - rtems_interrupt_disable(level); - if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) { - rtems_interrupt_enable(level); - return 0; - } - - 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); + compute_i8259_masks_from_prio(); /* - * Disable interrupt on device + * must enable slave pic anyway */ - if (irq->off) - irq->off(irq); + BSP_irq_enable_at_i8259s(2); - /* - * 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); -} |