Main Page | Directories | File List | Globals

irq.c

Go to the documentation of this file.
00001 /*
00002  * kernel_arch/i386/kernel/irq.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/01
00008  * Author:      Lukasz Dembinski
00009  * Info:        irq.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
00011  *
00012  */
00013  
00014 #include <agnix/agnix.h>
00015 #include <asm/atomic.h>
00016 #include <agnix/adi/adi.h>
00017 #include <agnix/tasks.h>
00018 #include <agnix/linkage.h>
00019 #include <agnix/console.h>
00020 #include <agnix/memory.h>
00021 #include <agnix/irq.h>
00022 #include <agnix/fastirq.h>
00023 #include <asm/faults.h>
00024 #include <agnix/list.h>
00025 #include <agnix/sched.h>
00026 #include <agnix/signals.h>
00027 #include <agnix/fastrand.h>
00028 #include <asm/segment.h>
00029 
00030 #define __KERNEL_SYSCALLS__
00031 
00032 asmlinkage void syscall_irq(struct regs_s regs);
00033 asmlinkage void execute_irq(u32 irq, struct regs_s regs);
00034 
00035 asmlinkage void IRQ_syscall(void);
00036     __asm__ (
00037     "\n.align 16,0x90\n"
00038     "IRQ_syscall:\n\t"
00039     REG_SAVE
00040     "call syscall_irq\n\t"
00041     REG_RESTORE
00042     "iret\n\t"
00043     );
00044 
00045 #define IRQ_BUILD(nr,offset)            \
00046 asmlinkage void IRQ_##nr##offset(void); \
00047     __asm__ (   \
00048     "\n.align 16,0x90\n"        \
00049     "IRQ_"#nr#offset":\n\t"     \
00050     REG_SAVE                    \
00051     "pushl $0x"#nr#offset"\n\t" \
00052     "call execute_irq\n\t"      \
00053     "addl $4, %esp\n\t"         \
00054     REG_RESTORE                 \
00055     "iret\n\t"                  \
00056     );
00057 
00058 #define IRQ_BUILD_NAME(nr, offset)      \
00059     irq_names[nr * 16 + 0x##offset] = IRQ_##nr##offset;
00060 
00061 #define IRQ_BUILD_16(x) \
00062     IRQ_BUILD(x,0); IRQ_BUILD(x,1); IRQ_BUILD(x,2); IRQ_BUILD(x,3);     \
00063     IRQ_BUILD(x,4); IRQ_BUILD(x,5); IRQ_BUILD(x,6); IRQ_BUILD(x,7);     \
00064     IRQ_BUILD(x,8); IRQ_BUILD(x,9); IRQ_BUILD(x,A); IRQ_BUILD(x,B);     \
00065     IRQ_BUILD(x,C); IRQ_BUILD(x,D); IRQ_BUILD(x,E); IRQ_BUILD(x,F);
00066 
00067 #define IRQ_BUILD_NAME_16(x) \
00068     IRQ_BUILD_NAME(x,0); IRQ_BUILD_NAME(x,1); IRQ_BUILD_NAME(x,2); IRQ_BUILD_NAME(x,3); \
00069     IRQ_BUILD_NAME(x,4); IRQ_BUILD_NAME(x,5); IRQ_BUILD_NAME(x,6); IRQ_BUILD_NAME(x,7); \
00070     IRQ_BUILD_NAME(x,8); IRQ_BUILD_NAME(x,9); IRQ_BUILD_NAME(x,A); IRQ_BUILD_NAME(x,B); \
00071     IRQ_BUILD_NAME(x,C); IRQ_BUILD_NAME(x,D); IRQ_BUILD_NAME(x,E); IRQ_BUILD_NAME(x,F);
00072 
00073 IRQ_BUILD_16(0);
00074 
00075 extern struct chip_s i8259a_chip;
00076 extern u32 random_val;
00077 
00078 struct desc_struct idt_table[256] __attribute__((__section__("data.idt"))) = { {0, 0}, };
00079 struct irq_s irq_info[256];
00080 void (*irq_names[256])(void);
00081 char irq_disabled[256];
00082 
00083 void irq_disable_soft(u8 irq)
00084 {
00085     atomic_write(&irq_disabled[irq], 1);
00086 }
00087 
00088 void irq_enable_soft(u8 irq)
00089 {
00090     atomic_write(&irq_disabled[irq], 0);
00091 }
00092 
00093 asmlinkage void execute_irq(u32 irq, struct regs_s regs)
00094 {
00095     struct chip_s *chip = &i8259a_chip;
00096 
00097     if (fastirq_started && (irq != 0))
00098         fastirq_queue(irq);
00099     else
00100         fastirq_run_irq(irq);
00101 
00102     pic_ops(chip)->ack_irq(chip, irq);
00103 
00104     if (current_task->signals.pending)
00105         execute_signals(current_task, &regs);
00106 
00107     //if ((regs.cs & 0x03) && current_task->t_resched) {
00108     if (current_task->t_resched) {
00109         schedule_task();
00110     }
00111 }
00112 
00113 int install_irq(u8 irq, struct irq_routine_s *irq_proc)
00114 {
00115     struct chip_s *chip = &i8259a_chip;
00116     struct irq_s *irq_struct = &irq_info[irq];
00117     u32 flags;
00118 
00119     spin_lock_irqsave(&irq_struct->lock, flags);
00120     pic_ops(chip)->enable_irq(chip, irq);
00121     list_add(&irq_proc->list, &irq_struct->head);
00122     spin_unlock_irqrestore(&irq_struct->lock, flags);
00123     
00124     return 0;
00125 }
00126 
00127 int free_irq(u8 irq, struct irq_routine_s *irq_proc)
00128 {
00129     struct chip_s *chip = &i8259a_chip;
00130     struct irq_s *irq_struct = &irq_info[irq];
00131     u32 flags;
00132 
00133     spin_lock_irqsave(&irq_struct->lock, flags);
00134     list_del(&irq_proc->list);
00135 
00136     if (list_empty(&irq_struct->head)) 
00137         pic_ops(chip)->disable_irq(chip, irq);
00138 
00139     spin_unlock_irqrestore(&irq_struct->lock, flags);
00140 
00141     return 0;
00142 }
00143 
00144 int __init irqs_init(void)
00145 {
00146     int i;
00147     u32 flags;
00148     save_flags(flags); __cli();
00149 
00150     memset(irq_info, 0, 256 * sizeof(struct irq_s));
00151 
00152     for (i = 0; i < 256; i++) {
00153         INIT_LIST_HEAD(&irq_info[i].head);
00154         irq_disabled[i] = 0;
00155     }
00156 
00157     IRQ_BUILD_NAME_16(0);
00158     for (i = 0; i < 16; i++)
00159         set_interrupt_gate(32 + i, __KERNEL_CS, irq_names[i], 0);
00160 
00161     set_interrupt_gate(0x80, __KERNEL_CS, IRQ_syscall, 3);
00162 
00163     __asm__ __volatile__ ("lgdt %0" : "=m" (gdt_descr));
00164     __asm__ __volatile__ ("lidt %0" : "=m" (idt_descr));
00165     __asm__ __volatile__ ("pushfl ; andl $0xffffbfff, (%esp); popfl");
00166 
00167     restore_flags(flags);
00168 
00169     return 0;
00170 }
00171 
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix