diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2006-06-25 08:47:05 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-25 13:00:58 -0400 |
commit | 77dda339e512c729bb27abd452e6632465490986 (patch) | |
tree | 6c3bdba69fbf9b27ebf2dfe4e52a78d14d649390 /arch/m68k | |
parent | 9c5f4afdfbe72d5d1c814ad7286a4524d00c7b96 (diff) |
[PATCH] m68k: convert q40 irq code
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/m68k')
-rw-r--r-- | arch/m68k/kernel/entry.S | 11 | ||||
-rw-r--r-- | arch/m68k/q40/config.c | 11 | ||||
-rw-r--r-- | arch/m68k/q40/q40ints.c | 464 |
3 files changed, 169 insertions, 317 deletions
diff --git a/arch/m68k/kernel/entry.S b/arch/m68k/kernel/entry.S index 48cccc556e13..449b62b30f45 100644 --- a/arch/m68k/kernel/entry.S +++ b/arch/m68k/kernel/entry.S | |||
@@ -205,18 +205,9 @@ ENTRY(auto_inthandler) | |||
205 | 205 | ||
206 | movel %sp,%sp@- | 206 | movel %sp,%sp@- |
207 | movel %d0,%sp@- | put vector # on stack | 207 | movel %d0,%sp@- | put vector # on stack |
208 | #if defined(MACH_Q40_ONLY) && defined(CONFIG_BLK_DEV_FD) | ||
209 | btstb #4,0xff000000 | Q40 floppy needs very special treatment ... | ||
210 | jbeq 1f | ||
211 | btstb #3,0xff000004 | ||
212 | jbeq 1f | ||
213 | jbsr floppy_hardint | ||
214 | jbra 3f | ||
215 | 1: | ||
216 | #endif | ||
217 | auto_irqhandler_fixup = . + 2 | 208 | auto_irqhandler_fixup = . + 2 |
218 | jsr m68k_handle_int | process the IRQ | 209 | jsr m68k_handle_int | process the IRQ |
219 | 3: addql #8,%sp | pop parameters off stack | 210 | addql #8,%sp | pop parameters off stack |
220 | 211 | ||
221 | ret_from_interrupt: | 212 | ret_from_interrupt: |
222 | subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) | 213 | subqb #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1) |
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c index 01fd662bfada..efa52d302d67 100644 --- a/arch/m68k/q40/config.c +++ b/arch/m68k/q40/config.c | |||
@@ -38,13 +38,8 @@ | |||
38 | 38 | ||
39 | extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); | 39 | extern irqreturn_t q40_process_int (int level, struct pt_regs *regs); |
40 | extern void q40_init_IRQ (void); | 40 | extern void q40_init_IRQ (void); |
41 | extern void q40_free_irq (unsigned int, void *); | ||
42 | extern int show_q40_interrupts (struct seq_file *, void *); | ||
43 | extern void q40_enable_irq (unsigned int); | ||
44 | extern void q40_disable_irq (unsigned int); | ||
45 | static void q40_get_model(char *model); | 41 | static void q40_get_model(char *model); |
46 | static int q40_get_hardware_list(char *buffer); | 42 | static int q40_get_hardware_list(char *buffer); |
47 | 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); | ||
48 | extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); | 43 | extern void q40_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); |
49 | 44 | ||
50 | extern unsigned long q40_gettimeoffset (void); | 45 | extern unsigned long q40_gettimeoffset (void); |
@@ -174,12 +169,6 @@ void __init config_q40(void) | |||
174 | mach_set_clock_mmss = q40_set_clock_mmss; | 169 | mach_set_clock_mmss = q40_set_clock_mmss; |
175 | 170 | ||
176 | mach_reset = q40_reset; | 171 | mach_reset = q40_reset; |
177 | mach_free_irq = q40_free_irq; | ||
178 | mach_process_int = q40_process_int; | ||
179 | mach_get_irq_list = show_q40_interrupts; | ||
180 | mach_request_irq = q40_request_irq; | ||
181 | enable_irq = q40_enable_irq; | ||
182 | disable_irq = q40_disable_irq; | ||
183 | mach_get_model = q40_get_model; | 172 | mach_get_model = q40_get_model; |
184 | mach_get_hardware_list = q40_get_hardware_list; | 173 | mach_get_hardware_list = q40_get_hardware_list; |
185 | 174 | ||
diff --git a/arch/m68k/q40/q40ints.c b/arch/m68k/q40/q40ints.c index ff80cba110d4..472f41c4158b 100644 --- a/arch/m68k/q40/q40ints.c +++ b/arch/m68k/q40/q40ints.c | |||
@@ -14,13 +14,8 @@ | |||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <linux/string.h> | ||
18 | #include <linux/sched.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
21 | #include <linux/hardirq.h> | ||
22 | 18 | ||
23 | #include <asm/rtc.h> | ||
24 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> |
25 | #include <asm/system.h> | 20 | #include <asm/system.h> |
26 | #include <asm/irq.h> | 21 | #include <asm/irq.h> |
@@ -39,28 +34,37 @@ | |||
39 | * | 34 | * |
40 | */ | 35 | */ |
41 | 36 | ||
42 | extern int ints_inited; | 37 | static void q40_irq_handler(unsigned int, struct pt_regs *fp); |
38 | static void q40_enable_irq(unsigned int); | ||
39 | static void q40_disable_irq(unsigned int); | ||
43 | 40 | ||
41 | unsigned short q40_ablecount[35]; | ||
42 | unsigned short q40_state[35]; | ||
44 | 43 | ||
45 | irqreturn_t q40_irq2_handler (int, void *, struct pt_regs *fp); | 44 | static int q40_irq_startup(unsigned int irq) |
46 | 45 | { | |
47 | 46 | /* test for ISA ints not implemented by HW */ | |
48 | static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp); | 47 | switch (irq) { |
49 | 48 | case 1: case 2: case 8: case 9: | |
50 | 49 | case 11: case 12: case 13: | |
51 | #define DEVNAME_SIZE 24 | 50 | printk("%s: ISA IRQ %d not implemented by HW\n", __FUNCTION__, irq); |
51 | return -ENXIO; | ||
52 | } | ||
53 | return 0; | ||
54 | } | ||
52 | 55 | ||
53 | static struct q40_irq_node { | 56 | static void q40_irq_shutdown(unsigned int irq) |
54 | irqreturn_t (*handler)(int, void *, struct pt_regs *); | 57 | { |
55 | unsigned long flags; | 58 | } |
56 | void *dev_id; | ||
57 | /* struct q40_irq_node *next;*/ | ||
58 | char devname[DEVNAME_SIZE]; | ||
59 | unsigned count; | ||
60 | unsigned short state; | ||
61 | } irq_tab[Q40_IRQ_MAX+1]; | ||
62 | 59 | ||
63 | short unsigned q40_ablecount[Q40_IRQ_MAX+1]; | 60 | static struct irq_controller q40_irq_controller = { |
61 | .name = "q40", | ||
62 | .lock = SPIN_LOCK_UNLOCKED, | ||
63 | .startup = q40_irq_startup, | ||
64 | .shutdown = q40_irq_shutdown, | ||
65 | .enable = q40_enable_irq, | ||
66 | .disable = q40_disable_irq, | ||
67 | }; | ||
64 | 68 | ||
65 | /* | 69 | /* |
66 | * void q40_init_IRQ (void) | 70 | * void q40_init_IRQ (void) |
@@ -73,139 +77,29 @@ short unsigned q40_ablecount[Q40_IRQ_MAX+1]; | |||
73 | * the q40 IRQ handling routines. | 77 | * the q40 IRQ handling routines. |
74 | */ | 78 | */ |
75 | 79 | ||
76 | static int disabled=0; | 80 | static int disabled; |
77 | 81 | ||
78 | void q40_init_IRQ (void) | 82 | void q40_init_IRQ(void) |
79 | { | 83 | { |
80 | int i; | 84 | m68k_setup_irq_controller(&q40_irq_controller, 1, Q40_IRQ_MAX); |
81 | |||
82 | disabled=0; | ||
83 | for (i = 0; i <= Q40_IRQ_MAX; i++) { | ||
84 | irq_tab[i].handler = q40_defhand; | ||
85 | irq_tab[i].flags = 0; | ||
86 | irq_tab[i].dev_id = NULL; | ||
87 | /* irq_tab[i].next = NULL;*/ | ||
88 | irq_tab[i].devname[0] = 0; | ||
89 | irq_tab[i].count = 0; | ||
90 | irq_tab[i].state =0; | ||
91 | q40_ablecount[i]=0; /* all enabled */ | ||
92 | } | ||
93 | 85 | ||
94 | /* setup handler for ISA ints */ | 86 | /* setup handler for ISA ints */ |
95 | cpu_request_irq(IRQ_AUTO_2, q40_irq2_handler, 0, | 87 | m68k_setup_auto_interrupt(q40_irq_handler); |
96 | "q40 ISA and master chip", NULL); | 88 | |
89 | m68k_irq_startup(IRQ_AUTO_2); | ||
90 | m68k_irq_startup(IRQ_AUTO_4); | ||
97 | 91 | ||
98 | /* now enable some ints.. */ | 92 | /* now enable some ints.. */ |
99 | master_outb(1,EXT_ENABLE_REG); /* ISA IRQ 5-15 */ | 93 | master_outb(1, EXT_ENABLE_REG); /* ISA IRQ 5-15 */ |
100 | 94 | ||
101 | /* make sure keyboard IRQ is disabled */ | 95 | /* make sure keyboard IRQ is disabled */ |
102 | master_outb(0,KEY_IRQ_ENABLE_REG); | 96 | master_outb(0, KEY_IRQ_ENABLE_REG); |
103 | } | 97 | } |
104 | 98 | ||
105 | int q40_request_irq(unsigned int irq, | ||
106 | irqreturn_t (*handler)(int, void *, struct pt_regs *), | ||
107 | unsigned long flags, const char *devname, void *dev_id) | ||
108 | { | ||
109 | /*printk("q40_request_irq %d, %s\n",irq,devname);*/ | ||
110 | |||
111 | if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { | ||
112 | printk("%s: Incorrect IRQ %d from %s\n", __FUNCTION__, irq, devname); | ||
113 | return -ENXIO; | ||
114 | } | ||
115 | |||
116 | /* test for ISA ints not implemented by HW */ | ||
117 | switch (irq) | ||
118 | { | ||
119 | case 1: case 2: case 8: case 9: | ||
120 | case 12: case 13: | ||
121 | printk("%s: ISA IRQ %d from %s not implemented by HW\n", __FUNCTION__, irq, devname); | ||
122 | return -ENXIO; | ||
123 | case 11: | ||
124 | printk("warning IRQ 10 and 11 not distinguishable\n"); | ||
125 | irq=10; | ||
126 | default: | ||
127 | ; | ||
128 | } | ||
129 | |||
130 | if (irq<Q40_IRQ_SAMPLE) | ||
131 | { | ||
132 | if (irq_tab[irq].dev_id != NULL) | ||
133 | { | ||
134 | printk("%s: IRQ %d from %s is not replaceable\n", | ||
135 | __FUNCTION__, irq, irq_tab[irq].devname); | ||
136 | return -EBUSY; | ||
137 | } | ||
138 | /*printk("IRQ %d set to handler %p\n",irq,handler);*/ | ||
139 | if (dev_id==NULL) | ||
140 | { | ||
141 | printk("WARNING: dev_id == NULL in request_irq\n"); | ||
142 | dev_id=(void*)1; | ||
143 | } | ||
144 | irq_tab[irq].handler = handler; | ||
145 | irq_tab[irq].flags = flags; | ||
146 | irq_tab[irq].dev_id = dev_id; | ||
147 | strlcpy(irq_tab[irq].devname,devname,sizeof(irq_tab[irq].devname)); | ||
148 | irq_tab[irq].state = 0; | ||
149 | return 0; | ||
150 | } | ||
151 | else { | ||
152 | /* Q40_IRQ_SAMPLE :somewhat special actions required here ..*/ | ||
153 | cpu_request_irq(4, handler, flags, devname, dev_id); | ||
154 | cpu_request_irq(6, handler, flags, devname, dev_id); | ||
155 | return 0; | ||
156 | } | ||
157 | } | ||
158 | |||
159 | void q40_free_irq(unsigned int irq, void *dev_id) | ||
160 | { | ||
161 | if (irq > Q40_IRQ_MAX || (irq>15 && irq<32)) { | ||
162 | printk("%s: Incorrect IRQ %d, dev_id %x \n", __FUNCTION__, irq, (unsigned)dev_id); | ||
163 | return; | ||
164 | } | ||
165 | |||
166 | /* test for ISA ints not implemented by HW */ | ||
167 | switch (irq) | ||
168 | { | ||
169 | case 1: case 2: case 8: case 9: | ||
170 | case 12: case 13: | ||
171 | printk("%s: ISA IRQ %d from %x invalid\n", __FUNCTION__, irq, (unsigned)dev_id); | ||
172 | return; | ||
173 | case 11: irq=10; | ||
174 | default: | ||
175 | ; | ||
176 | } | ||
177 | |||
178 | if (irq<Q40_IRQ_SAMPLE) | ||
179 | { | ||
180 | if (irq_tab[irq].dev_id != dev_id) | ||
181 | printk("%s: Removing probably wrong IRQ %d from %s\n", | ||
182 | __FUNCTION__, irq, irq_tab[irq].devname); | ||
183 | |||
184 | irq_tab[irq].handler = q40_defhand; | ||
185 | irq_tab[irq].flags = 0; | ||
186 | irq_tab[irq].dev_id = NULL; | ||
187 | /* irq_tab[irq].devname = NULL; */ | ||
188 | /* do not reset state !! */ | ||
189 | } | ||
190 | else | ||
191 | { /* == Q40_IRQ_SAMPLE */ | ||
192 | cpu_free_irq(4, dev_id); | ||
193 | cpu_free_irq(6, dev_id); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | |||
198 | irqreturn_t q40_process_int (int level, struct pt_regs *fp) | ||
199 | { | ||
200 | printk("unexpected interrupt vec=%x, pc=%lx, d0=%lx, d0_orig=%lx, d1=%lx, d2=%lx\n", | ||
201 | level, fp->pc, fp->d0, fp->orig_d0, fp->d1, fp->d2); | ||
202 | printk("\tIIRQ_REG = %x, EIRQ_REG = %x\n",master_inb(IIRQ_REG),master_inb(EIRQ_REG)); | ||
203 | return IRQ_HANDLED; | ||
204 | } | ||
205 | 99 | ||
206 | /* | 100 | /* |
207 | * this stuff doesn't really belong here.. | 101 | * this stuff doesn't really belong here.. |
208 | */ | 102 | */ |
209 | 103 | ||
210 | int ql_ticks; /* 200Hz ticks since last jiffie */ | 104 | int ql_ticks; /* 200Hz ticks since last jiffie */ |
211 | static int sound_ticks; | 105 | static int sound_ticks; |
@@ -214,54 +108,53 @@ static int sound_ticks; | |||
214 | 108 | ||
215 | void q40_mksound(unsigned int hz, unsigned int ticks) | 109 | void q40_mksound(unsigned int hz, unsigned int ticks) |
216 | { | 110 | { |
217 | /* for now ignore hz, except that hz==0 switches off sound */ | 111 | /* for now ignore hz, except that hz==0 switches off sound */ |
218 | /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ | 112 | /* simply alternate the ampl (128-SVOL)-(128+SVOL)-..-.. at 200Hz */ |
219 | if (hz==0) | 113 | if (hz == 0) { |
220 | { | 114 | if (sound_ticks) |
221 | if (sound_ticks) | 115 | sound_ticks = 1; |
222 | sound_ticks=1; | 116 | |
223 | 117 | *DAC_LEFT = 128; | |
224 | *DAC_LEFT=128; | 118 | *DAC_RIGHT = 128; |
225 | *DAC_RIGHT=128; | 119 | |
226 | 120 | return; | |
227 | return; | 121 | } |
228 | } | 122 | /* sound itself is done in q40_timer_int */ |
229 | /* sound itself is done in q40_timer_int */ | 123 | if (sound_ticks == 0) |
230 | if (sound_ticks == 0) sound_ticks=1000; /* pretty long beep */ | 124 | sound_ticks = 1000; /* pretty long beep */ |
231 | sound_ticks=ticks<<1; | 125 | sound_ticks = ticks << 1; |
232 | } | 126 | } |
233 | 127 | ||
234 | static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *); | 128 | static irqreturn_t (*q40_timer_routine)(int, void *, struct pt_regs *); |
235 | 129 | ||
236 | static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs) | 130 | static irqreturn_t q40_timer_int (int irq, void * dev, struct pt_regs * regs) |
237 | { | 131 | { |
238 | ql_ticks = ql_ticks ? 0 : 1; | 132 | ql_ticks = ql_ticks ? 0 : 1; |
239 | if (sound_ticks) | 133 | if (sound_ticks) { |
240 | { | 134 | unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; |
241 | unsigned char sval=(sound_ticks & 1) ? 128-SVOL : 128+SVOL; | 135 | sound_ticks--; |
242 | sound_ticks--; | 136 | *DAC_LEFT=sval; |
243 | *DAC_LEFT=sval; | 137 | *DAC_RIGHT=sval; |
244 | *DAC_RIGHT=sval; | 138 | } |
245 | } | 139 | |
246 | 140 | if (!ql_ticks) | |
247 | if (!ql_ticks) | 141 | q40_timer_routine(irq, dev, regs); |
248 | q40_timer_routine(irq, dev, regs); | 142 | return IRQ_HANDLED; |
249 | return IRQ_HANDLED; | ||
250 | } | 143 | } |
251 | 144 | ||
252 | void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) | 145 | void q40_sched_init (irqreturn_t (*timer_routine)(int, void *, struct pt_regs *)) |
253 | { | 146 | { |
254 | int timer_irq; | 147 | int timer_irq; |
255 | 148 | ||
256 | q40_timer_routine = timer_routine; | 149 | q40_timer_routine = timer_routine; |
257 | timer_irq=Q40_IRQ_FRAME; | 150 | timer_irq = Q40_IRQ_FRAME; |
258 | 151 | ||
259 | if (request_irq(timer_irq, q40_timer_int, 0, | 152 | if (request_irq(timer_irq, q40_timer_int, 0, |
260 | "timer", q40_timer_int)) | 153 | "timer", q40_timer_int)) |
261 | panic ("Couldn't register timer int"); | 154 | panic("Couldn't register timer int"); |
262 | 155 | ||
263 | master_outb(-1,FRAME_CLEAR_REG); | 156 | master_outb(-1, FRAME_CLEAR_REG); |
264 | master_outb( 1,FRAME_RATE_REG); | 157 | master_outb( 1, FRAME_RATE_REG); |
265 | } | 158 | } |
266 | 159 | ||
267 | 160 | ||
@@ -307,153 +200,132 @@ static int mext_disabled=0; /* ext irq disabled by master chip? */ | |||
307 | static int aliased_irq=0; /* how many times inside handler ?*/ | 200 | static int aliased_irq=0; /* how many times inside handler ?*/ |
308 | 201 | ||
309 | 202 | ||
310 | /* got level 2 interrupt, dispatch to ISA or keyboard/timer IRQs */ | 203 | /* got interrupt, dispatch to ISA or keyboard/timer IRQs */ |
311 | irqreturn_t q40_irq2_handler (int vec, void *devname, struct pt_regs *fp) | 204 | static void q40_irq_handler(unsigned int irq, struct pt_regs *fp) |
312 | { | 205 | { |
313 | unsigned mir, mer; | 206 | unsigned mir, mer; |
314 | int irq,i; | 207 | int i; |
315 | 208 | ||
316 | //repeat: | 209 | //repeat: |
317 | mir=master_inb(IIRQ_REG); | 210 | mir = master_inb(IIRQ_REG); |
318 | if (mir&Q40_IRQ_FRAME_MASK) { | 211 | #ifdef CONFIG_BLK_DEV_FD |
319 | irq_tab[Q40_IRQ_FRAME].count++; | 212 | if ((mir & Q40_IRQ_EXT_MASK) && |
320 | irq_tab[Q40_IRQ_FRAME].handler(Q40_IRQ_FRAME,irq_tab[Q40_IRQ_FRAME].dev_id,fp); | 213 | (master_inb(EIRQ_REG) & Q40_IRQ6_MASK)) { |
321 | master_outb(-1,FRAME_CLEAR_REG); | 214 | floppy_hardint(); |
322 | } | 215 | return; |
323 | if ((mir&Q40_IRQ_SER_MASK) || (mir&Q40_IRQ_EXT_MASK)) { | 216 | } |
324 | mer=master_inb(EIRQ_REG); | 217 | #endif |
325 | for (i=0; eirqs[i].mask; i++) { | 218 | switch (irq) { |
326 | if (mer&(eirqs[i].mask)) { | 219 | case 4: |
327 | irq=eirqs[i].irq; | 220 | case 6: |
221 | m68k_handle_int(Q40_IRQ_SAMPLE, fp); | ||
222 | return; | ||
223 | } | ||
224 | if (mir & Q40_IRQ_FRAME_MASK) { | ||
225 | m68k_handle_int(Q40_IRQ_FRAME, fp); | ||
226 | master_outb(-1, FRAME_CLEAR_REG); | ||
227 | } | ||
228 | if ((mir & Q40_IRQ_SER_MASK) || (mir & Q40_IRQ_EXT_MASK)) { | ||
229 | mer = master_inb(EIRQ_REG); | ||
230 | for (i = 0; eirqs[i].mask; i++) { | ||
231 | if (mer & eirqs[i].mask) { | ||
232 | irq = eirqs[i].irq; | ||
328 | /* | 233 | /* |
329 | * There is a little mess wrt which IRQ really caused this irq request. The | 234 | * There is a little mess wrt which IRQ really caused this irq request. The |
330 | * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they | 235 | * main problem is that IIRQ_REG and EIRQ_REG reflect the state when they |
331 | * are read - which is long after the request came in. In theory IRQs should | 236 | * are read - which is long after the request came in. In theory IRQs should |
332 | * not just go away but they occassionally do | 237 | * not just go away but they occassionally do |
333 | */ | 238 | */ |
334 | if (irq>4 && irq<=15 && mext_disabled) { | 239 | if (irq > 4 && irq <= 15 && mext_disabled) { |
335 | /*aliased_irq++;*/ | 240 | /*aliased_irq++;*/ |
336 | goto iirq; | 241 | goto iirq; |
337 | } | 242 | } |
338 | if (irq_tab[irq].handler == q40_defhand ) { | 243 | if (q40_state[irq] & IRQ_INPROGRESS) { |
339 | printk("handler for IRQ %d not defined\n",irq); | 244 | /* some handlers do local_irq_enable() for irq latency reasons, */ |
340 | continue; /* ignore uninited INTs :-( */ | 245 | /* however reentering an active irq handler is not permitted */ |
341 | } | ||
342 | if ( irq_tab[irq].state & IRQ_INPROGRESS ) { | ||
343 | /* some handlers do local_irq_enable() for irq latency reasons, */ | ||
344 | /* however reentering an active irq handler is not permitted */ | ||
345 | #ifdef IP_USE_DISABLE | 246 | #ifdef IP_USE_DISABLE |
346 | /* in theory this is the better way to do it because it still */ | 247 | /* in theory this is the better way to do it because it still */ |
347 | /* lets through eg the serial irqs, unfortunately it crashes */ | 248 | /* lets through eg the serial irqs, unfortunately it crashes */ |
348 | disable_irq(irq); | 249 | disable_irq(irq); |
349 | disabled=1; | 250 | disabled = 1; |
350 | #else | 251 | #else |
351 | /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n",irq,disabled ? "already" : "not yet"); */ | 252 | /*printk("IRQ_INPROGRESS detected for irq %d, disabling - %s disabled\n", |
352 | fp->sr = (((fp->sr) & (~0x700))+0x200); | 253 | irq, disabled ? "already" : "not yet"); */ |
353 | disabled=1; | 254 | fp->sr = (((fp->sr) & (~0x700))+0x200); |
255 | disabled = 1; | ||
354 | #endif | 256 | #endif |
355 | goto iirq; | 257 | goto iirq; |
356 | } | 258 | } |
357 | irq_tab[irq].count++; | 259 | q40_state[irq] |= IRQ_INPROGRESS; |
358 | irq_tab[irq].state |= IRQ_INPROGRESS; | 260 | m68k_handle_int(irq, fp); |
359 | irq_tab[irq].handler(irq,irq_tab[irq].dev_id,fp); | 261 | q40_state[irq] &= ~IRQ_INPROGRESS; |
360 | irq_tab[irq].state &= ~IRQ_INPROGRESS; | 262 | |
361 | 263 | /* naively enable everything, if that fails than */ | |
362 | /* naively enable everything, if that fails than */ | 264 | /* this function will be reentered immediately thus */ |
363 | /* this function will be reentered immediately thus */ | 265 | /* getting another chance to disable the IRQ */ |
364 | /* getting another chance to disable the IRQ */ | 266 | |
365 | 267 | if (disabled) { | |
366 | if ( disabled ) { | ||
367 | #ifdef IP_USE_DISABLE | 268 | #ifdef IP_USE_DISABLE |
368 | if (irq>4){ | 269 | if (irq > 4) { |
369 | disabled=0; | 270 | disabled = 0; |
370 | enable_irq(irq);} | 271 | enable_irq(irq); |
272 | } | ||
371 | #else | 273 | #else |
372 | disabled=0; | 274 | disabled = 0; |
373 | /*printk("reenabling irq %d\n",irq); */ | 275 | /*printk("reenabling irq %d\n", irq); */ |
374 | #endif | 276 | #endif |
375 | } | 277 | } |
376 | // used to do 'goto repeat;' here, this delayed bh processing too long | 278 | // used to do 'goto repeat;' here, this delayed bh processing too long |
377 | return IRQ_HANDLED; | 279 | return; |
378 | } | 280 | } |
379 | } | 281 | } |
380 | if (mer && ccleirq>0 && !aliased_irq) | 282 | if (mer && ccleirq > 0 && !aliased_irq) { |
381 | printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer),ccleirq--; | 283 | printk("ISA interrupt from unknown source? EIRQ_REG = %x\n",mer); |
382 | } | 284 | ccleirq--; |
383 | iirq: | 285 | } |
384 | mir=master_inb(IIRQ_REG); | ||
385 | /* should test whether keyboard irq is really enabled, doing it in defhand */ | ||
386 | if (mir&Q40_IRQ_KEYB_MASK) { | ||
387 | irq_tab[Q40_IRQ_KEYBOARD].count++; | ||
388 | irq_tab[Q40_IRQ_KEYBOARD].handler(Q40_IRQ_KEYBOARD,irq_tab[Q40_IRQ_KEYBOARD].dev_id,fp); | ||
389 | } | ||
390 | return IRQ_HANDLED; | ||
391 | } | ||
392 | |||
393 | int show_q40_interrupts (struct seq_file *p, void *v) | ||
394 | { | ||
395 | int i; | ||
396 | |||
397 | for (i = 0; i <= Q40_IRQ_MAX; i++) { | ||
398 | if (irq_tab[i].count) | ||
399 | seq_printf(p, "%sIRQ %02d: %8d %s%s\n", | ||
400 | (i<=15) ? "ISA-" : " " , | ||
401 | i, irq_tab[i].count, | ||
402 | irq_tab[i].devname[0] ? irq_tab[i].devname : "?", | ||
403 | irq_tab[i].handler == q40_defhand ? | ||
404 | " (now unassigned)" : ""); | ||
405 | } | 286 | } |
406 | return 0; | 287 | iirq: |
407 | } | 288 | mir = master_inb(IIRQ_REG); |
408 | 289 | /* should test whether keyboard irq is really enabled, doing it in defhand */ | |
290 | if (mir & Q40_IRQ_KEYB_MASK) | ||
291 | m68k_handle_int(Q40_IRQ_KEYBOARD, fp); | ||
409 | 292 | ||
410 | static irqreturn_t q40_defhand (int irq, void *dev_id, struct pt_regs *fp) | 293 | return; |
411 | { | ||
412 | if (irq!=Q40_IRQ_KEYBOARD) | ||
413 | printk ("Unknown q40 interrupt %d\n", irq); | ||
414 | else master_outb(-1,KEYBOARD_UNLOCK_REG); | ||
415 | return IRQ_NONE; | ||
416 | } | 294 | } |
417 | 295 | ||
418 | 296 | void q40_enable_irq(unsigned int irq) | |
419 | void q40_enable_irq (unsigned int irq) | ||
420 | { | 297 | { |
421 | if ( irq>=5 && irq<=15 ) | 298 | if (irq >= 5 && irq <= 15) { |
422 | { | 299 | mext_disabled--; |
423 | mext_disabled--; | 300 | if (mext_disabled > 0) |
424 | if (mext_disabled>0) | 301 | printk("q40_enable_irq : nested disable/enable\n"); |
425 | printk("q40_enable_irq : nested disable/enable\n"); | 302 | if (mext_disabled == 0) |
426 | if (mext_disabled==0) | 303 | master_outb(1, EXT_ENABLE_REG); |
427 | master_outb(1,EXT_ENABLE_REG); | 304 | } |
428 | } | ||
429 | } | 305 | } |
430 | 306 | ||
431 | 307 | ||
432 | void q40_disable_irq (unsigned int irq) | 308 | void q40_disable_irq(unsigned int irq) |
433 | { | 309 | { |
434 | /* disable ISA iqs : only do something if the driver has been | 310 | /* disable ISA iqs : only do something if the driver has been |
435 | * verified to be Q40 "compatible" - right now IDE, NE2K | 311 | * verified to be Q40 "compatible" - right now IDE, NE2K |
436 | * Any driver should not attempt to sleep across disable_irq !! | 312 | * Any driver should not attempt to sleep across disable_irq !! |
437 | */ | 313 | */ |
438 | 314 | ||
439 | if ( irq>=5 && irq<=15 ) { | 315 | if (irq >= 5 && irq <= 15) { |
440 | master_outb(0,EXT_ENABLE_REG); | 316 | master_outb(0, EXT_ENABLE_REG); |
441 | mext_disabled++; | 317 | mext_disabled++; |
442 | if (mext_disabled>1) printk("disable_irq nesting count %d\n",mext_disabled); | 318 | if (mext_disabled > 1) |
443 | } | 319 | printk("disable_irq nesting count %d\n",mext_disabled); |
320 | } | ||
444 | } | 321 | } |
445 | 322 | ||
446 | unsigned long q40_probe_irq_on (void) | 323 | unsigned long q40_probe_irq_on(void) |
447 | { | 324 | { |
448 | printk("irq probing not working - reconfigure the driver to avoid this\n"); | 325 | printk("irq probing not working - reconfigure the driver to avoid this\n"); |
449 | return -1; | 326 | return -1; |
450 | } | 327 | } |
451 | int q40_probe_irq_off (unsigned long irqs) | 328 | int q40_probe_irq_off(unsigned long irqs) |
452 | { | 329 | { |
453 | return -1; | 330 | return -1; |
454 | } | 331 | } |
455 | /* | ||
456 | * Local variables: | ||
457 | * 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" | ||
458 | * End: | ||
459 | */ | ||