00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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, ®s);
00106
00107
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