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

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);
1.1.1.3 ! root      698:   outb_p (latch & 0xff, PITCTR0_PORT);
1.1       root      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.