Loading arch/m68k/kernel/entry.S +1 −10 Original line number Original line Diff line number Diff line Loading @@ -205,18 +205,9 @@ ENTRY(auto_inthandler) movel %sp,%sp@- movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack movel %d0,%sp@- | put vector # on stack #if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) btstb #4,0xff000000 | Q40 floppy needs very special treatment ... jbeq 1f btstb #3,0xff000004 jbeq 1f jbsr floppy_hardint jbra 3f 1: #endif auto_irqhandler_fixup = . + 2 auto_irqhandler_fixup = . + 2 jsr m68k_handle_int | process the IRQ jsr m68k_handle_int | process the IRQ 3: addql #8,%sp | pop parameters off stack addql #8,%sp | pop parameters off stack ret_from_interrupt: ret_from_interrupt: subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) Loading arch/m68k/q40/config.c +0 −11 Original line number Original line Diff line number Diff line Loading @@ -38,13 +38,8 @@ extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); extern void q40_init_IRQ (void); extern void q40_init_IRQ (void); extern void q40_free_irq (unsigned int, void *); extern int show_q40_interrupts (struct seq_file *, void *); extern void q40_enable_irq (unsigned int); extern void q40_disable_irq (unsigned int); static void q40_get_model(char *model); static void q40_get_model(char *model); static int q40_get_hardware_list(char *buffer); static int q40_get_hardware_list(char *buffer); extern int q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern unsigned long q40_gettimeoffset (void); extern unsigned long q40_gettimeoffset (void); Loading Loading @@ -174,12 +169,6 @@ void __init config_q40(void) mach_set_clock_mmss = q40_set_clock_mmss; mach_set_clock_mmss = q40_set_clock_mmss; mach_reset = q40_reset; mach_reset = q40_reset; mach_free_irq = q40_free_irq; mach_process_int = q40_process_int; mach_get_irq_list = show_q40_interrupts; mach_request_irq = q40_request_irq; enable_irq = q40_enable_irq; disable_irq = q40_disable_irq; mach_get_model = q40_get_model; mach_get_model = q40_get_model; mach_get_hardware_list = q40_get_hardware_list; mach_get_hardware_list = q40_get_hardware_list; Loading arch/m68k/q40/q40ints.c +168 −296 Original line number Original line Diff line number Diff line Loading @@ -14,13 +14,8 @@ #include <linux/types.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/interrupt.h> #include <linux/interrupt.h> #include <linux/hardirq.h> #include <asm/rtc.h> #include <asm/ptrace.h> #include <asm/ptrace.h> #include <asm/system.h> #include <asm/system.h> #include <asm/irq.h> #include <asm/irq.h> Loading @@ -39,28 +34,37 @@ * * */ */ extern int ints_inited; static void q40_irq_handler(unsigned int, struct pt_regs *fp); static void q40_enable_irq(unsigned int); static void q40_disable_irq(unsigned int); unsigned short q40_ablecount[35]; unsigned short q40_state[35]; irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp); static int q40_irq_startup(unsigned int irq) { /* test for ISA ints not implemented by HW */ static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp); switch (irq) { case 1: case 2: case 8: case 9: case 11: case 12: case 13: #define DEVNAME_SIZE 24 printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq); return -ENXIO; } return 0; } static struct q40_irq_node { static void q40_irq_shutdown(unsigned int irq) irqreturn_t (*handler)(int, void *, struct pt_regs *); { unsigned long flags; } void *dev_id; /* struct q40_irq_node *next;*/ char devname[DEVNAME_SIZE]; unsigned count; unsigned short state; } irq_tab[Q40_IRQ_MAX+1]; short unsigned q40_ablecount[Q40_IRQ_MAX+1]; static struct irq_controller q40_irq_controller = { .name = "q40", .lock = SPIN_LOCK_UNLOCKED, .startup = q40_irq_startup, .shutdown = q40_irq_shutdown, .enable = q40_enable_irq, .disable = q40_disable_irq, }; /* /* * void q40_init_IRQ (void) * void q40_init_IRQ (void) Loading @@ -73,27 +77,17 @@ short unsigned q40_ablecount[Q40_IRQ_MAX+1]; * the q40 IRQ handling routines. * the q40 IRQ handling routines. */ */ static int disabled=0; static int disabled; void q40_init_IRQ(void) void q40_init_IRQ(void) { { int i; m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX); disabled=0; for (i = 0; i <= Q40_IRQ_MAX; i++) { irq_tab[i].handler = q40_defhand; irq_tab[i].flags = 0; irq_tab[i].dev_id = NULL; /* irq_tab[i].next = NULL;*/ irq_tab[i].devname[0] = 0; irq_tab[i].count = 0; irq_tab[i].state =0; q40_ablecount[i]=0; /* all enabled */ } /* setup handler for ISA ints */ /* setup handler for ISA ints */ cpu_request_irq(IRQ_AUTO_2, q40_irq2_handler, 0, m68k_setup_auto_interrupt(q40_irq_handler); "q40 ISA and master chip", NULL); m68k_irq_startup(IRQ_AUTO_2); m68k_irq_startup(IRQ_AUTO_4); /* now enable some ints.. */ /* now enable some ints.. */ master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ Loading @@ -102,106 +96,6 @@ void q40_init_IRQ (void) master_outb(0, KEY_IRQ_ENABLE_REG); master_outb(0, KEY_IRQ_ENABLE_REG); } } int q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { /*printk("q40_request_irq %d, %s\n",irq,devname);*/ if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); return -ENXIO; } /* test for ISA ints not implemented by HW */ switch (irq) { case 1: case 2: case 8: case 9: case 12: case 13: printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname); return -ENXIO; case 11: printk("warning IRQ 10 and 11 not distinguishable\n"); irq=10; default: ; } if (irq<Q40_IRQ_SAMPLE) { if (irq_tab[irq].dev_id != NULL) { printk("%s: IRQ %d from %s is not replaceable\n", __FUNCTION__, irq, irq_tab[irq].devname); return -EBUSY; } /*printk("IRQ %d set to handler %p\n",irq,handler);*/ if (dev_id==NULL) { printk("WARNING: dev_id == NULL in request_irq\n"); dev_id=(void*)1; } irq_tab[irq].handler = handler; irq_tab[irq].flags = flags; irq_tab[irq].dev_id = dev_id; strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname)); irq_tab[irq].state = 0; return 0; } else { /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/ cpu_request_irq(4, handler, flags, devname, dev_id); cpu_request_irq(6, handler, flags, devname, dev_id); return 0; } } void q40_free_irq(unsigned int irq, void *dev_id) { if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id); return; } /* test for ISA ints not implemented by HW */ switch (irq) { case 1: case 2: case 8: case 9: case 12: case 13: printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id); return; case 11: irq=10; default: ; } if (irq<Q40_IRQ_SAMPLE) { if (irq_tab[irq].dev_id != dev_id) printk("%s: Removing probably wrong IRQ %d from %s\n", __FUNCTION__, irq, irq_tab[irq].devname); irq_tab[irq].handler = q40_defhand; irq_tab[irq].flags = 0; irq_tab[irq].dev_id = NULL; /* irq_tab[irq].devname = NULL; */ /* do not reset state !! */ } else { /* == Q40_IRQ_SAMPLE */ cpu_free_irq(4, dev_id); cpu_free_irq(6, dev_id); } } irqreturn_t q40_process_int (int level, struct pt_regs *fp) { printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n", level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2); printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG)); return IRQ_HANDLED; } /* /* * this stuff doesn't really belong here.. * this stuff doesn't really belong here.. Loading @@ -216,8 +110,7 @@ void q40_mksound(unsigned int hz, unsigned int ticks) { { /* for now ignore hz, except that hz==0 switches off sound */ /* for now ignore hz, except that hz==0 switches off sound */ /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ if (hz==0) if (hz == 0) { { if (sound_ticks) if (sound_ticks) sound_ticks = 1; sound_ticks = 1; Loading @@ -227,7 +120,8 @@ void q40_mksound(unsigned int hz, unsigned int ticks) return; return; } } /* sound itself is done in q40_timer_int */ /* sound itself is done in q40_timer_int */ if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */ if (sound_ticks == 0) sound_ticks = 1000; /* pretty long beep */ sound_ticks = ticks << 1; sound_ticks = ticks << 1; } } Loading @@ -236,8 +130,7 @@ static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *); static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs) static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs) { { ql_ticks = ql_ticks ? 0 : 1; ql_ticks = ql_ticks ? 0 : 1; if (sound_ticks) if (sound_ticks) { { unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; sound_ticks--; sound_ticks--; *DAC_LEFT=sval; *DAC_LEFT=sval; Loading Loading @@ -307,23 +200,35 @@ static int mext_disabled=0; /* ext irq disabled by master chip? */ static int aliased_irq=0; /* how many times inside handler ?*/ static int aliased_irq=0; /* how many times inside handler ?*/ /* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */ /* got interrupt, dispatch to ISA or keyboard/timer IRQs */ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) { { unsigned mir, mer; unsigned mir, mer; int irq,i; int i; //repeat: //repeat: mir = master_inb(IIRQ_REG); mir = master_inb(IIRQ_REG); #ifdef CONFIG_BLK_DEV_FD if ((mir & Q40_IRQ_EXT_MASK) && (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) { floppy_hardint(); return; } #endif switch (irq) { case 4: case 6: m68k_handle_int(Q40_IRQ_SAMPLE, fp); return; } if (mir & Q40_IRQ_FRAME_MASK) { if (mir & Q40_IRQ_FRAME_MASK) { irq_tab[Q40_IRQ_FRAME].count++; m68k_handle_int(Q40_IRQ_FRAME, fp); irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp); master_outb(-1, FRAME_CLEAR_REG); master_outb(-1, FRAME_CLEAR_REG); } } if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { mer = master_inb(EIRQ_REG); mer = master_inb(EIRQ_REG); for (i = 0; eirqs[i].mask; i++) { for (i = 0; eirqs[i].mask; i++) { if (mer&(eirqs[i].mask)) { if (mer & eirqs[i].mask) { irq = eirqs[i].irq; irq = eirqs[i].irq; /* /* * There is a little mess wrt which IRQ really caused this irq request. The * There is a little mess wrt which IRQ really caused this irq request. The Loading @@ -335,11 +240,7 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) /*aliased_irq++;*/ /*aliased_irq++;*/ goto iirq; goto iirq; } } if (irq_tab[irq].handler == q40_defhand ) { if (q40_state[irq] & IRQ_INPROGRESS) { printk("handler for IRQ %d not defined\n",irq); continue; /* ignore uninited INTs :-( */ } if ( irq_tab[irq].state & IRQ_INPROGRESS ) { /* some handlers do local_irq_enable() for irq latency reasons, */ /* some handlers do local_irq_enable() for irq latency reasons, */ /* however reentering an active irq handler is not permitted */ /* however reentering an active irq handler is not permitted */ #ifdef IP_USE_DISABLE #ifdef IP_USE_DISABLE Loading @@ -348,16 +249,16 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) disable_irq(irq); disable_irq(irq); disabled = 1; disabled = 1; #else #else /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */ /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n", irq, disabled ? "already" : "not yet"); */ fp->sr = (((fp->sr) & (~0x700))+0x200); fp->sr = (((fp->sr) & (~0x700))+0x200); disabled = 1; disabled = 1; #endif #endif goto iirq; goto iirq; } } irq_tab[irq].count++; q40_state[irq] |= IRQ_INPROGRESS; irq_tab[irq].state |= IRQ_INPROGRESS; m68k_handle_int(irq, fp); irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); q40_state[irq] &= ~IRQ_INPROGRESS; irq_tab[irq].state &= ~IRQ_INPROGRESS; /* naively enable everything, if that fails than */ /* naively enable everything, if that fails than */ /* this function will be reentered immediately thus */ /* this function will be reentered immediately thus */ Loading @@ -367,59 +268,34 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) #ifdef IP_USE_DISABLE #ifdef IP_USE_DISABLE if (irq > 4) { if (irq > 4) { disabled = 0; disabled = 0; enable_irq(irq);} enable_irq(irq); } #else #else disabled = 0; disabled = 0; /*printk("reenabling irq %d\n", irq); */ /*printk("reenabling irq %d\n", irq); */ #endif #endif } } // used to do 'goto repeat;' here, this delayed bh processing too long // used to do 'goto repeat;' here, this delayed bh processing too long return IRQ_HANDLED; return; } } } if (mer && ccleirq > 0 && !aliased_irq) { printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer); ccleirq--; } } if (mer && ccleirq>0 && !aliased_irq) printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--; } } iirq: iirq: mir = master_inb(IIRQ_REG); mir = master_inb(IIRQ_REG); /* should test whether keyboard irq is really enabled, doing it in defhand */ /* should test whether keyboard irq is really enabled, doing it in defhand */ if (mir&Q40_IRQ_KEYB_MASK) { if (mir & Q40_IRQ_KEYB_MASK) irq_tab[Q40_IRQ_KEYBOARD].count++; m68k_handle_int(Q40_IRQ_KEYBOARD, fp); irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp); } return IRQ_HANDLED; } int show_q40_interrupts (struct seq_file *p, void *v) { int i; for (i = 0; i <= Q40_IRQ_MAX; i++) { return; if (irq_tab[i].count) seq_printf(p, "%sIRQ %02d: %8d %s%s\n", (i<=15) ? "ISA-" : " " , i, irq_tab[i].count, irq_tab[i].devname[0] ? irq_tab[i].devname : "?", irq_tab[i].handler == q40_defhand ? " (now unassigned)" : ""); } return 0; } static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp) { if (irq!=Q40_IRQ_KEYBOARD) printk ("Unknown q40 interrupt %d\n", irq); else master_outb(-1,KEYBOARD_UNLOCK_REG); return IRQ_NONE; } } void q40_enable_irq(unsigned int irq) void q40_enable_irq(unsigned int irq) { { if ( irq>=5 && irq<=15 ) if (irq >= 5 && irq <= 15) { { mext_disabled--; mext_disabled--; if (mext_disabled > 0) if (mext_disabled > 0) printk("q40_enable_irq : nested disable/enable\n"); printk("q40_enable_irq : nested disable/enable\n"); Loading @@ -439,7 +315,8 @@ void q40_disable_irq (unsigned int irq) if (irq >= 5 && irq <= 15) { if (irq >= 5 && irq <= 15) { master_outb(0, EXT_ENABLE_REG); master_outb(0, EXT_ENABLE_REG); mext_disabled++; mext_disabled++; if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled); if (mext_disabled > 1) printk("disable_irq nesting count %d\n",mext_disabled); } } } } Loading @@ -452,8 +329,3 @@ int q40_probe_irq_off (unsigned long irqs) { { return -1; return -1; } } /* * Local variables: * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c" * End: */ Loading
arch/m68k/kernel/entry.S +1 −10 Original line number Original line Diff line number Diff line Loading @@ -205,18 +205,9 @@ ENTRY(auto_inthandler) movel %sp,%sp@- movel %sp,%sp@- movel %d0,%sp@- | put vector # on stack movel %d0,%sp@- | put vector # on stack #if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) btstb #4,0xff000000 | Q40 floppy needs very special treatment ... jbeq 1f btstb #3,0xff000004 jbeq 1f jbsr floppy_hardint jbra 3f 1: #endif auto_irqhandler_fixup = . + 2 auto_irqhandler_fixup = . + 2 jsr m68k_handle_int | process the IRQ jsr m68k_handle_int | process the IRQ 3: addql #8,%sp | pop parameters off stack addql #8,%sp | pop parameters off stack ret_from_interrupt: ret_from_interrupt: subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) Loading
arch/m68k/q40/config.c +0 −11 Original line number Original line Diff line number Diff line Loading @@ -38,13 +38,8 @@ extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); extern void q40_init_IRQ (void); extern void q40_init_IRQ (void); extern void q40_free_irq (unsigned int, void *); extern int show_q40_interrupts (struct seq_file *, void *); extern void q40_enable_irq (unsigned int); extern void q40_disable_irq (unsigned int); static void q40_get_model(char *model); static void q40_get_model(char *model); static int q40_get_hardware_list(char *buffer); static int q40_get_hardware_list(char *buffer); extern int q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id); extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); extern unsigned long q40_gettimeoffset (void); extern unsigned long q40_gettimeoffset (void); Loading Loading @@ -174,12 +169,6 @@ void __init config_q40(void) mach_set_clock_mmss = q40_set_clock_mmss; mach_set_clock_mmss = q40_set_clock_mmss; mach_reset = q40_reset; mach_reset = q40_reset; mach_free_irq = q40_free_irq; mach_process_int = q40_process_int; mach_get_irq_list = show_q40_interrupts; mach_request_irq = q40_request_irq; enable_irq = q40_enable_irq; disable_irq = q40_disable_irq; mach_get_model = q40_get_model; mach_get_model = q40_get_model; mach_get_hardware_list = q40_get_hardware_list; mach_get_hardware_list = q40_get_hardware_list; Loading
arch/m68k/q40/q40ints.c +168 −296 Original line number Original line Diff line number Diff line Loading @@ -14,13 +14,8 @@ #include <linux/types.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/interrupt.h> #include <linux/interrupt.h> #include <linux/hardirq.h> #include <asm/rtc.h> #include <asm/ptrace.h> #include <asm/ptrace.h> #include <asm/system.h> #include <asm/system.h> #include <asm/irq.h> #include <asm/irq.h> Loading @@ -39,28 +34,37 @@ * * */ */ extern int ints_inited; static void q40_irq_handler(unsigned int, struct pt_regs *fp); static void q40_enable_irq(unsigned int); static void q40_disable_irq(unsigned int); unsigned short q40_ablecount[35]; unsigned short q40_state[35]; irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp); static int q40_irq_startup(unsigned int irq) { /* test for ISA ints not implemented by HW */ static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp); switch (irq) { case 1: case 2: case 8: case 9: case 11: case 12: case 13: #define DEVNAME_SIZE 24 printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq); return -ENXIO; } return 0; } static struct q40_irq_node { static void q40_irq_shutdown(unsigned int irq) irqreturn_t (*handler)(int, void *, struct pt_regs *); { unsigned long flags; } void *dev_id; /* struct q40_irq_node *next;*/ char devname[DEVNAME_SIZE]; unsigned count; unsigned short state; } irq_tab[Q40_IRQ_MAX+1]; short unsigned q40_ablecount[Q40_IRQ_MAX+1]; static struct irq_controller q40_irq_controller = { .name = "q40", .lock = SPIN_LOCK_UNLOCKED, .startup = q40_irq_startup, .shutdown = q40_irq_shutdown, .enable = q40_enable_irq, .disable = q40_disable_irq, }; /* /* * void q40_init_IRQ (void) * void q40_init_IRQ (void) Loading @@ -73,27 +77,17 @@ short unsigned q40_ablecount[Q40_IRQ_MAX+1]; * the q40 IRQ handling routines. * the q40 IRQ handling routines. */ */ static int disabled=0; static int disabled; void q40_init_IRQ(void) void q40_init_IRQ(void) { { int i; m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX); disabled=0; for (i = 0; i <= Q40_IRQ_MAX; i++) { irq_tab[i].handler = q40_defhand; irq_tab[i].flags = 0; irq_tab[i].dev_id = NULL; /* irq_tab[i].next = NULL;*/ irq_tab[i].devname[0] = 0; irq_tab[i].count = 0; irq_tab[i].state =0; q40_ablecount[i]=0; /* all enabled */ } /* setup handler for ISA ints */ /* setup handler for ISA ints */ cpu_request_irq(IRQ_AUTO_2, q40_irq2_handler, 0, m68k_setup_auto_interrupt(q40_irq_handler); "q40 ISA and master chip", NULL); m68k_irq_startup(IRQ_AUTO_2); m68k_irq_startup(IRQ_AUTO_4); /* now enable some ints.. */ /* now enable some ints.. */ master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ Loading @@ -102,106 +96,6 @@ void q40_init_IRQ (void) master_outb(0, KEY_IRQ_ENABLE_REG); master_outb(0, KEY_IRQ_ENABLE_REG); } } int q40_request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id) { /*printk("q40_request_irq %d, %s\n",irq,devname);*/ if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); return -ENXIO; } /* test for ISA ints not implemented by HW */ switch (irq) { case 1: case 2: case 8: case 9: case 12: case 13: printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname); return -ENXIO; case 11: printk("warning IRQ 10 and 11 not distinguishable\n"); irq=10; default: ; } if (irq<Q40_IRQ_SAMPLE) { if (irq_tab[irq].dev_id != NULL) { printk("%s: IRQ %d from %s is not replaceable\n", __FUNCTION__, irq, irq_tab[irq].devname); return -EBUSY; } /*printk("IRQ %d set to handler %p\n",irq,handler);*/ if (dev_id==NULL) { printk("WARNING: dev_id == NULL in request_irq\n"); dev_id=(void*)1; } irq_tab[irq].handler = handler; irq_tab[irq].flags = flags; irq_tab[irq].dev_id = dev_id; strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname)); irq_tab[irq].state = 0; return 0; } else { /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/ cpu_request_irq(4, handler, flags, devname, dev_id); cpu_request_irq(6, handler, flags, devname, dev_id); return 0; } } void q40_free_irq(unsigned int irq, void *dev_id) { if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id); return; } /* test for ISA ints not implemented by HW */ switch (irq) { case 1: case 2: case 8: case 9: case 12: case 13: printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id); return; case 11: irq=10; default: ; } if (irq<Q40_IRQ_SAMPLE) { if (irq_tab[irq].dev_id != dev_id) printk("%s: Removing probably wrong IRQ %d from %s\n", __FUNCTION__, irq, irq_tab[irq].devname); irq_tab[irq].handler = q40_defhand; irq_tab[irq].flags = 0; irq_tab[irq].dev_id = NULL; /* irq_tab[irq].devname = NULL; */ /* do not reset state !! */ } else { /* == Q40_IRQ_SAMPLE */ cpu_free_irq(4, dev_id); cpu_free_irq(6, dev_id); } } irqreturn_t q40_process_int (int level, struct pt_regs *fp) { printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n", level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2); printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG)); return IRQ_HANDLED; } /* /* * this stuff doesn't really belong here.. * this stuff doesn't really belong here.. Loading @@ -216,8 +110,7 @@ void q40_mksound(unsigned int hz, unsigned int ticks) { { /* for now ignore hz, except that hz==0 switches off sound */ /* for now ignore hz, except that hz==0 switches off sound */ /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ if (hz==0) if (hz == 0) { { if (sound_ticks) if (sound_ticks) sound_ticks = 1; sound_ticks = 1; Loading @@ -227,7 +120,8 @@ void q40_mksound(unsigned int hz, unsigned int ticks) return; return; } } /* sound itself is done in q40_timer_int */ /* sound itself is done in q40_timer_int */ if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */ if (sound_ticks == 0) sound_ticks = 1000; /* pretty long beep */ sound_ticks = ticks << 1; sound_ticks = ticks << 1; } } Loading @@ -236,8 +130,7 @@ static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *); static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs) static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs) { { ql_ticks = ql_ticks ? 0 : 1; ql_ticks = ql_ticks ? 0 : 1; if (sound_ticks) if (sound_ticks) { { unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; sound_ticks--; sound_ticks--; *DAC_LEFT=sval; *DAC_LEFT=sval; Loading Loading @@ -307,23 +200,35 @@ static int mext_disabled=0; /* ext irq disabled by master chip? */ static int aliased_irq=0; /* how many times inside handler ?*/ static int aliased_irq=0; /* how many times inside handler ?*/ /* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */ /* got interrupt, dispatch to ISA or keyboard/timer IRQs */ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) { { unsigned mir, mer; unsigned mir, mer; int irq,i; int i; //repeat: //repeat: mir = master_inb(IIRQ_REG); mir = master_inb(IIRQ_REG); #ifdef CONFIG_BLK_DEV_FD if ((mir & Q40_IRQ_EXT_MASK) && (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) { floppy_hardint(); return; } #endif switch (irq) { case 4: case 6: m68k_handle_int(Q40_IRQ_SAMPLE, fp); return; } if (mir & Q40_IRQ_FRAME_MASK) { if (mir & Q40_IRQ_FRAME_MASK) { irq_tab[Q40_IRQ_FRAME].count++; m68k_handle_int(Q40_IRQ_FRAME, fp); irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp); master_outb(-1, FRAME_CLEAR_REG); master_outb(-1, FRAME_CLEAR_REG); } } if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { mer = master_inb(EIRQ_REG); mer = master_inb(EIRQ_REG); for (i = 0; eirqs[i].mask; i++) { for (i = 0; eirqs[i].mask; i++) { if (mer&(eirqs[i].mask)) { if (mer & eirqs[i].mask) { irq = eirqs[i].irq; irq = eirqs[i].irq; /* /* * There is a little mess wrt which IRQ really caused this irq request. The * There is a little mess wrt which IRQ really caused this irq request. The Loading @@ -335,11 +240,7 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) /*aliased_irq++;*/ /*aliased_irq++;*/ goto iirq; goto iirq; } } if (irq_tab[irq].handler == q40_defhand ) { if (q40_state[irq] & IRQ_INPROGRESS) { printk("handler for IRQ %d not defined\n",irq); continue; /* ignore uninited INTs :-( */ } if ( irq_tab[irq].state & IRQ_INPROGRESS ) { /* some handlers do local_irq_enable() for irq latency reasons, */ /* some handlers do local_irq_enable() for irq latency reasons, */ /* however reentering an active irq handler is not permitted */ /* however reentering an active irq handler is not permitted */ #ifdef IP_USE_DISABLE #ifdef IP_USE_DISABLE Loading @@ -348,16 +249,16 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) disable_irq(irq); disable_irq(irq); disabled = 1; disabled = 1; #else #else /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */ /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n", irq, disabled ? "already" : "not yet"); */ fp->sr = (((fp->sr) & (~0x700))+0x200); fp->sr = (((fp->sr) & (~0x700))+0x200); disabled = 1; disabled = 1; #endif #endif goto iirq; goto iirq; } } irq_tab[irq].count++; q40_state[irq] |= IRQ_INPROGRESS; irq_tab[irq].state |= IRQ_INPROGRESS; m68k_handle_int(irq, fp); irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); q40_state[irq] &= ~IRQ_INPROGRESS; irq_tab[irq].state &= ~IRQ_INPROGRESS; /* naively enable everything, if that fails than */ /* naively enable everything, if that fails than */ /* this function will be reentered immediately thus */ /* this function will be reentered immediately thus */ Loading @@ -367,59 +268,34 @@ irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) #ifdef IP_USE_DISABLE #ifdef IP_USE_DISABLE if (irq > 4) { if (irq > 4) { disabled = 0; disabled = 0; enable_irq(irq);} enable_irq(irq); } #else #else disabled = 0; disabled = 0; /*printk("reenabling irq %d\n", irq); */ /*printk("reenabling irq %d\n", irq); */ #endif #endif } } // used to do 'goto repeat;' here, this delayed bh processing too long // used to do 'goto repeat;' here, this delayed bh processing too long return IRQ_HANDLED; return; } } } if (mer && ccleirq > 0 && !aliased_irq) { printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer); ccleirq--; } } if (mer && ccleirq>0 && !aliased_irq) printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--; } } iirq: iirq: mir = master_inb(IIRQ_REG); mir = master_inb(IIRQ_REG); /* should test whether keyboard irq is really enabled, doing it in defhand */ /* should test whether keyboard irq is really enabled, doing it in defhand */ if (mir&Q40_IRQ_KEYB_MASK) { if (mir & Q40_IRQ_KEYB_MASK) irq_tab[Q40_IRQ_KEYBOARD].count++; m68k_handle_int(Q40_IRQ_KEYBOARD, fp); irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp); } return IRQ_HANDLED; } int show_q40_interrupts (struct seq_file *p, void *v) { int i; for (i = 0; i <= Q40_IRQ_MAX; i++) { return; if (irq_tab[i].count) seq_printf(p, "%sIRQ %02d: %8d %s%s\n", (i<=15) ? "ISA-" : " " , i, irq_tab[i].count, irq_tab[i].devname[0] ? irq_tab[i].devname : "?", irq_tab[i].handler == q40_defhand ? " (now unassigned)" : ""); } return 0; } static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp) { if (irq!=Q40_IRQ_KEYBOARD) printk ("Unknown q40 interrupt %d\n", irq); else master_outb(-1,KEYBOARD_UNLOCK_REG); return IRQ_NONE; } } void q40_enable_irq(unsigned int irq) void q40_enable_irq(unsigned int irq) { { if ( irq>=5 && irq<=15 ) if (irq >= 5 && irq <= 15) { { mext_disabled--; mext_disabled--; if (mext_disabled > 0) if (mext_disabled > 0) printk("q40_enable_irq : nested disable/enable\n"); printk("q40_enable_irq : nested disable/enable\n"); Loading @@ -439,7 +315,8 @@ void q40_disable_irq (unsigned int irq) if (irq >= 5 && irq <= 15) { if (irq >= 5 && irq <= 15) { master_outb(0, EXT_ENABLE_REG); master_outb(0, EXT_ENABLE_REG); mext_disabled++; mext_disabled++; if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled); if (mext_disabled > 1) printk("disable_irq nesting count %d\n",mext_disabled); } } } } Loading @@ -452,8 +329,3 @@ int q40_probe_irq_off (unsigned long irqs) { { return -1; return -1; } } /* * Local variables: * compile-command: "m68k-linux-gcc -D__KERNEL__ -I/home/rz/lx/linux-2.2.6/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -ffixed-a2 -m68040 -c -o q40ints.o q40ints.c" * End: */