Annotation of Gnu-Mach/i386/i386at/gpl/linux/linux_irq.c, revision 1.1

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: 
        !            28: #include <kern/assert.h>
        !            29: 
        !            30: #include <i386/machspl.h>
        !            31: #include <i386/ipl.h>
        !            32: #include <i386/pic.h>
        !            33: 
        !            34: #define MACH_INCLUDE
        !            35: #include <linux/sched.h>
        !            36: #include <linux/interrupt.h>
        !            37: #include <linux/ptrace.h>
        !            38: #include <linux/errno.h>
        !            39: #include <linux/delay.h>
        !            40: #include <linux/kernel_stat.h>
        !            41: 
        !            42: #include <asm/system.h>
        !            43: #include <asm/bitops.h>
        !            44: #include <asm/irq.h>
        !            45: 
        !            46: /*
        !            47:  * Priority at which a Linux handler should be called.
        !            48:  * This is used at the time of an IRQ allocation.  It is
        !            49:  * set by emulation routines for each class of device.
        !            50:  */
        !            51: spl_t linux_intr_pri;
        !            52: 
        !            53: /*
        !            54:  * Flag indicating an interrupt is being handled.
        !            55:  */
        !            56: unsigned long intr_count = 0;
        !            57: 
        !            58: /*
        !            59:  * List of Linux interrupt handlers.
        !            60:  */
        !            61: static void (*linux_handlers[16])(int, struct pt_regs *);
        !            62: 
        !            63: extern spl_t curr_ipl;
        !            64: extern int curr_pic_mask;
        !            65: extern int pic_mask[];
        !            66: 
        !            67: extern int intnull(), prtnull();
        !            68: 
        !            69: /*
        !            70:  * Generic interrupt handler for Linux devices.
        !            71:  * Set up a fake `struct pt_regs' then call the real handler.
        !            72:  */
        !            73: static int
        !            74: linux_intr(irq)
        !            75:        int irq;
        !            76: {
        !            77:        struct pt_regs regs;
        !            78: 
        !            79:        kstat.interrupts[irq]++;
        !            80:        intr_count++;
        !            81:        (*linux_handlers[irq])(irq, &regs);
        !            82:        intr_count--;
        !            83: }
        !            84: 
        !            85: /*
        !            86:  * Mask an IRQ.
        !            87:  */
        !            88: void
        !            89: disable_irq(irq)
        !            90:        unsigned int irq;
        !            91: {
        !            92:        int i, flags;
        !            93: 
        !            94:        assert (irq < NR_IRQS);
        !            95: 
        !            96:        save_flags(flags);
        !            97:        cli();
        !            98:        for (i = 0; i < intpri[irq]; i++)
        !            99:                pic_mask[i] |= 1 << irq;
        !           100:        if (curr_pic_mask != pic_mask[curr_ipl]) {
        !           101:                curr_pic_mask = pic_mask[curr_ipl];
        !           102:                outb(PIC_MASTER_OCW, curr_pic_mask);
        !           103:                outb(PIC_SLAVE_OCW, curr_pic_mask >> 8);
        !           104:        }
        !           105:        restore_flags(flags);
        !           106: }
        !           107: 
        !           108: /*
        !           109:  * Unmask an IRQ.
        !           110:  */
        !           111: void
        !           112: enable_irq(irq)
        !           113:        unsigned int irq;
        !           114: {
        !           115:        int mask, i, flags;
        !           116: 
        !           117:        assert (irq < NR_IRQS);
        !           118: 
        !           119:        mask = 1 << irq;
        !           120:        if (irq >= 8)
        !           121:                mask |= 1 << 2;
        !           122:        save_flags(flags);
        !           123:        cli();
        !           124:        for (i = 0; i < intpri[irq]; i++)
        !           125:                pic_mask[i] &= ~mask;
        !           126:        if (curr_pic_mask != pic_mask[curr_ipl]) {
        !           127:                curr_pic_mask = pic_mask[curr_ipl];
        !           128:                outb(PIC_MASTER_OCW, curr_pic_mask);
        !           129:                outb(PIC_SLAVE_OCW, curr_pic_mask >> 8);
        !           130:        }
        !           131:        restore_flags(flags);
        !           132: }
        !           133: 
        !           134: /*
        !           135:  * Attach a handler to an IRQ.
        !           136:  */
        !           137: int
        !           138: request_irq(unsigned int irq, void (*handler)(int, struct pt_regs *),
        !           139:            unsigned long flags, const char *device)
        !           140: {
        !           141:        assert(irq < 16);
        !           142: 
        !           143:        if (ivect[irq] == intnull || ivect[irq] == prtnull) {
        !           144:                if (!handler)
        !           145:                        return (-LINUX_EINVAL);
        !           146:                linux_handlers[irq] = handler;
        !           147:                ivect[irq] = linux_intr;
        !           148:                iunit[irq] = irq;
        !           149:                intpri[irq] = linux_intr_pri;
        !           150:                enable_irq(irq);
        !           151:                return (0);
        !           152:        }
        !           153:        return (-LINUX_EBUSY);
        !           154: }
        !           155: 
        !           156: /*
        !           157:  * Deallocate an irq.
        !           158:  */
        !           159: void
        !           160: free_irq(unsigned int irq)
        !           161: {
        !           162:        if (irq > 15)
        !           163:                panic("free_irq: bad irq number");
        !           164: 
        !           165:        disable_irq(irq);
        !           166:        ivect[irq] = (irq == 7) ? prtnull : intnull;
        !           167:        iunit[irq] = irq;
        !           168:        intpri[irq] = SPL0;
        !           169: }
        !           170: 
        !           171: /*
        !           172:  * IRQ probe interrupt handler.
        !           173:  */
        !           174: void
        !           175: probe_intr(irq)
        !           176:        int irq;
        !           177: {
        !           178:        disable_irq(irq);
        !           179: }
        !           180: 
        !           181: /*
        !           182:  * Set for an irq probe.
        !           183:  */
        !           184: unsigned long
        !           185: probe_irq_on()
        !           186: {
        !           187:        unsigned i, irqs = 0;
        !           188:        unsigned long delay;
        !           189: 
        !           190:        assert (curr_ipl == 0);
        !           191: 
        !           192:        /*
        !           193:         * Allocate all available IRQs.
        !           194:         */
        !           195:        for (i = 15; i > 0; i--)
        !           196:                if (request_irq(i, probe_intr, 0, "probe") == 0)
        !           197:                        irqs |= 1 << i;
        !           198: 
        !           199:        /*
        !           200:         * Wait for spurious interrupts to mask themselves out.
        !           201:         */
        !           202:        for (delay = jiffies + 2; delay > jiffies; )
        !           203:                ;
        !           204: 
        !           205:        /*
        !           206:         * Free IRQs that caused spurious interrupts.
        !           207:         */
        !           208:        for (i = 15; i > 0; i--) {
        !           209:                if (irqs & (1 << i) & pic_mask[0]) {
        !           210:                        irqs ^= 1 << i;
        !           211:                        free_irq(i);
        !           212:                }
        !           213:        }
        !           214: 
        !           215:        return (irqs);
        !           216: }
        !           217: 
        !           218: /*
        !           219:  * Return the result of an irq probe.
        !           220:  */
        !           221: int
        !           222: probe_irq_off(unsigned long irqs)
        !           223: {
        !           224:        unsigned i, irqs_save = irqs;
        !           225: 
        !           226:        assert (curr_ipl == 0);
        !           227: 
        !           228:        irqs &= pic_mask[0];
        !           229: 
        !           230:        /*
        !           231:         * Deallocate IRQs.
        !           232:         */
        !           233:        for (i = 15; i > 0; i--)
        !           234:                if (irqs_save & (1 << i))
        !           235:                        free_irq(i);
        !           236: 
        !           237:        /*
        !           238:         * Return IRQ number.
        !           239:         */
        !           240:        if (!irqs)
        !           241:                return (0);
        !           242:        i = ffz(~irqs);
        !           243:        if (irqs != (irqs & (1 << i)))
        !           244:                i = -i;
        !           245:        return (i);
        !           246: }

unix.superglobalmegacorp.com

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