1 /* 2 * File : interrupt.c 3 * This file is part of RT-Thread RTOS 4 * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License along 17 * with this program; if not, write to the Free Software Foundation, Inc., 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Change Logs: 21 * Date Author Notes 22 * 2015/9/15 Bernard Update to new interrupt framework. 23 */ 24 25 #include <rtthread.h> 26 #include <rthw.h> 27 28 #include <bsp.h> 29 30 extern rt_uint32_t rt_interrupt_nest; 31 extern void rt_hw_idt_init(void); 32 33 rt_uint32_t rt_interrupt_from_thread, rt_interrupt_to_thread; 34 rt_uint32_t rt_thread_switch_interrupt_flag; 35 36 /* exception and interrupt handler table */ 37 struct rt_irq_desc irq_desc[MAX_HANDLERS]; 38 39 rt_uint16_t irq_mask_8259A = 0xFFFF; 40 41 void rt_hw_interrupt_handle(int vector, void* param); 42 43 /** 44 * @addtogroup I386 45 */ 46 /*@{*/ 47 48 /** 49 * This function initializes 8259 interrupt controller 50 */ 51 void rt_hw_pic_init() 52 { 53 outb(IO_PIC1, 0x11); 54 outb(IO_PIC1+1, IRQ_OFFSET); 55 outb(IO_PIC1+1, 1<<IRQ_SLAVE); 56 outb(IO_PIC1+1, 0x3); 57 outb(IO_PIC1+1, 0xff); 58 outb(IO_PIC1, 0x68); 59 outb(IO_PIC1, 0x0a); 60 outb(IO_PIC2, 0x11); 61 outb(IO_PIC2+1, IRQ_OFFSET + 8); 62 outb(IO_PIC2+1, IRQ_SLAVE); 63 outb(IO_PIC2+1, 0x3); 64 outb(IO_PIC2+1, 0xff); 65 outb(IO_PIC2, 0x68); 66 outb(IO_PIC2, 0x0a); 67 68 if (irq_mask_8259A != 0xFFFF) 69 { 70 outb(IO_PIC1+1, (char)irq_mask_8259A); 71 outb(IO_PIC2+1, (char)(irq_mask_8259A >> 8)); 72 } 73 74 /* init interrupt nest, and context */ 75 rt_interrupt_nest = 0; 76 rt_interrupt_from_thread = 0; 77 rt_interrupt_to_thread = 0; 78 rt_thread_switch_interrupt_flag = 0; 79 } 80 81 void rt_hw_interrupt_handle(int vector, void* param) 82 { 83 rt_kprintf("Unhandled interrupt %d occured!!!\n", vector); 84 } 85 86 void rt_hw_isr(int vector) 87 { 88 if (vector < MAX_HANDLERS) 89 { 90 irq_desc[vector].handler(vector, irq_desc[vector].param); 91 } 92 } 93 94 /** 95 * This function initializes interrupt descript table and 8259 interrupt controller 96 * 97 */ 98 void rt_hw_interrupt_init(void) 99 { 100 int idx; 101 102 rt_hw_idt_init(); 103 rt_hw_pic_init(); 104 105 /* init exceptions table */ 106 for(idx=0; idx < MAX_HANDLERS; idx++) 107 { 108 irq_desc[idx].handler = (rt_isr_handler_t)rt_hw_interrupt_handle; 109 irq_desc[idx].param = RT_NULL; 110 #ifdef RT_USING_INTERRUPT_INFO 111 rt_snprintf(irq_desc[idx].name, RT_NAME_MAX - 1, "default"); 112 irq_desc[idx].counter = 0; 113 #endif 114 } 115 } 116 117 void rt_hw_interrupt_umask(int vector) 118 { 119 irq_mask_8259A = irq_mask_8259A&~(1<<vector); 120 outb(IO_PIC1+1, (char)irq_mask_8259A); 121 outb(IO_PIC2+1, (char)(irq_mask_8259A >> 8)); 122 } 123 124 void rt_hw_interrupt_mask(int vector) 125 { 126 irq_mask_8259A = irq_mask_8259A | (1<<vector); 127 outb(IO_PIC1+1, (char)irq_mask_8259A); 128 outb(IO_PIC2+1, (char)(irq_mask_8259A >> 8)); 129 } 130 131 rt_isr_handler_t rt_hw_interrupt_install(int vector, 132 rt_isr_handler_t handler, 133 void *param, 134 const char *name) 135 { 136 rt_isr_handler_t old_handler = RT_NULL; 137 138 if(vector < MAX_HANDLERS) 139 { 140 old_handler = irq_desc[vector].handler; 141 if (handler != RT_NULL) 142 { 143 irq_desc[vector].handler = (rt_isr_handler_t)handler; 144 irq_desc[vector].param = param; 145 #ifdef RT_USING_INTERRUPT_INFO 146 rt_snprintf(irq_desc[vector].name, RT_NAME_MAX - 1, "%s", name); 147 irq_desc[vector].counter = 0; 148 #endif 149 } 150 } 151 152 return old_handler; 153 } 154 155 rt_base_t rt_hw_interrupt_disable(void) 156 { 157 rt_base_t level; 158 159 __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (level): :"memory"); 160 return level; 161 } 162 163 void rt_hw_interrupt_enable(rt_base_t level) 164 { 165 __asm__ __volatile__("pushl %0 ; popfl": :"g" (level):"memory", "cc"); 166 } 167 168 /*@}*/ 169