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

Annotation of sys/dev/eisa/uha_eisa.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: uha_eisa.c,v 1.6 2007/04/10 17:47:55 miod Exp $       */
        !             2: /*     $NetBSD: uha_eisa.c,v 1.5 1996/10/21 22:31:07 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/eisa/eisavar.h>
        !            48: #include <dev/eisa/eisadevs.h>
        !            49:
        !            50: #include <dev/ic/uhareg.h>
        !            51: #include <dev/ic/uhavar.h>
        !            52:
        !            53: #define        UHA_EISA_SLOT_OFFSET    0xc80
        !            54: #define        UHA_EISA_IOSIZE         0x020
        !            55:
        !            56: #ifndef DDB
        !            57: #define        Debugger() panic("should call debugger here (uha_eisa.c)")
        !            58: #endif
        !            59:
        !            60: int    uha_eisa_match(struct device *, void *, void *);
        !            61: void   uha_eisa_attach(struct device *, struct device *, void *);
        !            62:
        !            63: struct cfattach uha_eisa_ca = {
        !            64:        sizeof(struct uha_softc), uha_eisa_match, uha_eisa_attach
        !            65: };
        !            66:
        !            67: #define KVTOPHYS(x)    vtophys((vaddr_t)(x))
        !            68:
        !            69: int u24_find(bus_space_tag_t, bus_space_handle_t, struct uha_softc *);
        !            70: void u24_start_mbox(struct uha_softc *, struct uha_mscp *);
        !            71: int u24_poll(struct uha_softc *, struct scsi_xfer *, int);
        !            72: int u24_intr(void *);
        !            73: void u24_init(struct uha_softc *);
        !            74:
        !            75: /*
        !            76:  * Check the slots looking for a board we recognise
        !            77:  * If we find one, note its address (slot) and call
        !            78:  * the actual probe routine to check it out.
        !            79:  */
        !            80: int
        !            81: uha_eisa_match(parent, match, aux)
        !            82:        struct device *parent;
        !            83:        void *match, *aux;
        !            84: {
        !            85:        struct eisa_attach_args *ea = aux;
        !            86:        bus_space_tag_t iot = ea->ea_iot;
        !            87:        bus_space_handle_t ioh;
        !            88:        int rv;
        !            89:
        !            90:        /* must match one of our known ID strings */
        !            91:        if (strncmp(ea->ea_idstring, "USC024", 6))
        !            92:                return (0);
        !            93:
        !            94:        if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
        !            95:            UHA_EISA_SLOT_OFFSET, UHA_EISA_IOSIZE, 0, &ioh))
        !            96:                return (0);
        !            97:
        !            98:        rv = u24_find(iot, ioh, NULL);
        !            99:
        !           100:        bus_space_unmap(iot, ioh, UHA_EISA_IOSIZE);
        !           101:
        !           102:        return (rv);
        !           103: }
        !           104:
        !           105: /*
        !           106:  * Attach all the sub-devices we can find
        !           107:  */
        !           108: void
        !           109: uha_eisa_attach(parent, self, aux)
        !           110:        struct device *parent, *self;
        !           111:        void *aux;
        !           112: {
        !           113:        struct eisa_attach_args *ea = aux;
        !           114:        struct uha_softc *sc = (void *)self;
        !           115:        bus_space_tag_t iot = ea->ea_iot;
        !           116:        bus_space_handle_t ioh;
        !           117:        eisa_chipset_tag_t ec = ea->ea_ec;
        !           118:        eisa_intr_handle_t ih;
        !           119:        const char *model, *intrstr;
        !           120:
        !           121:        if (!strncmp(ea->ea_idstring, "USC024", 6))
        !           122:                model = EISA_PRODUCT_USC0240;
        !           123:        else
        !           124:                model = "unknown model!";
        !           125:        printf(": %s\n", model);
        !           126:
        !           127:        if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
        !           128:            UHA_EISA_SLOT_OFFSET, UHA_EISA_IOSIZE, 0, &ioh))
        !           129:                panic("uha_attach: could not map I/O addresses");
        !           130:
        !           131:        sc->sc_iot = iot;
        !           132:        sc->sc_ioh = ioh;
        !           133:        if (!u24_find(iot, ioh, sc))
        !           134:                panic("uha_attach: u24_find failed!");
        !           135:
        !           136:        if (eisa_intr_map(ec, sc->sc_irq, &ih)) {
        !           137:                printf("%s: couldn't map interrupt (%d)\n",
        !           138:                    sc->sc_dev.dv_xname, sc->sc_irq);
        !           139:                return;
        !           140:        }
        !           141:        intrstr = eisa_intr_string(ec, ih);
        !           142:        sc->sc_ih = eisa_intr_establish(ec, ih, IST_LEVEL, IPL_BIO,
        !           143:            u24_intr, sc, sc->sc_dev.dv_xname);
        !           144:        if (sc->sc_ih == NULL) {
        !           145:                printf("%s: couldn't establish interrupt",
        !           146:                    sc->sc_dev.dv_xname);
        !           147:                if (intrstr != NULL)
        !           148:                        printf(" at %s", intrstr);
        !           149:                printf("\n");
        !           150:                return;
        !           151:        }
        !           152:        printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr);
        !           153:
        !           154:        /* Save function pointers for later use. */
        !           155:        sc->start_mbox = u24_start_mbox;
        !           156:        sc->poll = u24_poll;
        !           157:        sc->init = u24_init;
        !           158:
        !           159:        uha_attach(sc);
        !           160: }
        !           161:
        !           162: int
        !           163: u24_find(iot, ioh, sc)
        !           164:        bus_space_tag_t iot;
        !           165:        bus_space_handle_t ioh;
        !           166:        struct uha_softc *sc;
        !           167: {
        !           168:        u_int8_t config0, config1, config2;
        !           169:        int irq, drq;
        !           170:        int resetcount = 4000;  /* 4 secs? */
        !           171:
        !           172:        config0 = bus_space_read_1(iot, ioh, U24_CONFIG + 0);
        !           173:        config1 = bus_space_read_1(iot, ioh, U24_CONFIG + 1);
        !           174:        config2 = bus_space_read_1(iot, ioh, U24_CONFIG + 2);
        !           175:        if ((config0 & U24_MAGIC1) == 0 ||
        !           176:            (config1 & U24_MAGIC2) == 0)
        !           177:                return (0);
        !           178:
        !           179:        drq = -1;
        !           180:
        !           181:        switch (config0 & U24_IRQ_MASK) {
        !           182:        case U24_IRQ10:
        !           183:                irq = 10;
        !           184:                break;
        !           185:        case U24_IRQ11:
        !           186:                irq = 11;
        !           187:                break;
        !           188:        case U24_IRQ14:
        !           189:                irq = 14;
        !           190:                break;
        !           191:        case U24_IRQ15:
        !           192:                irq = 15;
        !           193:                break;
        !           194:        default:
        !           195:                printf("u24_find: illegal irq setting %x\n",
        !           196:                    config0 & U24_IRQ_MASK);
        !           197:                return (0);
        !           198:        }
        !           199:
        !           200:        bus_space_write_1(iot, ioh, U24_LINT, UHA_ASRST);
        !           201:
        !           202:        while (--resetcount) {
        !           203:                if (bus_space_read_1(iot, ioh, U24_LINT))
        !           204:                        break;
        !           205:                delay(1000);    /* 1 mSec per loop */
        !           206:        }
        !           207:        if (!resetcount) {
        !           208:                printf("u24_find: board timed out during reset\n");
        !           209:                return (0);
        !           210:        }
        !           211:
        !           212:        /* if we want to fill in softc, do so now */
        !           213:        if (sc != NULL) {
        !           214:                sc->sc_irq = irq;
        !           215:                sc->sc_drq = drq;
        !           216:                sc->sc_scsi_dev = config2 & U24_HOSTID_MASK;
        !           217:        }
        !           218:
        !           219:        return (1);
        !           220: }
        !           221:
        !           222: void
        !           223: u24_start_mbox(sc, mscp)
        !           224:        struct uha_softc *sc;
        !           225:        struct uha_mscp *mscp;
        !           226: {
        !           227:        bus_space_tag_t iot = sc->sc_iot;
        !           228:        bus_space_handle_t ioh = sc->sc_ioh;
        !           229:        int spincount = 100000; /* 1s should be enough */
        !           230:
        !           231:        while (--spincount) {
        !           232:                if ((bus_space_read_1(iot, ioh, U24_LINT) & U24_LDIP) == 0)
        !           233:                        break;
        !           234:                delay(100);
        !           235:        }
        !           236:        if (!spincount) {
        !           237:                printf("%s: uha_start_mbox, board not responding\n",
        !           238:                    sc->sc_dev.dv_xname);
        !           239:                Debugger();
        !           240:        }
        !           241:
        !           242:        bus_space_write_4(iot, ioh, U24_OGMPTR, KVTOPHYS(mscp));
        !           243:        if (mscp->flags & MSCP_ABORT)
        !           244:                bus_space_write_1(iot, ioh, U24_OGMCMD, 0x80);
        !           245:        else
        !           246:                bus_space_write_1(iot, ioh, U24_OGMCMD, 0x01);
        !           247:        bus_space_write_1(iot, ioh, U24_LINT, U24_OGMFULL);
        !           248:
        !           249:        if ((mscp->xs->flags & SCSI_POLL) == 0)
        !           250:                timeout_add(&mscp->xs->stimeout, (mscp->timeout * hz) / 1000);
        !           251: }
        !           252:
        !           253: int
        !           254: u24_poll(sc, xs, count)
        !           255:        struct uha_softc *sc;
        !           256:        struct scsi_xfer *xs;
        !           257:        int count;
        !           258: {
        !           259:        bus_space_tag_t iot = sc->sc_iot;
        !           260:        bus_space_handle_t ioh = sc->sc_ioh;
        !           261:
        !           262:        while (count) {
        !           263:                /*
        !           264:                 * If we had interrupts enabled, would we
        !           265:                 * have got an interrupt?
        !           266:                 */
        !           267:                if (bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP)
        !           268:                        u24_intr(sc);
        !           269:                if (xs->flags & ITSDONE)
        !           270:                        return (0);
        !           271:                delay(1000);
        !           272:                count--;
        !           273:        }
        !           274:        return (1);
        !           275: }
        !           276:
        !           277: int
        !           278: u24_intr(arg)
        !           279:        void *arg;
        !           280: {
        !           281:        struct uha_softc *sc = arg;
        !           282:        bus_space_tag_t iot = sc->sc_iot;
        !           283:        bus_space_handle_t ioh = sc->sc_ioh;
        !           284:        struct uha_mscp *mscp;
        !           285:        u_char uhastat;
        !           286:        u_long mboxval;
        !           287:
        !           288: #ifdef UHADEBUG
        !           289:        printf("%s: uhaintr ", sc->sc_dev.dv_xname);
        !           290: #endif /*UHADEBUG */
        !           291:
        !           292:        if ((bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP) == 0)
        !           293:                return (0);
        !           294:
        !           295:        for (;;) {
        !           296:                /*
        !           297:                 * First get all the information and then
        !           298:                 * acknowledge the interrupt
        !           299:                 */
        !           300:                uhastat = bus_space_read_1(iot, ioh, U24_SINT);
        !           301:                mboxval = bus_space_read_4(iot, ioh, U24_ICMPTR);
        !           302:                bus_space_write_1(iot, ioh, U24_SINT, U24_ICM_ACK);
        !           303:                bus_space_write_1(iot, ioh, U24_ICMCMD, 0);
        !           304:
        !           305: #ifdef UHADEBUG
        !           306:                printf("status = 0x%x ", uhastat);
        !           307: #endif /*UHADEBUG*/
        !           308:
        !           309:                /*
        !           310:                 * Process the completed operation
        !           311:                 */
        !           312:                mscp = uha_mscp_phys_kv(sc, mboxval);
        !           313:                if (!mscp) {
        !           314:                        printf("%s: BAD MSCP RETURNED!\n",
        !           315:                            sc->sc_dev.dv_xname);
        !           316:                        continue;       /* whatever it was, it'll timeout */
        !           317:                }
        !           318:                timeout_del(&mscp->xs->stimeout);
        !           319:                uha_done(sc, mscp);
        !           320:
        !           321:                if ((bus_space_read_1(iot, ioh, U24_SINT) & U24_SDIP) == 0)
        !           322:                        return (1);
        !           323:        }
        !           324: }
        !           325:
        !           326: void
        !           327: u24_init(sc)
        !           328:        struct uha_softc *sc;
        !           329: {
        !           330:        bus_space_tag_t iot = sc->sc_iot;
        !           331:        bus_space_handle_t ioh = sc->sc_ioh;
        !           332:
        !           333:        /* free OGM and ICM */
        !           334:        bus_space_write_1(iot, ioh, U24_OGMCMD, 0);
        !           335:        bus_space_write_1(iot, ioh, U24_ICMCMD, 0);
        !           336:        /* make sure interrupts are enabled */
        !           337: #ifdef UHADEBUG
        !           338:        printf("u24_init: lmask=%02x, smask=%02x\n",
        !           339:            bus_space_read_1(iot, ioh, U24_LMASK),
        !           340:            bus_space_read_1(iot, ioh, U24_SMASK));
        !           341: #endif
        !           342:        bus_space_write_1(iot, ioh, U24_LMASK, 0xd2);   /* XXX */
        !           343:        bus_space_write_1(iot, ioh, U24_SMASK, 0x92);   /* XXX */
        !           344: }

CVSweb