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/system.h> 46 #include <asm/traps.h> 47 48 #include <asm/atarihw.h> 49 #include <asm/atariints.h> 50 #include <asm/atari_stdma.h> 51 #include <asm/irq.h> 52 #include <asm/entry.h> 53 54 55 /* 56 * Atari interrupt handling scheme: 57 * -------------------------------- 58 * 59 * All interrupt source have an internal number (defined in 60 * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP, 61 * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can 62 * be allocated by atari_register_vme_int(). 63 */ 64 65 /* 66 * Bitmap for free interrupt vector numbers 67 * (new vectors starting from 0x70 can be allocated by 68 * atari_register_vme_int()) 69 */ 70 static int free_vme_vec_bitmap; 71 72 /* GK: 73 * HBL IRQ handler for Falcon. Nobody needs it :-) 74 * ++andreas: raise ipl to disable further HBLANK interrupts. 75 */ 76 asmlinkage void falcon_hblhandler(void); 77 asm(".text\n" 78 __ALIGN_STR "\n\t" 79 "falcon_hblhandler:\n\t" 80 "orw #0x200,%sp@\n\t" /* set saved ipl to 2 */ 81 "rte"); 82 83 extern void atari_microwire_cmd(int cmd); 84 85 extern int atari_SCC_reset_done; 86 87 static unsigned int atari_irq_startup(struct irq_data *data) 88 { 89 unsigned int irq = data->irq; 90 91 m68k_irq_startup(data); 92 atari_turnon_irq(irq); 93 atari_enable_irq(irq); 94 return 0; 95 } 96 97 static void atari_irq_shutdown(struct irq_data *data) 98 { 99 unsigned int irq = data->irq; 100 101 atari_disable_irq(irq); 102 atari_turnoff_irq(irq); 103 m68k_irq_shutdown(data); 104 105 if (irq == IRQ_AUTO_4) 106 vectors[VEC_INT4] = falcon_hblhandler; 107 } 108 109 static void atari_irq_enable(struct irq_data *data) 110 { 111 atari_enable_irq(data->irq); 112 } 113 114 static void atari_irq_disable(struct irq_data *data) 115 { 116 atari_disable_irq(data->irq); 117 } 118 119 static struct irq_chip atari_irq_chip = { 120 .name = "atari", 121 .irq_startup = atari_irq_startup, 122 .irq_shutdown = atari_irq_shutdown, 123 .irq_enable = atari_irq_enable, 124 .irq_disable = atari_irq_disable, 125 }; 126 127 /* 128 * void atari_init_IRQ (void) 129 * 130 * Parameters: None 131 * 132 * Returns: Nothing 133 * 134 * This function should be called during kernel startup to initialize 135 * the atari IRQ handling routines. 136 */ 137 138 void __init atari_init_IRQ(void) 139 { 140 m68k_setup_user_interrupt(VEC_USER, NUM_ATARI_SOURCES - IRQ_USER); 141 m68k_setup_irq_controller(&atari_irq_chip, handle_simple_irq, 1, 142 NUM_ATARI_SOURCES - 1); 143 144 /* Initialize the MFP(s) */ 145 146 #ifdef ATARI_USE_SOFTWARE_EOI 147 st_mfp.vec_adr = 0x48; /* Software EOI-Mode */ 148 #else 149 st_mfp.vec_adr = 0x40; /* Automatic EOI-Mode */ 150 #endif 151 st_mfp.int_en_a = 0x00; /* turn off MFP-Ints */ 152 st_mfp.int_en_b = 0x00; 153 st_mfp.int_mk_a = 0xff; /* no Masking */ 154 st_mfp.int_mk_b = 0xff; 155 156 if (ATARIHW_PRESENT(TT_MFP)) { 157 #ifdef ATARI_USE_SOFTWARE_EOI 158 tt_mfp.vec_adr = 0x58; /* Software EOI-Mode */ 159 #else 160 tt_mfp.vec_adr = 0x50; /* Automatic EOI-Mode */ 161 #endif 162 tt_mfp.int_en_a = 0x00; /* turn off MFP-Ints */ 163 tt_mfp.int_en_b = 0x00; 164 tt_mfp.int_mk_a = 0xff; /* no Masking */ 165 tt_mfp.int_mk_b = 0xff; 166 } 167 168 if (ATARIHW_PRESENT(SCC) && !atari_SCC_reset_done) { 169 atari_scc.cha_a_ctrl = 9; 170 MFPDELAY(); 171 atari_scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */ 172 } 173 174 if (ATARIHW_PRESENT(SCU)) { 175 /* init the SCU if present */ 176 tt_scu.sys_mask = 0x10; /* enable VBL (for the cursor) and 177 * disable HSYNC interrupts (who 178 * needs them?) MFP and SCC are 179 * enabled in VME mask 180 */ 181 tt_scu.vme_mask = 0x60; /* enable MFP and SCC ints */ 182 } else { 183 /* If no SCU and no Hades, the HSYNC interrupt needs to be 184 * disabled this way. (Else _inthandler in kernel/sys_call.S 185 * gets overruns) 186 */ 187 188 vectors[VEC_INT2] = falcon_hblhandler; 189 vectors[VEC_INT4] = falcon_hblhandler; 190 } 191 192 if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) { 193 /* Initialize the LM1992 Sound Controller to enable 194 the PSG sound. This is misplaced here, it should 195 be in an atasound_init(), that doesn't exist yet. */ 196 atari_microwire_cmd(MW_LM1992_PSG_HIGH); 197 } 198 199 stdma_init(); 200 201 /* Initialize the PSG: all sounds off, both ports output */ 202 sound_ym.rd_data_reg_sel = 7; 203 sound_ym.wd_data = 0xff; 204 } 205 206 207 /* 208 * atari_register_vme_int() returns the number of a free interrupt vector for 209 * hardware with a programmable int vector (probably a VME board). 210 */ 211 212 unsigned long atari_register_vme_int(void) 213 { 214 int i; 215 216 for (i = 0; i < 32; i++) 217 if ((free_vme_vec_bitmap & (1 << i)) == 0) 218 break; 219 220 if (i == 16) 221 return 0; 222 223 free_vme_vec_bitmap |= 1 << i; 224 return VME_SOURCE_BASE + i; 225 } 226 EXPORT_SYMBOL(atari_register_vme_int); 227 228 229 void atari_unregister_vme_int(unsigned long irq) 230 { 231 if (irq >= VME_SOURCE_BASE && irq < VME_SOURCE_BASE + VME_MAX_SOURCES) { 232 irq -= VME_SOURCE_BASE; 233 free_vme_vec_bitmap &= ~(1 << irq); 234 } 235 } 236 EXPORT_SYMBOL(atari_unregister_vme_int); 237 238 239