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

Annotation of sys/dev/isa/aha.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: aha.c,v 1.57 2007/08/15 02:04:30 krw Exp $    */
                      2: /*     $NetBSD: aha.c,v 1.11 1996/05/12 23:51:23 mycroft Exp $ */
                      3:
                      4: #undef AHADIAG
                      5:
                      6: /*
                      7:  * Copyright (c) 1994, 1996 Charles M. Hannum.  All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *     This product includes software developed by Charles M. Hannum.
                     20:  * 4. The name of the author may not be used to endorse or promote products
                     21:  *    derived from this software without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     25:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     26:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     27:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     28:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     29:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     30:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     31:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     32:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     33:  */
                     34:
                     35: /*
                     36:  * Originally written by Julian Elischer (julian@tfs.com)
                     37:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
                     38:  *
                     39:  * TRW Financial Systems, in accordance with their agreement with Carnegie
                     40:  * Mellon University, makes this software available to CMU to distribute
                     41:  * or use in any manner that they see fit as long as this message is kept with
                     42:  * the software. For this reason TFS also grants any other persons or
                     43:  * organisations permission to use or modify this software.
                     44:  *
                     45:  * TFS supplies this software to be publicly redistributed
                     46:  * on the understanding that TFS is not responsible for the correct
                     47:  * functioning of this software in any circumstances.
                     48:  */
                     49:
                     50: #include <sys/types.h>
                     51: #include <sys/param.h>
                     52: #include <sys/systm.h>
                     53: #include <sys/kernel.h>
                     54: #include <sys/errno.h>
                     55: #include <sys/ioctl.h>
                     56: #include <sys/device.h>
                     57: #include <sys/malloc.h>
                     58: #include <sys/buf.h>
                     59: #include <sys/proc.h>
                     60: #include <sys/user.h>
                     61: #include <sys/timeout.h>
                     62:
                     63: #include <uvm/uvm.h>
                     64: #include <uvm/uvm_extern.h>
                     65:
                     66: #include <machine/intr.h>
                     67: #include <machine/bus.h>
                     68:
                     69: #include <scsi/scsi_all.h>
                     70: #include <scsi/scsiconf.h>
                     71:
                     72: #include <dev/isa/isavar.h>
                     73: #include <dev/isa/isadmavar.h>
                     74: #include <dev/isa/ahareg.h>
                     75:
                     76: #ifndef DDB
                     77: #define Debugger() panic("should call debugger here (aha1542.c)")
                     78: #endif /* ! DDB */
                     79:
                     80: /* XXX fixme:
                     81:  * on i386 at least, xfers to/from user memory
                     82:  * cannot be serviced at interrupt time.
                     83:  */
                     84: #ifdef i386
                     85: #define VOLATILE_XS(xs) \
                     86:        ((xs)->datalen > 0 && (xs)->bp == NULL && \
                     87:        ((xs)->flags & SCSI_POLL) == 0)
                     88: #else
                     89: #define VOLATILE_XS(xs)        0
                     90: #endif
                     91:
                     92: /*
                     93:  * Mail box defs  etc.
                     94:  * these could be bigger but we need the aha_softc to fit on a single page..
                     95:  */
                     96: #define AHA_MBX_SIZE   16      /* mail box size */
                     97:
                     98: #define        AHA_CCB_MAX     16      /* store up to 32 CCBs at one time */
                     99: #define        CCB_HASH_SIZE   16      /* hash table size for phystokv */
                    100: #define        CCB_HASH_SHIFT  9
                    101: #define        CCB_HASH(x)     ((((long)(x))>>CCB_HASH_SHIFT) & (CCB_HASH_SIZE - 1))
                    102:
                    103: #define aha_nextmbx(wmb, mbx, mbio) \
                    104:        if ((wmb) == &(mbx)->mbio[AHA_MBX_SIZE - 1])    \
                    105:                (wmb) = &(mbx)->mbio[0];                \
                    106:        else                                            \
                    107:                (wmb)++;
                    108:
                    109: struct aha_mbx {
                    110:        struct aha_mbx_out mbo[AHA_MBX_SIZE];
                    111:        struct aha_mbx_in mbi[AHA_MBX_SIZE];
                    112:        struct aha_mbx_out *cmbo;       /* Collection Mail Box out */
                    113:        struct aha_mbx_out *tmbo;       /* Target Mail Box out */
                    114:        struct aha_mbx_in *tmbi;        /* Target Mail Box in */
                    115: };
                    116:
                    117: struct aha_softc {
                    118:        struct device sc_dev;
                    119:        struct isadev sc_id;
                    120:        void *sc_ih;
                    121:        bus_dma_tag_t sc_dmat;
                    122:
                    123:        int sc_iobase;
                    124:        int sc_irq, sc_drq;
                    125:
                    126:        char sc_model[18],
                    127:             sc_firmware[4];
                    128:
                    129:        struct aha_mbx *sc_mbx;         /* all the mailboxes */
                    130: #define        wmbx    (sc->sc_mbx)
                    131:        struct aha_ccb *sc_ccbhash[CCB_HASH_SIZE];
                    132:        TAILQ_HEAD(, aha_ccb) sc_free_ccb, sc_waiting_ccb;
                    133:        int sc_numccbs, sc_mbofull;
                    134:        int sc_scsi_dev;                /* our scsi id */
                    135:        struct scsi_link sc_link;
                    136: };
                    137:
                    138: #ifdef AHADEBUG
                    139: int    aha_debug = 1;
                    140: #endif /* AHADEBUG */
                    141:
                    142: int aha_cmd(int, struct aha_softc *, int, u_char *, int, u_char *);
                    143: void aha_finish_ccbs(struct aha_softc *);
                    144: int ahaintr(void *);
                    145: void aha_reset_ccb(struct aha_softc *, struct aha_ccb *);
                    146: void aha_free_ccb(struct aha_softc *, struct aha_ccb *);
                    147: int aha_init_ccb(struct aha_softc *, struct aha_ccb *, int);
                    148: struct aha_ccb *aha_get_ccb(struct aha_softc *, int);
                    149: struct aha_ccb *aha_ccb_phys_kv(struct aha_softc *, u_long);
                    150: void aha_queue_ccb(struct aha_softc *, struct aha_ccb *);
                    151: void aha_collect_mbo(struct aha_softc *);
                    152: void aha_start_ccbs(struct aha_softc *);
                    153: void aha_done(struct aha_softc *, struct aha_ccb *);
                    154: int aha_find(struct isa_attach_args *, struct aha_softc *, int);
                    155: void aha_init(struct aha_softc *);
                    156: void aha_inquire_setup_information(struct aha_softc *);
                    157: void ahaminphys(struct buf *);
                    158: int aha_scsi_cmd(struct scsi_xfer *);
                    159: int aha_poll(struct aha_softc *, struct scsi_xfer *, int);
                    160: void aha_timeout(void *arg);
                    161:
                    162: struct scsi_adapter aha_switch = {
                    163:        aha_scsi_cmd,
                    164:        ahaminphys,
                    165:        0,
                    166:        0,
                    167: };
                    168:
                    169: /* the below structure is so we have a default dev struct for out link struct */
                    170: struct scsi_device aha_dev = {
                    171:        NULL,                   /* Use default error handler */
                    172:        NULL,                   /* have a queue, served by this */
                    173:        NULL,                   /* have no async handler */
                    174:        NULL,                   /* Use default 'done' routine */
                    175: };
                    176:
                    177: int    aha_isapnp_probe(struct device *, void *, void *);
                    178: int    ahaprobe(struct device *, void *, void *);
                    179: void   ahaattach(struct device *, struct device *, void *);
                    180:
                    181: struct cfattach aha_isapnp_ca = {
                    182:        sizeof(struct aha_softc), aha_isapnp_probe, ahaattach
                    183: };
                    184:
                    185: struct cfattach aha_isa_ca = {
                    186:        sizeof(struct aha_softc), ahaprobe, ahaattach
                    187: };
                    188:
                    189: struct cfdriver aha_cd = {
                    190:        NULL, "aha", DV_DULL
                    191: };
                    192:
                    193: #define AHA_RESET_TIMEOUT      2000    /* time to wait for reset (mSec) */
                    194: #define        AHA_ABORT_TIMEOUT       2000    /* time to wait for abort (mSec) */
                    195:
                    196: #include "bha.h"
                    197:
                    198: /*
                    199:  * aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
                    200:  *
                    201:  * Activate Adapter command
                    202:  *    icnt:   number of args (outbound bytes including opcode)
                    203:  *    ibuf:   argument buffer
                    204:  *    ocnt:   number of expected returned bytes
                    205:  *    obuf:   result buffer
                    206:  *    wait:   number of seconds to wait for response
                    207:  *
                    208:  * Performs an adapter command through the ports.  Not to be confused with a
                    209:  * scsi command, which is read in via the dma; one of the adapter commands
                    210:  * tells it to read in a scsi command.
                    211:  */
                    212: int
                    213: aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf)
                    214:        int iobase;
                    215:        struct aha_softc *sc;
                    216:        int icnt, ocnt;
                    217:        u_char *ibuf, *obuf;
                    218: {
                    219:        const char *name;
                    220:        register int i;
                    221:        int wait;
                    222:        u_char sts;
                    223:        u_char opcode = ibuf[0];
                    224:
                    225:        if (sc != NULL)
                    226:                name = sc->sc_dev.dv_xname;
                    227:        else
                    228:                name = "(aha probe)";
                    229:
                    230:        /*
                    231:         * Calculate a reasonable timeout for the command.
                    232:         */
                    233:        switch (opcode) {
                    234:        case AHA_INQUIRE_DEVICES:
                    235:                wait = 15 * 20000;
                    236:                break;
                    237:        default:
                    238:                wait = 1 * 20000;
                    239:                break;
                    240:        }
                    241:
                    242:        /*
                    243:         * Wait for the adapter to go idle, unless it's one of
                    244:         * the commands which don't need this
                    245:         */
                    246:        if (opcode != AHA_MBO_INTR_EN) {
                    247:                for (i = 20000; i; i--) {       /* 1 sec? */
                    248:                        sts = inb(iobase + AHA_STAT_PORT);
                    249:                        if (sts & AHA_STAT_IDLE)
                    250:                                break;
                    251:                        delay(50);
                    252:                }
                    253:                if (!i) {
                    254:                        printf("%s: aha_cmd, host not idle(0x%x)\n",
                    255:                            name, sts);
                    256:                        return (ENXIO);
                    257:                }
                    258:        }
                    259:        /*
                    260:         * Now that it is idle, if we expect output, preflush the
                    261:         * queue feeding to us.
                    262:         */
                    263:        if (ocnt) {
                    264:                while ((inb(iobase + AHA_STAT_PORT)) & AHA_STAT_DF)
                    265:                        inb(iobase + AHA_DATA_PORT);
                    266:        }
                    267:        /*
                    268:         * Output the command and the number of arguments given
                    269:         * for each byte, first check the port is empty.
                    270:         */
                    271:        while (icnt--) {
                    272:                for (i = wait; i; i--) {
                    273:                        sts = inb(iobase + AHA_STAT_PORT);
                    274:                        if (!(sts & AHA_STAT_CDF))
                    275:                                break;
                    276:                        delay(50);
                    277:                }
                    278:                if (!i) {
                    279:                        if (opcode != AHA_INQUIRE_REVISION)
                    280:                                printf("%s: aha_cmd, cmd/data port full\n",
                    281:                                    name);
                    282:                        outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
                    283:                        return (ENXIO);
                    284:                }
                    285:                outb(iobase + AHA_CMD_PORT, *ibuf++);
                    286:        }
                    287:        /*
                    288:         * If we expect input, loop that many times, each time,
                    289:         * looking for the data register to have valid data
                    290:         */
                    291:        while (ocnt--) {
                    292:                for (i = wait; i; i--) {
                    293:                        sts = inb(iobase + AHA_STAT_PORT);
                    294:                        if (sts & AHA_STAT_DF)
                    295:                                break;
                    296:                        delay(50);
                    297:                }
                    298:                if (!i) {
                    299:                        if (opcode != AHA_INQUIRE_REVISION)
                    300:                                printf("%s: aha_cmd, cmd/data port empty %d\n",
                    301:                                    name, ocnt);
                    302:                        outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST);
                    303:                        return (ENXIO);
                    304:                }
                    305:                *obuf++ = inb(iobase + AHA_DATA_PORT);
                    306:        }
                    307:        /*
                    308:         * Wait for the board to report a finished instruction.
                    309:         * We may get an extra interrupt for the HACC signal, but this is
                    310:         * unimportant.
                    311:         */
                    312:        if (opcode != AHA_MBO_INTR_EN) {
                    313:                for (i = 20000; i; i--) {       /* 1 sec? */
                    314:                        sts = inb(iobase + AHA_INTR_PORT);
                    315:                        /* XXX Need to save this in the interrupt handler? */
                    316:                        if (sts & AHA_INTR_HACC)
                    317:                                break;
                    318:                        delay(50);
                    319:                }
                    320:                if (!i) {
                    321:                        printf("%s: aha_cmd, host not finished(0x%x)\n",
                    322:                            name, sts);
                    323:                        return (ENXIO);
                    324:                }
                    325:        }
                    326:        outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
                    327:        return (0);
                    328: }
                    329:
                    330: int
                    331: aha_isapnp_probe(parent, match, aux)
                    332:        struct device *parent;
                    333:        void *match, *aux;
                    334: {
                    335:        return (1);
                    336: }
                    337:
                    338:
                    339: /*
                    340:  * Check if the device can be found at the port given
                    341:  * and if so, set it up ready for further work
                    342:  * as an argument, takes the isa_device structure from
                    343:  * autoconf.c
                    344:  */
                    345: int
                    346: ahaprobe(parent, match, aux)
                    347:        struct device *parent;
                    348:        void *match, *aux;
                    349: {
                    350:        register struct isa_attach_args *ia = aux;
                    351: #if NBHA > 0
                    352:        extern int btports[], nbtports;
                    353:        int i;
                    354:
                    355:        for (i = 0; i < nbtports; i++)
                    356:                if (btports[i] == ia->ia_iobase)
                    357:                        return (0);
                    358: #endif
                    359:
                    360:        /* See if there is a unit at this location. */
                    361:        if (aha_find(ia, NULL, 0) != 0)
                    362:                return (0);
                    363:
                    364:        ia->ia_msize = 0;
                    365:        ia->ia_iosize = 4;
                    366:        /* IRQ and DRQ set by aha_find(). */
                    367:        return (1);
                    368: }
                    369:
                    370: /*
                    371:  * Attach all the sub-devices we can find
                    372:  */
                    373: void
                    374: ahaattach(parent, self, aux)
                    375:        struct device *parent, *self;
                    376:        void *aux;
                    377: {
                    378:        struct isa_attach_args *ia = aux;
                    379:        struct aha_softc *sc = (void *)self;
                    380:        struct scsibus_attach_args saa;
                    381:        int isapnp = !strcmp(parent->dv_cfdata->cf_driver->cd_name, "isapnp");
                    382:
                    383:        if (isapnp) {
                    384:                ia->ia_iobase = ia->ipa_io[0].base;
                    385:                isadma_cascade(ia->ia_drq);
                    386:        }
                    387:
                    388:        if (aha_find(ia, sc, isapnp) != 0)
                    389:                panic("ahaattach: aha_find of %s failed", self->dv_xname);
                    390:        sc->sc_iobase = ia->ia_iobase;
                    391:        sc->sc_dmat = ia->ia_dmat;
                    392:
                    393:        if (sc->sc_drq != DRQUNK && isapnp == 0)
                    394:                isadma_cascade(sc->sc_drq);
                    395:
                    396:        aha_inquire_setup_information(sc);
                    397:        aha_init(sc);
                    398:        TAILQ_INIT(&sc->sc_free_ccb);
                    399:        TAILQ_INIT(&sc->sc_waiting_ccb);
                    400:
                    401:        /*
                    402:         * fill in the prototype scsi_link.
                    403:         */
                    404:        sc->sc_link.adapter_softc = sc;
                    405:        sc->sc_link.adapter_target = sc->sc_scsi_dev;
                    406:        sc->sc_link.adapter = &aha_switch;
                    407:        sc->sc_link.device = &aha_dev;
                    408:        sc->sc_link.openings = 2;
                    409:
                    410:        bzero(&saa, sizeof(saa));
                    411:        saa.saa_sc_link = &sc->sc_link;
                    412:
                    413:        sc->sc_ih = isa_intr_establish(ia->ia_ic, sc->sc_irq, IST_EDGE,
                    414:            IPL_BIO, ahaintr, sc, sc->sc_dev.dv_xname);
                    415:
                    416:        /*
                    417:         * ask the adapter what subunits are present
                    418:         */
                    419:        config_found(self, &saa, scsiprint);
                    420: }
                    421:
                    422: void
                    423: aha_finish_ccbs(sc)
                    424:        struct aha_softc *sc;
                    425: {
                    426:        struct aha_mbx_in *wmbi;
                    427:        struct aha_ccb *ccb;
                    428:        int i;
                    429:
                    430:        wmbi = wmbx->tmbi;
                    431:
                    432:        if (wmbi->stat == AHA_MBI_FREE) {
                    433:                for (i = 0; i < AHA_MBX_SIZE; i++) {
                    434:                        if (wmbi->stat != AHA_MBI_FREE) {
                    435:                                printf("%s: mbi not in round-robin order\n",
                    436:                                    sc->sc_dev.dv_xname);
                    437:                                goto AGAIN;
                    438:                        }
                    439:                        aha_nextmbx(wmbi, wmbx, mbi);
                    440:                }
                    441: #ifdef AHADIAGnot
                    442:                printf("%s: mbi interrupt with no full mailboxes\n",
                    443:                    sc->sc_dev.dv_xname);
                    444: #endif
                    445:                return;
                    446:        }
                    447:
                    448: AGAIN:
                    449:        do {
                    450:                ccb = aha_ccb_phys_kv(sc, phystol(wmbi->ccb_addr));
                    451:                if (!ccb) {
                    452:                        printf("%s: bad mbi ccb pointer; skipping\n",
                    453:                            sc->sc_dev.dv_xname);
                    454:                        goto next;
                    455:                }
                    456:
                    457: #ifdef AHADEBUG
                    458:                if (aha_debug) {
                    459:                        u_char *cp = (u_char *)&ccb->scsi_cmd;
                    460:                        printf("op=%x %x %x %x %x %x\n",
                    461:                            cp[0], cp[1], cp[2], cp[3], cp[4], cp[5]);
                    462:                        printf("stat %x for mbi addr = 0x%08x, ",
                    463:                            wmbi->stat, wmbi);
                    464:                        printf("ccb addr = 0x%x\n", ccb);
                    465:                }
                    466: #endif /* AHADEBUG */
                    467:
                    468:                switch (wmbi->stat) {
                    469:                case AHA_MBI_OK:
                    470:                case AHA_MBI_ERROR:
                    471:                        if ((ccb->flags & CCB_ABORT) != 0) {
                    472:                                /*
                    473:                                 * If we already started an abort, wait for it
                    474:                                 * to complete before clearing the CCB.  We
                    475:                                 * could instead just clear CCB_SENDING, but
                    476:                                 * what if the mailbox was already received?
                    477:                                 * The worst that happens here is that we clear
                    478:                                 * the CCB a bit later than we need to.  BFD.
                    479:                                 */
                    480:                                goto next;
                    481:                        }
                    482:                        break;
                    483:
                    484:                case AHA_MBI_ABORT:
                    485:                case AHA_MBI_UNKNOWN:
                    486:                        /*
                    487:                         * Even if the CCB wasn't found, we clear it anyway.
                    488:                         * See preceding comment.
                    489:                         */
                    490:                        break;
                    491:
                    492:                default:
                    493:                        printf("%s: bad mbi status %02x; skipping\n",
                    494:                            sc->sc_dev.dv_xname, wmbi->stat);
                    495:                        goto next;
                    496:                }
                    497:
                    498:                if ((ccb->xs->flags & SCSI_POLL) == 0)
                    499:                        timeout_del(&ccb->xs->stimeout);
                    500:                bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0,
                    501:                    ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_POSTREAD);
                    502:                aha_done(sc, ccb);
                    503:
                    504:        next:
                    505:                wmbi->stat = AHA_MBI_FREE;
                    506:                aha_nextmbx(wmbi, wmbx, mbi);
                    507:        } while (wmbi->stat != AHA_MBI_FREE);
                    508:
                    509:        wmbx->tmbi = wmbi;
                    510: }
                    511:
                    512: /*
                    513:  * Catch an interrupt from the adaptor
                    514:  */
                    515: int
                    516: ahaintr(arg)
                    517:        void *arg;
                    518: {
                    519:        struct aha_softc *sc = arg;
                    520:        int iobase = sc->sc_iobase;
                    521:        u_char sts;
                    522:
                    523: #ifdef AHADEBUG
                    524:        if (aha_debug)
                    525:                printf("%s: ahaintr ", sc->sc_dev.dv_xname);
                    526: #endif /*AHADEBUG */
                    527:
                    528:        /*
                    529:         * First acknowlege the interrupt, Then if it's not telling about
                    530:         * a completed operation just return.
                    531:         */
                    532:        sts = inb(iobase + AHA_INTR_PORT);
                    533:        if ((sts & AHA_INTR_ANYINTR) == 0)
                    534:                return (0);
                    535:        outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST);
                    536:
                    537: #ifdef AHADIAG
                    538:        /* Make sure we clear CCB_SENDING before finishing a CCB. */
                    539:        aha_collect_mbo(sc);
                    540: #endif
                    541:
                    542:        /* Mail box out empty? */
                    543:        if (sts & AHA_INTR_MBOA) {
                    544:                struct aha_toggle toggle;
                    545:
                    546:                toggle.cmd.opcode = AHA_MBO_INTR_EN;
                    547:                toggle.cmd.enable = 0;
                    548:                aha_cmd(iobase, sc, sizeof(toggle.cmd), (u_char *)&toggle.cmd,
                    549:                    0, (u_char *)0);
                    550:                aha_start_ccbs(sc);
                    551:        }
                    552:
                    553:        /* Mail box in full? */
                    554:        if (sts & AHA_INTR_MBIF)
                    555:                aha_finish_ccbs(sc);
                    556:
                    557:        return (1);
                    558: }
                    559:
                    560: void
                    561: aha_reset_ccb(sc, ccb)
                    562:        struct aha_softc *sc;
                    563:        struct aha_ccb *ccb;
                    564: {
                    565:
                    566:        ccb->flags = 0;
                    567: }
                    568:
                    569: /*
                    570:  * A ccb is put onto the free list.
                    571:  */
                    572: void
                    573: aha_free_ccb(sc, ccb)
                    574:        struct aha_softc *sc;
                    575:        struct aha_ccb *ccb;
                    576: {
                    577:        int s, hashnum;
                    578:        struct aha_ccb **hashccb;
                    579:
                    580:        s = splbio();
                    581:
                    582:        if (ccb->ccb_dmam->dm_segs[0].ds_addr != 0)
                    583:                bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmam);
                    584:
                    585:        /* remove from hash table */
                    586:
                    587:        hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr);
                    588:        hashccb = &sc->sc_ccbhash[hashnum];
                    589:
                    590:        while (*hashccb) {
                    591:                if ((*hashccb)->ccb_dmam->dm_segs[0].ds_addr ==
                    592:                    ccb->ccb_dmam->dm_segs[0].ds_addr) {
                    593:                        *hashccb = (*hashccb)->nexthash;
                    594:                        break;
                    595:                }
                    596:                hashccb = &(*hashccb)->nexthash;
                    597:        }
                    598:
                    599:        aha_reset_ccb(sc, ccb);
                    600:        TAILQ_INSERT_HEAD(&sc->sc_free_ccb, ccb, chain);
                    601:
                    602:        /*
                    603:         * If there were none, wake anybody waiting for one to come free,
                    604:         * starting with queued entries.
                    605:         */
                    606:        if (TAILQ_NEXT(ccb, chain) == NULL)
                    607:                wakeup(&sc->sc_free_ccb);
                    608:
                    609:        splx(s);
                    610: }
                    611:
                    612: int
                    613: aha_init_ccb(sc, ccb, flags)
                    614:        struct aha_softc *sc;
                    615:        struct aha_ccb *ccb;
                    616:        int flags;
                    617: {
                    618:        int error, wait, state = 0;
                    619:
                    620:        bzero(ccb, sizeof(struct aha_ccb));
                    621:        aha_reset_ccb(sc, ccb);
                    622:
                    623:        wait = (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK;
                    624:        /* Create a DMA map for the data area.  */
                    625:        error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, (MAXPHYS / NBPG) + 1,
                    626:            MAXPHYS, 0, wait | BUS_DMA_ALLOCNOW, &ccb->dmam);
                    627:        if (error)
                    628:                goto fail;
                    629:        state++;
                    630:
                    631:        /* Create a DMA map for the command control block.  */
                    632:        error = bus_dmamap_create(sc->sc_dmat, CCB_PHYS_SIZE, 1, CCB_PHYS_SIZE,
                    633:            0, wait | BUS_DMA_ALLOCNOW, &ccb->ccb_dmam);
                    634:        if (error)
                    635:                goto fail;
                    636:
                    637:        return (0);
                    638:
                    639:  fail:
                    640:        if (state > 0)
                    641:                bus_dmamap_destroy(sc->sc_dmat, ccb->dmam);
                    642:        return (error);
                    643: }
                    644:
                    645: /*
                    646:  * Get a free ccb
                    647:  *
                    648:  * If there are none, see if we can allocate a new one.  If so, put it in
                    649:  * the hash table too otherwise either return an error or sleep.
                    650:  */
                    651: struct aha_ccb *
                    652: aha_get_ccb(sc, flags)
                    653:        struct aha_softc *sc;
                    654:        int flags;
                    655: {
                    656:        struct aha_ccb *ccb;
                    657:        int hashnum, s;
                    658:
                    659:        s = splbio();
                    660:
                    661:        /*
                    662:         * If we can and have to, sleep waiting for one to come free
                    663:         * but only if we can't allocate a new one.
                    664:         */
                    665:        for (;;) {
                    666:                ccb = TAILQ_FIRST(&sc->sc_free_ccb);
                    667:                if (ccb) {
                    668:                        TAILQ_REMOVE(&sc->sc_free_ccb, ccb, chain);
                    669:                        break;
                    670:                }
                    671:                if (sc->sc_numccbs < AHA_CCB_MAX) {
                    672:                        MALLOC(ccb, struct aha_ccb *, sizeof *ccb, M_DEVBUF,
                    673:                            (flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK);
                    674:                        if (ccb == NULL) {
                    675:                                printf("%s: can't malloc ccb\n",
                    676:                                    sc->sc_dev.dv_xname);
                    677:                                goto out;
                    678:                        }
                    679:                        if (aha_init_ccb(sc, ccb, flags) == 0) {
                    680:                                sc->sc_numccbs++;
                    681:                                break;
                    682:                        }
                    683:                        FREE(ccb, M_DEVBUF);
                    684:                        ccb = NULL;
                    685:                }
                    686:                if (flags & SCSI_NOSLEEP)
                    687:                        goto out;
                    688:                tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0);
                    689:        }
                    690:
                    691:        ccb->flags |= CCB_ALLOC;
                    692:
                    693:        if (bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmam, ccb, CCB_PHYS_SIZE,
                    694:            NULL, BUS_DMA_NOWAIT) != 0) {
                    695:                aha_free_ccb(sc, ccb);
                    696:                ccb = NULL;
                    697:        } else {
                    698:                hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr);
                    699:                ccb->nexthash = sc->sc_ccbhash[hashnum];
                    700:                sc->sc_ccbhash[hashnum] = ccb;
                    701:        }
                    702: out:
                    703:        splx(s);
                    704:        return (ccb);
                    705: }
                    706:
                    707: /*
                    708:  * Given a physical address, find the ccb that it corresponds to.
                    709:  */
                    710: struct aha_ccb *
                    711: aha_ccb_phys_kv(sc, ccb_phys)
                    712:        struct aha_softc *sc;
                    713:        u_long ccb_phys;
                    714: {
                    715:        int hashnum = CCB_HASH(ccb_phys);
                    716:        struct aha_ccb *ccb = sc->sc_ccbhash[hashnum];
                    717:
                    718:        while (ccb) {
                    719:                if (ccb->ccb_dmam->dm_segs[0].ds_addr == ccb_phys)
                    720:                        break;
                    721:                ccb = ccb->nexthash;
                    722:        }
                    723:        return (ccb);
                    724: }
                    725:
                    726: /*
                    727:  * Queue a CCB to be sent to the controller, and send it if possible.
                    728:  */
                    729: void
                    730: aha_queue_ccb(sc, ccb)
                    731:        struct aha_softc *sc;
                    732:        struct aha_ccb *ccb;
                    733: {
                    734:
                    735:        TAILQ_INSERT_TAIL(&sc->sc_waiting_ccb, ccb, chain);
                    736:        aha_start_ccbs(sc);
                    737: }
                    738:
                    739: /*
                    740:  * Garbage collect mailboxes that are no longer in use.
                    741:  */
                    742: void
                    743: aha_collect_mbo(sc)
                    744:        struct aha_softc *sc;
                    745: {
                    746:        struct aha_mbx_out *wmbo;       /* Mail Box Out pointer */
                    747: #ifdef AHADIAG
                    748:        struct aha_ccb *ccb;
                    749: #endif
                    750:
                    751:        wmbo = wmbx->cmbo;
                    752:
                    753:        while (sc->sc_mbofull > 0) {
                    754:                if (wmbo->cmd != AHA_MBO_FREE)
                    755:                        break;
                    756:
                    757: #ifdef AHADIAG
                    758:                ccb = aha_ccb_phys_kv(sc, phystol(wmbo->ccb_addr));
                    759:                if (!ccb) {
                    760:                        printf("%s: bad mbo ccb pointer; skipping\n",
                    761:                            sc->sc_dev.dv_xname);
                    762:                } else
                    763:                        ccb->flags &= ~CCB_SENDING;
                    764: #endif
                    765:
                    766:                --sc->sc_mbofull;
                    767:                aha_nextmbx(wmbo, wmbx, mbo);
                    768:        }
                    769:
                    770:        wmbx->cmbo = wmbo;
                    771: }
                    772:
                    773: /*
                    774:  * Send as many CCBs as we have empty mailboxes for.
                    775:  */
                    776: void
                    777: aha_start_ccbs(sc)
                    778:        struct aha_softc *sc;
                    779: {
                    780:        int iobase = sc->sc_iobase;
                    781:        struct aha_mbx_out *wmbo;       /* Mail Box Out pointer */
                    782:        struct aha_ccb *ccb;
                    783:
                    784:        wmbo = wmbx->tmbo;
                    785:
                    786:        while ((ccb = TAILQ_FIRST(&sc->sc_waiting_ccb)) != NULL) {
                    787:                if (sc->sc_mbofull >= AHA_MBX_SIZE) {
                    788:                        aha_collect_mbo(sc);
                    789:                        if (sc->sc_mbofull >= AHA_MBX_SIZE) {
                    790:                                struct aha_toggle toggle;
                    791:
                    792:                                toggle.cmd.opcode = AHA_MBO_INTR_EN;
                    793:                                toggle.cmd.enable = 1;
                    794:                                aha_cmd(iobase, sc, sizeof(toggle.cmd),
                    795:                                    (u_char *)&toggle.cmd, 0, (u_char *)0);
                    796:                                break;
                    797:                        }
                    798:                }
                    799:
                    800:                TAILQ_REMOVE(&sc->sc_waiting_ccb, ccb, chain);
                    801: #ifdef AHADIAG
                    802:                ccb->flags |= CCB_SENDING;
                    803: #endif
                    804:
                    805:                /* Link ccb to mbo. */
                    806:                bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0,
                    807:                    ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_PREWRITE);
                    808:                ltophys(ccb->ccb_dmam->dm_segs[0].ds_addr, wmbo->ccb_addr);
                    809:                if (ccb->flags & CCB_ABORT)
                    810:                        wmbo->cmd = AHA_MBO_ABORT;
                    811:                else
                    812:                        wmbo->cmd = AHA_MBO_START;
                    813:
                    814:                /* Tell the card to poll immediately. */
                    815:                outb(iobase + AHA_CMD_PORT, AHA_START_SCSI);
                    816:
                    817:                if ((ccb->xs->flags & SCSI_POLL) == 0) {
                    818:                        timeout_set(&ccb->xs->stimeout, aha_timeout, ccb);
                    819:                        timeout_add(&ccb->xs->stimeout, (ccb->timeout * hz) / 1000);
                    820:                }
                    821:
                    822:                ++sc->sc_mbofull;
                    823:                aha_nextmbx(wmbo, wmbx, mbo);
                    824:        }
                    825:
                    826:        wmbx->tmbo = wmbo;
                    827: }
                    828:
                    829: /*
                    830:  * We have a ccb which has been processed by the
                    831:  * adaptor, now we look to see how the operation
                    832:  * went. Wake up the owner if waiting
                    833:  */
                    834: void
                    835: aha_done(sc, ccb)
                    836:        struct aha_softc *sc;
                    837:        struct aha_ccb *ccb;
                    838: {
                    839:        struct scsi_sense_data *s1, *s2;
                    840:        struct scsi_xfer *xs = ccb->xs;
                    841:
                    842:        SC_DEBUG(xs->sc_link, SDEV_DB2, ("aha_done\n"));
                    843:        /*
                    844:         * Otherwise, put the results of the operation
                    845:         * into the xfer and call whoever started it
                    846:         */
                    847: #ifdef AHADIAG
                    848:        if (ccb->flags & CCB_SENDING) {
                    849:                printf("%s: exiting ccb still in transit!\n",
                    850:                    sc->sc_dev.dv_xname);
                    851:                Debugger();
                    852:                return;
                    853:        }
                    854: #endif
                    855:        if ((ccb->flags & CCB_ALLOC) == 0) {
                    856:                printf("%s: exiting ccb not allocated!\n",
                    857:                    sc->sc_dev.dv_xname);
                    858:                Debugger();
                    859:                return;
                    860:        }
                    861:        if (xs->error == XS_NOERROR) {
                    862:                if (ccb->host_stat != AHA_OK) {
                    863:                        switch (ccb->host_stat) {
                    864:                        case AHA_SEL_TIMEOUT:   /* No response */
                    865:                                xs->error = XS_SELTIMEOUT;
                    866:                                break;
                    867:                        default:        /* Other scsi protocol messes */
                    868:                                printf("%s: host_stat %x\n",
                    869:                                    sc->sc_dev.dv_xname, ccb->host_stat);
                    870:                                xs->error = XS_DRIVER_STUFFUP;
                    871:                                break;
                    872:                        }
                    873:                } else if (ccb->target_stat != SCSI_OK) {
                    874:                        switch (ccb->target_stat) {
                    875:                        case SCSI_CHECK:
                    876:                                s1 = (struct scsi_sense_data *)
                    877:                                    (((char *)(&ccb->scsi_cmd)) +
                    878:                                    ccb->scsi_cmd_length);
                    879:                                s2 = &xs->sense;
                    880:                                *s2 = *s1;
                    881:                                xs->error = XS_SENSE;
                    882:                                break;
                    883:                        case SCSI_BUSY:
                    884:                                xs->error = XS_BUSY;
                    885:                                break;
                    886:                        default:
                    887:                                printf("%s: target_stat %x\n",
                    888:                                    sc->sc_dev.dv_xname, ccb->target_stat);
                    889:                                xs->error = XS_DRIVER_STUFFUP;
                    890:                                break;
                    891:                        }
                    892:                } else
                    893:                        xs->resid = 0;
                    894:        }
                    895:        xs->flags |= ITSDONE;
                    896:
                    897:        if (VOLATILE_XS(xs)) {
                    898:                wakeup(ccb);
                    899:                return;
                    900:        }
                    901:
                    902:        if (ccb->dmam->dm_nsegs > 0) {
                    903:                if (xs->flags & SCSI_DATA_IN)
                    904:                        bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
                    905:                            ccb->dmam->dm_mapsize, BUS_DMASYNC_POSTREAD);
                    906:                if (xs->flags & SCSI_DATA_OUT)
                    907:                        bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
                    908:                            ccb->dmam->dm_mapsize, BUS_DMASYNC_POSTWRITE);
                    909:                bus_dmamap_unload(sc->sc_dmat, ccb->dmam);
                    910:        }
                    911:        aha_free_ccb(sc, ccb);
                    912:        scsi_done(xs);
                    913: }
                    914:
                    915: /*
                    916:  * Find the board and find its irq/drq
                    917:  */
                    918: int
                    919: aha_find(ia, sc, isapnp)
                    920:        struct isa_attach_args *ia;
                    921:        struct aha_softc *sc;
                    922:        int isapnp;
                    923: {
                    924:        int iobase = ia->ia_iobase;
                    925:        int i;
                    926:        u_char sts;
                    927:        struct aha_config config;
                    928:        int irq, drq;
                    929:
                    930:        /*
                    931:         * reset board, If it doesn't respond, assume
                    932:         * that it's not there.. good for the probe
                    933:         */
                    934:
                    935:        outb(iobase + AHA_CTRL_PORT, AHA_CTRL_HRST | AHA_CTRL_SRST);
                    936:
                    937:        delay(100);
                    938:        for (i = AHA_RESET_TIMEOUT; i; i--) {
                    939:                sts = inb(iobase + AHA_STAT_PORT);
                    940:                if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
                    941:                        break;
                    942:                delay(1000);    /* calibrated in msec */
                    943:        }
                    944:        if (!i) {
                    945: #ifdef AHADEBUG
                    946:                if (aha_debug)
                    947:                        printf("aha_find: No answer from adaptec board\n");
                    948: #endif /* AHADEBUG */
                    949:                return (1);
                    950:        }
                    951:
                    952:        /*
                    953:         * setup dma channel from jumpers and save int
                    954:         * level
                    955:         */
                    956:        delay(1000);            /* for Bustek 545 */
                    957:        config.cmd.opcode = AHA_INQUIRE_CONFIG;
                    958:        aha_cmd(iobase, sc, sizeof(config.cmd), (u_char *)&config.cmd,
                    959:            sizeof(config.reply), (u_char *)&config.reply);
                    960:        switch (config.reply.chan) {
                    961:        case EISADMA:
                    962:                drq = DRQUNK;   /* for EISA/VLB/PCI clones */
                    963:                break;
                    964:        case CHAN0:
                    965:                drq = 0;
                    966:                break;
                    967:        case CHAN5:
                    968:                drq = 5;
                    969:                break;
                    970:        case CHAN6:
                    971:                drq = 6;
                    972:                break;
                    973:        case CHAN7:
                    974:                drq = 7;
                    975:                break;
                    976:        default:
                    977:                printf("aha_find: illegal drq setting %x\n",
                    978:                    config.reply.chan);
                    979:                return (1);
                    980:        }
                    981:        if (isapnp)
                    982:                irq = ia->ia_irq;
                    983:
                    984:        switch (config.reply.intr) {
                    985:        case INT9:
                    986:                irq = 9;
                    987:                break;
                    988:        case INT10:
                    989:                irq = 10;
                    990:                break;
                    991:        case INT11:
                    992:                irq = 11;
                    993:                break;
                    994:        case INT12:
                    995:                irq = 12;
                    996:                break;
                    997:        case INT14:
                    998:                irq = 14;
                    999:                break;
                   1000:        case INT15:
                   1001:                irq = 15;
                   1002:                break;
                   1003:        default:
                   1004:                printf("aha_find: illegal irq setting %x\n",
                   1005:                    config.reply.intr);
                   1006:                return (EIO);
                   1007:        }
                   1008:        if (isapnp)
                   1009:                drq = ia->ia_drq;
                   1010:
                   1011:        if (sc != NULL) {
                   1012:                /* who are we on the scsi bus? */
                   1013:                sc->sc_scsi_dev = config.reply.scsi_dev;
                   1014:
                   1015:                sc->sc_iobase = iobase;
                   1016:                sc->sc_irq = irq;
                   1017:                sc->sc_drq = drq;
                   1018:        } else {
                   1019:                if (isapnp)
                   1020:                        return (0);
                   1021:                if (ia->ia_irq == IRQUNK)
                   1022:                        ia->ia_irq = irq;
                   1023:                else if (ia->ia_irq != irq)
                   1024:                        return (1);
                   1025:                if (ia->ia_drq == DRQUNK)
                   1026:                        ia->ia_drq = drq;
                   1027:                else if (ia->ia_drq != drq)
                   1028:                        return (1);
                   1029:        }
                   1030:
                   1031:        return (0);
                   1032: }
                   1033:
                   1034: /*
                   1035:  * Start the board, ready for normal operation
                   1036:  */
                   1037: void
                   1038: aha_init(sc)
                   1039:        struct aha_softc *sc;
                   1040: {
                   1041:        int iobase = sc->sc_iobase;
                   1042:        struct aha_devices devices;
                   1043:        struct aha_setup setup;
                   1044:        struct aha_mailbox mailbox;
                   1045:        struct pglist pglist;
                   1046:        struct vm_page *pg;
                   1047:        vaddr_t va;
                   1048:        vsize_t size;
                   1049:        int i;
                   1050:
                   1051:        /*
                   1052:         * XXX
                   1053:         * If we are a 1542C or later, disable the extended BIOS so that the
                   1054:         * mailbox interface is unlocked.
                   1055:         * No need to check the extended BIOS flags as some of the
                   1056:         * extensions that cause us problems are not flagged in that byte.
                   1057:         */
                   1058:        if (!strncmp(sc->sc_model, "1542C", 5)) {
                   1059:                struct aha_extbios extbios;
                   1060:                struct aha_unlock unlock;
                   1061:
                   1062:                printf("%s: unlocking mailbox interface\n",
                   1063:                    sc->sc_dev.dv_xname);
                   1064:                extbios.cmd.opcode = AHA_EXT_BIOS;
                   1065:                aha_cmd(iobase, sc, sizeof(extbios.cmd),
                   1066:                    (u_char *)&extbios.cmd, sizeof(extbios.reply),
                   1067:                    (u_char *)&extbios.reply);
                   1068:
                   1069: #ifdef AHADEBUG
                   1070:                printf("%s: flags=%02x, mailboxlock=%02x\n",
                   1071:                    sc->sc_dev.dv_xname,
                   1072:                    extbios.reply.flags, extbios.reply.mailboxlock);
                   1073: #endif /* AHADEBUG */
                   1074:
                   1075:                unlock.cmd.opcode = AHA_MBX_ENABLE;
                   1076:                unlock.cmd.junk = 0;
                   1077:                unlock.cmd.magic = extbios.reply.mailboxlock;
                   1078:                aha_cmd(iobase, sc, sizeof(unlock.cmd), (u_char *)&unlock.cmd,
                   1079:                    0, (u_char *)0);
                   1080:        }
                   1081:
                   1082: #if 0
                   1083:        /*
                   1084:         * Change the bus on/off times to not clash with other dma users.
                   1085:         */
                   1086:        aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
                   1087:        aha_cmd(sc, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
                   1088: #endif
                   1089:
                   1090:        /* Inquire Installed Devices (to force synchronous negotiation). */
                   1091:        devices.cmd.opcode = AHA_INQUIRE_DEVICES;
                   1092:        aha_cmd(iobase, sc, sizeof(devices.cmd), (u_char *)&devices.cmd,
                   1093:            sizeof(devices.reply), (u_char *)&devices.reply);
                   1094:
                   1095:        /* Obtain setup information from. */
                   1096:        setup.cmd.opcode = AHA_INQUIRE_SETUP;
                   1097:        setup.cmd.len = sizeof(setup.reply);
                   1098:        aha_cmd(iobase, sc, sizeof(setup.cmd), (u_char *)&setup.cmd,
                   1099:            sizeof(setup.reply), (u_char *)&setup.reply);
                   1100:
                   1101:        printf("%s: %s, %s\n",
                   1102:            sc->sc_dev.dv_xname,
                   1103:            setup.reply.sync_neg ? "sync" : "async",
                   1104:            setup.reply.parity ? "parity" : "no parity");
                   1105:
                   1106:        for (i = 0; i < 8; i++) {
                   1107:                if (!setup.reply.sync[i].valid ||
                   1108:                    (!setup.reply.sync[i].offset &&
                   1109:                    !setup.reply.sync[i].period))
                   1110:                        continue;
                   1111:                printf("%s targ %d: sync, offset %d, period %dnsec\n",
                   1112:                    sc->sc_dev.dv_xname, i, setup.reply.sync[i].offset,
                   1113:                    setup.reply.sync[i].period * 50 + 200);
                   1114:        }
                   1115:
                   1116:        /*
                   1117:         * Set up initial mail box for round-robin operation.
                   1118:         */
                   1119:
                   1120:        /*
                   1121:         * XXX - this vm juggling is so wrong. use bus_dma instead!
                   1122:         */
                   1123:        size = round_page(sizeof(struct aha_mbx));
                   1124:        TAILQ_INIT(&pglist);
                   1125:        if (uvm_pglistalloc(size, 0, 0xffffff, PAGE_SIZE, 0, &pglist, 1, 0) ||
                   1126:            uvm_map(kernel_map, &va, size, NULL, UVM_UNKNOWN_OFFSET, 0,
                   1127:                UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_NONE,
                   1128:                        UVM_ADV_RANDOM, 0)))
                   1129:                panic("aha_init: could not allocate mailbox");
                   1130:
                   1131:        wmbx = (struct aha_mbx *)va;
                   1132:        for (pg = TAILQ_FIRST(&pglist); pg != NULL;
                   1133:            pg = TAILQ_NEXT(pg, pageq)) {
                   1134:                pmap_kenter_pa(va, VM_PAGE_TO_PHYS(pg),
                   1135:                        VM_PROT_READ|VM_PROT_WRITE);
                   1136:                va += PAGE_SIZE;
                   1137:        }
                   1138:        pmap_update(pmap_kernel());
                   1139:        /*
                   1140:         * XXXEND
                   1141:         */
                   1142:
                   1143:        for (i = 0; i < AHA_MBX_SIZE; i++) {
                   1144:                wmbx->mbo[i].cmd = AHA_MBO_FREE;
                   1145:                wmbx->mbi[i].stat = AHA_MBI_FREE;
                   1146:        }
                   1147:        wmbx->cmbo = wmbx->tmbo = &wmbx->mbo[0];
                   1148:        wmbx->tmbi = &wmbx->mbi[0];
                   1149:        sc->sc_mbofull = 0;
                   1150:
                   1151:        /* Initialize mail box. */
                   1152:        mailbox.cmd.opcode = AHA_MBX_INIT;
                   1153:        mailbox.cmd.nmbx = AHA_MBX_SIZE;
                   1154:        ltophys(vtophys((vaddr_t)wmbx), mailbox.cmd.addr);
                   1155:        aha_cmd(iobase, sc, sizeof(mailbox.cmd), (u_char *)&mailbox.cmd,
                   1156:            0, (u_char *)0);
                   1157: }
                   1158:
                   1159: void
                   1160: aha_inquire_setup_information(sc)
                   1161:        struct aha_softc *sc;
                   1162: {
                   1163:        int iobase = sc->sc_iobase;
                   1164:        struct aha_revision revision;
                   1165:        u_char sts;
                   1166:        int i;
                   1167:        char *p;
                   1168:
                   1169:        strlcpy(sc->sc_model, "unknown", sizeof sc->sc_model);
                   1170:
                   1171:        /*
                   1172:         * Assume we have a board at this stage, do an adapter inquire
                   1173:         * to find out what type of controller it is.  If the command
                   1174:         * fails, we assume it's either a crusty board or an old 1542
                   1175:         * clone, and skip the board-specific stuff.
                   1176:         */
                   1177:        revision.cmd.opcode = AHA_INQUIRE_REVISION;
                   1178:        if (aha_cmd(iobase, sc, sizeof(revision.cmd), (u_char *)&revision.cmd,
                   1179:            sizeof(revision.reply), (u_char *)&revision.reply)) {
                   1180:                /*
                   1181:                 * aha_cmd() already started the reset.  It's not clear we
                   1182:                 * even need to bother here.
                   1183:                 */
                   1184:                for (i = AHA_RESET_TIMEOUT; i; i--) {
                   1185:                        sts = inb(iobase + AHA_STAT_PORT);
                   1186:                        if (sts == (AHA_STAT_IDLE | AHA_STAT_INIT))
                   1187:                                break;
                   1188:                        delay(1000);
                   1189:                }
                   1190:                if (!i) {
                   1191: #ifdef AHADEBUG
                   1192:                        printf("aha_init: soft reset failed\n");
                   1193: #endif /* AHADEBUG */
                   1194:                        return;
                   1195:                }
                   1196: #ifdef AHADEBUG
                   1197:                printf("aha_init: inquire command failed\n");
                   1198: #endif /* AHADEBUG */
                   1199:                goto noinquire;
                   1200:        }
                   1201:
                   1202: #ifdef AHADEBUG
                   1203:        printf("%s: inquire %x, %x, %x, %x\n",
                   1204:            sc->sc_dev.dv_xname,
                   1205:            revision.reply.boardid, revision.reply.spec_opts,
                   1206:            revision.reply.revision_1, revision.reply.revision_2);
                   1207: #endif /* AHADEBUG */
                   1208:
                   1209:        switch (revision.reply.boardid) {
                   1210:        case 0x31:
                   1211:                strlcpy(sc->sc_model, "1540", sizeof sc->sc_model);
                   1212:                break;
                   1213:        case 0x41:
                   1214:                strlcpy(sc->sc_model, "1540A/1542A/1542B", sizeof sc->sc_model);
                   1215:                break;
                   1216:        case 0x42:
                   1217:                strlcpy(sc->sc_model, "1640", sizeof sc->sc_model);
                   1218:                break;
                   1219:        case 0x43:
                   1220:        case 0x44:              /* Is this 1542C or -CF? */
                   1221:                strlcpy(sc->sc_model, "1542C", sizeof sc->sc_model);
                   1222:                break;
                   1223:        case 0x45:
                   1224:                strlcpy(sc->sc_model, "1542CF", sizeof sc->sc_model);
                   1225:                break;
                   1226:        case 0x46:
                   1227:                strlcpy(sc->sc_model, "1542CP", sizeof sc->sc_model);
                   1228:                break;
                   1229:        }
                   1230:
                   1231:        p = sc->sc_firmware;
                   1232:        *p++ = revision.reply.revision_1;
                   1233:        *p++ = '.';
                   1234:        *p++ = revision.reply.revision_2;
                   1235:        *p = '\0';
                   1236:
                   1237: noinquire:
                   1238:        printf(": model AHA-%s, firmware %s\n", sc->sc_model, sc->sc_firmware);
                   1239: }
                   1240:
                   1241: void
                   1242: ahaminphys(bp)
                   1243:        struct buf *bp;
                   1244: {
                   1245:
                   1246:        if (bp->b_bcount > ((AHA_NSEG - 1) << PGSHIFT))
                   1247:                bp->b_bcount = ((AHA_NSEG - 1) << PGSHIFT);
                   1248:        minphys(bp);
                   1249: }
                   1250:
                   1251: /*
                   1252:  * start a scsi operation given the command and the data address. Also needs
                   1253:  * the unit, target and lu.
                   1254:  */
                   1255: int
                   1256: aha_scsi_cmd(xs)
                   1257:        struct scsi_xfer *xs;
                   1258: {
                   1259:        struct scsi_link *sc_link = xs->sc_link;
                   1260:        struct aha_softc *sc = sc_link->adapter_softc;
                   1261:        struct aha_ccb *ccb;
                   1262:        struct aha_scat_gath *sg;
                   1263:        int seg, flags;
                   1264: #ifdef TFS
                   1265:        struct iovec *iovp;
                   1266:        int datalen;
                   1267: #endif
                   1268:        int s;
                   1269:
                   1270:        SC_DEBUG(sc_link, SDEV_DB2, ("aha_scsi_cmd\n"));
                   1271:        /*
                   1272:         * get a ccb to use. If the transfer
                   1273:         * is from a buf (possibly from interrupt time)
                   1274:         * then we can't allow it to sleep
                   1275:         */
                   1276:        flags = xs->flags;
                   1277:        if ((ccb = aha_get_ccb(sc, flags)) == NULL) {
                   1278:                return (TRY_AGAIN_LATER);
                   1279:        }
                   1280:        ccb->xs = xs;
                   1281:        ccb->timeout = xs->timeout;
                   1282:
                   1283:        /*
                   1284:         * Put all the arguments for the xfer in the ccb
                   1285:         */
                   1286:        if (flags & SCSI_RESET) {
                   1287:                ccb->opcode = AHA_RESET_CCB;
                   1288:                ccb->scsi_cmd_length = 0;
                   1289:        } else {
                   1290:                /* can't use S/G if zero length */
                   1291:                ccb->opcode =
                   1292:                    (xs->datalen ? AHA_INIT_SCAT_GATH_CCB : AHA_INITIATOR_CCB);
                   1293:                bcopy(xs->cmd, &ccb->scsi_cmd,
                   1294:                    ccb->scsi_cmd_length = xs->cmdlen);
                   1295:        }
                   1296:
                   1297:        if (xs->datalen) {
                   1298:                sg = ccb->scat_gath;
                   1299:                seg = 0;
                   1300: #ifdef TFS
                   1301:                if (flags & SCSI_DATA_UIO) {
                   1302:                        iovp = ((struct uio *)xs->data)->uio_iov;
                   1303:                        datalen = ((struct uio *)xs->data)->uio_iovcnt;
                   1304:                        xs->datalen = 0;
                   1305:                        while (datalen && seg < AHA_NSEG) {
                   1306:                                ltophys(iovp->iov_base, sg->seg_addr);
                   1307:                                ltophys(iovp->iov_len, sg->seg_len);
                   1308:                                xs->datalen += iovp->iov_len;
                   1309:                                SC_DEBUGN(sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)",
                   1310:                                    iovp->iov_len, iovp->iov_base));
                   1311:                                sg++;
                   1312:                                iovp++;
                   1313:                                seg++;
                   1314:                                datalen--;
                   1315:                        }
                   1316:                } else
                   1317: #endif /* TFS */
                   1318:                {
                   1319:                        /*
                   1320:                         * Set up the scatter-gather block.
                   1321:                         */
                   1322:                        if (bus_dmamap_load(sc->sc_dmat, ccb->dmam, xs->data,
                   1323:                            xs->datalen, NULL, BUS_DMA_NOWAIT) != 0) {
                   1324:                                aha_free_ccb(sc, ccb);
                   1325:                                xs->error = XS_DRIVER_STUFFUP;
                   1326:                                return (TRY_AGAIN_LATER);
                   1327:                        }
                   1328:                        for (seg = 0; seg < ccb->dmam->dm_nsegs; seg++) {
                   1329:                                ltophys(ccb->dmam->dm_segs[seg].ds_addr,
                   1330:                                    sg[seg].seg_addr);
                   1331:                                ltophys(ccb->dmam->dm_segs[seg].ds_len,
                   1332:                                    sg[seg].seg_len);
                   1333:                        }
                   1334:                }
                   1335:                if (flags & SCSI_DATA_OUT)
                   1336:                        bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
                   1337:                            ccb->dmam->dm_mapsize, BUS_DMASYNC_PREWRITE);
                   1338:                if (flags & SCSI_DATA_IN)
                   1339:                        bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
                   1340:                            ccb->dmam->dm_mapsize, BUS_DMASYNC_PREREAD);
                   1341:                ltophys((unsigned)
                   1342:                    ((struct aha_ccb *)(ccb->ccb_dmam->dm_segs[0].ds_addr))->
                   1343:                    scat_gath,
                   1344:                    ccb->data_addr);
                   1345:                ltophys(ccb->dmam->dm_nsegs * sizeof(struct aha_scat_gath),
                   1346:                    ccb->data_length);
                   1347:        } else {                /* No data xfer, use non S/G values */
                   1348:                ltophys(0, ccb->data_addr);
                   1349:                ltophys(0, ccb->data_length);
                   1350:        }
                   1351:
                   1352:        ccb->data_out = 0;
                   1353:        ccb->data_in = 0;
                   1354:        ccb->target = sc_link->target;
                   1355:        ccb->lun = sc_link->lun;
                   1356:        ccb->req_sense_length = sizeof(ccb->scsi_sense);
                   1357:        ccb->host_stat = 0x00;
                   1358:        ccb->target_stat = 0x00;
                   1359:        ccb->link_id = 0;
                   1360:        ltophys(0, ccb->link_addr);
                   1361:
                   1362:        s = splbio();
                   1363:        aha_queue_ccb(sc, ccb);
                   1364:
                   1365:        /*
                   1366:         * Usually return SUCCESSFULLY QUEUED
                   1367:         */
                   1368:        SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
                   1369:
                   1370:        if (VOLATILE_XS(xs)) {
                   1371:                while ((ccb->xs->flags & ITSDONE) == 0) {
                   1372:                        tsleep(ccb, PRIBIO, "ahawait", 0);
                   1373:                }
                   1374:                if (ccb->dmam->dm_nsegs > 0) {
                   1375:                        if (flags & SCSI_DATA_OUT)
                   1376:                                bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
                   1377:                                    ccb->dmam->dm_mapsize,
                   1378:                                    BUS_DMASYNC_POSTWRITE);
                   1379:                        if (flags & SCSI_DATA_IN)
                   1380:                                bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0,
                   1381:                                    ccb->dmam->dm_mapsize,
                   1382:                                    BUS_DMASYNC_POSTREAD);
                   1383:                        bus_dmamap_unload(sc->sc_dmat, ccb->dmam);
                   1384:                }
                   1385:                aha_free_ccb(sc, ccb);
                   1386:                scsi_done(xs);
                   1387:                splx(s);
                   1388:                return (COMPLETE);
                   1389:        }
                   1390:        splx(s);
                   1391:
                   1392:        if ((flags & SCSI_POLL) == 0)
                   1393:                return (SUCCESSFULLY_QUEUED);
                   1394:
                   1395:        /*
                   1396:         * If we can't use interrupts, poll on completion
                   1397:         */
                   1398:        if (aha_poll(sc, xs, ccb->timeout)) {
                   1399:                aha_timeout(ccb);
                   1400:                if (aha_poll(sc, xs, ccb->timeout))
                   1401:                        aha_timeout(ccb);
                   1402:        }
                   1403:        return (COMPLETE);
                   1404: }
                   1405:
                   1406: /*
                   1407:  * Poll a particular unit, looking for a particular xs
                   1408:  */
                   1409: int
                   1410: aha_poll(sc, xs, count)
                   1411:        struct aha_softc *sc;
                   1412:        struct scsi_xfer *xs;
                   1413:        int count;
                   1414: {
                   1415:        int iobase = sc->sc_iobase;
                   1416:        int s;
                   1417:
                   1418:        /* timeouts are in msec, so we loop in 1000 usec cycles */
                   1419:        while (count) {
                   1420:                /*
                   1421:                 * If we had interrupts enabled, would we
                   1422:                 * have got an interrupt?
                   1423:                 */
                   1424:                if (inb(iobase + AHA_INTR_PORT) & AHA_INTR_ANYINTR) {
                   1425:                        s = splbio();
                   1426:                        ahaintr(sc);
                   1427:                        splx(s);
                   1428:                }
                   1429:                if (xs->flags & ITSDONE)
                   1430:                        return (0);
                   1431:                delay(1000);    /* only happens in boot so ok */
                   1432:                count--;
                   1433:        }
                   1434:        return (1);
                   1435: }
                   1436:
                   1437: void
                   1438: aha_timeout(arg)
                   1439:        void *arg;
                   1440: {
                   1441:        struct aha_ccb *ccb = arg;
                   1442:        struct scsi_xfer *xs;
                   1443:        struct scsi_link *sc_link;
                   1444:        struct aha_softc *sc;
                   1445:        int s;
                   1446:
                   1447:        s = splbio();
                   1448:        bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0,
                   1449:            ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_POSTREAD);
                   1450:        xs = ccb->xs;
                   1451:        sc_link = xs->sc_link;
                   1452:        sc = sc_link->adapter_softc;
                   1453:
                   1454:        sc_print_addr(sc_link);
                   1455:        printf("timed out");
                   1456:
                   1457: #ifdef AHADIAG
                   1458:        /*
                   1459:         * If The ccb's mbx is not free, then the board has gone south?
                   1460:         */
                   1461:        aha_collect_mbo(sc);
                   1462:        if (ccb->flags & CCB_SENDING) {
                   1463:                printf("%s: not taking commands!\n", sc->sc_dev.dv_xname);
                   1464:                Debugger();
                   1465:        }
                   1466: #endif
                   1467:
                   1468:        /*
                   1469:         * If it has been through before, then
                   1470:         * a previous abort has failed, don't
                   1471:         * try abort again
                   1472:         */
                   1473:        if (ccb->flags & CCB_ABORT) {
                   1474:                /* abort timed out */
                   1475:                printf(" AGAIN\n");
                   1476:                /* XXX Must reset! */
                   1477:        } else {
                   1478:                /* abort the operation that has timed out */
                   1479:                printf("\n");
                   1480:                ccb->xs->error = XS_TIMEOUT;
                   1481:                ccb->timeout = AHA_ABORT_TIMEOUT;
                   1482:                ccb->flags |= CCB_ABORT;
                   1483:                aha_queue_ccb(sc, ccb);
                   1484:        }
                   1485:
                   1486:        splx(s);
                   1487: }
                   1488:

CVSweb