Annotation of sys/dev/ic/osiop.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: osiop.c,v 1.29 2007/06/20 18:02:39 miod Exp $ */
! 2: /* $NetBSD: osiop.c,v 1.9 2002/04/05 18:27:54 bouyer Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2001 Izumi Tsutsui. All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. The name of the author may not be used to endorse or promote products
! 16: * derived from this software without specific prior written permission.
! 17: *
! 18: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 19: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 20: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 21: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 22: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 23: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 24: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 25: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 26: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 27: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 28: */
! 29:
! 30: /*
! 31: * Copyright (c) 1994 Michael L. Hitch
! 32: * Copyright (c) 1990 The Regents of the University of California.
! 33: * All rights reserved.
! 34: *
! 35: * This code is derived from software contributed to Berkeley by
! 36: * Van Jacobson of Lawrence Berkeley Laboratory.
! 37: *
! 38: * Redistribution and use in source and binary forms, with or without
! 39: * modification, are permitted provided that the following conditions
! 40: * are met:
! 41: * 1. Redistributions of source code must retain the above copyright
! 42: * notice, this list of conditions and the following disclaimer.
! 43: * 2. Redistributions in binary form must reproduce the above copyright
! 44: * notice, this list of conditions and the following disclaimer in the
! 45: * documentation and/or other materials provided with the distribution.
! 46: * 3. Neither the name of the University nor the names of its contributors
! 47: * may be used to endorse or promote products derived from this software
! 48: * without specific prior written permission.
! 49: *
! 50: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
! 51: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 52: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 53: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
! 54: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 55: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 56: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 57: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 58: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 59: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 60: * SUCH DAMAGE.
! 61: *
! 62: * @(#)siop.c 7.5 (Berkeley) 5/4/91
! 63: */
! 64:
! 65: /*
! 66: * MI NCR53C710 scsi adaptor driver; based on arch/amiga/dev/siop.c:
! 67: * NetBSD: siop.c,v 1.43 1999/09/30 22:59:53 thorpej Exp
! 68: *
! 69: * bus_space/bus_dma'fied by Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
! 70: */
! 71:
! 72: #include <sys/cdefs.h>
! 73: /* __KERNEL_RCSID(0, "$NetBSD: osiop.c,v 1.9 2002/04/05 18:27:54 bouyer Exp $"); */
! 74:
! 75: #include <sys/param.h>
! 76: #include <sys/systm.h>
! 77: #include <sys/device.h>
! 78: #include <sys/malloc.h>
! 79: #include <sys/buf.h>
! 80: #include <sys/kernel.h>
! 81:
! 82: #include <scsi/scsi_all.h>
! 83: #include <scsi/scsiconf.h>
! 84: #include <scsi/scsi_message.h>
! 85:
! 86: #include <machine/cpu.h>
! 87: #include <machine/bus.h>
! 88:
! 89: #include <dev/ic/osiopreg.h>
! 90: #include <dev/ic/osiopvar.h>
! 91:
! 92: /* 53C710 script */
! 93: #include <dev/microcode/siop/osiop.out>
! 94:
! 95: void osiop_attach(struct osiop_softc *);
! 96: void osiop_minphys(struct buf *);
! 97: int osiop_scsicmd(struct scsi_xfer *xs);
! 98: void osiop_poll(struct osiop_softc *, struct osiop_acb *);
! 99: void osiop_sched(struct osiop_softc *);
! 100: void osiop_scsidone(struct osiop_acb *, int);
! 101: void osiop_abort(struct osiop_softc *, const char *);
! 102: void osiop_init(struct osiop_softc *);
! 103: void osiop_reset(struct osiop_softc *);
! 104: void osiop_resetbus(struct osiop_softc *);
! 105: void osiop_start(struct osiop_softc *);
! 106: int osiop_checkintr(struct osiop_softc *, u_int8_t, u_int8_t, u_int8_t, int *);
! 107: void osiop_select(struct osiop_softc *);
! 108: void osiop_update_xfer_mode(struct osiop_softc *, int);
! 109: void scsi_period_to_osiop(struct osiop_softc *, int);
! 110: void osiop_timeout(void *);
! 111:
! 112: int osiop_reset_delay = 250; /* delay after reset, in milliseconds */
! 113:
! 114: /* #define OSIOP_DEBUG */
! 115: #ifdef OSIOP_DEBUG
! 116: #define DEBUG_DMA 0x0001
! 117: #define DEBUG_INT 0x0002
! 118: #define DEBUG_PHASE 0x0004
! 119: #define DEBUG_DISC 0x0008
! 120: #define DEBUG_CMD 0x0010
! 121: #define DEBUG_SYNC 0x0020
! 122: #define DEBUG_SCHED 0x0040
! 123: #define DEBUG_ALL 0xffff
! 124: int osiop_debug = 0; /*DEBUG_ALL;*/
! 125: int osiopstarts = 0;
! 126: int osiopints = 0;
! 127: int osiopphmm = 0;
! 128: int osiop_trix = 0;
! 129: #define OSIOP_TRACE_SIZE 128
! 130: #define OSIOP_TRACE(a,b,c,d) do { \
! 131: osiop_trbuf[osiop_trix + 0] = (a); \
! 132: osiop_trbuf[osiop_trix + 1] = (b); \
! 133: osiop_trbuf[osiop_trix + 2] = (c); \
! 134: osiop_trbuf[osiop_trix + 3] = (d); \
! 135: osiop_trix = (osiop_trix + 4) & (OSIOP_TRACE_SIZE - 1); \
! 136: } while (0)
! 137: u_int8_t osiop_trbuf[OSIOP_TRACE_SIZE];
! 138: void osiop_dump_trace(void);
! 139: void osiop_dump_acb(struct osiop_acb *);
! 140: void osiop_dump(struct osiop_softc *);
! 141: #else
! 142: #define OSIOP_TRACE(a,b,c,d)
! 143: #endif
! 144:
! 145: #ifdef OSIOP_DEBUG
! 146: /*
! 147: * sync period transfer lookup - only valid for 66MHz clock
! 148: */
! 149: static struct {
! 150: u_int8_t p; /* period from sync request message */
! 151: u_int8_t r; /* siop_period << 4 | sbcl */
! 152: } sync_tab[] = {
! 153: { 60/4, 0<<4 | 1},
! 154: { 76/4, 1<<4 | 1},
! 155: { 92/4, 2<<4 | 1},
! 156: { 92/4, 0<<4 | 2},
! 157: {108/4, 3<<4 | 1},
! 158: {116/4, 1<<4 | 2},
! 159: {120/4, 4<<4 | 1},
! 160: {120/4, 0<<4 | 3},
! 161: {136/4, 5<<4 | 1},
! 162: {140/4, 2<<4 | 2},
! 163: {152/4, 6<<4 | 1},
! 164: {152/4, 1<<4 | 3},
! 165: {164/4, 3<<4 | 2},
! 166: {168/4, 7<<4 | 1},
! 167: {180/4, 2<<4 | 3},
! 168: {184/4, 4<<4 | 2},
! 169: {208/4, 5<<4 | 2},
! 170: {212/4, 3<<4 | 3},
! 171: {232/4, 6<<4 | 2},
! 172: {240/4, 4<<4 | 3},
! 173: {256/4, 7<<4 | 2},
! 174: {272/4, 5<<4 | 3},
! 175: {300/4, 6<<4 | 3},
! 176: {332/4, 7<<4 | 3}
! 177: };
! 178: #endif
! 179:
! 180: struct cfdriver osiop_cd = {
! 181: NULL, "osiop", DV_DULL
! 182: };
! 183:
! 184: struct scsi_adapter osiop_adapter = {
! 185: osiop_scsicmd,
! 186: osiop_minphys,
! 187: NULL,
! 188: NULL,
! 189: };
! 190:
! 191: struct scsi_device osiop_dev = {
! 192: NULL,
! 193: NULL,
! 194: NULL,
! 195: NULL,
! 196: };
! 197:
! 198: void
! 199: osiop_attach(sc)
! 200: struct osiop_softc *sc;
! 201: {
! 202: struct scsibus_attach_args saa;
! 203: struct osiop_acb *acb;
! 204: bus_dma_segment_t seg;
! 205: int nseg;
! 206: int i, err;
! 207:
! 208: /*
! 209: * Allocate and map DMA-safe memory for the script.
! 210: */
! 211: err = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, PAGE_SIZE, 0,
! 212: &seg, 1, &nseg, BUS_DMA_NOWAIT);
! 213: if (err) {
! 214: printf(": failed to allocate script memory, err=%d\n", err);
! 215: return;
! 216: }
! 217: err = bus_dmamem_map(sc->sc_dmat, &seg, nseg, PAGE_SIZE,
! 218: (caddr_t *)&sc->sc_script, BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
! 219: if (err) {
! 220: printf(": failed to map script memory, err=%d\n", err);
! 221: return;
! 222: }
! 223: err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, 0,
! 224: BUS_DMA_NOWAIT, &sc->sc_scrdma);
! 225: if (err) {
! 226: printf(": failed to create script map, err=%d\n", err);
! 227: return;
! 228: }
! 229: err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_scrdma,
! 230: &seg, nseg, PAGE_SIZE, BUS_DMA_NOWAIT);
! 231: if (err) {
! 232: printf(": failed to load script map, err=%d\n", err);
! 233: return;
! 234: }
! 235: bzero(sc->sc_script, PAGE_SIZE);
! 236:
! 237: /*
! 238: * Copy and sync script
! 239: */
! 240: memcpy(sc->sc_script, osiop_script, sizeof(osiop_script));
! 241: bus_dmamap_sync(sc->sc_dmat, sc->sc_scrdma, 0, sizeof(osiop_script),
! 242: BUS_DMASYNC_PREWRITE);
! 243:
! 244: /*
! 245: * Allocate and map DMA-safe memory for the script data structure.
! 246: */
! 247: err = bus_dmamem_alloc(sc->sc_dmat,
! 248: sizeof(struct osiop_ds) * OSIOP_NACB, PAGE_SIZE, 0,
! 249: &seg, 1, &nseg, BUS_DMA_NOWAIT);
! 250: if (err) {
! 251: printf(": failed to allocate ds memory, err=%d\n", err);
! 252: return;
! 253: }
! 254: err = bus_dmamem_map(sc->sc_dmat, &seg, nseg,
! 255: sizeof(struct osiop_ds) * OSIOP_NACB, (caddr_t *)&sc->sc_ds,
! 256: BUS_DMA_NOWAIT | BUS_DMA_COHERENT);
! 257: if (err) {
! 258: printf(": failed to map ds memory, err=%d\n", err);
! 259: return;
! 260: }
! 261: err = bus_dmamap_create(sc->sc_dmat,
! 262: sizeof(struct osiop_ds) * OSIOP_NACB, 1,
! 263: sizeof(struct osiop_ds) * OSIOP_NACB, 0,
! 264: BUS_DMA_NOWAIT, &sc->sc_dsdma);
! 265: if (err) {
! 266: printf(": failed to create ds map, err=%d\n", err);
! 267: return;
! 268: }
! 269: err = bus_dmamap_load_raw(sc->sc_dmat, sc->sc_dsdma,
! 270: &seg, nseg, sizeof(struct osiop_ds) * OSIOP_NACB, BUS_DMA_NOWAIT);
! 271: if (err) {
! 272: printf(": failed to load ds map, err=%d\n", err);
! 273: return;
! 274: }
! 275: bzero(sc->sc_ds, sizeof(struct osiop_ds) * OSIOP_NACB);
! 276:
! 277: /*
! 278: * Allocate (malloc) memory for acb's.
! 279: */
! 280: acb = malloc(sizeof(struct osiop_acb) * OSIOP_NACB,
! 281: M_DEVBUF, M_NOWAIT);
! 282: if (acb == NULL) {
! 283: printf(": can't allocate memory for acb\n");
! 284: return;
! 285: }
! 286: bzero(acb, sizeof(struct osiop_acb) * OSIOP_NACB);
! 287: sc->sc_acb = acb;
! 288:
! 289: sc->sc_cfflags = sc->sc_dev.dv_cfdata->cf_flags;
! 290: sc->sc_nexus = NULL;
! 291: sc->sc_active = 0;
! 292:
! 293: bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
! 294:
! 295: /* Initialize command block queue */
! 296: TAILQ_INIT(&sc->ready_list);
! 297: TAILQ_INIT(&sc->nexus_list);
! 298: TAILQ_INIT(&sc->free_list);
! 299:
! 300: /* Initialize each command block */
! 301: for (i = 0; i < OSIOP_NACB; i++, acb++) {
! 302: bus_addr_t dsa;
! 303:
! 304: err = bus_dmamap_create(sc->sc_dmat, OSIOP_MAX_XFER, OSIOP_NSG,
! 305: OSIOP_MAX_XFER, 0, BUS_DMA_NOWAIT, &acb->datadma);
! 306: if (err) {
! 307: printf(": failed to create datadma map, err=%d\n",
! 308: err);
! 309: return;
! 310: }
! 311:
! 312: acb->sc = sc;
! 313: acb->ds = &sc->sc_ds[i];
! 314: acb->dsoffset = sizeof(struct osiop_ds) * i;
! 315:
! 316: dsa = sc->sc_dsdma->dm_segs[0].ds_addr + acb->dsoffset;
! 317: acb->ds->id.addr = dsa + OSIOP_DSIDOFF;
! 318: acb->ds->cmd.addr = dsa + OSIOP_DSCMDOFF;
! 319: acb->ds->status.count = 1;
! 320: acb->ds->status.addr = dsa + OSIOP_DSSTATOFF;
! 321: acb->ds->msg.count = 1;
! 322: acb->ds->msg.addr = dsa + OSIOP_DSMSGOFF;
! 323: acb->ds->msgin.count = 1;
! 324: acb->ds->msgin.addr = dsa + OSIOP_DSMSGINOFF;
! 325: acb->ds->extmsg.count = 1;
! 326: acb->ds->extmsg.addr = dsa + OSIOP_DSEXTMSGOFF;
! 327: acb->ds->synmsg.count = 3;
! 328: acb->ds->synmsg.addr = dsa + OSIOP_DSSYNMSGOFF;
! 329: TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
! 330: }
! 331:
! 332: printf(": NCR53C710 rev %d, %dMHz, SCSI ID %d\n",
! 333: osiop_read_1(sc, OSIOP_CTEST8) >> 4, sc->sc_clock_freq, sc->sc_id);
! 334:
! 335: /*
! 336: * Initialize all
! 337: */
! 338: osiop_init(sc);
! 339:
! 340: /*
! 341: * Fill in the sc_link.
! 342: */
! 343: sc->sc_link.adapter = &osiop_adapter;
! 344: sc->sc_link.adapter_softc = sc;
! 345: sc->sc_link.device = &osiop_dev;
! 346: sc->sc_link.openings = 4;
! 347: sc->sc_link.adapter_buswidth = OSIOP_NTGT;
! 348: sc->sc_link.adapter_target = sc->sc_id;
! 349:
! 350: bzero(&saa, sizeof(saa));
! 351: saa.saa_sc_link = &sc->sc_link;
! 352:
! 353: /*
! 354: * Now try to attach all the sub devices.
! 355: */
! 356: config_found(&sc->sc_dev, &saa, scsiprint);
! 357: }
! 358:
! 359: /*
! 360: * default minphys routine for osiop based controllers
! 361: */
! 362: void
! 363: osiop_minphys(bp)
! 364: struct buf *bp;
! 365: {
! 366:
! 367: if (bp->b_bcount > OSIOP_MAX_XFER)
! 368: bp->b_bcount = OSIOP_MAX_XFER;
! 369: minphys(bp);
! 370: }
! 371:
! 372: /*
! 373: * used by specific osiop controller
! 374: *
! 375: */
! 376: int
! 377: osiop_scsicmd(xs)
! 378: struct scsi_xfer *xs;
! 379: {
! 380: struct scsi_link *periph = xs->sc_link;
! 381: struct osiop_acb *acb;
! 382: struct osiop_softc *sc = periph->adapter_softc;
! 383: int err, s;
! 384:
! 385: /* XXXX ?? */
! 386: if (xs->flags & SCSI_DATA_UIO)
! 387: panic("osiop: scsi data uio requested");
! 388:
! 389: /* XXXX ?? */
! 390: if (sc->sc_nexus && (xs->flags & SCSI_POLL))
! 391: #if 0
! 392: panic("osiop_scsicmd: busy");
! 393: #else
! 394: printf("osiop_scsicmd: busy\n");
! 395: #endif
! 396:
! 397: s = splbio();
! 398: acb = TAILQ_FIRST(&sc->free_list);
! 399: if (acb != NULL) {
! 400: TAILQ_REMOVE(&sc->free_list, acb, chain);
! 401: }
! 402: else {
! 403: #ifdef DIAGNOSTIC
! 404: sc_print_addr(periph);
! 405: printf("unable to allocate acb\n");
! 406: panic("osiop_scsipi_request");
! 407: #endif
! 408: splx(s);
! 409: return (TRY_AGAIN_LATER);
! 410: }
! 411:
! 412: acb->flags = 0;
! 413: acb->status = ACB_S_READY;
! 414: acb->xs = xs;
! 415: acb->xsflags = xs->flags;
! 416: bcopy(xs->cmd, &acb->ds->scsi_cmd, xs->cmdlen);
! 417: acb->ds->cmd.count = xs->cmdlen;
! 418: acb->datalen = 0;
! 419: #ifdef OSIOP_DEBUG
! 420: acb->data = xs->data;
! 421: #endif
! 422:
! 423: /* Setup DMA map for data buffer */
! 424: if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
! 425: acb->datalen = xs->datalen;
! 426: err = bus_dmamap_load(sc->sc_dmat, acb->datadma,
! 427: xs->data, acb->datalen, NULL,
! 428: BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
! 429: ((acb->xsflags & SCSI_DATA_IN) ?
! 430: BUS_DMA_READ : BUS_DMA_WRITE));
! 431: if (err) {
! 432: printf("%s: unable to load data DMA map: %d",
! 433: sc->sc_dev.dv_xname, err);
! 434: xs->error = XS_DRIVER_STUFFUP;
! 435: scsi_done(xs);
! 436: TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
! 437: splx(s);
! 438: return (COMPLETE);
! 439: }
! 440: bus_dmamap_sync(sc->sc_dmat, acb->datadma,
! 441: 0, acb->datalen, (acb->xsflags & SCSI_DATA_IN) ?
! 442: BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
! 443: }
! 444:
! 445: /*
! 446: * Always initialize timeout so it does not contain trash
! 447: * that could confuse timeout_del().
! 448: */
! 449: timeout_set(&xs->stimeout, osiop_timeout, acb);
! 450:
! 451: TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
! 452:
! 453: osiop_sched(sc);
! 454:
! 455: splx(s);
! 456:
! 457: if ((acb->xsflags & SCSI_POLL) || (sc->sc_flags & OSIOP_NODMA))
! 458: osiop_poll(sc, acb);
! 459: else
! 460: /* start expire timer */
! 461: timeout_add(&xs->stimeout, (xs->timeout/1000) * hz);
! 462:
! 463: if ((xs->flags & ITSDONE) == 0)
! 464: return (SUCCESSFULLY_QUEUED);
! 465: else
! 466: return (COMPLETE);
! 467: }
! 468:
! 469: void
! 470: osiop_poll(sc, acb)
! 471: struct osiop_softc *sc;
! 472: struct osiop_acb *acb;
! 473: {
! 474: struct scsi_xfer *xs = acb->xs;
! 475: int status, i, s, to;
! 476: u_int8_t istat, dstat, sstat0;
! 477:
! 478: s = splbio();
! 479: to = xs->timeout / 1000;
! 480: if (!TAILQ_EMPTY(&sc->nexus_list))
! 481: printf("%s: osiop_poll called with disconnected device\n",
! 482: sc->sc_dev.dv_xname);
! 483: for (;;) {
! 484: i = 1000;
! 485: while (((istat = osiop_read_1(sc, OSIOP_ISTAT)) &
! 486: (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0) {
! 487: if (i <= 0) {
! 488: #ifdef OSIOP_DEBUG
! 489: printf("waiting: tgt %d cmd %02x sbcl %02x"
! 490: " dsp %x (+%lx) dcmd %x"
! 491: " ds %p timeout %d\n",
! 492: xs->sc_link->target,
! 493: acb->ds->scsi_cmd.opcode,
! 494: osiop_read_1(sc, OSIOP_SBCL),
! 495: osiop_read_4(sc, OSIOP_DSP),
! 496: osiop_read_4(sc, OSIOP_DSP) -
! 497: sc->sc_scrdma->dm_segs[0].ds_addr,
! 498: osiop_read_1(sc, OSIOP_DCMD),
! 499: acb->ds, acb->xs->timeout);
! 500: #endif
! 501: i = 1000;
! 502: to--;
! 503: if (to <= 0) {
! 504: osiop_reset(sc);
! 505: splx(s);
! 506: return;
! 507: }
! 508: }
! 509: delay(1000);
! 510: i--;
! 511: }
! 512: sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
! 513: delay(25); /* Need delay between SSTAT0 and DSTAT reads */
! 514: dstat = osiop_read_1(sc, OSIOP_DSTAT);
! 515: if (osiop_checkintr(sc, istat, dstat, sstat0, &status)) {
! 516: if (acb != sc->sc_nexus)
! 517: printf("%s: osiop_poll disconnected device"
! 518: " completed\n", sc->sc_dev.dv_xname);
! 519: else if ((sc->sc_flags & OSIOP_INTDEFER) == 0) {
! 520: sc->sc_flags &= ~OSIOP_INTSOFF;
! 521: osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
! 522: osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
! 523: }
! 524: osiop_scsidone(sc->sc_nexus, status);
! 525: }
! 526:
! 527: if (xs->flags & ITSDONE)
! 528: break;
! 529: }
! 530:
! 531: splx(s);
! 532: return;
! 533: }
! 534:
! 535: /*
! 536: * start next command that's ready
! 537: */
! 538: void
! 539: osiop_sched(sc)
! 540: struct osiop_softc *sc;
! 541: {
! 542: struct osiop_tinfo *ti;
! 543: struct scsi_link *periph;
! 544: struct osiop_acb *acb;
! 545:
! 546: if ((sc->sc_nexus != NULL) || TAILQ_EMPTY(&sc->ready_list)) {
! 547: #ifdef OSIOP_DEBUG
! 548: if (osiop_debug & DEBUG_SCHED)
! 549: printf("%s: osiop_sched->nexus %p/%d ready %p/%d\n",
! 550: sc->sc_dev.dv_xname, sc->sc_nexus,
! 551: sc->sc_nexus != NULL ?
! 552: sc->sc_nexus->xs->sc_link->target : 0,
! 553: TAILQ_FIRST(&sc->ready_list),
! 554: TAILQ_FIRST(&sc->ready_list) != NULL ?
! 555: TAILQ_FIRST(&sc->ready_list)->xs->sc_link->target :
! 556: 0);
! 557: #endif
! 558: return;
! 559: }
! 560: TAILQ_FOREACH(acb, &sc->ready_list, chain) {
! 561: periph = acb->xs->sc_link;
! 562: ti = &sc->sc_tinfo[periph->target];
! 563: if ((ti->lubusy & (1 << periph->lun)) == 0) {
! 564: TAILQ_REMOVE(&sc->ready_list, acb, chain);
! 565: sc->sc_nexus = acb;
! 566: ti->lubusy |= (1 << periph->lun);
! 567: break;
! 568: }
! 569: }
! 570:
! 571: if (acb == NULL) {
! 572: #ifdef OSIOP_DEBUG
! 573: if (osiop_debug & DEBUG_SCHED)
! 574: printf("%s: osiop_sched didn't find ready command\n",
! 575: sc->sc_dev.dv_xname);
! 576: #endif
! 577: return;
! 578: }
! 579:
! 580: if (acb->xsflags & SCSI_RESET)
! 581: osiop_reset(sc);
! 582:
! 583: sc->sc_active++;
! 584: osiop_select(sc);
! 585: }
! 586:
! 587: void
! 588: osiop_scsidone(acb, status)
! 589: struct osiop_acb *acb;
! 590: int status;
! 591: {
! 592: struct scsi_xfer *xs;
! 593: struct scsi_link *periph;
! 594: struct osiop_softc *sc;
! 595: int autosense;
! 596:
! 597: #ifdef DIAGNOSTIC
! 598: if (acb == NULL || acb->xs == NULL) {
! 599: printf("osiop_scsidone: NULL acb or scsi_xfer\n");
! 600: #if defined(OSIOP_DEBUG) && defined(DDB)
! 601: Debugger();
! 602: #endif
! 603: return;
! 604: }
! 605: #endif
! 606: xs = acb->xs;
! 607: sc = acb->sc;
! 608: periph = xs->sc_link;
! 609:
! 610: /*
! 611: * Record if this is the completion of an auto sense
! 612: * scsi command, and then reset the flag so we don't loop
! 613: * when such a command fails or times out.
! 614: */
! 615: autosense = acb->flags & ACB_F_AUTOSENSE;
! 616: acb->flags &= ~ACB_F_AUTOSENSE;
! 617:
! 618: #ifdef OSIOP_DEBUG
! 619: if (acb->status != ACB_S_DONE)
! 620: printf("%s: acb not done (status %d)\n",
! 621: sc->sc_dev.dv_xname, acb->status);
! 622: #endif
! 623:
! 624: if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
! 625: bus_dmamap_sync(sc->sc_dmat, acb->datadma, 0, acb->datalen,
! 626: (acb->xsflags & SCSI_DATA_IN) ?
! 627: BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
! 628: bus_dmamap_unload(sc->sc_dmat, acb->datadma);
! 629: }
! 630:
! 631: timeout_del(&xs->stimeout);
! 632: xs->status = status;
! 633:
! 634: switch (status) {
! 635: case SCSI_OK:
! 636: if (autosense == 0)
! 637: xs->error = XS_NOERROR;
! 638: else
! 639: xs->error = XS_SENSE;
! 640: break;
! 641: case SCSI_BUSY:
! 642: xs->error = XS_BUSY;
! 643: break;
! 644: case SCSI_CHECK:
! 645: if (autosense == 0)
! 646: acb->flags |= ACB_F_AUTOSENSE;
! 647: else
! 648: xs->error = XS_DRIVER_STUFFUP;
! 649: break;
! 650: case SCSI_OSIOP_NOCHECK:
! 651: /*
! 652: * don't check status, xs->error is already valid
! 653: */
! 654: break;
! 655: case SCSI_OSIOP_NOSTATUS:
! 656: /*
! 657: * the status byte was not updated, cmd was
! 658: * aborted
! 659: */
! 660: xs->error = XS_SELTIMEOUT;
! 661: break;
! 662: default:
! 663: #ifdef OSIOP_DEBUG
! 664: printf("%s: osiop_scsidone: unknown status code (0x%02x)\n",
! 665: sc->sc_dev.dv_xname, status);
! 666: #endif
! 667: xs->error = XS_DRIVER_STUFFUP;
! 668: break;
! 669: }
! 670:
! 671: /*
! 672: * Remove the ACB from whatever queue it's on. We have to do a bit of
! 673: * a hack to figure out which queue it's on. Note that it is *not*
! 674: * necessary to cdr down the ready queue, but we must cdr down the
! 675: * nexus queue and see if it's there, so we can mark the unit as no
! 676: * longer busy. This code is sickening, but it works.
! 677: */
! 678: if (acb == sc->sc_nexus) {
! 679: sc->sc_nexus = NULL;
! 680: sc->sc_tinfo[periph->target].lubusy &=
! 681: ~(1 << periph->lun);
! 682: sc->sc_active--;
! 683: OSIOP_TRACE('d', 'a', status, 0);
! 684: } else if (sc->ready_list.tqh_last == &TAILQ_NEXT(acb, chain)) {
! 685: TAILQ_REMOVE(&sc->ready_list, acb, chain);
! 686: OSIOP_TRACE('d', 'r', status, 0);
! 687: } else {
! 688: struct osiop_acb *acb2;
! 689: TAILQ_FOREACH(acb2, &sc->nexus_list, chain) {
! 690: if (acb2 == acb) {
! 691: TAILQ_REMOVE(&sc->nexus_list, acb, chain);
! 692: sc->sc_tinfo[periph->target].lubusy &=
! 693: ~(1 << periph->lun);
! 694: sc->sc_active--;
! 695: break;
! 696: }
! 697: }
! 698: if (acb2 == NULL) {
! 699: if (TAILQ_NEXT(acb, chain) != NULL) {
! 700: TAILQ_REMOVE(&sc->ready_list, acb, chain);
! 701: sc->sc_active--;
! 702: } else {
! 703: printf("%s: can't find matching acb\n",
! 704: sc->sc_dev.dv_xname);
! 705: #ifdef DDB
! 706: #if 0
! 707: Debugger();
! 708: #endif
! 709: #endif
! 710: }
! 711: }
! 712: OSIOP_TRACE('d', 'n', status, 0);
! 713: }
! 714:
! 715: if ((acb->flags & ACB_F_AUTOSENSE) == 0) {
! 716: /* Put it on the free list. */
! 717: FREE:
! 718: acb->status = ACB_S_FREE;
! 719: TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
! 720: sc->sc_tinfo[periph->target].cmds++;
! 721:
! 722: xs->resid = 0;
! 723: xs->flags |= ITSDONE;
! 724: scsi_done(xs);
! 725: } else {
! 726: /* Set up REQUEST_SENSE command */
! 727: struct scsi_sense *cmd = (struct scsi_sense *)&acb->ds->scsi_cmd;
! 728: int err;
! 729:
! 730: bzero(cmd, sizeof(*cmd));
! 731: acb->ds->cmd.count = sizeof(*cmd);
! 732: cmd->opcode = REQUEST_SENSE;
! 733: cmd->byte2 = xs->sc_link->lun << 5;
! 734: cmd->length = sizeof(xs->sense);
! 735:
! 736: /* Setup DMA map for data buffer */
! 737: acb->xsflags &= SCSI_POLL | SCSI_NOSLEEP;
! 738: acb->xsflags |= SCSI_DATA_IN;
! 739: acb->datalen = sizeof xs->sense;
! 740: #ifdef OSIOP_DEBUG
! 741: acb->data = &xs->sense;
! 742: #endif
! 743: err = bus_dmamap_load(sc->sc_dmat, acb->datadma,
! 744: &xs->sense, sizeof(xs->sense), NULL,
! 745: BUS_DMA_NOWAIT | BUS_DMA_STREAMING | BUS_DMA_READ);
! 746: if (err) {
! 747: printf("%s: unable to load REQUEST_SENSE data DMA map: %d",
! 748: sc->sc_dev.dv_xname, err);
! 749: xs->error = XS_DRIVER_STUFFUP;
! 750: goto FREE;
! 751: }
! 752: bus_dmamap_sync(sc->sc_dmat, acb->datadma,
! 753: 0, sizeof(xs->sense), BUS_DMASYNC_PREREAD);
! 754:
! 755: sc->sc_tinfo[periph->target].senses++;
! 756: acb->status = ACB_S_READY;
! 757: TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
! 758: if (((acb->xsflags & SCSI_POLL) == 0) && ((sc->sc_flags & OSIOP_NODMA) == 0))
! 759: /* start expire timer */
! 760: timeout_add(&xs->stimeout, (xs->timeout/1000) * hz);
! 761: }
! 762:
! 763: osiop_sched(sc);
! 764: }
! 765:
! 766: void
! 767: osiop_abort(sc, where)
! 768: struct osiop_softc *sc;
! 769: const char *where;
! 770: {
! 771: u_int8_t dstat, sstat0;
! 772:
! 773: sstat0 = osiop_read_1(sc, OSIOP_SSTAT0);
! 774: delay(25); /* Need delay between SSTAT0 and DSTAT reads */
! 775: dstat = osiop_read_1(sc, OSIOP_DSTAT);
! 776:
! 777: printf("%s: abort %s: dstat %02x, sstat0 %02x sbcl %02x\n",
! 778: sc->sc_dev.dv_xname, where,
! 779: dstat, sstat0,
! 780: osiop_read_1(sc, OSIOP_SBCL));
! 781:
! 782: /* XXX XXX XXX */
! 783: if (sc->sc_active > 0) {
! 784: sc->sc_active = 0;
! 785: }
! 786: }
! 787:
! 788: void
! 789: osiop_init(sc)
! 790: struct osiop_softc *sc;
! 791: {
! 792: int i, inhibit_sync, inhibit_disc;
! 793:
! 794: sc->sc_tcp[1] = 1000 / sc->sc_clock_freq;
! 795: sc->sc_tcp[2] = 1500 / sc->sc_clock_freq;
! 796: sc->sc_tcp[3] = 2000 / sc->sc_clock_freq;
! 797: sc->sc_minsync = sc->sc_tcp[1]; /* in 4ns units */
! 798:
! 799: if (sc->sc_minsync < 25)
! 800: sc->sc_minsync = 25;
! 801:
! 802: if (sc->sc_clock_freq <= 25) {
! 803: sc->sc_dcntl |= OSIOP_DCNTL_CF_1; /* SCLK/1 */
! 804: sc->sc_tcp[0] = sc->sc_tcp[1];
! 805: } else if (sc->sc_clock_freq <= 37) {
! 806: sc->sc_dcntl |= OSIOP_DCNTL_CF_1_5; /* SCLK/1.5 */
! 807: sc->sc_tcp[0] = sc->sc_tcp[2];
! 808: } else if (sc->sc_clock_freq <= 50) {
! 809: sc->sc_dcntl |= OSIOP_DCNTL_CF_2; /* SCLK/2 */
! 810: sc->sc_tcp[0] = sc->sc_tcp[3];
! 811: } else {
! 812: sc->sc_dcntl |= OSIOP_DCNTL_CF_3; /* SCLK/3 */
! 813: sc->sc_tcp[0] = 3000 / sc->sc_clock_freq;
! 814: }
! 815:
! 816: if ((sc->sc_cfflags & 0x10000) != 0) {
! 817: sc->sc_flags |= OSIOP_NODMA;
! 818: #ifdef OSIOP_DEBUG
! 819: printf("%s: DMA disabled; use polling\n",
! 820: sc->sc_dev.dv_xname);
! 821: #endif
! 822: }
! 823:
! 824: inhibit_sync = (sc->sc_cfflags & 0xff00) >> 8; /* XXX */
! 825: inhibit_disc = sc->sc_cfflags & 0x00ff; /* XXX */
! 826: #ifdef OSIOP_DEBUG
! 827: if (inhibit_sync != 0)
! 828: printf("%s: Inhibiting synchronous transfer: 0x%02x\n",
! 829: sc->sc_dev.dv_xname, inhibit_sync);
! 830: if (inhibit_disc != 0)
! 831: printf("%s: Inhibiting disconnect: 0x%02x\n",
! 832: sc->sc_dev.dv_xname, inhibit_disc);
! 833: #endif
! 834: for (i = 0; i < OSIOP_NTGT; i++) {
! 835: if (inhibit_sync & (1 << i))
! 836: sc->sc_tinfo[i].flags |= TI_NOSYNC;
! 837: if (inhibit_disc & (1 << i))
! 838: sc->sc_tinfo[i].flags |= TI_NODISC;
! 839: }
! 840:
! 841: osiop_resetbus(sc);
! 842: osiop_reset(sc);
! 843: }
! 844:
! 845: void
! 846: osiop_reset(sc)
! 847: struct osiop_softc *sc;
! 848: {
! 849: struct osiop_acb *acb;
! 850: int i, s;
! 851: u_int8_t stat;
! 852:
! 853: #ifdef OSIOP_DEBUG
! 854: printf("%s: resetting chip\n", sc->sc_dev.dv_xname);
! 855: #endif
! 856: if (sc->sc_flags & OSIOP_ALIVE)
! 857: osiop_abort(sc, "reset");
! 858:
! 859: s = splbio();
! 860:
! 861: /*
! 862: * Reset the chip
! 863: * XXX - is this really needed?
! 864: */
! 865:
! 866: /* abort current script */
! 867: osiop_write_1(sc, OSIOP_ISTAT,
! 868: osiop_read_1(sc, OSIOP_ISTAT) | OSIOP_ISTAT_ABRT);
! 869: /* reset chip */
! 870: osiop_write_1(sc, OSIOP_ISTAT,
! 871: osiop_read_1(sc, OSIOP_ISTAT) | OSIOP_ISTAT_RST);
! 872: delay(100);
! 873: osiop_write_1(sc, OSIOP_ISTAT,
! 874: osiop_read_1(sc, OSIOP_ISTAT) & ~OSIOP_ISTAT_RST);
! 875: delay(100);
! 876:
! 877: /*
! 878: * Set up various chip parameters
! 879: */
! 880: osiop_write_1(sc, OSIOP_SCNTL0,
! 881: OSIOP_ARB_FULL | OSIOP_SCNTL0_EPC | OSIOP_SCNTL0_EPG);
! 882: osiop_write_1(sc, OSIOP_SCNTL1, OSIOP_SCNTL1_ESR);
! 883: osiop_write_1(sc, OSIOP_DCNTL, sc->sc_dcntl);
! 884: osiop_write_1(sc, OSIOP_DMODE, sc->sc_dmode);
! 885: /* don't enable interrupts yet */
! 886: osiop_write_1(sc, OSIOP_SIEN, 0x00);
! 887: osiop_write_1(sc, OSIOP_DIEN, 0x00);
! 888: osiop_write_1(sc, OSIOP_SCID, OSIOP_SCID_VALUE(sc->sc_id));
! 889: osiop_write_1(sc, OSIOP_DWT, 0x00);
! 890: osiop_write_1(sc, OSIOP_CTEST0, osiop_read_1(sc, OSIOP_CTEST0)
! 891: | OSIOP_CTEST0_BTD | OSIOP_CTEST0_EAN);
! 892: osiop_write_1(sc, OSIOP_CTEST7,
! 893: osiop_read_1(sc, OSIOP_CTEST7) | sc->sc_ctest7);
! 894:
! 895: /* will need to re-negotiate sync xfers */
! 896: for (i = 0; i < OSIOP_NTGT; i++) {
! 897: sc->sc_tinfo[i].state = NEG_INIT;
! 898: sc->sc_tinfo[i].period = 0;
! 899: sc->sc_tinfo[i].offset = 0;
! 900: }
! 901:
! 902: stat = osiop_read_1(sc, OSIOP_ISTAT);
! 903: if (stat & OSIOP_ISTAT_SIP)
! 904: osiop_read_1(sc, OSIOP_SSTAT0);
! 905: if (stat & OSIOP_ISTAT_DIP) {
! 906: if (stat & OSIOP_ISTAT_SIP)
! 907: /* Need delay between SSTAT0 and DSTAT reads */
! 908: delay(25);
! 909: osiop_read_1(sc, OSIOP_DSTAT);
! 910: }
! 911:
! 912: splx(s);
! 913:
! 914: delay(osiop_reset_delay * 1000);
! 915:
! 916: s = splbio();
! 917: if (sc->sc_nexus != NULL) {
! 918: sc->sc_nexus->xs->error =
! 919: (sc->sc_nexus->flags & ACB_F_TIMEOUT) ?
! 920: XS_TIMEOUT : XS_RESET;
! 921: sc->sc_nexus->status = ACB_S_DONE;
! 922: osiop_scsidone(sc->sc_nexus, SCSI_OSIOP_NOCHECK);
! 923: }
! 924: while ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
! 925: acb->xs->error = (acb->flags & ACB_F_TIMEOUT) ?
! 926: XS_TIMEOUT : XS_RESET;
! 927: acb->status = ACB_S_DONE;
! 928: osiop_scsidone(acb, SCSI_OSIOP_NOCHECK);
! 929: }
! 930: splx(s);
! 931:
! 932: sc->sc_flags &= ~(OSIOP_INTDEFER | OSIOP_INTSOFF);
! 933: /* enable SCSI and DMA interrupts */
! 934: sc->sc_sien = OSIOP_SIEN_M_A | OSIOP_SIEN_STO | /*OSIOP_SIEN_SEL |*/
! 935: OSIOP_SIEN_SGE | OSIOP_SIEN_UDC | OSIOP_SIEN_RST | OSIOP_SIEN_PAR;
! 936: sc->sc_dien = OSIOP_DIEN_BF | OSIOP_DIEN_ABRT | OSIOP_DIEN_SIR |
! 937: /*OSIOP_DIEN_WTD |*/ OSIOP_DIEN_IID;
! 938: osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
! 939: osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
! 940: }
! 941:
! 942: void
! 943: osiop_resetbus(sc)
! 944: struct osiop_softc *sc;
! 945: {
! 946:
! 947: osiop_write_1(sc, OSIOP_SIEN, 0);
! 948: osiop_write_1(sc, OSIOP_SCNTL1,
! 949: osiop_read_1(sc, OSIOP_SCNTL1) | OSIOP_SCNTL1_RST);
! 950: delay(25);
! 951: osiop_write_1(sc, OSIOP_SCNTL1,
! 952: osiop_read_1(sc, OSIOP_SCNTL1) & ~OSIOP_SCNTL1_RST);
! 953: }
! 954:
! 955: /*
! 956: * Setup Data Storage for 53C710 and start SCRIPTS processing
! 957: */
! 958:
! 959: void
! 960: osiop_start(sc)
! 961: struct osiop_softc *sc;
! 962: {
! 963: struct osiop_acb *acb = sc->sc_nexus;
! 964: struct osiop_ds *ds = acb->ds;
! 965: struct scsi_xfer *xs = acb->xs;
! 966: bus_dmamap_t dsdma = sc->sc_dsdma, datadma = acb->datadma;
! 967: struct osiop_tinfo *ti;
! 968: int target = xs->sc_link->target;
! 969: int lun = xs->sc_link->lun;
! 970: int disconnect, i;
! 971:
! 972: #ifdef OSIOP_DEBUG
! 973: if (osiop_debug & DEBUG_DISC &&
! 974: osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
! 975: printf("ACK! osiop was busy: script %p dsa %p active %d\n",
! 976: sc->sc_script, acb->ds, sc->sc_active);
! 977: printf("istat %02x sfbr %02x lcrc %02x sien %02x dien %02x\n",
! 978: osiop_read_1(sc, OSIOP_ISTAT),
! 979: osiop_read_1(sc, OSIOP_SFBR),
! 980: osiop_read_1(sc, OSIOP_LCRC),
! 981: osiop_read_1(sc, OSIOP_SIEN),
! 982: osiop_read_1(sc, OSIOP_DIEN));
! 983: #ifdef DDB
! 984: #if 0
! 985: Debugger();
! 986: #endif
! 987: #endif
! 988: }
! 989: #endif
! 990:
! 991: #ifdef OSIOP_DEBUG
! 992: if (acb->status != ACB_S_READY)
! 993: panic("osiop_start: non-ready cmd in acb");
! 994: #endif
! 995:
! 996: acb->intstat = 0;
! 997:
! 998: ti = &sc->sc_tinfo[target];
! 999: ds->scsi_addr = ((1 << 16) << target) | (ti->sxfer << 8);
! 1000:
! 1001: disconnect = (ds->scsi_cmd.opcode != REQUEST_SENSE) &&
! 1002: (ti->flags & TI_NODISC) == 0;
! 1003:
! 1004: ds->msgout[0] = MSG_IDENTIFY(lun, disconnect);
! 1005: ds->id.count = 1;
! 1006: ds->stat[0] = SCSI_OSIOP_NOSTATUS; /* set invalid status */
! 1007: ds->msgbuf[0] = ds->msgbuf[1] = MSG_INVALID;
! 1008: bzero(&ds->data, sizeof(ds->data));
! 1009:
! 1010: /*
! 1011: * Negotiate wide is the initial negotiation state; since the 53c710
! 1012: * doesn't do wide transfers, just begin the synchronous transfer
! 1013: * negotiation here.
! 1014: */
! 1015: if (ti->state == NEG_INIT) {
! 1016: if ((ti->flags & TI_NOSYNC) != 0) {
! 1017: ti->state = NEG_DONE;
! 1018: ti->period = 0;
! 1019: ti->offset = 0;
! 1020: osiop_update_xfer_mode(sc, target);
! 1021: #ifdef OSIOP_DEBUG
! 1022: if (osiop_debug & DEBUG_SYNC)
! 1023: printf("Forcing target %d asynchronous\n",
! 1024: target);
! 1025: #endif
! 1026: } else {
! 1027: ds->msgbuf[2] = MSG_INVALID;
! 1028: ds->msgout[1] = MSG_EXTENDED;
! 1029: ds->msgout[2] = MSG_EXT_SDTR_LEN;
! 1030: ds->msgout[3] = MSG_EXT_SDTR;
! 1031: ds->msgout[4] = sc->sc_minsync;
! 1032: ds->msgout[5] = OSIOP_MAX_OFFSET;
! 1033: ds->id.count = MSG_EXT_SDTR_LEN + 3;
! 1034: ti->state = NEG_WAITS;
! 1035: #ifdef OSIOP_DEBUG
! 1036: if (osiop_debug & DEBUG_SYNC)
! 1037: printf("Sending sync request to target %d\n",
! 1038: target);
! 1039: #endif
! 1040: }
! 1041: }
! 1042:
! 1043: acb->curaddr = 0;
! 1044: acb->curlen = 0;
! 1045:
! 1046: /*
! 1047: * Build physical DMA addresses for scatter/gather I/O
! 1048: */
! 1049: if (acb->xsflags & (SCSI_DATA_IN | SCSI_DATA_OUT)) {
! 1050: for (i = 0; i < datadma->dm_nsegs; i++) {
! 1051: ds->data[i].count = datadma->dm_segs[i].ds_len;
! 1052: ds->data[i].addr = datadma->dm_segs[i].ds_addr;
! 1053: }
! 1054: }
! 1055:
! 1056: /* sync script data structure */
! 1057: bus_dmamap_sync(sc->sc_dmat, dsdma,
! 1058: acb->dsoffset, sizeof(struct osiop_ds),
! 1059: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1060:
! 1061: acb->status = ACB_S_ACTIVE;
! 1062:
! 1063: #ifdef OSIOP_DEBUG
! 1064: if (osiop_debug & DEBUG_DISC &&
! 1065: osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
! 1066: printf("ACK! osiop was busy at start: "
! 1067: "script %p dsa %p active %d\n",
! 1068: sc->sc_script, acb->ds, sc->sc_active);
! 1069: #ifdef DDB
! 1070: #if 0
! 1071: Debugger();
! 1072: #endif
! 1073: #endif
! 1074: }
! 1075: #endif
! 1076: if (TAILQ_EMPTY(&sc->nexus_list)) {
! 1077: if (osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON)
! 1078: printf("%s: osiop_select while connected?\n",
! 1079: sc->sc_dev.dv_xname);
! 1080: osiop_write_4(sc, OSIOP_TEMP, 0);
! 1081: osiop_write_1(sc, OSIOP_SBCL, ti->sbcl);
! 1082: osiop_write_4(sc, OSIOP_DSA,
! 1083: dsdma->dm_segs[0].ds_addr + acb->dsoffset);
! 1084: osiop_write_4(sc, OSIOP_DSP,
! 1085: sc->sc_scrdma->dm_segs[0].ds_addr + Ent_scripts);
! 1086: OSIOP_TRACE('s', 1, 0, 0);
! 1087: } else {
! 1088: if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
! 1089: osiop_write_1(sc, OSIOP_ISTAT, OSIOP_ISTAT_SIGP);
! 1090: OSIOP_TRACE('s', 2, 0, 0);
! 1091: } else {
! 1092: OSIOP_TRACE('s', 3,
! 1093: osiop_read_1(sc, OSIOP_ISTAT), 0);
! 1094: }
! 1095: }
! 1096: #ifdef OSIOP_DEBUG
! 1097: osiopstarts++;
! 1098: #endif
! 1099: }
! 1100:
! 1101: /*
! 1102: * Process a DMA or SCSI interrupt from the 53C710 SIOP
! 1103: */
! 1104:
! 1105: int
! 1106: osiop_checkintr(sc, istat, dstat, sstat0, status)
! 1107: struct osiop_softc *sc;
! 1108: u_int8_t istat;
! 1109: u_int8_t dstat;
! 1110: u_int8_t sstat0;
! 1111: int *status;
! 1112: {
! 1113: struct osiop_acb *acb = sc->sc_nexus;
! 1114: struct osiop_ds *ds;
! 1115: bus_dmamap_t dsdma = sc->sc_dsdma;
! 1116: bus_addr_t scraddr = sc->sc_scrdma->dm_segs[0].ds_addr;
! 1117: int target = 0;
! 1118: int dfifo, dbc, intcode, sstat1;
! 1119:
! 1120: dfifo = osiop_read_1(sc, OSIOP_DFIFO);
! 1121: dbc = osiop_read_4(sc, OSIOP_DBC) & 0x00ffffff;
! 1122: sstat1 = osiop_read_1(sc, OSIOP_SSTAT1);
! 1123: osiop_write_1(sc, OSIOP_CTEST8,
! 1124: osiop_read_1(sc, OSIOP_CTEST8) | OSIOP_CTEST8_CLF);
! 1125: while ((osiop_read_1(sc, OSIOP_CTEST1) & OSIOP_CTEST1_FMT) !=
! 1126: OSIOP_CTEST1_FMT)
! 1127: ;
! 1128: osiop_write_1(sc, OSIOP_CTEST8,
! 1129: osiop_read_1(sc, OSIOP_CTEST8) & ~OSIOP_CTEST8_CLF);
! 1130: intcode = osiop_read_4(sc, OSIOP_DSPS);
! 1131: #ifdef OSIOP_DEBUG
! 1132: osiopints++;
! 1133: if (osiop_read_4(sc, OSIOP_DSP) != 0 &&
! 1134: (osiop_read_4(sc, OSIOP_DSP) < scraddr ||
! 1135: osiop_read_4(sc, OSIOP_DSP) >= scraddr + sizeof(osiop_script))) {
! 1136: printf("%s: dsp not within script dsp %x scripts %lx:%lx",
! 1137: sc->sc_dev.dv_xname,
! 1138: osiop_read_4(sc, OSIOP_DSP),
! 1139: scraddr, scraddr + sizeof(osiop_script));
! 1140: printf(" istat %x dstat %x sstat0 %x\n", istat, dstat, sstat0);
! 1141: #ifdef DDB
! 1142: Debugger();
! 1143: #endif
! 1144: }
! 1145: #endif
! 1146: OSIOP_TRACE('i', dstat, istat, (istat & OSIOP_ISTAT_DIP) ?
! 1147: intcode & 0xff : sstat0);
! 1148:
! 1149: ds = NULL;
! 1150: if (acb != NULL) { /* XXX */
! 1151: ds = acb->ds;
! 1152: bus_dmamap_sync(sc->sc_dmat, dsdma,
! 1153: acb->dsoffset, sizeof(struct osiop_ds),
! 1154: BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
! 1155: #ifdef OSIOP_DEBUG
! 1156: if (acb->status != ACB_S_ACTIVE)
! 1157: printf("osiop_checkintr: acb not active (status %d)\n",
! 1158: acb->status);
! 1159: #endif
! 1160: }
! 1161:
! 1162: if (dstat & OSIOP_DSTAT_SIR && intcode == A_ok) {
! 1163: /* Normal completion status, or check condition */
! 1164: struct osiop_tinfo *ti;
! 1165: if (acb == NULL) {
! 1166: printf("%s: COMPLETE with no active command?\n",
! 1167: sc->sc_dev.dv_xname);
! 1168: return (0);
! 1169: }
! 1170: #ifdef OSIOP_DEBUG
! 1171: if (osiop_read_4(sc, OSIOP_DSA) !=
! 1172: dsdma->dm_segs[0].ds_addr + acb->dsoffset) {
! 1173: printf("osiop: invalid dsa: %x %lx\n",
! 1174: osiop_read_4(sc, OSIOP_DSA),
! 1175: dsdma->dm_segs[0].ds_addr + acb->dsoffset);
! 1176: panic("*** osiop DSA invalid ***");
! 1177: }
! 1178: #endif
! 1179: target = acb->xs->sc_link->target;
! 1180: ti = &sc->sc_tinfo[target];
! 1181: if (ti->state == NEG_WAITS) {
! 1182: if (ds->msgbuf[1] == MSG_INVALID)
! 1183: printf("%s: target %d ignored sync request\n",
! 1184: sc->sc_dev.dv_xname, target);
! 1185: else if (ds->msgbuf[1] == MSG_MESSAGE_REJECT)
! 1186: printf("%s: target %d rejected sync request\n",
! 1187: sc->sc_dev.dv_xname, target);
! 1188: ti->period = 0;
! 1189: ti->offset = 0;
! 1190: osiop_update_xfer_mode(sc, target);
! 1191: ti->state = NEG_DONE;
! 1192: }
! 1193: #ifdef OSIOP_DEBUG
! 1194: if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
! 1195: #if 0
! 1196: printf("ACK! osiop was busy at end: "
! 1197: "script %p dsa %p\n", &osiop_script, ds);
! 1198: #ifdef DDB
! 1199: Debugger();
! 1200: #endif
! 1201: #endif
! 1202: }
! 1203: if (ds->msgbuf[0] != MSG_CMDCOMPLETE)
! 1204: printf("%s: message was not COMMAND COMPLETE: %02x\n",
! 1205: sc->sc_dev.dv_xname, ds->msgbuf[0]);
! 1206: #endif
! 1207: if (!TAILQ_EMPTY(&sc->nexus_list))
! 1208: osiop_write_1(sc, OSIOP_DCNTL,
! 1209: osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
! 1210: *status = ds->stat[0];
! 1211: acb->status = ACB_S_DONE;
! 1212: return (1);
! 1213: }
! 1214: if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_syncmsg) {
! 1215: if (acb == NULL) {
! 1216: printf("%s: Sync message with no active command?\n",
! 1217: sc->sc_dev.dv_xname);
! 1218: return (0);
! 1219: }
! 1220: target = acb->xs->sc_link->target;
! 1221: if (ds->msgbuf[1] == MSG_EXTENDED &&
! 1222: ds->msgbuf[2] == MSG_EXT_SDTR_LEN &&
! 1223: ds->msgbuf[3] == MSG_EXT_SDTR) {
! 1224: struct osiop_tinfo *ti = &sc->sc_tinfo[target];
! 1225: #ifdef OSIOP_DEBUG
! 1226: if (osiop_debug & DEBUG_SYNC)
! 1227: printf("sync msg in: "
! 1228: "%02x %02x %02x %02x %02x %02x\n",
! 1229: ds->msgbuf[0], ds->msgbuf[1],
! 1230: ds->msgbuf[2], ds->msgbuf[3],
! 1231: ds->msgbuf[4], ds->msgbuf[5]);
! 1232: #endif
! 1233: ti->period = ds->msgbuf[4];
! 1234: ti->offset = ds->msgbuf[5];
! 1235: osiop_update_xfer_mode(sc, target);
! 1236:
! 1237: bus_dmamap_sync(sc->sc_dmat, dsdma,
! 1238: acb->dsoffset, sizeof(struct osiop_ds),
! 1239: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1240: osiop_write_1(sc, OSIOP_SXFER, ti->sxfer);
! 1241: osiop_write_1(sc, OSIOP_SBCL, ti->sbcl);
! 1242: if (ti->state == NEG_WAITS) {
! 1243: ti->state = NEG_DONE;
! 1244: osiop_write_4(sc, OSIOP_DSP,
! 1245: scraddr + Ent_clear_ack);
! 1246: return (0);
! 1247: }
! 1248: osiop_write_1(sc, OSIOP_DCNTL,
! 1249: osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
! 1250: ti->state = NEG_DONE;
! 1251: return (0);
! 1252: }
! 1253: /* XXX - not SDTR message */
! 1254: }
! 1255: if (sstat0 & OSIOP_SSTAT0_M_A) {
! 1256: /* Phase mismatch */
! 1257: #ifdef OSIOP_DEBUG
! 1258: osiopphmm++;
! 1259: #endif
! 1260: if (acb == NULL) {
! 1261: printf("%s: Phase mismatch with no active command?\n",
! 1262: sc->sc_dev.dv_xname);
! 1263: return (0);
! 1264: }
! 1265: if (acb->datalen > 0) {
! 1266: int adjust = (dfifo - (dbc & 0x7f)) & 0x7f;
! 1267: if (sstat1 & OSIOP_SSTAT1_ORF)
! 1268: adjust++;
! 1269: if (sstat1 & OSIOP_SSTAT1_OLF)
! 1270: adjust++;
! 1271: acb->curaddr = osiop_read_4(sc, OSIOP_DNAD) - adjust;
! 1272: acb->curlen = dbc + adjust;
! 1273: #ifdef OSIOP_DEBUG
! 1274: if (osiop_debug & DEBUG_DISC) {
! 1275: printf("Phase mismatch: curaddr %lx "
! 1276: "curlen %lx dfifo %x dbc %x sstat1 %x "
! 1277: "adjust %x sbcl %x starts %d acb %p\n",
! 1278: acb->curaddr, acb->curlen, dfifo,
! 1279: dbc, sstat1, adjust,
! 1280: osiop_read_1(sc, OSIOP_SBCL),
! 1281: osiopstarts, acb);
! 1282: if (ds->data[1].count != 0) {
! 1283: int i;
! 1284: for (i = 0; ds->data[i].count != 0; i++)
! 1285: printf("chain[%d] "
! 1286: "addr %x len %x\n", i,
! 1287: ds->data[i].addr,
! 1288: ds->data[i].count);
! 1289: }
! 1290: bus_dmamap_sync(sc->sc_dmat, dsdma,
! 1291: acb->dsoffset, sizeof(struct osiop_ds),
! 1292: BUS_DMASYNC_PREREAD |
! 1293: BUS_DMASYNC_PREWRITE);
! 1294: }
! 1295: #endif
! 1296: }
! 1297: #ifdef OSIOP_DEBUG
! 1298: OSIOP_TRACE('m', osiop_read_1(sc, OSIOP_SBCL),
! 1299: osiop_read_4(sc, OSIOP_DSP) >> 8,
! 1300: osiop_read_4(sc, OSIOP_DSP));
! 1301: if (osiop_debug & DEBUG_PHASE)
! 1302: printf("Phase mismatch: %x dsp +%lx dcmd %x\n",
! 1303: osiop_read_1(sc, OSIOP_SBCL),
! 1304: osiop_read_4(sc, OSIOP_DSP) - scraddr,
! 1305: osiop_read_4(sc, OSIOP_DBC));
! 1306: #endif
! 1307: if ((osiop_read_1(sc, OSIOP_SBCL) & OSIOP_REQ) == 0) {
! 1308: printf("Phase mismatch: "
! 1309: "REQ not asserted! %02x dsp %x\n",
! 1310: osiop_read_1(sc, OSIOP_SBCL),
! 1311: osiop_read_4(sc, OSIOP_DSP));
! 1312: #if defined(OSIOP_DEBUG) && defined(DDB)
! 1313: /*Debugger(); XXX is*/
! 1314: #endif
! 1315: }
! 1316: switch (OSIOP_PHASE(osiop_read_1(sc, OSIOP_SBCL))) {
! 1317: case DATA_OUT_PHASE:
! 1318: case DATA_IN_PHASE:
! 1319: case STATUS_PHASE:
! 1320: case COMMAND_PHASE:
! 1321: case MSG_IN_PHASE:
! 1322: case MSG_OUT_PHASE:
! 1323: osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_switch);
! 1324: break;
! 1325: default:
! 1326: printf("%s: invalid phase\n", sc->sc_dev.dv_xname);
! 1327: goto bad_phase;
! 1328: }
! 1329: return (0);
! 1330: }
! 1331: if (sstat0 & OSIOP_SSTAT0_STO) {
! 1332: /* Select timed out */
! 1333: if (acb == NULL) {
! 1334: printf("%s: Select timeout with no active command?\n",
! 1335: sc->sc_dev.dv_xname);
! 1336: #if 0
! 1337: return (0);
! 1338: #else
! 1339: goto bad_phase;
! 1340: #endif
! 1341: }
! 1342: #ifdef OSIOP_DEBUG
! 1343: if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
! 1344: printf("ACK! osiop was busy at timeout: "
! 1345: "script %p dsa %lx\n", sc->sc_script,
! 1346: dsdma->dm_segs[0].ds_addr + acb->dsoffset);
! 1347: printf(" sbcl %x sdid %x "
! 1348: "istat %x dstat %x sstat0 %x\n",
! 1349: osiop_read_1(sc, OSIOP_SBCL),
! 1350: osiop_read_1(sc, OSIOP_SDID),
! 1351: istat, dstat, sstat0);
! 1352: if ((osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) == 0) {
! 1353: printf("Yikes, it's not busy now!\n");
! 1354: #if 0
! 1355: *status = SCSI_OSIOP_NOSTATUS;
! 1356: if (!TAILQ_EMPTY(&sc->nexus_list))
! 1357: osiop_write_4(sc, OSIOP_DSP,
! 1358: scraddr + Ent_wait_reselect);
! 1359: return (1);
! 1360: #endif
! 1361: }
! 1362: #if 0
! 1363: osiop_write_1(sc, OSIOP_DCNTL,
! 1364: osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
! 1365: #endif
! 1366: #ifdef DDB
! 1367: Debugger();
! 1368: #endif
! 1369: return (0);
! 1370: }
! 1371: #endif
! 1372: acb->status = ACB_S_DONE;
! 1373: *status = SCSI_OSIOP_NOSTATUS;
! 1374: acb->xs->error = XS_SELTIMEOUT;
! 1375: if (!TAILQ_EMPTY(&sc->nexus_list))
! 1376: osiop_write_4(sc, OSIOP_DSP,
! 1377: scraddr + Ent_wait_reselect);
! 1378: return (1);
! 1379: }
! 1380: if (acb != NULL)
! 1381: target = acb->xs->sc_link->target;
! 1382: else
! 1383: target = sc->sc_id;
! 1384: if (sstat0 & OSIOP_SSTAT0_UDC) {
! 1385: #ifdef OSIOP_DEBUG
! 1386: if (acb == NULL)
! 1387: printf("%s: Unexpected disconnect "
! 1388: "with no active command?\n", sc->sc_dev.dv_xname);
! 1389: printf("%s: target %d disconnected unexpectedly\n",
! 1390: sc->sc_dev.dv_xname, target);
! 1391: #endif
! 1392: #if 0
! 1393: osiop_abort(sc, "osiop_chkintr");
! 1394: #endif
! 1395: *status = SCSI_CHECK;
! 1396: if (!TAILQ_EMPTY(&sc->nexus_list))
! 1397: osiop_write_4(sc, OSIOP_DSP,
! 1398: scraddr + Ent_wait_reselect);
! 1399: return (acb != NULL);
! 1400: }
! 1401: if (dstat & OSIOP_DSTAT_SIR &&
! 1402: (intcode == A_int_disc || intcode == A_int_disc_wodp)) {
! 1403: /* Disconnect */
! 1404: if (acb == NULL) {
! 1405: printf("%s: Disconnect with no active command?\n",
! 1406: sc->sc_dev.dv_xname);
! 1407: return (0);
! 1408: }
! 1409: #ifdef OSIOP_DEBUG
! 1410: if (osiop_debug & DEBUG_DISC) {
! 1411: printf("%s: ID %02x disconnected TEMP %x (+%lx) "
! 1412: "curaddr %lx curlen %lx buf %x len %x dfifo %x "
! 1413: "dbc %x sstat1 %x starts %d acb %p\n",
! 1414: sc->sc_dev.dv_xname, 1 << target,
! 1415: osiop_read_4(sc, OSIOP_TEMP),
! 1416: (osiop_read_4(sc, OSIOP_TEMP) != 0) ?
! 1417: osiop_read_4(sc, OSIOP_TEMP) - scraddr : 0,
! 1418: acb->curaddr, acb->curlen,
! 1419: ds->data[0].addr, ds->data[0].count,
! 1420: dfifo, dbc, sstat1, osiopstarts, acb);
! 1421: bus_dmamap_sync(sc->sc_dmat, dsdma,
! 1422: acb->dsoffset, sizeof(struct osiop_ds),
! 1423: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1424: }
! 1425: #endif
! 1426: /*
! 1427: * XXXX need to update curaddr/curlen to reflect
! 1428: * current data transferred. If device disconnected in
! 1429: * the middle of a DMA block, they should already be set
! 1430: * by the phase change interrupt. If the disconnect
! 1431: * occurs on a DMA block boundary, we have to figure out
! 1432: * which DMA block it was.
! 1433: */
! 1434: if (acb->datalen > 0 &&
! 1435: osiop_read_4(sc, OSIOP_TEMP) != 0) {
! 1436: long n = osiop_read_4(sc, OSIOP_TEMP) - scraddr;
! 1437:
! 1438: if (acb->curlen != 0 &&
! 1439: acb->curlen != ds->data[0].count)
! 1440: printf("%s: curaddr/curlen already set? "
! 1441: "n %lx iob %lx/%lx chain[0] %x/%x\n",
! 1442: sc->sc_dev.dv_xname, n,
! 1443: acb->curaddr, acb->curlen,
! 1444: ds->data[0].addr, ds->data[0].count);
! 1445: if (n < Ent_datain)
! 1446: n = (n - Ent_dataout) / 16;
! 1447: else
! 1448: n = (n - Ent_datain) / 16;
! 1449: if (n < 0 || n >= OSIOP_NSG)
! 1450: printf("TEMP invalid %ld\n", n);
! 1451: else {
! 1452: acb->curaddr = ds->data[n].addr;
! 1453: acb->curlen = ds->data[n].count;
! 1454: }
! 1455: #ifdef OSIOP_DEBUG
! 1456: if (osiop_debug & DEBUG_DISC) {
! 1457: printf("%s: TEMP offset %ld",
! 1458: sc->sc_dev.dv_xname, n);
! 1459: printf(" curaddr %lx curlen %lx\n",
! 1460: acb->curaddr, acb->curlen);
! 1461: }
! 1462: #endif
! 1463: }
! 1464: /*
! 1465: * If data transfer was interrupted by disconnect, curaddr
! 1466: * and curlen should reflect the point of interruption.
! 1467: * Adjust the DMA chain so that the data transfer begins
! 1468: * at the appropriate place upon reselection.
! 1469: * XXX This should only be done on save data pointer message?
! 1470: */
! 1471: if (acb->curlen > 0) {
! 1472: int i, j;
! 1473: #ifdef OSIOP_DEBUG
! 1474: if (osiop_debug & DEBUG_DISC)
! 1475: printf("%s: adjusting DMA chain\n",
! 1476: sc->sc_dev.dv_xname);
! 1477: if (intcode == A_int_disc_wodp)
! 1478: printf("%s: ID %02x disconnected "
! 1479: "without Save Data Pointers\n",
! 1480: sc->sc_dev.dv_xname, 1 << target);
! 1481: #endif
! 1482: for (i = 0; i < OSIOP_NSG; i++) {
! 1483: if (ds->data[i].count == 0)
! 1484: break;
! 1485: if (acb->curaddr >= ds->data[i].addr &&
! 1486: acb->curaddr <
! 1487: (ds->data[i].addr + ds->data[i].count))
! 1488: break;
! 1489: }
! 1490: if (i >= OSIOP_NSG || ds->data[i].count == 0) {
! 1491: printf("couldn't find saved data pointer: "
! 1492: "curaddr %lx curlen %lx i %d\n",
! 1493: acb->curaddr, acb->curlen, i);
! 1494: #if defined(OSIOP_DEBUG) && defined(DDB)
! 1495: Debugger();
! 1496: #endif
! 1497: }
! 1498: #ifdef OSIOP_DEBUG
! 1499: if (osiop_debug & DEBUG_DISC)
! 1500: printf(" chain[0]: %x/%x -> %lx/%lx\n",
! 1501: ds->data[0].addr, ds->data[0].count,
! 1502: acb->curaddr, acb->curlen);
! 1503: #endif
! 1504: ds->data[0].addr = acb->curaddr;
! 1505: ds->data[0].count = acb->curlen;
! 1506: for (j = 1, i = i + 1;
! 1507: i < OSIOP_NSG && ds->data[i].count > 0;
! 1508: i++, j++) {
! 1509: #ifdef OSIOP_DEBUG
! 1510: if (osiop_debug & DEBUG_DISC)
! 1511: printf(" chain[%d]: %x/%x -> %x/%x\n",
! 1512: j,
! 1513: ds->data[j].addr, ds->data[j].count,
! 1514: ds->data[i].addr, ds->data[i].count);
! 1515: #endif
! 1516: ds->data[j].addr = ds->data[i].addr;
! 1517: ds->data[j].count = ds->data[i].count;
! 1518: }
! 1519: if (j < OSIOP_NSG) {
! 1520: ds->data[j].addr = 0;
! 1521: ds->data[j].count = 0;
! 1522: }
! 1523: bus_dmamap_sync(sc->sc_dmat, dsdma,
! 1524: acb->dsoffset, sizeof(struct osiop_ds),
! 1525: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1526: }
! 1527: sc->sc_tinfo[target].dconns++;
! 1528: /*
! 1529: * add nexus to waiting list
! 1530: * clear nexus
! 1531: * try to start another command for another target/lun
! 1532: */
! 1533: acb->intstat = sc->sc_flags & OSIOP_INTSOFF;
! 1534: TAILQ_INSERT_TAIL(&sc->nexus_list, acb, chain);
! 1535: sc->sc_nexus = NULL; /* no current device */
! 1536: osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_wait_reselect);
! 1537: /* XXXX start another command ? */
! 1538: osiop_sched(sc);
! 1539: return (0);
! 1540: }
! 1541: if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_reconnect) {
! 1542: int reselid = ffs(osiop_read_4(sc, OSIOP_SCRATCH) & 0xff) - 1;
! 1543: int reselun = osiop_read_1(sc, OSIOP_SFBR) & 0x07;
! 1544: #ifdef OSIOP_DEBUG
! 1545: u_int8_t resmsg;
! 1546: #endif
! 1547:
! 1548: /* Reconnect */
! 1549: /* XXXX save current SBCL */
! 1550: sc->sc_sstat1 = osiop_read_1(sc, OSIOP_SBCL);
! 1551: #ifdef OSIOP_DEBUG
! 1552: if (osiop_debug & DEBUG_DISC)
! 1553: printf("%s: target ID %02x reselected dsps %x\n",
! 1554: sc->sc_dev.dv_xname, reselid, intcode);
! 1555: resmsg = osiop_read_1(sc, OSIOP_SFBR);
! 1556: if (!MSG_ISIDENTIFY(resmsg))
! 1557: printf("%s: Reselect message in was not identify: "
! 1558: "%02x\n", sc->sc_dev.dv_xname, resmsg);
! 1559: #endif
! 1560: if (sc->sc_nexus != NULL) {
! 1561: struct scsi_link *periph =
! 1562: sc->sc_nexus->xs->sc_link;
! 1563: #ifdef OSIOP_DEBUG
! 1564: if (osiop_debug & DEBUG_DISC)
! 1565: printf("%s: reselect ID %02x w/active\n",
! 1566: sc->sc_dev.dv_xname, reselid);
! 1567: #endif
! 1568: TAILQ_INSERT_HEAD(&sc->ready_list,
! 1569: sc->sc_nexus, chain);
! 1570: sc->sc_tinfo[periph->target].lubusy
! 1571: &= ~(1 << periph->lun);
! 1572: sc->sc_active--;
! 1573: }
! 1574: /*
! 1575: * locate acb of reselecting device
! 1576: * set sc->sc_nexus to acb
! 1577: */
! 1578: TAILQ_FOREACH(acb, &sc->nexus_list, chain) {
! 1579: struct scsi_link *periph = acb->xs->sc_link;
! 1580: if (reselid != periph->target ||
! 1581: reselun != periph->lun) {
! 1582: continue;
! 1583: }
! 1584: TAILQ_REMOVE(&sc->nexus_list, acb, chain);
! 1585: sc->sc_nexus = acb;
! 1586: sc->sc_flags |= acb->intstat;
! 1587: acb->intstat = 0;
! 1588: osiop_write_4(sc, OSIOP_DSA,
! 1589: dsdma->dm_segs[0].ds_addr + acb->dsoffset);
! 1590: osiop_write_1(sc, OSIOP_SXFER,
! 1591: sc->sc_tinfo[reselid].sxfer);
! 1592: osiop_write_1(sc, OSIOP_SBCL,
! 1593: sc->sc_tinfo[reselid].sbcl);
! 1594: break;
! 1595: }
! 1596: if (acb == NULL) {
! 1597: printf("%s: target ID %02x reselect nexus_list %p\n",
! 1598: sc->sc_dev.dv_xname, reselid,
! 1599: TAILQ_FIRST(&sc->nexus_list));
! 1600: panic("unable to find reselecting device");
! 1601: }
! 1602:
! 1603: osiop_write_4(sc, OSIOP_TEMP, 0);
! 1604: osiop_write_1(sc, OSIOP_DCNTL,
! 1605: osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
! 1606: return (0);
! 1607: }
! 1608: if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_connect) {
! 1609: #ifdef OSIOP_DEBUG
! 1610: u_int8_t ctest2 = osiop_read_1(sc, OSIOP_CTEST2);
! 1611:
! 1612: /* reselect was interrupted (by Sig_P or select) */
! 1613: if (osiop_debug & DEBUG_DISC ||
! 1614: (ctest2 & OSIOP_CTEST2_SIGP) == 0)
! 1615: printf("%s: reselect interrupted (Sig_P?) "
! 1616: "scntl1 %x ctest2 %x sfbr %x istat %x/%x\n",
! 1617: sc->sc_dev.dv_xname,
! 1618: osiop_read_1(sc, OSIOP_SCNTL1), ctest2,
! 1619: osiop_read_1(sc, OSIOP_SFBR), istat,
! 1620: osiop_read_1(sc, OSIOP_ISTAT));
! 1621: #endif
! 1622: /* XXX assumes it was not select */
! 1623: if (sc->sc_nexus == NULL) {
! 1624: #ifdef OSIOP_DEBUG
! 1625: printf("%s: reselect interrupted, sc_nexus == NULL\n",
! 1626: sc->sc_dev.dv_xname);
! 1627: #if 0
! 1628: osiop_dump(sc);
! 1629: #ifdef DDB
! 1630: Debugger();
! 1631: #endif
! 1632: #endif
! 1633: #endif
! 1634: osiop_write_1(sc, OSIOP_DCNTL,
! 1635: osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
! 1636: return (0);
! 1637: }
! 1638: target = sc->sc_nexus->xs->sc_link->target;
! 1639: osiop_write_4(sc, OSIOP_TEMP, 0);
! 1640: osiop_write_4(sc, OSIOP_DSA,
! 1641: dsdma->dm_segs[0].ds_addr + sc->sc_nexus->dsoffset);
! 1642: osiop_write_1(sc, OSIOP_SXFER, sc->sc_tinfo[target].sxfer);
! 1643: osiop_write_1(sc, OSIOP_SBCL, sc->sc_tinfo[target].sbcl);
! 1644: osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_scripts);
! 1645: return (0);
! 1646: }
! 1647: if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_msgin) {
! 1648: /* Unrecognized message in byte */
! 1649: if (acb == NULL) {
! 1650: printf("%s: Bad message-in with no active command?\n",
! 1651: sc->sc_dev.dv_xname);
! 1652: return (0);
! 1653: }
! 1654: printf("%s: Unrecognized message in data "
! 1655: "sfbr %x msg %x sbcl %x\n", sc->sc_dev.dv_xname,
! 1656: osiop_read_1(sc, OSIOP_SFBR), ds->msgbuf[1],
! 1657: osiop_read_1(sc, OSIOP_SBCL));
! 1658: /* what should be done here? */
! 1659: osiop_write_4(sc, OSIOP_DSP, scraddr + Ent_switch);
! 1660: bus_dmamap_sync(sc->sc_dmat, dsdma,
! 1661: acb->dsoffset, sizeof(struct osiop_ds),
! 1662: BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
! 1663: return (0);
! 1664: }
! 1665: if (dstat & OSIOP_DSTAT_SIR && intcode == A_int_status) {
! 1666: /* Status phase wasn't followed by message in phase? */
! 1667: printf("%s: Status phase not followed by message in phase? "
! 1668: "sbcl %x sbdl %x\n", sc->sc_dev.dv_xname,
! 1669: osiop_read_1(sc, OSIOP_SBCL),
! 1670: osiop_read_1(sc, OSIOP_SBDL));
! 1671: if (osiop_read_1(sc, OSIOP_SBCL) == 0xa7) {
! 1672: /* It is now, just continue the script? */
! 1673: osiop_write_1(sc, OSIOP_DCNTL,
! 1674: osiop_read_1(sc, OSIOP_DCNTL) | OSIOP_DCNTL_STD);
! 1675: return (0);
! 1676: }
! 1677: }
! 1678: if (dstat & OSIOP_DSTAT_SIR && sstat0 == 0) {
! 1679: printf("OSIOP interrupt: %x sts %x msg %x %x sbcl %x\n",
! 1680: intcode, ds->stat[0], ds->msgbuf[0], ds->msgbuf[1],
! 1681: osiop_read_1(sc, OSIOP_SBCL));
! 1682: osiop_reset(sc);
! 1683: *status = SCSI_OSIOP_NOSTATUS;
! 1684: return (0); /* osiop_reset has cleaned up */
! 1685: }
! 1686: if (sstat0 & OSIOP_SSTAT0_SGE)
! 1687: printf("%s: SCSI Gross Error\n", sc->sc_dev.dv_xname);
! 1688: if (sstat0 & OSIOP_SSTAT0_PAR)
! 1689: printf("%s: Parity Error\n", sc->sc_dev.dv_xname);
! 1690: if (dstat & OSIOP_DSTAT_IID)
! 1691: printf("%s: Invalid instruction detected\n",
! 1692: sc->sc_dev.dv_xname);
! 1693: bad_phase:
! 1694: /*
! 1695: * temporary panic for unhandled conditions
! 1696: * displays various things about the 53C710 status and registers
! 1697: * then panics.
! 1698: * XXXX need to clean this up to print out the info, reset, and continue
! 1699: */
! 1700: printf("osiop_chkintr: target %x ds %p\n", target, ds);
! 1701: printf("scripts %lx ds %lx dsp %x dcmd %x\n", scraddr,
! 1702: sc->sc_dsdma->dm_segs[0].ds_addr + acb->dsoffset,
! 1703: osiop_read_4(sc, OSIOP_DSP),
! 1704: osiop_read_4(sc, OSIOP_DBC));
! 1705: printf("osiop_chkintr: istat %x dstat %x sstat0 %x "
! 1706: "dsps %x dsa %x sbcl %x sts %x msg %x %x sfbr %x\n",
! 1707: istat, dstat, sstat0, intcode,
! 1708: osiop_read_4(sc, OSIOP_DSA),
! 1709: osiop_read_1(sc, OSIOP_SBCL),
! 1710: ds->stat[0], ds->msgbuf[0], ds->msgbuf[1],
! 1711: osiop_read_1(sc, OSIOP_SFBR));
! 1712: #ifdef OSIOP_DEBUG
! 1713: if (osiop_debug & DEBUG_DMA)
! 1714: panic("osiop_chkintr: **** temp ****");
! 1715: #if 0
! 1716: #ifdef DDB
! 1717: Debugger();
! 1718: #endif
! 1719: #endif
! 1720: #endif
! 1721: osiop_reset(sc); /* hard reset */
! 1722: *status = SCSI_OSIOP_NOSTATUS;
! 1723: if (acb != NULL)
! 1724: acb->status = ACB_S_DONE;
! 1725: return (0); /* osiop_reset cleaned up */
! 1726: }
! 1727:
! 1728: void
! 1729: osiop_select(sc)
! 1730: struct osiop_softc *sc;
! 1731: {
! 1732: struct osiop_acb *acb = sc->sc_nexus;
! 1733:
! 1734: #ifdef OSIOP_DEBUG
! 1735: if (osiop_debug & DEBUG_CMD)
! 1736: printf("%s: select ", sc->sc_dev.dv_xname);
! 1737: #endif
! 1738:
! 1739: if (acb->xsflags & SCSI_POLL || sc->sc_flags & OSIOP_NODMA) {
! 1740: sc->sc_flags |= OSIOP_INTSOFF;
! 1741: sc->sc_flags &= ~OSIOP_INTDEFER;
! 1742: if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
! 1743: osiop_write_1(sc, OSIOP_SIEN, 0);
! 1744: osiop_write_1(sc, OSIOP_DIEN, 0);
! 1745: }
! 1746: #if 0
! 1747: } else if ((sc->sc_flags & OSIOP_INTDEFER) == 0) {
! 1748: sc->sc_flags &= ~OSIOP_INTSOFF;
! 1749: if ((osiop_read_1(sc, OSIOP_ISTAT) & OSIOP_ISTAT_CON) == 0) {
! 1750: osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
! 1751: osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
! 1752: }
! 1753: #endif
! 1754: }
! 1755: #ifdef OSIOP_DEBUG
! 1756: if (osiop_debug & DEBUG_CMD)
! 1757: printf("osiop_select: target %x cmd %02x ds %p\n",
! 1758: acb->xs->sc_link->target,
! 1759: acb->ds->scsi_cmd.opcode, sc->sc_nexus->ds);
! 1760: #endif
! 1761:
! 1762: osiop_start(sc);
! 1763:
! 1764: return;
! 1765: }
! 1766:
! 1767: /*
! 1768: * 53C710 interrupt handler
! 1769: */
! 1770:
! 1771: void
! 1772: osiop_intr(sc)
! 1773: struct osiop_softc *sc;
! 1774: {
! 1775: int status, s;
! 1776: u_int8_t istat, dstat, sstat0;
! 1777:
! 1778: s = splbio();
! 1779:
! 1780: istat = sc->sc_istat;
! 1781: if ((istat & (OSIOP_ISTAT_SIP | OSIOP_ISTAT_DIP)) == 0) {
! 1782: splx(s);
! 1783: return;
! 1784: }
! 1785:
! 1786: /* Got a valid interrupt on this device; set by MD handler */
! 1787: dstat = sc->sc_dstat;
! 1788: sstat0 = sc->sc_sstat0;
! 1789: sc->sc_istat = 0;
! 1790: #ifdef OSIOP_DEBUG
! 1791: if (!sc->sc_active) {
! 1792: /* XXX needs sync */
! 1793: printf("%s: spurious interrupt? "
! 1794: "istat %x dstat %x sstat0 %x nexus %p status %x\n",
! 1795: sc->sc_dev.dv_xname, istat, dstat, sstat0, sc->sc_nexus,
! 1796: (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->stat[0] : 0);
! 1797: }
! 1798: #endif
! 1799:
! 1800: #ifdef OSIOP_DEBUG
! 1801: if (osiop_debug & (DEBUG_INT|DEBUG_CMD)) {
! 1802: /* XXX needs sync */
! 1803: printf("%s: intr istat %x dstat %x sstat0 %x dsps %x "
! 1804: "sbcl %x dsp %x dcmd %x sts %x msg %x\n",
! 1805: sc->sc_dev.dv_xname,
! 1806: istat, dstat, sstat0,
! 1807: osiop_read_4(sc, OSIOP_DSPS),
! 1808: osiop_read_1(sc, OSIOP_SBCL),
! 1809: osiop_read_4(sc, OSIOP_DSP),
! 1810: osiop_read_4(sc, OSIOP_DBC),
! 1811: (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->stat[0] : 0,
! 1812: (sc->sc_nexus != NULL) ? sc->sc_nexus->ds->msgbuf[0] : 0);
! 1813: }
! 1814: #endif
! 1815: if (sc->sc_flags & OSIOP_INTDEFER) {
! 1816: sc->sc_flags &= ~(OSIOP_INTDEFER | OSIOP_INTSOFF);
! 1817: osiop_write_1(sc, OSIOP_SIEN, sc->sc_sien);
! 1818: osiop_write_1(sc, OSIOP_DIEN, sc->sc_dien);
! 1819: }
! 1820: if (osiop_checkintr(sc, istat, dstat, sstat0, &status)) {
! 1821: #if 0
! 1822: if (status == SCSI_OSIOP_NOSTATUS)
! 1823: printf("osiop_intr: no valid status \n");
! 1824: #endif
! 1825: if ((sc->sc_flags & (OSIOP_INTSOFF | OSIOP_INTDEFER)) !=
! 1826: OSIOP_INTSOFF) {
! 1827: #if 0
! 1828: if (osiop_read_1(sc, OSIOP_SBCL) & OSIOP_BSY) {
! 1829: struct scsi_link *periph;
! 1830:
! 1831: periph = sc->sc_nexus->xs->sc_link;
! 1832: printf("%s: SCSI bus busy at completion"
! 1833: " targ %d sbcl %02x sfbr %x lcrc "
! 1834: "%02x dsp +%x\n", sc->sc_dev.dv_xname,
! 1835: periph->periphtarget,
! 1836: osiop_read_1(sc, OSIOP_SBCL),
! 1837: osiop_read_1(sc, OSIOP_SFBR),
! 1838: osiop_read_1(sc, OSIOP_LCRC),
! 1839: osiop_read_4(sc, OSIOP_DSP) -
! 1840: sc->sc_scrdma->dm_segs[0].ds_addr);
! 1841: }
! 1842: #endif
! 1843: osiop_scsidone(sc->sc_nexus, status);
! 1844: }
! 1845: }
! 1846: splx(s);
! 1847: }
! 1848:
! 1849: void
! 1850: osiop_update_xfer_mode(sc, target)
! 1851: struct osiop_softc *sc;
! 1852: int target;
! 1853: {
! 1854: struct osiop_tinfo *ti = &sc->sc_tinfo[target];
! 1855:
! 1856: printf("%s: target %d now using 8 bit ", sc->sc_dev.dv_xname, target);
! 1857:
! 1858: ti->sxfer = 0;
! 1859: ti->sbcl = 0;
! 1860: if (ti->offset != 0) {
! 1861: scsi_period_to_osiop(sc, target);
! 1862: switch (ti->period) {
! 1863: case 0x00:
! 1864: case 0x01:
! 1865: case 0x02:
! 1866: case 0x03:
! 1867: case 0x04:
! 1868: case 0x05:
! 1869: case 0x06:
! 1870: case 0x07:
! 1871: case 0x08:
! 1872: /* Reserved transfer period factor */
! 1873: printf("??");
! 1874: break;
! 1875: case 0x09:
! 1876: /* Transfer period = 12.5 ns */
! 1877: printf("80");
! 1878: break;
! 1879: case 0x0a:
! 1880: /* Transfer period = 25 ns */
! 1881: printf("40");
! 1882: break;
! 1883: case 0x0b:
! 1884: /* Transfer period = 30.3 ns */
! 1885: printf("33");
! 1886: break;
! 1887: case 0x0c:
! 1888: /* Transfer period = 50 ns */
! 1889: printf("20");
! 1890: break;
! 1891: default:
! 1892: /* Transfer period = ti->period*4 ns */
! 1893: printf("%d", 1000/(ti->period*4));
! 1894: break;
! 1895: }
! 1896: printf(" MHz %d REQ/ACK offset", ti->offset);
! 1897: } else
! 1898: printf("asynch");
! 1899:
! 1900: printf(" xfers\n");
! 1901: }
! 1902:
! 1903: /*
! 1904: * This is based on the Progressive Peripherals 33MHz Zeus driver and will
! 1905: * not be correct for other 53c710 boards.
! 1906: *
! 1907: */
! 1908: void
! 1909: scsi_period_to_osiop(sc, target)
! 1910: struct osiop_softc *sc;
! 1911: int target;
! 1912: {
! 1913: int period, offset, sxfer, sbcl;
! 1914: #ifdef OSIOP_DEBUG
! 1915: int i;
! 1916: #endif
! 1917:
! 1918: period = sc->sc_tinfo[target].period;
! 1919: offset = sc->sc_tinfo[target].offset;
! 1920: #ifdef OSIOP_DEBUG
! 1921: if (osiop_debug & DEBUG_SYNC) {
! 1922: sxfer = 0;
! 1923: if (offset <= OSIOP_MAX_OFFSET)
! 1924: sxfer = offset;
! 1925: for (i = 0; i < sizeof(sync_tab) / sizeof(sync_tab[0]); i++) {
! 1926: if (period <= sync_tab[i].p) {
! 1927: sxfer |= sync_tab[i].r & 0x70;
! 1928: sbcl = sync_tab[i].r & 0x03;
! 1929: break;
! 1930: }
! 1931: }
! 1932: printf("osiop sync old: osiop_sxfr %02x, osiop_sbcl %02x\n",
! 1933: sxfer, sbcl);
! 1934: }
! 1935: #endif
! 1936: for (sbcl = 1; sbcl < 4; sbcl++) {
! 1937: sxfer = (period * 4 - 1) / sc->sc_tcp[sbcl] - 3;
! 1938: if (sxfer >= 0 && sxfer <= 7)
! 1939: break;
! 1940: }
! 1941: if (sbcl > 3) {
! 1942: printf("osiop sync: unable to compute sync params "
! 1943: "for period %d ns\n", period * 4);
! 1944: /*
! 1945: * XXX need to pick a value we can do and renegotiate
! 1946: */
! 1947: sxfer = sbcl = 0;
! 1948: } else {
! 1949: sxfer = (sxfer << 4) | ((offset <= OSIOP_MAX_OFFSET) ?
! 1950: offset : OSIOP_MAX_OFFSET);
! 1951: #ifdef OSIOP_DEBUG
! 1952: if (osiop_debug & DEBUG_SYNC) {
! 1953: printf("osiop sync: params for period %dns: sxfer %x sbcl %x",
! 1954: period * 4, sxfer, sbcl);
! 1955: printf(" actual period %dns\n",
! 1956: sc->sc_tcp[sbcl] * ((sxfer >> 4) + 4));
! 1957: }
! 1958: #endif
! 1959: }
! 1960: sc->sc_tinfo[target].sxfer = sxfer;
! 1961: sc->sc_tinfo[target].sbcl = sbcl;
! 1962: #ifdef OSIOP_DEBUG
! 1963: if (osiop_debug & DEBUG_SYNC)
! 1964: printf("osiop sync: osiop_sxfr %02x, osiop_sbcl %02x\n",
! 1965: sxfer, sbcl);
! 1966: #endif
! 1967: }
! 1968:
! 1969: void
! 1970: osiop_timeout(arg)
! 1971: void *arg;
! 1972: {
! 1973: struct osiop_acb *acb = arg;
! 1974: struct scsi_xfer *xs = acb->xs;
! 1975: struct osiop_softc *sc = acb->sc;
! 1976: int s;
! 1977:
! 1978: sc_print_addr(xs->sc_link);
! 1979: printf("command 0x%02x timeout on xs %p\n", xs->cmd->opcode, xs);
! 1980:
! 1981: s = splbio();
! 1982: /* reset the scsi bus */
! 1983: osiop_resetbus(sc);
! 1984:
! 1985: acb->flags |= ACB_F_TIMEOUT;
! 1986: osiop_reset(sc);
! 1987: splx(s);
! 1988: return;
! 1989: }
! 1990:
! 1991: #ifdef OSIOP_DEBUG
! 1992:
! 1993: #if OSIOP_TRACE_SIZE
! 1994: void
! 1995: osiop_dump_trace()
! 1996: {
! 1997: int i;
! 1998:
! 1999: printf("osiop trace: next index %d\n", osiop_trix);
! 2000: i = osiop_trix;
! 2001: do {
! 2002: printf("%3d: '%c' %02x %02x %02x\n", i,
! 2003: osiop_trbuf[i], osiop_trbuf[i + 1],
! 2004: osiop_trbuf[i + 2], osiop_trbuf[i + 3]);
! 2005: i = (i + 4) & (OSIOP_TRACE_SIZE - 1);
! 2006: } while (i != osiop_trix);
! 2007: }
! 2008: #endif
! 2009:
! 2010: void
! 2011: osiop_dump_acb(acb)
! 2012: struct osiop_acb *acb;
! 2013: {
! 2014: u_int8_t *b;
! 2015: int i;
! 2016:
! 2017: printf("acb@%p ", acb);
! 2018: if (acb->xs == NULL) {
! 2019: printf("<unused>\n");
! 2020: return;
! 2021: }
! 2022:
! 2023: b = (u_int8_t *)&acb->ds->scsi_cmd;
! 2024: printf("(%d:%d) status %2x cmdlen %2ld cmd ",
! 2025: acb->xs->sc_link->target,
! 2026: acb->xs->sc_link->lun,
! 2027: acb->status,
! 2028: acb->ds->cmd.count);
! 2029: for (i = acb->ds->cmd.count; i > 0; i--)
! 2030: printf(" %02x", *b++);
! 2031: printf("\n");
! 2032: printf(" xs: %p data %p:%04x ", acb->xs, acb->data,
! 2033: acb->datalen);
! 2034: printf("cur %lx:%lx\n", acb->curaddr, acb->curlen);
! 2035: }
! 2036:
! 2037: void
! 2038: osiop_dump(sc)
! 2039: struct osiop_softc *sc;
! 2040: {
! 2041: struct osiop_acb *acb;
! 2042: int i, s;
! 2043:
! 2044: s = splbio();
! 2045: #if OSIOP_TRACE_SIZE
! 2046: osiop_dump_trace();
! 2047: #endif
! 2048: printf("%s@%p istat %02x\n",
! 2049: sc->sc_dev.dv_xname, sc, osiop_read_1(sc, OSIOP_ISTAT));
! 2050: if ((acb = TAILQ_FIRST(&sc->free_list)) != NULL) {
! 2051: printf("Free list:\n");
! 2052: while (acb) {
! 2053: osiop_dump_acb(acb);
! 2054: acb = TAILQ_NEXT(acb, chain);
! 2055: }
! 2056: }
! 2057: if ((acb = TAILQ_FIRST(&sc->ready_list)) != NULL) {
! 2058: printf("Ready list:\n");
! 2059: while (acb) {
! 2060: osiop_dump_acb(acb);
! 2061: acb = TAILQ_NEXT(acb, chain);
! 2062: }
! 2063: }
! 2064: if ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
! 2065: printf("Nexus list:\n");
! 2066: while (acb) {
! 2067: osiop_dump_acb(acb);
! 2068: acb = TAILQ_NEXT(acb, chain);
! 2069: }
! 2070: }
! 2071: if (sc->sc_nexus) {
! 2072: printf("Nexus:\n");
! 2073: osiop_dump_acb(sc->sc_nexus);
! 2074: }
! 2075: for (i = 0; i < OSIOP_NTGT; i++) {
! 2076: if (sc->sc_tinfo[i].cmds > 2) {
! 2077: printf("tgt %d: cmds %d disc %d lubusy %x\n",
! 2078: i, sc->sc_tinfo[i].cmds,
! 2079: sc->sc_tinfo[i].dconns,
! 2080: sc->sc_tinfo[i].lubusy);
! 2081: }
! 2082: }
! 2083: splx(s);
! 2084: }
! 2085: #endif
CVSweb