⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 irq.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  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.rtems.com/license/LICENSE. * *  $Id: irq.c,v 1.4.2.9 2004/11/10 22:15:00 joel Exp $ */  #include <rtems/system.h>#include <bsp.h>#include <bsp/irq.h>#include <bsp/VME.h>#include <bsp/openpic.h>#include <rtems/score/thread.h>#include <rtems/score/apiext.h>#include <libcpu/raw_exception.h>#include <libcpu/io.h>#include <bsp/vectors.h>#include <stdlib.h>#include <rtems/bspIo.h> /* for printk */#define RAVEN_INTR_ACK_REG 0xfeff0030/* * pointer to the mask representing the additionnal irq vectors * that must be disabled when a particular entry is activated. * They will be dynamically computed from the priority table given * in BSP_rtems_irq_mngt_set(); * CAUTION : this table is accessed directly by interrupt routine * 	     prologue. */rtems_i8259_masks 	irq_mask_or_tbl[BSP_IRQ_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;static rtems_irq_connect_data*		rtems_hdl_tbl;/* * Check if IRQ is an ISA IRQ */static inline int is_isa_irq(const rtems_irq_symbolic_name irqLine){  return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) &	  ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET)	 );}/* * Check if IRQ is an OPENPIC IRQ */static inline int is_pci_irq(const rtems_irq_symbolic_name irqLine){  return (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) &	  ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET)	 );}/* * Check if IRQ 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)	 );}/* * ------------------------ 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_i8259_masks_from_prio (){  int i;  int j;  /*   * Always mask at least current interrupt to prevent re-entrance   */  for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) {    * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i);    for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) {      /*       * Mask interrupts at i8259 level that have a lower priority       */      if (internal_config->irqPrioTbl [i] > internal_config->irqPrioTbl [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){    unsigned int level;    rtems_irq_connect_data* vchain;     if (!isValidInterrupt(irq->name)) {      printk("Invalid interrupt vector %d\n",irq->name);      return 0;    }    _CPU_ISR_Disable(level);    if ( (int)rtems_hdl_tbl[irq->name].next_handler  == -1 ) {      _CPU_ISR_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;        if (is_isa_irq(irq->name)) {      /*       * Enable interrupt at PIC level       */      BSP_irq_enable_at_i8259s (irq->name);    }        if (is_pci_irq(irq->name)) {      /*       * Enable interrupt at OPENPIC level       */      openpic_enable_irq ((int) irq->name - BSP_PCI_IRQ_LOWEST_OFFSET);    }    if (is_processor_irq(irq->name)) {      /*       * Enable exception at processor level       */    }    /*     * Enable interrupt on device     */    irq->on(irq);        _CPU_ISR_Enable(level);    return 1;}/* * ------------------------ 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)) {      printk("Invalid interrupt vector %d\n",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.     */    _CPU_ISR_Disable(level);    if (rtems_hdl_tbl[irq->name].hdl != default_rtems_entry.hdl) {      _CPU_ISR_Enable(level);      printk("IRQ vector %d already connected\n",irq->name);      return 0;    }    /*     * store the data provided by user     */    rtems_hdl_tbl[irq->name] = *irq;    rtems_hdl_tbl[irq->name].next_handler = (void *)-1;        if (is_isa_irq(irq->name)) {      /*       * Enable interrupt at PIC level       */      BSP_irq_enable_at_i8259s (irq->name);    }        if (is_pci_irq(irq->name)) {      /*       * Enable interrupt at OPENPIC level       */      openpic_enable_irq ((int) irq->name - BSP_PCI_IRQ_LOWEST_OFFSET);    }    if (is_processor_irq(irq->name)) {      /*       * Enable exception at processor level       */    }    /*     * 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){     unsigned int level;     if (!isValidInterrupt(irq->name)) {      return 0;     }     _CPU_ISR_Disable(level);     *irq = rtems_hdl_tbl[irq->name];     _CPU_ISR_Enable(level);     return 1;}int BSP_remove_rtems_irq_handler  (const rtems_irq_connect_data* irq){   rtems_irq_connect_data *pchain= NULL, *vchain = NULL;    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.     */    _CPU_ISR_Disable(level);    if (rtems_hdl_tbl[irq->name].hdl != irq->hdl) {      _CPU_ISR_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 )       {          _CPU_ISR_Enable(level);          return 0;       }    }    else    {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -