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

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

1.1     ! nbrk        1: /* $OpenBSD: pci_550.c,v 1.17 2007/05/02 21:50:14 martin Exp $ */
        !             2: /* $NetBSD: pci_550.c,v 1.18 2000/06/29 08:58:48 mrg 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, and by Andrew Gallatin.
        !            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/types.h>
        !            69: #include <sys/param.h>
        !            70: #include <sys/time.h>
        !            71: #include <sys/systm.h>
        !            72: #include <sys/errno.h>
        !            73: #include <sys/malloc.h>
        !            74: #include <sys/device.h>
        !            75: #include <sys/syslog.h>
        !            76:
        !            77: #include <uvm/uvm_extern.h>
        !            78:
        !            79: #include <machine/autoconf.h>
        !            80: #include <machine/rpb.h>
        !            81:
        !            82: #include <dev/pci/pcireg.h>
        !            83: #include <dev/pci/pcivar.h>
        !            84: #include <dev/pci/pciidereg.h>
        !            85: #include <dev/pci/pciidevar.h>
        !            86:
        !            87: #include <alpha/pci/ciareg.h>
        !            88: #include <alpha/pci/ciavar.h>
        !            89:
        !            90: #include <alpha/pci/pci_550.h>
        !            91:
        !            92: #include "sio.h"
        !            93: #if NSIO
        !            94: #include <alpha/pci/siovar.h>
        !            95: #endif
        !            96:
        !            97: int    dec_550_intr_map(void *, pcitag_t, int, int,
        !            98:            pci_intr_handle_t *);
        !            99: const char *dec_550_intr_string(void *, pci_intr_handle_t);
        !           100: int    dec_550_intr_line(void *, pci_intr_handle_t);
        !           101: void   *dec_550_intr_establish(void *, pci_intr_handle_t,
        !           102:            int, int (*func)(void *), void *, char *);
        !           103: void   dec_550_intr_disestablish(void *, void *);
        !           104:
        !           105: void   *dec_550_pciide_compat_intr_establish(void *, struct device *,
        !           106:            struct pci_attach_args *, int, int (*)(void *), void *);
        !           107: void    dec_550_pciide_compat_intr_disestablish(void *, void *);
        !           108:
        !           109: #define        DEC_550_PCI_IRQ_BEGIN   8
        !           110: #define        DEC_550_MAX_IRQ         (64 - DEC_550_PCI_IRQ_BEGIN)
        !           111:
        !           112: /*
        !           113:  * The Miata has a Pyxis, which seems to have problems with stray
        !           114:  * interrupts.  Work around this by just ignoring strays.
        !           115:  */
        !           116: #define        PCI_STRAY_MAX           0
        !           117:
        !           118: /*
        !           119:  * Some Miata models, notably models with a Cypress PCI-ISA bridge, have
        !           120:  * a PCI device (the OHCI USB controller) with interrupts tied to ISA IRQ
        !           121:  * lines.  This IRQ is encoded as: line = FLAG | isa_irq. Usually FLAG
        !           122:  * is 0xe0, however it can be 0xf0.  We don't allow 0xf0 | irq15.
        !           123:  */
        !           124: #define        DEC_550_LINE_IS_ISA(line)       ((line) >= 0xe0 && (line) <= 0xfe)
        !           125: #define        DEC_550_LINE_ISA_IRQ(line)      ((line) & 0x0f)
        !           126:
        !           127: struct alpha_shared_intr *dec_550_pci_intr;
        !           128:
        !           129: void   dec_550_iointr(void *arg, unsigned long vec);
        !           130: void   dec_550_intr_enable(int irq);
        !           131: void   dec_550_intr_disable(int irq);
        !           132:
        !           133: void
        !           134: pci_550_pickintr(ccp)
        !           135:        struct cia_config *ccp;
        !           136: {
        !           137:        bus_space_tag_t iot = &ccp->cc_iot;
        !           138:        pci_chipset_tag_t pc = &ccp->cc_pc;
        !           139: #if 0
        !           140:        char *cp;
        !           141: #endif
        !           142:        int i;
        !           143:
        !           144:         pc->pc_intr_v = ccp;
        !           145:         pc->pc_intr_map = dec_550_intr_map;
        !           146:         pc->pc_intr_string = dec_550_intr_string;
        !           147:         pc->pc_intr_line = dec_550_intr_line;
        !           148:         pc->pc_intr_establish = dec_550_intr_establish;
        !           149:         pc->pc_intr_disestablish = dec_550_intr_disestablish;
        !           150:
        !           151:        pc->pc_pciide_compat_intr_establish =
        !           152:            dec_550_pciide_compat_intr_establish;
        !           153:        pc->pc_pciide_compat_intr_disestablish =
        !           154:            dec_550_pciide_compat_intr_disestablish;
        !           155:
        !           156:        /*
        !           157:         * DEC 550's interrupts are enabled via the Pyxis interrupt
        !           158:         * mask register.  Nothing to map.
        !           159:         */
        !           160:
        !           161:        for (i = 0; i < DEC_550_MAX_IRQ; i++)
        !           162:                dec_550_intr_disable(i);
        !           163:
        !           164:        dec_550_pci_intr = alpha_shared_intr_alloc(DEC_550_MAX_IRQ);
        !           165:        for (i = 0; i < DEC_550_MAX_IRQ; i++) {
        !           166:                alpha_shared_intr_set_maxstrays(dec_550_pci_intr, i,
        !           167:                    PCI_STRAY_MAX);
        !           168:                alpha_shared_intr_set_private(dec_550_pci_intr, i, ccp);
        !           169:        }
        !           170:
        !           171: #if NSIO
        !           172:        sio_intr_setup(pc, iot);
        !           173: #endif
        !           174: }
        !           175:
        !           176: int
        !           177: dec_550_intr_map(ccv, bustag, buspin, line, ihp)
        !           178:         void *ccv;
        !           179:         pcitag_t bustag;
        !           180:         int buspin, line;
        !           181:         pci_intr_handle_t *ihp;
        !           182: {
        !           183:        struct cia_config *ccp = ccv;
        !           184:        pci_chipset_tag_t pc = &ccp->cc_pc;
        !           185:        int bus, device, function;
        !           186:
        !           187:        if (buspin == 0) {
        !           188:                /* No IRQ used. */
        !           189:                return 1;
        !           190:        }
        !           191:        if (buspin > 4) {
        !           192:                printf("dec_550_intr_map: bad interrupt pin %d\n", buspin);
        !           193:                return 1;
        !           194:        }
        !           195:
        !           196:        pci_decompose_tag(pc, bustag, &bus, &device, &function);
        !           197:
        !           198:        /*
        !           199:         * There are two main variants of Miata: Miata 1 (Intel SIO)
        !           200:         * and Miata {1.5,2} (Cypress).
        !           201:         *
        !           202:         * The Miata 1 has a CMD PCI IDE wired to compatibility mode at
        !           203:         * device 4 of bus 0.  This variant apparently also has the
        !           204:         * Pyxis DMA bug.
        !           205:         *
        !           206:         * On the Miata 1.5 and Miata 2, the Cypress PCI-ISA bridge lives
        !           207:         * on device 7 of bus 0.  This device has PCI IDE wired to
        !           208:         * compatibility mode on functions 1 and 2.
        !           209:         *
        !           210:         * There will be no interrupt mapping for these devices, so just
        !           211:         * bail out now.
        !           212:         */
        !           213:        if (bus == 0) {
        !           214:                if ((hwrpb->rpb_variation & SV_ST_MASK) < SV_ST_MIATA_1_5) {
        !           215:                        /* Miata 1 */
        !           216:                        if (device == 7)
        !           217:                                panic("dec_550_intr_map: SIO device");
        !           218:                        else if (device == 4)
        !           219:                                return (1);
        !           220:                } else {
        !           221:                        /* Miata 1.5 or Miata 2 */
        !           222:                        if (device == 7) {
        !           223:                                if (function == 0)
        !           224:                                        panic("dec_550_intr_map: SIO device");
        !           225:                                if (function == 1 || function == 2)
        !           226:                                        return (1);
        !           227:                        }
        !           228:                }
        !           229:        }
        !           230:
        !           231:        /*
        !           232:         * The console places the interrupt mapping in the "line" value.
        !           233:         * A value of (char)-1 indicates there is no mapping.
        !           234:         */
        !           235:        if (line == 0xff) {
        !           236:                printf("dec_550_intr_map: no mapping for %d/%d/%d\n",
        !           237:                    bus, device, function);
        !           238:                return (1);
        !           239:        }
        !           240:
        !           241: #if NSIO == 0
        !           242:        if (DEC_550_LINE_IS_ISA(line)) {
        !           243:                printf("dec_550_intr_map: ISA IRQ %d for %d/%d/%d\n",
        !           244:                    DEC_550_LINE_ISA_IRQ(line), bus, device, function);
        !           245:                return (1);
        !           246:        }
        !           247: #endif
        !           248:
        !           249:        if (DEC_550_LINE_IS_ISA(line) == 0 && line >= DEC_550_MAX_IRQ) {
        !           250:                printf("dec_550_intr_map: dec 550 irq too large (%d)",
        !           251:                    line);
        !           252:                return (1);
        !           253:        }
        !           254:
        !           255:        *ihp = line;
        !           256:        return (0);
        !           257: }
        !           258:
        !           259: const char *
        !           260: dec_550_intr_string(ccv, ih)
        !           261:        void *ccv;
        !           262:        pci_intr_handle_t ih;
        !           263: {
        !           264: #if 0
        !           265:        struct cia_config *ccp = ccv;
        !           266: #endif
        !           267:        static char irqstr[16];         /* 12 + 2 + NULL + sanity */
        !           268:
        !           269: #if NSIO
        !           270:        if (DEC_550_LINE_IS_ISA(ih))
        !           271:                return (sio_intr_string(NULL /*XXX*/,
        !           272:                    DEC_550_LINE_ISA_IRQ(ih)));
        !           273: #endif
        !           274:
        !           275:        if (ih >= DEC_550_MAX_IRQ)
        !           276:                panic("dec_550_intr_string: bogus 550 IRQ 0x%lx", ih);
        !           277:        snprintf(irqstr, sizeof irqstr, "dec 550 irq %ld", ih);
        !           278:        return (irqstr);
        !           279: }
        !           280:
        !           281: int
        !           282: dec_550_intr_line(ccv, ih)
        !           283:        void *ccv;
        !           284:        pci_intr_handle_t ih;
        !           285: {
        !           286: #if NSIO
        !           287:        if (DEC_550_LINE_IS_ISA(ih))
        !           288:                return (sio_intr_line(NULL /*XXX*/, DEC_550_LINE_ISA_IRQ(ih)));
        !           289: #endif
        !           290:
        !           291:        return (ih);
        !           292: }
        !           293:
        !           294: void *
        !           295: dec_550_intr_establish(ccv, ih, level, func, arg, name)
        !           296:        void *ccv, *arg;
        !           297:        pci_intr_handle_t ih;
        !           298:        int level;
        !           299:        int (*func)(void *);
        !           300:        char *name;
        !           301: {
        !           302: #if 0
        !           303:        struct cia_config *ccp = ccv;
        !           304: #endif
        !           305:        void *cookie;
        !           306:
        !           307: #if NSIO
        !           308:        if (DEC_550_LINE_IS_ISA(ih))
        !           309:                return (sio_intr_establish(NULL /*XXX*/,
        !           310:                    DEC_550_LINE_ISA_IRQ(ih), IST_LEVEL, level, func, arg,
        !           311:                    name));
        !           312: #endif
        !           313:
        !           314:        if (ih >= DEC_550_MAX_IRQ)
        !           315:                panic("dec_550_intr_establish: bogus dec 550 IRQ 0x%lx", ih);
        !           316:
        !           317:        cookie = alpha_shared_intr_establish(dec_550_pci_intr, ih, IST_LEVEL,
        !           318:            level, func, arg, name);
        !           319:
        !           320:        if (cookie != NULL &&
        !           321:            alpha_shared_intr_firstactive(dec_550_pci_intr, ih)) {
        !           322:                scb_set(0x900 + SCB_IDXTOVEC(ih), dec_550_iointr, NULL);
        !           323:                dec_550_intr_enable(ih);
        !           324:        }
        !           325:        return (cookie);
        !           326: }
        !           327:
        !           328: void
        !           329: dec_550_intr_disestablish(ccv, cookie)
        !           330:         void *ccv, *cookie;
        !           331: {
        !           332:        struct cia_config *ccp = ccv;
        !           333:        struct alpha_shared_intrhand *ih = cookie;
        !           334:        unsigned int irq = ih->ih_num;
        !           335:        int s;
        !           336:
        !           337: #if NSIO
        !           338:        /*
        !           339:         * We have to determine if this is an ISA IRQ or not!  We do this
        !           340:         * by checking to see if the intrhand points back to an intrhead
        !           341:         * that points to our cia_config.  If not, it's an ISA IRQ.  Pretty
        !           342:         * disgusting, eh?
        !           343:         */
        !           344:        if (ih->ih_intrhead->intr_private != ccp) {
        !           345:                sio_intr_disestablish(NULL /*XXX*/, cookie);
        !           346:                return;
        !           347:        }
        !           348: #endif
        !           349:
        !           350:        s = splhigh();
        !           351:
        !           352:        alpha_shared_intr_disestablish(dec_550_pci_intr, cookie,
        !           353:            "dec 550 irq");
        !           354:        if (alpha_shared_intr_isactive(dec_550_pci_intr, irq) == 0) {
        !           355:                dec_550_intr_disable(irq);
        !           356:                alpha_shared_intr_set_dfltsharetype(dec_550_pci_intr, irq,
        !           357:                    IST_NONE);
        !           358:                scb_free(0x900 + SCB_IDXTOVEC(irq));
        !           359:        }
        !           360:
        !           361:        splx(s);
        !           362: }
        !           363:
        !           364: void *
        !           365: dec_550_pciide_compat_intr_establish(v, dev, pa, chan, func, arg)
        !           366:        void *v;
        !           367:        struct device *dev;
        !           368:        struct pci_attach_args *pa;
        !           369:        int chan;
        !           370:        int (*func)(void *);
        !           371:        void *arg;
        !           372: {
        !           373:        pci_chipset_tag_t pc = pa->pa_pc;
        !           374:        void *cookie = NULL;
        !           375:        int bus, irq;
        !           376:
        !           377:        pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL);
        !           378:
        !           379:        /*
        !           380:         * If this isn't PCI bus #0, all bets are off.
        !           381:         */
        !           382:        if (bus != 0)
        !           383:                return (NULL);
        !           384:
        !           385:        irq = PCIIDE_COMPAT_IRQ(chan);
        !           386: #if NSIO
        !           387:        cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO,
        !           388:            func, arg, dev->dv_xname);
        !           389: #endif
        !           390:        return (cookie);
        !           391: }
        !           392:
        !           393: void
        !           394: dec_550_pciide_compat_intr_disestablish(v, cookie)
        !           395:        void *v;
        !           396:        void *cookie;
        !           397: {
        !           398:        sio_intr_disestablish(NULL, cookie);
        !           399: }
        !           400:
        !           401: void
        !           402: dec_550_iointr(arg, vec)
        !           403:        void *arg;
        !           404:        unsigned long vec;
        !           405: {
        !           406:        int irq;
        !           407:
        !           408:        irq = SCB_VECTOIDX(vec - 0x900);
        !           409:
        !           410:        if (irq >= DEC_550_MAX_IRQ)
        !           411:                panic("550_iointr: vec 0x%lx out of range\n", vec);
        !           412:
        !           413:        if (!alpha_shared_intr_dispatch(dec_550_pci_intr, irq)) {
        !           414:                alpha_shared_intr_stray(dec_550_pci_intr, irq,
        !           415:                    "dec 550 irq");
        !           416:                if (ALPHA_SHARED_INTR_DISABLE(dec_550_pci_intr, irq))
        !           417:                        dec_550_intr_disable(irq);
        !           418:        } else
        !           419:                alpha_shared_intr_reset_strays(dec_550_pci_intr, irq);
        !           420: }
        !           421:
        !           422: void
        !           423: dec_550_intr_enable(irq)
        !           424:        int irq;
        !           425: {
        !           426:
        !           427:        cia_pyxis_intr_enable(irq + DEC_550_PCI_IRQ_BEGIN, 1);
        !           428: }
        !           429:
        !           430: void
        !           431: dec_550_intr_disable(irq)
        !           432:        int irq;
        !           433: {
        !           434:
        !           435:        cia_pyxis_intr_enable(irq + DEC_550_PCI_IRQ_BEGIN, 0);
        !           436: }

CVSweb