Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] m68k: convert amiga 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>

authored by

Roman Zippel and committed by
Linus Torvalds
74be8d08 68387c44

+119 -447
-2
arch/m68k/amiga/amiga_ksyms.c
··· 23 23 EXPORT_SYMBOL(amiga_chip_size); 24 24 EXPORT_SYMBOL(amiga_audio_period); 25 25 EXPORT_SYMBOL(amiga_audio_min_period); 26 - EXPORT_SYMBOL(amiga_do_irq); 27 - EXPORT_SYMBOL(amiga_do_irq_list); 28 26 29 27 #ifdef CONFIG_AMIGA_PCMCIA 30 28 EXPORT_SYMBOL(pcmcia_reset);
+35 -345
arch/m68k/amiga/amiints.c
··· 35 35 * /Jes 36 36 */ 37 37 38 - #include <linux/types.h> 39 - #include <linux/kernel.h> 40 - #include <linux/sched.h> 41 - #include <linux/kernel_stat.h> 42 38 #include <linux/init.h> 43 39 #include <linux/interrupt.h> 44 40 #include <linux/errno.h> 45 - #include <linux/seq_file.h> 46 41 47 - #include <asm/system.h> 48 42 #include <asm/irq.h> 49 43 #include <asm/traps.h> 50 44 #include <asm/amigahw.h> 51 45 #include <asm/amigaints.h> 52 46 #include <asm/amipcmcia.h> 53 47 54 - extern int cia_request_irq(struct ciabase *base,int irq, 55 - irqreturn_t (*handler)(int, void *, struct pt_regs *), 56 - unsigned long flags, const char *devname, void *dev_id); 57 - extern void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id); 58 - extern void cia_init_IRQ(struct ciabase *base); 59 - extern int cia_get_irq_list(struct ciabase *base, struct seq_file *p); 48 + static void amiga_enable_irq(unsigned int irq); 49 + static void amiga_disable_irq(unsigned int irq); 50 + static irqreturn_t ami_int1(int irq, void *dev_id, struct pt_regs *fp); 51 + static irqreturn_t ami_int3(int irq, void *dev_id, struct pt_regs *fp); 52 + static irqreturn_t ami_int4(int irq, void *dev_id, struct pt_regs *fp); 53 + static irqreturn_t ami_int5(int irq, void *dev_id, struct pt_regs *fp); 60 54 61 - /* irq node variables for amiga interrupt sources */ 62 - static irq_node_t *ami_irq_list[AMI_STD_IRQS]; 63 - 64 - static unsigned short amiga_intena_vals[AMI_STD_IRQS] = { 65 - [IRQ_AMIGA_VERTB-IRQ_USER] = IF_VERTB, 66 - [IRQ_AMIGA_COPPER-IRQ_USER] = IF_COPER, 67 - [IRQ_AMIGA_AUD0-IRQ_USER] = IF_AUD0, 68 - [IRQ_AMIGA_AUD1-IRQ_USER] = IF_AUD1, 69 - [IRQ_AMIGA_AUD2-IRQ_USER] = IF_AUD2, 70 - [IRQ_AMIGA_AUD3-IRQ_USER] = IF_AUD3, 71 - [IRQ_AMIGA_BLIT-IRQ_USER] = IF_BLIT, 72 - [IRQ_AMIGA_DSKSYN-IRQ_USER] = IF_DSKSYN, 73 - [IRQ_AMIGA_DSKBLK-IRQ_USER] = IF_DSKBLK, 74 - [IRQ_AMIGA_RBF-IRQ_USER] = IF_RBF, 75 - [IRQ_AMIGA_TBE-IRQ_USER] = IF_TBE, 76 - [IRQ_AMIGA_SOFT-IRQ_USER] = IF_SOFT, 77 - [IRQ_AMIGA_PORTS-IRQ_USER] = IF_PORTS, 78 - [IRQ_AMIGA_EXTER-IRQ_USER] = IF_EXTER 55 + static struct irq_controller amiga_irq_controller = { 56 + .name = "amiga", 57 + .lock = SPIN_LOCK_UNLOCKED, 58 + .enable = amiga_enable_irq, 59 + .disable = amiga_disable_irq, 79 60 }; 80 - static const unsigned char ami_servers[AMI_STD_IRQS] = { 81 - [IRQ_AMIGA_VERTB-IRQ_USER] = 1, 82 - [IRQ_AMIGA_PORTS-IRQ_USER] = 1, 83 - [IRQ_AMIGA_EXTER-IRQ_USER] = 1 84 - }; 85 - 86 - static short ami_ablecount[AMI_IRQS]; 87 - 88 - static irqreturn_t ami_badint(int irq, void *dev_id, struct pt_regs *fp) 89 - { 90 - num_spurious += 1; 91 - return IRQ_NONE; 92 - } 93 61 94 62 /* 95 63 * void amiga_init_IRQ(void) ··· 72 104 73 105 void __init amiga_init_IRQ(void) 74 106 { 75 - int i; 107 + request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL); 108 + request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL); 109 + request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL); 110 + request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL); 76 111 77 - /* initialize handlers */ 78 - for (i = 0; i < AMI_STD_IRQS; i++) { 79 - if (ami_servers[i]) { 80 - ami_irq_list[i] = NULL; 81 - } else { 82 - ami_irq_list[i] = new_irq_node(); 83 - ami_irq_list[i]->handler = ami_badint; 84 - ami_irq_list[i]->flags = 0; 85 - ami_irq_list[i]->dev_id = NULL; 86 - ami_irq_list[i]->devname = NULL; 87 - ami_irq_list[i]->next = NULL; 88 - } 89 - } 90 - for (i = 0; i < AMI_IRQS; i++) 91 - ami_ablecount[i] = 0; 112 + m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS); 92 113 93 114 /* turn off PCMCIA interrupts */ 94 115 if (AMIGAHW_PRESENT(PCMCIA)) ··· 92 135 cia_init_IRQ(&ciab_base); 93 136 } 94 137 95 - static inline int amiga_insert_irq(irq_node_t **list, irq_node_t *node) 96 - { 97 - unsigned long flags; 98 - irq_node_t *cur; 99 - 100 - if (!node->dev_id) 101 - printk("%s: Warning: dev_id of %s is zero\n", 102 - __FUNCTION__, node->devname); 103 - 104 - local_irq_save(flags); 105 - 106 - cur = *list; 107 - 108 - if (node->flags & SA_INTERRUPT) { 109 - if (node->flags & SA_SHIRQ) 110 - return -EBUSY; 111 - /* 112 - * There should never be more than one 113 - */ 114 - while (cur && cur->flags & SA_INTERRUPT) { 115 - list = &cur->next; 116 - cur = cur->next; 117 - } 118 - } else { 119 - while (cur) { 120 - list = &cur->next; 121 - cur = cur->next; 122 - } 123 - } 124 - 125 - node->next = cur; 126 - *list = node; 127 - 128 - local_irq_restore(flags); 129 - return 0; 130 - } 131 - 132 - static inline void amiga_delete_irq(irq_node_t **list, void *dev_id) 133 - { 134 - unsigned long flags; 135 - irq_node_t *node; 136 - 137 - local_irq_save(flags); 138 - 139 - for (node = *list; node; list = &node->next, node = *list) { 140 - if (node->dev_id == dev_id) { 141 - *list = node->next; 142 - /* Mark it as free. */ 143 - node->handler = NULL; 144 - local_irq_restore(flags); 145 - return; 146 - } 147 - } 148 - local_irq_restore(flags); 149 - printk ("%s: tried to remove invalid irq\n", __FUNCTION__); 150 - } 151 - 152 - /* 153 - * amiga_request_irq : add an interrupt service routine for a particular 154 - * machine specific interrupt source. 155 - * If the addition was successful, it returns 0. 156 - */ 157 - 158 - int amiga_request_irq(unsigned int irq, 159 - irqreturn_t (*handler)(int, void *, struct pt_regs *), 160 - unsigned long flags, const char *devname, void *dev_id) 161 - { 162 - irq_node_t *node; 163 - int error = 0; 164 - 165 - if (irq >= AMI_IRQS) { 166 - printk ("%s: Unknown IRQ %d from %s\n", __FUNCTION__, 167 - irq, devname); 168 - return -ENXIO; 169 - } 170 - 171 - if (irq < IRQ_USER) 172 - return cpu_request_irq(irq, handler, flags, devname, dev_id); 173 - 174 - if (irq >= IRQ_AMIGA_CIAB) 175 - return cia_request_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, 176 - handler, flags, devname, dev_id); 177 - 178 - if (irq >= IRQ_AMIGA_CIAA) 179 - return cia_request_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, 180 - handler, flags, devname, dev_id); 181 - 182 - irq -= IRQ_USER; 183 - /* 184 - * IRQ_AMIGA_PORTS & IRQ_AMIGA_EXTER defaults to shared, 185 - * we could add a check here for the SA_SHIRQ flag but all drivers 186 - * should be aware of sharing anyway. 187 - */ 188 - if (ami_servers[irq]) { 189 - if (!(node = new_irq_node())) 190 - return -ENOMEM; 191 - node->handler = handler; 192 - node->flags = flags; 193 - node->dev_id = dev_id; 194 - node->devname = devname; 195 - node->next = NULL; 196 - error = amiga_insert_irq(&ami_irq_list[irq], node); 197 - } else { 198 - ami_irq_list[irq]->handler = handler; 199 - ami_irq_list[irq]->flags = flags; 200 - ami_irq_list[irq]->dev_id = dev_id; 201 - ami_irq_list[irq]->devname = devname; 202 - } 203 - 204 - /* enable the interrupt */ 205 - if (irq < IRQ_AMIGA_PORTS && !ami_ablecount[irq]) 206 - amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq]; 207 - 208 - return error; 209 - } 210 - 211 - void amiga_free_irq(unsigned int irq, void *dev_id) 212 - { 213 - if (irq >= AMI_IRQS) { 214 - printk ("%s: Unknown IRQ %d\n", __FUNCTION__, irq); 215 - return; 216 - } 217 - 218 - if (irq < IRQ_USER) 219 - cpu_free_irq(irq, dev_id); 220 - 221 - if (irq >= IRQ_AMIGA_CIAB) { 222 - cia_free_irq(&ciab_base, irq - IRQ_AMIGA_CIAB, dev_id); 223 - return; 224 - } 225 - 226 - if (irq >= IRQ_AMIGA_CIAA) { 227 - cia_free_irq(&ciaa_base, irq - IRQ_AMIGA_CIAA, dev_id); 228 - return; 229 - } 230 - 231 - irq -= IRQ_USER; 232 - if (ami_servers[irq]) { 233 - amiga_delete_irq(&ami_irq_list[irq], dev_id); 234 - /* if server list empty, disable the interrupt */ 235 - if (!ami_irq_list[irq] && irq < IRQ_AMIGA_PORTS) 236 - amiga_custom.intena = amiga_intena_vals[irq]; 237 - } else { 238 - if (ami_irq_list[irq]->dev_id != dev_id) 239 - printk("%s: removing probably wrong IRQ %d from %s\n", 240 - __FUNCTION__, irq, ami_irq_list[irq]->devname); 241 - ami_irq_list[irq]->handler = ami_badint; 242 - ami_irq_list[irq]->flags = 0; 243 - ami_irq_list[irq]->dev_id = NULL; 244 - ami_irq_list[irq]->devname = NULL; 245 - amiga_custom.intena = amiga_intena_vals[irq]; 246 - } 247 - } 248 - 249 138 /* 250 139 * Enable/disable a particular machine specific interrupt source. 251 140 * Note that this may affect other interrupts in case of a shared interrupt. 252 141 * This function should only be called for a _very_ short time to change some 253 142 * internal data, that may not be changed by the interrupt at the same time. 254 - * ami_(enable|disable)_irq calls may also be nested. 255 143 */ 256 144 257 - void amiga_enable_irq(unsigned int irq) 145 + static void amiga_enable_irq(unsigned int irq) 258 146 { 259 - if (irq >= AMI_IRQS) { 260 - printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); 261 - return; 262 - } 263 - 264 - if (--ami_ablecount[irq]) 265 - return; 266 - 267 - /* No action for auto-vector interrupts */ 268 - if (irq < IRQ_USER) { 269 - printk("%s: Trying to enable auto-vector IRQ %i\n", 270 - __FUNCTION__, irq); 271 - return; 272 - } 273 - 274 - if (irq >= IRQ_AMIGA_CIAB) { 275 - cia_set_irq(&ciab_base, (1 << (irq - IRQ_AMIGA_CIAB))); 276 - cia_able_irq(&ciab_base, CIA_ICR_SETCLR | 277 - (1 << (irq - IRQ_AMIGA_CIAB))); 278 - return; 279 - } 280 - 281 - if (irq >= IRQ_AMIGA_CIAA) { 282 - cia_set_irq(&ciaa_base, (1 << (irq - IRQ_AMIGA_CIAA))); 283 - cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | 284 - (1 << (irq - IRQ_AMIGA_CIAA))); 285 - return; 286 - } 287 - 288 - /* enable the interrupt */ 289 - amiga_custom.intena = IF_SETCLR | amiga_intena_vals[irq-IRQ_USER]; 147 + amiga_custom.intena = IF_SETCLR | (1 << (irq - IRQ_USER)); 290 148 } 291 149 292 - void amiga_disable_irq(unsigned int irq) 150 + static void amiga_disable_irq(unsigned int irq) 293 151 { 294 - if (irq >= AMI_IRQS) { 295 - printk("%s: Unknown IRQ %d\n", __FUNCTION__, irq); 296 - return; 297 - } 298 - 299 - if (ami_ablecount[irq]++) 300 - return; 301 - 302 - /* No action for auto-vector interrupts */ 303 - if (irq < IRQ_USER) { 304 - printk("%s: Trying to disable auto-vector IRQ %i\n", 305 - __FUNCTION__, irq); 306 - return; 307 - } 308 - 309 - if (irq >= IRQ_AMIGA_CIAB) { 310 - cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); 311 - return; 312 - } 313 - 314 - if (irq >= IRQ_AMIGA_CIAA) { 315 - cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); 316 - return; 317 - } 318 - 319 - /* disable the interrupt */ 320 - amiga_custom.intena = amiga_intena_vals[irq-IRQ_USER]; 321 - } 322 - 323 - inline void amiga_do_irq(int irq, struct pt_regs *fp) 324 - { 325 - kstat_cpu(0).irqs[irq]++; 326 - ami_irq_list[irq-IRQ_USER]->handler(irq, ami_irq_list[irq-IRQ_USER]->dev_id, fp); 327 - } 328 - 329 - void amiga_do_irq_list(int irq, struct pt_regs *fp) 330 - { 331 - irq_node_t *node; 332 - 333 - kstat_cpu(0).irqs[irq]++; 334 - 335 - amiga_custom.intreq = amiga_intena_vals[irq-IRQ_USER]; 336 - 337 - for (node = ami_irq_list[irq-IRQ_USER]; node; node = node->next) 338 - node->handler(irq, node->dev_id, fp); 152 + amiga_custom.intena = 1 << (irq - IRQ_USER); 339 153 } 340 154 341 155 /* ··· 120 392 /* if serial transmit buffer empty, interrupt */ 121 393 if (ints & IF_TBE) { 122 394 amiga_custom.intreq = IF_TBE; 123 - amiga_do_irq(IRQ_AMIGA_TBE, fp); 395 + m68k_handle_int(IRQ_AMIGA_TBE, fp); 124 396 } 125 397 126 398 /* if floppy disk transfer complete, interrupt */ 127 399 if (ints & IF_DSKBLK) { 128 400 amiga_custom.intreq = IF_DSKBLK; 129 - amiga_do_irq(IRQ_AMIGA_DSKBLK, fp); 401 + m68k_handle_int(IRQ_AMIGA_DSKBLK, fp); 130 402 } 131 403 132 404 /* if software interrupt set, interrupt */ 133 405 if (ints & IF_SOFT) { 134 406 amiga_custom.intreq = IF_SOFT; 135 - amiga_do_irq(IRQ_AMIGA_SOFT, fp); 407 + m68k_handle_int(IRQ_AMIGA_SOFT, fp); 136 408 } 137 409 return IRQ_HANDLED; 138 410 } ··· 144 416 /* if a blitter interrupt */ 145 417 if (ints & IF_BLIT) { 146 418 amiga_custom.intreq = IF_BLIT; 147 - amiga_do_irq(IRQ_AMIGA_BLIT, fp); 419 + m68k_handle_int(IRQ_AMIGA_BLIT, fp); 148 420 } 149 421 150 422 /* if a copper interrupt */ 151 423 if (ints & IF_COPER) { 152 424 amiga_custom.intreq = IF_COPER; 153 - amiga_do_irq(IRQ_AMIGA_COPPER, fp); 425 + m68k_handle_int(IRQ_AMIGA_COPPER, fp); 154 426 } 155 427 156 428 /* if a vertical blank interrupt */ 157 - if (ints & IF_VERTB) 158 - amiga_do_irq_list(IRQ_AMIGA_VERTB, fp); 429 + if (ints & IF_VERTB) { 430 + amiga_custom.intreq = IF_VERTB; 431 + m68k_handle_int(IRQ_AMIGA_VERTB, fp); 432 + } 159 433 return IRQ_HANDLED; 160 434 } 161 435 ··· 168 438 /* if audio 0 interrupt */ 169 439 if (ints & IF_AUD0) { 170 440 amiga_custom.intreq = IF_AUD0; 171 - amiga_do_irq(IRQ_AMIGA_AUD0, fp); 441 + m68k_handle_int(IRQ_AMIGA_AUD0, fp); 172 442 } 173 443 174 444 /* if audio 1 interrupt */ 175 445 if (ints & IF_AUD1) { 176 446 amiga_custom.intreq = IF_AUD1; 177 - amiga_do_irq(IRQ_AMIGA_AUD1, fp); 447 + m68k_handle_int(IRQ_AMIGA_AUD1, fp); 178 448 } 179 449 180 450 /* if audio 2 interrupt */ 181 451 if (ints & IF_AUD2) { 182 452 amiga_custom.intreq = IF_AUD2; 183 - amiga_do_irq(IRQ_AMIGA_AUD2, fp); 453 + m68k_handle_int(IRQ_AMIGA_AUD2, fp); 184 454 } 185 455 186 456 /* if audio 3 interrupt */ 187 457 if (ints & IF_AUD3) { 188 458 amiga_custom.intreq = IF_AUD3; 189 - amiga_do_irq(IRQ_AMIGA_AUD3, fp); 459 + m68k_handle_int(IRQ_AMIGA_AUD3, fp); 190 460 } 191 461 return IRQ_HANDLED; 192 462 } ··· 198 468 /* if serial receive buffer full interrupt */ 199 469 if (ints & IF_RBF) { 200 470 /* acknowledge of IF_RBF must be done by the serial interrupt */ 201 - amiga_do_irq(IRQ_AMIGA_RBF, fp); 471 + m68k_handle_int(IRQ_AMIGA_RBF, fp); 202 472 } 203 473 204 474 /* if a disk sync interrupt */ 205 475 if (ints & IF_DSKSYN) { 206 476 amiga_custom.intreq = IF_DSKSYN; 207 - amiga_do_irq(IRQ_AMIGA_DSKSYN, fp); 477 + m68k_handle_int(IRQ_AMIGA_DSKSYN, fp); 208 478 } 209 479 return IRQ_HANDLED; 210 - } 211 - 212 - static irqreturn_t ami_int7(int irq, void *dev_id, struct pt_regs *fp) 213 - { 214 - panic ("level 7 interrupt received\n"); 215 - } 216 - 217 - irqreturn_t (*amiga_default_handler[SYS_IRQS])(int, void *, struct pt_regs *) = { 218 - [1] = ami_int1, 219 - [3] = ami_int3, 220 - [4] = ami_int4, 221 - [5] = ami_int5, 222 - [7] = ami_int7 223 - }; 224 - 225 - int show_amiga_interrupts(struct seq_file *p, void *v) 226 - { 227 - int i; 228 - irq_node_t *node; 229 - 230 - for (i = IRQ_USER; i < IRQ_AMIGA_CIAA; i++) { 231 - node = ami_irq_list[i - IRQ_USER]; 232 - if (!node) 233 - continue; 234 - seq_printf(p, "ami %2d: %10u ", i, 235 - kstat_cpu(0).irqs[i]); 236 - do { 237 - if (node->flags & SA_INTERRUPT) 238 - seq_puts(p, "F "); 239 - else 240 - seq_puts(p, " "); 241 - seq_printf(p, "%s\n", node->devname); 242 - if ((node = node->next)) 243 - seq_puts(p, " "); 244 - } while (node); 245 - } 246 - 247 - cia_get_irq_list(&ciaa_base, p); 248 - cia_get_irq_list(&ciab_base, p); 249 - return 0; 250 480 }
+81 -80
arch/m68k/amiga/cia.c
··· 29 29 unsigned short int_mask; 30 30 int handler_irq, cia_irq, server_irq; 31 31 char *name; 32 - irq_handler_t irq_list[CIA_IRQS]; 33 32 } ciaa_base = { 34 33 .cia = &ciaa, 35 34 .int_mask = IF_PORTS, 36 - .handler_irq = IRQ_AUTO_2, 35 + .handler_irq = IRQ_AMIGA_PORTS, 37 36 .cia_irq = IRQ_AMIGA_CIAA, 38 - .server_irq = IRQ_AMIGA_PORTS, 39 - .name = "CIAA handler" 37 + .name = "CIAA" 40 38 }, ciab_base = { 41 39 .cia = &ciab, 42 40 .int_mask = IF_EXTER, 43 - .handler_irq = IRQ_AUTO_6, 41 + .handler_irq = IRQ_AMIGA_EXTER, 44 42 .cia_irq = IRQ_AMIGA_CIAB, 45 - .server_irq = IRQ_AMIGA_EXTER, 46 - .name = "CIAB handler" 43 + .name = "CIAB" 47 44 }; 48 45 49 46 /* ··· 63 66 64 67 /* 65 68 * Enable or disable CIA interrupts, return old interrupt mask, 66 - * interrupts will only be enabled if a handler exists 67 69 */ 68 70 69 71 unsigned char cia_able_irq(struct ciabase *base, unsigned char mask) 70 72 { 71 - unsigned char old, tmp; 72 - int i; 73 + unsigned char old; 73 74 74 75 old = base->icr_mask; 75 76 base->icr_data |= base->cia->icr; ··· 77 82 else 78 83 base->icr_mask &= ~mask; 79 84 base->icr_mask &= CIA_ICR_ALL; 80 - for (i = 0, tmp = 1; i < CIA_IRQS; i++, tmp <<= 1) { 81 - if ((tmp & base->icr_mask) && !base->irq_list[i].handler) { 82 - base->icr_mask &= ~tmp; 83 - base->cia->icr = tmp; 84 - } 85 - } 86 85 if (base->icr_data & base->icr_mask) 87 86 amiga_custom.intreq = IF_SETCLR | base->int_mask; 88 87 return old; 89 88 } 90 89 91 - int cia_request_irq(struct ciabase *base, unsigned int irq, 92 - irqreturn_t (*handler)(int, void *, struct pt_regs *), 93 - unsigned long flags, const char *devname, void *dev_id) 94 - { 95 - unsigned char mask; 96 - 97 - base->irq_list[irq].handler = handler; 98 - base->irq_list[irq].flags = flags; 99 - base->irq_list[irq].dev_id = dev_id; 100 - base->irq_list[irq].devname = devname; 101 - 102 - /* enable the interrupt */ 103 - mask = 1 << irq; 104 - cia_set_irq(base, mask); 105 - cia_able_irq(base, CIA_ICR_SETCLR | mask); 106 - return 0; 107 - } 108 - 109 - void cia_free_irq(struct ciabase *base, unsigned int irq, void *dev_id) 110 - { 111 - if (base->irq_list[irq].dev_id != dev_id) 112 - printk("%s: removing probably wrong IRQ %i from %s\n", 113 - __FUNCTION__, base->cia_irq + irq, 114 - base->irq_list[irq].devname); 115 - 116 - base->irq_list[irq].handler = NULL; 117 - base->irq_list[irq].flags = 0; 118 - 119 - cia_able_irq(base, 1 << irq); 120 - } 121 - 122 90 static irqreturn_t cia_handler(int irq, void *dev_id, struct pt_regs *fp) 123 91 { 124 92 struct ciabase *base = (struct ciabase *)dev_id; 125 - int mach_irq, i; 93 + int mach_irq; 126 94 unsigned char ints; 127 95 128 96 mach_irq = base->cia_irq; 129 97 ints = cia_set_irq(base, CIA_ICR_ALL); 130 98 amiga_custom.intreq = base->int_mask; 131 - for (i = 0; i < CIA_IRQS; i++, mach_irq++) { 132 - if (ints & 1) { 133 - kstat_cpu(0).irqs[mach_irq]++; 134 - base->irq_list[i].handler(mach_irq, base->irq_list[i].dev_id, fp); 135 - } 136 - ints >>= 1; 99 + for (; ints; mach_irq++, ints >>= 1) { 100 + if (ints & 1) 101 + m68k_handle_int(mach_irq, fp); 137 102 } 138 - amiga_do_irq_list(base->server_irq, fp); 139 103 return IRQ_HANDLED; 140 104 } 141 105 106 + static void cia_enable_irq(unsigned int irq) 107 + { 108 + unsigned char mask; 109 + 110 + if (irq >= IRQ_AMIGA_CIAB) { 111 + mask = 1 << (irq - IRQ_AMIGA_CIAB); 112 + cia_set_irq(&ciab_base, mask); 113 + cia_able_irq(&ciab_base, CIA_ICR_SETCLR | mask); 114 + } else { 115 + mask = 1 << (irq - IRQ_AMIGA_CIAA); 116 + cia_set_irq(&ciaa_base, mask); 117 + cia_able_irq(&ciaa_base, CIA_ICR_SETCLR | mask); 118 + } 119 + } 120 + 121 + static void cia_disable_irq(unsigned int irq) 122 + { 123 + if (irq >= IRQ_AMIGA_CIAB) 124 + cia_able_irq(&ciab_base, 1 << (irq - IRQ_AMIGA_CIAB)); 125 + else 126 + cia_able_irq(&ciaa_base, 1 << (irq - IRQ_AMIGA_CIAA)); 127 + } 128 + 129 + static struct irq_controller cia_irq_controller = { 130 + .name = "cia", 131 + .lock = SPIN_LOCK_UNLOCKED, 132 + .enable = cia_enable_irq, 133 + .disable = cia_disable_irq, 134 + }; 135 + 136 + /* 137 + * Override auto irq 2 & 6 and use them as general chain 138 + * for external interrupts, we link the CIA interrupt sources 139 + * into this chain. 140 + */ 141 + 142 + static void auto_enable_irq(unsigned int irq) 143 + { 144 + switch (irq) { 145 + case IRQ_AUTO_2: 146 + amiga_custom.intena = IF_SETCLR | IF_PORTS; 147 + break; 148 + case IRQ_AUTO_6: 149 + amiga_custom.intena = IF_SETCLR | IF_EXTER; 150 + break; 151 + } 152 + } 153 + 154 + static void auto_disable_irq(unsigned int irq) 155 + { 156 + switch (irq) { 157 + case IRQ_AUTO_2: 158 + amiga_custom.intena = IF_PORTS; 159 + break; 160 + case IRQ_AUTO_6: 161 + amiga_custom.intena = IF_EXTER; 162 + break; 163 + } 164 + } 165 + 166 + static struct irq_controller auto_irq_controller = { 167 + .name = "auto", 168 + .lock = SPIN_LOCK_UNLOCKED, 169 + .enable = auto_enable_irq, 170 + .disable = auto_disable_irq, 171 + }; 172 + 142 173 void __init cia_init_IRQ(struct ciabase *base) 143 174 { 144 - int i; 145 - 146 - /* init isr handlers */ 147 - for (i = 0; i < CIA_IRQS; i++) { 148 - base->irq_list[i].handler = NULL; 149 - base->irq_list[i].flags = 0; 150 - } 175 + m68k_setup_irq_controller(&cia_irq_controller, base->cia_irq, CIA_IRQS); 151 176 152 177 /* clear any pending interrupt and turn off all interrupts */ 153 178 cia_set_irq(base, CIA_ICR_ALL); 154 179 cia_able_irq(base, CIA_ICR_ALL); 155 180 156 - /* install CIA handler */ 157 - request_irq(base->handler_irq, cia_handler, 0, base->name, base); 158 - 159 - amiga_custom.intena = IF_SETCLR | base->int_mask; 160 - } 161 - 162 - int cia_get_irq_list(struct ciabase *base, struct seq_file *p) 163 - { 164 - int i, j; 165 - 166 - j = base->cia_irq; 167 - for (i = 0; i < CIA_IRQS; i++) { 168 - seq_printf(p, "cia %2d: %10d ", j + i, 169 - kstat_cpu(0).irqs[j + i]); 170 - seq_puts(p, " "); 171 - seq_printf(p, "%s\n", base->irq_list[i].devname); 172 - } 173 - return 0; 181 + /* override auto int and install CIA handler */ 182 + m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1); 183 + m68k_irq_startup(base->handler_irq); 184 + request_irq(base->handler_irq, cia_handler, SA_SHIRQ, base->name, base); 174 185 }
-15
arch/m68k/amiga/config.c
··· 87 87 static void amiga_sched_init(irqreturn_t (*handler)(int, void *, struct pt_regs *)); 88 88 /* amiga specific irq functions */ 89 89 extern void amiga_init_IRQ (void); 90 - extern irqreturn_t (*amiga_default_handler[]) (int, void *, struct pt_regs *); 91 - extern int amiga_request_irq (unsigned int irq, 92 - irqreturn_t (*handler)(int, void *, struct pt_regs *), 93 - unsigned long flags, const char *devname, 94 - void *dev_id); 95 - extern void amiga_free_irq (unsigned int irq, void *dev_id); 96 - extern void amiga_enable_irq (unsigned int); 97 - extern void amiga_disable_irq (unsigned int); 98 90 static void amiga_get_model(char *model); 99 91 static int amiga_get_hardware_list(char *buffer); 100 - extern int show_amiga_interrupts (struct seq_file *, void *); 101 92 /* amiga specific timer functions */ 102 93 static unsigned long amiga_gettimeoffset (void); 103 94 static int a3000_hwclk (int, struct rtc_time *); ··· 383 392 384 393 mach_sched_init = amiga_sched_init; 385 394 mach_init_IRQ = amiga_init_IRQ; 386 - mach_default_handler = &amiga_default_handler; 387 - mach_request_irq = amiga_request_irq; 388 - mach_free_irq = amiga_free_irq; 389 - enable_irq = amiga_enable_irq; 390 - disable_irq = amiga_disable_irq; 391 395 mach_get_model = amiga_get_model; 392 396 mach_get_hardware_list = amiga_get_hardware_list; 393 - mach_get_irq_list = show_amiga_interrupts; 394 397 mach_gettimeoffset = amiga_gettimeoffset; 395 398 if (AMIGAHW_PRESENT(A3000_CLK)){ 396 399 mach_hwclk = a3000_hwclk;
+3 -5
include/asm-m68k/amigaints.h
··· 37 37 #define IRQ_AMIGA_SOFT (IRQ_USER+2) 38 38 39 39 /* interrupts from external hardware */ 40 - #define IRQ_AMIGA_PORTS (IRQ_USER+3) 41 - #define IRQ_AMIGA_EXTER (IRQ_USER+13) 40 + #define IRQ_AMIGA_PORTS IRQ_AUTO_2 41 + #define IRQ_AMIGA_EXTER IRQ_AUTO_6 42 42 43 43 /* copper interrupt */ 44 44 #define IRQ_AMIGA_COPPER (IRQ_USER+4) ··· 88 88 #define IF_DSKBLK 0x0002 /* diskblock DMA finished */ 89 89 #define IF_TBE 0x0001 /* serial transmit buffer empty interrupt */ 90 90 91 - extern void amiga_do_irq(int irq, struct pt_regs *fp); 92 - extern void amiga_do_irq_list(int irq, struct pt_regs *fp); 93 - 94 91 /* CIA interrupt control register bits */ 95 92 96 93 #define CIA_ICR_TA 0x01 ··· 104 107 105 108 extern struct ciabase ciaa_base, ciab_base; 106 109 110 + extern void cia_init_IRQ(struct ciabase *base); 107 111 extern unsigned char cia_set_irq(struct ciabase *base, unsigned char mask); 108 112 extern unsigned char cia_able_irq(struct ciabase *base, unsigned char mask); 109 113