Annotation of Gnu-Mach/linux/dev/arch/i386/kernel/irq.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * Linux IRQ management.
                      3:  * Copyright (C) 1995 Shantanu Goel.
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify
                      6:  * it under the terms of the GNU General Public License as published by
                      7:  * the Free Software Foundation; either version 2, or (at your option)
                      8:  * any later version.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful,
                     11:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     12:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     13:  * GNU General Public License for more details.
                     14:  *
                     15:  * You should have received a copy of the GNU General Public License
                     16:  * along with this program; if not, write to the Free Software
                     17:  * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
                     18:  */
                     19: 
                     20: /*
                     21:  *    linux/arch/i386/kernel/irq.c
                     22:  *
                     23:  *      Copyright (C) 1992 Linus Torvalds
                     24:  */
                     25: 
                     26: #include <sys/types.h>
                     27: #include <mach/mach_types.h>
                     28: #include <mach/vm_param.h>
                     29: #include <kern/assert.h>
                     30: 
                     31: #include <i386/spl.h>
                     32: #include <i386/pic.h>
                     33: #include <i386/pit.h>
                     34: 
                     35: #define MACH_INCLUDE
                     36: #include <linux/mm.h>
                     37: #include <linux/interrupt.h>
                     38: #include <linux/ptrace.h>
                     39: #include <linux/delay.h>
                     40: #include <linux/kernel_stat.h>
                     41: #include <linux/malloc.h>
                     42: #include <linux/ioport.h>
                     43: 
                     44: #include <asm/system.h>
                     45: #include <asm/bitops.h>
                     46: #include <asm/irq.h>
                     47: #include <asm/io.h>
1.1.1.2 ! root       48: #include <asm/hardirq.h>
1.1       root       49: 
1.1.1.2 ! root       50: #include <linux/dev/glue/glue.h>
        !            51: #include <machine/machspl.h>
        !            52: 
        !            53: #if 0
        !            54: /* XXX: This is the way it's done in linux 2.2. GNU Mach currently uses intr_count. It should be made using local_{bh/irq}_count instead (through hardirq_enter/exit) for SMP support. */
        !            55: unsigned int local_bh_count[NR_CPUS];
        !            56: unsigned int local_irq_count[NR_CPUS];
        !            57: #endif
1.1       root       58: 
                     59: /*
                     60:  * XXX Move this into more suitable place...
                     61:  * Set if the machine has an EISA bus.
                     62:  */
                     63: int EISA_bus = 0;
                     64: 
                     65: /*
                     66:  * Priority at which a Linux handler should be called.
                     67:  * This is used at the time of an IRQ allocation.  It is
                     68:  * set by emulation routines for each class of device.
                     69:  */
                     70: spl_t linux_intr_pri;
                     71: 
                     72: /*
                     73:  * Flag indicating an interrupt is being handled.
                     74:  */
1.1.1.2 ! root       75: unsigned int intr_count = 0;
1.1       root       76: 
                     77: /*
                     78:  * List of Linux interrupt handlers.
                     79:  */
                     80: struct linux_action
                     81: {
                     82:   void (*handler) (int, void *, struct pt_regs *);
                     83:   void *dev_id;
                     84:   struct linux_action *next;
                     85:   unsigned long flags;
                     86: };
                     87: 
                     88: static struct linux_action *irq_action[16] =
                     89: {
                     90:   NULL, NULL, NULL, NULL,
                     91:   NULL, NULL, NULL, NULL,
                     92:   NULL, NULL, NULL, NULL,
                     93:   NULL, NULL, NULL, NULL
                     94: };
                     95: 
                     96: /*
                     97:  * Generic interrupt handler for Linux devices.
                     98:  * Set up a fake `struct pt_regs' then call the real handler.
                     99:  */
1.1.1.2 ! root      100: static void
1.1       root      101: linux_intr (int irq)
                    102: {
                    103:   struct pt_regs regs;
                    104:   struct linux_action *action = *(irq_action + irq);
1.1.1.2 ! root      105:   unsigned long flags;
1.1       root      106: 
                    107:   kstat.interrupts[irq]++;
                    108:   intr_count++;
                    109: 
1.1.1.2 ! root      110:   save_flags (flags);
        !           111:   if (action && (action->flags & SA_INTERRUPT))
        !           112:     cli ();
        !           113: 
1.1       root      114:   while (action)
                    115:     {
                    116:       action->handler (irq, action->dev_id, &regs);
                    117:       action = action->next;
                    118:     }
                    119: 
1.1.1.2 ! root      120:   restore_flags (flags);
1.1       root      121: 
1.1.1.2 ! root      122:   intr_count--;
1.1       root      123: }
                    124: 
                    125: /*
                    126:  * Mask an IRQ.
                    127:  */
                    128: static inline void
                    129: mask_irq (unsigned int irq_nr)
                    130: {
                    131:   int i;
                    132: 
                    133:   for (i = 0; i < intpri[irq_nr]; i++)
                    134:     pic_mask[i] |= 1 << irq_nr;
                    135: 
                    136:   if (curr_pic_mask != pic_mask[curr_ipl])
                    137:     {
                    138:       curr_pic_mask = pic_mask[curr_ipl];
                    139:       if (irq_nr < 8)
                    140:        outb (curr_pic_mask & 0xff, PIC_MASTER_OCW);
                    141:       else
                    142:        outb (curr_pic_mask >> 8, PIC_SLAVE_OCW);
                    143:     }
                    144: }
                    145: 
                    146: /*
                    147:  * Unmask an IRQ.
                    148:  */
                    149: static inline void
                    150: unmask_irq (unsigned int irq_nr)
                    151: {
                    152:   int mask, i;
                    153: 
                    154:   mask = 1 << irq_nr;
                    155:   if (irq_nr >= 8)
                    156:     mask |= 1 << 2;
                    157: 
                    158:   for (i = 0; i < intpri[irq_nr]; i++)
                    159:     pic_mask[i] &= ~mask;
                    160: 
                    161:   if (curr_pic_mask != pic_mask[curr_ipl])
                    162:     {
                    163:       curr_pic_mask = pic_mask[curr_ipl];
                    164:       if (irq_nr < 8)
                    165:        outb (curr_pic_mask & 0xff, PIC_MASTER_OCW);
                    166:       else
                    167:        outb (curr_pic_mask >> 8, PIC_SLAVE_OCW);
                    168:     }
                    169: }
                    170: 
                    171: void
                    172: disable_irq (unsigned int irq_nr)
                    173: {
                    174:   unsigned long flags;
                    175: 
                    176:   assert (irq_nr < NR_IRQS);
                    177: 
                    178:   save_flags (flags);
                    179:   cli ();
                    180:   mask_irq (irq_nr);
                    181:   restore_flags (flags);
                    182: }
                    183: 
                    184: void
                    185: enable_irq (unsigned int irq_nr)
                    186: {
                    187:   unsigned long flags;
                    188: 
                    189:   assert (irq_nr < NR_IRQS);
                    190: 
                    191:   save_flags (flags);
                    192:   cli ();
                    193:   unmask_irq (irq_nr);
                    194:   restore_flags (flags);
                    195: }
                    196: 
                    197: /*
                    198:  * Default interrupt handler for Linux.
                    199:  */
1.1.1.2 ! root      200: void
1.1       root      201: linux_bad_intr (int irq)
                    202: {
                    203:   mask_irq (irq);
                    204: }
                    205: 
                    206: static int
                    207: setup_x86_irq (int irq, struct linux_action *new)
                    208: {
                    209:   int shared = 0;
                    210:   struct linux_action *old, **p;
                    211:   unsigned long flags;
                    212: 
                    213:   p = irq_action + irq;
                    214:   if ((old = *p) != NULL)
                    215:     {
                    216:       /* Can't share interrupts unless both agree to */
                    217:       if (!(old->flags & new->flags & SA_SHIRQ))
1.1.1.2 ! root      218:        return (-EBUSY);
1.1       root      219: 
                    220:       /* Can't share interrupts unless both are same type */
                    221:       if ((old->flags ^ new->flags) & SA_INTERRUPT)
1.1.1.2 ! root      222:        return (-EBUSY);
        !           223: 
        !           224:       /* Can't share at different levels */
        !           225:       if (intpri[irq] && linux_intr_pri != intpri[irq])
        !           226:        return (-EBUSY);
1.1       root      227: 
                    228:       /* add new interrupt at end of irq queue */
                    229:       do
                    230:        {
                    231:          p = &old->next;
                    232:          old = *p;
                    233:        }
                    234:       while (old);
                    235:       shared = 1;
                    236:     }
                    237: 
                    238:   save_flags (flags);
                    239:   cli ();
                    240:   *p = new;
                    241: 
                    242:   if (!shared)
                    243:     {
                    244:       ivect[irq] = linux_intr;
                    245:       iunit[irq] = irq;
                    246:       intpri[irq] = linux_intr_pri;
                    247:       unmask_irq (irq);
                    248:     }
                    249:   restore_flags (flags);
                    250:   return 0;
                    251: }
                    252: 
                    253: /*
                    254:  * Attach a handler to an IRQ.
                    255:  */
                    256: int
                    257: request_irq (unsigned int irq, void (*handler) (int, void *, struct pt_regs *),
                    258:             unsigned long flags, const char *device, void *dev_id)
                    259: {
                    260:   struct linux_action *action;
                    261:   int retval;
                    262: 
                    263:   assert (irq < 16);
                    264: 
                    265:   if (!handler)
1.1.1.2 ! root      266:     return -EINVAL;
1.1       root      267:   
                    268:   /*
                    269:    * Hmm... Should I use `kalloc()' ?
                    270:    * By OKUJI Yoshinori.
                    271:    */
                    272:   action = (struct linux_action *)
                    273:     linux_kmalloc (sizeof (struct linux_action), GFP_KERNEL);
                    274:   if (action == NULL)
1.1.1.2 ! root      275:     return -ENOMEM;
1.1       root      276:   
                    277:   action->handler = handler;
                    278:   action->next = NULL;
                    279:   action->dev_id = dev_id;
                    280:   action->flags = flags;
                    281:   
                    282:   retval = setup_x86_irq (irq, action);
                    283:   if (retval)
                    284:     linux_kfree (action);
                    285:   
                    286:   return retval;
                    287: }
                    288: 
                    289: /*
                    290:  * Deallocate an irq.
                    291:  */
                    292: void
                    293: free_irq (unsigned int irq, void *dev_id)
                    294: {
                    295:   struct linux_action *action, **p;
                    296:   unsigned long flags;
                    297: 
                    298:   if (irq > 15)
                    299:     panic ("free_irq: bad irq number");
                    300: 
                    301:   for (p = irq_action + irq; (action = *p) != NULL; p = &action->next)
                    302:     {
                    303:       if (action->dev_id != dev_id)
                    304:        continue;
                    305: 
                    306:       save_flags (flags);
                    307:       cli ();
                    308:       *p = action->next;
                    309:       if (!irq_action[irq])
                    310:        {
                    311:          mask_irq (irq);
                    312:          ivect[irq] = linux_bad_intr;
                    313:          iunit[irq] = irq;
                    314:          intpri[irq] = SPL0;
                    315:        }
                    316:       restore_flags (flags);
                    317:       linux_kfree (action);
                    318:       return;
                    319:     }
                    320: 
                    321:   panic ("free_irq: bad irq number");
                    322: }
                    323: 
                    324: /*
                    325:  * Set for an irq probe.
                    326:  */
                    327: unsigned long
                    328: probe_irq_on (void)
                    329: {
                    330:   unsigned i, irqs = 0;
                    331:   unsigned long delay;
                    332: 
                    333:   assert (curr_ipl == 0);
                    334: 
                    335:   /*
                    336:    * Allocate all available IRQs.
                    337:    */
                    338:   for (i = 15; i > 0; i--)
                    339:     {
                    340:       if (!irq_action[i] && ivect[i] == linux_bad_intr)
                    341:        {
                    342:          intpri[i] = linux_intr_pri;
                    343:          enable_irq (i);
                    344:          irqs |= 1 << i;
                    345:        }
                    346:     }
                    347: 
                    348:   /*
                    349:    * Wait for spurious interrupts to mask themselves out.
                    350:    */
                    351:   for (delay = jiffies + HZ / 10; delay > jiffies;)
                    352:     ;
                    353: 
                    354:   return (irqs & ~curr_pic_mask);
                    355: }
                    356: 
                    357: /*
                    358:  * Return the result of an irq probe.
                    359:  */
                    360: int
                    361: probe_irq_off (unsigned long irqs)
                    362: {
                    363:   unsigned int i;
                    364: 
                    365:   assert (curr_ipl == 0);
                    366: 
                    367:   irqs &= curr_pic_mask;
                    368: 
                    369:   /*
                    370:    * Disable unnecessary IRQs.
                    371:    */
                    372:   for (i = 15; i > 0; i--)
                    373:     {
                    374:       if (!irq_action[i] && ivect[i] == linux_bad_intr)
                    375:        {
                    376:          disable_irq (i);
                    377:          intpri[i] = SPL0;
                    378:        }
                    379:     }
                    380:   
                    381:   /*
                    382:    * Return IRQ number.
                    383:    */
                    384:   if (!irqs)
                    385:     return 0;
                    386:   i = ffz (~irqs);
                    387:   if (irqs != (irqs & (1 << i)))
                    388:     i = -i;
                    389:   return i;
                    390: }
                    391: 
                    392: /*
                    393:  * Reserve IRQs used by Mach drivers.
                    394:  * Must be called before Linux IRQ detection, after Mach IRQ detection.
                    395:  */
                    396: static void
                    397: reserve_mach_irqs (void)
                    398: {
                    399:   unsigned int i;
                    400: 
                    401:   for (i = 0; i < 16; i++)
                    402:     {
                    403:       if (ivect[i] != prtnull && ivect[i] != intnull)
                    404:        /* Set non-NULL value. */
                    405:        irq_action[i] = (struct linux_action *) -1;
                    406:     }
                    407: }
                    408: 
1.1.1.2 ! root      409: #ifdef __SMP__
        !           410: unsigned char global_irq_holder = NO_PROC_ID;
        !           411: unsigned volatile int global_irq_lock;
        !           412: atomic_t global_irq_count;
        !           413: 
        !           414: atomic_t global_bh_count;
        !           415: atomic_t global_bh_lock;
        !           416: 
        !           417: /*
        !           418:  * "global_cli()" is a special case, in that it can hold the
        !           419:  * interrupts disabled for a longish time, and also because
        !           420:  * we may be doing TLB invalidates when holding the global
        !           421:  * IRQ lock for historical reasons. Thus we may need to check
        !           422:  * SMP invalidate events specially by hand here (but not in
        !           423:  * any normal spinlocks)
        !           424:  */
        !           425: #if 0
        !           426: /* XXX: check how Mach handles this */
        !           427: static inline void check_smp_invalidate(int cpu)
        !           428: {
        !           429:        if (test_bit(cpu, &smp_invalidate_needed)) {
        !           430:                clear_bit(cpu, &smp_invalidate_needed);
        !           431:                local_flush_tlb();
        !           432:        }
        !           433: }
        !           434: #endif
        !           435: 
        !           436: static void show(char * str)
        !           437: {
        !           438:        int i;
        !           439:        unsigned long *stack;
        !           440:        int cpu = smp_processor_id();
        !           441: 
        !           442:        printk("\n%s, CPU %d:\n", str, cpu);
        !           443:        printk("irq:  %d [%d %d]\n",
        !           444:                atomic_read(&global_irq_count), local_irq_count[0], local_irq_count[1]);
        !           445:        printk("bh:   %d [%d %d]\n",
        !           446:                atomic_read(&global_bh_count), local_bh_count[0], local_bh_count[1]);
        !           447:        stack = (unsigned long *) &stack;
        !           448:        for (i = 40; i ; i--) {
        !           449:                unsigned long x = *++stack;
        !           450:                //if (x > (unsigned long) &get_options && x < (unsigned long) &vsprintf) {
        !           451:                        printk("<[%08lx]> ", x);
        !           452:                //}
        !           453:        }
        !           454: }
        !           455:        
        !           456: #define MAXCOUNT 100000000
        !           457: 
        !           458: static inline void wait_on_bh(void)
        !           459: {
        !           460:        int count = MAXCOUNT;
        !           461:        do {
        !           462:                if (!--count) {
        !           463:                        show("wait_on_bh");
        !           464:                        count = ~0;
        !           465:                }
        !           466:                /* nothing .. wait for the other bh's to go away */
        !           467:        } while (atomic_read(&global_bh_count) != 0);
        !           468: }
        !           469: 
        !           470: /*
        !           471:  * I had a lockup scenario where a tight loop doing
        !           472:  * spin_unlock()/spin_lock() on CPU#1 was racing with
        !           473:  * spin_lock() on CPU#0. CPU#0 should have noticed spin_unlock(), but
        !           474:  * apparently the spin_unlock() information did not make it
        !           475:  * through to CPU#0 ... nasty, is this by design, do we have to limit
        !           476:  * 'memory update oscillation frequency' artificially like here?
        !           477:  *
        !           478:  * Such 'high frequency update' races can be avoided by careful design, but
        !           479:  * some of our major constructs like spinlocks use similar techniques,
        !           480:  * it would be nice to clarify this issue. Set this define to 0 if you
        !           481:  * want to check whether your system freezes.  I suspect the delay done
        !           482:  * by SYNC_OTHER_CORES() is in correlation with 'snooping latency', but
        !           483:  * i thought that such things are guaranteed by design, since we use
        !           484:  * the 'LOCK' prefix.
        !           485:  */
        !           486: #define SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND 1
        !           487: 
        !           488: #if SUSPECTED_CPU_OR_CHIPSET_BUG_WORKAROUND
        !           489: # define SYNC_OTHER_CORES(x) udelay(x+1)
        !           490: #else
        !           491: /*
        !           492:  * We have to allow irqs to arrive between __sti and __cli
        !           493:  */
        !           494: # define SYNC_OTHER_CORES(x) __asm__ __volatile__ ("nop")
        !           495: #endif
        !           496: 
        !           497: static inline void wait_on_irq(int cpu)
        !           498: {
        !           499:        int count = MAXCOUNT;
        !           500: 
        !           501:        for (;;) {
        !           502: 
        !           503:                /*
        !           504:                 * Wait until all interrupts are gone. Wait
        !           505:                 * for bottom half handlers unless we're
        !           506:                 * already executing in one..
        !           507:                 */
        !           508:                if (!atomic_read(&global_irq_count)) {
        !           509:                        if (local_bh_count[cpu] || !atomic_read(&global_bh_count))
        !           510:                                break;
        !           511:                }
        !           512: 
        !           513:                /* Duh, we have to loop. Release the lock to avoid deadlocks */
        !           514:                clear_bit(0,&global_irq_lock);
        !           515: 
        !           516:                for (;;) {
        !           517:                        if (!--count) {
        !           518:                                show("wait_on_irq");
        !           519:                                count = ~0;
        !           520:                        }
        !           521:                        __sti();
        !           522:                        SYNC_OTHER_CORES(cpu);
        !           523:                        __cli();
        !           524:                        //check_smp_invalidate(cpu);
        !           525:                        if (atomic_read(&global_irq_count))
        !           526:                                continue;
        !           527:                        if (global_irq_lock)
        !           528:                                continue;
        !           529:                        if (!local_bh_count[cpu] && atomic_read(&global_bh_count))
        !           530:                                continue;
        !           531:                        if (!test_and_set_bit(0,&global_irq_lock))
        !           532:                                break;
        !           533:                }
        !           534:        }
        !           535: }
        !           536: 
        !           537: /*
        !           538:  * This is called when we want to synchronize with
        !           539:  * bottom half handlers. We need to wait until
        !           540:  * no other CPU is executing any bottom half handler.
        !           541:  *
        !           542:  * Don't wait if we're already running in an interrupt
        !           543:  * context or are inside a bh handler. 
        !           544:  */
        !           545: void synchronize_bh(void)
        !           546: {
        !           547:        if (atomic_read(&global_bh_count) && !in_interrupt())
        !           548:                wait_on_bh();
        !           549: }
        !           550: 
        !           551: /*
        !           552:  * This is called when we want to synchronize with
        !           553:  * interrupts. We may for example tell a device to
        !           554:  * stop sending interrupts: but to make sure there
        !           555:  * are no interrupts that are executing on another
        !           556:  * CPU we need to call this function.
        !           557:  */
        !           558: void synchronize_irq(void)
        !           559: {
        !           560:        if (atomic_read(&global_irq_count)) {
        !           561:                /* Stupid approach */
        !           562:                cli();
        !           563:                sti();
        !           564:        }
        !           565: }
        !           566: 
        !           567: static inline void get_irqlock(int cpu)
        !           568: {
        !           569:        if (test_and_set_bit(0,&global_irq_lock)) {
        !           570:                /* do we already hold the lock? */
        !           571:                if ((unsigned char) cpu == global_irq_holder)
        !           572:                        return;
        !           573:                /* Uhhuh.. Somebody else got it. Wait.. */
        !           574:                do {
        !           575:                        do {
        !           576:                                //check_smp_invalidate(cpu);
        !           577:                        } while (test_bit(0,&global_irq_lock));
        !           578:                } while (test_and_set_bit(0,&global_irq_lock));         
        !           579:        }
        !           580:        /* 
        !           581:         * We also to make sure that nobody else is running
        !           582:         * in an interrupt context. 
        !           583:         */
        !           584:        wait_on_irq(cpu);
        !           585: 
        !           586:        /*
        !           587:         * Ok, finally..
        !           588:         */
        !           589:        global_irq_holder = cpu;
        !           590: }
        !           591: 
        !           592: #define EFLAGS_IF_SHIFT 9
        !           593: 
        !           594: /*
        !           595:  * A global "cli()" while in an interrupt context
        !           596:  * turns into just a local cli(). Interrupts
        !           597:  * should use spinlocks for the (very unlikely)
        !           598:  * case that they ever want to protect against
        !           599:  * each other.
        !           600:  *
        !           601:  * If we already have local interrupts disabled,
        !           602:  * this will not turn a local disable into a
        !           603:  * global one (problems with spinlocks: this makes
        !           604:  * save_flags+cli+sti usable inside a spinlock).
        !           605:  */
        !           606: void __global_cli(void)
        !           607: {
        !           608:        unsigned int flags;
        !           609: 
        !           610:        __save_flags(flags);
        !           611:        if (flags & (1 << EFLAGS_IF_SHIFT)) {
        !           612:                int cpu = smp_processor_id();
        !           613:                __cli();
        !           614:                if (!local_irq_count[cpu])
        !           615:                        get_irqlock(cpu);
        !           616:        }
        !           617: }
        !           618: 
        !           619: void __global_sti(void)
        !           620: {
        !           621:        int cpu = smp_processor_id();
        !           622: 
        !           623:        if (!local_irq_count[cpu])
        !           624:                release_irqlock(cpu);
        !           625:        __sti();
        !           626: }
        !           627: 
        !           628: /*
        !           629:  * SMP flags value to restore to:
        !           630:  * 0 - global cli
        !           631:  * 1 - global sti
        !           632:  * 2 - local cli
        !           633:  * 3 - local sti
        !           634:  */
        !           635: unsigned long __global_save_flags(void)
        !           636: {
        !           637:        int retval;
        !           638:        int local_enabled;
        !           639:        unsigned long flags;
        !           640: 
        !           641:        __save_flags(flags);
        !           642:        local_enabled = (flags >> EFLAGS_IF_SHIFT) & 1;
        !           643:        /* default to local */
        !           644:        retval = 2 + local_enabled;
        !           645: 
        !           646:        /* check for global flags if we're not in an interrupt */
        !           647:        if (!local_irq_count[smp_processor_id()]) {
        !           648:                if (local_enabled)
        !           649:                        retval = 1;
        !           650:                if (global_irq_holder == (unsigned char) smp_processor_id())
        !           651:                        retval = 0;
        !           652:        }
        !           653:        return retval;
        !           654: }
        !           655: 
        !           656: void __global_restore_flags(unsigned long flags)
        !           657: {
        !           658:        switch (flags) {
        !           659:        case 0:
        !           660:                __global_cli();
        !           661:                break;
        !           662:        case 1:
        !           663:                __global_sti();
        !           664:                break;
        !           665:        case 2:
        !           666:                __cli();
        !           667:                break;
        !           668:        case 3:
        !           669:                __sti();
        !           670:                break;
        !           671:        default:
        !           672:                printk("global_restore_flags: %08lx (%08lx)\n",
        !           673:                        flags, (&flags)[-1]);
        !           674:        }
        !           675: }
        !           676: 
        !           677: #endif
        !           678: 
        !           679: static void (*old_clock_handler) ();
1.1       root      680: static int old_clock_pri;
                    681: 
                    682: void
                    683: init_IRQ (void)
                    684: {
                    685:   int i;
                    686:   char *p;
                    687:   int latch = (CLKNUM + hz / 2) / hz;
                    688:   
                    689:   /*
                    690:    * Ensure interrupts are disabled.
                    691:    */
                    692:   (void) splhigh ();
                    693:   
                    694:   /*
                    695:    * Program counter 0 of 8253 to interrupt hz times per second.
                    696:    */
                    697:   outb_p (PIT_C0 | PIT_SQUAREMODE | PIT_READMODE, PITCTL_PORT);
                    698:   outb_p (latch && 0xff, PITCTR0_PORT);
                    699:   outb (latch >> 8, PITCTR0_PORT);
                    700:   
                    701:   /*
                    702:    * Install our clock interrupt handler.
                    703:    */
                    704:   old_clock_handler = ivect[0];
                    705:   old_clock_pri = intpri[0];
                    706:   ivect[0] = linux_timer_intr;
                    707:   intpri[0] = SPLHI;
                    708: 
                    709:   reserve_mach_irqs ();
                    710: 
                    711:   for (i = 1; i < 16; i++)
                    712:     {
                    713:       /*
                    714:        * irq2 and irq13 should be igonored.
                    715:        */
                    716:       if (i == 2 || i == 13)
                    717:        continue;
                    718:       if (ivect[i] == prtnull || ivect[i] == intnull)
                    719:        {
                    720:           ivect[i] = linux_bad_intr;
                    721:           iunit[i] = i;
                    722:           intpri[i] = SPL0;
                    723:        }
                    724:     }
                    725:   
                    726:   form_pic_mask ();
                    727:   
                    728:   /*
                    729:    * Enable interrupts.
                    730:    */
                    731:   (void) spl0 ();
                    732:   
                    733:   /*
                    734:    * Check if the machine has an EISA bus.
                    735:    */
                    736:   p = (char *) 0x0FFFD9;
                    737:   if (*p++ == 'E' && *p++ == 'I' && *p++ == 'S' && *p == 'A')
                    738:     EISA_bus = 1;
                    739:   
                    740:   /*
                    741:    * Permanently allocate standard device ports.
                    742:    */
                    743:   request_region (0x00, 0x20, "dma1");
                    744:   request_region (0x20, 0x20, "pic1");
                    745:   request_region (0x40, 0x20, "timer");
                    746:   request_region (0x70, 0x10, "rtc");
                    747:   request_region (0x80, 0x20, "dma page reg");
                    748:   request_region (0xa0, 0x20, "pic2");
                    749:   request_region (0xc0, 0x20, "dma2");
                    750:   request_region (0xf0, 0x10, "npu");
                    751: }
                    752: 
                    753: void
                    754: restore_IRQ (void)
                    755: {
                    756:   /*
                    757:    * Disable interrupts.
                    758:    */
                    759:   (void) splhigh ();
                    760:   
                    761:   /*
                    762:    * Restore clock interrupt handler.
                    763:    */
                    764:   ivect[0] = old_clock_handler;
                    765:   intpri[0] = old_clock_pri;
                    766:   form_pic_mask ();
                    767: }
                    768:   

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.