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

Annotation of sys/dev/ic/bha.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: bha.c,v 1.10 2007/04/10 17:47:55 miod Exp $   */
        !             2: /*     $NetBSD: bha.c,v 1.27 1998/11/19 21:53:00 thorpej Exp $ */
        !             3:
        !             4: #undef BHADEBUG
        !             5: #ifdef DDB
        !             6: #define        integrate
        !             7: #else
        !             8: #define        integrate       static inline
        !             9: #endif
        !            10:
        !            11: /*-
        !            12:  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
        !            13:  * All rights reserved.
        !            14:  *
        !            15:  * This code is derived from software contributed to The NetBSD Foundation
        !            16:  * by Charles M. Hannum and by Jason R. Thorpe of the Numerical Aerospace
        !            17:  * Simulation Facility, NASA Ames Research Center.
        !            18:  *
        !            19:  * Redistribution and use in source and binary forms, with or without
        !            20:  * modification, are permitted provided that the following conditions
        !            21:  * are met:
        !            22:  * 1. Redistributions of source code must retain the above copyright
        !            23:  *    notice, this list of conditions and the following disclaimer.
        !            24:  * 2. Redistributions in binary form must reproduce the above copyright
        !            25:  *    notice, this list of conditions and the following disclaimer in the
        !            26:  *    documentation and/or other materials provided with the distribution.
        !            27:  * 3. All advertising materials mentioning features or use of this software
        !            28:  *    must display the following acknowledgement:
        !            29:  *     This product includes software developed by the NetBSD
        !            30:  *     Foundation, Inc. and its contributors.
        !            31:  * 4. Neither the name of The NetBSD Foundation nor the names of its
        !            32:  *    contributors may be used to endorse or promote products derived
        !            33:  *    from this software without specific prior written permission.
        !            34:  *
        !            35:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
        !            36:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            37:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            38:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
        !            39:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            40:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            41:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            42:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            43:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            44:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            45:  * POSSIBILITY OF SUCH DAMAGE.
        !            46:  */
        !            47:
        !            48: /*
        !            49:  * Originally written by Julian Elischer (julian@tfs.com)
        !            50:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
        !            51:  *
        !            52:  * TRW Financial Systems, in accordance with their agreement with Carnegie
        !            53:  * Mellon University, makes this software available to CMU to distribute
        !            54:  * or use in any manner that they see fit as long as this message is kept with
        !            55:  * the software. For this reason TFS also grants any other persons or
        !            56:  * organisations permission to use or modify this software.
        !            57:  *
        !            58:  * TFS supplies this software to be publicly redistributed
        !            59:  * on the understanding that TFS is not responsible for the correct
        !            60:  * functioning of this software in any circumstances.
        !            61:  */
        !            62:
        !            63: #include <sys/types.h>
        !            64: #include <sys/param.h>
        !            65: #include <sys/systm.h>
        !            66: #include <sys/kernel.h>
        !            67: #include <sys/errno.h>
        !            68: #include <sys/ioctl.h>
        !            69: #include <sys/device.h>
        !            70: #include <sys/malloc.h>
        !            71: #include <sys/buf.h>
        !            72: #include <sys/proc.h>
        !            73: #include <sys/user.h>
        !            74:
        !            75: #include <machine/bus.h>
        !            76: #include <machine/intr.h>
        !            77:
        !            78: #include <scsi/scsi_all.h>
        !            79: #include <scsi/scsiconf.h>
        !            80:
        !            81: #include <dev/ic/bhareg.h>
        !            82: #include <dev/ic/bhavar.h>
        !            83:
        !            84: #ifndef DDB
        !            85: #define Debugger() panic("should call debugger here (bha.c)")
        !            86: #endif /* ! DDB */
        !            87:
        !            88: #define        BHA_MAXXFER     ((BHA_NSEG - 1) << PGSHIFT)
        !            89: #define        ISWIDE(sc)      ((sc)->sc_iswide)
        !            90:
        !            91: #ifdef BHADEBUG
        !            92: int     bha_debug = 1;
        !            93: #endif /* BHADEBUG */
        !            94:
        !            95: integrate void bha_finish_ccbs(struct bha_softc *);
        !            96: integrate void bha_reset_ccb(struct bha_softc *, struct bha_ccb *);
        !            97: void bha_free_ccb(struct bha_softc *, struct bha_ccb *);
        !            98: integrate int bha_init_ccb(struct bha_softc *, struct bha_ccb *);
        !            99: struct bha_ccb *bha_get_ccb(struct bha_softc *, int);
        !           100: struct bha_ccb *bha_ccb_phys_kv(struct bha_softc *, u_long);
        !           101: void bha_queue_ccb(struct bha_softc *, struct bha_ccb *);
        !           102: void bha_collect_mbo(struct bha_softc *);
        !           103: void bha_start_ccbs(struct bha_softc *);
        !           104: void bha_done(struct bha_softc *, struct bha_ccb *);
        !           105: int bha_init(struct bha_softc *);
        !           106: void bhaminphys(struct buf *);
        !           107: int bha_scsi_cmd(struct scsi_xfer *);
        !           108: int bha_poll(struct bha_softc *, struct scsi_xfer *, int);
        !           109: void bha_timeout(void *arg);
        !           110: int bha_create_ccbs(struct bha_softc *, struct bha_ccb *, int);
        !           111: void bha_enqueue(struct bha_softc *, struct scsi_xfer *, int);
        !           112: struct scsi_xfer *bha_dequeue(struct bha_softc *);
        !           113:
        !           114: struct cfdriver bha_cd = {
        !           115:        NULL, "bha", DV_DULL
        !           116: };
        !           117:
        !           118: /* the below structure is so we have a default dev struct for out link struct */
        !           119: struct scsi_device bha_dev = {
        !           120:        NULL,                   /* Use default error handler */
        !           121:        NULL,                   /* have a queue, served by this */
        !           122:        NULL,                   /* have no async handler */
        !           123:        NULL,                   /* Use default 'done' routine */
        !           124: };
        !           125:
        !           126: #define BHA_RESET_TIMEOUT      2000    /* time to wait for reset (mSec) */
        !           127: #define        BHA_ABORT_TIMEOUT       2000    /* time to wait for abort (mSec) */
        !           128:
        !           129: /*
        !           130:  * Insert a scsi_xfer into the software queue.  We overload xs->free_list
        !           131:  * to avoid having to allocate additional resources (since we're used
        !           132:  * only during resource shortages anyhow.
        !           133:  */
        !           134: void
        !           135: bha_enqueue(sc, xs, infront)
        !           136:        struct bha_softc *sc;
        !           137:        struct scsi_xfer *xs;
        !           138:        int infront;
        !           139: {
        !           140:
        !           141:        if (infront || LIST_EMPTY(&sc->sc_queue)) {
        !           142:                if (LIST_EMPTY(&sc->sc_queue))
        !           143:                        sc->sc_queuelast = xs;
        !           144:                LIST_INSERT_HEAD(&sc->sc_queue, xs, free_list);
        !           145:                return;
        !           146:        }
        !           147:
        !           148:        LIST_INSERT_AFTER(sc->sc_queuelast, xs, free_list);
        !           149:        sc->sc_queuelast = xs;
        !           150: }
        !           151:
        !           152: /*
        !           153:  * Pull a scsi_xfer off the front of the software queue.
        !           154:  */
        !           155: struct scsi_xfer *
        !           156: bha_dequeue(sc)
        !           157:        struct bha_softc *sc;
        !           158: {
        !           159:        struct scsi_xfer *xs;
        !           160:
        !           161:        xs = LIST_FIRST(&sc->sc_queue);
        !           162:        LIST_REMOVE(xs, free_list);
        !           163:
        !           164:        if (LIST_EMPTY(&sc->sc_queue))
        !           165:                sc->sc_queuelast = NULL;
        !           166:
        !           167:        return (xs);
        !           168: }
        !           169:
        !           170: /*
        !           171:  * bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
        !           172:  *
        !           173:  * Activate Adapter command
        !           174:  *    icnt:   number of args (outbound bytes including opcode)
        !           175:  *    ibuf:   argument buffer
        !           176:  *    ocnt:   number of expected returned bytes
        !           177:  *    obuf:   result buffer
        !           178:  *    wait:   number of seconds to wait for response
        !           179:  *
        !           180:  * Performs an adapter command through the ports.  Not to be confused with a
        !           181:  * scsi command, which is read in via the dma; one of the adapter commands
        !           182:  * tells it to read in a scsi command.
        !           183:  */
        !           184: int
        !           185: bha_cmd(iot, ioh, sc, icnt, ibuf, ocnt, obuf)
        !           186:        bus_space_tag_t iot;
        !           187:        bus_space_handle_t ioh;
        !           188:        struct bha_softc *sc;
        !           189:        int icnt, ocnt;
        !           190:        u_char *ibuf, *obuf;
        !           191: {
        !           192:        const char *name;
        !           193:        register int i;
        !           194:        int wait;
        !           195:        u_char sts;
        !           196:        u_char opcode = ibuf[0];
        !           197:
        !           198:        if (sc != NULL)
        !           199:                name = sc->sc_dev.dv_xname;
        !           200:        else
        !           201:                name = "(bha probe)";
        !           202:
        !           203:        /*
        !           204:         * Calculate a reasonable timeout for the command.
        !           205:         */
        !           206:        switch (opcode) {
        !           207:        case BHA_INQUIRE_DEVICES:
        !           208:        case BHA_INQUIRE_DEVICES_2:
        !           209:                wait = 90 * 20000;
        !           210:                break;
        !           211:        default:
        !           212:                wait = 1 * 20000;
        !           213:                break;
        !           214:        }
        !           215:
        !           216:        /*
        !           217:         * Wait for the adapter to go idle, unless it's one of
        !           218:         * the commands which don't need this
        !           219:         */
        !           220:        if (opcode != BHA_MBO_INTR_EN) {
        !           221:                for (i = 20000; i; i--) {       /* 1 sec? */
        !           222:                        sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
        !           223:                        if (sts & BHA_STAT_IDLE)
        !           224:                                break;
        !           225:                        delay(50);
        !           226:                }
        !           227:                if (!i) {
        !           228:                        printf("%s: bha_cmd, host not idle(0x%x)\n",
        !           229:                            name, sts);
        !           230:                        return (1);
        !           231:                }
        !           232:        }
        !           233:        /*
        !           234:         * Now that it is idle, if we expect output, preflush the
        !           235:         * queue feeding to us.
        !           236:         */
        !           237:        if (ocnt) {
        !           238:                while ((bus_space_read_1(iot, ioh, BHA_STAT_PORT)) &
        !           239:                    BHA_STAT_DF)
        !           240:                        bus_space_read_1(iot, ioh, BHA_DATA_PORT);
        !           241:        }
        !           242:        /*
        !           243:         * Output the command and the number of arguments given
        !           244:         * for each byte, first check the port is empty.
        !           245:         */
        !           246:        while (icnt--) {
        !           247:                for (i = wait; i; i--) {
        !           248:                        sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
        !           249:                        if (!(sts & BHA_STAT_CDF))
        !           250:                                break;
        !           251:                        delay(50);
        !           252:                }
        !           253:                if (!i) {
        !           254:                        if (opcode != BHA_INQUIRE_REVISION)
        !           255:                                printf("%s: bha_cmd, cmd/data port full\n",
        !           256:                                    name);
        !           257:                        goto bad;
        !           258:                }
        !           259:                bus_space_write_1(iot, ioh, BHA_CMD_PORT, *ibuf++);
        !           260:        }
        !           261:        /*
        !           262:         * If we expect input, loop that many times, each time,
        !           263:         * looking for the data register to have valid data
        !           264:         */
        !           265:        while (ocnt--) {
        !           266:                for (i = wait; i; i--) {
        !           267:                        sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
        !           268:                        if (sts & BHA_STAT_DF)
        !           269:                                break;
        !           270:                        delay(50);
        !           271:                }
        !           272:                if (!i) {
        !           273:                        if (opcode != BHA_INQUIRE_REVISION)
        !           274:                                printf("%s: bha_cmd, cmd/data port empty %d\n",
        !           275:                                    name, ocnt);
        !           276:                        goto bad;
        !           277:                }
        !           278:                *obuf++ = bus_space_read_1(iot, ioh, BHA_DATA_PORT);
        !           279:        }
        !           280:        /*
        !           281:         * Wait for the board to report a finished instruction.
        !           282:         * We may get an extra interrupt for the HACC signal, but this is
        !           283:         * unimportant.
        !           284:         */
        !           285:        if (opcode != BHA_MBO_INTR_EN && opcode != BHA_MODIFY_IOPORT) {
        !           286:                for (i = 20000; i; i--) {       /* 1 sec? */
        !           287:                        sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
        !           288:                        /* XXX Need to save this in the interrupt handler? */
        !           289:                        if (sts & BHA_INTR_HACC)
        !           290:                                break;
        !           291:                        delay(50);
        !           292:                }
        !           293:                if (!i) {
        !           294:                        printf("%s: bha_cmd, host not finished(0x%x)\n",
        !           295:                            name, sts);
        !           296:                        return (1);
        !           297:                }
        !           298:        }
        !           299:        bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
        !           300:        return (0);
        !           301:
        !           302: bad:
        !           303:        bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_SRST);
        !           304:        return (1);
        !           305: }
        !           306:
        !           307: /*
        !           308:  * Attach all the sub-devices we can find
        !           309:  */
        !           310: void
        !           311: bha_attach(sc, bpd)
        !           312:        struct bha_softc *sc;
        !           313:        struct bha_probe_data *bpd;
        !           314: {
        !           315:        struct scsibus_attach_args saa;
        !           316:        int s;
        !           317:
        !           318:        /*
        !           319:         * Fill in the adapter.
        !           320:         */
        !           321:        sc->sc_adapter.scsi_cmd = bha_scsi_cmd;
        !           322:        sc->sc_adapter.scsi_minphys = bhaminphys;
        !           323:
        !           324:        /*
        !           325:         * fill in the prototype scsi_link.
        !           326:         */
        !           327:        sc->sc_link.adapter_softc = sc;
        !           328:        sc->sc_link.adapter_target = bpd->sc_scsi_dev;
        !           329:        sc->sc_link.adapter = &sc->sc_adapter;
        !           330:        sc->sc_link.device = &bha_dev;
        !           331:        sc->sc_link.openings = 4;
        !           332:
        !           333:        TAILQ_INIT(&sc->sc_free_ccb);
        !           334:        TAILQ_INIT(&sc->sc_waiting_ccb);
        !           335:        LIST_INIT(&sc->sc_queue);
        !           336:
        !           337:        s = splbio();
        !           338:        bha_inquire_setup_information(sc);
        !           339:
        !           340:        printf("%s: model BT-%s, firmware %s\n", sc->sc_dev.dv_xname,
        !           341:            sc->sc_model, sc->sc_firmware);
        !           342:
        !           343:        if (bha_init(sc) != 0) {
        !           344:                /* Error during initialization! */
        !           345:                splx(s);
        !           346:                return;
        !           347:        }
        !           348:
        !           349:        splx(s);
        !           350:
        !           351:        bzero(&saa, sizeof(saa));
        !           352:        saa.saa_sc_link = &sc->sc_link;
        !           353:
        !           354:        /*
        !           355:         * ask the adapter what subunits are present
        !           356:         */
        !           357:        config_found(&sc->sc_dev, &saa, scsiprint);
        !           358: }
        !           359:
        !           360: integrate void
        !           361: bha_finish_ccbs(sc)
        !           362:        struct bha_softc *sc;
        !           363: {
        !           364:        struct bha_mbx_in *wmbi;
        !           365:        struct bha_ccb *ccb;
        !           366:        int i;
        !           367:
        !           368:        wmbi = wmbx->tmbi;
        !           369:
        !           370:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !           371:            0, sc->sc_dmamap_control->dm_mapsize,
        !           372:            BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !           373:
        !           374:        if (wmbi->comp_stat == BHA_MBI_FREE) {
        !           375:                for (i = 0; i < BHA_MBX_SIZE; i++) {
        !           376:                        if (wmbi->comp_stat != BHA_MBI_FREE) {
        !           377:                                printf("%s: mbi not in round-robin order\n",
        !           378:                                    sc->sc_dev.dv_xname);
        !           379:                                goto AGAIN;
        !           380:                        }
        !           381:                        bha_nextmbx(wmbi, wmbx, mbi);
        !           382:                        bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !           383:                            0, sc->sc_dmamap_control->dm_mapsize,
        !           384:                            BUS_DMASYNC_POSTREAD);
        !           385:                }
        !           386: #ifdef BHADIAGnot
        !           387:                printf("%s: mbi interrupt with no full mailboxes\n",
        !           388:                    sc->sc_dev.dv_xname);
        !           389: #endif
        !           390:                return;
        !           391:        }
        !           392:
        !           393: AGAIN:
        !           394:        do {
        !           395:                ccb = bha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
        !           396:                if (!ccb) {
        !           397:                        printf("%s: bad mbi ccb pointer; skipping\n",
        !           398:                            sc->sc_dev.dv_xname);
        !           399:                        goto next;
        !           400:                }
        !           401:
        !           402:                bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !           403:                    0, sc->sc_dmamap_control->dm_mapsize,
        !           404:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !           405:
        !           406: #ifdef BHADEBUG
        !           407:                if (bha_debug) {
        !           408:                        u_int8_t *cp = ccb->scsi_cmd.bytes;
        !           409:                        printf("op=%x %x %x %x %x %x\n",
        !           410:                                ccb->scsi_cmd.opcode,
        !           411:                                cp[0], cp[1], cp[2], cp[3], cp[4]);
        !           412:                        printf("stat %x for mbi addr = 0x%08x, ",
        !           413:                                wmbi->comp_stat, wmbi);
        !           414:                        printf("ccb addr = 0x%x\n", ccb);
        !           415:                }
        !           416: #endif /* BHADEBUG */
        !           417:
        !           418:                switch (wmbi->comp_stat) {
        !           419:                case BHA_MBI_OK:
        !           420:                case BHA_MBI_ERROR:
        !           421:                        if ((ccb->flags & CCB_ABORT) != 0) {
        !           422:                                /*
        !           423:                                 * If we already started an abort, wait for it
        !           424:                                 * to complete before clearing the CCB.  We
        !           425:                                 * could instead just clear CCB_SENDING, but
        !           426:                                 * what if the mailbox was already received?
        !           427:                                 * The worst that happens here is that we clear
        !           428:                                 * the CCB a bit later than we need to.  BFD.
        !           429:                                 */
        !           430:                                goto next;
        !           431:                        }
        !           432:                        break;
        !           433:
        !           434:                case BHA_MBI_ABORT:
        !           435:                case BHA_MBI_UNKNOWN:
        !           436:                        /*
        !           437:                         * Even if the CCB wasn't found, we clear it anyway.
        !           438:                         * See preceding comment.
        !           439:                         */
        !           440:                        break;
        !           441:
        !           442:                default:
        !           443:                        printf("%s: bad mbi status %02x; skipping\n",
        !           444:                            sc->sc_dev.dv_xname, wmbi->comp_stat);
        !           445:                        goto next;
        !           446:                }
        !           447:
        !           448:                timeout_del(&ccb->xs->stimeout);
        !           449:                bha_done(sc, ccb);
        !           450:
        !           451:        next:
        !           452:                wmbi->comp_stat = BHA_MBI_FREE;
        !           453:                bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !           454:                    0, sc->sc_dmamap_control->dm_mapsize,
        !           455:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !           456:                bha_nextmbx(wmbi, wmbx, mbi);
        !           457:                bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !           458:                    0, sc->sc_dmamap_control->dm_mapsize,
        !           459:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !           460:        } while (wmbi->comp_stat != BHA_MBI_FREE);
        !           461:
        !           462:        wmbx->tmbi = wmbi;
        !           463: }
        !           464:
        !           465: /*
        !           466:  * Catch an interrupt from the adaptor
        !           467:  */
        !           468: int
        !           469: bha_intr(arg)
        !           470:        void *arg;
        !           471: {
        !           472:        struct bha_softc *sc = arg;
        !           473:        bus_space_tag_t iot = sc->sc_iot;
        !           474:        bus_space_handle_t ioh = sc->sc_ioh;
        !           475:        u_char sts;
        !           476:
        !           477: #ifdef BHADEBUG
        !           478:        printf("%s: bha_intr ", sc->sc_dev.dv_xname);
        !           479: #endif /* BHADEBUG */
        !           480:
        !           481:        /*
        !           482:         * First acknowledge the interrupt, Then if it's not telling about
        !           483:         * a completed operation just return.
        !           484:         */
        !           485:        sts = bus_space_read_1(iot, ioh, BHA_INTR_PORT);
        !           486:        if ((sts & BHA_INTR_ANYINTR) == 0)
        !           487:                return (0);
        !           488:        bus_space_write_1(iot, ioh, BHA_CTRL_PORT, BHA_CTRL_IRST);
        !           489:
        !           490: #ifdef BHADIAG
        !           491:        /* Make sure we clear CCB_SENDING before finishing a CCB. */
        !           492:        bha_collect_mbo(sc);
        !           493: #endif
        !           494:
        !           495:        /* Mail box out empty? */
        !           496:        if (sts & BHA_INTR_MBOA) {
        !           497:                struct bha_toggle toggle;
        !           498:
        !           499:                toggle.cmd.opcode = BHA_MBO_INTR_EN;
        !           500:                toggle.cmd.enable = 0;
        !           501:                bha_cmd(iot, ioh, sc,
        !           502:                    sizeof(toggle.cmd), (u_char *)&toggle.cmd,
        !           503:                    0, (u_char *)0);
        !           504:                bha_start_ccbs(sc);
        !           505:        }
        !           506:
        !           507:        /* Mail box in full? */
        !           508:        if (sts & BHA_INTR_MBIF)
        !           509:                bha_finish_ccbs(sc);
        !           510:
        !           511:        return (1);
        !           512: }
        !           513:
        !           514: integrate void
        !           515: bha_reset_ccb(sc, ccb)
        !           516:        struct bha_softc *sc;
        !           517:        struct bha_ccb *ccb;
        !           518: {
        !           519:
        !           520:        ccb->flags = 0;
        !           521: }
        !           522:
        !           523: /*
        !           524:  * A ccb is put onto the free list.
        !           525:  */
        !           526: void
        !           527: bha_free_ccb(sc, ccb)
        !           528:        struct bha_softc *sc;
        !           529:        struct bha_ccb *ccb;
        !           530: {
        !           531:        int s;
        !           532:
        !           533:        s = splbio();
        !           534:
        !           535:        bha_reset_ccb(sc, ccb);
        !           536:        TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
        !           537:
        !           538:        /*
        !           539:         * If there were none, wake anybody waiting for one to come free,
        !           540:         * starting with queued entries.
        !           541:         */
        !           542:        if (TAILQ_NEXT(ccb, chain) == NULL)
        !           543:                wakeup(&sc->sc_free_ccb);
        !           544:
        !           545:        splx(s);
        !           546: }
        !           547:
        !           548: integrate int
        !           549: bha_init_ccb(sc, ccb)
        !           550:        struct bha_softc *sc;
        !           551:        struct bha_ccb *ccb;
        !           552: {
        !           553:        bus_dma_tag_t dmat = sc->sc_dmat;
        !           554:        int hashnum, error;
        !           555:
        !           556:        /*
        !           557:         * Create the DMA map for this CCB.
        !           558:         */
        !           559:        error = bus_dmamap_create(dmat, BHA_MAXXFER, BHA_NSEG, BHA_MAXXFER,
        !           560:            0, BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW | sc->sc_dmaflags,
        !           561:            &ccb->dmamap_xfer);
        !           562:        if (error) {
        !           563:                printf("%s: unable to create ccb DMA map, error = %d\n",
        !           564:                    sc->sc_dev.dv_xname, error);
        !           565:                return (error);
        !           566:        }
        !           567:
        !           568:        /*
        !           569:         * put in the phystokv hash table
        !           570:         * Never gets taken out.
        !           571:         */
        !           572:        ccb->hashkey = sc->sc_dmamap_control->dm_segs[0].ds_addr +
        !           573:            BHA_CCB_OFF(ccb);
        !           574:        hashnum = CCB_HASH(ccb->hashkey);
        !           575:        ccb->nexthash = sc->sc_ccbhash[hashnum];
        !           576:        sc->sc_ccbhash[hashnum] = ccb;
        !           577:        bha_reset_ccb(sc, ccb);
        !           578:        return (0);
        !           579: }
        !           580:
        !           581: /*
        !           582:  * Create a set of ccbs and add them to the free list.  Called once
        !           583:  * by bha_init().  We return the number of CCBs successfully created.
        !           584:  */
        !           585: int
        !           586: bha_create_ccbs(sc, ccbstore, count)
        !           587:        struct bha_softc *sc;
        !           588:        struct bha_ccb *ccbstore;
        !           589:        int count;
        !           590: {
        !           591:        struct bha_ccb *ccb;
        !           592:        int i, error;
        !           593:
        !           594:        bzero(ccbstore, sizeof(struct bha_ccb) * count);
        !           595:        for (i = 0; i < count; i++) {
        !           596:                ccb = &ccbstore[i];
        !           597:                if ((error = bha_init_ccb(sc, ccb)) != 0) {
        !           598:                        printf("%s: unable to initialize ccb, error = %d\n",
        !           599:                            sc->sc_dev.dv_xname, error);
        !           600:                        goto out;
        !           601:                }
        !           602:                TAILQ_INSERT_TAIL(&sc->sc_free_ccb, ccb, chain);
        !           603:        }
        !           604:  out:
        !           605:        return (i);
        !           606: }
        !           607:
        !           608: /*
        !           609:  * Get a free ccb
        !           610:  *
        !           611:  * If there are none, see if we can allocate a new one.  If so, put it in
        !           612:  * the hash table too otherwise either return an error or sleep.
        !           613:  */
        !           614: struct bha_ccb *
        !           615: bha_get_ccb(sc, flags)
        !           616:        struct bha_softc *sc;
        !           617:        int flags;
        !           618: {
        !           619:        struct bha_ccb *ccb;
        !           620:        int s;
        !           621:
        !           622:        s = splbio();
        !           623:
        !           624:        /*
        !           625:         * If we can and have to, sleep waiting for one to come free
        !           626:         * but only if we can't allocate a new one.
        !           627:         */
        !           628:        for (;;) {
        !           629:                ccb = TAILQ_FIRST(&sc->sc_free_ccb);
        !           630:                if (ccb) {
        !           631:                        TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
        !           632:                        break;
        !           633:                }
        !           634:                if ((flags & SCSI_NOSLEEP) != 0)
        !           635:                        goto out;
        !           636:                tsleep(&sc->sc_free_ccb, PRIBIO, "bhaccb", 0);
        !           637:        }
        !           638:
        !           639:        ccb->flags |= CCB_ALLOC;
        !           640:
        !           641: out:
        !           642:        splx(s);
        !           643:        return (ccb);
        !           644: }
        !           645:
        !           646: /*
        !           647:  * Given a physical address, find the ccb that it corresponds to.
        !           648:  */
        !           649: struct bha_ccb *
        !           650: bha_ccb_phys_kv(sc, ccb_phys)
        !           651:        struct bha_softc *sc;
        !           652:        u_long ccb_phys;
        !           653: {
        !           654:        int hashnum = CCB_HASH(ccb_phys);
        !           655:        struct bha_ccb *ccb = sc->sc_ccbhash[hashnum];
        !           656:
        !           657:        while (ccb) {
        !           658:                if (ccb->hashkey == ccb_phys)
        !           659:                        break;
        !           660:                ccb = ccb->nexthash;
        !           661:        }
        !           662:        return (ccb);
        !           663: }
        !           664:
        !           665: /*
        !           666:  * Queue a CCB to be sent to the controller, and send it if possible.
        !           667:  */
        !           668: void
        !           669: bha_queue_ccb(sc, ccb)
        !           670:        struct bha_softc *sc;
        !           671:        struct bha_ccb *ccb;
        !           672: {
        !           673:
        !           674:        timeout_set(&ccb->xs->stimeout, bha_timeout, ccb);
        !           675:        TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
        !           676:        bha_start_ccbs(sc);
        !           677: }
        !           678:
        !           679: /*
        !           680:  * Garbage collect mailboxes that are no longer in use.
        !           681:  */
        !           682: void
        !           683: bha_collect_mbo(sc)
        !           684:        struct bha_softc *sc;
        !           685: {
        !           686:        struct bha_mbx_out *wmbo;       /* Mail Box Out pointer */
        !           687: #ifdef BHADIAG
        !           688:        struct bha_ccb *ccb;
        !           689: #endif
        !           690:
        !           691:        wmbo = wmbx->cmbo;
        !           692:
        !           693:        while (sc->sc_mbofull > 0) {
        !           694:                bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !           695:                    0, sc->sc_dmamap_control->dm_mapsize,
        !           696:                    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
        !           697:                if (wmbo->cmd != BHA_MBO_FREE)
        !           698:                        break;
        !           699:
        !           700: #ifdef BHADIAG
        !           701:                ccb = bha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
        !           702:                ccb->flags &= ~CCB_SENDING;
        !           703: #endif
        !           704:
        !           705:                --sc->sc_mbofull;
        !           706:                bha_nextmbx(wmbo, wmbx, mbo);
        !           707:        }
        !           708:
        !           709:        wmbx->cmbo = wmbo;
        !           710: }
        !           711:
        !           712: /*
        !           713:  * Send as many CCBs as we have empty mailboxes for.
        !           714:  */
        !           715: void
        !           716: bha_start_ccbs(sc)
        !           717:        struct bha_softc *sc;
        !           718: {
        !           719:        bus_space_tag_t iot = sc->sc_iot;
        !           720:        bus_space_handle_t ioh = sc->sc_ioh;
        !           721:        struct bha_mbx_out *wmbo;       /* Mail Box Out pointer */
        !           722:        struct bha_ccb *ccb;
        !           723:        struct scsi_xfer *xs;
        !           724:
        !           725:        wmbo = wmbx->tmbo;
        !           726:
        !           727:        while ((ccb = TAILQ_FIRST(&sc->sc_waiting_ccb)) != NULL) {
        !           728:
        !           729:                xs = ccb->xs;
        !           730:                if (sc->sc_mbofull >= BHA_MBX_SIZE) {
        !           731:                        bha_collect_mbo(sc);
        !           732:                        if (sc->sc_mbofull >= BHA_MBX_SIZE) {
        !           733:                                struct bha_toggle toggle;
        !           734:
        !           735:                                toggle.cmd.opcode = BHA_MBO_INTR_EN;
        !           736:                                toggle.cmd.enable = 1;
        !           737:                                bha_cmd(iot, ioh, sc,
        !           738:                                    sizeof(toggle.cmd), (u_char *)&toggle.cmd,
        !           739:                                    0, (u_char *)0);
        !           740:                                break;
        !           741:                        }
        !           742:                }
        !           743:
        !           744:                TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
        !           745: #ifdef BHADIAG
        !           746:                ccb->flags |= CCB_SENDING;
        !           747: #endif
        !           748:
        !           749:                /* Link ccb to mbo. */
        !           750:                ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
        !           751:                    BHA_CCB_OFF(ccb), wmbo->ccb_addr);
        !           752:                if (ccb->flags & CCB_ABORT)
        !           753:                        wmbo->cmd = BHA_MBO_ABORT;
        !           754:                else
        !           755:                        wmbo->cmd = BHA_MBO_START;
        !           756:
        !           757:                bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !           758:                    0, sc->sc_dmamap_control->dm_mapsize,
        !           759:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !           760:
        !           761:                /* Tell the card to poll immediately. */
        !           762:                bus_space_write_1(iot, ioh, BHA_CMD_PORT, BHA_START_SCSI);
        !           763:
        !           764:                if ((xs->flags & SCSI_POLL) == 0)
        !           765:                        timeout_add(&xs->stimeout, (ccb->timeout * hz) / 1000);
        !           766:
        !           767:                ++sc->sc_mbofull;
        !           768:                bha_nextmbx(wmbo, wmbx, mbo);
        !           769:        }
        !           770:
        !           771:        wmbx->tmbo = wmbo;
        !           772: }
        !           773:
        !           774: /*
        !           775:  * We have a ccb which has been processed by the
        !           776:  * adaptor, now we look to see how the operation
        !           777:  * went. Wake up the owner if waiting
        !           778:  */
        !           779: void
        !           780: bha_done(sc, ccb)
        !           781:        struct bha_softc *sc;
        !           782:        struct bha_ccb *ccb;
        !           783: {
        !           784:        bus_dma_tag_t dmat = sc->sc_dmat;
        !           785:        struct scsi_sense_data *s1, *s2;
        !           786:        struct scsi_xfer *xs = ccb->xs;
        !           787:
        !           788:        SC_DEBUG(xs->sc_link, SDEV_DB2, ("bha_done\n"));
        !           789:
        !           790:        /*
        !           791:         * If we were a data transfer, unload the map that described
        !           792:         * the data buffer.
        !           793:         */
        !           794:        if (xs->datalen) {
        !           795:                bus_dmamap_sync(dmat, ccb->dmamap_xfer,
        !           796:                    0, ccb->dmamap_xfer->dm_mapsize,
        !           797:                    (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD :
        !           798:                    BUS_DMASYNC_POSTWRITE);
        !           799:                bus_dmamap_unload(dmat, ccb->dmamap_xfer);
        !           800:        }
        !           801:
        !           802:        /*
        !           803:         * Otherwise, put the results of the operation
        !           804:         * into the xfer and call whoever started it
        !           805:         */
        !           806: #ifdef BHADIAG
        !           807:        if (ccb->flags & CCB_SENDING) {
        !           808:                printf("%s: exiting ccb still in transit!\n",
        !           809:                    sc->sc_dev.dv_xname);
        !           810:                Debugger();
        !           811:                return;
        !           812:        }
        !           813: #endif
        !           814:        if ((ccb->flags & CCB_ALLOC) == 0) {
        !           815:                printf("%s: exiting ccb not allocated!\n",
        !           816:                    sc->sc_dev.dv_xname);
        !           817:                Debugger();
        !           818:                return;
        !           819:        }
        !           820:        if (xs->error == XS_NOERROR) {
        !           821:                if (ccb->host_stat != BHA_OK) {
        !           822:                        switch (ccb->host_stat) {
        !           823:                        case BHA_SEL_TIMEOUT:   /* No response */
        !           824:                                xs->error = XS_SELTIMEOUT;
        !           825:                                break;
        !           826:                        default:        /* Other scsi protocol messes */
        !           827:                                printf("%s: host_stat %x\n",
        !           828:                                    sc->sc_dev.dv_xname, ccb->host_stat);
        !           829:                                xs->error = XS_DRIVER_STUFFUP;
        !           830:                                break;
        !           831:                        }
        !           832:                } else if (ccb->target_stat != SCSI_OK) {
        !           833:                        switch (ccb->target_stat) {
        !           834:                        case SCSI_CHECK:
        !           835:                                s1 = &ccb->scsi_sense;
        !           836:                                s2 = &xs->sense;
        !           837:                                *s2 = *s1;
        !           838:                                xs->error = XS_SENSE;
        !           839:                                break;
        !           840:                        case SCSI_BUSY:
        !           841:                                xs->error = XS_BUSY;
        !           842:                                break;
        !           843:                        default:
        !           844:                                printf("%s: target_stat %x\n",
        !           845:                                    sc->sc_dev.dv_xname, ccb->target_stat);
        !           846:                                xs->error = XS_DRIVER_STUFFUP;
        !           847:                                break;
        !           848:                        }
        !           849:                } else
        !           850:                        xs->resid = 0;
        !           851:        }
        !           852:        bha_free_ccb(sc, ccb);
        !           853:        xs->flags |= ITSDONE;
        !           854:        scsi_done(xs);
        !           855:
        !           856:        /*
        !           857:         * If there are queue entries in the software queue, try to
        !           858:         * run the first one.  We should be more or less guaranteed
        !           859:         * to succeed, since we just freed a CCB.
        !           860:         *
        !           861:         * NOTE: bha_scsi_cmd() relies on our calling it with
        !           862:         * the first entry in the queue.
        !           863:         */
        !           864:        if ((xs = LIST_FIRST(&sc->sc_queue)) != NULL)
        !           865:                (void) bha_scsi_cmd(xs);
        !           866: }
        !           867:
        !           868: /*
        !           869:  * Find the board and find its irq/drq
        !           870:  */
        !           871: int
        !           872: bha_find(iot, ioh, sc)
        !           873:        bus_space_tag_t iot;
        !           874:        bus_space_handle_t ioh;
        !           875:        struct bha_probe_data *sc;
        !           876: {
        !           877:        int i, iswide;
        !           878:        u_char sts;
        !           879:        struct bha_extended_inquire inquire;
        !           880:        struct bha_config config;
        !           881:        int irq, drq;
        !           882:
        !           883:        /* Check something is at the ports we need to access */
        !           884:        sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
        !           885:        if (sts == 0xFF) {
        !           886: #ifdef BHADEBUG
        !           887:                if (bha_debug)
        !           888:                        printf("bha_find: Not present\n");
        !           889: #endif /* BHADEBUG */
        !           890:                return (0);
        !           891:        }
        !           892:
        !           893:        /*
        !           894:         * Reset board, If it doesn't respond, assume
        !           895:         * that it's not there.. good for the probe
        !           896:         */
        !           897:
        !           898:        bus_space_write_1(iot, ioh, BHA_CTRL_PORT,
        !           899:            BHA_CTRL_HRST | BHA_CTRL_SRST);
        !           900:
        !           901:        for (i = BHA_RESET_TIMEOUT; i--;) {
        !           902:                delay(100);
        !           903:                sts = bus_space_read_1(iot, ioh, BHA_STAT_PORT);
        !           904:                if (sts == (BHA_STAT_IDLE | BHA_STAT_INIT))
        !           905:                        break;
        !           906:        }
        !           907:        if (i < 0) {
        !           908: #ifdef BHADEBUG
        !           909:                if (bha_debug)
        !           910:                        printf("bha_find: No answer from board a=%x sts=%b\n",
        !           911:                            ioh, sts, BHA_STAT_BITS);
        !           912: #endif /* BHADEBUG */
        !           913:                return (0);
        !           914:        }
        !           915:
        !           916:        /*
        !           917:         * The BusLogic cards implement an Adaptec 1542 (aha)-compatible
        !           918:         * interface. The native bha interface is not compatible with
        !           919:         * an aha. 1542. We need to ensure that we never match an
        !           920:         * Adaptec 1542. We must also avoid sending Adaptec-compatible
        !           921:         * commands to a real bha, lest it go into 1542 emulation mode.
        !           922:         * (On an indirect bus like ISA, we should always probe for BusLogic
        !           923:         * interfaces  before Adaptec interfaces).
        !           924:         */
        !           925:
        !           926:        /*
        !           927:         * Make sure we don't match an AHA-1542A or AHA-1542B, by checking
        !           928:         * for an extended-geometry register.  The 1542[AB] don't have one.
        !           929:         */
        !           930:        sts = bus_space_read_1(iot, ioh, BHA_EXTGEOM_PORT);
        !           931:        if (sts == 0xFF)
        !           932:                return (0);
        !           933:
        !           934:        /*
        !           935:         * Check that we actually know how to use this board.
        !           936:         */
        !           937:        delay(1000);
        !           938:        inquire.cmd.opcode = BHA_INQUIRE_EXTENDED;
        !           939:        inquire.cmd.len = sizeof(inquire.reply);
        !           940:        i = bha_cmd(iot, ioh, NULL,
        !           941:            sizeof(inquire.cmd), (u_char *)&inquire.cmd,
        !           942:            sizeof(inquire.reply), (u_char *)&inquire.reply);
        !           943:
        !           944:        /*
        !           945:         * Some 1542Cs (CP, perhaps not CF, may depend on firmware rev)
        !           946:         * have the extended-geometry register and also respond to
        !           947:         * BHA_INQUIRE_EXTENDED.  Make sure we never  match such cards,
        !           948:         * by checking the size of the reply is what a BusLogic card returns.
        !           949:         */
        !           950:        if (i) {
        !           951: #ifdef BHADEBUG
        !           952:                printf("bha_find: board returned %d instead of %d to %s\n",
        !           953:                       i, sizeof(inquire.reply), "INQUIRE_EXTENDED");
        !           954: #endif
        !           955:                return (0);
        !           956:        }
        !           957:
        !           958:        /* OK, we know we've found a buslogic adaptor. */
        !           959:
        !           960:        switch (inquire.reply.bus_type) {
        !           961:        case BHA_BUS_TYPE_24BIT:
        !           962:        case BHA_BUS_TYPE_32BIT:
        !           963:                break;
        !           964:        case BHA_BUS_TYPE_MCA:
        !           965:                /* We don't grok MicroChannel (yet). */
        !           966:                return (0);
        !           967:        default:
        !           968:                printf("bha_find: illegal bus type %c\n",
        !           969:                    inquire.reply.bus_type);
        !           970:                return (0);
        !           971:        }
        !           972:
        !           973:        /* Note if we have a wide bus. */
        !           974:        iswide = inquire.reply.scsi_flags & BHA_SCSI_WIDE;
        !           975:
        !           976:        /*
        !           977:         * Assume we have a board at this stage setup dma channel from
        !           978:         * jumpers and save int level
        !           979:         */
        !           980:        delay(1000);
        !           981:        config.cmd.opcode = BHA_INQUIRE_CONFIG;
        !           982:        bha_cmd(iot, ioh, NULL,
        !           983:            sizeof(config.cmd), (u_char *)&config.cmd,
        !           984:            sizeof(config.reply), (u_char *)&config.reply);
        !           985:        switch (config.reply.chan) {
        !           986:        case EISADMA:
        !           987:                drq = -1;
        !           988:                break;
        !           989:        case CHAN0:
        !           990:                drq = 0;
        !           991:                break;
        !           992:        case CHAN5:
        !           993:                drq = 5;
        !           994:                break;
        !           995:        case CHAN6:
        !           996:                drq = 6;
        !           997:                break;
        !           998:        case CHAN7:
        !           999:                drq = 7;
        !          1000:                break;
        !          1001:        default:
        !          1002:                printf("bha_find: illegal drq setting %x\n",
        !          1003:                    config.reply.chan);
        !          1004:                return (0);
        !          1005:        }
        !          1006:
        !          1007:        switch (config.reply.intr) {
        !          1008:        case INT9:
        !          1009:                irq = 9;
        !          1010:                break;
        !          1011:        case INT10:
        !          1012:                irq = 10;
        !          1013:                break;
        !          1014:        case INT11:
        !          1015:                irq = 11;
        !          1016:                break;
        !          1017:        case INT12:
        !          1018:                irq = 12;
        !          1019:                break;
        !          1020:        case INT14:
        !          1021:                irq = 14;
        !          1022:                break;
        !          1023:        case INT15:
        !          1024:                irq = 15;
        !          1025:                break;
        !          1026:        default:
        !          1027:                printf("bha_find: illegal irq setting %x\n",
        !          1028:                    config.reply.intr);
        !          1029:                return (0);
        !          1030:        }
        !          1031:
        !          1032:        /* if we want to fill in softc, do so now */
        !          1033:        if (sc != NULL) {
        !          1034:                sc->sc_irq = irq;
        !          1035:                sc->sc_drq = drq;
        !          1036:                sc->sc_scsi_dev = config.reply.scsi_dev;
        !          1037:                sc->sc_iswide = iswide;
        !          1038:        }
        !          1039:
        !          1040:        return (1);
        !          1041: }
        !          1042:
        !          1043:
        !          1044: /*
        !          1045:  * Disable the ISA-compatibility ioports on PCI bha devices,
        !          1046:  * to ensure they're not autoconfigured a second time as an ISA bha.
        !          1047:  */
        !          1048: int
        !          1049: bha_disable_isacompat(sc)
        !          1050:        struct bha_softc *sc;
        !          1051: {
        !          1052:        struct bha_isadisable isa_disable;
        !          1053:
        !          1054:        isa_disable.cmd.opcode = BHA_MODIFY_IOPORT;
        !          1055:        isa_disable.cmd.modifier = BHA_IOMODIFY_DISABLE1;
        !          1056:        bha_cmd(sc->sc_iot, sc->sc_ioh, sc,
        !          1057:            sizeof(isa_disable.cmd), (u_char *)&isa_disable.cmd,
        !          1058:            0, (u_char *)0);
        !          1059:        return (0);
        !          1060: }
        !          1061:
        !          1062:
        !          1063: /*
        !          1064:  * Start the board, ready for normal operation
        !          1065:  */
        !          1066: int
        !          1067: bha_init(sc)
        !          1068:        struct bha_softc *sc;
        !          1069: {
        !          1070:        bus_space_tag_t iot = sc->sc_iot;
        !          1071:        bus_space_handle_t ioh = sc->sc_ioh;
        !          1072:        bus_dma_segment_t seg;
        !          1073:        struct bha_devices devices;
        !          1074:        struct bha_setup setup;
        !          1075:        struct bha_mailbox mailbox;
        !          1076:        struct bha_period period;
        !          1077:        int error, i, j, initial_ccbs, rlen, rseg;
        !          1078:
        !          1079:        /* Enable round-robin scheme - appeared at firmware rev. 3.31. */
        !          1080:        if (strcmp(sc->sc_firmware, "3.31") >= 0) {
        !          1081:                struct bha_toggle toggle;
        !          1082:
        !          1083:                toggle.cmd.opcode = BHA_ROUND_ROBIN;
        !          1084:                toggle.cmd.enable = 1;
        !          1085:                bha_cmd(iot, ioh, sc,
        !          1086:                    sizeof(toggle.cmd), (u_char *)&toggle.cmd,
        !          1087:                    0, (u_char *)0);
        !          1088:        }
        !          1089:
        !          1090:        /*
        !          1091:         * Inquire installed devices (to force synchronous negotiation).
        !          1092:         */
        !          1093:
        !          1094:        /*
        !          1095:         * Poll targets 0 - 7.
        !          1096:         */
        !          1097:        devices.cmd.opcode = BHA_INQUIRE_DEVICES;
        !          1098:        bha_cmd(iot, ioh, sc,
        !          1099:            sizeof(devices.cmd), (u_char *)&devices.cmd,
        !          1100:            sizeof(devices.reply), (u_char *)&devices.reply);
        !          1101:
        !          1102:        /* Count installed units. */
        !          1103:        initial_ccbs = 0;
        !          1104:        for (i = 0; i < 8; i++) {
        !          1105:                for (j = 0; j < 8; j++) {
        !          1106:                        if (((devices.reply.lun_map[i] >> j) & 1) == 1)
        !          1107:                                initial_ccbs++;
        !          1108:                }
        !          1109:        }
        !          1110:
        !          1111:        /*
        !          1112:         * Poll targets 8 - 15 if we have a wide bus.
        !          1113:          */
        !          1114:        if (ISWIDE(sc)) {
        !          1115:                devices.cmd.opcode = BHA_INQUIRE_DEVICES_2;
        !          1116:                bha_cmd(iot, ioh, sc,
        !          1117:                    sizeof(devices.cmd), (u_char *)&devices.cmd,
        !          1118:                    sizeof(devices.reply), (u_char *)&devices.reply);
        !          1119:
        !          1120:                for (i = 0; i < 8; i++) {
        !          1121:                        for (j = 0; j < 8; j++) {
        !          1122:                                if (((devices.reply.lun_map[i] >> j) & 1) == 1)
        !          1123:                                        initial_ccbs++;
        !          1124:                        }
        !          1125:                }
        !          1126:        }
        !          1127:
        !          1128:        initial_ccbs *= sc->sc_link.openings;
        !          1129:        if (initial_ccbs > BHA_CCB_MAX)
        !          1130:                initial_ccbs = BHA_CCB_MAX;
        !          1131:        if (initial_ccbs == 0)  /* yes, this can happen */
        !          1132:                initial_ccbs = sc->sc_link.openings;
        !          1133:
        !          1134:        /* Obtain setup information from. */
        !          1135:        rlen = sizeof(setup.reply) +
        !          1136:            (ISWIDE(sc) ? sizeof(setup.reply_w) : 0);
        !          1137:        setup.cmd.opcode = BHA_INQUIRE_SETUP;
        !          1138:        setup.cmd.len = rlen;
        !          1139:        bha_cmd(iot, ioh, sc,
        !          1140:            sizeof(setup.cmd), (u_char *)&setup.cmd,
        !          1141:            rlen, (u_char *)&setup.reply);
        !          1142:
        !          1143:        printf("%s: %s, %s\n", sc->sc_dev.dv_xname,
        !          1144:            setup.reply.sync_neg ? "sync" : "async",
        !          1145:            setup.reply.parity ? "parity" : "no parity");
        !          1146:
        !          1147:        for (i = 0; i < 8; i++)
        !          1148:                period.reply.period[i] = setup.reply.sync[i].period * 5 + 20;
        !          1149:        if (ISWIDE(sc)) {
        !          1150:                for (i = 0; i < 8; i++)
        !          1151:                        period.reply_w.period[i] =
        !          1152:                            setup.reply_w.sync_high[i].period * 5 + 20;
        !          1153:        }
        !          1154:
        !          1155:        if (sc->sc_firmware[0] >= '3') {
        !          1156:                rlen = sizeof(period.reply) +
        !          1157:                    (ISWIDE(sc) ? sizeof(period.reply_w) : 0);
        !          1158:                period.cmd.opcode = BHA_INQUIRE_PERIOD;
        !          1159:                period.cmd.len = sizeof(period.reply);
        !          1160:                bha_cmd(iot, ioh, sc,
        !          1161:                    sizeof(period.cmd), (u_char *)&period.cmd,
        !          1162:                    rlen, (u_char *)&period.reply);
        !          1163:        }
        !          1164:
        !          1165:        for (i = 0; i < 8; i++) {
        !          1166:                if (!setup.reply.sync[i].valid ||
        !          1167:                    (!setup.reply.sync[i].offset &&
        !          1168:                     !setup.reply.sync[i].period))
        !          1169:                        continue;
        !          1170:                printf("%s targ %d: sync, offset %d, period %dnsec\n",
        !          1171:                    sc->sc_dev.dv_xname, i,
        !          1172:                    setup.reply.sync[i].offset, period.reply.period[i] * 10);
        !          1173:        }
        !          1174:        if (ISWIDE(sc)) {
        !          1175:                for (i = 0; i < 8; i++) {
        !          1176:                        if (!setup.reply_w.sync_high[i].valid ||
        !          1177:                            (!setup.reply_w.sync_high[i].offset &&
        !          1178:                             !setup.reply_w.sync_high[i].period))
        !          1179:                                continue;
        !          1180:                        printf("%s targ %d: sync, offset %d, period %dnsec\n",
        !          1181:                            sc->sc_dev.dv_xname, i + 8,
        !          1182:                            setup.reply_w.sync_high[i].offset,
        !          1183:                            period.reply_w.period[i] * 10);
        !          1184:                }
        !          1185:        }
        !          1186:
        !          1187:        /*
        !          1188:         * Allocate the mailbox and control blocks.
        !          1189:         */
        !          1190:        if ((error = bus_dmamem_alloc(sc->sc_dmat, sizeof(struct bha_control),
        !          1191:            NBPG, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
        !          1192:                printf("%s: unable to allocate control structures, "
        !          1193:                    "error = %d\n", sc->sc_dev.dv_xname, error);
        !          1194:                return (error);
        !          1195:        }
        !          1196:        if ((error = bus_dmamem_map(sc->sc_dmat, &seg, rseg,
        !          1197:            sizeof(struct bha_control), (caddr_t *)&sc->sc_control,
        !          1198:            BUS_DMA_NOWAIT)) != 0) {
        !          1199:                printf("%s: unable to map control structures, error = %d\n",
        !          1200:                    sc->sc_dev.dv_xname, error);
        !          1201:                return (error);
        !          1202:        }
        !          1203:
        !          1204:        /*
        !          1205:         * Create and load the DMA map used for the mailbox and
        !          1206:         * control blocks.
        !          1207:         */
        !          1208:        if ((error = bus_dmamap_create(sc->sc_dmat, sizeof(struct bha_control),
        !          1209:            1, sizeof(struct bha_control), 0, BUS_DMA_NOWAIT | sc->sc_dmaflags,
        !          1210:            &sc->sc_dmamap_control)) != 0) {
        !          1211:                printf("%s: unable to create control DMA map, error = %d\n",
        !          1212:                    sc->sc_dev.dv_xname, error);
        !          1213:                return (error);
        !          1214:        }
        !          1215:        if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap_control,
        !          1216:            sc->sc_control, sizeof(struct bha_control), NULL,
        !          1217:            BUS_DMA_NOWAIT)) != 0) {
        !          1218:                printf("%s: unable to load control DMA map, error = %d\n",
        !          1219:                    sc->sc_dev.dv_xname, error);
        !          1220:                return (error);
        !          1221:        }
        !          1222:
        !          1223:        /*
        !          1224:         * Initialize the control blocks.
        !          1225:         */
        !          1226:        i = bha_create_ccbs(sc, sc->sc_control->bc_ccbs, initial_ccbs);
        !          1227:        if (i == 0) {
        !          1228:                printf("%s: unable to create control blocks\n",
        !          1229:                    sc->sc_dev.dv_xname);
        !          1230:                return (ENOMEM);
        !          1231:        } else if (i != initial_ccbs) {
        !          1232:                printf("%s: WARNING: only %d of %d control blocks created\n",
        !          1233:                    sc->sc_dev.dv_xname, i, initial_ccbs);
        !          1234:        }
        !          1235:
        !          1236:        /*
        !          1237:         * Set up initial mail box for round-robin operation.
        !          1238:         */
        !          1239:        for (i = 0; i < BHA_MBX_SIZE; i++) {
        !          1240:                wmbx->mbo[i].cmd = BHA_MBO_FREE;
        !          1241:                bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !          1242:                    0, sc->sc_dmamap_control->dm_mapsize,
        !          1243:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1244:                wmbx->mbi[i].comp_stat = BHA_MBI_FREE;
        !          1245:                bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !          1246:                    0, sc->sc_dmamap_control->dm_mapsize,
        !          1247:                    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1248:        }
        !          1249:        wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
        !          1250:        wmbx->tmbi = &wmbx->mbi[0];
        !          1251:        sc->sc_mbofull = 0;
        !          1252:
        !          1253:        /* Initialize mail box. */
        !          1254:        mailbox.cmd.opcode = BHA_MBX_INIT_EXTENDED;
        !          1255:        mailbox.cmd.nmbx = BHA_MBX_SIZE;
        !          1256:        ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
        !          1257:            offsetof(struct bha_control, bc_mbx), mailbox.cmd.addr);
        !          1258:        bha_cmd(iot, ioh, sc,
        !          1259:            sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
        !          1260:            0, (u_char *)0);
        !          1261:        return (0);
        !          1262: }
        !          1263:
        !          1264: void
        !          1265: bha_inquire_setup_information(sc)
        !          1266:        struct bha_softc *sc;
        !          1267: {
        !          1268:        bus_space_tag_t iot = sc->sc_iot;
        !          1269:        bus_space_handle_t ioh = sc->sc_ioh;
        !          1270:        struct bha_model model;
        !          1271:        struct bha_revision revision;
        !          1272:        struct bha_digit digit;
        !          1273:        char *p;
        !          1274:
        !          1275:        /*
        !          1276:         * Get the firmware revision.
        !          1277:         */
        !          1278:        p = sc->sc_firmware;
        !          1279:        revision.cmd.opcode = BHA_INQUIRE_REVISION;
        !          1280:        bha_cmd(iot, ioh, sc,
        !          1281:            sizeof(revision.cmd), (u_char *)&revision.cmd,
        !          1282:            sizeof(revision.reply), (u_char *)&revision.reply);
        !          1283:        *p++ = revision.reply.firm_revision;
        !          1284:        *p++ = '.';
        !          1285:        *p++ = revision.reply.firm_version;
        !          1286:        digit.cmd.opcode = BHA_INQUIRE_REVISION_3;
        !          1287:        bha_cmd(iot, ioh, sc,
        !          1288:            sizeof(digit.cmd), (u_char *)&digit.cmd,
        !          1289:            sizeof(digit.reply), (u_char *)&digit.reply);
        !          1290:        *p++ = digit.reply.digit;
        !          1291:        if (revision.reply.firm_revision >= '3' ||
        !          1292:            (revision.reply.firm_revision == '3' &&
        !          1293:             revision.reply.firm_version >= '3')) {
        !          1294:                digit.cmd.opcode = BHA_INQUIRE_REVISION_4;
        !          1295:                bha_cmd(iot, ioh, sc,
        !          1296:                    sizeof(digit.cmd), (u_char *)&digit.cmd,
        !          1297:                    sizeof(digit.reply), (u_char *)&digit.reply);
        !          1298:                *p++ = digit.reply.digit;
        !          1299:        }
        !          1300:        while (p > sc->sc_firmware && (p[-1] == ' ' || p[-1] == '\0'))
        !          1301:                p--;
        !          1302:        *p = '\0';
        !          1303:
        !          1304:        /*
        !          1305:         * Get the model number.
        !          1306:         */
        !          1307:        if (revision.reply.firm_revision >= '3') {
        !          1308:                p = sc->sc_model;
        !          1309:                model.cmd.opcode = BHA_INQUIRE_MODEL;
        !          1310:                model.cmd.len = sizeof(model.reply);
        !          1311:                bha_cmd(iot, ioh, sc,
        !          1312:                    sizeof(model.cmd), (u_char *)&model.cmd,
        !          1313:                    sizeof(model.reply), (u_char *)&model.reply);
        !          1314:                *p++ = model.reply.id[0];
        !          1315:                *p++ = model.reply.id[1];
        !          1316:                *p++ = model.reply.id[2];
        !          1317:                *p++ = model.reply.id[3];
        !          1318:                while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
        !          1319:                        p--;
        !          1320:                *p++ = model.reply.version[0];
        !          1321:                *p++ = model.reply.version[1];
        !          1322:                while (p > sc->sc_model && (p[-1] == ' ' || p[-1] == '\0'))
        !          1323:                        p--;
        !          1324:                *p = '\0';
        !          1325:        } else
        !          1326:                strlcpy(sc->sc_model, "542B", sizeof sc->sc_model);
        !          1327: }
        !          1328:
        !          1329: void
        !          1330: bhaminphys(bp)
        !          1331:        struct buf *bp;
        !          1332: {
        !          1333:
        !          1334:        if (bp->b_bcount > BHA_MAXXFER)
        !          1335:                bp->b_bcount = BHA_MAXXFER;
        !          1336:        minphys(bp);
        !          1337: }
        !          1338:
        !          1339: /*
        !          1340:  * start a scsi operation given the command and the data address.  Also needs
        !          1341:  * the unit, target and lu.
        !          1342:  */
        !          1343: int
        !          1344: bha_scsi_cmd(xs)
        !          1345:        struct scsi_xfer *xs;
        !          1346: {
        !          1347:        struct scsi_link *sc_link = xs->sc_link;
        !          1348:        struct bha_softc *sc = sc_link->adapter_softc;
        !          1349:        bus_dma_tag_t dmat = sc->sc_dmat;
        !          1350:        struct bha_ccb *ccb;
        !          1351:        int error, seg, flags, s;
        !          1352:        int fromqueue = 0, dontqueue = 0;
        !          1353:
        !          1354:        SC_DEBUG(sc_link, SDEV_DB2, ("bha_scsi_cmd\n"));
        !          1355:
        !          1356:        s = splbio();           /* protect the queue */
        !          1357:
        !          1358:        /*
        !          1359:         * If we're running the queue from bha_done(), we've been
        !          1360:         * called with the first queue entry as our argument.
        !          1361:         */
        !          1362:        if (xs == LIST_FIRST(&sc->sc_queue)) {
        !          1363:                xs = bha_dequeue(sc);
        !          1364:                fromqueue = 1;
        !          1365:                goto get_ccb;
        !          1366:        }
        !          1367:
        !          1368:        /* Polled requests can't be queued for later. */
        !          1369:        dontqueue = xs->flags & SCSI_POLL;
        !          1370:
        !          1371:        /*
        !          1372:         * If there are jobs in the queue, run them first.
        !          1373:         */
        !          1374:        if (!LIST_EMPTY(&sc->sc_queue)) {
        !          1375:                /*
        !          1376:                 * If we can't queue, we have to abort, since
        !          1377:                 * we have to preserve order.
        !          1378:                 */
        !          1379:                if (dontqueue) {
        !          1380:                        splx(s);
        !          1381:                        return (TRY_AGAIN_LATER);
        !          1382:                }
        !          1383:
        !          1384:                /*
        !          1385:                 * Swap with the first queue entry.
        !          1386:                 */
        !          1387:                bha_enqueue(sc, xs, 0);
        !          1388:                xs = bha_dequeue(sc);
        !          1389:                fromqueue = 1;
        !          1390:        }
        !          1391:
        !          1392:  get_ccb:
        !          1393:        /*
        !          1394:         * get a ccb to use. If the transfer
        !          1395:         * is from a buf (possibly from interrupt time)
        !          1396:         * then we can't allow it to sleep
        !          1397:         */
        !          1398:        flags = xs->flags;
        !          1399:        if ((ccb = bha_get_ccb(sc, flags)) == NULL) {
        !          1400:                /*
        !          1401:                 * If we can't queue, we lose.
        !          1402:                 */
        !          1403:                if (dontqueue) {
        !          1404:                        splx(s);
        !          1405:                        return (TRY_AGAIN_LATER);
        !          1406:                }
        !          1407:
        !          1408:                /*
        !          1409:                 * Stuff ourselves into the queue, in front
        !          1410:                 * if we came off in the first place.
        !          1411:                 */
        !          1412:                bha_enqueue(sc, xs, fromqueue);
        !          1413:                splx(s);
        !          1414:                return (SUCCESSFULLY_QUEUED);
        !          1415:        }
        !          1416:
        !          1417:        splx(s);                /* done playing with the queue */
        !          1418:
        !          1419:        ccb->xs = xs;
        !          1420:        ccb->timeout = xs->timeout;
        !          1421:
        !          1422:        /*
        !          1423:         * Put all the arguments for the xfer in the ccb
        !          1424:         */
        !          1425:        if (flags & SCSI_RESET) {
        !          1426:                ccb->opcode = BHA_RESET_CCB;
        !          1427:                ccb->scsi_cmd_length = 0;
        !          1428:        } else {
        !          1429:                /* can't use S/G if zero length */
        !          1430:                ccb->opcode = (xs->datalen ? BHA_INIT_SCAT_GATH_CCB
        !          1431:                                           : BHA_INITIATOR_CCB);
        !          1432:                bcopy(xs->cmd, &ccb->scsi_cmd,
        !          1433:                    ccb->scsi_cmd_length = xs->cmdlen);
        !          1434:        }
        !          1435:
        !          1436:        if (xs->datalen) {
        !          1437:                /*
        !          1438:                 * Map the DMA transfer.
        !          1439:                 */
        !          1440: #ifdef TFS
        !          1441:                if (flags & SCSI_DATA_UIO) {
        !          1442:                        error = bus_dmamap_load_uio(dmat,
        !          1443:                            ccb->dmamap_xfer, (struct uio *)xs->data,
        !          1444:                            (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
        !          1445:                            BUS_DMA_WAITOK);
        !          1446:                } else
        !          1447: #endif /* TFS */
        !          1448:                {
        !          1449:                        error = bus_dmamap_load(dmat,
        !          1450:                            ccb->dmamap_xfer, xs->data, xs->datalen, NULL,
        !          1451:                            (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT :
        !          1452:                            BUS_DMA_WAITOK);
        !          1453:                }
        !          1454:
        !          1455:                if (error) {
        !          1456:                        if (error == EFBIG) {
        !          1457:                                printf("%s: bha_scsi_cmd, more than %d"
        !          1458:                                    " dma segments\n",
        !          1459:                                    sc->sc_dev.dv_xname, BHA_NSEG);
        !          1460:                        } else {
        !          1461:                                printf("%s: bha_scsi_cmd, error %d loading"
        !          1462:                                    " dma map\n",
        !          1463:                                    sc->sc_dev.dv_xname, error);
        !          1464:                        }
        !          1465:                        goto bad;
        !          1466:                }
        !          1467:
        !          1468:                bus_dmamap_sync(dmat, ccb->dmamap_xfer,
        !          1469:                    0, ccb->dmamap_xfer->dm_mapsize,
        !          1470:                    (flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD :
        !          1471:                    BUS_DMASYNC_PREWRITE);
        !          1472:
        !          1473:                /*
        !          1474:                 * Load the hardware scatter/gather map with the
        !          1475:                 * contents of the DMA map.
        !          1476:                 */
        !          1477:                for (seg = 0; seg < ccb->dmamap_xfer->dm_nsegs; seg++) {
        !          1478:                        ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_addr,
        !          1479:                            ccb->scat_gath[seg].seg_addr);
        !          1480:                        ltophys(ccb->dmamap_xfer->dm_segs[seg].ds_len,
        !          1481:                            ccb->scat_gath[seg].seg_len);
        !          1482:                }
        !          1483:
        !          1484:                ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
        !          1485:                    BHA_CCB_OFF(ccb) + offsetof(struct bha_ccb, scat_gath),
        !          1486:                    ccb->data_addr);
        !          1487:                ltophys(ccb->dmamap_xfer->dm_nsegs *
        !          1488:                    sizeof(struct bha_scat_gath), ccb->data_length);
        !          1489:        } else {
        !          1490:                /*
        !          1491:                 * No data xfer, use non S/G values.
        !          1492:                 */
        !          1493:                ltophys(0, ccb->data_addr);
        !          1494:                ltophys(0, ccb->data_length);
        !          1495:        }
        !          1496:
        !          1497:        ccb->data_out = 0;
        !          1498:        ccb->data_in = 0;
        !          1499:        ccb->target = sc_link->target;
        !          1500:        ccb->lun = sc_link->lun;
        !          1501:        ltophys(sc->sc_dmamap_control->dm_segs[0].ds_addr +
        !          1502:            BHA_CCB_OFF(ccb) + offsetof(struct bha_ccb, scsi_sense),
        !          1503:            ccb->sense_ptr);
        !          1504:        ccb->req_sense_length = sizeof(ccb->scsi_sense);
        !          1505:        ccb->host_stat = 0x00;
        !          1506:        ccb->target_stat = 0x00;
        !          1507:        ccb->link_id = 0;
        !          1508:        ltophys(0, ccb->link_addr);
        !          1509:
        !          1510:        bus_dmamap_sync(sc->sc_dmat, sc->sc_dmamap_control,
        !          1511:            0, sc->sc_dmamap_control->dm_mapsize,
        !          1512:            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
        !          1513:
        !          1514:        s = splbio();
        !          1515:        bha_queue_ccb(sc, ccb);
        !          1516:        splx(s);
        !          1517:
        !          1518:        /*
        !          1519:         * Usually return SUCCESSFULLY QUEUED
        !          1520:         */
        !          1521:        SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
        !          1522:        if ((flags & SCSI_POLL) == 0)
        !          1523:                return (SUCCESSFULLY_QUEUED);
        !          1524:
        !          1525:        /*
        !          1526:         * If we can't use interrupts, poll on completion
        !          1527:         */
        !          1528:        if (bha_poll(sc, xs, ccb->timeout)) {
        !          1529:                bha_timeout(ccb);
        !          1530:                if (bha_poll(sc, xs, ccb->timeout))
        !          1531:                        bha_timeout(ccb);
        !          1532:        }
        !          1533:        return (COMPLETE);
        !          1534:
        !          1535: bad:
        !          1536:        xs->error = XS_DRIVER_STUFFUP;
        !          1537:        bha_free_ccb(sc, ccb);
        !          1538:        return (COMPLETE);
        !          1539: }
        !          1540:
        !          1541: /*
        !          1542:  * Poll a particular unit, looking for a particular xs
        !          1543:  */
        !          1544: int
        !          1545: bha_poll(sc, xs, count)
        !          1546:        struct bha_softc *sc;
        !          1547:        struct scsi_xfer *xs;
        !          1548:        int count;
        !          1549: {
        !          1550:        bus_space_tag_t iot = sc->sc_iot;
        !          1551:        bus_space_handle_t ioh = sc->sc_ioh;
        !          1552:
        !          1553:        /* timeouts are in msec, so we loop in 1000 usec cycles */
        !          1554:        while (count) {
        !          1555:                /*
        !          1556:                 * If we had interrupts enabled, would we
        !          1557:                 * have got an interrupt?
        !          1558:                 */
        !          1559:                if (bus_space_read_1(iot, ioh, BHA_INTR_PORT) &
        !          1560:                    BHA_INTR_ANYINTR)
        !          1561:                        bha_intr(sc);
        !          1562:                if (xs->flags & ITSDONE)
        !          1563:                        return (0);
        !          1564:                delay(1000);    /* only happens in boot so ok */
        !          1565:                count--;
        !          1566:        }
        !          1567:        return (1);
        !          1568: }
        !          1569:
        !          1570: void
        !          1571: bha_timeout(arg)
        !          1572:        void *arg;
        !          1573: {
        !          1574:        struct bha_ccb *ccb = arg;
        !          1575:        struct scsi_xfer *xs = ccb->xs;
        !          1576:        struct scsi_link *sc_link = xs->sc_link;
        !          1577:        struct bha_softc *sc = sc_link->adapter_softc;
        !          1578:        int s;
        !          1579:
        !          1580:        sc_print_addr(sc_link);
        !          1581:        printf("timed out");
        !          1582:
        !          1583:        s = splbio();
        !          1584:
        !          1585: #ifdef BHADIAG
        !          1586:        /*
        !          1587:         * If the ccb's mbx is not free, then the board has gone Far East?
        !          1588:         */
        !          1589:        bha_collect_mbo(sc);
        !          1590:        if (ccb->flags & CCB_SENDING) {
        !          1591:                printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
        !          1592:                Debugger();
        !          1593:        }
        !          1594: #endif
        !          1595:
        !          1596:        /*
        !          1597:         * If it has been through before, then
        !          1598:         * a previous abort has failed, don't
        !          1599:         * try abort again
        !          1600:         */
        !          1601:        if (ccb->flags & CCB_ABORT) {
        !          1602:                /* abort timed out */
        !          1603:                printf(" AGAIN\n");
        !          1604:                /* XXX Must reset! */
        !          1605:        } else {
        !          1606:                /* abort the operation that has timed out */
        !          1607:                printf("\n");
        !          1608:                ccb->xs->error = XS_TIMEOUT;
        !          1609:                ccb->timeout = BHA_ABORT_TIMEOUT;
        !          1610:                ccb->flags |= CCB_ABORT;
        !          1611:                bha_queue_ccb(sc, ccb);
        !          1612:        }
        !          1613:
        !          1614:        splx(s);
        !          1615: }

CVSweb