📄 ataints.c
字号:
* Returns: Nothing * * This function should be called during kernel startup to initialize * the atari IRQ handling routines. */void __init atari_init_IRQ(void){ int i; /* initialize the vector table */ for (i = 0; i < NUM_INT_SOURCES; ++i) { vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt; } /* Initialize the MFP(s) */#ifdef ATARI_USE_SOFTWARE_EOI mfp.vec_adr = 0x48; /* Software EOI-Mode */#else mfp.vec_adr = 0x40; /* Automatic EOI-Mode */#endif mfp.int_en_a = 0x00; /* turn off MFP-Ints */ mfp.int_en_b = 0x00; mfp.int_mk_a = 0xff; /* no Masking */ mfp.int_mk_b = 0xff; if (ATARIHW_PRESENT(TT_MFP)) {#ifdef ATARI_USE_SOFTWARE_EOI tt_mfp.vec_adr = 0x58; /* Software EOI-Mode */#else tt_mfp.vec_adr = 0x50; /* Automatic EOI-Mode */#endif tt_mfp.int_en_a = 0x00; /* turn off MFP-Ints */ tt_mfp.int_en_b = 0x00; tt_mfp.int_mk_a = 0xff; /* no Masking */ tt_mfp.int_mk_b = 0xff; } if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) { scc.cha_a_ctrl = 9; MFPDELAY(); scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */ } if (ATARIHW_PRESENT(SCU)) { /* init the SCU if present */ tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and * disable HSYNC interrupts (who * needs them?) MFP and SCC are * enabled in VME mask */ tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ } else { /* If no SCU and no Hades, the HSYNC interrupt needs to be * disabled this way. (Else _inthandler in kernel/sys_call.S * gets overruns) */ if (!MACH_IS_HADES) vectors[VEC_INT2] = falcon_hblhandler; } if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) { /* Initialize the LM1992 Sound Controller to enable the PSG sound. This is misplaced here, it should be in an atasound_init(), that doesn't exist yet. */ atari_microwire_cmd(MW_LM1992_PSG_HIGH); } stdma_init(); /* Initialize the PSG: all sounds off, both ports output */ sound_ym.rd_data_reg_sel = 7; sound_ym.wd_data = 0xff;}static void atari_call_irq_list( int irq, void *dev_id, struct pt_regs *fp ){ irq_node_t *node; for (node = (irq_node_t *)dev_id; node; node = node->next) node->handler(irq, node->dev_id, fp);}/* * atari_request_irq : add an interrupt service routine for a particular * machine specific interrupt source. * If the addition was successful, it returns 0. */int atari_request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *devname, void *dev_id){ int vector; unsigned long oflags = flags; /* * The following is a hack to make some PCI card drivers work, * which set the SA_SHIRQ flag. */ flags &= ~SA_SHIRQ; if (flags == SA_INTERRUPT) { printk ("%s: SA_INTERRUPT changed to IRQ_TYPE_SLOW for %s\n", __FUNCTION__, devname); flags = IRQ_TYPE_SLOW; } if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) { printk ("%s: Bad irq type 0x%lx <0x%lx> requested from %s\n", __FUNCTION__, flags, oflags, devname); return -EINVAL; } if (!IS_VALID_INTNO(irq)) { printk ("%s: Unknown irq %d requested from %s\n", __FUNCTION__, irq, devname); return -ENXIO; } vector = IRQ_SOURCE_TO_VECTOR(irq); /* * Check type/source combination: slow ints are (currently) * only possible for MFP-interrupts. */ if (flags == IRQ_TYPE_SLOW && (irq < STMFP_SOURCE_BASE || irq >= SCC_SOURCE_BASE)) { printk ("%s: Slow irq requested for non-MFP source %d from %s\n", __FUNCTION__, irq, devname); return -EINVAL; } if (vectors[vector] == bad_interrupt) { /* int has no handler yet */ irq_handler[irq].handler = handler; irq_handler[irq].dev_id = dev_id; irq_param[irq].flags = flags; irq_param[irq].devname = devname; vectors[vector] = (flags == IRQ_TYPE_SLOW) ? slow_handlers[irq-STMFP_SOURCE_BASE] : (flags == IRQ_TYPE_FAST) ? atari_fast_irq_handler : atari_prio_irq_handler; /* If MFP int, also enable and umask it */ atari_turnon_irq(irq); atari_enable_irq(irq); return 0; } else if (irq_param[irq].flags == flags) { /* old handler is of same type -> handlers can be chained */ irq_node_t *node; unsigned long flags; save_flags(flags); cli(); if (irq_handler[irq].handler != atari_call_irq_list) { /* Only one handler yet, make a node for this first one */ if (!(node = new_irq_node())) return -ENOMEM; node->handler = irq_handler[irq].handler; node->dev_id = irq_handler[irq].dev_id; node->devname = irq_param[irq].devname; node->next = NULL; irq_handler[irq].handler = atari_call_irq_list; irq_handler[irq].dev_id = node; irq_param[irq].devname = "chained"; } if (!(node = new_irq_node())) return -ENOMEM; node->handler = handler; node->dev_id = dev_id; node->devname = devname; /* new handlers are put in front of the queue */ node->next = irq_handler[irq].dev_id; irq_handler[irq].dev_id = node; restore_flags(flags); return 0; } else { printk ("%s: Irq %d allocated by other type int (call from %s)\n", __FUNCTION__, irq, devname); return -EBUSY; }}void atari_free_irq(unsigned int irq, void *dev_id){ unsigned long flags; int vector; irq_node_t **list, *node; if (!IS_VALID_INTNO(irq)) { printk("%s: Unknown irq %d\n", __FUNCTION__, irq); return; } vector = IRQ_SOURCE_TO_VECTOR(irq); if (vectors[vector] == bad_interrupt) goto not_found; save_flags(flags); cli(); if (irq_handler[irq].handler != atari_call_irq_list) { /* It's the only handler for the interrupt */ if (irq_handler[irq].dev_id != dev_id) { restore_flags(flags); goto not_found; } irq_handler[irq].handler = NULL; irq_handler[irq].dev_id = NULL; irq_param[irq].devname = NULL; vectors[vector] = bad_interrupt; /* If MFP int, also disable it */ atari_disable_irq(irq); atari_turnoff_irq(irq); restore_flags(flags); return; } /* The interrupt is chained, find the irq on the list */ for(list = (irq_node_t **)&irq_handler[irq].dev_id; *list; list = &(*list)->next) { if ((*list)->dev_id == dev_id) break; } if (!*list) { restore_flags(flags); goto not_found; } (*list)->handler = NULL; /* Mark it as free for reallocation */ *list = (*list)->next; /* If there's now only one handler, unchain the interrupt, i.e. plug in * the handler directly again and omit atari_call_irq_list */ node = (irq_node_t *)irq_handler[irq].dev_id; if (node && !node->next) { irq_handler[irq].handler = node->handler; irq_handler[irq].dev_id = node->dev_id; irq_param[irq].devname = node->devname; node->handler = NULL; /* Mark it as free for reallocation */ } restore_flags(flags); return;not_found: printk("%s: tried to remove invalid irq\n", __FUNCTION__); return;}/* * atari_register_vme_int() returns the number of a free interrupt vector for * hardware with a programmable int vector (probably a VME board). */unsigned long atari_register_vme_int(void){ int i; for(i = 0; i < 32; i++) if((free_vme_vec_bitmap & (1 << i)) == 0) break; if(i == 16) return 0; free_vme_vec_bitmap |= 1 << i; return (VME_SOURCE_BASE + i);}void atari_unregister_vme_int(unsigned long irq){ if(irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { irq -= VME_SOURCE_BASE; free_vme_vec_bitmap &= ~(1 << irq); }}int atari_get_irq_list(char *buf){ int i, len = 0; for (i = 0; i < NUM_INT_SOURCES; ++i) { if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt) continue; if (i < STMFP_SOURCE_BASE) len += sprintf(buf+len, "auto %2d: %10u ", i, kstat.irqs[0][i]); else len += sprintf(buf+len, "vec $%02x: %10u ", IRQ_SOURCE_TO_VECTOR(i), kstat.irqs[0][i]); if (irq_handler[i].handler != atari_call_irq_list) { len += sprintf(buf+len, "%s\n", irq_param[i].devname); } else { irq_node_t *p; for( p = (irq_node_t *)irq_handler[i].dev_id; p; p = p->next ) { len += sprintf(buf+len, "%s\n", p->devname); if (p->next) len += sprintf( buf+len, " " ); } } } if (num_spurious) len += sprintf(buf+len, "spurio.: %10u\n", num_spurious); return len;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -