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

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

1.1     ! nbrk        1: /*     $OpenBSD: uha_isa.c,v 1.8 2007/04/10 17:47:55 miod Exp $        */
        !             2: /*     $NetBSD: uha_isa.c,v 1.5 1996/10/21 22:41:21 thorpej Exp $      */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1994, 1996 Charles M. Hannum.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Charles M. Hannum.
        !            18:  * 4. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: #include <sys/types.h>
        !            34: #include <sys/param.h>
        !            35: #include <sys/systm.h>
        !            36: #include <sys/device.h>
        !            37: #include <sys/kernel.h>
        !            38: #include <sys/proc.h>
        !            39: #include <sys/user.h>
        !            40:
        !            41: #include <machine/bus.h>
        !            42: #include <machine/intr.h>
        !            43:
        !            44: #include <scsi/scsi_all.h>
        !            45: #include <scsi/scsiconf.h>
        !            46:
        !            47: #include <dev/isa/isavar.h>
        !            48: #include <dev/isa/isadmavar.h>
        !            49:
        !            50: #include <dev/ic/uhareg.h>
        !            51: #include <dev/ic/uhavar.h>
        !            52:
        !            53: #define        UHA_ISA_IOSIZE  16
        !            54:
        !            55: #ifndef DDB
        !            56: #define        Debugger() panic("should call debugger here (uha_isa.c)")
        !            57: #endif
        !            58:
        !            59: int    uha_isa_probe(struct device *, void *, void *);
        !            60: void   uha_isa_attach(struct device *, struct device *, void *);
        !            61:
        !            62: struct cfattach uha_isa_ca = {
        !            63:        sizeof(struct uha_softc), uha_isa_probe, uha_isa_attach
        !            64: };
        !            65:
        !            66: #define KVTOPHYS(x)    vtophys((vaddr_t)(x))
        !            67:
        !            68: int u14_find(bus_space_tag_t, bus_space_handle_t, struct uha_softc *);
        !            69: void u14_start_mbox(struct uha_softc *, struct uha_mscp *);
        !            70: int u14_poll(struct uha_softc *, struct scsi_xfer *, int);
        !            71: int u14_intr(void *);
        !            72: void u14_init(struct uha_softc *);
        !            73:
        !            74: /*
        !            75:  * Check the slots looking for a board we recognise
        !            76:  * If we find one, note its address (slot) and call
        !            77:  * the actual probe routine to check it out.
        !            78:  */
        !            79: int
        !            80: uha_isa_probe(parent, match, aux)
        !            81:        struct device *parent;
        !            82:        void *match, *aux;
        !            83: {
        !            84:        struct isa_attach_args *ia = aux;
        !            85:        struct uha_softc sc;
        !            86:        bus_space_tag_t iot = ia->ia_iot;
        !            87:        bus_space_handle_t ioh;
        !            88:        int rv;
        !            89:
        !            90:        if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
        !            91:                return (0);
        !            92:
        !            93:        rv = u14_find(iot, ioh, &sc);
        !            94:
        !            95:        bus_space_unmap(iot, ioh, UHA_ISA_IOSIZE);
        !            96:
        !            97:        if (rv) {
        !            98:                if (ia->ia_irq != -1 && ia->ia_irq != sc.sc_irq)
        !            99:                        return (0);
        !           100:                if (ia->ia_drq != -1 && ia->ia_drq != sc.sc_drq)
        !           101:                        return (0);
        !           102:                ia->ia_irq = sc.sc_irq;
        !           103:                ia->ia_drq = sc.sc_drq;
        !           104:                ia->ia_msize = 0;
        !           105:                ia->ia_iosize = UHA_ISA_IOSIZE;
        !           106:        }
        !           107:        return (rv);
        !           108: }
        !           109:
        !           110: /*
        !           111:  * Attach all the sub-devices we can find
        !           112:  */
        !           113: void
        !           114: uha_isa_attach(parent, self, aux)
        !           115:        struct device *parent, *self;
        !           116:        void *aux;
        !           117: {
        !           118:        struct isa_attach_args *ia = aux;
        !           119:        struct uha_softc *sc = (void *)self;
        !           120:        bus_space_tag_t iot = ia->ia_iot;
        !           121:        bus_space_handle_t ioh;
        !           122:        isa_chipset_tag_t ic = ia->ia_ic;
        !           123:
        !           124:        printf("\n");
        !           125:
        !           126:        if (bus_space_map(iot, ia->ia_iobase, UHA_ISA_IOSIZE, 0, &ioh))
        !           127:                panic("uha_attach: bus_space_map failed!");
        !           128:
        !           129:        sc->sc_iot = iot;
        !           130:        sc->sc_ioh = ioh;
        !           131:        if (!u14_find(iot, ioh, sc))
        !           132:                panic("uha_attach: u14_find failed!");
        !           133:
        !           134:        if (sc->sc_drq != -1)
        !           135:                isadma_cascade(sc->sc_drq);
        !           136:
        !           137:        sc->sc_ih = isa_intr_establish(ic, sc->sc_irq, IST_EDGE, IPL_BIO,
        !           138:            u14_intr, sc, sc->sc_dev.dv_xname);
        !           139:        if (sc->sc_ih == NULL) {
        !           140:                printf("%s: couldn't establish interrupt\n",
        !           141:                    sc->sc_dev.dv_xname);
        !           142:                return;
        !           143:        }
        !           144:
        !           145:        /* Save function pointers for later use. */
        !           146:        sc->start_mbox = u14_start_mbox;
        !           147:        sc->poll = u14_poll;
        !           148:        sc->init = u14_init;
        !           149:
        !           150:        uha_attach(sc);
        !           151: }
        !           152:
        !           153: /*
        !           154:  * Start the board, ready for normal operation
        !           155:  */
        !           156: int
        !           157: u14_find(iot, ioh, sc)
        !           158:        bus_space_tag_t iot;
        !           159:        bus_space_handle_t ioh;
        !           160:        struct uha_softc *sc;
        !           161: {
        !           162:        u_int16_t model, config;
        !           163:        int irq, drq;
        !           164:        int resetcount = 4000;  /* 4 secs? */
        !           165:
        !           166:        model = (bus_space_read_1(iot, ioh, U14_ID + 0) << 8) |
        !           167:                (bus_space_read_1(iot, ioh, U14_ID + 1) << 0);
        !           168:        if ((model & 0xfff0) != 0x5640)
        !           169:                return (0);
        !           170:
        !           171:        config = (bus_space_read_1(iot, ioh, U14_CONFIG + 0) << 8) |
        !           172:                 (bus_space_read_1(iot, ioh, U14_CONFIG + 1) << 0);
        !           173:
        !           174:        switch (model & 0x000f) {
        !           175:        case 0x0000:
        !           176:                switch (config & U14_DMA_MASK) {
        !           177:                case U14_DMA_CH5:
        !           178:                        drq = 5;
        !           179:                        break;
        !           180:                case U14_DMA_CH6:
        !           181:                        drq = 6;
        !           182:                        break;
        !           183:                case U14_DMA_CH7:
        !           184:                        drq = 7;
        !           185:                        break;
        !           186:                default:
        !           187:                        printf("u14_find: illegal drq setting %x\n",
        !           188:                            config & U14_DMA_MASK);
        !           189:                        return (0);
        !           190:                }
        !           191:                break;
        !           192:        case 0x0001:
        !           193:                /* This is a 34f, and doesn't need an ISA DMA channel. */
        !           194:                drq = -1;
        !           195:                break;
        !           196:        default:
        !           197:                printf("u14_find: unknown model %x\n", model);
        !           198:                return (0);
        !           199:        }
        !           200:
        !           201:        switch (config & U14_IRQ_MASK) {
        !           202:        case U14_IRQ10:
        !           203:                irq = 10;
        !           204:                break;
        !           205:        case U14_IRQ11:
        !           206:                irq = 11;
        !           207:                break;
        !           208:        case U14_IRQ14:
        !           209:                irq = 14;
        !           210:                break;
        !           211:        case U14_IRQ15:
        !           212:                irq = 15;
        !           213:                break;
        !           214:        default:
        !           215:                printf("u14_find: illegal irq setting %x\n",
        !           216:                    config & U14_IRQ_MASK);
        !           217:                return (0);
        !           218:        }
        !           219:
        !           220:        bus_space_write_1(iot, ioh, U14_LINT, UHA_ASRST);
        !           221:
        !           222:        while (--resetcount) {
        !           223:                if (bus_space_read_1(iot, ioh, U14_LINT))
        !           224:                        break;
        !           225:                delay(1000);    /* 1 mSec per loop */
        !           226:        }
        !           227:        if (!resetcount) {
        !           228:                printf("u14_find: board timed out during reset\n");
        !           229:                return (0);
        !           230:        }
        !           231:
        !           232:        /* if we want to fill in softc, do so now */
        !           233:        if (sc != NULL) {
        !           234:                sc->sc_irq = irq;
        !           235:                sc->sc_drq = drq;
        !           236:                sc->sc_scsi_dev = config & U14_HOSTID_MASK;
        !           237:        }
        !           238:
        !           239:        return (1);
        !           240: }
        !           241:
        !           242: /*
        !           243:  * Function to send a command out through a mailbox
        !           244:  */
        !           245: void
        !           246: u14_start_mbox(sc, mscp)
        !           247:        struct uha_softc *sc;
        !           248:        struct uha_mscp *mscp;
        !           249: {
        !           250:        bus_space_tag_t iot = sc->sc_iot;
        !           251:        bus_space_handle_t ioh = sc->sc_ioh;
        !           252:        int spincount = 100000; /* 1s should be enough */
        !           253:
        !           254:        while (--spincount) {
        !           255:                if ((bus_space_read_1(iot, ioh, U14_LINT) & U14_LDIP) == 0)
        !           256:                        break;
        !           257:                delay(100);
        !           258:        }
        !           259:        if (!spincount) {
        !           260:                printf("%s: uha_start_mbox, board not responding\n",
        !           261:                    sc->sc_dev.dv_xname);
        !           262:                Debugger();
        !           263:        }
        !           264:
        !           265:        bus_space_write_4(iot, ioh, U14_OGMPTR, KVTOPHYS(mscp));
        !           266:        if (mscp->flags & MSCP_ABORT)
        !           267:                bus_space_write_1(iot, ioh, U14_LINT, U14_ABORT);
        !           268:        else
        !           269:                bus_space_write_1(iot, ioh, U14_LINT, U14_OGMFULL);
        !           270:
        !           271:        if ((mscp->xs->flags & SCSI_POLL) == 0)
        !           272:                timeout_add(&mscp->xs->stimeout, (mscp->timeout * hz) / 1000);
        !           273: }
        !           274:
        !           275: /*
        !           276:  * Function to poll for command completion when in poll mode.
        !           277:  *
        !           278:  *     wait = timeout in msec
        !           279:  */
        !           280: int
        !           281: u14_poll(sc, xs, count)
        !           282:        struct uha_softc *sc;
        !           283:        struct scsi_xfer *xs;
        !           284:        int count;
        !           285: {
        !           286:        bus_space_tag_t iot = sc->sc_iot;
        !           287:        bus_space_handle_t ioh = sc->sc_ioh;
        !           288:
        !           289:        while (count) {
        !           290:                /*
        !           291:                 * If we had interrupts enabled, would we
        !           292:                 * have got an interrupt?
        !           293:                 */
        !           294:                if (bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP)
        !           295:                        u14_intr(sc);
        !           296:                if (xs->flags & ITSDONE)
        !           297:                        return (0);
        !           298:                delay(1000);
        !           299:                count--;
        !           300:        }
        !           301:        return (1);
        !           302: }
        !           303:
        !           304: /*
        !           305:  * Catch an interrupt from the adaptor
        !           306:  */
        !           307: int
        !           308: u14_intr(arg)
        !           309:        void *arg;
        !           310: {
        !           311:        struct uha_softc *sc = arg;
        !           312:        bus_space_tag_t iot = sc->sc_iot;
        !           313:        bus_space_handle_t ioh = sc->sc_ioh;
        !           314:        struct uha_mscp *mscp;
        !           315:        u_char uhastat;
        !           316:        u_long mboxval;
        !           317:
        !           318: #ifdef UHADEBUG
        !           319:        printf("%s: uhaintr ", sc->sc_dev.dv_xname);
        !           320: #endif /*UHADEBUG */
        !           321:
        !           322:        if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
        !           323:                return (0);
        !           324:
        !           325:        for (;;) {
        !           326:                /*
        !           327:                 * First get all the information and then
        !           328:                 * acknowledge the interrupt
        !           329:                 */
        !           330:                uhastat = bus_space_read_1(iot, ioh, U14_SINT);
        !           331:                mboxval = bus_space_read_4(iot, ioh, U14_ICMPTR);
        !           332:                /* XXX Send an ABORT_ACK instead? */
        !           333:                bus_space_write_1(iot, ioh, U14_SINT, U14_ICM_ACK);
        !           334:
        !           335: #ifdef UHADEBUG
        !           336:                printf("status = 0x%x ", uhastat);
        !           337: #endif /*UHADEBUG*/
        !           338:
        !           339:                /*
        !           340:                 * Process the completed operation
        !           341:                 */
        !           342:                mscp = uha_mscp_phys_kv(sc, mboxval);
        !           343:                if (!mscp) {
        !           344:                        printf("%s: BAD MSCP RETURNED!\n",
        !           345:                            sc->sc_dev.dv_xname);
        !           346:                        continue;       /* whatever it was, it'll timeout */
        !           347:                }
        !           348:
        !           349:                timeout_del(&mscp->xs->stimeout);
        !           350:                uha_done(sc, mscp);
        !           351:
        !           352:                if ((bus_space_read_1(iot, ioh, U14_SINT) & U14_SDIP) == 0)
        !           353:                        return (1);
        !           354:        }
        !           355: }
        !           356:
        !           357: void
        !           358: u14_init(sc)
        !           359:        struct uha_softc *sc;
        !           360: {
        !           361:        bus_space_tag_t iot = sc->sc_iot;
        !           362:        bus_space_handle_t ioh = sc->sc_ioh;
        !           363:
        !           364:        /* make sure interrupts are enabled */
        !           365: #ifdef UHADEBUG
        !           366:        printf("u14_init: lmask=%02x, smask=%02x\n",
        !           367:            bus_space_read_1(iot, ioh, U14_LMASK),
        !           368:            bus_space_read_1(iot, ioh, U14_SMASK));
        !           369: #endif
        !           370:        bus_space_write_1(iot, ioh, U14_LMASK, 0xd1);   /* XXX */
        !           371:        bus_space_write_1(iot, ioh, U14_SMASK, 0x91);   /* XXX */
        !           372: }

CVSweb