1 /* 2 * arch/m68k/atari/ataints.c -- Atari Linux interrupt handling code 3 * 4 * 5/2/94 Roman Hodek: 5 * Added support for TT interrupts; setup for TT SCU (may someone has 6 * twiddled there and we won't get the right interrupts :-() 7 * 8 * Major change: The device-independent code in m68k/ints.c didn't know 9 * about non-autovec ints yet. It hardcoded the number of possible ints to 10 * 7 (IRQ1...IRQ7). But the Atari has lots of non-autovec ints! I made the 11 * number of possible ints a constant defined in interrupt.h, which is 12 * 47 for the Atari. So we can call request_irq() for all Atari interrupts 13 * just the normal way. Additionally, all vectors >= 48 are initialized to 14 * call trap() instead of inthandler(). This must be changed here, too. 15 * 16 * 1995-07-16 Lars Brinkhoff <f93labr@dd.chalmers.se>: 17 * Corrected a bug in atari_add_isr() which rejected all SCC 18 * interrupt sources if there were no TT MFP! 19 * 20 * 12/13/95: New interface functions atari_level_triggered_int() and 21 * atari_register_vme_int() as support for level triggered VME interrupts. 22 * 23 * 02/12/96: (Roman) 24 * Total rewrite of Atari interrupt handling, for new scheme see comments 25 * below. 26 * 27 * 1996-09-03 lars brinkhoff <f93labr@dd.chalmers.se>: 28 * Added new function atari_unregister_vme_int(), and 29 * modified atari_register_vme_int() as well as IS_VALID_INTNO() 30 * to work with it. 31 * 32 * This file is subject to the terms and conditions of the GNU General Public 33 * License. See the file COPYING in the main directory of this archive 34 * for more details. 35 * 36 */ 37 38 #include <linux/types.h> 39 #include <linux/kernel.h> 40 #include <linux/kernel_stat.h> 41 #include <linux/init.h> 42 #include <linux/seq_file.h> 43 #include <linux/module.h> 44 45 #include <asm/traps.h> 46 47 #include <asm/atarihw.h> 48 #include <asm/atariints.h> 49 #include <asm/atari_stdma.h> 50 #include <asm/irq.h> 51 #include <asm/entry.h> 52 53 54 /* 55 * Atari interrupt handling scheme: 56 * -------------------------------- 57 * 58 * All interrupt source have an internal number (defined in 59 * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP, 60 * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can 61 * be allocated by atari_register_vme_int(). 62 */ 63 64 /* 65 * Bitmap for free interrupt vector numbers 66 * (new vectors starting from 0x70 can be allocated by 67 * atari_register_vme_int()) 68 */ 69 static int free_vme_vec_bitmap; 70 71 /* GK: 72 * HBL IRQ handler for Falcon. Nobody needs it :-) 73 * ++andreas: raise ipl to disable further HBLANK interrupts. 74 */ 75 asmlinkage void falcon_hblhandler(void); 76 asm(".text\n" 77 __ALIGN_STR "\n\t" 78 "falcon_hblhandler:\n\t" 79 "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */ 80 "rte"); 81 82 extern void atari_microwire_cmd(int cmd); 83 84 static unsigned int atari_irq_startup(struct irq_data *data) 85 { 86 unsigned int irq = data->irq; 87 88 m68k_irq_startup(data); 89 atari_turnon_irq(irq); 90 atari_enable_irq(irq); 91 return 0; 92 } 93 94 static void atari_irq_shutdown(struct irq_data *data) 95 { 96 unsigned int irq = data->irq; 97 98 atari_disable_irq(irq); 99 atari_turnoff_irq(irq); 100 m68k_irq_shutdown(data); 101 102 if (irq == IRQ_AUTO_4) 103 vectors[VEC_INT4] = falcon_hblhandler; 104 } 105 106 static void atari_irq_enable(struct irq_data *data) 107 { 108 atari_enable_irq(data->irq); 109 } 110 111 static void atari_irq_disable(struct irq_data *data) 112 { 113 atari_disable_irq(data->irq); 114 } 115 116 static struct irq_chip atari_irq_chip = { 117 .name = "atari", 118 .irq_startup = atari_irq_startup, 119 .irq_shutdown = atari_irq_shutdown, 120 .irq_enable = atari_irq_enable, 121 .irq_disable = atari_irq_disable, 122 }; 123 124 /* 125 * void atari_init_IRQ (void) 126 * 127 * Parameters: None 128 * 129 * Returns: Nothing 130 * 131 * This function should be called during kernel startup to initialize 132 * the atari IRQ handling routines. 133 */ 134 135 void __init atari_init_IRQ(void) 136 { 137 m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER); 138 m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1, 139 NUM_ATARI_SOURCES - 1); 140 141 /* Initialize the MFP(s) */ 142 143 #ifdef ATARI_USE_SOFTWARE_EOI 144 st_mfp.vec_adr = 0x48; /* Software EOI-Mode */ 145 #else 146 st_mfp.vec_adr = 0x40; /* Automatic EOI-Mode */ 147 #endif 148 st_mfp.int_en_a = 0x00; /* turn off MFP-Ints */ 149 st_mfp.int_en_b = 0x00; 150 st_mfp.int_mk_a = 0xff; /* no Masking */ 151 st_mfp.int_mk_b = 0xff; 152 153 if (ATARIHW_PRESENT(TT_MFP)) { 154 #ifdef ATARI_USE_SOFTWARE_EOI 155 tt_mfp.vec_adr = 0x58; /* Software EOI-Mode */ 156 #else 157 tt_mfp.vec_adr = 0x50; /* Automatic EOI-Mode */ 158 #endif 159 tt_mfp.int_en_a = 0x00; /* turn off MFP-Ints */ 160 tt_mfp.int_en_b = 0x00; 161 tt_mfp.int_mk_a = 0xff; /* no Masking */ 162 tt_mfp.int_mk_b = 0xff; 163 } 164 165 if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) { 166 atari_scc.cha_a_ctrl = 9; 167 MFPDELAY(); 168 atari_scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */ 169 } 170 171 if (ATARIHW_PRESENT(SCU)) { 172 /* init the SCU if present */ 173 tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and 174 * disable HSYNC interrupts (who 175 * needs them?) MFP and SCC are 176 * enabled in VME mask 177 */ 178 tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ 179 } else { 180 /* If no SCU and no Hades, the HSYNC interrupt needs to be 181 * disabled this way. (Else _inthandler in kernel/sys_call.S 182 * gets overruns) 183 */ 184 185 vectors[VEC_INT2] = falcon_hblhandler; 186 vectors[VEC_INT4] = falcon_hblhandler; 187 } 188 189 if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) { 190 /* Initialize the LM1992 Sound Controller to enable 191 the PSG sound. This is misplaced here, it should 192 be in an atasound_init(), that doesn't exist yet. */ 193 atari_microwire_cmd(MW_LM1992_PSG_HIGH); 194 } 195 196 stdma_init(); 197 198 /* Initialize the PSG: all sounds off, both ports output */ 199 sound_ym.rd_data_reg_sel = 7; 200 sound_ym.wd_data = 0xff; 201 } 202 203 204 /* 205 * atari_register_vme_int() returns the number of a free interrupt vector for 206 * hardware with a programmable int vector (probably a VME board). 207 */ 208 209 unsigned int atari_register_vme_int(void) 210 { 211 int i; 212 213 for (i = 0; i < 32; i++) 214 if ((free_vme_vec_bitmap & (1 << i)) == 0) 215 break; 216 217 if (i == 16) 218 return 0; 219 220 free_vme_vec_bitmap |= 1 << i; 221 return VME_SOURCE_BASE + i; 222 } 223 EXPORT_SYMBOL(atari_register_vme_int); 224 225 226 void atari_unregister_vme_int(unsigned int irq) 227 { 228 if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { 229 irq -= VME_SOURCE_BASE; 230 free_vme_vec_bitmap &= ~(1 << irq); 231 } 232 } 233 EXPORT_SYMBOL(atari_unregister_vme_int); 234 235 236