Annotation of sys/dev/ic/ncr53c9x.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: ncr53c9x.c,v 1.34 2007/08/06 08:28:09 tom Exp $ */
! 2: /* $NetBSD: ncr53c9x.c,v 1.56 2000/11/30 14:41:46 thorpej Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 1996 Charles M. Hannum. 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. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Charles M. Hannum.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: /*
! 34: * Copyright (c) 1994 Peter Galbavy
! 35: * Copyright (c) 1995 Paul Kranenburg
! 36: * All rights reserved.
! 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: *
! 47: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 48: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 49: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 50: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 51: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 52: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 53: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 54: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 55: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 56: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 57: * POSSIBILITY OF SUCH DAMAGE.
! 58: */
! 59:
! 60: /*
! 61: * Based on aic6360 by Jarle Greipsland
! 62: *
! 63: * Acknowledgements: Many of the algorithms used in this driver are
! 64: * inspired by the work of Julian Elischer (julian@tfs.com) and
! 65: * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
! 66: */
! 67:
! 68: #include <sys/types.h>
! 69: #include <sys/param.h>
! 70: #include <sys/systm.h>
! 71: #include <sys/kernel.h>
! 72: #include <sys/errno.h>
! 73: #include <sys/ioctl.h>
! 74: #include <sys/device.h>
! 75: #include <sys/buf.h>
! 76: #include <sys/malloc.h>
! 77: #include <sys/proc.h>
! 78: #include <sys/user.h>
! 79: #include <sys/queue.h>
! 80: #include <sys/pool.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:
! 88: #include <dev/ic/ncr53c9xreg.h>
! 89: #include <dev/ic/ncr53c9xvar.h>
! 90:
! 91: #ifdef NCR53C9X_DEBUG
! 92: int ncr53c9x_debug = 0; /*NCR_SHOWPHASE|NCR_SHOWMISC|NCR_SHOWTRAC|NCR_SHOWCMDS;*/
! 93: #endif
! 94: #ifdef DEBUG
! 95: int ncr53c9x_notag = 0;
! 96: #endif
! 97:
! 98: /*static*/ void ncr53c9x_readregs(struct ncr53c9x_softc *);
! 99: /*static*/ void ncr53c9x_select(struct ncr53c9x_softc *,
! 100: struct ncr53c9x_ecb *);
! 101: /*static*/ int ncr53c9x_reselect(struct ncr53c9x_softc *, int, int, int);
! 102: /*static*/ void ncr53c9x_scsi_reset(struct ncr53c9x_softc *);
! 103: /*static*/ int ncr53c9x_poll(struct ncr53c9x_softc *,
! 104: struct scsi_xfer *, int);
! 105: /*static*/ void ncr53c9x_sched(struct ncr53c9x_softc *);
! 106: /*static*/ void ncr53c9x_done(struct ncr53c9x_softc *,
! 107: struct ncr53c9x_ecb *);
! 108: /*static*/ void ncr53c9x_msgin(struct ncr53c9x_softc *);
! 109: /*static*/ void ncr53c9x_msgout(struct ncr53c9x_softc *);
! 110: /*static*/ void ncr53c9x_timeout(void *arg);
! 111: /*static*/ void ncr53c9x_watch(void *arg);
! 112: /*static*/ void ncr53c9x_abort(struct ncr53c9x_softc *,
! 113: struct ncr53c9x_ecb *);
! 114: /*static*/ void ncr53c9x_dequeue(struct ncr53c9x_softc *,
! 115: struct ncr53c9x_ecb *);
! 116:
! 117: void ncr53c9x_sense(struct ncr53c9x_softc *,
! 118: struct ncr53c9x_ecb *);
! 119: void ncr53c9x_free_ecb(struct ncr53c9x_softc *,
! 120: struct ncr53c9x_ecb *, int);
! 121: struct ncr53c9x_ecb *ncr53c9x_get_ecb(struct ncr53c9x_softc *, int);
! 122:
! 123: static inline int ncr53c9x_stp2cpb(struct ncr53c9x_softc *, int);
! 124: static inline void ncr53c9x_setsync(struct ncr53c9x_softc *,
! 125: struct ncr53c9x_tinfo *);
! 126: static struct ncr53c9x_linfo *ncr53c9x_lunsearch(struct ncr53c9x_tinfo *,
! 127: int64_t lun);
! 128:
! 129: static void ncr53c9x_wrfifo(struct ncr53c9x_softc *, u_char *, int);
! 130: static int ncr53c9x_rdfifo(struct ncr53c9x_softc *, int);
! 131: #define NCR_RDFIFO_START 0
! 132: #define NCR_RDFIFO_CONTINUE 1
! 133:
! 134: #define NCR_SET_COUNT(sc, size) do { \
! 135: NCR_WRITE_REG((sc), NCR_TCL, (size)); \
! 136: NCR_WRITE_REG((sc), NCR_TCM, (size) >> 8); \
! 137: if ((sc->sc_cfg2 & NCRCFG2_FE) || \
! 138: (sc->sc_rev == NCR_VARIANT_FAS366)) { \
! 139: NCR_WRITE_REG((sc), NCR_TCH, (size) >> 16); \
! 140: } \
! 141: if (sc->sc_rev == NCR_VARIANT_FAS366) { \
! 142: NCR_WRITE_REG(sc, NCR_RCH, 0); \
! 143: } \
! 144: } while (0)
! 145:
! 146: static int ecb_pool_initialized = 0;
! 147: static struct pool ecb_pool;
! 148:
! 149: struct cfdriver esp_cd = {
! 150: NULL, "esp", DV_DULL
! 151: };
! 152:
! 153: /*
! 154: * Names for the NCR53c9x variants, corresponding to the variant tags
! 155: * in ncr53c9xvar.h.
! 156: */
! 157: const char *ncr53c9x_variant_names[] = {
! 158: "ESP100",
! 159: "ESP100A",
! 160: "ESP200",
! 161: "NCR53C94",
! 162: "NCR53C96",
! 163: "ESP406",
! 164: "FAS408",
! 165: "FAS216",
! 166: "AM53C974",
! 167: "FAS366/HME",
! 168: };
! 169:
! 170: /*
! 171: * Search linked list for LUN info by LUN id.
! 172: */
! 173: static struct ncr53c9x_linfo *
! 174: ncr53c9x_lunsearch(ti, lun)
! 175: struct ncr53c9x_tinfo *ti;
! 176: int64_t lun;
! 177: {
! 178: struct ncr53c9x_linfo *li;
! 179: LIST_FOREACH(li, &ti->luns, link)
! 180: if (li->lun == lun)
! 181: return (li);
! 182: return (NULL);
! 183: }
! 184:
! 185: /*
! 186: * Attach this instance, and then all the sub-devices
! 187: */
! 188: void
! 189: ncr53c9x_attach(sc, adapter, dev)
! 190: struct ncr53c9x_softc *sc;
! 191: struct scsi_adapter *adapter;
! 192: struct scsi_device *dev;
! 193: {
! 194: struct scsibus_attach_args saa;
! 195:
! 196: timeout_set(&sc->sc_watchdog, ncr53c9x_watch, sc);
! 197: /*
! 198: * Allocate SCSI message buffers.
! 199: * Front-ends can override allocation to avoid alignment
! 200: * handling in the DMA engines. Note that ncr53c9x_msgout()
! 201: * can request a 1 byte DMA transfer.
! 202: */
! 203: if (sc->sc_omess == NULL)
! 204: sc->sc_omess = malloc(NCR_MAX_MSG_LEN, M_DEVBUF, M_NOWAIT);
! 205:
! 206: if (sc->sc_imess == NULL)
! 207: sc->sc_imess = malloc(NCR_MAX_MSG_LEN+1, M_DEVBUF, M_NOWAIT);
! 208:
! 209: if (sc->sc_omess == NULL || sc->sc_imess == NULL) {
! 210: printf("out of memory\n");
! 211: return;
! 212: }
! 213:
! 214: /*
! 215: * Note, the front-end has set us up to print the chip variation.
! 216: */
! 217: if (sc->sc_rev >= NCR_VARIANT_MAX) {
! 218: printf("\n%s: unknown variant %d, devices not attached\n",
! 219: sc->sc_dev.dv_xname, sc->sc_rev);
! 220: return;
! 221: }
! 222:
! 223: printf(": %s, %dMHz, SCSI ID %d\n",
! 224: ncr53c9x_variant_names[sc->sc_rev], sc->sc_freq, sc->sc_id);
! 225:
! 226: sc->sc_ccf = FREQTOCCF(sc->sc_freq);
! 227:
! 228: /* The value *must not* be == 1. Make it 2 */
! 229: if (sc->sc_ccf == 1)
! 230: sc->sc_ccf = 2;
! 231:
! 232: /*
! 233: * The recommended timeout is 250ms. This register is loaded
! 234: * with a value calculated as follows, from the docs:
! 235: *
! 236: * (timout period) x (CLK frequency)
! 237: * reg = -------------------------------------
! 238: * 8192 x (Clock Conversion Factor)
! 239: *
! 240: * Since CCF has a linear relation to CLK, this generally computes
! 241: * to the constant of 153.
! 242: */
! 243: sc->sc_timeout = ((250 * 1000) * sc->sc_freq) / (8192 * sc->sc_ccf);
! 244:
! 245: /* CCF register only has 3 bits; 0 is actually 8 */
! 246: sc->sc_ccf &= 7;
! 247:
! 248: /* Find how many targets we need to support */
! 249: switch (sc->sc_rev) {
! 250: case NCR_VARIANT_FAS366:
! 251: sc->sc_ntarg = 16;
! 252: break;
! 253: default:
! 254: sc->sc_ntarg = 8;
! 255: break;
! 256: }
! 257:
! 258: /* Reset state & bus */
! 259: sc->sc_cfflags = sc->sc_dev.dv_cfdata->cf_flags;
! 260: sc->sc_state = 0;
! 261: ncr53c9x_init(sc, 1);
! 262:
! 263: /*
! 264: * fill in the prototype scsi_link.
! 265: */
! 266: sc->sc_link.adapter_softc = sc;
! 267: sc->sc_link.adapter_target = sc->sc_id;
! 268: sc->sc_link.adapter = adapter;
! 269: sc->sc_link.device = dev;
! 270: sc->sc_link.openings = 2;
! 271: sc->sc_link.adapter_buswidth = sc->sc_ntarg;
! 272:
! 273: bzero(&saa, sizeof(saa));
! 274: saa.saa_sc_link = &sc->sc_link;
! 275:
! 276: /*
! 277: * Now try to attach all the sub-devices
! 278: */
! 279: config_found(&sc->sc_dev, &saa, scsiprint);
! 280: timeout_add(&sc->sc_watchdog, 60*hz);
! 281: }
! 282:
! 283: /*
! 284: * This is the generic ncr53c9x reset function. It does not reset the SCSI bus,
! 285: * only this controller, but kills any on-going commands, and also stops
! 286: * and resets the DMA.
! 287: *
! 288: * After reset, registers are loaded with the defaults from the attach
! 289: * routine above.
! 290: */
! 291: void
! 292: ncr53c9x_reset(sc)
! 293: struct ncr53c9x_softc *sc;
! 294: {
! 295:
! 296: /* reset DMA first */
! 297: NCRDMA_RESET(sc);
! 298:
! 299: /* reset SCSI chip */
! 300: NCRCMD(sc, NCRCMD_RSTCHIP);
! 301: NCRCMD(sc, NCRCMD_NOP);
! 302: DELAY(500);
! 303:
! 304: /* do these backwards, and fall through */
! 305: switch (sc->sc_rev) {
! 306: case NCR_VARIANT_ESP406:
! 307: case NCR_VARIANT_FAS408:
! 308: NCR_WRITE_REG(sc, NCR_CFG5, sc->sc_cfg5 | NCRCFG5_SINT);
! 309: NCR_WRITE_REG(sc, NCR_CFG4, sc->sc_cfg4);
! 310: case NCR_VARIANT_AM53C974:
! 311: case NCR_VARIANT_FAS216:
! 312: case NCR_VARIANT_NCR53C94:
! 313: case NCR_VARIANT_NCR53C96:
! 314: case NCR_VARIANT_ESP200:
! 315: sc->sc_features |= NCR_F_HASCFG3;
! 316: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
! 317: case NCR_VARIANT_ESP100A:
! 318: sc->sc_features |= NCR_F_SELATN3;
! 319: NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
! 320: case NCR_VARIANT_ESP100:
! 321: NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
! 322: NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf);
! 323: NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
! 324: NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
! 325: break;
! 326: case NCR_VARIANT_FAS366:
! 327: sc->sc_features |=
! 328: NCR_F_SELATN3 | NCR_F_HASCFG3 | NCR_F_FASTSCSI;
! 329: sc->sc_cfg3 = NCRFASCFG3_FASTCLK | NCRFASCFG3_OBAUTO;
! 330: sc->sc_cfg3_fscsi = NCRFASCFG3_FASTSCSI;
! 331: NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
! 332: sc->sc_cfg2 = 0; /* NCRCFG2_HMEFE | NCRCFG2_HME32 */
! 333: NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
! 334: NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
! 335: NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf);
! 336: NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
! 337: NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
! 338: break;
! 339: default:
! 340: printf("%s: unknown revision code, assuming ESP100\n",
! 341: sc->sc_dev.dv_xname);
! 342: NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
! 343: NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf);
! 344: NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
! 345: NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
! 346: }
! 347:
! 348: if (sc->sc_rev == NCR_VARIANT_AM53C974)
! 349: NCR_WRITE_REG(sc, NCR_AMDCFG4, sc->sc_cfg4);
! 350:
! 351: #if 0
! 352: printf("%s: ncr53c9x_reset: revision %d\n",
! 353: sc->sc_dev.dv_xname, sc->sc_rev);
! 354: printf("%s: ncr53c9x_reset: cfg1 0x%x, cfg2 0x%x, cfg3 0x%x, ccf 0x%x, timeout 0x%x\n",
! 355: sc->sc_dev.dv_xname,
! 356: sc->sc_cfg1, sc->sc_cfg2, sc->sc_cfg3,
! 357: sc->sc_ccf, sc->sc_timeout);
! 358: #endif
! 359: }
! 360:
! 361: /*
! 362: * Reset the SCSI bus, but not the chip
! 363: */
! 364: void
! 365: ncr53c9x_scsi_reset(sc)
! 366: struct ncr53c9x_softc *sc;
! 367: {
! 368:
! 369: (*sc->sc_glue->gl_dma_stop)(sc);
! 370:
! 371: printf("%s: resetting SCSI bus\n", sc->sc_dev.dv_xname);
! 372: NCRCMD(sc, NCRCMD_RSTSCSI);
! 373: }
! 374:
! 375: /*
! 376: * Initialize ncr53c9x state machine
! 377: */
! 378: void
! 379: ncr53c9x_init(sc, doreset)
! 380: struct ncr53c9x_softc *sc;
! 381: int doreset;
! 382: {
! 383: struct ncr53c9x_ecb *ecb;
! 384: struct ncr53c9x_linfo *li;
! 385: int r, i;
! 386:
! 387: NCR_TRACE(("[NCR_INIT(%d) %d] ", doreset, sc->sc_state));
! 388:
! 389: if (!ecb_pool_initialized) {
! 390: /* All instances share this pool */
! 391: pool_init(&ecb_pool, sizeof(struct ncr53c9x_ecb), 0, 0, 0,
! 392: "ncr53c9x_ecb", NULL);
! 393: ecb_pool_initialized = 1;
! 394: }
! 395:
! 396: if (sc->sc_state == 0) {
! 397: /* First time through; initialize. */
! 398:
! 399: TAILQ_INIT(&sc->ready_list);
! 400: sc->sc_nexus = NULL;
! 401: bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
! 402: for (r = 0; r < sc->sc_ntarg; r++) {
! 403: LIST_INIT(&sc->sc_tinfo[r].luns);
! 404: }
! 405: } else {
! 406: /* Cancel any active commands. */
! 407: sc->sc_state = NCR_CLEANING;
! 408: sc->sc_msgify = 0;
! 409: if ((ecb = sc->sc_nexus) != NULL) {
! 410: ecb->xs->error = XS_TIMEOUT;
! 411: ncr53c9x_done(sc, ecb);
! 412: }
! 413: for (r = 0; r < sc->sc_ntarg; r++) {
! 414: LIST_FOREACH(li, &sc->sc_tinfo[r].luns, link) {
! 415: if ((ecb = li->untagged)) {
! 416: li->untagged = NULL;
! 417: /*
! 418: * XXXXXXX
! 419: * Should we terminate a command
! 420: * that never reached the disk?
! 421: */
! 422: li->busy = 0;
! 423: ecb->xs->error = XS_TIMEOUT;
! 424: ncr53c9x_done(sc, ecb);
! 425: }
! 426: for (i = 0; i < 256; i++)
! 427: if ((ecb = li->queued[i])) {
! 428: li->queued[i] = NULL;
! 429: ecb->xs->error = XS_TIMEOUT;
! 430: ncr53c9x_done(sc, ecb);
! 431: }
! 432: li->used = 0;
! 433: }
! 434: }
! 435: }
! 436:
! 437: /*
! 438: * reset the chip to a known state
! 439: */
! 440: ncr53c9x_reset(sc);
! 441:
! 442: sc->sc_phase = sc->sc_prevphase = INVALID_PHASE;
! 443: for (r = 0; r < sc->sc_ntarg; r++) {
! 444: struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[r];
! 445: /* XXX - config flags per target: low bits: no reselect; high bits: no synch */
! 446:
! 447: ti->flags = ((!(sc->sc_cfflags & (1 << (r + 16))) &&
! 448: sc->sc_minsync) ? 0 : T_SYNCHOFF) |
! 449: ((sc->sc_cfflags & (1 << r)) ? T_RSELECTOFF : 0) |
! 450: T_NEED_TO_RESET;
! 451: #ifdef DEBUG
! 452: if (ncr53c9x_notag)
! 453: ti->flags &= ~T_TAG;
! 454: #endif
! 455: ti->period = sc->sc_minsync;
! 456: ti->offset = 0;
! 457: ti->cfg3 = 0;
! 458: }
! 459:
! 460: if (doreset) {
! 461: sc->sc_state = NCR_SBR;
! 462: NCRCMD(sc, NCRCMD_RSTSCSI);
! 463: /*
! 464: * XXX gross...
! 465: * On some systems, commands issued too close to a reset
! 466: * do not work correctly. We'll force a short delay on
! 467: * known-to-be-sensitive chips.
! 468: */
! 469: switch (sc->sc_rev) {
! 470: case NCR_VARIANT_NCR53C94:
! 471: DELAY(600000); /* 600ms */
! 472: break;
! 473: case NCR_VARIANT_NCR53C96:
! 474: DELAY(100000); /* 100ms */
! 475: break;
! 476: }
! 477: } else {
! 478: sc->sc_state = NCR_IDLE;
! 479: ncr53c9x_sched(sc);
! 480: }
! 481: }
! 482:
! 483: /*
! 484: * Read the NCR registers, and save their contents for later use.
! 485: * NCR_STAT, NCR_STEP & NCR_INTR are mostly zeroed out when reading
! 486: * NCR_INTR - so make sure it is the last read.
! 487: *
! 488: * I think that (from reading the docs) most bits in these registers
! 489: * only make sense when he DMA CSR has an interrupt showing. Call only
! 490: * if an interrupt is pending.
! 491: */
! 492: __inline__ void
! 493: ncr53c9x_readregs(sc)
! 494: struct ncr53c9x_softc *sc;
! 495: {
! 496:
! 497: sc->sc_espstat = NCR_READ_REG(sc, NCR_STAT);
! 498: /* Only the stepo bits are of interest */
! 499: sc->sc_espstep = NCR_READ_REG(sc, NCR_STEP) & NCRSTEP_MASK;
! 500:
! 501: if (sc->sc_rev == NCR_VARIANT_FAS366)
! 502: sc->sc_espstat2 = NCR_READ_REG(sc, NCR_STAT2);
! 503:
! 504: sc->sc_espintr = NCR_READ_REG(sc, NCR_INTR);
! 505:
! 506: if (sc->sc_glue->gl_clear_latched_intr != NULL)
! 507: (*sc->sc_glue->gl_clear_latched_intr)(sc);
! 508:
! 509: /*
! 510: * Determine the SCSI bus phase, return either a real SCSI bus phase
! 511: * or some pseudo phase we use to detect certain exceptions.
! 512: */
! 513:
! 514: sc->sc_phase = (sc->sc_espintr & NCRINTR_DIS)
! 515: ? /* Disconnected */ BUSFREE_PHASE
! 516: : sc->sc_espstat & NCRSTAT_PHASE;
! 517:
! 518: NCR_MISC(("regs[intr=%02x,stat=%02x,step=%02x,stat2=%02x] ",
! 519: sc->sc_espintr, sc->sc_espstat, sc->sc_espstep, sc->sc_espstat2));
! 520: }
! 521:
! 522: /*
! 523: * Convert Synchronous Transfer Period to chip register Clock Per Byte value.
! 524: */
! 525: static inline int
! 526: ncr53c9x_stp2cpb(sc, period)
! 527: struct ncr53c9x_softc *sc;
! 528: int period;
! 529: {
! 530: int v;
! 531: v = (sc->sc_freq * period) / 250;
! 532: if (ncr53c9x_cpb2stp(sc, v) < period)
! 533: /* Correct round-down error */
! 534: v++;
! 535: return (v);
! 536: }
! 537:
! 538: static inline void
! 539: ncr53c9x_setsync(sc, ti)
! 540: struct ncr53c9x_softc *sc;
! 541: struct ncr53c9x_tinfo *ti;
! 542: {
! 543: u_char syncoff, synctp;
! 544: u_char cfg3 = sc->sc_cfg3 | ti->cfg3;
! 545:
! 546: if (ti->flags & T_SYNCMODE) {
! 547: syncoff = ti->offset;
! 548: synctp = ncr53c9x_stp2cpb(sc, ti->period);
! 549: if (sc->sc_features & NCR_F_FASTSCSI) {
! 550: /*
! 551: * If the period is 200ns or less (ti->period <= 50),
! 552: * put the chip in Fast SCSI mode.
! 553: */
! 554: if (ti->period <= 50)
! 555: /*
! 556: * There are (at least) 4 variations of the
! 557: * configuration 3 register. The drive attach
! 558: * routine sets the appropriate bit to put the
! 559: * chip into Fast SCSI mode so that it doesn't
! 560: * have to be figured out here each time.
! 561: */
! 562: cfg3 |= (sc->sc_rev == NCR_VARIANT_AM53C974) ?
! 563: NCRAMDCFG3_FSCSI : NCRCFG3_FSCSI;
! 564: }
! 565:
! 566: /*
! 567: * Am53c974 requires different SYNCTP values when the
! 568: * FSCSI bit is off.
! 569: */
! 570: if (sc->sc_rev == NCR_VARIANT_AM53C974 &&
! 571: (cfg3 & NCRAMDCFG3_FSCSI) == 0)
! 572: synctp--;
! 573: } else {
! 574: syncoff = 0;
! 575: synctp = 0;
! 576: }
! 577:
! 578: if (sc->sc_features & NCR_F_HASCFG3)
! 579: NCR_WRITE_REG(sc, NCR_CFG3, cfg3);
! 580:
! 581: NCR_WRITE_REG(sc, NCR_SYNCOFF, syncoff);
! 582: NCR_WRITE_REG(sc, NCR_SYNCTP, synctp);
! 583: }
! 584:
! 585: /*
! 586: * Send a command to a target, set the driver state to NCR_SELECTING
! 587: * and let the caller take care of the rest.
! 588: *
! 589: * Keeping this as a function allows me to say that this may be done
! 590: * by DMA instead of programmed I/O soon.
! 591: */
! 592: void
! 593: ncr53c9x_select(sc, ecb)
! 594: struct ncr53c9x_softc *sc;
! 595: struct ncr53c9x_ecb *ecb;
! 596: {
! 597: struct scsi_link *sc_link = ecb->xs->sc_link;
! 598: int target = sc_link->target;
! 599: int lun = sc_link->lun;
! 600: struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[target];
! 601: int tiflags = ti->flags;
! 602: u_char *cmd;
! 603: int clen;
! 604: int selatn3, selatns;
! 605: size_t dmasize;
! 606:
! 607: NCR_TRACE(("[ncr53c9x_select(t%d,l%d,cmd:%x,tag%x,%x)] ",
! 608: target, lun, ecb->cmd.cmd.opcode, ecb->tag[0], ecb->tag[1]));
! 609:
! 610: sc->sc_state = NCR_SELECTING;
! 611: /*
! 612: * Schedule the timeout now, the first time we will go away
! 613: * expecting to come back due to an interrupt, because it is
! 614: * always possible that the interrupt may never happen.
! 615: */
! 616: if ((ecb->xs->flags & SCSI_POLL) == 0) {
! 617: int timeout = ecb->timeout;
! 618:
! 619: if (timeout > 1000000)
! 620: timeout = (timeout / 1000) * hz;
! 621: else
! 622: timeout = (timeout * hz) / 1000;
! 623: timeout_add(&ecb->to, timeout);
! 624: }
! 625:
! 626: /*
! 627: * The docs say the target register is never reset, and I
! 628: * can't think of a better place to set it
! 629: */
! 630: if (sc->sc_rev == NCR_VARIANT_FAS366) {
! 631: NCRCMD(sc, NCRCMD_FLUSH);
! 632: NCR_WRITE_REG(sc, NCR_SELID, target | NCR_BUSID_HME);
! 633: } else {
! 634: NCR_WRITE_REG(sc, NCR_SELID, target);
! 635: }
! 636: ncr53c9x_setsync(sc, ti);
! 637:
! 638: if ((ecb->flags & ECB_SENSE) != 0) {
! 639: /*
! 640: * For REQUEST SENSE, we should not send an IDENTIFY or
! 641: * otherwise mangle the target. There should be no MESSAGE IN
! 642: * phase.
! 643: */
! 644: if (sc->sc_features & NCR_F_DMASELECT) {
! 645: /* setup DMA transfer for command */
! 646: dmasize = clen = ecb->clen;
! 647: sc->sc_cmdlen = clen;
! 648: sc->sc_cmdp = (caddr_t)&ecb->cmd.cmd;
! 649:
! 650: NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0,
! 651: &dmasize);
! 652: /* Program the SCSI counter */
! 653: NCR_SET_COUNT(sc, dmasize);
! 654:
! 655: if (sc->sc_rev != NCR_VARIANT_FAS366)
! 656: NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
! 657:
! 658: /* And get the targets attention */
! 659: NCRCMD(sc, NCRCMD_SELNATN | NCRCMD_DMA);
! 660: NCRDMA_GO(sc);
! 661: } else {
! 662: ncr53c9x_wrfifo(sc, (u_char *)&ecb->cmd.cmd, ecb->clen);
! 663: NCRCMD(sc, NCRCMD_SELNATN);
! 664: }
! 665: return;
! 666: }
! 667:
! 668: selatn3 = selatns = 0;
! 669: if (ecb->tag[0] != 0) {
! 670: if (sc->sc_features & NCR_F_SELATN3)
! 671: /* use SELATN3 to send tag messages */
! 672: selatn3 = 1;
! 673: else
! 674: /* We don't have SELATN3; use SELATNS to send tags */
! 675: selatns = 1;
! 676: }
! 677:
! 678: if (ti->flags & T_NEGOTIATE) {
! 679: /* We have to use SELATNS to send sync/wide messages */
! 680: selatn3 = 0;
! 681: selatns = 1;
! 682: }
! 683:
! 684: cmd = (u_char *)&ecb->cmd.cmd;
! 685:
! 686: if (selatn3) {
! 687: /* We'll use tags with SELATN3 */
! 688: clen = ecb->clen + 3;
! 689: cmd -= 3;
! 690: cmd[0] = MSG_IDENTIFY(lun, 1); /* msg[0] */
! 691: cmd[1] = ecb->tag[0]; /* msg[1] */
! 692: cmd[2] = ecb->tag[1]; /* msg[2] */
! 693: } else {
! 694: /* We don't have tags, or will send messages with SELATNS */
! 695: clen = ecb->clen + 1;
! 696: cmd -= 1;
! 697: cmd[0] = MSG_IDENTIFY(lun, (tiflags & T_RSELECTOFF) == 0);
! 698: }
! 699:
! 700: if ((sc->sc_features & NCR_F_DMASELECT) && !selatns) {
! 701:
! 702: /* setup DMA transfer for command */
! 703: dmasize = clen;
! 704: sc->sc_cmdlen = clen;
! 705: sc->sc_cmdp = cmd;
! 706:
! 707: NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmasize);
! 708: /* Program the SCSI counter */
! 709: NCR_SET_COUNT(sc, dmasize);
! 710:
! 711: /* load the count in */
! 712: /* if (sc->sc_rev != NCR_VARIANT_FAS366) */
! 713: NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
! 714:
! 715: /* And get the targets attention */
! 716: if (selatn3) {
! 717: sc->sc_msgout = SEND_TAG;
! 718: sc->sc_flags |= NCR_ATN;
! 719: NCRCMD(sc, NCRCMD_SELATN3 | NCRCMD_DMA);
! 720: } else
! 721: NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);
! 722: NCRDMA_GO(sc);
! 723: return;
! 724: }
! 725:
! 726: /*
! 727: * Who am I. This is where we tell the target that we are
! 728: * happy for it to disconnect etc.
! 729: */
! 730:
! 731: /* Now get the command into the FIFO */
! 732: ncr53c9x_wrfifo(sc, cmd, clen);
! 733:
! 734: /* And get the targets attention */
! 735: if (selatns) {
! 736: NCR_MISC(("SELATNS \n"));
! 737: /* Arbitrate, select and stop after IDENTIFY message */
! 738: NCRCMD(sc, NCRCMD_SELATNS);
! 739: } else if (selatn3) {
! 740: sc->sc_msgout = SEND_TAG;
! 741: sc->sc_flags |= NCR_ATN;
! 742: NCRCMD(sc, NCRCMD_SELATN3);
! 743: } else
! 744: NCRCMD(sc, NCRCMD_SELATN);
! 745: }
! 746:
! 747: void
! 748: ncr53c9x_free_ecb(sc, ecb, flags)
! 749: struct ncr53c9x_softc *sc;
! 750: struct ncr53c9x_ecb *ecb;
! 751: int flags;
! 752: {
! 753: int s;
! 754:
! 755: s = splbio();
! 756: ecb->flags = 0;
! 757: pool_put(&ecb_pool, (void *)ecb);
! 758: splx(s);
! 759: }
! 760:
! 761: struct ncr53c9x_ecb *
! 762: ncr53c9x_get_ecb(sc, flags)
! 763: struct ncr53c9x_softc *sc;
! 764: int flags;
! 765: {
! 766: struct ncr53c9x_ecb *ecb;
! 767: int s, wait = 0;
! 768:
! 769: if ((curproc != NULL) && ((flags & SCSI_NOSLEEP) == 0))
! 770: wait = PR_WAITOK;
! 771:
! 772: s = splbio();
! 773: ecb = (struct ncr53c9x_ecb *)pool_get(&ecb_pool, wait);
! 774: splx(s);
! 775: if (ecb == NULL)
! 776: return (NULL);
! 777: bzero(ecb, sizeof(*ecb));
! 778: timeout_set(&ecb->to, ncr53c9x_timeout, ecb);
! 779: ecb->flags |= ECB_ALLOC;
! 780: return (ecb);
! 781: }
! 782:
! 783: /*
! 784: * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS
! 785: */
! 786:
! 787: /*
! 788: * Start a SCSI-command
! 789: * This function is called by the higher level SCSI-driver to queue/run
! 790: * SCSI-commands.
! 791: */
! 792: int
! 793: ncr53c9x_scsi_cmd(xs)
! 794: struct scsi_xfer *xs;
! 795: {
! 796: struct scsi_link *sc_link = xs->sc_link;
! 797: struct ncr53c9x_softc *sc = sc_link->adapter_softc;
! 798: struct ncr53c9x_ecb *ecb;
! 799: struct ncr53c9x_tinfo *ti;
! 800: struct ncr53c9x_linfo *li;
! 801: int64_t lun = sc_link->lun;
! 802: int s, flags;
! 803:
! 804: NCR_TRACE(("[ncr53c9x_scsi_cmd] "));
! 805: NCR_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
! 806: sc_link->target));
! 807:
! 808: flags = xs->flags;
! 809: ti = &sc->sc_tinfo[sc_link->target];
! 810: li = TINFO_LUN(ti, lun);
! 811: if (li == NULL) {
! 812: /* Initialize LUN info and add to list. */
! 813: if ((li = malloc(sizeof(*li), M_DEVBUF, M_NOWAIT)) == NULL) {
! 814: return (TRY_AGAIN_LATER);
! 815: }
! 816: bzero(li, sizeof(*li));
! 817: li->last_used = time_second;
! 818: li->lun = lun;
! 819: s = splbio();
! 820: LIST_INSERT_HEAD(&ti->luns, li, link);
! 821: if (lun < NCR_NLUN)
! 822: ti->lun[lun] = li;
! 823: splx(s);
! 824: }
! 825:
! 826: if ((ecb = ncr53c9x_get_ecb(sc, flags)) == NULL)
! 827: return (TRY_AGAIN_LATER);
! 828:
! 829: /* Initialize ecb */
! 830: ecb->xs = xs;
! 831: ecb->timeout = xs->timeout;
! 832:
! 833: if (flags & SCSI_RESET) {
! 834: ecb->flags |= ECB_RESET;
! 835: ecb->clen = 0;
! 836: ecb->dleft = 0;
! 837: } else {
! 838: bcopy(xs->cmd, &ecb->cmd.cmd, xs->cmdlen);
! 839: ecb->clen = xs->cmdlen;
! 840: ecb->daddr = xs->data;
! 841: ecb->dleft = xs->datalen;
! 842: }
! 843: ecb->stat = 0;
! 844:
! 845: s = splbio();
! 846:
! 847: TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain);
! 848: ecb->flags |= ECB_READY;
! 849: if (sc->sc_state == NCR_IDLE)
! 850: ncr53c9x_sched(sc);
! 851:
! 852: splx(s);
! 853:
! 854: if ((flags & SCSI_POLL) == 0)
! 855: return (SUCCESSFULLY_QUEUED);
! 856:
! 857: /* Not allowed to use interrupts, use polling instead */
! 858: if (ncr53c9x_poll(sc, xs, ecb->timeout)) {
! 859: ncr53c9x_timeout(ecb);
! 860: if (ncr53c9x_poll(sc, xs, ecb->timeout))
! 861: ncr53c9x_timeout(ecb);
! 862: }
! 863: return (COMPLETE);
! 864: }
! 865:
! 866: /*
! 867: * Used when interrupt driven I/O isn't allowed, e.g. during boot.
! 868: */
! 869: int
! 870: ncr53c9x_poll(sc, xs, count)
! 871: struct ncr53c9x_softc *sc;
! 872: struct scsi_xfer *xs;
! 873: int count;
! 874: {
! 875:
! 876: NCR_TRACE(("[ncr53c9x_poll] "));
! 877: while (count) {
! 878: if (NCRDMA_ISINTR(sc)) {
! 879: ncr53c9x_intr(sc);
! 880: }
! 881: #if alternatively
! 882: if (NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT)
! 883: ncr53c9x_intr(sc);
! 884: #endif
! 885: if ((xs->flags & ITSDONE) != 0)
! 886: return (0);
! 887: if (sc->sc_state == NCR_IDLE) {
! 888: NCR_TRACE(("[ncr53c9x_poll: rescheduling] "));
! 889: ncr53c9x_sched(sc);
! 890: }
! 891: DELAY(1000);
! 892: count--;
! 893: }
! 894: return (1);
! 895: }
! 896:
! 897:
! 898: /*
! 899: * LOW LEVEL SCSI UTILITIES
! 900: */
! 901:
! 902: /*
! 903: * Schedule a scsi operation. This has now been pulled out of the interrupt
! 904: * handler so that we may call it from ncr53c9x_scsi_cmd and ncr53c9x_done.
! 905: * This may save us an unnecessary interrupt just to get things going.
! 906: * Should only be called when state == NCR_IDLE and at bio pl.
! 907: */
! 908: void
! 909: ncr53c9x_sched(sc)
! 910: struct ncr53c9x_softc *sc;
! 911: {
! 912: struct ncr53c9x_ecb *ecb;
! 913: struct scsi_link *sc_link;
! 914: struct ncr53c9x_tinfo *ti;
! 915: int lun;
! 916: struct ncr53c9x_linfo *li;
! 917: int s, tag;
! 918:
! 919: NCR_TRACE(("[ncr53c9x_sched] "));
! 920: if (sc->sc_state != NCR_IDLE)
! 921: panic("ncr53c9x_sched: not IDLE (state=%d)", sc->sc_state);
! 922:
! 923: /*
! 924: * Find first ecb in ready queue that is for a target/lunit
! 925: * combinations that is not busy.
! 926: */
! 927: TAILQ_FOREACH(ecb, &sc->ready_list, chain) {
! 928: sc_link = ecb->xs->sc_link;
! 929: ti = &sc->sc_tinfo[sc_link->target];
! 930: lun = sc_link->lun;
! 931:
! 932: /* Select type of tag for this command */
! 933: if ((ti->flags & (T_RSELECTOFF)) != 0)
! 934: tag = 0;
! 935: else if ((ti->flags & T_TAG) == 0)
! 936: tag = 0;
! 937: else if ((ecb->flags & ECB_SENSE) != 0)
! 938: tag = 0;
! 939: else if (ecb->xs->flags & SCSI_URGENT)
! 940: tag = MSG_HEAD_OF_Q_TAG;
! 941: else
! 942: tag = MSG_SIMPLE_Q_TAG;
! 943: #if 0
! 944: /* XXXX Use tags for polled commands? */
! 945: if (ecb->xs->flags & SCSI_POLL)
! 946: tag = 0;
! 947: #endif
! 948: s = splbio();
! 949: li = TINFO_LUN(ti, lun);
! 950: if (!li) {
! 951: /* Initialize LUN info and add to list. */
! 952: if ((li = malloc(sizeof(*li), M_DEVBUF, M_NOWAIT)) == NULL) {
! 953: splx(s);
! 954: continue;
! 955: }
! 956: bzero(li, sizeof(*li));
! 957: li->lun = lun;
! 958:
! 959: LIST_INSERT_HEAD(&ti->luns, li, link);
! 960: if (lun < NCR_NLUN)
! 961: ti->lun[lun] = li;
! 962: }
! 963: li->last_used = time_second;
! 964: if (!tag) {
! 965: /* Try to issue this as an un-tagged command */
! 966: if (!li->untagged)
! 967: li->untagged = ecb;
! 968: }
! 969: if (li->untagged) {
! 970: tag = 0;
! 971: if ((li->busy != 1) && !li->used) {
! 972: /* We need to issue this untagged command now */
! 973: ecb = li->untagged;
! 974: sc_link = ecb->xs->sc_link;
! 975: }
! 976: else {
! 977: /* Not ready yet */
! 978: splx(s);
! 979: continue;
! 980: }
! 981: }
! 982: ecb->tag[0] = tag;
! 983: if (tag) {
! 984: int i;
! 985:
! 986: /* Allocate a tag */
! 987: if (li->used == 255) {
! 988: /* no free tags */
! 989: splx(s);
! 990: continue;
! 991: }
! 992: /* Start from the last used location */
! 993: for (i=li->avail; i<256; i++) {
! 994: if (li->queued[i] == NULL)
! 995: break;
! 996: }
! 997: /* Couldn't find one, start again from the beginning */
! 998: if (i == 256) {
! 999: for (i = 0; i<256; i++) {
! 1000: if (li->queued[i] == NULL)
! 1001: break;
! 1002: }
! 1003: }
! 1004: #ifdef DIAGNOSTIC
! 1005: if (i == 256)
! 1006: panic("ncr53c9x_sched: tag alloc failure");
! 1007: #endif
! 1008:
! 1009: /* Save where to start next time. */
! 1010: li->avail = i+1;
! 1011: li->used++;
! 1012:
! 1013: li->queued[i] = ecb;
! 1014: ecb->tag[1] = i;
! 1015: }
! 1016: splx(s);
! 1017: if (li->untagged && (li->busy != 1)) {
! 1018: li->busy = 1;
! 1019: TAILQ_REMOVE(&sc->ready_list, ecb, chain);
! 1020: ecb->flags &= ~ECB_READY;
! 1021: sc->sc_nexus = ecb;
! 1022: ncr53c9x_select(sc, ecb);
! 1023: break;
! 1024: }
! 1025: if (!li->untagged && tag) {
! 1026: TAILQ_REMOVE(&sc->ready_list, ecb, chain);
! 1027: ecb->flags &= ~ECB_READY;
! 1028: sc->sc_nexus = ecb;
! 1029: ncr53c9x_select(sc, ecb);
! 1030: break;
! 1031: } else
! 1032: NCR_MISC(("%d:%d busy\n",
! 1033: sc_link->target,
! 1034: sc_link->lun));
! 1035: }
! 1036: }
! 1037:
! 1038: void
! 1039: ncr53c9x_sense(sc, ecb)
! 1040: struct ncr53c9x_softc *sc;
! 1041: struct ncr53c9x_ecb *ecb;
! 1042: {
! 1043: struct scsi_xfer *xs = ecb->xs;
! 1044: struct scsi_link *sc_link = xs->sc_link;
! 1045: struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[sc_link->target];
! 1046: struct scsi_sense *ss = (void *)&ecb->cmd.cmd;
! 1047: struct ncr53c9x_linfo *li;
! 1048: int lun = sc_link->lun;
! 1049:
! 1050: NCR_MISC(("requesting sense "));
! 1051: /* Next, setup a request sense command block */
! 1052: bzero(ss, sizeof(*ss));
! 1053: ss->opcode = REQUEST_SENSE;
! 1054: ss->byte2 = sc_link->lun << 5;
! 1055: ss->length = sizeof(struct scsi_sense_data);
! 1056: ecb->clen = sizeof(*ss);
! 1057: ecb->daddr = (char *)&xs->sense;
! 1058: ecb->dleft = sizeof(struct scsi_sense_data);
! 1059: ecb->flags |= ECB_SENSE;
! 1060: ecb->timeout = NCR_SENSE_TIMEOUT;
! 1061: ti->senses++;
! 1062: li = TINFO_LUN(ti, lun);
! 1063: if (li->busy) li->busy = 0;
! 1064: ncr53c9x_dequeue(sc, ecb);
! 1065: li->untagged = ecb;
! 1066: li->busy = 2;
! 1067: if (ecb == sc->sc_nexus) {
! 1068: ncr53c9x_select(sc, ecb);
! 1069: } else {
! 1070: TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
! 1071: ecb->flags |= ECB_READY;
! 1072: if (sc->sc_state == NCR_IDLE)
! 1073: ncr53c9x_sched(sc);
! 1074: }
! 1075: }
! 1076:
! 1077: /*
! 1078: * POST PROCESSING OF SCSI_CMD (usually current)
! 1079: */
! 1080: void
! 1081: ncr53c9x_done(sc, ecb)
! 1082: struct ncr53c9x_softc *sc;
! 1083: struct ncr53c9x_ecb *ecb;
! 1084: {
! 1085: struct scsi_xfer *xs = ecb->xs;
! 1086: struct scsi_link *sc_link = xs->sc_link;
! 1087: struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[sc_link->target];
! 1088: int lun = sc_link->lun;
! 1089: struct ncr53c9x_linfo *li = TINFO_LUN(ti, lun);
! 1090:
! 1091: NCR_TRACE(("[ncr53c9x_done(error:%x)] ", xs->error));
! 1092:
! 1093: timeout_del(&ecb->to);
! 1094:
! 1095: if (ecb->stat == SCSI_QUEUE_FULL) {
! 1096: /*
! 1097: * Set current throttle -- we should reset
! 1098: * this periodically
! 1099: */
! 1100: sc_link->openings = li->used - 1;
! 1101: printf("\n%s: QFULL -- throttling to %d commands\n",
! 1102: sc->sc_dev.dv_xname, sc_link->openings);
! 1103: }
! 1104:
! 1105: /*
! 1106: * Now, if we've come here with no error code, i.e. we've kept the
! 1107: * initial XS_NOERROR, and the status code signals that we should
! 1108: * check sense, we'll need to set up a request sense cmd block and
! 1109: * push the command back into the ready queue *before* any other
! 1110: * commands for this target/lunit, else we lose the sense info.
! 1111: * We don't support chk sense conditions for the request sense cmd.
! 1112: */
! 1113: if (xs->error == XS_NOERROR) {
! 1114: xs->status = ecb->stat;
! 1115: if ((ecb->flags & ECB_ABORT) != 0) {
! 1116: xs->error = XS_TIMEOUT;
! 1117: } else if ((ecb->flags & ECB_SENSE) != 0) {
! 1118: xs->error = XS_SENSE;
! 1119: } else if ((ecb->stat & ST_MASK) == SCSI_CHECK) {
! 1120: /* First, save the return values */
! 1121: xs->resid = ecb->dleft;
! 1122: ncr53c9x_sense(sc, ecb);
! 1123: return;
! 1124: } else {
! 1125: xs->resid = ecb->dleft;
! 1126: }
! 1127: }
! 1128:
! 1129: xs->flags |= ITSDONE;
! 1130:
! 1131: #ifdef NCR53C9X_DEBUG
! 1132: if (ncr53c9x_debug & NCR_SHOWMISC) {
! 1133: if (xs->resid != 0)
! 1134: printf("resid=%lu ", (unsigned long)xs->resid);
! 1135: if (xs->error == XS_SENSE)
! 1136: printf("sense=0x%02x\n", xs->sense.error_code);
! 1137: else
! 1138: printf("error=%d\n", xs->error);
! 1139: }
! 1140: #endif
! 1141:
! 1142: /*
! 1143: * Remove the ECB from whatever queue it's on.
! 1144: */
! 1145: ncr53c9x_dequeue(sc, ecb);
! 1146: if (ecb == sc->sc_nexus) {
! 1147: sc->sc_nexus = NULL;
! 1148: if (sc->sc_state != NCR_CLEANING) {
! 1149: sc->sc_state = NCR_IDLE;
! 1150: ncr53c9x_sched(sc);
! 1151: }
! 1152: }
! 1153:
! 1154: if (xs->error == XS_SELTIMEOUT) {
! 1155: /* Selection timeout -- discard this LUN if empty */
! 1156: if (!li->untagged && !li->used) {
! 1157: if (lun < NCR_NLUN)
! 1158: ti->lun[lun] = NULL;
! 1159: LIST_REMOVE(li, link);
! 1160: free(li, M_DEVBUF);
! 1161: }
! 1162: }
! 1163:
! 1164: ncr53c9x_free_ecb(sc, ecb, xs->flags);
! 1165: ti->cmds++;
! 1166: scsi_done(xs);
! 1167: }
! 1168:
! 1169: void
! 1170: ncr53c9x_dequeue(sc, ecb)
! 1171: struct ncr53c9x_softc *sc;
! 1172: struct ncr53c9x_ecb *ecb;
! 1173: {
! 1174: struct ncr53c9x_tinfo *ti =
! 1175: &sc->sc_tinfo[ecb->xs->sc_link->target];
! 1176: struct ncr53c9x_linfo *li;
! 1177: int64_t lun = ecb->xs->sc_link->lun;
! 1178:
! 1179: li = TINFO_LUN(ti, lun);
! 1180: #ifdef DIAGNOSTIC
! 1181: if ((!li) || (li->lun != lun))
! 1182: panic("ncr53c9x_dequeue: lun %qx for ecb %p does not exist",
! 1183: (long long)lun, ecb);
! 1184: #endif
! 1185: if (li->untagged == ecb) {
! 1186: li->busy = 0;
! 1187: li->untagged = NULL;
! 1188: }
! 1189: if (ecb->tag[0] && li->queued[ecb->tag[1]]) {
! 1190: #ifdef DIAGNOSTIC
! 1191: if (li->queued[ecb->tag[1]] && (li->queued[ecb->tag[1]] != ecb))
! 1192: panic("ncr53c9x_dequeue: slot %d for lun %qx has %p "
! 1193: "instead of ecb %p", ecb->tag[1],
! 1194: (long long)lun,
! 1195: li->queued[ecb->tag[1]], ecb);
! 1196: #endif
! 1197: li->queued[ecb->tag[1]] = NULL;
! 1198: li->used --;
! 1199:
! 1200: }
! 1201: if (ecb->flags & ECB_READY) {
! 1202: ecb->flags &= ~ECB_READY;
! 1203: TAILQ_REMOVE(&sc->ready_list, ecb, chain);
! 1204: }
! 1205: }
! 1206:
! 1207: /*
! 1208: * INTERRUPT/PROTOCOL ENGINE
! 1209: */
! 1210:
! 1211: /*
! 1212: * Schedule an outgoing message by prioritizing it, and asserting
! 1213: * attention on the bus. We can only do this when we are the initiator
! 1214: * else there will be an illegal command interrupt.
! 1215: */
! 1216: #define ncr53c9x_sched_msgout(m) \
! 1217: do { \
! 1218: NCR_MISC(("ncr53c9x_sched_msgout %x %d ", m, __LINE__)); \
! 1219: NCRCMD(sc, NCRCMD_SETATN); \
! 1220: sc->sc_flags |= NCR_ATN; \
! 1221: sc->sc_msgpriq |= (m); \
! 1222: } while (0)
! 1223:
! 1224: static void
! 1225: ncr53c9x_flushfifo(struct ncr53c9x_softc *sc)
! 1226: {
! 1227: NCR_MISC(("[flushfifo] "));
! 1228:
! 1229: NCRCMD(sc, NCRCMD_FLUSH);
! 1230:
! 1231: if (sc->sc_phase == COMMAND_PHASE ||
! 1232: sc->sc_phase == MESSAGE_OUT_PHASE)
! 1233: DELAY(2);
! 1234: }
! 1235:
! 1236: static int
! 1237: ncr53c9x_rdfifo(struct ncr53c9x_softc *sc, int how)
! 1238: {
! 1239: int i, n;
! 1240: u_char *buf;
! 1241:
! 1242: switch(how) {
! 1243: case NCR_RDFIFO_START:
! 1244: buf = sc->sc_imess;
! 1245: sc->sc_imlen = 0;
! 1246: break;
! 1247: case NCR_RDFIFO_CONTINUE:
! 1248: buf = sc->sc_imess + sc->sc_imlen;
! 1249: break;
! 1250: default:
! 1251: panic("ncr53c9x_rdfifo: bad flag");
! 1252: break;
! 1253: }
! 1254:
! 1255: /*
! 1256: * XXX buffer (sc_imess) size for message
! 1257: */
! 1258:
! 1259: n = NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF;
! 1260:
! 1261: if (sc->sc_rev == NCR_VARIANT_FAS366) {
! 1262: n *= 2;
! 1263:
! 1264: for (i = 0; i < n; i++)
! 1265: buf[i] = NCR_READ_REG(sc, NCR_FIFO);
! 1266:
! 1267: if (sc->sc_espstat2 & FAS_STAT2_ISHUTTLE) {
! 1268:
! 1269: NCR_WRITE_REG(sc, NCR_FIFO, 0);
! 1270: buf[i++] = NCR_READ_REG(sc, NCR_FIFO);
! 1271:
! 1272: NCR_READ_REG(sc, NCR_FIFO);
! 1273:
! 1274: ncr53c9x_flushfifo(sc);
! 1275: }
! 1276: } else {
! 1277: for (i = 0; i < n; i++)
! 1278: buf[i] = NCR_READ_REG(sc, NCR_FIFO);
! 1279: }
! 1280:
! 1281: sc->sc_imlen += i;
! 1282:
! 1283: #ifdef NCR53C9X_DEBUG
! 1284: {
! 1285: int j;
! 1286:
! 1287: NCR_TRACE(("\n[rdfifo %s (%d):",
! 1288: (how == NCR_RDFIFO_START) ? "start" : "cont",
! 1289: (int)sc->sc_imlen));
! 1290: if (ncr53c9x_debug & NCR_SHOWTRAC) {
! 1291: for (j = 0; j < sc->sc_imlen; j++)
! 1292: printf(" %02x", sc->sc_imess[j]);
! 1293: printf("]\n");
! 1294: }
! 1295: }
! 1296: #endif
! 1297: return sc->sc_imlen;
! 1298: }
! 1299:
! 1300: static void
! 1301: ncr53c9x_wrfifo(struct ncr53c9x_softc *sc, u_char *p, int len)
! 1302: {
! 1303: int i;
! 1304:
! 1305: #ifdef NCR53C9X_DEBUG
! 1306: NCR_MISC(("[wrfifo(%d):", len));
! 1307: if (ncr53c9x_debug & NCR_SHOWTRAC) {
! 1308: for (i = 0; i < len; i++)
! 1309: printf(" %02x", p[i]);
! 1310: printf("]\n");
! 1311: }
! 1312: #endif
! 1313:
! 1314: for (i = 0; i < len; i++) {
! 1315: NCR_WRITE_REG(sc, NCR_FIFO, p[i]);
! 1316:
! 1317: if (sc->sc_rev == NCR_VARIANT_FAS366)
! 1318: NCR_WRITE_REG(sc, NCR_FIFO, 0);
! 1319: }
! 1320: }
! 1321:
! 1322: int
! 1323: ncr53c9x_reselect(sc, message, tagtype, tagid)
! 1324: struct ncr53c9x_softc *sc;
! 1325: int message;
! 1326: int tagtype;
! 1327: int tagid;
! 1328: {
! 1329: u_char selid, target, lun;
! 1330: struct ncr53c9x_ecb *ecb = NULL;
! 1331: struct ncr53c9x_tinfo *ti;
! 1332: struct ncr53c9x_linfo *li;
! 1333:
! 1334: if (sc->sc_rev == NCR_VARIANT_FAS366) {
! 1335: target = sc->sc_selid;
! 1336: } else {
! 1337: /*
! 1338: * The SCSI chip made a snapshot of the data bus while the reselection
! 1339: * was being negotiated. This enables us to determine which target did
! 1340: * the reselect.
! 1341: */
! 1342: selid = sc->sc_selid & ~(1 << sc->sc_id);
! 1343: if (selid & (selid - 1)) {
! 1344: printf("%s: reselect with invalid selid %02x;"
! 1345: " sending DEVICE RESET\n", sc->sc_dev.dv_xname, selid);
! 1346: goto reset;
! 1347:
! 1348: }
! 1349: target = ffs(selid) - 1;
! 1350: }
! 1351: lun = message & 0x07;
! 1352:
! 1353: /*
! 1354: * Search wait queue for disconnected cmd
! 1355: * The list should be short, so I haven't bothered with
! 1356: * any more sophisticated structures than a simple
! 1357: * singly linked list.
! 1358: */
! 1359: ti = &sc->sc_tinfo[target];
! 1360: li = TINFO_LUN(ti, lun);
! 1361:
! 1362: /*
! 1363: * We can get as far as the LUN with the IDENTIFY
! 1364: * message. Check to see if we're running an
! 1365: * un-tagged command. Otherwise ack the IDENTIFY
! 1366: * and wait for a tag message.
! 1367: */
! 1368: if (li != NULL) {
! 1369: if (li->untagged != NULL && li->busy)
! 1370: ecb = li->untagged;
! 1371: else if (tagtype != MSG_SIMPLE_Q_TAG) {
! 1372: /* Wait for tag to come by */
! 1373: sc->sc_state = NCR_IDENTIFIED;
! 1374: return (0);
! 1375: } else if (tagtype) ecb = li->queued[tagid];
! 1376: }
! 1377: if (ecb == NULL) {
! 1378: printf("%s: reselect from target %d lun %d tag %x:%x with no nexus;"
! 1379: " sending ABORT\n", sc->sc_dev.dv_xname, target, lun, tagtype, tagid);
! 1380: goto abort;
! 1381: }
! 1382:
! 1383: /* Make this nexus active again. */
! 1384: sc->sc_state = NCR_CONNECTED;
! 1385: sc->sc_nexus = ecb;
! 1386: ncr53c9x_setsync(sc, ti);
! 1387:
! 1388: if (ecb->flags & ECB_RESET)
! 1389: ncr53c9x_sched_msgout(SEND_DEV_RESET);
! 1390: else if (ecb->flags & ECB_ABORT)
! 1391: ncr53c9x_sched_msgout(SEND_ABORT);
! 1392:
! 1393: /* Do an implicit RESTORE POINTERS. */
! 1394: sc->sc_dp = ecb->daddr;
! 1395: sc->sc_dleft = ecb->dleft;
! 1396:
! 1397: return (0);
! 1398:
! 1399: reset:
! 1400: ncr53c9x_sched_msgout(SEND_DEV_RESET);
! 1401: return (1);
! 1402:
! 1403: abort:
! 1404: ncr53c9x_sched_msgout(SEND_ABORT);
! 1405: return (1);
! 1406: }
! 1407:
! 1408: #define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80)
! 1409: #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
! 1410: #define ISEXTMSG(m) ((m) == 1)
! 1411:
! 1412: static inline int
! 1413: __verify_msg_format(u_char *p, int len)
! 1414: {
! 1415:
! 1416: if (len == 1 && IS1BYTEMSG(p[0]))
! 1417: return 1;
! 1418: if (len == 2 && IS2BYTEMSG(p[0]))
! 1419: return 1;
! 1420: if (len >= 3 && ISEXTMSG(p[0]) &&
! 1421: len == p[1] + 2)
! 1422: return 1;
! 1423:
! 1424: return 0;
! 1425: }
! 1426:
! 1427: /*
! 1428: * Get an incoming message as initiator.
! 1429: *
! 1430: * The SCSI bus must already be in MESSAGE_IN_PHASE and there is a
! 1431: * byte in the FIFO
! 1432: */
! 1433: void
! 1434: ncr53c9x_msgin(sc)
! 1435: struct ncr53c9x_softc *sc;
! 1436: {
! 1437:
! 1438: NCR_TRACE(("[ncr53c9x_msgin(curmsglen:%ld)] ", (long)sc->sc_imlen));
! 1439:
! 1440: if (sc->sc_imlen == 0) {
! 1441: printf("%s: msgin: no msg byte available\n", sc->sc_dev.dv_xname);
! 1442: return;
! 1443: }
! 1444:
! 1445: /*
! 1446: * Prepare for a new message. A message should (according
! 1447: * to the SCSI standard) be transmitted in one single
! 1448: * MESSAGE_IN_PHASE. If we have been in some other phase,
! 1449: * then this is a new message.
! 1450: */
! 1451: if (sc->sc_prevphase != MESSAGE_IN_PHASE && sc->sc_state != NCR_RESELECTED) {
! 1452: printf("%s: phase change, dropping message, prev %d, state %d\n",
! 1453: sc->sc_dev.dv_xname, sc->sc_prevphase, sc->sc_state);
! 1454: sc->sc_flags &= ~NCR_DROP_MSGI;
! 1455: sc->sc_imlen = 0;
! 1456: }
! 1457:
! 1458: NCR_TRACE(("<msgbyte:0x%02x>", sc->sc_imess[0]));
! 1459:
! 1460: /*
! 1461: * If we're going to reject the message, don't bother storing
! 1462: * the incoming bytes. But still, we need to ACK them.
! 1463: */
! 1464: if ((sc->sc_flags & NCR_DROP_MSGI)) {
! 1465: NCRCMD(sc, NCRCMD_MSGOK);
! 1466: printf("<dropping msg byte %x>",
! 1467: sc->sc_imess[sc->sc_imlen]);
! 1468: return;
! 1469: }
! 1470:
! 1471: if (sc->sc_imlen >= NCR_MAX_MSG_LEN) {
! 1472: ncr53c9x_sched_msgout(SEND_REJECT);
! 1473: sc->sc_flags |= NCR_DROP_MSGI;
! 1474: } else {
! 1475: u_char *pb;
! 1476: int plen;
! 1477:
! 1478: switch (sc->sc_state) {
! 1479: /*
! 1480: * if received message is the first of reselection
! 1481: * then first byte is selid, and then message
! 1482: */
! 1483: case NCR_RESELECTED:
! 1484: pb = sc->sc_imess + 1;
! 1485: plen = sc->sc_imlen - 1;
! 1486: break;
! 1487: default:
! 1488: pb = sc->sc_imess;
! 1489: plen = sc->sc_imlen;
! 1490: break;
! 1491: }
! 1492:
! 1493: if (__verify_msg_format(pb, plen))
! 1494: goto gotit;
! 1495: }
! 1496:
! 1497: /* Ack what we have so far */
! 1498: NCRCMD(sc, NCRCMD_MSGOK);
! 1499: return;
! 1500:
! 1501: gotit:
! 1502: NCR_MSGS(("gotmsg(%x) state %d", sc->sc_imess[0], sc->sc_state));
! 1503: /* we got complete message, flush the imess, XXX nobody uses imlen below */
! 1504: sc->sc_imlen = 0;
! 1505:
! 1506: /*
! 1507: * Now we should have a complete message (1 byte, 2 byte
! 1508: * and moderately long extended messages). We only handle
! 1509: * extended messages which total length is shorter than
! 1510: * NCR_MAX_MSG_LEN. Longer messages will be amputated.
! 1511: */
! 1512: switch (sc->sc_state) {
! 1513: struct ncr53c9x_ecb *ecb;
! 1514: struct ncr53c9x_tinfo *ti;
! 1515: struct ncr53c9x_linfo *li;
! 1516: int lun;
! 1517:
! 1518: case NCR_CONNECTED:
! 1519: ecb = sc->sc_nexus;
! 1520: ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
! 1521:
! 1522: switch (sc->sc_imess[0]) {
! 1523: case MSG_CMDCOMPLETE:
! 1524: NCR_MSGS(("cmdcomplete "));
! 1525: if (sc->sc_dleft < 0) {
! 1526: sc_print_addr(ecb->xs->sc_link);
! 1527: printf("got %ld extra bytes\n",
! 1528: -(long)sc->sc_dleft);
! 1529: sc->sc_dleft = 0;
! 1530: }
! 1531: ecb->dleft = (ecb->flags & ECB_TENTATIVE_DONE)
! 1532: ? 0
! 1533: : sc->sc_dleft;
! 1534: if ((ecb->flags & ECB_SENSE) == 0)
! 1535: ecb->xs->resid = ecb->dleft;
! 1536: sc->sc_state = NCR_CMDCOMPLETE;
! 1537: break;
! 1538:
! 1539: case MSG_MESSAGE_REJECT:
! 1540: NCR_MSGS(("msg reject (msgout=%x) ", sc->sc_msgout));
! 1541: switch (sc->sc_msgout) {
! 1542: case SEND_TAG:
! 1543: /* Target does not like tagged queuing.
! 1544: * - Flush the command queue
! 1545: * - Disable tagged queuing for the target
! 1546: * - Dequeue ecb from the queued array.
! 1547: */
! 1548: printf("%s: tagged queuing rejected: target %d\n",
! 1549: sc->sc_dev.dv_xname, ecb->xs->sc_link->target);
! 1550:
! 1551: NCR_MSGS(("(rejected sent tag)"));
! 1552: NCRCMD(sc, NCRCMD_FLUSH);
! 1553: DELAY(1);
! 1554: ti->flags &= ~T_TAG;
! 1555: lun = ecb->xs->sc_link->lun;
! 1556: li = TINFO_LUN(ti, lun);
! 1557: if (ecb->tag[0] &&
! 1558: li->queued[ecb->tag[1]] != NULL) {
! 1559: li->queued[ecb->tag[1]] = NULL;
! 1560: li->used--;
! 1561: }
! 1562: ecb->tag[0] = ecb->tag[1] = 0;
! 1563: li->untagged = ecb;
! 1564: li->busy = 1;
! 1565: break;
! 1566:
! 1567: case SEND_SDTR:
! 1568: printf("%s: sync transfer rejected: target %d\n",
! 1569: sc->sc_dev.dv_xname, ecb->xs->sc_link->target);
! 1570: sc->sc_flags &= ~NCR_SYNCHNEGO;
! 1571: ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE);
! 1572: ncr53c9x_setsync(sc, ti);
! 1573: break;
! 1574:
! 1575: case SEND_WDTR:
! 1576: printf("%s: wide transfer rejected: target %d\n",
! 1577: sc->sc_dev.dv_xname, ecb->xs->sc_link->target);
! 1578: ti->flags &= ~T_WIDE;
! 1579: ti->width = 0;
! 1580: break;
! 1581:
! 1582: case SEND_INIT_DET_ERR:
! 1583: goto abort;
! 1584: }
! 1585: break;
! 1586:
! 1587: case MSG_NOOP:
! 1588: NCR_MSGS(("noop "));
! 1589: break;
! 1590:
! 1591: case MSG_HEAD_OF_Q_TAG:
! 1592: case MSG_SIMPLE_Q_TAG:
! 1593: case MSG_ORDERED_Q_TAG:
! 1594: NCR_MSGS(("TAG %x:%x", sc->sc_imess[0], sc->sc_imess[1]));
! 1595: break;
! 1596:
! 1597: case MSG_DISCONNECT:
! 1598: NCR_MSGS(("disconnect "));
! 1599: ti->dconns++;
! 1600: sc->sc_state = NCR_DISCONNECT;
! 1601:
! 1602: /*
! 1603: * Mark the fact that all bytes have moved. The
! 1604: * target may not bother to do a SAVE POINTERS
! 1605: * at this stage. This flag will set the residual
! 1606: * count to zero on MSG COMPLETE.
! 1607: */
! 1608: if (sc->sc_dleft == 0)
! 1609: ecb->flags |= ECB_TENTATIVE_DONE;
! 1610:
! 1611: break;
! 1612:
! 1613: case MSG_SAVEDATAPOINTER:
! 1614: NCR_MSGS(("save datapointer "));
! 1615: ecb->daddr = sc->sc_dp;
! 1616: ecb->dleft = sc->sc_dleft;
! 1617: break;
! 1618:
! 1619: case MSG_RESTOREPOINTERS:
! 1620: NCR_MSGS(("restore datapointer "));
! 1621: sc->sc_dp = ecb->daddr;
! 1622: sc->sc_dleft = ecb->dleft;
! 1623: break;
! 1624:
! 1625: case MSG_EXTENDED:
! 1626: NCR_MSGS(("extended(%x) ", sc->sc_imess[2]));
! 1627: switch (sc->sc_imess[2]) {
! 1628: case MSG_EXT_SDTR:
! 1629: NCR_MSGS(("SDTR period %d, offset %d ",
! 1630: sc->sc_imess[3], sc->sc_imess[4]));
! 1631: if (sc->sc_imess[1] != 3)
! 1632: goto reject;
! 1633: ti->period = sc->sc_imess[3];
! 1634: ti->offset = sc->sc_imess[4];
! 1635: ti->flags &= ~T_NEGOTIATE;
! 1636: if (sc->sc_minsync == 0 ||
! 1637: ti->offset == 0 ||
! 1638: ti->period > 124) {
! 1639: #ifdef NCR53C9X_DEBUG
! 1640: sc_print_addr(ecb->xs->sc_link);
! 1641: printf("async mode\n");
! 1642: #endif
! 1643: if ((sc->sc_flags&NCR_SYNCHNEGO)
! 1644: == 0) {
! 1645: /*
! 1646: * target initiated negotiation
! 1647: */
! 1648: ti->offset = 0;
! 1649: ti->flags &= ~T_SYNCMODE;
! 1650: ncr53c9x_sched_msgout(
! 1651: SEND_SDTR);
! 1652: } else {
! 1653: /* we are async */
! 1654: ti->flags &= ~T_SYNCMODE;
! 1655: }
! 1656: } else {
! 1657: #ifdef NCR53C9X_DEBUG
! 1658: int r, s;
! 1659: #endif
! 1660: int p;
! 1661:
! 1662: p = ncr53c9x_stp2cpb(sc, ti->period);
! 1663: ti->period = ncr53c9x_cpb2stp(sc, p);
! 1664: #ifdef NCR53C9X_DEBUG
! 1665: sc_print_addr(ecb->xs->sc_link);
! 1666: r = 250/ti->period;
! 1667: s = (100*250)/ti->period - 100*r;
! 1668: printf("max sync rate %d.%02dMB/s\n",
! 1669: r, s);
! 1670: #endif
! 1671: if ((sc->sc_flags&NCR_SYNCHNEGO) == 0) {
! 1672: /*
! 1673: * target initiated negotiation
! 1674: */
! 1675: if (ti->period <
! 1676: sc->sc_minsync)
! 1677: ti->period =
! 1678: sc->sc_minsync;
! 1679: if (ti->offset > 15)
! 1680: ti->offset = 15;
! 1681: ti->flags &= ~T_SYNCMODE;
! 1682: ncr53c9x_sched_msgout(
! 1683: SEND_SDTR);
! 1684: } else {
! 1685: /* we are sync */
! 1686: ti->flags |= T_SYNCMODE;
! 1687: }
! 1688: }
! 1689: sc->sc_flags &= ~NCR_SYNCHNEGO;
! 1690: ncr53c9x_setsync(sc, ti);
! 1691: break;
! 1692:
! 1693: case MSG_EXT_WDTR:
! 1694: printf("%s: wide mode %d\n",
! 1695: sc->sc_dev.dv_xname, sc->sc_imess[3]);
! 1696: if (sc->sc_imess[3] == 1) {
! 1697: ti->cfg3 |= NCRFASCFG3_EWIDE;
! 1698: ncr53c9x_setsync(sc, ti);
! 1699: } else
! 1700: ti->width = 0;
! 1701: ti->flags &= ~T_WIDE;
! 1702: break;
! 1703: default:
! 1704: sc_print_addr(ecb->xs->sc_link);
! 1705: printf("unrecognized MESSAGE EXTENDED;"
! 1706: " sending REJECT\n");
! 1707: goto reject;
! 1708: }
! 1709: break;
! 1710:
! 1711: default:
! 1712: NCR_MSGS(("ident "));
! 1713: sc_print_addr(ecb->xs->sc_link);
! 1714: printf("unrecognized MESSAGE; sending REJECT\n");
! 1715: reject:
! 1716: ncr53c9x_sched_msgout(SEND_REJECT);
! 1717: break;
! 1718: }
! 1719: break;
! 1720:
! 1721: case NCR_IDENTIFIED:
! 1722: /*
! 1723: * IDENTIFY message was received and queue tag is expected now
! 1724: */
! 1725: if ((sc->sc_imess[0] != MSG_SIMPLE_Q_TAG) ||
! 1726: (sc->sc_msgify == 0)) {
! 1727: printf("%s: TAG reselect without IDENTIFY;"
! 1728: " MSG %x;"
! 1729: " sending DEVICE RESET\n",
! 1730: sc->sc_dev.dv_xname,
! 1731: sc->sc_imess[0]);
! 1732: goto reset;
! 1733: }
! 1734: (void) ncr53c9x_reselect(sc, sc->sc_msgify,
! 1735: sc->sc_imess[0], sc->sc_imess[1]);
! 1736: break;
! 1737:
! 1738: case NCR_RESELECTED:
! 1739: if (MSG_ISIDENTIFY(sc->sc_imess[1])) {
! 1740: sc->sc_msgify = sc->sc_imess[1];
! 1741: } else {
! 1742: printf("%s: reselect without IDENTIFY;"
! 1743: " MSG %x;"
! 1744: " sending DEVICE RESET\n",
! 1745: sc->sc_dev.dv_xname,
! 1746: sc->sc_imess[1]);
! 1747: goto reset;
! 1748: }
! 1749: (void) ncr53c9x_reselect(sc, sc->sc_msgify, 0, 0);
! 1750: break;
! 1751:
! 1752: default:
! 1753: printf("%s: unexpected MESSAGE IN; sending DEVICE RESET\n",
! 1754: sc->sc_dev.dv_xname);
! 1755: reset:
! 1756: ncr53c9x_sched_msgout(SEND_DEV_RESET);
! 1757: break;
! 1758:
! 1759: abort:
! 1760: ncr53c9x_sched_msgout(SEND_ABORT);
! 1761: break;
! 1762: }
! 1763:
! 1764: /* if we have more messages to send set ATN */
! 1765: if (sc->sc_msgpriq)
! 1766: NCRCMD(sc, NCRCMD_SETATN);
! 1767:
! 1768: /* Ack last message byte */
! 1769: NCRCMD(sc, NCRCMD_MSGOK);
! 1770:
! 1771: /* Done, reset message pointer. */
! 1772: sc->sc_flags &= ~NCR_DROP_MSGI;
! 1773: sc->sc_imlen = 0;
! 1774: }
! 1775:
! 1776:
! 1777: /*
! 1778: * Send the highest priority, scheduled message
! 1779: */
! 1780: void
! 1781: ncr53c9x_msgout(sc)
! 1782: struct ncr53c9x_softc *sc;
! 1783: {
! 1784: struct ncr53c9x_tinfo *ti;
! 1785: struct ncr53c9x_ecb *ecb;
! 1786: size_t size;
! 1787:
! 1788: NCR_TRACE(("[ncr53c9x_msgout(priq:%x, prevphase:%x)]",
! 1789: sc->sc_msgpriq, sc->sc_prevphase));
! 1790:
! 1791: /*
! 1792: * XXX - the NCR_ATN flag is not in sync with the actual ATN
! 1793: * condition on the SCSI bus. The 53c9x chip
! 1794: * automatically turns off ATN before sending the
! 1795: * message byte. (see also the comment below in the
! 1796: * default case when picking out a message to send)
! 1797: */
! 1798: if (sc->sc_flags & NCR_ATN) {
! 1799: if (sc->sc_prevphase != MESSAGE_OUT_PHASE) {
! 1800: new:
! 1801: NCRCMD(sc, NCRCMD_FLUSH);
! 1802: /* DELAY(1); */
! 1803: sc->sc_msgoutq = 0;
! 1804: sc->sc_omlen = 0;
! 1805: }
! 1806: } else {
! 1807: if (sc->sc_prevphase == MESSAGE_OUT_PHASE) {
! 1808: ncr53c9x_sched_msgout(sc->sc_msgoutq);
! 1809: goto new;
! 1810: } else {
! 1811: printf("%s at line %d: unexpected MESSAGE OUT phase\n",
! 1812: sc->sc_dev.dv_xname, __LINE__);
! 1813: }
! 1814: }
! 1815:
! 1816: if (sc->sc_omlen == 0) {
! 1817: /* Pick up highest priority message */
! 1818: sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq;
! 1819: sc->sc_msgoutq |= sc->sc_msgout;
! 1820: sc->sc_msgpriq &= ~sc->sc_msgout;
! 1821: sc->sc_omlen = 1; /* "Default" message len */
! 1822: switch (sc->sc_msgout) {
! 1823: case SEND_SDTR:
! 1824: ecb = sc->sc_nexus;
! 1825: ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
! 1826: sc->sc_omess[0] = MSG_EXTENDED;
! 1827: sc->sc_omess[1] = 3;
! 1828: sc->sc_omess[2] = MSG_EXT_SDTR;
! 1829: sc->sc_omess[3] = ti->period;
! 1830: sc->sc_omess[4] = ti->offset;
! 1831: sc->sc_omlen = 5;
! 1832: if ((sc->sc_flags & NCR_SYNCHNEGO) == 0) {
! 1833: ti->flags |= T_SYNCMODE;
! 1834: ncr53c9x_setsync(sc, ti);
! 1835: }
! 1836: break;
! 1837: case SEND_WDTR:
! 1838: ecb = sc->sc_nexus;
! 1839: ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
! 1840: sc->sc_omess[0] = MSG_EXTENDED;
! 1841: sc->sc_omess[1] = 2;
! 1842: sc->sc_omess[2] = MSG_EXT_WDTR;
! 1843: sc->sc_omess[3] = ti->width;
! 1844: sc->sc_omlen = 4;
! 1845: break;
! 1846: case SEND_IDENTIFY:
! 1847: if (sc->sc_state != NCR_CONNECTED) {
! 1848: printf("%s at line %d: no nexus\n",
! 1849: sc->sc_dev.dv_xname, __LINE__);
! 1850: }
! 1851: ecb = sc->sc_nexus;
! 1852: sc->sc_omess[0] =
! 1853: MSG_IDENTIFY(ecb->xs->sc_link->lun, 0);
! 1854: break;
! 1855: case SEND_TAG:
! 1856: if (sc->sc_state != NCR_CONNECTED) {
! 1857: printf("%s at line %d: no nexus\n",
! 1858: sc->sc_dev.dv_xname, __LINE__);
! 1859: }
! 1860: ecb = sc->sc_nexus;
! 1861: sc->sc_omess[0] = ecb->tag[0];
! 1862: sc->sc_omess[1] = ecb->tag[1];
! 1863: sc->sc_omlen = 2;
! 1864: break;
! 1865: case SEND_DEV_RESET:
! 1866: sc->sc_flags |= NCR_ABORTING;
! 1867: sc->sc_omess[0] = MSG_BUS_DEV_RESET;
! 1868: ecb = sc->sc_nexus;
! 1869: ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
! 1870: ti->flags &= ~T_SYNCMODE;
! 1871: if ((ti->flags & T_SYNCHOFF) == 0)
! 1872: /* We can re-start sync negotiation */
! 1873: ti->flags |= T_NEGOTIATE;
! 1874: break;
! 1875: case SEND_PARITY_ERROR:
! 1876: sc->sc_omess[0] = MSG_PARITY_ERROR;
! 1877: break;
! 1878: case SEND_ABORT:
! 1879: sc->sc_flags |= NCR_ABORTING;
! 1880: sc->sc_omess[0] = MSG_ABORT;
! 1881: break;
! 1882: case SEND_INIT_DET_ERR:
! 1883: sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
! 1884: break;
! 1885: case SEND_REJECT:
! 1886: sc->sc_omess[0] = MSG_MESSAGE_REJECT;
! 1887: break;
! 1888: default:
! 1889: /*
! 1890: * We normally do not get here, since the chip
! 1891: * automatically turns off ATN before the last
! 1892: * byte of a message is sent to the target.
! 1893: * However, if the target rejects our (multi-byte)
! 1894: * message early by switching to MSG IN phase
! 1895: * ATN remains on, so the target may return to
! 1896: * MSG OUT phase. If there are no scheduled messages
! 1897: * left we send a NO-OP.
! 1898: *
! 1899: * XXX - Note that this leaves no useful purpose for
! 1900: * the NCR_ATN flag.
! 1901: */
! 1902: sc->sc_flags &= ~NCR_ATN;
! 1903: sc->sc_omess[0] = MSG_NOOP;
! 1904: break;
! 1905: }
! 1906: sc->sc_omp = sc->sc_omess;
! 1907: }
! 1908:
! 1909: #ifdef DEBUG
! 1910: {
! 1911: int i;
! 1912:
! 1913: for (i = 0; i<sc->sc_omlen; i++)
! 1914: NCR_MISC(("<msgbyte:0x%02x>", sc->sc_omess[i]));
! 1915: }
! 1916: #endif
! 1917: if (sc->sc_rev == NCR_VARIANT_FAS366) {
! 1918: /*
! 1919: * XXX fifo size
! 1920: */
! 1921: ncr53c9x_flushfifo(sc);
! 1922: ncr53c9x_wrfifo(sc, sc->sc_omp, sc->sc_omlen);
! 1923: NCRCMD(sc, NCRCMD_TRANS);
! 1924: } else {
! 1925: /* (re)send the message */
! 1926: size = min(sc->sc_omlen, sc->sc_maxxfer);
! 1927: NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size);
! 1928: /* Program the SCSI counter */
! 1929: NCR_SET_COUNT(sc, size);
! 1930:
! 1931: /* Load the count in and start the message-out transfer */
! 1932: NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
! 1933: NCRCMD(sc, NCRCMD_TRANS|NCRCMD_DMA);
! 1934: NCRDMA_GO(sc);
! 1935: }
! 1936: }
! 1937:
! 1938: /*
! 1939: * This is the most critical part of the driver, and has to know
! 1940: * how to deal with *all* error conditions and phases from the SCSI
! 1941: * bus. If there are no errors and the DMA was active, then call the
! 1942: * DMA pseudo-interrupt handler. If this returns 1, then that was it
! 1943: * and we can return from here without further processing.
! 1944: *
! 1945: * Most of this needs verifying.
! 1946: */
! 1947: int sdebug = 0;
! 1948: int
! 1949: ncr53c9x_intr(arg)
! 1950: void *arg;
! 1951: {
! 1952: struct ncr53c9x_softc *sc = arg;
! 1953: struct ncr53c9x_ecb *ecb;
! 1954: struct scsi_link *sc_link;
! 1955: struct ncr53c9x_tinfo *ti;
! 1956: size_t size;
! 1957: int nfifo;
! 1958:
! 1959: NCR_TRACE(("[ncr53c9x_intr: state %d] ", sc->sc_state));
! 1960:
! 1961: if (!NCRDMA_ISINTR(sc))
! 1962: return (0);
! 1963:
! 1964: again:
! 1965: /* and what do the registers say... */
! 1966: ncr53c9x_readregs(sc);
! 1967:
! 1968: /*
! 1969: * At the moment, only a SCSI Bus Reset or Illegal
! 1970: * Command are classed as errors. A disconnect is a
! 1971: * valid condition, and we let the code check is the
! 1972: * "NCR_BUSFREE_OK" flag was set before declaring it
! 1973: * and error.
! 1974: *
! 1975: * Also, the status register tells us about "Gross
! 1976: * Errors" and "Parity errors". Only the Gross Error
! 1977: * is really bad, and the parity errors are dealt
! 1978: * with later
! 1979: *
! 1980: * TODO
! 1981: * If there are too many parity error, go to slow
! 1982: * cable mode ?
! 1983: */
! 1984:
! 1985: /* SCSI Reset */
! 1986: if (sc->sc_espintr & NCRINTR_SBR) {
! 1987: if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
! 1988: NCRCMD(sc, NCRCMD_FLUSH);
! 1989: DELAY(1);
! 1990: }
! 1991: if (sc->sc_state != NCR_SBR) {
! 1992: printf("%s: SCSI bus reset\n",
! 1993: sc->sc_dev.dv_xname);
! 1994: ncr53c9x_init(sc, 0); /* Restart everything */
! 1995: return (1);
! 1996: }
! 1997: #if 0
! 1998: /*XXX*/ printf("<expected bus reset: "
! 1999: "[intr %x, stat %x, step %d]>\n",
! 2000: sc->sc_espintr, sc->sc_espstat,
! 2001: sc->sc_espstep);
! 2002: #endif
! 2003: if (sc->sc_nexus)
! 2004: panic("%s: nexus in reset state",
! 2005: sc->sc_dev.dv_xname);
! 2006: goto sched;
! 2007: }
! 2008:
! 2009: ecb = sc->sc_nexus;
! 2010:
! 2011: #define NCRINTR_ERR (NCRINTR_SBR|NCRINTR_ILL)
! 2012: if (sc->sc_espintr & NCRINTR_ERR ||
! 2013: sc->sc_espstat & NCRSTAT_GE) {
! 2014:
! 2015: if (sc->sc_espstat & NCRSTAT_GE) {
! 2016: /* Gross Error; no target ? */
! 2017: if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
! 2018: NCRCMD(sc, NCRCMD_FLUSH);
! 2019: DELAY(1);
! 2020: }
! 2021: if (sc->sc_state == NCR_CONNECTED ||
! 2022: sc->sc_state == NCR_SELECTING) {
! 2023: ecb->xs->error = XS_TIMEOUT;
! 2024: ncr53c9x_done(sc, ecb);
! 2025: }
! 2026: return (1);
! 2027: }
! 2028:
! 2029: if (sc->sc_espintr & NCRINTR_ILL) {
! 2030: if (sc->sc_flags & NCR_EXPECT_ILLCMD) {
! 2031: /*
! 2032: * Eat away "Illegal command" interrupt
! 2033: * on a ESP100 caused by a re-selection
! 2034: * while we were trying to select
! 2035: * another target.
! 2036: */
! 2037: #ifdef DEBUG
! 2038: printf("%s: ESP100 work-around activated\n",
! 2039: sc->sc_dev.dv_xname);
! 2040: #endif
! 2041: sc->sc_flags &= ~NCR_EXPECT_ILLCMD;
! 2042: return (1);
! 2043: }
! 2044: /* illegal command, out of sync ? */
! 2045: printf("%s: illegal command: 0x%x "
! 2046: "(state %d, phase %x, prevphase %x)\n",
! 2047: sc->sc_dev.dv_xname, sc->sc_lastcmd,
! 2048: sc->sc_state, sc->sc_phase,
! 2049: sc->sc_prevphase);
! 2050: if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
! 2051: NCRCMD(sc, NCRCMD_FLUSH);
! 2052: DELAY(1);
! 2053: }
! 2054: ncr53c9x_init(sc, 1); /* Restart everything */
! 2055: return (1);
! 2056: }
! 2057: }
! 2058: sc->sc_flags &= ~NCR_EXPECT_ILLCMD;
! 2059:
! 2060: /*
! 2061: * Call if DMA is active.
! 2062: *
! 2063: * If DMA_INTR returns true, then maybe go 'round the loop
! 2064: * again in case there is no more DMA queued, but a phase
! 2065: * change is expected.
! 2066: */
! 2067: if (NCRDMA_ISACTIVE(sc)) {
! 2068: int r = NCRDMA_INTR(sc);
! 2069: if (r == -1) {
! 2070: printf("%s: DMA error; resetting\n",
! 2071: sc->sc_dev.dv_xname);
! 2072: ncr53c9x_init(sc, 1);
! 2073: return (1);
! 2074: }
! 2075: /* If DMA active here, then go back to work... */
! 2076: if (NCRDMA_ISACTIVE(sc))
! 2077: return (1);
! 2078:
! 2079: if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
! 2080: /*
! 2081: * DMA not completed. If we can not find a
! 2082: * acceptable explanation, print a diagnostic.
! 2083: */
! 2084: if (sc->sc_state == NCR_SELECTING)
! 2085: /*
! 2086: * This can happen if we are reselected
! 2087: * while using DMA to select a target.
! 2088: */
! 2089: /*void*/;
! 2090: else if (sc->sc_prevphase == MESSAGE_OUT_PHASE){
! 2091: /*
! 2092: * Our (multi-byte) message (eg SDTR)
! 2093: * was interrupted by the target to
! 2094: * send a MSG REJECT.
! 2095: * Print diagnostic if current phase
! 2096: * is not MESSAGE IN.
! 2097: */
! 2098: if (sc->sc_phase != MESSAGE_IN_PHASE)
! 2099: printf("%s: !TC on MSG OUT"
! 2100: " [intr %x, stat %x, step %d]"
! 2101: " prevphase %x, resid %lx\n",
! 2102: sc->sc_dev.dv_xname,
! 2103: sc->sc_espintr,
! 2104: sc->sc_espstat,
! 2105: sc->sc_espstep,
! 2106: sc->sc_prevphase,
! 2107: (u_long)sc->sc_omlen);
! 2108: } else if (sc->sc_dleft == 0) {
! 2109: /*
! 2110: * The DMA operation was started for
! 2111: * a DATA transfer. Print a diagnostic
! 2112: * if the DMA counter and TC bit
! 2113: * appear to be out of sync.
! 2114: */
! 2115: printf("%s: !TC on DATA XFER"
! 2116: " [intr %x, stat %x, step %d]"
! 2117: " prevphase %x, resid %x\n",
! 2118: sc->sc_dev.dv_xname,
! 2119: sc->sc_espintr,
! 2120: sc->sc_espstat,
! 2121: sc->sc_espstep,
! 2122: sc->sc_prevphase,
! 2123: ecb?ecb->dleft:-1);
! 2124: }
! 2125: }
! 2126: }
! 2127:
! 2128: /*
! 2129: * check for less serious errors
! 2130: */
! 2131: if (sc->sc_espstat & NCRSTAT_PE) {
! 2132: printf("%s: SCSI bus parity error\n", sc->sc_dev.dv_xname);
! 2133: if (sc->sc_prevphase == MESSAGE_IN_PHASE)
! 2134: ncr53c9x_sched_msgout(SEND_PARITY_ERROR);
! 2135: else
! 2136: ncr53c9x_sched_msgout(SEND_INIT_DET_ERR);
! 2137: }
! 2138:
! 2139: if (sc->sc_espintr & NCRINTR_DIS) {
! 2140: sc->sc_msgify = 0;
! 2141: NCR_MISC(("<DISC [intr %x, stat %x, step %d]>",
! 2142: sc->sc_espintr,sc->sc_espstat,sc->sc_espstep));
! 2143: if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
! 2144: NCRCMD(sc, NCRCMD_FLUSH);
! 2145: /* DELAY(1); */
! 2146: }
! 2147: /*
! 2148: * This command must (apparently) be issued within
! 2149: * 250mS of a disconnect. So here you are...
! 2150: */
! 2151: NCRCMD(sc, NCRCMD_ENSEL);
! 2152:
! 2153: switch (sc->sc_state) {
! 2154: case NCR_RESELECTED:
! 2155: goto sched;
! 2156:
! 2157: case NCR_SELECTING:
! 2158: {
! 2159: struct ncr53c9x_linfo *li;
! 2160:
! 2161: ecb->xs->error = XS_SELTIMEOUT;
! 2162:
! 2163: /* Selection timeout -- discard all LUNs if empty */
! 2164: sc_link = ecb->xs->sc_link;
! 2165: ti = &sc->sc_tinfo[sc_link->target];
! 2166: for (li = LIST_FIRST(&ti->luns);
! 2167: li != LIST_END(&ti->luns); ) {
! 2168: if (!li->untagged && !li->used) {
! 2169: if (li->lun < NCR_NLUN)
! 2170: ti->lun[li->lun] = NULL;
! 2171: LIST_REMOVE(li, link);
! 2172: free(li, M_DEVBUF);
! 2173: /* Restart the search at the beginning */
! 2174: li = LIST_FIRST(&ti->luns);
! 2175: continue;
! 2176: }
! 2177: li = LIST_NEXT(li, link);
! 2178: }
! 2179: goto finish;
! 2180: }
! 2181: case NCR_CONNECTED:
! 2182: if ((sc->sc_flags & NCR_SYNCHNEGO)) {
! 2183: #ifdef NCR53C9X_DEBUG
! 2184: if (ecb)
! 2185: sc_print_addr(ecb->xs->sc_link);
! 2186: printf("sync nego not completed!\n");
! 2187: #endif
! 2188: ti = &sc->sc_tinfo[ecb->xs->sc_link->target];
! 2189: sc->sc_flags &= ~NCR_SYNCHNEGO;
! 2190: ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE);
! 2191: }
! 2192:
! 2193: /* it may be OK to disconnect */
! 2194: if ((sc->sc_flags & NCR_ABORTING) == 0) {
! 2195: /*
! 2196: * Section 5.1.1 of the SCSI 2 spec
! 2197: * suggests issuing a REQUEST SENSE
! 2198: * following an unexpected disconnect.
! 2199: * Some devices go into a contingent
! 2200: * allegiance condition when
! 2201: * disconnecting, and this is necessary
! 2202: * to clean up their state.
! 2203: */
! 2204: printf("%s: unexpected disconnect; ",
! 2205: sc->sc_dev.dv_xname);
! 2206: if (ecb->flags & ECB_SENSE) {
! 2207: printf("resetting\n");
! 2208: goto reset;
! 2209: }
! 2210: printf("sending REQUEST SENSE\n");
! 2211: timeout_del(&ecb->to);
! 2212: ncr53c9x_sense(sc, ecb);
! 2213: goto out;
! 2214: }
! 2215:
! 2216: ecb->xs->error = XS_TIMEOUT;
! 2217: goto finish;
! 2218:
! 2219: case NCR_DISCONNECT:
! 2220: sc->sc_nexus = NULL;
! 2221: goto sched;
! 2222:
! 2223: case NCR_CMDCOMPLETE:
! 2224: goto finish;
! 2225: }
! 2226: }
! 2227:
! 2228: switch (sc->sc_state) {
! 2229:
! 2230: case NCR_SBR:
! 2231: printf("%s: waiting for SCSI Bus Reset to happen\n",
! 2232: sc->sc_dev.dv_xname);
! 2233: return (1);
! 2234:
! 2235: case NCR_RESELECTED:
! 2236: /*
! 2237: * we must be continuing a message ?
! 2238: */
! 2239: if (sc->sc_phase != MESSAGE_IN_PHASE) {
! 2240: printf("%s: target didn't identify\n",
! 2241: sc->sc_dev.dv_xname);
! 2242: ncr53c9x_init(sc, 1);
! 2243: return (1);
! 2244: }
! 2245: printf("<<RESELECT CONT'd>>");
! 2246: #if XXXX
! 2247: ncr53c9x_msgin(sc);
! 2248: if (sc->sc_state != NCR_CONNECTED) {
! 2249: /* IDENTIFY fail?! */
! 2250: printf("%s: identify failed\n",
! 2251: sc->sc_dev.dv_xname);
! 2252: ncr53c9x_init(sc, 1);
! 2253: return (1);
! 2254: }
! 2255: #endif
! 2256: break;
! 2257:
! 2258: case NCR_IDENTIFIED:
! 2259: ecb = sc->sc_nexus;
! 2260: if (sc->sc_phase != MESSAGE_IN_PHASE) {
! 2261: int i = (NCR_READ_REG(sc, NCR_FFLAG)
! 2262: & NCRFIFO_FF);
! 2263: /*
! 2264: * Things are seriously fucked up.
! 2265: * Pull the brakes, i.e. reset
! 2266: */
! 2267: printf("%s: target didn't send tag: %d bytes in fifo\n",
! 2268: sc->sc_dev.dv_xname, i);
! 2269: /* Drain and display fifo */
! 2270: while (i-- > 0)
! 2271: printf("[%d] ", NCR_READ_REG(sc, NCR_FIFO));
! 2272: ncr53c9x_init(sc, 1);
! 2273: return (1);
! 2274: } else
! 2275: goto msgin;
! 2276:
! 2277: break;
! 2278: case NCR_IDLE:
! 2279: case NCR_SELECTING:
! 2280: ecb = sc->sc_nexus;
! 2281: if (sc->sc_espintr & NCRINTR_RESEL) {
! 2282: sc->sc_msgpriq = sc->sc_msgout = sc->sc_msgoutq = 0;
! 2283: sc->sc_flags = 0;
! 2284: /*
! 2285: * If we're trying to select a
! 2286: * target ourselves, push our command
! 2287: * back into the ready list.
! 2288: */
! 2289: if (sc->sc_state == NCR_SELECTING) {
! 2290: NCR_MISC(("backoff selector "));
! 2291: timeout_del(&ecb->to);
! 2292: ncr53c9x_dequeue(sc, ecb);
! 2293: TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
! 2294: ecb->flags |= ECB_READY;
! 2295: ecb = sc->sc_nexus = NULL;
! 2296: }
! 2297: sc->sc_state = NCR_RESELECTED;
! 2298: if (sc->sc_phase != MESSAGE_IN_PHASE) {
! 2299: /*
! 2300: * Things are seriously fucked up.
! 2301: * Pull the brakes, i.e. reset
! 2302: */
! 2303: printf("%s: target didn't identify\n",
! 2304: sc->sc_dev.dv_xname);
! 2305: ncr53c9x_init(sc, 1);
! 2306: return (1);
! 2307: }
! 2308: /*
! 2309: * The C90 only inhibits FIFO writes until
! 2310: * reselection is complete, instead of
! 2311: * waiting until the interrupt status register
! 2312: * has been read. So, if the reselect happens
! 2313: * while we were entering a command bytes (for
! 2314: * another target) some of those bytes can
! 2315: * appear in the FIFO here, after the
! 2316: * interrupt is taken.
! 2317: */
! 2318: nfifo = ncr53c9x_rdfifo(sc, NCR_RDFIFO_START);
! 2319:
! 2320: if (nfifo < 2 ||
! 2321: (nfifo > 2 &&
! 2322: sc->sc_rev != NCR_VARIANT_ESP100)) {
! 2323: printf("%s: RESELECT: "
! 2324: "%d bytes in FIFO! "
! 2325: "[intr %x, stat %x, step %d, prevphase %x]\n",
! 2326: sc->sc_dev.dv_xname,
! 2327: nfifo,
! 2328: sc->sc_espintr,
! 2329: sc->sc_espstat,
! 2330: sc->sc_espstep,
! 2331: sc->sc_prevphase);
! 2332: ncr53c9x_init(sc, 1);
! 2333: return (1);
! 2334: }
! 2335: sc->sc_selid = sc->sc_imess[0];
! 2336: NCR_MISC(("selid=%2x ", sc->sc_selid));
! 2337:
! 2338: /* Handle identify message */
! 2339: ncr53c9x_msgin(sc);
! 2340: if (nfifo != 2) {
! 2341: /*
! 2342: * Note: this should not happen
! 2343: * with `dmaselect' on.
! 2344: */
! 2345: sc->sc_flags |= NCR_EXPECT_ILLCMD;
! 2346: NCRCMD(sc, NCRCMD_FLUSH);
! 2347: } else if (sc->sc_features & NCR_F_DMASELECT &&
! 2348: sc->sc_rev == NCR_VARIANT_ESP100) {
! 2349: sc->sc_flags |= NCR_EXPECT_ILLCMD;
! 2350: }
! 2351:
! 2352: if (sc->sc_state != NCR_CONNECTED &&
! 2353: sc->sc_state != NCR_IDENTIFIED) {
! 2354: /* IDENTIFY fail?! */
! 2355: printf("%s: identify failed, state %d, intr %02x\n",
! 2356: sc->sc_dev.dv_xname, sc->sc_state,
! 2357: sc->sc_espintr);
! 2358: ncr53c9x_init(sc, 1);
! 2359: return (1);
! 2360: }
! 2361: goto shortcut; /* ie. next phase expected soon */
! 2362: }
! 2363:
! 2364: #define NCRINTR_DONE (NCRINTR_FC|NCRINTR_BS)
! 2365: if ((sc->sc_espintr & NCRINTR_DONE) == NCRINTR_DONE) {
! 2366: /*
! 2367: * Arbitration won; examine the `step' register
! 2368: * to determine how far the selection could progress.
! 2369: */
! 2370: ecb = sc->sc_nexus;
! 2371: if (!ecb)
! 2372: panic("ncr53c9x: no nexus");
! 2373:
! 2374: sc_link = ecb->xs->sc_link;
! 2375: ti = &sc->sc_tinfo[sc_link->target];
! 2376:
! 2377: switch (sc->sc_espstep) {
! 2378: case 0:
! 2379: /*
! 2380: * The target did not respond with a
! 2381: * message out phase - probably an old
! 2382: * device that doesn't recognize ATN.
! 2383: * Clear ATN and just continue, the
! 2384: * target should be in the command
! 2385: * phase.
! 2386: * XXXX check for command phase?
! 2387: */
! 2388: NCRCMD(sc, NCRCMD_RSTATN);
! 2389: break;
! 2390: case 1:
! 2391: if ((ti->flags & T_NEGOTIATE) == 0 &&
! 2392: ecb->tag[0] == 0) {
! 2393: printf("%s: step 1 & !NEG\n",
! 2394: sc->sc_dev.dv_xname);
! 2395: goto reset;
! 2396: }
! 2397: if (sc->sc_phase != MESSAGE_OUT_PHASE) {
! 2398: printf("%s: !MSGOUT\n",
! 2399: sc->sc_dev.dv_xname);
! 2400: goto reset;
! 2401: }
! 2402: if (ti->flags & T_WIDE) {
! 2403: ncr53c9x_sched_msgout(SEND_WDTR);
! 2404: }
! 2405: if (ti->flags & T_NEGOTIATE) {
! 2406: /* Start negotiating */
! 2407: ti->period = sc->sc_minsync;
! 2408: ti->offset = 15;
! 2409: sc->sc_flags |= NCR_SYNCHNEGO;
! 2410: if (ecb->tag[0])
! 2411: ncr53c9x_sched_msgout(SEND_TAG|SEND_SDTR);
! 2412: else
! 2413: ncr53c9x_sched_msgout(SEND_SDTR);
! 2414: } else {
! 2415: /* Could not do ATN3 so send TAG */
! 2416: ncr53c9x_sched_msgout(SEND_TAG);
! 2417: }
! 2418: sc->sc_prevphase = MESSAGE_OUT_PHASE; /* XXXX */
! 2419: break;
! 2420: case 3:
! 2421: /*
! 2422: * Grr, this is supposed to mean
! 2423: * "target left command phase prematurely".
! 2424: * It seems to happen regularly when
! 2425: * sync mode is on.
! 2426: * Look at FIFO to see if command went out.
! 2427: * (Timing problems?)
! 2428: */
! 2429: if (sc->sc_features & NCR_F_DMASELECT) {
! 2430: if (sc->sc_cmdlen == 0)
! 2431: /* Hope for the best.. */
! 2432: break;
! 2433: } else if ((NCR_READ_REG(sc, NCR_FFLAG)
! 2434: & NCRFIFO_FF) == 0) {
! 2435: /* Hope for the best.. */
! 2436: break;
! 2437: }
! 2438: printf("(%s:%d:%d): selection failed;"
! 2439: " %d left in FIFO "
! 2440: "[intr %x, stat %x, step %d]\n",
! 2441: sc->sc_dev.dv_xname,
! 2442: sc_link->target,
! 2443: sc_link->lun,
! 2444: NCR_READ_REG(sc, NCR_FFLAG)
! 2445: & NCRFIFO_FF,
! 2446: sc->sc_espintr, sc->sc_espstat,
! 2447: sc->sc_espstep);
! 2448: NCRCMD(sc, NCRCMD_FLUSH);
! 2449: ncr53c9x_sched_msgout(SEND_ABORT);
! 2450: return (1);
! 2451: case 2:
! 2452: /* Select stuck at Command Phase */
! 2453: NCRCMD(sc, NCRCMD_FLUSH);
! 2454: break;
! 2455: case 4:
! 2456: if (sc->sc_features & NCR_F_DMASELECT &&
! 2457: sc->sc_cmdlen != 0)
! 2458: printf("(%s:%d:%d): select; "
! 2459: "%lu left in DMA buffer "
! 2460: "[intr %x, stat %x, step %d]\n",
! 2461: sc->sc_dev.dv_xname,
! 2462: sc_link->target,
! 2463: sc_link->lun,
! 2464: (u_long)sc->sc_cmdlen,
! 2465: sc->sc_espintr,
! 2466: sc->sc_espstat,
! 2467: sc->sc_espstep);
! 2468: /* So far, everything went fine */
! 2469: break;
! 2470: }
! 2471:
! 2472: sc->sc_prevphase = INVALID_PHASE; /* ?? */
! 2473: /* Do an implicit RESTORE POINTERS. */
! 2474: sc->sc_dp = ecb->daddr;
! 2475: sc->sc_dleft = ecb->dleft;
! 2476: sc->sc_state = NCR_CONNECTED;
! 2477: break;
! 2478:
! 2479: } else {
! 2480:
! 2481: printf("%s: unexpected status after select"
! 2482: ": [intr %x, stat %x, step %x]\n",
! 2483: sc->sc_dev.dv_xname,
! 2484: sc->sc_espintr, sc->sc_espstat,
! 2485: sc->sc_espstep);
! 2486: NCRCMD(sc, NCRCMD_FLUSH);
! 2487: DELAY(1);
! 2488: goto reset;
! 2489: }
! 2490: if (sc->sc_state == NCR_IDLE) {
! 2491: printf("%s: stray interrupt\n",
! 2492: sc->sc_dev.dv_xname);
! 2493: return (0);
! 2494: }
! 2495: break;
! 2496:
! 2497: case NCR_CONNECTED:
! 2498: if (sc->sc_flags & NCR_ICCS) {
! 2499: /* "Initiate Command Complete Steps" in progress */
! 2500: u_char msg;
! 2501:
! 2502: sc->sc_flags &= ~NCR_ICCS;
! 2503:
! 2504: if (!(sc->sc_espintr & NCRINTR_DONE)) {
! 2505: printf("%s: ICCS: "
! 2506: ": [intr %x, stat %x, step %x]\n",
! 2507: sc->sc_dev.dv_xname,
! 2508: sc->sc_espintr, sc->sc_espstat,
! 2509: sc->sc_espstep);
! 2510: }
! 2511: ncr53c9x_rdfifo(sc, NCR_RDFIFO_START);
! 2512: if (sc->sc_imlen < 2)
! 2513: printf("%s: can't get status, only %d bytes\n",
! 2514: sc->sc_dev.dv_xname, (int)sc->sc_imlen);
! 2515: ecb->stat = sc->sc_imess[sc->sc_imlen - 2];
! 2516: msg = sc->sc_imess[sc->sc_imlen - 1];
! 2517: NCR_PHASE(("<stat:(%x,%x)>", ecb->stat, msg));
! 2518: if (msg == MSG_CMDCOMPLETE) {
! 2519: ecb->dleft = (ecb->flags & ECB_TENTATIVE_DONE)
! 2520: ? 0
! 2521: : sc->sc_dleft;
! 2522: if ((ecb->flags & ECB_SENSE) == 0)
! 2523: ecb->xs->resid = ecb->dleft;
! 2524: sc->sc_state = NCR_CMDCOMPLETE;
! 2525: } else
! 2526: printf("%s: STATUS_PHASE: msg %d\n",
! 2527: sc->sc_dev.dv_xname, msg);
! 2528: sc->sc_imlen = 0;
! 2529: NCRCMD(sc, NCRCMD_MSGOK);
! 2530: goto shortcut; /* ie. wait for disconnect */
! 2531: }
! 2532: break;
! 2533: default:
! 2534: /* Don't panic: reset. */
! 2535: printf("%s: invalid state: %d\n",
! 2536: sc->sc_dev.dv_xname,
! 2537: sc->sc_state);
! 2538: ncr53c9x_scsi_reset(sc);
! 2539: goto out;
! 2540: break;
! 2541: }
! 2542:
! 2543: /*
! 2544: * Driver is now in state NCR_CONNECTED, i.e. we
! 2545: * have a current command working the SCSI bus.
! 2546: */
! 2547: if (sc->sc_state != NCR_CONNECTED || ecb == NULL) {
! 2548: panic("ncr53c9x no nexus");
! 2549: }
! 2550:
! 2551: switch (sc->sc_phase) {
! 2552: case MESSAGE_OUT_PHASE:
! 2553: NCR_PHASE(("MESSAGE_OUT_PHASE "));
! 2554: ncr53c9x_msgout(sc);
! 2555: sc->sc_prevphase = MESSAGE_OUT_PHASE;
! 2556: break;
! 2557: case MESSAGE_IN_PHASE:
! 2558: msgin:
! 2559: NCR_PHASE(("MESSAGE_IN_PHASE "));
! 2560: if (sc->sc_espintr & NCRINTR_BS) {
! 2561: if ((sc->sc_rev != NCR_VARIANT_FAS366) ||
! 2562: !(sc->sc_espstat2 & FAS_STAT2_EMPTY)) {
! 2563: NCRCMD(sc, NCRCMD_FLUSH);
! 2564: }
! 2565: sc->sc_flags |= NCR_WAITI;
! 2566: NCRCMD(sc, NCRCMD_TRANS);
! 2567: } else if (sc->sc_espintr & NCRINTR_FC) {
! 2568: if ((sc->sc_flags & NCR_WAITI) == 0) {
! 2569: printf("%s: MSGIN: unexpected FC bit: "
! 2570: "[intr %x, stat %x, step %x]\n",
! 2571: sc->sc_dev.dv_xname,
! 2572: sc->sc_espintr, sc->sc_espstat,
! 2573: sc->sc_espstep);
! 2574: }
! 2575: sc->sc_flags &= ~NCR_WAITI;
! 2576: ncr53c9x_rdfifo(sc,
! 2577: (sc->sc_prevphase == sc->sc_phase) ?
! 2578: NCR_RDFIFO_CONTINUE : NCR_RDFIFO_START);
! 2579: ncr53c9x_msgin(sc);
! 2580: } else {
! 2581: printf("%s: MSGIN: weird bits: "
! 2582: "[intr %x, stat %x, step %x]\n",
! 2583: sc->sc_dev.dv_xname,
! 2584: sc->sc_espintr, sc->sc_espstat,
! 2585: sc->sc_espstep);
! 2586: }
! 2587: sc->sc_prevphase = MESSAGE_IN_PHASE;
! 2588: goto shortcut; /* i.e. expect data to be ready */
! 2589: break;
! 2590: case COMMAND_PHASE:
! 2591: /*
! 2592: * Send the command block. Normally we don't see this
! 2593: * phase because the SEL_ATN command takes care of
! 2594: * all this. However, we end up here if either the
! 2595: * target or we wanted to exchange some more messages
! 2596: * first (e.g. to start negotiations).
! 2597: */
! 2598:
! 2599: NCR_PHASE(("COMMAND_PHASE 0x%02x (%d) ",
! 2600: ecb->cmd.cmd.opcode, ecb->clen));
! 2601: if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
! 2602: NCRCMD(sc, NCRCMD_FLUSH);
! 2603: /* DELAY(1); */
! 2604: }
! 2605: if (sc->sc_features & NCR_F_DMASELECT) {
! 2606: size_t size;
! 2607: /* setup DMA transfer for command */
! 2608: size = ecb->clen;
! 2609: sc->sc_cmdlen = size;
! 2610: sc->sc_cmdp = (caddr_t)&ecb->cmd.cmd;
! 2611: NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen,
! 2612: 0, &size);
! 2613: /* Program the SCSI counter */
! 2614: NCR_SET_COUNT(sc, size);
! 2615:
! 2616: /* load the count in */
! 2617: NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
! 2618:
! 2619: /* start the command transfer */
! 2620: NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA);
! 2621: NCRDMA_GO(sc);
! 2622: } else {
! 2623: ncr53c9x_wrfifo(sc, (u_char *)&ecb->cmd.cmd, ecb->clen);
! 2624: NCRCMD(sc, NCRCMD_TRANS);
! 2625: }
! 2626: sc->sc_prevphase = COMMAND_PHASE;
! 2627: break;
! 2628: case DATA_OUT_PHASE:
! 2629: NCR_PHASE(("DATA_OUT_PHASE [%ld] ",(long)sc->sc_dleft));
! 2630: NCRCMD(sc, NCRCMD_FLUSH);
! 2631: size = min(sc->sc_dleft, sc->sc_maxxfer);
! 2632: NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft,
! 2633: 0, &size);
! 2634: sc->sc_prevphase = DATA_OUT_PHASE;
! 2635: goto setup_xfer;
! 2636: case DATA_IN_PHASE:
! 2637: NCR_PHASE(("DATA_IN_PHASE "));
! 2638: if (sc->sc_rev == NCR_VARIANT_ESP100)
! 2639: NCRCMD(sc, NCRCMD_FLUSH);
! 2640: size = min(sc->sc_dleft, sc->sc_maxxfer);
! 2641: NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft,
! 2642: 1, &size);
! 2643: sc->sc_prevphase = DATA_IN_PHASE;
! 2644: setup_xfer:
! 2645: /* Target returned to data phase: wipe "done" memory */
! 2646: ecb->flags &= ~ECB_TENTATIVE_DONE;
! 2647:
! 2648: /* Program the SCSI counter */
! 2649: NCR_SET_COUNT(sc, size);
! 2650:
! 2651: /* load the count in */
! 2652: NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
! 2653:
! 2654: /*
! 2655: * Note that if `size' is 0, we've already transceived
! 2656: * all the bytes we want but we're still in DATA PHASE.
! 2657: * Apparently, the device needs padding. Also, a
! 2658: * transfer size of 0 means "maximum" to the chip
! 2659: * DMA logic.
! 2660: */
! 2661: NCRCMD(sc,
! 2662: (size==0?NCRCMD_TRPAD:NCRCMD_TRANS)|NCRCMD_DMA);
! 2663: NCRDMA_GO(sc);
! 2664: return (1);
! 2665: case STATUS_PHASE:
! 2666: NCR_PHASE(("STATUS_PHASE "));
! 2667: sc->sc_flags |= NCR_ICCS;
! 2668: NCRCMD(sc, NCRCMD_ICCS);
! 2669: sc->sc_prevphase = STATUS_PHASE;
! 2670: goto shortcut; /* i.e. expect status results soon */
! 2671: break;
! 2672: case INVALID_PHASE:
! 2673: break;
! 2674: default:
! 2675: printf("%s: unexpected bus phase; resetting\n",
! 2676: sc->sc_dev.dv_xname);
! 2677: goto reset;
! 2678: }
! 2679:
! 2680: out:
! 2681: return (1);
! 2682:
! 2683: reset:
! 2684: ncr53c9x_init(sc, 1);
! 2685: goto out;
! 2686:
! 2687: finish:
! 2688: ncr53c9x_done(sc, ecb);
! 2689: goto out;
! 2690:
! 2691: sched:
! 2692: sc->sc_state = NCR_IDLE;
! 2693: ncr53c9x_sched(sc);
! 2694: goto out;
! 2695:
! 2696: shortcut:
! 2697: /*
! 2698: * The idea is that many of the SCSI operations take very little
! 2699: * time, and going away and getting interrupted is too high an
! 2700: * overhead to pay. For example, selecting, sending a message
! 2701: * and command and then doing some work can be done in one "pass".
! 2702: *
! 2703: * The delay is a heuristic. It is 2 when at 20MHz, 2 at 25MHz and 1
! 2704: * at 40MHz. This needs testing.
! 2705: */
! 2706: {
! 2707: struct timeval wait, cur;
! 2708:
! 2709: microtime(&wait);
! 2710: wait.tv_usec += 50/sc->sc_freq;
! 2711: if (wait.tv_usec > 1000000) {
! 2712: wait.tv_sec++;
! 2713: wait.tv_usec -= 1000000;
! 2714: }
! 2715: do {
! 2716: if (NCRDMA_ISINTR(sc))
! 2717: goto again;
! 2718: microtime(&cur);
! 2719: } while (timercmp(&cur, &wait, <=));
! 2720: }
! 2721: goto out;
! 2722: }
! 2723:
! 2724: void
! 2725: ncr53c9x_abort(sc, ecb)
! 2726: struct ncr53c9x_softc *sc;
! 2727: struct ncr53c9x_ecb *ecb;
! 2728: {
! 2729:
! 2730: /* 2 secs for the abort */
! 2731: ecb->timeout = NCR_ABORT_TIMEOUT;
! 2732: ecb->flags |= ECB_ABORT;
! 2733:
! 2734: if (ecb == sc->sc_nexus) {
! 2735: int timeout = ecb->timeout;
! 2736:
! 2737: /*
! 2738: * If we're still selecting, the message will be scheduled
! 2739: * after selection is complete.
! 2740: */
! 2741: if (sc->sc_state == NCR_CONNECTED)
! 2742: ncr53c9x_sched_msgout(SEND_ABORT);
! 2743:
! 2744: /*
! 2745: * Reschedule timeout.
! 2746: */
! 2747: if (timeout > 1000000)
! 2748: timeout = (timeout / 1000) * hz;
! 2749: else
! 2750: timeout = (timeout * hz) / 1000;
! 2751: timeout_add(&ecb->to, timeout);
! 2752: } else {
! 2753: /*
! 2754: * Just leave the command where it is.
! 2755: * XXX - what choice do we have but to reset the SCSI
! 2756: * eventually?
! 2757: */
! 2758: if (sc->sc_state == NCR_IDLE)
! 2759: ncr53c9x_sched(sc);
! 2760: }
! 2761: }
! 2762:
! 2763: void
! 2764: ncr53c9x_timeout(arg)
! 2765: void *arg;
! 2766: {
! 2767: struct ncr53c9x_ecb *ecb = arg;
! 2768: struct scsi_xfer *xs = ecb->xs;
! 2769: struct scsi_link *sc_link = xs->sc_link;
! 2770: struct ncr53c9x_softc *sc = sc_link->adapter_softc;
! 2771: struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[sc_link->target];
! 2772: int s;
! 2773:
! 2774: sc_print_addr(sc_link);
! 2775: printf("%s: timed out [ecb %p (flags 0x%x, dleft %x, stat %x)], "
! 2776: "<state %d, nexus %p, phase(l %x, c %x, p %x), resid %lx, "
! 2777: "msg(q %x,o %x) %s>",
! 2778: sc->sc_dev.dv_xname,
! 2779: ecb, ecb->flags, ecb->dleft, ecb->stat,
! 2780: sc->sc_state, sc->sc_nexus,
! 2781: NCR_READ_REG(sc, NCR_STAT),
! 2782: sc->sc_phase, sc->sc_prevphase,
! 2783: (long)sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout,
! 2784: NCRDMA_ISACTIVE(sc) ? "DMA active" : "");
! 2785: #if NCR53C9X_DEBUG > 1
! 2786: printf("TRACE: %s.", ecb->trace);
! 2787: #endif
! 2788:
! 2789: s = splbio();
! 2790:
! 2791: if (ecb->flags & ECB_ABORT) {
! 2792: /* abort timed out */
! 2793: printf(" AGAIN\n");
! 2794:
! 2795: ncr53c9x_init(sc, 1);
! 2796: } else {
! 2797: /* abort the operation that has timed out */
! 2798: printf("\n");
! 2799: xs->error = XS_TIMEOUT;
! 2800: ncr53c9x_abort(sc, ecb);
! 2801:
! 2802: /* Disable sync mode if stuck in a data phase */
! 2803: if (ecb == sc->sc_nexus &&
! 2804: (ti->flags & T_SYNCMODE) != 0 &&
! 2805: (sc->sc_phase & (MSGI|CDI)) == 0) {
! 2806: sc_print_addr(sc_link);
! 2807: printf("sync negotiation disabled\n");
! 2808: sc->sc_cfflags |= (1 << (sc_link->target + 16));
! 2809: }
! 2810: }
! 2811:
! 2812: splx(s);
! 2813: }
! 2814:
! 2815: void
! 2816: ncr53c9x_watch(arg)
! 2817: void *arg;
! 2818: {
! 2819: struct ncr53c9x_softc *sc = (struct ncr53c9x_softc *)arg;
! 2820: struct ncr53c9x_tinfo *ti;
! 2821: struct ncr53c9x_linfo *li;
! 2822: int t, s;
! 2823: /* Delete any structures that have not been used in 10min. */
! 2824: time_t old = time_second - (10*60);
! 2825:
! 2826: s = splbio();
! 2827: for (t = 0; t < sc->sc_ntarg; t++) {
! 2828: ti = &sc->sc_tinfo[t];
! 2829: for (li = LIST_FIRST(&ti->luns); li != LIST_END(&ti->luns); ) {
! 2830: if (li->last_used < old && !li->untagged && !li->used) {
! 2831: if (li->lun < NCR_NLUN)
! 2832: ti->lun[li->lun] = NULL;
! 2833: LIST_REMOVE(li, link);
! 2834: free(li, M_DEVBUF);
! 2835: /* Restart the search at the beginning */
! 2836: li = LIST_FIRST(&ti->luns);
! 2837: continue;
! 2838: }
! 2839: li = LIST_NEXT(li, link);
! 2840: }
! 2841: }
! 2842: splx(s);
! 2843: timeout_add(&sc->sc_watchdog, 60*hz);
! 2844: }
CVSweb