[BACK]Return to mesh.c CVS log [TXT][DIR] Up to [local] / sys / arch / macppc / dev

Annotation of sys/arch/macppc/dev/mesh.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: mesh.c,v 1.18 2007/04/22 22:31:14 deraadt Exp $       */
                      2: /*     $NetBSD: mesh.c,v 1.1 1999/02/19 13:06:03 tsubai Exp $  */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2000  Tsubai Masanari.
                      6:  * Copyright (c) 1999  Internet Research Institute, Inc.
                      7:  * 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
                     20:  *     Internet Research Institute, Inc.
                     21:  * 4. The name of the author may not be used to endorse or promote products
                     22:  *    derived from this software without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     26:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     27:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     28:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     29:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     30:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     31:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     32:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     33:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35:
                     36: #include <sys/param.h>
                     37: #include <sys/buf.h>
                     38: #include <sys/device.h>
                     39: #include <sys/errno.h>
                     40: #include <sys/kernel.h>
                     41: #include <sys/malloc.h>
                     42: #include <sys/queue.h>
                     43: #include <sys/systm.h>
                     44:
                     45: #include <uvm/uvm_extern.h>
                     46:
                     47: #include <scsi/scsi_all.h>
                     48: #include <scsi/scsiconf.h>
                     49: #include <scsi/scsi_message.h>
                     50:
                     51: #include <dev/ofw/openfirm.h>
                     52:
                     53: #include <machine/autoconf.h>
                     54: #include <machine/cpu.h>
                     55:
                     56: #include <macppc/dev/dbdma.h>
                     57:
                     58: #ifdef MESH_DEBUG
                     59: # define DPRINTF printf
                     60: #else
                     61: # define DPRINTF while (0) printf
                     62: #endif
                     63:
                     64: /* MESH register offsets */
                     65: #define MESH_XFER_COUNT0       0x00    /* transfer count (low)  */
                     66: #define MESH_XFER_COUNT1       0x10    /* transfer count (high) */
                     67: #define MESH_FIFO              0x20    /* FIFO (16byte depth) */
                     68: #define MESH_SEQUENCE          0x30    /* command register */
                     69: #define MESH_BUS_STATUS0       0x40
                     70: #define MESH_BUS_STATUS1       0x50
                     71: #define MESH_FIFO_COUNT                0x60
                     72: #define MESH_EXCEPTION         0x70
                     73: #define MESH_ERROR             0x80
                     74: #define MESH_INTR_MASK         0x90
                     75: #define MESH_INTERRUPT         0xa0
                     76: #define MESH_SOURCE_ID         0xb0
                     77: #define MESH_DEST_ID           0xc0
                     78: #define MESH_SYNC_PARAM                0xd0
                     79: #define MESH_MESH_ID           0xe0    /* MESH version */
                     80: #define MESH_SEL_TIMEOUT       0xf0    /* selection timeout delay */
                     81:
                     82: #define MESH_SIGNATURE         0xe2    /* XXX wrong! */
                     83:
                     84: /* MESH commands */
                     85: #define MESH_CMD_ARBITRATE     0x01
                     86: #define MESH_CMD_SELECT                0x02
                     87: #define MESH_CMD_COMMAND       0x03
                     88: #define MESH_CMD_STATUS                0x04
                     89: #define MESH_CMD_DATAOUT       0x05
                     90: #define MESH_CMD_DATAIN                0x06
                     91: #define MESH_CMD_MSGOUT                0x07
                     92: #define MESH_CMD_MSGIN         0x08
                     93: #define MESH_CMD_BUSFREE       0x09
                     94: #define MESH_CMD_ENABLE_PARITY 0x0A
                     95: #define MESH_CMD_DISABLE_PARITY        0x0B
                     96: #define MESH_CMD_ENABLE_RESEL  0x0C
                     97: #define MESH_CMD_DISABLE_RESEL 0x0D
                     98: #define MESH_CMD_RESET_MESH    0x0E
                     99: #define MESH_CMD_FLUSH_FIFO    0x0F
                    100: #define MESH_SEQ_DMA           0x80
                    101: #define MESH_SEQ_TARGET                0x40
                    102: #define MESH_SEQ_ATN           0x20
                    103: #define MESH_SEQ_ACTNEG                0x10
                    104:
                    105: /* INTERRUPT/INTR_MASK register bits */
                    106: #define MESH_INTR_ERROR                0x04
                    107: #define MESH_INTR_EXCEPTION    0x02
                    108: #define MESH_INTR_CMDDONE      0x01
                    109:
                    110: /* EXCEPTION register bits */
                    111: #define MESH_EXC_SELATN                0x20    /* selected and ATN asserted (T) */
                    112: #define MESH_EXC_SELECTED      0x10    /* selected (T) */
                    113: #define MESH_EXC_RESEL         0x08    /* reselected */
                    114: #define MESH_EXC_ARBLOST       0x04    /* arbitration lost */
                    115: #define MESH_EXC_PHASEMM       0x02    /* phase mismatch */
                    116: #define MESH_EXC_SELTO         0x01    /* selection timeout */
                    117:
                    118: /* ERROR register bits */
                    119: #define MESH_ERR_DISCONNECT    0x40    /* unexpected disconnect */
                    120: #define MESH_ERR_SCSI_RESET    0x20    /* Rst signal asserted */
                    121: #define MESH_ERR_SEQERR                0x10    /* sequence error */
                    122: #define MESH_ERR_PARITY_ERR3   0x08    /* parity error */
                    123: #define MESH_ERR_PARITY_ERR2   0x04
                    124: #define MESH_ERR_PARITY_ERR1   0x02
                    125: #define MESH_ERR_PARITY_ERR0   0x01
                    126:
                    127: /* BUS_STATUS0 status bits */
                    128: #define MESH_STATUS0_REQ32     0x80
                    129: #define MESH_STATUS0_ACK32     0x40
                    130: #define MESH_STATUS0_REQ       0x20
                    131: #define MESH_STATUS0_ACK       0x10
                    132: #define MESH_STATUS0_ATN       0x08
                    133: #define MESH_STATUS0_MSG       0x04
                    134: #define MESH_STATUS0_CD                0x02
                    135: #define MESH_STATUS0_IO                0x01
                    136:
                    137: /* BUS_STATUS1 status bits */
                    138: #define MESH_STATUS1_RST       0x80
                    139: #define MESH_STATUS1_BSY       0x40
                    140: #define MESH_STATUS1_SEL       0x20
                    141:
                    142: #define T_SYNCMODE 0x01                /* target uses sync mode */
                    143: #define T_SYNCNEGO 0x02                /* sync negotiation done */
                    144:
                    145: struct mesh_tinfo {
                    146:        int flags;
                    147:        int period;
                    148:        int offset;
                    149: };
                    150:
                    151: /* scb flags */
                    152: #define MESH_POLL              0x01
                    153: #define MESH_CHECK             0x02
                    154: #define MESH_SENSE             0x04
                    155: #define MESH_READ              0x80
                    156:
                    157: struct mesh_scb {
                    158:        TAILQ_ENTRY(mesh_scb) chain;
                    159:        int flags;
                    160:        struct scsi_xfer *xs;
                    161:        struct scsi_generic cmd;
                    162:        int cmdlen;
                    163:        int target;                     /* target SCSI ID */
                    164:        int resid;
                    165:        void *daddr;
                    166:        vsize_t dlen;
                    167:        int status;
                    168: };
                    169:
                    170: /* sc_flags value */
                    171: #define MESH_DMA_ACTIVE        0x01
                    172:
                    173: #define MESH_DMALIST_MAX       32
                    174:
                    175: struct mesh_softc {
                    176:        struct device sc_dev;           /* us as a device */
                    177:        struct scsi_link sc_link;
                    178:
                    179:        struct scsibus_softc *sc_scsibus;
                    180:
                    181:        u_char *sc_reg;                 /* MESH base address */
                    182:        bus_dmamap_t sc_dmamap;
                    183:        bus_dma_tag_t sc_dmat;
                    184:        struct dbdma_regmap *sc_dmareg; /* DMA register address */
                    185:        struct dbdma_command *sc_dmacmd;        /* DMA command area */
                    186:        dbdma_t sc_dbdma;
                    187:
                    188:        int sc_flags;
                    189:        int sc_cfflags;                 /* copy of config flags */
                    190:        int sc_minsync;                 /* minimum sync period */
                    191:        int sc_irq;
                    192:        int sc_freq;                    /* SCSI bus frequency in MHz */
                    193:        int sc_id;                      /* our SCSI ID */
                    194:        struct mesh_tinfo sc_tinfo[8];  /* target information */
                    195:
                    196:        int sc_nextstate;
                    197:        int sc_prevphase;
                    198:        struct mesh_scb *sc_nexus;      /* current command */
                    199:
                    200:        int sc_msgout;
                    201:        int sc_imsglen;
                    202:        u_char sc_imsg[16];
                    203:        u_char sc_omsg[16];
                    204:
                    205:        TAILQ_HEAD(, mesh_scb) free_scb;
                    206:        TAILQ_HEAD(, mesh_scb) ready_scb;
                    207:        struct mesh_scb sc_scb[16];
                    208:
                    209:        struct timeout sc_tmo;
                    210: };
                    211:
                    212: /* mesh_msgout() values */
                    213: #define SEND_REJECT    1
                    214: #define SEND_IDENTIFY  2
                    215: #define SEND_SDTR      4
                    216:
                    217: static inline int mesh_read_reg(struct mesh_softc *, int);
                    218: static inline void mesh_set_reg(struct mesh_softc *, int, int);
                    219:
                    220: int mesh_match(struct device *, void *, void *);
                    221: void mesh_attach(struct device *, struct device *, void *);
                    222: void mesh_shutdownhook(void *);
                    223: int mesh_intr(void *);
                    224: void mesh_error(struct mesh_softc *, struct mesh_scb *, int, int);
                    225: void mesh_select(struct mesh_softc *, struct mesh_scb *);
                    226: void mesh_identify(struct mesh_softc *, struct mesh_scb *);
                    227: void mesh_command(struct mesh_softc *, struct mesh_scb *);
                    228: int mesh_dma_setup(struct mesh_softc *, struct mesh_scb *);
                    229: int mesh_dataio(struct mesh_softc *, struct mesh_scb *);
                    230: void mesh_status(struct mesh_softc *, struct mesh_scb *);
                    231: void mesh_msgin(struct mesh_softc *, struct mesh_scb *);
                    232: void mesh_msgout(struct mesh_softc *, int);
                    233: void mesh_bus_reset(struct mesh_softc *);
                    234: void mesh_reset(struct mesh_softc *);
                    235: int mesh_stp(struct mesh_softc *, int);
                    236: void mesh_setsync(struct mesh_softc *, struct mesh_tinfo *);
                    237: struct mesh_scb *mesh_get_scb(struct mesh_softc *);
                    238: void mesh_free_scb(struct mesh_softc *, struct mesh_scb *);
                    239: int mesh_scsi_cmd(struct scsi_xfer *);
                    240: void mesh_sched(struct mesh_softc *);
                    241: int mesh_poll(struct scsi_xfer *);
                    242: void mesh_done(struct mesh_softc *, struct mesh_scb *);
                    243: void mesh_timeout(void *);
                    244: void mesh_minphys(struct buf *);
                    245:
                    246: struct cfattach mesh_ca = {
                    247:        sizeof(struct mesh_softc), mesh_match, mesh_attach
                    248: };
                    249:
                    250: struct cfdriver mesh_cd = {
                    251:        NULL, "mesh", DV_DULL
                    252: };
                    253:
                    254: struct scsi_adapter mesh_switch = {
                    255:        mesh_scsi_cmd, mesh_minphys, NULL, NULL
                    256: };
                    257:
                    258: struct scsi_device mesh_dev = {
                    259:        NULL, NULL, NULL, NULL
                    260: };
                    261:
                    262: #define MESH_DATAOUT   0
                    263: #define MESH_DATAIN    MESH_STATUS0_IO
                    264: #define MESH_COMMAND   MESH_STATUS0_CD
                    265: #define MESH_STATUS    (MESH_STATUS0_CD | MESH_STATUS0_IO)
                    266: #define MESH_MSGOUT    (MESH_STATUS0_MSG | MESH_STATUS0_CD)
                    267: #define MESH_MSGIN     (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
                    268:
                    269: #define MESH_SELECTING 8
                    270: #define MESH_IDENTIFY  9
                    271: #define MESH_COMPLETE  10
                    272: #define MESH_BUSFREE   11
                    273: #define MESH_UNKNOWN   -1
                    274:
                    275: #define MESH_PHASE_MASK        (MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
                    276:
                    277: int
                    278: mesh_match(struct device *parent, void *vcf, void *aux)
                    279: {
                    280:        struct confargs *ca = aux;
                    281:        char compat[32];
                    282:
                    283:        if (strcmp(ca->ca_name, "mesh") == 0)
                    284:                return 1;
                    285:
                    286:        memset(compat, 0, sizeof(compat));
                    287:        OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
                    288:        if (strcmp(compat, "chrp,mesh0") == 0)
                    289:                return 1;
                    290:
                    291:        return 0;
                    292: }
                    293:
                    294: void
                    295: mesh_attach(struct device *parent, struct device *self, void *aux)
                    296: {
                    297:        struct mesh_softc *sc = (void *)self;
                    298:        struct confargs *ca = aux;
                    299:        struct scsibus_attach_args saa;
                    300:        int i, error;
                    301:        u_int *reg;
                    302:
                    303:        reg = ca->ca_reg;
                    304:        reg[0] += ca->ca_baseaddr;
                    305:        reg[2] += ca->ca_baseaddr;
                    306:        if ((sc->sc_reg = mapiodev(reg[0], reg[1])) == NULL) {
                    307:                printf(": cannot map device registers\n");
                    308:                return;
                    309:        }
                    310:
                    311:        sc->sc_irq = ca->ca_intr[0];
                    312:        if ((sc->sc_dmareg = mapiodev(reg[2], reg[3])) == NULL) {
                    313:                printf(": cannot map DMA registers\n");
                    314:                goto noreg;
                    315:        }
                    316:
                    317:        sc->sc_cfflags = sc->sc_dev.dv_cfdata->cf_flags;
                    318:
                    319:        if (OF_getprop(ca->ca_node, "clock-frequency", &sc->sc_freq, 4) != 4) {
                    320:                printf(": cannot get clock-frequency\n");
                    321:                goto nofreq;
                    322:        }
                    323:
                    324:        sc->sc_dmat = ca->ca_dmat;
                    325:        if ((error = bus_dmamap_create(sc->sc_dmat,
                    326:            MESH_DMALIST_MAX * DBDMA_COUNT_MAX, MESH_DMALIST_MAX,
                    327:            DBDMA_COUNT_MAX, NBPG, BUS_DMA_NOWAIT, &sc->sc_dmamap)) != 0) {
                    328:                printf(": cannot create DMA map, error = %d\n", error);
                    329:                goto nofreq;
                    330:        }
                    331:
                    332:        sc->sc_freq /= 1000000; /* in MHz */
                    333:        sc->sc_minsync = 25;    /* maximum sync rate = 10MB/sec */
                    334:        sc->sc_id = 7;
                    335:
                    336:        TAILQ_INIT(&sc->free_scb);
                    337:        TAILQ_INIT(&sc->ready_scb);
                    338:        for (i = 0; i < sizeof(sc->sc_scb)/sizeof(sc->sc_scb[0]); i++)
                    339:                TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain);
                    340:
                    341:        if ((sc->sc_dbdma = dbdma_alloc(sc->sc_dmat, MESH_DMALIST_MAX))
                    342:            == NULL) {
                    343:                printf(": cannot alloc dma descriptors\n");
                    344:                goto nodbdma;
                    345:        }
                    346:
                    347:        sc->sc_dmacmd = sc->sc_dbdma->d_addr;
                    348:        timeout_set(&sc->sc_tmo, mesh_timeout, sc);
                    349:
                    350:        mesh_reset(sc);
                    351:        mesh_bus_reset(sc);
                    352:
                    353:        printf(" irq %d: %dMHz, SCSI ID %d\n",
                    354:            sc->sc_irq, sc->sc_freq, sc->sc_id);
                    355:
                    356:        sc->sc_link.adapter_softc = sc;
                    357:        sc->sc_link.adapter_target = sc->sc_id;
                    358:        sc->sc_link.device = &mesh_dev;
                    359:        sc->sc_link.adapter = &mesh_switch;
                    360:        sc->sc_link.openings = 2;
                    361:
                    362:        bzero(&saa, sizeof(saa));
                    363:        saa.saa_sc_link = &sc->sc_link;
                    364:
                    365:        config_found(&sc->sc_dev, &saa, scsiprint);
                    366:
                    367:        mac_intr_establish(parent, sc->sc_irq, IST_LEVEL, IPL_BIO, mesh_intr,
                    368:            sc, sc->sc_dev.dv_xname);
                    369:
                    370:        /* Reset SCSI bus when halt. */
                    371:        shutdownhook_establish(mesh_shutdownhook, sc);
                    372:
                    373:        return;
                    374: nodbdma:
                    375:        bus_dmamap_destroy(sc->sc_dmat, sc->sc_dmamap);
                    376: nofreq:
                    377:        unmapiodev(sc->sc_dmareg, reg[3]);
                    378: noreg:
                    379:        unmapiodev(sc->sc_reg, reg[1]);
                    380: }
                    381:
                    382: #define MESH_SET_XFER(sc, count) do {                                  \
                    383:        mesh_set_reg(sc, MESH_XFER_COUNT0, count);                      \
                    384:        mesh_set_reg(sc, MESH_XFER_COUNT1, count >> 8);                 \
                    385: } while (0)
                    386:
                    387: #define MESH_GET_XFER(sc) ((mesh_read_reg(sc, MESH_XFER_COUNT1) << 8) |        \
                    388:                           mesh_read_reg(sc, MESH_XFER_COUNT0))
                    389:
                    390: int
                    391: mesh_read_reg(struct mesh_softc *sc, int reg)
                    392: {
                    393:        return in8(sc->sc_reg + reg);
                    394: }
                    395:
                    396: void
                    397: mesh_set_reg(struct mesh_softc *sc, int reg, int val)
                    398: {
                    399:        out8(sc->sc_reg + reg, val);
                    400: }
                    401:
                    402: void
                    403: mesh_shutdownhook(void *arg)
                    404: {
                    405:        struct mesh_softc *sc = arg;
                    406:
                    407:        /* Set to async mode. */
                    408:        mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
                    409:        mesh_bus_reset(sc);
                    410: }
                    411:
                    412: #ifdef MESH_DEBUG
                    413: static char scsi_phase[][8] = {
                    414:        "DATAOUT",
                    415:        "DATAIN",
                    416:        "COMMAND",
                    417:        "STATUS",
                    418:        "",
                    419:        "",
                    420:        "MSGOUT",
                    421:        "MSGIN"
                    422: };
                    423: #endif
                    424:
                    425: int
                    426: mesh_intr(void *arg)
                    427: {
                    428:        struct mesh_softc *sc = arg;
                    429:        struct mesh_scb *scb;
                    430:        int fifocnt;
                    431:        u_char intr, exception, error, status0, status1;
                    432:
                    433:        intr = mesh_read_reg(sc, MESH_INTERRUPT);
                    434:
                    435:        if (intr == 0) {
                    436:                DPRINTF("%s: stray interrupt\n", sc->sc_dev.dv_xname);
                    437:                return 0;
                    438:        }
                    439:        exception = mesh_read_reg(sc, MESH_EXCEPTION);
                    440:        error = mesh_read_reg(sc, MESH_ERROR);
                    441:        status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
                    442:        status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
                    443:
                    444:        /* clear interrupt */
                    445:        mesh_set_reg(sc, MESH_INTERRUPT, intr);
                    446:
                    447: #ifdef MESH_DEBUG
                    448: {
                    449:
                    450:        printf("mesh_intr status0 = 0x%x (%s), exc = 0x%x\n",
                    451:            status0, scsi_phase[status0 & 7], exception);
                    452: }
                    453: #endif
                    454:
                    455:        scb = sc->sc_nexus;
                    456:        if (scb == NULL) {
                    457:                DPRINTF("%s: NULL nexus\n", sc->sc_dev.dv_xname);
                    458:                return 1;
                    459:        }
                    460:
                    461:        if (intr & MESH_INTR_CMDDONE) {
                    462:                if (sc->sc_flags & MESH_DMA_ACTIVE) {
                    463:                        dbdma_stop(sc->sc_dmareg);
                    464:                        bus_dmamap_unload(sc->sc_dmat, sc->sc_dmamap);
                    465:
                    466:                        sc->sc_flags &= ~MESH_DMA_ACTIVE;
                    467:                        scb->resid = MESH_GET_XFER(sc);
                    468:
                    469:                        fifocnt = mesh_read_reg(sc, MESH_FIFO_COUNT);
                    470:                        if (fifocnt != 0) {
                    471:                                if (scb->flags & MESH_READ) {
                    472:                                        char *cp;
                    473:
                    474:                                        cp = (char *)scb->daddr + scb->dlen
                    475:                                            - fifocnt;
                    476:                                        DPRINTF("fifocnt = %d, resid = %d\n",
                    477:                                            fifocnt, scb->resid);
                    478:                                        while (fifocnt > 0) {
                    479:                                                *cp++ = mesh_read_reg(sc,
                    480:                                                    MESH_FIFO);
                    481:                                                fifocnt--;
                    482:                                        }
                    483:                                } else {
                    484:                                        mesh_set_reg(sc, MESH_SEQUENCE,
                    485:                                            MESH_CMD_FLUSH_FIFO);
                    486:                                }
                    487:                        } else {
                    488:                                /* Clear all interrupts */
                    489:                                mesh_set_reg(sc, MESH_INTERRUPT, 7);
                    490:                        }
                    491:                }
                    492:        }
                    493:
                    494:        if (intr & MESH_INTR_ERROR) {
                    495:                printf("%s: error %02x %02x\n",
                    496:                    sc->sc_dev.dv_xname, error, exception);
                    497:                mesh_error(sc, scb, error, 0);
                    498:                return 1;
                    499:        }
                    500:
                    501:        if (intr & MESH_INTR_EXCEPTION) {
                    502:                /* selection timeout */
                    503:                if (exception & MESH_EXC_SELTO) {
                    504:                        mesh_error(sc, scb, 0, exception);
                    505:                        return 1;
                    506:                }
                    507:
                    508:                /* phase mismatch */
                    509:                if (exception & MESH_EXC_PHASEMM) {
                    510:                        DPRINTF("%s: PHASE MISMATCH; nextstate = %d -> ",
                    511:                            sc->sc_dev.dv_xname, sc->sc_nextstate);
                    512:                        sc->sc_nextstate = status0 & MESH_PHASE_MASK;
                    513:
                    514:                        DPRINTF("%d, resid = %d\n",
                    515:                            sc->sc_nextstate, scb->resid);
                    516:                }
                    517:        }
                    518:
                    519:        if (sc->sc_nextstate == MESH_UNKNOWN)
                    520:                sc->sc_nextstate = status0 & MESH_PHASE_MASK;
                    521:
                    522:        switch (sc->sc_nextstate) {
                    523:
                    524:        case MESH_IDENTIFY:
                    525:                mesh_identify(sc, scb);
                    526:                break;
                    527:        case MESH_COMMAND:
                    528:                mesh_command(sc, scb);
                    529:                break;
                    530:        case MESH_DATAIN:
                    531:        case MESH_DATAOUT:
                    532:                if (mesh_dataio(sc, scb)) {
                    533:                        scb->xs->error = XS_DRIVER_STUFFUP;
                    534:                        mesh_done(sc, scb);
                    535:                }
                    536:                break;
                    537:        case MESH_STATUS:
                    538:                mesh_status(sc, scb);
                    539:                break;
                    540:        case MESH_MSGIN:
                    541:                mesh_msgin(sc, scb);
                    542:                break;
                    543:        case MESH_COMPLETE:
                    544:                mesh_done(sc, scb);
                    545:                break;
                    546:
                    547:        default:
                    548:                printf("%s: unknown state (%d)\n", sc->sc_dev.dv_xname,
                    549:                    sc->sc_nextstate);
                    550:                scb->xs->error = XS_DRIVER_STUFFUP;
                    551:                mesh_done(sc, scb);
                    552:        }
                    553:
                    554:        return 1;
                    555: }
                    556:
                    557: void
                    558: mesh_error(struct mesh_softc *sc, struct mesh_scb *scb, int error,
                    559:     int exception)
                    560: {
                    561:        if (error & MESH_ERR_SCSI_RESET) {
                    562:                printf("%s: SCSI RESET\n", sc->sc_dev.dv_xname);
                    563:
                    564:                /* Wait until the RST signal is deasserted. */
                    565:                while (mesh_read_reg(sc, MESH_BUS_STATUS1) & MESH_STATUS1_RST);
                    566:                        mesh_reset(sc);
                    567:                return;
                    568:        }
                    569:
                    570:        if (error & MESH_ERR_PARITY_ERR0) {
                    571:                printf("%s: parity error\n", sc->sc_dev.dv_xname);
                    572:                scb->xs->error = XS_DRIVER_STUFFUP;
                    573:        }
                    574:
                    575:        if (error & MESH_ERR_DISCONNECT) {
                    576:                printf("%s: unexpected disconnect\n", sc->sc_dev.dv_xname);
                    577:                if (sc->sc_nextstate != MESH_COMPLETE)
                    578:                        scb->xs->error = XS_DRIVER_STUFFUP;
                    579:        }
                    580:
                    581:        if (exception & MESH_EXC_SELTO) {
                    582:                /* XXX should reset bus here? */
                    583:                scb->xs->error = XS_SELTIMEOUT;
                    584:        }
                    585:
                    586:        mesh_done(sc, scb);
                    587: }
                    588:
                    589: void
                    590: mesh_select(struct mesh_softc *sc, struct mesh_scb *scb)
                    591: {
                    592:        struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
                    593:
                    594:        DPRINTF("mesh_select\n");
                    595:
                    596:        mesh_setsync(sc, ti);
                    597:        MESH_SET_XFER(sc, 0);
                    598:
                    599:        /* arbitration */
                    600:
                    601:        /*
                    602:         * MESH mistakenly asserts TARGET ID bit along with its own ID bit
                    603:         * in arbitration phase (like selection).  So we should load
                    604:         * initiator ID to DestID register temporarily.
                    605:         */
                    606:        mesh_set_reg(sc, MESH_DEST_ID, sc->sc_id);
                    607:        mesh_set_reg(sc, MESH_INTR_MASK, 0);    /* disable intr. */
                    608:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ARBITRATE);
                    609:
                    610:        while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
                    611:        mesh_set_reg(sc, MESH_INTERRUPT, 1);
                    612:        mesh_set_reg(sc, MESH_INTR_MASK, 7);
                    613:
                    614:        /* selection */
                    615:        mesh_set_reg(sc, MESH_DEST_ID, scb->target);
                    616:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_SELECT | MESH_SEQ_ATN);
                    617:
                    618:        sc->sc_prevphase = MESH_SELECTING;
                    619:        sc->sc_nextstate = MESH_IDENTIFY;
                    620:
                    621:        timeout_add(&sc->sc_tmo, 10*hz);
                    622: }
                    623:
                    624: void
                    625: mesh_identify(struct mesh_softc *sc, struct mesh_scb *scb)
                    626: {
                    627:        struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
                    628:
                    629:        DPRINTF("mesh_identify\n");
                    630:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
                    631:
                    632:        if ((ti->flags & T_SYNCNEGO) == 0) {
                    633:                ti->period = sc->sc_minsync;
                    634:                ti->offset = 15;
                    635:                mesh_msgout(sc, SEND_IDENTIFY | SEND_SDTR);
                    636:                sc->sc_nextstate = MESH_MSGIN;
                    637:        } else {
                    638:                mesh_msgout(sc, SEND_IDENTIFY);
                    639:                sc->sc_nextstate = MESH_COMMAND;
                    640:        }
                    641: }
                    642:
                    643: void
                    644: mesh_command(struct mesh_softc *sc, struct mesh_scb *scb)
                    645: {
                    646:        int i;
                    647:        char *cmdp;
                    648:
                    649: #ifdef MESH_DEBUG
                    650:        printf("mesh_command cdb = %02x", scb->cmd.opcode);
                    651:        for (i = 0; i < 5; i++)
                    652:                printf(" %02x", scb->cmd.bytes[i]);
                    653:        printf("\n");
                    654: #endif
                    655:
                    656:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
                    657:
                    658:        MESH_SET_XFER(sc, scb->cmdlen);
                    659:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_COMMAND);
                    660:
                    661:        cmdp = (char *)&scb->cmd;
                    662:        for (i = 0; i < scb->cmdlen; i++)
                    663:                mesh_set_reg(sc, MESH_FIFO, *cmdp++);
                    664:
                    665:        if (scb->resid == 0)
                    666:                sc->sc_nextstate = MESH_STATUS;         /* no data xfer */
                    667:        else
                    668:                sc->sc_nextstate = MESH_DATAIN;
                    669: }
                    670:
                    671: int
                    672: mesh_dma_setup(struct mesh_softc *sc, struct mesh_scb *scb)
                    673: {
                    674:        int datain = scb->flags & MESH_READ;
                    675:        struct dbdma_command *cmdp;
                    676:        u_int cmd;
                    677:        int i, error;
                    678:
                    679:        if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dmamap, scb->daddr,
                    680:            scb->dlen, NULL, BUS_DMA_NOWAIT)) != 0)
                    681:                return (error);
                    682:
                    683:        cmdp = sc->sc_dmacmd;
                    684:        cmd = datain ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE;
                    685:
                    686:        for (i = 0; i < sc->sc_dmamap->dm_nsegs; i++, cmdp++) {
                    687:                if (i + 1 == sc->sc_dmamap->dm_nsegs)
                    688:                        cmd = datain ? DBDMA_CMD_IN_LAST : DBDMA_CMD_OUT_LAST;
                    689:                DBDMA_BUILD(cmdp, cmd, 0, sc->sc_dmamap->dm_segs[i].ds_len,
                    690:                    sc->sc_dmamap->dm_segs[i].ds_addr, DBDMA_INT_NEVER,
                    691:                    DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
                    692:        }
                    693:
                    694:        DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
                    695:            DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
                    696:
                    697:        return(0);
                    698: }
                    699:
                    700: int
                    701: mesh_dataio(struct mesh_softc *sc, struct mesh_scb *scb)
                    702: {
                    703:        int error;
                    704:
                    705:        if ((error = mesh_dma_setup(sc, scb)))
                    706:                return(error);
                    707:
                    708:        if (scb->dlen == 65536)
                    709:                MESH_SET_XFER(sc, 0);   /* TC = 0 means 64KB transfer */
                    710:        else
                    711:                MESH_SET_XFER(sc, scb->dlen);
                    712:
                    713:        if (scb->flags & MESH_READ)
                    714:                mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAIN | MESH_SEQ_DMA);
                    715:        else
                    716:                mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAOUT | MESH_SEQ_DMA);
                    717:
                    718:        dbdma_start(sc->sc_dmareg, sc->sc_dbdma);
                    719:        sc->sc_flags |= MESH_DMA_ACTIVE;
                    720:        sc->sc_nextstate = MESH_STATUS;
                    721:
                    722:        return(0);
                    723: }
                    724:
                    725: void
                    726: mesh_status(struct mesh_softc *sc, struct mesh_scb *scb)
                    727: {
                    728:        if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) {  /* XXX cheat */
                    729:                DPRINTF("mesh_status(0)\n");
                    730:                MESH_SET_XFER(sc, 1);
                    731:                mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_STATUS);
                    732:                sc->sc_nextstate = MESH_STATUS;
                    733:                return;
                    734:        }
                    735:
                    736:        scb->status = mesh_read_reg(sc, MESH_FIFO);
                    737:        DPRINTF("mesh_status(1): status = 0x%x\n", scb->status);
                    738:        if (mesh_read_reg(sc, MESH_FIFO_COUNT) != 0)
                    739:                DPRINTF("FIFO_COUNT=%d\n", mesh_read_reg(sc, MESH_FIFO_COUNT));
                    740:
                    741:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
                    742:        MESH_SET_XFER(sc, 1);
                    743:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
                    744:
                    745:        sc->sc_nextstate = MESH_MSGIN;
                    746: }
                    747:
                    748: #define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80)
                    749: #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
                    750: #define ISEXTMSG(m) ((m) == 1)
                    751:
                    752: void
                    753: mesh_msgin(struct mesh_softc *sc, struct mesh_scb *scb)
                    754: {
                    755:        DPRINTF("mesh_msgin\n");
                    756:
                    757:        if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) {  /* XXX cheat */
                    758:                MESH_SET_XFER(sc, 1);
                    759:                mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
                    760:                sc->sc_imsglen = 0;
                    761:                sc->sc_nextstate = MESH_MSGIN;
                    762:                return;
                    763:        }
                    764:
                    765:        sc->sc_imsg[sc->sc_imsglen++] = mesh_read_reg(sc, MESH_FIFO);
                    766:
                    767:        if (sc->sc_imsglen == 1 && IS1BYTEMSG(sc->sc_imsg[0]))
                    768:                goto gotit;
                    769:        if (sc->sc_imsglen == 2 && IS2BYTEMSG(sc->sc_imsg[0]))
                    770:                goto gotit;
                    771:        if (sc->sc_imsglen >= 3 && ISEXTMSG(sc->sc_imsg[0]) &&
                    772:            sc->sc_imsglen == sc->sc_imsg[1] + 2)
                    773:                goto gotit;
                    774:
                    775:        sc->sc_nextstate = MESH_MSGIN;
                    776:        MESH_SET_XFER(sc, 1);
                    777:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
                    778:        return;
                    779:
                    780: gotit:
                    781: #ifdef MESH_DEBUG
                    782:        {
                    783:                int i;
                    784:                printf("msgin:");
                    785:                for (i = 0; i < sc->sc_imsglen; i++)
                    786:                        printf(" 0x%02x", sc->sc_imsg[i]);
                    787:                printf("\n");
                    788:        }
                    789: #endif
                    790:
                    791:        switch (sc->sc_imsg[0]) {
                    792:        case MSG_CMDCOMPLETE:
                    793:                mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
                    794:                sc->sc_nextstate = MESH_COMPLETE;
                    795:                sc->sc_imsglen = 0;
                    796:                return;
                    797:
                    798:        case MSG_MESSAGE_REJECT:
                    799:                if (sc->sc_msgout & SEND_SDTR) {
                    800:                        printf("SDTR rejected\n");
                    801:                        printf("using async mode\n");
                    802:                        sc->sc_tinfo[scb->target].period = 0;
                    803:                        sc->sc_tinfo[scb->target].offset = 0;
                    804:                        mesh_setsync(sc, &sc->sc_tinfo[scb->target]);
                    805:                        break;
                    806:                }
                    807:                break;
                    808:
                    809:        case MSG_NOOP:
                    810:                break;
                    811:
                    812:        case MSG_EXTENDED:
                    813:                goto extended_msg;
                    814:
                    815:        default:
                    816:                sc_print_addr(scb->xs->sc_link);
                    817:                printf("unrecognized MESSAGE(0x%02x); sending REJECT\n",
                    818:                    sc->sc_imsg[0]);
                    819:
                    820:        reject:
                    821:                mesh_msgout(sc, SEND_REJECT);
                    822:                return;
                    823:        }
                    824:        goto done;
                    825:
                    826: extended_msg:
                    827:        /* process an extended message */
                    828:        switch (sc->sc_imsg[2]) {
                    829:        case MSG_EXT_SDTR:
                    830:          {
                    831:                struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
                    832:                int period = sc->sc_imsg[3];
                    833:                int offset = sc->sc_imsg[4];
                    834:                int r = 250 / period;
                    835:                int s = (100*250) / period - 100 * r;
                    836:
                    837:                if (period < sc->sc_minsync) {
                    838:                        ti->period = sc->sc_minsync;
                    839:                        ti->offset = 15;
                    840:                        mesh_msgout(sc, SEND_SDTR);
                    841:                        return;
                    842:                }
                    843:                sc_print_addr(scb->xs->sc_link);
                    844:                /* XXX if (offset != 0) ... */
                    845:                printf("max sync rate %d.%02dMb/s\n", r, s);
                    846:                ti->period = period;
                    847:                ti->offset = offset;
                    848:                ti->flags |= T_SYNCNEGO;
                    849:                ti->flags |= T_SYNCMODE;
                    850:                mesh_setsync(sc, ti);
                    851:                goto done;
                    852:          }
                    853:        default:
                    854:                printf("%s target %d: rejecting extended message 0x%x\n",
                    855:                    sc->sc_dev.dv_xname, scb->target, sc->sc_imsg[0]);
                    856:                goto reject;
                    857:        }
                    858:
                    859: done:
                    860:        sc->sc_imsglen = 0;
                    861:        sc->sc_nextstate = MESH_UNKNOWN;
                    862:
                    863:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); /* XXX really? */
                    864: }
                    865:
                    866: void
                    867: mesh_msgout(struct mesh_softc *sc, int msg)
                    868: {
                    869:        struct mesh_scb *scb = sc->sc_nexus;
                    870:        struct mesh_tinfo *ti;
                    871:        int lun, len, i;
                    872:
                    873:        DPRINTF("mesh_msgout: sending");
                    874:
                    875:        sc->sc_msgout = msg;
                    876:        len = 0;
                    877:
                    878:        if (msg & SEND_REJECT) {
                    879:                DPRINTF(" REJECT");
                    880:                sc->sc_omsg[len++] = MSG_MESSAGE_REJECT;
                    881:        }
                    882:        if (msg & SEND_IDENTIFY) {
                    883:                DPRINTF(" IDENTIFY");
                    884:                lun = scb->xs->sc_link->lun;
                    885:                sc->sc_omsg[len++] = MSG_IDENTIFY(lun, 0);
                    886:        }
                    887:        if (msg & SEND_SDTR) {
                    888:                DPRINTF(" SDTR");
                    889:                ti = &sc->sc_tinfo[scb->target];
                    890:                sc->sc_omsg[len++] = MSG_EXTENDED;
                    891:                sc->sc_omsg[len++] = 3;
                    892:                sc->sc_omsg[len++] = MSG_EXT_SDTR;
                    893:                sc->sc_omsg[len++] = ti->period;
                    894:                sc->sc_omsg[len++] = ti->offset;
                    895:        }
                    896:        DPRINTF("\n");
                    897:
                    898:        MESH_SET_XFER(sc, len);
                    899:        if (len == 1) {
                    900:                mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT);
                    901:                mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[0]);
                    902:        } else {
                    903:                mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT | MESH_SEQ_ATN);
                    904:
                    905:                for (i = 0; i < len - 1; i++)
                    906:                        mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
                    907:
                    908:                /* Wait for the FIFO empty... */
                    909:                while (mesh_read_reg(sc, MESH_FIFO_COUNT) > 0);
                    910:
                    911:                /* ...then write the last byte. */
                    912:                mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
                    913:        }
                    914:        sc->sc_nextstate = MESH_UNKNOWN;
                    915: }
                    916:
                    917: void
                    918: mesh_bus_reset(struct mesh_softc *sc)
                    919: {
                    920:        DPRINTF("mesh_bus_reset\n");
                    921:
                    922:        /* Disable interrupts. */
                    923:        mesh_set_reg(sc, MESH_INTR_MASK, 0);
                    924:
                    925:        /* Assert RST line. */
                    926:        mesh_set_reg(sc, MESH_BUS_STATUS1, MESH_STATUS1_RST);
                    927:        delay(50);
                    928:        mesh_set_reg(sc, MESH_BUS_STATUS1, 0);
                    929:
                    930:        mesh_reset(sc);
                    931: }
                    932:
                    933: void
                    934: mesh_reset(struct mesh_softc *sc)
                    935: {
                    936:        int i;
                    937:
                    938:        DPRINTF("mesh_reset\n");
                    939:
                    940:        /* Reset DMA first. */
                    941:        dbdma_reset(sc->sc_dmareg);
                    942:
                    943:        /* Disable interrupts. */
                    944:        mesh_set_reg(sc, MESH_INTR_MASK, 0);
                    945:
                    946:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_RESET_MESH);
                    947:        delay(1);
                    948:
                    949:        /* Wait for reset done. */
                    950:        while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
                    951:
                    952:        /* Clear interrupts */
                    953:        mesh_set_reg(sc, MESH_INTERRUPT, 0x7);
                    954:
                    955:        /* Set SCSI ID */
                    956:        mesh_set_reg(sc, MESH_SOURCE_ID, sc->sc_id);
                    957:
                    958:        /* Set to async mode by default. */
                    959:        mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
                    960:
                    961:        /* Set selection timeout to 250ms. */
                    962:        mesh_set_reg(sc, MESH_SEL_TIMEOUT, 250 * sc->sc_freq / 500);
                    963:
                    964:        /* Enable parity check. */
                    965:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ENABLE_PARITY);
                    966:
                    967:        /* Enable all interrupts. */
                    968:        mesh_set_reg(sc, MESH_INTR_MASK, 0x7);
                    969:
                    970:        for (i = 0; i < 7; i++) {
                    971:                struct mesh_tinfo *ti = &sc->sc_tinfo[i];
                    972:
                    973:                ti->flags = 0;
                    974:                ti->period = ti->offset = 0;
                    975:                if (sc->sc_cfflags & (0x100 << i))
                    976:                        ti->flags |= T_SYNCNEGO;
                    977:        }
                    978:        sc->sc_nexus = NULL;
                    979: }
                    980:
                    981: int
                    982: mesh_stp(struct mesh_softc *sc, int v)
                    983: {
                    984:        /*
                    985:         * stp(v) = 5 * clock_period     (v == 0)
                    986:         *      = (v + 2) * 2 clock_period (v > 0)
                    987:         */
                    988:
                    989:        if (v == 0)
                    990:                return 5 * 250 / sc->sc_freq;
                    991:        else
                    992:                return (v + 2) * 2 * 250 / sc->sc_freq;
                    993: }
                    994:
                    995: void
                    996: mesh_setsync(struct mesh_softc *sc, struct mesh_tinfo *ti)
                    997: {
                    998:        int period = ti->period;
                    999:        int offset = ti->offset;
                   1000:        int v;
                   1001:
                   1002:        if ((ti->flags & T_SYNCMODE) == 0)
                   1003:                offset = 0;
                   1004:
                   1005:        if (offset == 0) {      /* async mode */
                   1006:                mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
                   1007:                return;
                   1008:        }
                   1009:
                   1010:        v = period * sc->sc_freq / 250 / 2 - 2;
                   1011:        if (v < 0)
                   1012:                v = 0;
                   1013:        if (mesh_stp(sc, v) < period)
                   1014:                v++;
                   1015:        if (v > 15)
                   1016:                v = 15;
                   1017:        mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v);
                   1018: }
                   1019:
                   1020: struct mesh_scb *
                   1021: mesh_get_scb(struct mesh_softc *sc)
                   1022: {
                   1023:        struct mesh_scb *scb;
                   1024:
                   1025:        scb = TAILQ_FIRST(&sc->free_scb);
                   1026:        if (scb)
                   1027:                TAILQ_REMOVE(&sc->free_scb, scb, chain);
                   1028:
                   1029:        return scb;
                   1030: }
                   1031:
                   1032: void
                   1033: mesh_free_scb(struct mesh_softc *sc, struct mesh_scb *scb)
                   1034: {
                   1035:        TAILQ_INSERT_TAIL(&sc->free_scb, scb, chain);
                   1036: }
                   1037:
                   1038: int
                   1039: mesh_scsi_cmd(struct scsi_xfer *xs)
                   1040: {
                   1041:        struct scsi_link *sc_link = xs->sc_link;;
                   1042:        struct mesh_softc *sc = sc_link->adapter_softc;
                   1043:        struct mesh_scb *scb;
                   1044:        u_int flags;
                   1045:        int s;
                   1046:
                   1047:        flags = xs->flags;
                   1048:        s = splbio();
                   1049:        scb = mesh_get_scb(sc);
                   1050:        splx(s);
                   1051:        if (scb == NULL)
                   1052:                return (TRY_AGAIN_LATER);
                   1053:        DPRINTF("cmdlen: %d\n", xs->cmdlen);
                   1054:        scb->xs = xs;
                   1055:        scb->flags = 0;
                   1056:        scb->status = 0;
                   1057:        scb->daddr = xs->data;
                   1058:        scb->dlen = xs->datalen;
                   1059:        scb->resid = xs->datalen;
                   1060:        bcopy(xs->cmd, &scb->cmd, xs->cmdlen);
                   1061:        scb->cmdlen = xs->cmdlen;
                   1062:        scb->target = sc_link->target;
                   1063:        sc->sc_imsglen = 0;     /* XXX ? */
                   1064:
                   1065:        if (flags & SCSI_POLL)
                   1066:                scb->flags |= MESH_POLL;
                   1067:
                   1068:        if (flags & SCSI_DATA_IN)
                   1069:                scb->flags |= MESH_READ;
                   1070:
                   1071:        s = splbio();
                   1072:        TAILQ_INSERT_TAIL(&sc->ready_scb, scb, chain);
                   1073:        if (sc->sc_nexus == NULL)
                   1074:                mesh_sched(sc);
                   1075:        splx(s);
                   1076:
                   1077:        if (xs->flags & SCSI_POLL) {
                   1078:                if (mesh_poll(xs)) {
                   1079:                        printf("%s: poll timeout\n",
                   1080:                            sc->sc_dev.dv_xname);
                   1081:
                   1082:                }
                   1083:                return COMPLETE;
                   1084:        }
                   1085:
                   1086:        return SUCCESSFULLY_QUEUED;
                   1087: }
                   1088:
                   1089: void
                   1090: mesh_sched(struct mesh_softc *sc)
                   1091: {
                   1092:        struct mesh_scb *scb;
                   1093:
                   1094:        TAILQ_FOREACH(scb, &sc->ready_scb, chain) {
                   1095:                if (sc->sc_nexus == NULL) {
                   1096:                        TAILQ_REMOVE(&sc->ready_scb, scb, chain);
                   1097:                        sc->sc_nexus = scb;
                   1098:                        mesh_select(sc, scb);
                   1099:                        return;
                   1100:                }
                   1101:        }
                   1102: }
                   1103:
                   1104: int
                   1105: mesh_poll(struct scsi_xfer *xs)
                   1106: {
                   1107:        struct scsi_link *link = xs->sc_link;
                   1108:        struct mesh_softc *sc = link->adapter_softc;
                   1109:
                   1110:        int count = xs->timeout;
                   1111:        while (count) {
                   1112:                if (mesh_read_reg(sc, MESH_INTERRUPT))
                   1113:                        mesh_intr(sc);
                   1114:
                   1115:                if (xs->flags & ITSDONE)
                   1116:                        return 0;
                   1117:                DELAY(1000);
                   1118:                count--;
                   1119:        }
                   1120:
                   1121:        return 1;
                   1122: }
                   1123:
                   1124: void
                   1125: mesh_done(struct mesh_softc *sc, struct mesh_scb *scb)
                   1126: {
                   1127:        struct scsi_xfer *xs = scb->xs;
                   1128:
                   1129:        DPRINTF("mesh_done\n");
                   1130:
                   1131:        sc->sc_nextstate = MESH_BUSFREE;
                   1132:        sc->sc_nexus = NULL;
                   1133:
                   1134:        timeout_del(&sc->sc_tmo);
                   1135:
                   1136:        if (scb->status == SCSI_BUSY) {
                   1137:                xs->error = XS_BUSY;
                   1138:                printf("Target busy\n");
                   1139:        }
                   1140:
                   1141:        if (scb->status == SCSI_CHECK)
                   1142:                xs->error = XS_BUSY;
                   1143:
                   1144:        xs->status = scb->status;
                   1145:        xs->resid = scb->resid;
                   1146:        xs->flags |= ITSDONE;
                   1147:
                   1148:        mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
                   1149:
                   1150:        if ((xs->flags & SCSI_POLL) == 0)
                   1151:                mesh_sched(sc);
                   1152:
                   1153:        scsi_done(xs);
                   1154:        mesh_free_scb(sc, scb);
                   1155: }
                   1156:
                   1157: void
                   1158: mesh_timeout(void *arg)
                   1159: {
                   1160:
                   1161:        struct mesh_softc *sc = arg;
                   1162:        struct mesh_scb *scb = sc->sc_nexus;
                   1163:        int s;
                   1164:        int status0, status1;
                   1165:        int intr, error, exception, imsk;
                   1166:
                   1167:        printf("%s: timeout state %d\n", sc->sc_dev.dv_xname, sc->sc_nextstate);
                   1168:
                   1169:        intr = mesh_read_reg(sc, MESH_INTERRUPT);
                   1170:        imsk = mesh_read_reg(sc, MESH_INTR_MASK);
                   1171:        exception = mesh_read_reg(sc, MESH_EXCEPTION);
                   1172:        error = mesh_read_reg(sc, MESH_ERROR);
                   1173:        status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
                   1174:        status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
                   1175:
                   1176:        s = splbio();
                   1177:        if (sc->sc_flags & MESH_DMA_ACTIVE) {
                   1178:                dbdma_reset(sc->sc_dmareg);
                   1179:        }
                   1180:        scb->xs->error = XS_TIMEOUT;
                   1181:
                   1182:        mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
                   1183:        sc->sc_nextstate = MESH_COMPLETE;
                   1184:
                   1185:        splx(s);
                   1186: }
                   1187:
                   1188: void
                   1189: mesh_minphys(struct buf *bp)
                   1190: {
                   1191:        if (bp->b_bcount > 64*1024)
                   1192:                bp->b_bcount = 64*1024;
                   1193:
                   1194:        minphys(bp);
                   1195: }

CVSweb