Annotation of sys/arch/macppc/dev/mesh.c, Revision 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