^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * arch/m68k/q40/q40ints.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (C) 1999,2001 Richard Zidlicky
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * License. See the file COPYING in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * .. used to be loosely based on bvme6000ints.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/ptrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/q40_master.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <asm/q40ints.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * Q40 IRQs are defined as follows:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * 3,4,5,6,7,10,11,14,15 : ISA dev IRQs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * 16-31: reserved
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * 32 : keyboard int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * 33 : frame int (50/200 Hz periodic timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * 34 : sample int (10/20 KHz periodic timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void q40_irq_handler(unsigned int, struct pt_regs *fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static void q40_irq_enable(struct irq_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void q40_irq_disable(struct irq_data *data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) unsigned short q40_ablecount[35];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) unsigned short q40_state[35];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static unsigned int q40_irq_startup(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) /* test for ISA ints not implemented by HW */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) switch (irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case 1: case 2: case 8: case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case 11: case 12: case 13:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) pr_warn("%s: ISA IRQ %d not implemented by HW\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) /* FIXME return -ENXIO; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) static void q40_irq_shutdown(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) static struct irq_chip q40_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) .name = "q40",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) .irq_startup = q40_irq_startup,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) .irq_shutdown = q40_irq_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) .irq_enable = q40_irq_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) .irq_disable = q40_irq_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * void q40_init_IRQ (void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * Parameters: None
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * Returns: Nothing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * This function is called during kernel startup to initialize
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * the q40 IRQ handling routines.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static int disabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) void __init q40_init_IRQ(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) m68k_setup_irq_controller(&q40_irq_chip, handle_simple_irq, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) Q40_IRQ_MAX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) /* setup handler for ISA ints */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) m68k_setup_auto_interrupt(q40_irq_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) m68k_irq_startup_irq(IRQ_AUTO_2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) m68k_irq_startup_irq(IRQ_AUTO_4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* now enable some ints.. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* make sure keyboard IRQ is disabled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) master_outb(0, KEY_IRQ_ENABLE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * this stuff doesn't really belong here..
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) int ql_ticks; /* 200Hz ticks since last jiffie */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) static int sound_ticks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) #define SVOL 45
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) void q40_mksound(unsigned int hz, unsigned int ticks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) /* for now ignore hz, except that hz==0 switches off sound */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (hz == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (sound_ticks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) sound_ticks = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) *DAC_LEFT = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) *DAC_RIGHT = 128;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) /* sound itself is done in q40_timer_int */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (sound_ticks == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) sound_ticks = 1000; /* pretty long beep */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) sound_ticks = ticks << 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) static irqreturn_t q40_timer_int(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) irq_handler_t timer_routine = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) ql_ticks = ql_ticks ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) if (sound_ticks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) sound_ticks--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) *DAC_LEFT=sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *DAC_RIGHT=sval;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (!ql_ticks) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) local_irq_save(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) timer_routine(0, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) local_irq_restore(flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) void q40_sched_init (irq_handler_t timer_routine)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int timer_irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) timer_irq = Q40_IRQ_FRAME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (request_irq(timer_irq, q40_timer_int, 0, "timer", timer_routine))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) panic("Couldn't register timer int");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) master_outb(-1, FRAME_CLEAR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) master_outb( 1, FRAME_RATE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * tables to translate bits into IRQ numbers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * it is a good idea to order the entries by priority
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct IRQ_TABLE{ unsigned mask; int irq ;};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) static struct IRQ_TABLE iirqs[]={
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) {Q40_IRQ_FRAME_MASK,Q40_IRQ_FRAME},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) {Q40_IRQ_KEYB_MASK,Q40_IRQ_KEYBOARD},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {0,0}};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) static struct IRQ_TABLE eirqs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) { .mask = Q40_IRQ3_MASK, .irq = 3 }, /* ser 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) { .mask = Q40_IRQ4_MASK, .irq = 4 }, /* ser 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) { .mask = Q40_IRQ14_MASK, .irq = 14 }, /* IDE 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) { .mask = Q40_IRQ15_MASK, .irq = 15 }, /* IDE 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) { .mask = Q40_IRQ6_MASK, .irq = 6 }, /* floppy, handled elsewhere */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) { .mask = Q40_IRQ7_MASK, .irq = 7 }, /* par */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) { .mask = Q40_IRQ5_MASK, .irq = 5 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) { .mask = Q40_IRQ10_MASK, .irq = 10 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) {0,0}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) /* complain only this many times about spurious ints : */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) static int ccleirq=60; /* ISA dev IRQs*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) /*static int cclirq=60;*/ /* internal */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /* FIXME: add shared ints,mask,unmask,probing.... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) #define IRQ_INPROGRESS 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) /*static unsigned short saved_mask;*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) //static int do_tint=0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) #define DEBUG_Q40INT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) /*#define IP_USE_DISABLE *//* would be nice, but crashes ???? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) static int mext_disabled=0; /* ext irq disabled by master chip? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) static int aliased_irq=0; /* how many times inside handler ?*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* got interrupt, dispatch to ISA or keyboard/timer IRQs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) static void q40_irq_handler(unsigned int irq, struct pt_regs *fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) unsigned mir, mer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) //repeat:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) mir = master_inb(IIRQ_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #ifdef CONFIG_BLK_DEV_FD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if ((mir & Q40_IRQ_EXT_MASK) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) floppy_hardint();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) switch (irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) do_IRQ(Q40_IRQ_SAMPLE, fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) if (mir & Q40_IRQ_FRAME_MASK) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) do_IRQ(Q40_IRQ_FRAME, fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) master_outb(-1, FRAME_CLEAR_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) mer = master_inb(EIRQ_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) for (i = 0; eirqs[i].mask; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (mer & eirqs[i].mask) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) irq = eirqs[i].irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) * There is a little mess wrt which IRQ really caused this irq request. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * are read - which is long after the request came in. In theory IRQs should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) * not just go away but they occasionally do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (irq > 4 && irq <= 15 && mext_disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) /*aliased_irq++;*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) goto iirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if (q40_state[irq] & IRQ_INPROGRESS) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) /* some handlers do local_irq_enable() for irq latency reasons, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /* however reentering an active irq handler is not permitted */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) #ifdef IP_USE_DISABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* in theory this is the better way to do it because it still */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) /* lets through eg the serial irqs, unfortunately it crashes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) disable_irq(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) /*pr_warn("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) irq, disabled ? "already" : "not yet"); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) fp->sr = (((fp->sr) & (~0x700))+0x200);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) disabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) goto iirq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) q40_state[irq] |= IRQ_INPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) do_IRQ(irq, fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) q40_state[irq] &= ~IRQ_INPROGRESS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) /* naively enable everything, if that fails than */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) /* this function will be reentered immediately thus */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) /* getting another chance to disable the IRQ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) if (disabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) #ifdef IP_USE_DISABLE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (irq > 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) disabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) enable_irq(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) disabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) /*pr_info("reenabling irq %d\n", irq); */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) // used to do 'goto repeat;' here, this delayed bh processing too long
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) if (mer && ccleirq > 0 && !aliased_irq) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) pr_warn("ISA interrupt from unknown source? EIRQ_REG = %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) mer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ccleirq--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) iirq:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) mir = master_inb(IIRQ_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) /* should test whether keyboard irq is really enabled, doing it in defhand */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) if (mir & Q40_IRQ_KEYB_MASK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) do_IRQ(Q40_IRQ_KEYBOARD, fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) void q40_irq_enable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if (irq >= 5 && irq <= 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) mext_disabled--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (mext_disabled > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) pr_warn("q40_irq_enable : nested disable/enable\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (mext_disabled == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) master_outb(1, EXT_ENABLE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) void q40_irq_disable(struct irq_data *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) unsigned int irq = data->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* disable ISA iqs : only do something if the driver has been
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) * verified to be Q40 "compatible" - right now IDE, NE2K
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * Any driver should not attempt to sleep across disable_irq !!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (irq >= 5 && irq <= 15) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) master_outb(0, EXT_ENABLE_REG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) mext_disabled++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (mext_disabled > 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) pr_info("disable_irq nesting count %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) mext_disabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) }