[BACK]Return to sio_pic.c CVS log [TXT][DIR] Up to [local] / sys / arch / alpha / pci

Annotation of sys/arch/alpha/pci/sio_pic.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: sio_pic.c,v 1.26 2006/06/15 20:08:29 brad Exp $       */
        !             2: /* $NetBSD: sio_pic.c,v 1.28 2000/06/06 03:10:13 thorpej Exp $ */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
        !             6:  * All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to The NetBSD Foundation
        !             9:  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
        !            10:  * NASA Ames Research Center.
        !            11:  *
        !            12:  * Redistribution and use in source and binary forms, with or without
        !            13:  * modification, are permitted provided that the following conditions
        !            14:  * are met:
        !            15:  * 1. Redistributions of source code must retain the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer.
        !            17:  * 2. Redistributions in binary form must reproduce the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer in the
        !            19:  *    documentation and/or other materials provided with the distribution.
        !            20:  * 3. All advertising materials mentioning features or use of this software
        !            21:  *    must display the following acknowledgement:
        !            22:  *     This product includes software developed by the NetBSD
        !            23:  *     Foundation, Inc. and its contributors.
        !            24:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            25:  *    contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            29:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            30:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            31:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            32:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            33:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            34:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            35:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            36:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            37:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            38:  * POSSIBILITY OF SUCH DAMAGE.
        !            39:  */
        !            40:
        !            41: /*
        !            42:  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
        !            43:  * All rights reserved.
        !            44:  *
        !            45:  * Author: Chris G. Demetriou
        !            46:  *
        !            47:  * Permission to use, copy, modify and distribute this software and
        !            48:  * its documentation is hereby granted, provided that both the copyright
        !            49:  * notice and this permission notice appear in all copies of the
        !            50:  * software, derivative works or modified versions, and any portions
        !            51:  * thereof, and that both notices appear in supporting documentation.
        !            52:  *
        !            53:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
        !            54:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
        !            55:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            56:  *
        !            57:  * Carnegie Mellon requests users of this software to return to
        !            58:  *
        !            59:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
        !            60:  *  School of Computer Science
        !            61:  *  Carnegie Mellon University
        !            62:  *  Pittsburgh PA 15213-3890
        !            63:  *
        !            64:  * any improvements or extensions that they make and grant Carnegie the
        !            65:  * rights to redistribute these changes.
        !            66:  */
        !            67:
        !            68: #include <sys/param.h>
        !            69: #include <sys/systm.h>
        !            70:
        !            71: #include <sys/device.h>
        !            72: #include <sys/malloc.h>
        !            73: #include <sys/syslog.h>
        !            74:
        !            75: #include <machine/intr.h>
        !            76: #include <machine/bus.h>
        !            77:
        !            78: #include <dev/pci/pcireg.h>
        !            79: #include <dev/pci/pcivar.h>
        !            80: #include <dev/pci/pcidevs.h>
        !            81:
        !            82: #include <dev/pci/cy82c693reg.h>
        !            83: #include <dev/pci/cy82c693var.h>
        !            84:
        !            85: #include <dev/isa/isareg.h>
        !            86: #include <dev/isa/isavar.h>
        !            87: #include <alpha/pci/siovar.h>
        !            88:
        !            89: #include "sio.h"
        !            90:
        !            91: /*
        !            92:  * To add to the long history of wonderful PROM console traits,
        !            93:  * AlphaStation PROMs don't reset themselves completely on boot!
        !            94:  * Therefore, if an interrupt was turned on when the kernel was
        !            95:  * started, we're not going to EVER turn it off...  I don't know
        !            96:  * what will happen if new interrupts (that the PROM console doesn't
        !            97:  * want) are turned on.  I'll burn that bridge when I come to it.
        !            98:  */
        !            99: #define        BROKEN_PROM_CONSOLE
        !           100:
        !           101: /*
        !           102:  * Private functions and variables.
        !           103:  */
        !           104:
        !           105: bus_space_tag_t sio_iot;
        !           106: pci_chipset_tag_t sio_pc;
        !           107: bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2;
        !           108:
        !           109: #define        ICU_LEN         16              /* number of ISA IRQs */
        !           110:
        !           111: static struct alpha_shared_intr *sio_intr;
        !           112:
        !           113: #ifndef STRAY_MAX
        !           114: #define        STRAY_MAX       5
        !           115: #endif
        !           116:
        !           117: #ifdef BROKEN_PROM_CONSOLE
        !           118: /*
        !           119:  * If prom console is broken, must remember the initial interrupt
        !           120:  * settings and enforce them.  WHEE!
        !           121:  */
        !           122: u_int8_t initial_ocw1[2];
        !           123: u_int8_t initial_elcr[2];
        !           124: #endif
        !           125:
        !           126: void           sio_setirqstat(int, int, int);
        !           127: int            sio_intr_alloc(void *, int, int, int *);
        !           128:
        !           129: u_int8_t       (*sio_read_elcr)(int);
        !           130: void           (*sio_write_elcr)(int, u_int8_t);
        !           131: static void    specific_eoi(int);
        !           132: #ifdef BROKEN_PROM_CONSOLE
        !           133: void           sio_intr_shutdown(void *);
        !           134: #endif
        !           135:
        !           136: /******************** i82378 SIO ELCR functions ********************/
        !           137:
        !           138: int            i82378_setup_elcr(void);
        !           139: u_int8_t       i82378_read_elcr(int);
        !           140: void           i82378_write_elcr(int, u_int8_t);
        !           141:
        !           142: bus_space_handle_t sio_ioh_elcr;
        !           143:
        !           144: int
        !           145: i82378_setup_elcr()
        !           146: {
        !           147:        int rv;
        !           148:
        !           149:        /*
        !           150:         * We could probe configuration space to see that there's
        !           151:         * actually an SIO present, but we are using this as a
        !           152:         * fall-back in case nothing else matches.
        !           153:         */
        !           154:
        !           155:        rv = bus_space_map(sio_iot, 0x4d0, 2, 0, &sio_ioh_elcr);
        !           156:
        !           157:        if (rv == 0) {
        !           158:                sio_read_elcr = i82378_read_elcr;
        !           159:                sio_write_elcr = i82378_write_elcr;
        !           160:        }
        !           161:
        !           162:        return (rv);
        !           163: }
        !           164:
        !           165: u_int8_t
        !           166: i82378_read_elcr(elcr)
        !           167:        int elcr;
        !           168: {
        !           169:
        !           170:        return (bus_space_read_1(sio_iot, sio_ioh_elcr, elcr));
        !           171: }
        !           172:
        !           173: void
        !           174: i82378_write_elcr(elcr, val)
        !           175:        int elcr;
        !           176:        u_int8_t val;
        !           177: {
        !           178:
        !           179:        bus_space_write_1(sio_iot, sio_ioh_elcr, elcr, val);
        !           180: }
        !           181:
        !           182: /******************** Cypress CY82C693 ELCR functions ********************/
        !           183:
        !           184: int            cy82c693_setup_elcr(void);
        !           185: u_int8_t       cy82c693_read_elcr(int);
        !           186: void           cy82c693_write_elcr(int, u_int8_t);
        !           187:
        !           188: const struct cy82c693_handle *sio_cy82c693_handle;
        !           189:
        !           190: int
        !           191: cy82c693_setup_elcr()
        !           192: {
        !           193:        int device, maxndevs;
        !           194:        pcitag_t tag;
        !           195:        pcireg_t id;
        !           196:
        !           197:        /*
        !           198:         * Search PCI configuration space for a Cypress CY82C693.
        !           199:         *
        !           200:         * Note we can make some assumptions about our bus number
        !           201:         * here, because:
        !           202:         *
        !           203:         *      (1) there can be at most one ISA/EISA bridge per PCI bus, and
        !           204:         *
        !           205:         *      (2) any ISA/EISA bridges must be attached to primary PCI
        !           206:         *          busses (i.e. bus zero).
        !           207:         */
        !           208:
        !           209:        maxndevs = pci_bus_maxdevs(sio_pc, 0);
        !           210:
        !           211:        for (device = 0; device < maxndevs; device++) {
        !           212:                tag = pci_make_tag(sio_pc, 0, device, 0);
        !           213:                id = pci_conf_read(sio_pc, tag, PCI_ID_REG);
        !           214:
        !           215:                /* Invalid vendor ID value? */
        !           216:                if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
        !           217:                        continue;
        !           218:                /* XXX Not invalid, but we've done this ~forever. */
        !           219:                if (PCI_VENDOR(id) == 0)
        !           220:                        continue;
        !           221:
        !           222:                if (PCI_VENDOR(id) != PCI_VENDOR_CONTAQ ||
        !           223:                    PCI_PRODUCT(id) != PCI_PRODUCT_CONTAQ_82C693)
        !           224:                        continue;
        !           225:
        !           226:                /*
        !           227:                 * Found one!
        !           228:                 */
        !           229:
        !           230: #if 0
        !           231:                printf("cy82c693_setup_elcr: found 82C693 at device %d\n",
        !           232:                    device);
        !           233: #endif
        !           234:
        !           235:                sio_cy82c693_handle = cy82c693_init(sio_iot);
        !           236:                sio_read_elcr = cy82c693_read_elcr;
        !           237:                sio_write_elcr = cy82c693_write_elcr;
        !           238:
        !           239:                return (0);
        !           240:        }
        !           241:
        !           242:        /*
        !           243:         * Didn't find a CY82C693.
        !           244:         */
        !           245:        return (ENODEV);
        !           246: }
        !           247:
        !           248: u_int8_t
        !           249: cy82c693_read_elcr(elcr)
        !           250:        int elcr;
        !           251: {
        !           252:
        !           253:        return (cy82c693_read(sio_cy82c693_handle, CONFIG_ELCR1 + elcr));
        !           254: }
        !           255:
        !           256: void
        !           257: cy82c693_write_elcr(elcr, val)
        !           258:        int elcr;
        !           259:        u_int8_t val;
        !           260: {
        !           261:
        !           262:        cy82c693_write(sio_cy82c693_handle, CONFIG_ELCR1 + elcr, val);
        !           263: }
        !           264:
        !           265: /******************** ELCR access function configuration ********************/
        !           266:
        !           267: /*
        !           268:  * Put the Intel SIO at the end, so we fall back on it if we don't
        !           269:  * find anything else.  If any of the non-Intel functions find a
        !           270:  * matching device, but are unable to map it for whatever reason,
        !           271:  * they should panic.
        !           272:  */
        !           273:
        !           274: int (*sio_elcr_setup_funcs[])(void) = {
        !           275:        cy82c693_setup_elcr,
        !           276:        i82378_setup_elcr,
        !           277:        NULL,
        !           278: };
        !           279:
        !           280: /******************** Shared SIO/Cypress functions ********************/
        !           281:
        !           282: void
        !           283: sio_setirqstat(irq, enabled, type)
        !           284:        int irq, enabled;
        !           285:        int type;
        !           286: {
        !           287:        u_int8_t ocw1[2], elcr[2];
        !           288:        int icu, bit;
        !           289:
        !           290: #if 0
        !           291:        printf("sio_setirqstat: irq %d: %s, %s\n", irq,
        !           292:            enabled ? "enabled" : "disabled", isa_intr_typename(type));
        !           293: #endif
        !           294:
        !           295:        icu = irq / 8;
        !           296:        bit = irq % 8;
        !           297:
        !           298:        ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
        !           299:        ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
        !           300:        elcr[0] = (*sio_read_elcr)(0);                          /* XXX */
        !           301:        elcr[1] = (*sio_read_elcr)(1);                          /* XXX */
        !           302:
        !           303:        /*
        !           304:         * interrupt enable: set bit to mask (disable) interrupt.
        !           305:         */
        !           306:        if (enabled)
        !           307:                ocw1[icu] &= ~(1 << bit);
        !           308:        else
        !           309:                ocw1[icu] |= 1 << bit;
        !           310:
        !           311:        /*
        !           312:         * interrupt type select: set bit to get level-triggered.
        !           313:         */
        !           314:        if (type == IST_LEVEL)
        !           315:                elcr[icu] |= 1 << bit;
        !           316:        else
        !           317:                elcr[icu] &= ~(1 << bit);
        !           318:
        !           319: #ifdef not_here
        !           320:        /* see the init function... */
        !           321:        ocw1[0] &= ~0x04;               /* always enable IRQ2 on first PIC */
        !           322:        elcr[0] &= ~0x07;               /* IRQ[0-2] must be edge-triggered */
        !           323:        elcr[1] &= ~0x21;               /* IRQ[13,8] must be edge-triggered */
        !           324: #endif
        !           325:
        !           326:        bus_space_write_1(sio_iot, sio_ioh_icu1, 1, ocw1[0]);
        !           327:        bus_space_write_1(sio_iot, sio_ioh_icu2, 1, ocw1[1]);
        !           328:        (*sio_write_elcr)(0, elcr[0]);                          /* XXX */
        !           329:        (*sio_write_elcr)(1, elcr[1]);                          /* XXX */
        !           330: }
        !           331:
        !           332: void
        !           333: sio_intr_setup(pc, iot)
        !           334:        pci_chipset_tag_t pc;
        !           335:        bus_space_tag_t iot;
        !           336: {
        !           337: #ifdef notyet
        !           338:        char *cp;
        !           339: #endif
        !           340:        int i;
        !           341:
        !           342:        sio_iot = iot;
        !           343:        sio_pc = pc;
        !           344:
        !           345:        if (bus_space_map(sio_iot, IO_ICU1, 2, 0, &sio_ioh_icu1) ||
        !           346:            bus_space_map(sio_iot, IO_ICU2, 2, 0, &sio_ioh_icu2))
        !           347:                panic("sio_intr_setup: can't map ICU I/O ports");
        !           348:
        !           349:        for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++)
        !           350:                if ((*sio_elcr_setup_funcs[i])() == 0)
        !           351:                        break;
        !           352:        if (sio_elcr_setup_funcs[i] == NULL)
        !           353:                panic("sio_intr_setup: can't map ELCR");
        !           354:
        !           355: #ifdef BROKEN_PROM_CONSOLE
        !           356:        /*
        !           357:         * Remember the initial values, so we can restore them later.
        !           358:         */
        !           359:        initial_ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1);
        !           360:        initial_ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1);
        !           361:        initial_elcr[0] = (*sio_read_elcr)(0);                  /* XXX */
        !           362:        initial_elcr[1] = (*sio_read_elcr)(1);                  /* XXX */
        !           363:        shutdownhook_establish(sio_intr_shutdown, 0);
        !           364: #endif
        !           365:
        !           366:        sio_intr = alpha_shared_intr_alloc(ICU_LEN);
        !           367:
        !           368:        /*
        !           369:         * set up initial values for interrupt enables.
        !           370:         */
        !           371:        for (i = 0; i < ICU_LEN; i++) {
        !           372:                alpha_shared_intr_set_maxstrays(sio_intr, i, STRAY_MAX);
        !           373:
        !           374:                switch (i) {
        !           375:                case 0:
        !           376:                case 1:
        !           377:                case 8:
        !           378:                case 13:
        !           379:                        /*
        !           380:                         * IRQs 0, 1, 8, and 13 must always be
        !           381:                         * edge-triggered.
        !           382:                         */
        !           383:                        sio_setirqstat(i, 0, IST_EDGE);
        !           384:                        alpha_shared_intr_set_dfltsharetype(sio_intr, i,
        !           385:                            IST_EDGE);
        !           386:                        specific_eoi(i);
        !           387:                        break;
        !           388:
        !           389:                case 2:
        !           390:                        /*
        !           391:                         * IRQ 2 must be edge-triggered, and should be
        !           392:                         * enabled (otherwise IRQs 8-15 are ignored).
        !           393:                         */
        !           394:                        sio_setirqstat(i, 1, IST_EDGE);
        !           395:                        alpha_shared_intr_set_dfltsharetype(sio_intr, i,
        !           396:                            IST_UNUSABLE);
        !           397:                        break;
        !           398:
        !           399:                default:
        !           400:                        /*
        !           401:                         * Otherwise, disable the IRQ and set its
        !           402:                         * type to (effectively) "unknown."
        !           403:                         */
        !           404:                        sio_setirqstat(i, 0, IST_NONE);
        !           405:                        alpha_shared_intr_set_dfltsharetype(sio_intr, i,
        !           406:                            IST_NONE);
        !           407:                        specific_eoi(i);
        !           408:                        break;
        !           409:                }
        !           410:        }
        !           411: }
        !           412:
        !           413: #ifdef BROKEN_PROM_CONSOLE
        !           414: void
        !           415: sio_intr_shutdown(arg)
        !           416:        void *arg;
        !           417: {
        !           418:        /*
        !           419:         * Restore the initial values, to make the PROM happy.
        !           420:         */
        !           421:        bus_space_write_1(sio_iot, sio_ioh_icu1, 1, initial_ocw1[0]);
        !           422:        bus_space_write_1(sio_iot, sio_ioh_icu2, 1, initial_ocw1[1]);
        !           423:        (*sio_write_elcr)(0, initial_elcr[0]);                  /* XXX */
        !           424:        (*sio_write_elcr)(1, initial_elcr[1]);                  /* XXX */
        !           425: }
        !           426: #endif
        !           427:
        !           428: const char *
        !           429: sio_intr_string(v, irq)
        !           430:        void *v;
        !           431:        int irq;
        !           432: {
        !           433:        static char irqstr[12];         /* 8 + 2 + NULL + sanity */
        !           434:
        !           435:        if (irq == 0 || irq >= ICU_LEN || irq == 2)
        !           436:                panic("sio_intr_string: bogus isa irq 0x%x", irq);
        !           437:
        !           438:        snprintf(irqstr, sizeof irqstr, "isa irq %d", irq);
        !           439:        return (irqstr);
        !           440: }
        !           441:
        !           442: int
        !           443: sio_intr_line(v, irq)
        !           444:        void *v;
        !           445:        int irq;
        !           446: {
        !           447:        return (irq);
        !           448: }
        !           449:
        !           450: void *
        !           451: sio_intr_establish(v, irq, type, level, fn, arg, name)
        !           452:        void *v, *arg;
        !           453:         int irq;
        !           454:         int type;
        !           455:         int level;
        !           456:         int (*fn)(void *);
        !           457:        char *name;
        !           458: {
        !           459:        void *cookie;
        !           460:
        !           461:        if (irq > ICU_LEN || type == IST_NONE)
        !           462:                panic("sio_intr_establish: bogus irq or type");
        !           463:
        !           464:        cookie = alpha_shared_intr_establish(sio_intr, irq, type, level, fn,
        !           465:            arg, name);
        !           466:
        !           467:        if (cookie != NULL &&
        !           468:            alpha_shared_intr_firstactive(sio_intr, irq)) {
        !           469:                scb_set(0x800 + SCB_IDXTOVEC(irq), sio_iointr, NULL);
        !           470:                sio_setirqstat(irq, 1,
        !           471:                    alpha_shared_intr_get_sharetype(sio_intr, irq));
        !           472:        }
        !           473:
        !           474:        return (cookie);
        !           475: }
        !           476:
        !           477: void
        !           478: sio_intr_disestablish(v, cookie)
        !           479:        void *v;
        !           480:        void *cookie;
        !           481: {
        !           482:        struct alpha_shared_intrhand *ih = cookie;
        !           483:        int s, ist, irq = ih->ih_num;
        !           484:
        !           485:        s = splhigh();
        !           486:
        !           487:        /* Remove it from the link. */
        !           488:        alpha_shared_intr_disestablish(sio_intr, cookie, "isa irq");
        !           489:
        !           490:        /*
        !           491:         * Decide if we should disable the interrupt.  We must ensure
        !           492:         * that:
        !           493:         *
        !           494:         *      - An initially-enabled interrupt is never disabled.
        !           495:         *      - An initially-LT interrupt is never untyped.
        !           496:         */
        !           497:        if (alpha_shared_intr_isactive(sio_intr, irq) == 0) {
        !           498:                /*
        !           499:                 * IRQs 0, 1, 8, and 13 must always be edge-triggered
        !           500:                 * (see setup).
        !           501:                 */
        !           502:                switch (irq) {
        !           503:                case 0:
        !           504:                case 1:
        !           505:                case 8:
        !           506:                case 13:
        !           507:                        /*
        !           508:                         * If the interrupt was initially level-triggered
        !           509:                         * a warning was printed in setup.
        !           510:                         */
        !           511:                        ist = IST_EDGE;
        !           512:                        break;
        !           513:
        !           514:                default:
        !           515:                        ist = IST_NONE;
        !           516:                        break;
        !           517:                }
        !           518:                sio_setirqstat(irq, 0, ist);
        !           519:                alpha_shared_intr_set_dfltsharetype(sio_intr, irq, ist);
        !           520:
        !           521:                /* Release our SCB vector. */
        !           522:                scb_free(0x800 + SCB_IDXTOVEC(irq));
        !           523:        }
        !           524:
        !           525:        splx(s);
        !           526: }
        !           527:
        !           528: void
        !           529: sio_iointr(arg, vec)
        !           530:        void *arg;
        !           531:        unsigned long vec;
        !           532: {
        !           533:        int irq;
        !           534:
        !           535:        irq = SCB_VECTOIDX(vec - 0x800);
        !           536:
        !           537: #ifdef DIAGNOSTIC
        !           538:        if (irq >= ICU_LEN || irq < 0)
        !           539:                panic("sio_iointr: irq out of range (%d)", irq);
        !           540: #endif
        !           541:
        !           542:        if (!alpha_shared_intr_dispatch(sio_intr, irq))
        !           543:                alpha_shared_intr_stray(sio_intr, irq, "isa irq");
        !           544:        else
        !           545:                alpha_shared_intr_reset_strays(sio_intr, irq);
        !           546:
        !           547:        /*
        !           548:         * Some versions of the machines which use the SIO
        !           549:         * (or is it some PALcode revisions on those machines?)
        !           550:         * require the non-specific EOI to be fed to the PIC(s)
        !           551:         * by the interrupt handler.
        !           552:         */
        !           553:        specific_eoi(irq);
        !           554: }
        !           555:
        !           556: #define        LEGAL_IRQ(x)    ((x) >= 0 && (x) < ICU_LEN && (x) != 2)
        !           557:
        !           558: int
        !           559: sio_intr_alloc(v, mask, type, irq)
        !           560:        void *v;
        !           561:        int mask;
        !           562:        int type;
        !           563:        int *irq;
        !           564: {
        !           565:        int i, tmp, bestirq, count;
        !           566:        struct alpha_shared_intrhand **p, *q;
        !           567:
        !           568:        if (type == IST_NONE)
        !           569:                panic("intr_alloc: bogus type");
        !           570:
        !           571:        bestirq = -1;
        !           572:        count = -1;
        !           573:
        !           574:        /* some interrupts should never be dynamically allocated */
        !           575:        mask &= 0xdef8;
        !           576:
        !           577:        /*
        !           578:         * XXX some interrupts will be used later (6 for fdc, 12 for pms).
        !           579:         * the right answer is to do "breadth-first" searching of devices.
        !           580:         */
        !           581:        mask &= 0xefbf;
        !           582:
        !           583:        for (i = 0; i < ICU_LEN; i++) {
        !           584:                if (LEGAL_IRQ(i) == 0 || (mask & (1<<i)) == 0)
        !           585:                        continue;
        !           586:
        !           587:                switch(sio_intr[i].intr_sharetype) {
        !           588:                case IST_NONE:
        !           589:                        /*
        !           590:                         * if nothing's using the irq, just return it
        !           591:                         */
        !           592:                        *irq = i;
        !           593:                        return (0);
        !           594:
        !           595:                case IST_EDGE:
        !           596:                case IST_LEVEL:
        !           597:                        if (type != sio_intr[i].intr_sharetype)
        !           598:                                continue;
        !           599:                        /*
        !           600:                         * if the irq is shareable, count the number of other
        !           601:                         * handlers, and if it's smaller than the last irq like
        !           602:                         * this, remember it
        !           603:                         *
        !           604:                         * XXX We should probably also consider the
        !           605:                         * interrupt level and stick IPL_TTY with other
        !           606:                         * IPL_TTY, etc.
        !           607:                         */
        !           608:                        for (p = &TAILQ_FIRST(&sio_intr[i].intr_q), tmp = 0;
        !           609:                             (q = *p) != NULL; p = &TAILQ_NEXT(q, ih_q), tmp++)
        !           610:                                ;
        !           611:                        if ((bestirq == -1) || (count > tmp)) {
        !           612:                                bestirq = i;
        !           613:                                count = tmp;
        !           614:                        }
        !           615:                        break;
        !           616:
        !           617:                case IST_PULSE:
        !           618:                        /* this just isn't shareable */
        !           619:                        continue;
        !           620:                }
        !           621:        }
        !           622:
        !           623:        if (bestirq == -1)
        !           624:                return (1);
        !           625:
        !           626:        *irq = bestirq;
        !           627:
        !           628:        return (0);
        !           629: }
        !           630:
        !           631: static void
        !           632: specific_eoi(irq)
        !           633:        int irq;
        !           634: {
        !           635:        if (irq > 7)
        !           636:                bus_space_write_1(sio_iot,
        !           637:                    sio_ioh_icu2, 0, 0x20 | (irq & 0x07));      /* XXX */
        !           638:        bus_space_write_1(sio_iot, sio_ioh_icu1, 0, 0x20 | (irq > 7 ? 2 : irq));
        !           639: }

CVSweb