[BACK]Return to tcic2_isa.c CVS log [TXT][DIR] Up to [local] / sys / dev / isa

Annotation of sys/dev/isa/tcic2_isa.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: tcic2_isa.c,v 1.7 2005/01/27 17:03:23 millert Exp $   */
        !             2: /*     $NetBSD: tcic2_isa.c,v 1.2 1999/04/08 16:14:29 bad Exp $        */
        !             3:
        !             4: #undef TCICISADEBUG
        !             5:
        !             6: /*
        !             7:  *
        !             8:  * Copyright (c) 1998, 1999 Christoph Badura. All rights reserved.
        !             9:  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
        !            10:  *
        !            11:  * Redistribution and use in source and binary forms, with or without
        !            12:  * modification, are permitted provided that the following conditions
        !            13:  * are met:
        !            14:  * 1. Redistributions of source code must retain the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer.
        !            16:  * 2. Redistributions in binary form must reproduce the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer in the
        !            18:  *    documentation and/or other materials provided with the distribution.
        !            19:  * 3. All advertising materials mentioning features or use of this software
        !            20:  *    must display the following acknowledgement:
        !            21:  *     This product includes software developed by Marc Horowitz.
        !            22:  * 4. The name of the author may not be used to endorse or promote products
        !            23:  *    derived from this software without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            26:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            27:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            28:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            29:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            30:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            31:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            32:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            33:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            34:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            35:  */
        !            36:
        !            37:
        !            38: #include <sys/types.h>
        !            39: #include <sys/param.h>
        !            40: #include <sys/systm.h>
        !            41: #include <sys/device.h>
        !            42: #include <sys/extent.h>
        !            43: #include <sys/malloc.h>
        !            44:
        !            45: #include <machine/bus.h>
        !            46: #include <machine/intr.h>
        !            47:
        !            48: #include <dev/isa/isareg.h>
        !            49: #include <dev/isa/isavar.h>
        !            50:
        !            51: #include <dev/pcmcia/pcmciareg.h>
        !            52: #include <dev/pcmcia/pcmciavar.h>
        !            53: #include <dev/pcmcia/pcmciachip.h>
        !            54:
        !            55: #include <dev/ic/tcic2reg.h>
        !            56: #include <dev/ic/tcic2var.h>
        !            57:
        !            58: /*****************************************************************************
        !            59:  * Configurable parameters.
        !            60:  *****************************************************************************/
        !            61:
        !            62: /*
        !            63:  * Default I/O allocation range.  If both are set to non-zero, these
        !            64:  * values will be used instead.  Otherwise, the code attempts to probe
        !            65:  * the bus width.  Systems with 10 address bits should use 0x300 and 0xff.
        !            66:  * Systems with 12 address bits (most) should use 0x400 and 0xbff.
        !            67:  */
        !            68:
        !            69: #ifndef TCIC_ISA_ALLOC_IOBASE
        !            70: #define        TCIC_ISA_ALLOC_IOBASE           0
        !            71: #endif
        !            72:
        !            73: #ifndef TCIC_ISA_ALLOC_IOSIZE
        !            74: #define        TCIC_ISA_ALLOC_IOSIZE           0
        !            75: #endif
        !            76:
        !            77: int    tcic_isa_alloc_iobase = TCIC_ISA_ALLOC_IOBASE;
        !            78: int    tcic_isa_alloc_iosize = TCIC_ISA_ALLOC_IOSIZE;
        !            79:
        !            80: /*
        !            81:  * Default IRQ allocation bitmask.  This defines the range of allowable
        !            82:  * IRQs for PCMCIA slots.  Useful if order of probing would screw up other
        !            83:  * devices, or if TCIC hardware/cards have trouble with certain interrupt
        !            84:  * lines.
        !            85:  *
        !            86:  * We disable IRQ 10 by default, since some common laptops (namely, the
        !            87:  * NEC Versa series) reserve IRQ 10 for the docking station SCSI interface.
        !            88:  *
        !            89:  * XXX Do we care about this?  the Versa doesn't use a tcic. -chb
        !            90:  */
        !            91:
        !            92: #ifndef TCIC_ISA_INTR_ALLOC_MASK
        !            93: #define        TCIC_ISA_INTR_ALLOC_MASK        0xffff
        !            94: #endif
        !            95:
        !            96: int    tcic_isa_intr_alloc_mask = TCIC_ISA_INTR_ALLOC_MASK;
        !            97:
        !            98: /*****************************************************************************
        !            99:  * End of configurable parameters.
        !           100:  *****************************************************************************/
        !           101:
        !           102: #ifdef TCICISADEBUG
        !           103: int    tcic_isa_debug = 1;
        !           104: #define        DPRINTF(arg) if (tcic_isa_debug) printf arg;
        !           105: #else
        !           106: #define        DPRINTF(arg)
        !           107: #endif
        !           108:
        !           109: int    tcic_isa_probe(struct device *, void *, void *);
        !           110: void   tcic_isa_attach(struct device *, struct device *, void *);
        !           111:
        !           112: void   *tcic_isa_chip_intr_establish(pcmcia_chipset_handle_t,
        !           113:            struct pcmcia_function *, int, int (*) (void *), void *, char *);
        !           114: void   tcic_isa_chip_intr_disestablish(pcmcia_chipset_handle_t, void *);
        !           115: const char *tcic_isa_chip_intr_string(pcmcia_chipset_handle_t, void *);
        !           116:
        !           117: struct cfattach tcic_isa_ca = {
        !           118:        sizeof(struct tcic_softc), tcic_isa_probe, tcic_isa_attach
        !           119: };
        !           120:
        !           121: static struct pcmcia_chip_functions tcic_isa_functions = {
        !           122:        tcic_chip_mem_alloc,
        !           123:        tcic_chip_mem_free,
        !           124:        tcic_chip_mem_map,
        !           125:        tcic_chip_mem_unmap,
        !           126:
        !           127:        tcic_chip_io_alloc,
        !           128:        tcic_chip_io_free,
        !           129:        tcic_chip_io_map,
        !           130:        tcic_chip_io_unmap,
        !           131:
        !           132:        tcic_isa_chip_intr_establish,
        !           133:        tcic_isa_chip_intr_disestablish,
        !           134:        tcic_isa_chip_intr_string,
        !           135:
        !           136:        tcic_chip_socket_enable,
        !           137:        tcic_chip_socket_disable,
        !           138: };
        !           139:
        !           140: int
        !           141: tcic_isa_probe(parent, match, aux)
        !           142:        struct device *parent;
        !           143:        void *match;
        !           144:        void *aux;
        !           145: {
        !           146:        struct isa_attach_args *ia = aux;
        !           147:        bus_space_tag_t iot = ia->ia_iot;
        !           148:        bus_space_handle_t ioh, memh;
        !           149:        int val, found;
        !           150:
        !           151:        /* Disallow wildcarded i/o address. */
        !           152:        if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */)
        !           153:                return (0);
        !           154:
        !           155:        if (bus_space_map(iot, ia->ia_iobase, TCIC_IOSIZE, 0, &ioh))
        !           156:                return (0);
        !           157:
        !           158:        if (ia->ia_msize == 0)
        !           159:                ia->ia_msize = TCIC_MEMSIZE;
        !           160:
        !           161:        if (bus_space_map(ia->ia_memt, ia->ia_maddr, ia->ia_msize, 0, &memh))
        !           162:                return (0);
        !           163:
        !           164:        DPRINTF(("tcic probing 0x%03x\n", ia->ia_iobase));
        !           165:        found = 0;
        !           166:
        !           167:        /*
        !           168:         * First, check for the reserved bits to be zero.
        !           169:         */
        !           170:        if (tcic_check_reserved_bits(iot, ioh)) {
        !           171:                DPRINTF(("tcic: reserved bits checked OK\n"));
        !           172:                /* Second, check whether the we know how to handle the chip. */
        !           173:                if ((val = tcic_chipid(iot, ioh))) {
        !           174:                        DPRINTF(("tcic id: 0x%02x\n", val));
        !           175:                        if (tcic_chipid_known(val))
        !           176:                                found++;
        !           177:                }
        !           178:        }
        !           179:        else
        !           180:                DPRINTF(("tcic: reserved bits didn't check OK\n"));
        !           181:
        !           182:        bus_space_unmap(iot, ioh, TCIC_IOSIZE);
        !           183:        bus_space_unmap(ia->ia_memt, memh, ia->ia_msize);
        !           184:
        !           185:        if (!found)
        !           186:                return (0);
        !           187:
        !           188:        ia->ia_iosize = TCIC_IOSIZE;
        !           189:
        !           190:        return (1);
        !           191: }
        !           192:
        !           193: void
        !           194: tcic_isa_attach(parent, self, aux)
        !           195:        struct device *parent, *self;
        !           196:        void *aux;
        !           197: {
        !           198:        struct tcic_softc *sc = (void *) self;
        !           199:        struct isa_attach_args *ia = aux;
        !           200:        isa_chipset_tag_t ic = ia->ia_ic;
        !           201:        bus_space_tag_t iot = ia->ia_iot;
        !           202:        bus_space_tag_t memt = ia->ia_memt;
        !           203:        bus_space_handle_t ioh;
        !           204:        bus_space_handle_t memh;
        !           205:
        !           206:        /* Map i/o space. */
        !           207:        if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) {
        !           208:                printf(": can't map i/o space\n");
        !           209:                return;
        !           210:        }
        !           211:
        !           212:        /* Map mem space. */
        !           213:        if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) {
        !           214:                printf(": can't map mem space\n");
        !           215:                return;
        !           216:        }
        !           217:
        !           218:        sc->membase = ia->ia_maddr;
        !           219:        sc->subregionmask = (1 << (ia->ia_msize / TCIC_MEM_PAGESIZE)) - 1;
        !           220:        sc->memsize2 = tcic_log2((u_int)ia->ia_msize);
        !           221:
        !           222:        sc->intr_est = ic;
        !           223:        sc->pct = (pcmcia_chipset_tag_t) &tcic_isa_functions;
        !           224:
        !           225:        sc->iot = iot;
        !           226:        sc->ioh = ioh;
        !           227:        sc->memt = memt;
        !           228:        sc->memh = memh;
        !           229:
        !           230:        /*
        !           231:         * determine chip type and initialise some chip type dependend
        !           232:         * parameters in softc.
        !           233:         */
        !           234:        sc->chipid = tcic_chipid(iot, ioh);
        !           235:        sc->validirqs = tcic_validirqs(sc->chipid);
        !           236:
        !           237:        /*
        !           238:         * allocate an irq.  interrupts are relatively
        !           239:         * scarce but for TCIC controllers very infrequent.
        !           240:         */
        !           241:
        !           242:        if ((sc->irq = ia->ia_irq) == IRQUNK) {
        !           243:                if (isa_intr_alloc(ic,
        !           244:                    sc->validirqs & (tcic_isa_intr_alloc_mask & 0xff00),
        !           245:                    IST_EDGE, &sc->irq)) {
        !           246:                        printf("\n%s: can't allocate interrupt\n",
        !           247:                            sc->dev.dv_xname);
        !           248:                        return;
        !           249:                }
        !           250:                printf(": using irq %d", sc->irq);
        !           251:        }
        !           252:        printf("\n");
        !           253:
        !           254:        tcic_attach(sc);
        !           255:
        !           256:
        !           257:        /*
        !           258:         * XXX mycroft recommends I/O space range 0x400-0xfff.
        !           259:         */
        !           260:
        !           261:        /*
        !           262:         * XXX some hardware doesn't seem to grok addresses in 0x400 range--
        !           263:         * apparently missing a bit or more of address lines. (e.g.
        !           264:         * CIRRUS_PD672X with Linksys EthernetCard ne2000 clone in TI
        !           265:         * TravelMate 5000--not clear which is at fault)
        !           266:         *
        !           267:         * Add a kludge to detect 10 bit wide buses and deal with them,
        !           268:         * and also a config file option to override the probe.
        !           269:         */
        !           270:
        !           271: #if 0
        !           272:        /*
        !           273:         * This is what we'd like to use, but...
        !           274:         */
        !           275:        sc->iobase = 0x400;
        !           276:        sc->iosize = 0xbff;
        !           277: #else
        !           278:        /*
        !           279:         * ...the above bus width probe doesn't always work.
        !           280:         * So, experimentation has shown the following range
        !           281:         * to not lose on systems that 0x300-0x3ff loses on
        !           282:         * (e.g. the NEC Versa 6030X).
        !           283:         */
        !           284:        sc->iobase = 0x330;
        !           285:        sc->iosize = 0x0cf;
        !           286: #endif
        !           287:
        !           288:        DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx)\n",
        !           289:            sc->dev.dv_xname, (long) sc->iobase,
        !           290:            (long) sc->iobase + sc->iosize));
        !           291:
        !           292:        if (tcic_isa_alloc_iobase && tcic_isa_alloc_iosize) {
        !           293:                sc->iobase = tcic_isa_alloc_iobase;
        !           294:                sc->iosize = tcic_isa_alloc_iosize;
        !           295:
        !           296:                DPRINTF(("%s: bus_space_alloc range 0x%04lx-0x%04lx "
        !           297:                    "(config override)\n", sc->dev.dv_xname, (long) sc->iobase,
        !           298:                    (long) sc->iobase + sc->iosize));
        !           299:        }
        !           300:        sc->ih = isa_intr_establish(ic, sc->irq, IST_EDGE, IPL_TTY,
        !           301:            tcic_intr, sc, sc->dev.dv_xname);
        !           302:        if (sc->ih == NULL) {
        !           303:                printf("%s: can't establish interrupt\n", sc->dev.dv_xname);
        !           304:                return;
        !           305:        }
        !           306:
        !           307:        tcic_attach_sockets(sc);
        !           308: }
        !           309:
        !           310: void *
        !           311: tcic_isa_chip_intr_establish(pch, pf, ipl, fct, arg, xname)
        !           312:        pcmcia_chipset_handle_t pch;
        !           313:        struct pcmcia_function *pf;
        !           314:        int ipl;
        !           315:        int (*fct)(void *);
        !           316:        void *arg;
        !           317:        char *xname;
        !           318: {
        !           319:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !           320:        int irq, ist, val, reg;
        !           321:        void *ih;
        !           322:        int irqmap[] = {
        !           323:            0, 0, 0, TCIC_SCF1_IRQ3, TCIC_SCF1_IRQ4, TCIC_SCF1_IRQ5,
        !           324:            TCIC_SCF1_IRQ6, TCIC_SCF1_IRQ7, 0, TCIC_SCF1_IRQ9,
        !           325:            TCIC_SCF1_IRQ10, TCIC_SCF1_IRQ11, TCIC_SCF1_IRQ12, 0,
        !           326:            TCIC_SCF1_IRQ14, TCIC_SCF1_IRQ15
        !           327:        };
        !           328:
        !           329:        DPRINTF(("%s: tcic_isa_chip_intr_establish\n", h->sc->dev.dv_xname));
        !           330:
        !           331:        /* XXX should we convert level to pulse? -chb  */
        !           332:        if (pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)
        !           333:                ist = IST_LEVEL;
        !           334:        else if (pf->cfe->flags & PCMCIA_CFE_IRQPULSE)
        !           335:                ist = IST_PULSE;
        !           336:        else
        !           337:                ist = IST_LEVEL;
        !           338:
        !           339:        if (isa_intr_alloc(h->sc->intr_est,
        !           340:            h->sc->validirqs & tcic_isa_intr_alloc_mask, ist, &irq))
        !           341:                return (NULL);
        !           342:        if ((ih = isa_intr_establish(h->sc->intr_est, irq, ist, ipl,
        !           343:            fct, arg, h->pcmcia->dv_xname)) == NULL)
        !           344:                return (NULL);
        !           345:
        !           346:        DPRINTF(("%s: intr established\n", h->sc->dev.dv_xname));
        !           347:
        !           348:        h->ih_irq = irq;
        !           349:
        !           350:        reg = TCIC_IR_SCF1_N(h->sock);
        !           351:        val = (tcic_read_ind_2(h, reg) & (~TCIC_SCF1_IRQ_MASK)) | irqmap[irq];
        !           352:        tcic_write_ind_2(h, reg, val);
        !           353:
        !           354:        printf(" irq %d", irq);
        !           355:        return (ih);
        !           356: }
        !           357:
        !           358: void
        !           359: tcic_isa_chip_intr_disestablish(pch, ih)
        !           360:        pcmcia_chipset_handle_t pch;
        !           361:        void *ih;
        !           362: {
        !           363:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !           364:        int val, reg;
        !           365:
        !           366:        DPRINTF(("%s: tcic_isa_chip_intr_disestablish\n", h->sc->dev.dv_xname));
        !           367:
        !           368:        h->ih_irq = 0;
        !           369:
        !           370:        reg = TCIC_IR_SCF1_N(h->sock);
        !           371:        val = tcic_read_ind_2(h, reg);
        !           372:        val &= ~TCIC_SCF1_IRQ_MASK;
        !           373:        tcic_write_ind_2(h, reg, val);
        !           374:
        !           375:        isa_intr_disestablish(h->sc->intr_est, ih);
        !           376: }
        !           377:
        !           378: const char *
        !           379: tcic_isa_chip_intr_string(pch, ih)
        !           380:        pcmcia_chipset_handle_t pch;
        !           381:        void *ih;
        !           382: {
        !           383:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !           384:        static char irqstr[64];
        !           385:
        !           386:        if (ih == NULL)
        !           387:                snprintf(irqstr, sizeof(irqstr), "couldn't establish interrupt");
        !           388:        else
        !           389:                snprintf(irqstr, sizeof(irqstr), "irq %d", h->ih_irq);
        !           390:        return (irqstr);
        !           391: }

CVSweb