root/arch/m68k/atari/ataints.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. atari_fast_prio_irq_dummy
  2. atari_init_INTS
  3. atari_call_isr_list
  4. atari_add_isr
  5. atari_remove_isr
  6. atari_register_vme_int
  7. atari_get_irq_list

   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 add_isr() for all Atari interrupts just
  13  *  the normal way. Additionally, all vectors >= 48 are initialized to call
  14  *  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  * This file is subject to the terms and conditions of the GNU General Public
  28  * License.  See the file README.legal in the main directory of this archive
  29  * for more details.
  30  *
  31  */
  32 
  33 #include <linux/types.h>
  34 #include <linux/kernel.h>
  35 #include <linux/ptrace.h>
  36 #include <linux/kernel_stat.h>
  37 
  38 #include <asm/system.h>
  39 #include <asm/traps.h>
  40 
  41 #include <asm/atarihw.h>
  42 #include <asm/atariints.h>
  43 #include <asm/atari_stdma.h>
  44 #include <asm/bootinfo.h>
  45 #include <asm/irq.h>
  46 
  47 
  48 /*
  49  * Atari interrupt handling scheme:
  50  * --------------------------------
  51  * 
  52  * All interrupt source have an internal number (defined in
  53  * <asm/atariints.h>): Autovector interrupts are 1..7, then follow ST-MFP,
  54  * TT-MFP, SCC, and finally VME interrupts. Vector numbers for the latter can
  55  * be allocated by atari_register_vme_int(). Currently, all int source numbers
  56  * have the IRQ_MACHSPEC bit set, to keep the general int handling functions
  57  * in kernel/ints.c from them.
  58  *
  59  * Each interrupt can be of three types:
  60  * 
  61  *  - SLOW: The handler runs with all interrupts enabled, except the one it
  62  *    was called by (to avoid reentering). This should be the usual method.
  63  *    But it is currently possible only for MFP ints, since only the MFP
  64  *    offers an easy way to mask interrupts.
  65  *
  66  *  - FAST: The handler runs with all interrupts disabled. This should be used
  67  *    only for really fast handlers, that just do actions immediately
  68  *    necessary, and let the rest do a bottom half or task queue.
  69  *
  70  *  - PRIORITIZED: The handler can be interrupted by higher-level ints
  71  *    (greater IPL, no MFP priorities!). This is the method of choice for ints
  72  *    which should be slow, but are not from a MFP.
  73  *
  74  * The feature of more than one handler for one int source is still there, but
  75  * only applicable if all handers are of the same type. To not slow down
  76  * processing of ints with only one handler by the chaining feature, the list
  77  * calling function atari_call_isr_list() is only plugged in at the time the
  78  * second handler is registered.
  79  *
  80  * Implementation notes: For fast-as-possible int handling, there are separate
  81  * entry points for each type (slow/fast/prio). The assembler handler calls
  82  * the isr directly in the usual case, no C wrapper is involved. In case of
  83  * multiple handlers, atari_call_isr_list() is registered as handler and calls
  84  * in turn the real isr's. To ease access from assembler level to the isr
  85  * function pointer and accompanying data, these two are stored in a separate
  86  * array, irq_handler[]. The rest of data (type, name) are put into a second
  87  * array, irq_param, that is accessed from C only. For each slow interrupt (32
  88  * in all) there are separate handler functions, which makes it possible to
  89  * hard-code the MFP register address and value, are necessary to mask the
  90  * int. If there'd be only one generic function, lots of calculations would be
  91  * needed to determine MFP register and int mask from the vector number :-(
  92  *
  93  * Furthermore, slow ints may not lower the IPL below its previous value
  94  * (before the int happened). This is needed so that an int of class PRIO, on
  95  * that this int may be stacked, cannot be reentered. This feature is
  96  * implemented as follows: If the stack frame format is 1 (throwaway), the int
  97  * is not stacked, and the IPL is anded with 0xfbff, resulting in a new level
  98  * 2, which still blocks the HSYNC, but no interrupts of interest. If the
  99  * frame format is 0, the int is nested, and the old IPL value can be found in
 100  * the sr copy in the frame.
 101  */
 102 
 103 
 104 #define NUM_INT_SOURCES (8 + NUM_ATARI_SOURCES)
 105 
 106 typedef void (*asm_irq_handler)(void);
 107 
 108 struct irqhandler {
 109         isrfunc isr;
 110         void    *data;
 111 };
 112 
 113 struct irqparam {
 114         int type;
 115         char *name;
 116 };
 117 
 118 /*
 119  * Array with isr's and their parameter data. This array is accessed from low
 120  * level assembler code, so an element size of 8 allows usage of index scaling
 121  * addressing mode.
 122  */
 123 static struct irqhandler irq_handler[NUM_INT_SOURCES];
 124 
 125 /*
 126  * This array hold the rest of parameters of int handlers: type
 127  * (slow,fast,prio) and the name of the handler. These values are only
 128  * accessed from C
 129  */
 130 static struct irqparam irq_param[NUM_INT_SOURCES];
 131 
 132 /*
 133  * Counter for next free interrupt vector number
 134  * (new vectors starting from 0x70 can be allocated by
 135  * atari_register_vme_int())
 136  */
 137 static int next_free_vme_vec = VME_SOURCE_BASE;
 138 
 139 /* check for valid int number (complex, sigh...) */
 140 #define IS_VALID_INTNO(n)                                                                                       \
 141         ((n) > 0 &&                                                                                                             \
 142          /* autovec and ST-MFP ok anyway */                                                             \
 143          (((n) < TTMFP_SOURCE_BASE) ||                                                                  \
 144           /* TT-MFP ok if present */                                                                    \
 145           ((n) >= TTMFP_SOURCE_BASE && (n) < SCC_SOURCE_BASE &&                 \
 146            ATARIHW_PRESENT(TT_MFP)) ||                                                                  \
 147           /* SCC ok if present and number even */                                               \
 148           ((n) >= SCC_SOURCE_BASE && (n) < VME_SOURCE_BASE &&                   \
 149            !((n) & 1) && ATARIHW_PRESENT(SCC)) ||                                               \
 150           /* greater numbers ok if less than #registered VME vectors */ \
 151           ((n) >= VME_SOURCE_BASE && (n) < next_free_vme_vec)))
 152 
 153 
 154 /*
 155  * Here start the assembler entry points for interrupts
 156  */
 157 
 158 #define IRQ_NAME(nr) atari_slow_irq_##nr##_handler(void)
 159 
 160 #define MFP_MK_BASE     "0xfa13"
 161 
 162 /* This must agree with head.S.  */
 163 #define ORIG_DO "0x20"
 164 #define FORMATVEC "0x2E"
 165 #define SR "0x28"
 166 #define SAVE_ALL                                \
 167         "clrl   %%sp@-;"    /* stk_adj */       \
 168         "clrl   %%sp@-;"                        \
 169         "subql  #1,%%sp@;"  /* orig d0 = -1 */  \
 170         "movel  %%d0,%%sp@-;" /* d0 */          \
 171         "moveml %%d1-%%d5/%%a0-%%a1,%%sp@-"
 172 
 173 #define BUILD_SLOW_IRQ(n)                                                  \
 174 asmlinkage void IRQ_NAME(n);                                               \
 175 /* Dummy function to allow asm with operands.  */                          \
 176 void atari_slow_irq_##n##_dummy (void) {                                   \
 177 __asm__ (ALIGN_STR "\n"                                                    \
 178 SYMBOL_NAME_STR(atari_slow_irq_) #n "_handler:\t"                          \
 179         SAVE_ALL "\n"                                                      \
 180 "       addql   #1,"SYMBOL_NAME_STR(intr_count)"\n"                        \
 181 "       andb    #~(1<<(" #n "&7)),"     /* mask this interrupt */          \
 182         "("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n"         \
 183 "       movew   %%sp@("SR"),%%d0\n"     /* get old IPL from stack frame */ \
 184 "       movew   %%sr,%%d1\n"                                               \
 185 "       andw    #0x0700,%%d0\n"                                            \
 186 "       andw    #0xf8ff,%%d1\n"                                            \
 187 "       orw     %%d0,%%d1\n"                                               \
 188 "       movew   %%d1,%%sr\n"            /* set IPL = previous value */     \
 189 "       addql   #1,%a0\n"                                                  \
 190 "       lea     "SYMBOL_NAME_STR(irq_handler)"+("#n"+8)*8,%%a0\n"          \
 191 "       movel   %%a0@(4),%%sp@-\n"      /* push handler data */            \
 192 "       pea     %%sp@(4)\n"             /* push addr of frame */           \
 193 "       pea     (" #n "+8):w\n"         /* push int number */              \
 194 "       movel   %%a0@,%%a0\n"                                              \
 195 "       jbsr    %%a0@\n"                /* call the handler */             \
 196 "       addql   #8,%%sp\n"                                                 \
 197 "       addql   #4,%%sp\n"                                                 \
 198 "       orw     #0x0600,%%sr\n"                                            \
 199 "       andw    #0xfeff,%%sr\n"         /* set IPL = 6 again */            \
 200 "       orb     #(1<<(" #n "&7)),"      /* now unmask the int again */     \
 201             "("MFP_MK_BASE"+(((" #n "&8)^8)>>2)+((" #n "&16)<<3)):w\n"     \
 202 "       jbra    "SYMBOL_NAME_STR(ret_from_interrupt)"\n"                   \
 203          : : "i" (&kstat.interrupts[n+8])                                  \
 204 );                                                                         \
 205 }
 206 
 207 BUILD_SLOW_IRQ(0);
 208 BUILD_SLOW_IRQ(1);
 209 BUILD_SLOW_IRQ(2);
 210 BUILD_SLOW_IRQ(3);
 211 BUILD_SLOW_IRQ(4);
 212 BUILD_SLOW_IRQ(5);
 213 BUILD_SLOW_IRQ(6);
 214 BUILD_SLOW_IRQ(7);
 215 BUILD_SLOW_IRQ(8);
 216 BUILD_SLOW_IRQ(9);
 217 BUILD_SLOW_IRQ(10);
 218 BUILD_SLOW_IRQ(11);
 219 BUILD_SLOW_IRQ(12);
 220 BUILD_SLOW_IRQ(13);
 221 BUILD_SLOW_IRQ(14);
 222 BUILD_SLOW_IRQ(15);
 223 BUILD_SLOW_IRQ(16);
 224 BUILD_SLOW_IRQ(17);
 225 BUILD_SLOW_IRQ(18);
 226 BUILD_SLOW_IRQ(19);
 227 BUILD_SLOW_IRQ(20);
 228 BUILD_SLOW_IRQ(21);
 229 BUILD_SLOW_IRQ(22);
 230 BUILD_SLOW_IRQ(23);
 231 BUILD_SLOW_IRQ(24);
 232 BUILD_SLOW_IRQ(25);
 233 BUILD_SLOW_IRQ(26);
 234 BUILD_SLOW_IRQ(27);
 235 BUILD_SLOW_IRQ(28);
 236 BUILD_SLOW_IRQ(29);
 237 BUILD_SLOW_IRQ(30);
 238 BUILD_SLOW_IRQ(31);
 239 
 240 asm_irq_handler slow_handlers[32] = {
 241         atari_slow_irq_0_handler,
 242         atari_slow_irq_1_handler,
 243         atari_slow_irq_2_handler,
 244         atari_slow_irq_3_handler,
 245         atari_slow_irq_4_handler,
 246         atari_slow_irq_5_handler,
 247         atari_slow_irq_6_handler,
 248         atari_slow_irq_7_handler,
 249         atari_slow_irq_8_handler,
 250         atari_slow_irq_9_handler,
 251         atari_slow_irq_10_handler,
 252         atari_slow_irq_11_handler,
 253         atari_slow_irq_12_handler,
 254         atari_slow_irq_13_handler,
 255         atari_slow_irq_14_handler,
 256         atari_slow_irq_15_handler,
 257         atari_slow_irq_16_handler,
 258         atari_slow_irq_17_handler,
 259         atari_slow_irq_18_handler,
 260         atari_slow_irq_19_handler,
 261         atari_slow_irq_20_handler,
 262         atari_slow_irq_21_handler,
 263         atari_slow_irq_22_handler,
 264         atari_slow_irq_23_handler,
 265         atari_slow_irq_24_handler,
 266         atari_slow_irq_25_handler,
 267         atari_slow_irq_26_handler,
 268         atari_slow_irq_27_handler,
 269         atari_slow_irq_28_handler,
 270         atari_slow_irq_29_handler,
 271         atari_slow_irq_30_handler,
 272         atari_slow_irq_31_handler
 273 };
 274 
 275 asmlinkage void atari_fast_irq_handler( void );
 276 asmlinkage void atari_prio_irq_handler( void );
 277 
 278 /* Dummy function to allow asm with operands.  */
 279 void atari_fast_prio_irq_dummy (void) {
     /* [previous][next][first][last][top][bottom][index][help] */
 280 __asm__ (ALIGN_STR "\n"
 281 SYMBOL_NAME_STR(atari_fast_irq_handler) ":
 282         orw     #0x700,%%sr             /* disable all interrupts */
 283 "SYMBOL_NAME_STR(atari_prio_irq_handler) ":\t"
 284         SAVE_ALL "
 285         addql   #1,"SYMBOL_NAME_STR(intr_count)"
 286         movew   %%sp@(" FORMATVEC "),%%d0       /* get vector number from stack frame */
 287         andil   #0xfff,%%d0             /* mask off format nibble */
 288         lsrl    #2,%%d0                 /* convert vector to source */
 289         subl    #(0x40-8),%%d0
 290         jpl     1f
 291         addl    #(0x40-8-0x18),%%d0
 292 1:      lea     %a0,%%a0
 293         addql   #1,%%a0@(%%d0:l:4)
 294         lea     "SYMBOL_NAME_STR(irq_handler)",%%a0
 295         lea     %%a0@(%%d0:l:8),%%a0
 296         movel   %%a0@(4),%%sp@-         /* push handler data */
 297         pea     %%sp@(4)                /* push frame address */
 298         movel   %%d0,%%sp@-             /* push int number */
 299         movel   %%a0@,%%a0
 300         jsr     %%a0@                   /* and call the handler */
 301         addql   #8,%%sp
 302         addql   #4,%%sp
 303         jbra    "SYMBOL_NAME_STR(ret_from_interrupt)
 304          : : "i" (&kstat.interrupts)
 305 );
 306 }
 307 
 308 /* GK:
 309  * HBL IRQ handler for Falcon. Nobody needs it :-)
 310  * ++andreas: raise ipl to disable further HBLANK interrupts.
 311  */
 312 asmlinkage void falcon_hblhandler(void);
 313 asm(".text\n"
 314 ALIGN_STR "\n"
 315 SYMBOL_NAME_STR(falcon_hblhandler) ":
 316         movel   %d0,%sp@-
 317         movew   %sp@(4),%d0
 318         andw    #0xf8ff,%d0
 319         orw     #0x0200,%d0     /* set saved ipl to 2 */
 320         movew   %d0,%sp@(4)
 321         movel   %sp@+,%d0
 322         rte");
 323 
 324 /* Defined in entry.S; only increments 'num_spurious' */
 325 asmlinkage void bad_interrupt(void);
 326 
 327 extern void atari_microwire_cmd( int cmd );
 328 
 329 /*
 330  * void atari_init_INTS (void)
 331  *
 332  * Parameters:  None
 333  *
 334  * Returns:     Nothing
 335  *
 336  * This function should be called during kernel startup to initialize
 337  * the atari IRQ handling routines.
 338  */
 339 
 340 void atari_init_INTS(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 341 {
 342         int i;
 343 
 344         /* initialize the vector table */
 345         for (i = 0; i < NUM_INT_SOURCES; ++i) {
 346                 vectors[IRQ_SOURCE_TO_VECTOR(i)] = bad_interrupt;
 347         }
 348 
 349         /* Initialize the MFP(s) */
 350 
 351 #ifdef ATARI_USE_SOFTWARE_EOI
 352         mfp.vec_adr  = 0x48;    /* Software EOI-Mode */
 353 #else
 354         mfp.vec_adr  = 0x40;    /* Automatic EOI-Mode */
 355 #endif
 356         mfp.int_en_a =              /* turn off MFP-Ints */
 357         mfp.int_en_b = 0x00;
 358         mfp.int_mk_a =                  /* no Masking */
 359         mfp.int_mk_b = 0xff;
 360 
 361         if (ATARIHW_PRESENT(TT_MFP)) {
 362 #ifdef ATARI_USE_SOFTWARE_EOI
 363                 tt_mfp.vec_adr  = 0x58;         /* Software EOI-Mode */
 364 #else
 365                 tt_mfp.vec_adr  = 0x50;         /* Automatic EOI-Mode */
 366 #endif
 367                 tt_mfp.int_en_a =                       /* turn off MFP-Ints */
 368                 tt_mfp.int_en_b = 0x00;
 369                 tt_mfp.int_mk_a =                       /* no Masking */
 370                 tt_mfp.int_mk_b = 0xff;
 371         }
 372 
 373         if (ATARIHW_PRESENT(SCC)) {
 374                 scc.cha_a_ctrl = 9;
 375                 MFPDELAY();
 376                 scc.cha_a_ctrl = (char) 0xc0; /* hardware reset */
 377         }
 378 
 379         if (ATARIHW_PRESENT(SCU)) {
 380                 /* init the SCU if present */
 381                 tt_scu.sys_mask = 0x10;         /* enable VBL (for the cursor) and
 382                                                                          * disable HSYNC interrupts (who
 383                                                                          * needs them?)  MFP and SCC are
 384                                                                          * enabled in VME mask
 385                                                                          */
 386                 tt_scu.vme_mask = 0x60;         /* enable MFP and SCC ints */
 387         }
 388         else {
 389                 /* If no SCU, the HSYNC interrupt needs to be disabled this
 390                  * way. (Else _inthandler in kernel/sys_call.S gets overruns)
 391                  */
 392                 vectors[VEC_INT2] = falcon_hblhandler;
 393         }
 394 
 395         if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
 396                 /* Initialize the LM1992 Sound Controller to enable
 397                    the PSG sound.  This is misplaced here, it should
 398                    be in a atasound_init(), that doesn't exist yet. */
 399                 atari_microwire_cmd(MW_LM1992_PSG_HIGH);
 400         }
 401         
 402         stdma_init();
 403 
 404         /* Initialize the PSG: all sounds off, both ports output */
 405         sound_ym.rd_data_reg_sel = 7;
 406         sound_ym.wd_data = 0xff;
 407 }
 408 
 409 
 410 static void atari_call_isr_list( int irq, struct pt_regs *fp, void *_p )
     /* [previous][next][first][last][top][bottom][index][help] */
 411 {
 412   isr_node_t *p;
 413         
 414   for( p = (isr_node_t *)_p; p; p = p->next )
 415     p->isr( irq, fp, p->data );
 416 }
 417 
 418 
 419 /*
 420  * atari_add_isr : add an interrupt service routine for a particular
 421  *                 machine specific interrupt source.
 422  *                 If the addition was successful, it returns 1, otherwise
 423  *                 it returns 0.  It will fail if the interrupt is already
 424  *                 occupied of another handler with different type
 425  */
 426 
 427 int atari_add_isr(unsigned long source, isrfunc isr, int type, void
     /* [previous][next][first][last][top][bottom][index][help] */
 428                   *data, char *name)
 429 {
 430         int vector;
 431         
 432         source &= ~IRQ_MACHSPEC;
 433         if (type < IRQ_TYPE_SLOW || type > IRQ_TYPE_PRIO) {
 434                 printk ("atari_add_isr: Bad irq type %d requested from %s\n",
 435                                 type, name );
 436                 return( 0 );
 437         }
 438         if (!IS_VALID_INTNO(source)) {
 439                 printk ("atari_add_isr: Unknown irq %ld requested from %s\n",
 440                                 source, name );
 441                 return( 0 );
 442         }
 443         vector = IRQ_SOURCE_TO_VECTOR(source);
 444 
 445         /*
 446          * Check type/source combination: slow ints are (currently)
 447          * only possible for MFP-interrupts.
 448          */
 449         if (type == IRQ_TYPE_SLOW &&
 450                 (source < STMFP_SOURCE_BASE || source >= SCC_SOURCE_BASE)) {
 451                 printk ("atari_add_isr: Slow irq requested for non-MFP source %ld from %s\n",
 452                                 source, name );
 453                 return( 0 );
 454         }
 455                 
 456         if (vectors[vector] == bad_interrupt) {
 457                 /* int has no handler yet */
 458                 irq_handler[source].isr = isr;
 459                 irq_handler[source].data = data;
 460                 irq_param[source].type = type;
 461                 irq_param[source].name = name;
 462                 vectors[vector] =
 463                         (type == IRQ_TYPE_SLOW) ? slow_handlers[source-STMFP_SOURCE_BASE] :
 464                         (type == IRQ_TYPE_FAST) ? atari_fast_irq_handler :
 465                                                                           atari_prio_irq_handler;
 466                 /* If MFP int, also enable and umask it */
 467                 atari_turnon_irq(source);
 468                 atari_enable_irq(source);
 469 
 470                 return 1;
 471         }
 472         else if (irq_param[source].type == type) {
 473                 /* old handler is of same type -> handlers can be chained */
 474                 isr_node_t *p;
 475                 unsigned long flags;
 476 
 477                 save_flags(flags);
 478                 cli();
 479 
 480                 if (irq_handler[source].isr != atari_call_isr_list) {
 481                         /* Only one handler yet, make a node for this first one */
 482                         p = new_isr_node();
 483                         if (p == NULL) return 0;
 484                         p->isr = irq_handler[source].isr;
 485                         p->data = irq_handler[source].data;
 486                         p->name = irq_param[source].name;
 487                         p->next = NULL;
 488 
 489                         irq_handler[source].isr = atari_call_isr_list;
 490                         irq_handler[source].data = p;
 491                         irq_param[source].name = "chained";
 492                 }
 493 
 494                 p = new_isr_node();
 495                 if (p == NULL) return 0;
 496                 p->isr = isr;
 497                 p->data = data;
 498                 p->name = name;
 499                 /* new handlers are put in front of the queue */
 500                 p->next = irq_handler[source].data;
 501                 irq_handler[source].data = p;
 502 
 503                 restore_flags(flags);
 504                 return 1;
 505         }
 506         else {
 507                 printk ("atari_add_isr: Irq %ld allocated by other type int (call from %s)\n",
 508                                 source, name );
 509                 return( 0 );
 510         }
 511 }
 512 
 513 
 514 int atari_remove_isr(unsigned long source, isrfunc isr)
     /* [previous][next][first][last][top][bottom][index][help] */
 515 {
 516         unsigned long flags;
 517         int vector;
 518         isr_node_t **p, *q;
 519 
 520         source &= ~IRQ_MACHSPEC;
 521 
 522         if (!IS_VALID_INTNO(source)) {
 523                 printk("atari_remove_isr: Unknown irq %ld\n", source);
 524                 return 0;
 525         }
 526 
 527         vector = IRQ_SOURCE_TO_VECTOR(source);
 528         if (vectors[vector] == bad_interrupt)
 529                 goto not_found;
 530 
 531         save_flags(flags);
 532         cli();
 533 
 534         if (irq_handler[source].isr != atari_call_isr_list) {
 535                 /* It's the only handler for the interrupt */
 536                 if (irq_handler[source].isr != isr) {
 537                         restore_flags(flags);
 538                         goto not_found;
 539                 }
 540                 irq_handler[source].isr = NULL;
 541                 irq_handler[source].data = NULL;
 542                 irq_param[source].name = NULL;
 543                 vectors[vector] = bad_interrupt;
 544                 /* If MFP int, also disable it */
 545                 atari_disable_irq(source);
 546                 atari_turnoff_irq(source);
 547 
 548                 restore_flags(flags);
 549                 return 1;
 550         }
 551 
 552         /* The interrupt is chained, find the isr on the list */
 553         for( p = (isr_node_t **)&irq_handler[source].data; *p; p = &(*p)->next ) {
 554                 if ((*p)->isr == isr) break;
 555         }
 556         if (!*p) {
 557                 restore_flags(flags);
 558                 goto not_found;
 559         }
 560 
 561         (*p)->isr = NULL; /* Mark it as free for reallocation */
 562         *p = (*p)->next;
 563 
 564         /* If there's now only one handler, unchain the interrupt, i.e. plug in
 565          * the handler directly again and omit atari_call_isr_list */
 566         q = (isr_node_t *)irq_handler[source].data;
 567         if (q && !q->next) {
 568                 irq_handler[source].isr = q->isr;
 569                 irq_handler[source].data = q->data;
 570                 irq_param[source].name = q->name;
 571                 q->isr = NULL; /* Mark it as free for reallocation */
 572         }
 573 
 574         restore_flags(flags);
 575         return 1;
 576 
 577   not_found:
 578         printk("atari_remove_isr: isr %p not found on list!\n", isr);
 579         return 0;
 580 }
 581 
 582 
 583 /*
 584  * atari_register_vme_int() returns the number of a free interrupt vector for
 585  * hardware with a programmable int vector (probably a VME board).
 586  */
 587 
 588 unsigned long atari_register_vme_int(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 589 {
 590         unsigned long source;
 591         
 592         if (next_free_vme_vec == NUM_ATARI_SOURCES)
 593                 return 0;
 594 
 595         source = next_free_vme_vec | IRQ_MACHSPEC;
 596         next_free_vme_vec++;
 597         return source;
 598 }
 599 
 600 
 601 int atari_get_irq_list(char *buf, int len)
     /* [previous][next][first][last][top][bottom][index][help] */
 602 {
 603         int i;
 604 
 605         for (i = 0; i < NUM_INT_SOURCES; ++i) {
 606                 if (vectors[IRQ_SOURCE_TO_VECTOR(i)] == bad_interrupt)
 607                         continue;
 608                 if (i < STMFP_SOURCE_BASE)
 609                         len += sprintf(buf+len, "auto %2d: %8d ",
 610                                        i, kstat.interrupts[i]);
 611                 else
 612                         len += sprintf(buf+len, "vec $%02x: %8d ",
 613                                        IRQ_SOURCE_TO_VECTOR(i),
 614                                        kstat.interrupts[i]);
 615 
 616                 if (irq_handler[i].isr != atari_call_isr_list) {
 617                         len += sprintf(buf+len, "%s\n", irq_param[i].name);
 618                 }
 619                 else {
 620                         isr_node_t *p;
 621                         for( p = (isr_node_t *)irq_handler[i].data; p; p = p->next ) {
 622                                 len += sprintf(buf+len, "%s\n", p->name);
 623                                 if (p->next)
 624                                         len += sprintf( buf+len, "                  " );
 625                         }
 626                 }
 627         }
 628         if (num_spurious)
 629                 len += sprintf(buf+len, "spurio.: %8ld\n", num_spurious);
 630         
 631         return len;
 632 }
 633 
 634 

/* [previous][next][first][last][top][bottom][index][help] */