Annotation of sys/arch/hp300/dev/mb89352.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: mb89352.c,v 1.15 2006/11/28 23:59:45 dlg Exp $ */
! 2: /* $NetBSD: mb89352.c,v 1.5 2000/03/23 07:01:31 thorpej Exp $ */
! 3: /* NecBSD: mb89352.c,v 1.4 1998/03/14 07:31:20 kmatsuda Exp */
! 4:
! 5: /*-
! 6: * Copyright (c) 1996,97,98,99 The NetBSD Foundation, Inc.
! 7: * All rights reserved.
! 8: *
! 9: * This code is derived from software contributed to The NetBSD Foundation
! 10: * by Charles M. Hannum, Masaru Oki and Kouichi Matsuda.
! 11: *
! 12: * Redistribution and use in source and binary forms, with or without
! 13: * modification, are permitted provided that the following conditions
! 14: * are met:
! 15: * 1. Redistributions of source code must retain the above copyright
! 16: * notice, this list of conditions and the following disclaimer.
! 17: * 2. Redistributions in binary form must reproduce the above copyright
! 18: * notice, this list of conditions and the following disclaimer in the
! 19: * documentation and/or other materials provided with the distribution.
! 20: * 3. All advertising materials mentioning features or use of this software
! 21: * must display the following acknowledgement:
! 22: * This product includes software developed by Charles M. Hannum.
! 23: * 4. The name of the author may not be used to endorse or promote products
! 24: * derived from this software without specific prior written permission.
! 25: *
! 26: * Copyright (c) 1994 Jarle Greipsland
! 27: * All rights reserved.
! 28: *
! 29: * Redistribution and use in source and binary forms, with or without
! 30: * modification, are permitted provided that the following conditions
! 31: * are met:
! 32: * 1. Redistributions of source code must retain the above copyright
! 33: * notice, this list of conditions and the following disclaimer.
! 34: * 2. Redistributions in binary form must reproduce the above copyright
! 35: * notice, this list of conditions and the following disclaimer in the
! 36: * documentation and/or other materials provided with the distribution.
! 37: * 3. The name of the author may not be used to endorse or promote products
! 38: * derived from this software without specific prior written permission.
! 39: *
! 40: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 41: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
! 42: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
! 43: * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
! 44: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
! 45: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
! 46: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 47: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
! 48: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
! 49: * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 50: * POSSIBILITY OF SUCH DAMAGE.
! 51: */
! 52: /*
! 53: * [NetBSD for NEC PC-98 series]
! 54: * Copyright (c) 1996, 1997, 1998
! 55: * NetBSD/pc98 porting staff. All rights reserved.
! 56: * Copyright (c) 1996, 1997, 1998
! 57: * Kouichi Matsuda. All rights reserved.
! 58: */
! 59:
! 60: /*
! 61: * Acknowledgements: Many of the algorithms used in this driver are
! 62: * inspired by the work of Julian Elischer (julian@tfs.com) and
! 63: * Charles Hannum (mycroft@duality.gnu.ai.mit.edu). Thanks a million!
! 64: */
! 65:
! 66: /*
! 67: * A few customizable items:
! 68: */
! 69:
! 70: /* Synchronous data transfers? */
! 71: #define SPC_USE_SYNCHRONOUS 0
! 72: #define SPC_SYNC_REQ_ACK_OFS 8
! 73:
! 74: /* Wide data transfers? */
! 75: #define SPC_USE_WIDE 0
! 76: #define SPC_MAX_WIDTH 0
! 77:
! 78: /* Max attempts made to transmit a message */
! 79: #define SPC_MSG_MAX_ATTEMPT 3 /* Not used now XXX */
! 80:
! 81: /*
! 82: * Some spin loop parameters (essentially how long to wait some places)
! 83: * The problem(?) is that sometimes we expect either to be able to transmit a
! 84: * byte or to get a new one from the SCSI bus pretty soon. In order to avoid
! 85: * returning from the interrupt just to get yanked back for the next byte we
! 86: * may spin in the interrupt routine waiting for this byte to come. How long?
! 87: * This is really (SCSI) device and processor dependent. Tunable, I guess.
! 88: */
! 89: #define SPC_MSGIN_SPIN 1 /* Will spinwait upto ?ms for a new msg byte */
! 90: #define SPC_MSGOUT_SPIN 1
! 91:
! 92: /*
! 93: * Include debug functions? At the end of this file there are a bunch of
! 94: * functions that will print out various information regarding queued SCSI
! 95: * commands, driver state and chip contents. You can call them from the
! 96: * kernel debugger. If you set SPC_DEBUG to 0 they are not included (the
! 97: * kernel uses less memory) but you lose the debugging facilities.
! 98: */
! 99: #if 0
! 100: #define SPC_DEBUG
! 101: #endif
! 102:
! 103: #define SPC_ABORT_TIMEOUT 2000 /* time to wait for abort */
! 104:
! 105: /* threshold length for DMA transfer */
! 106: #define SPC_MIN_DMA_LEN 32
! 107:
! 108: /* End of customizable parameters */
! 109:
! 110: /*
! 111: * MB89352 SCSI Protocol Controller (SPC) routines.
! 112: */
! 113:
! 114: #include <sys/param.h>
! 115: #include <sys/systm.h>
! 116: #include <sys/kernel.h>
! 117: #include <sys/errno.h>
! 118: #include <sys/ioctl.h>
! 119: #include <sys/device.h>
! 120: #include <sys/buf.h>
! 121: #include <sys/proc.h>
! 122: #include <sys/user.h>
! 123: #include <sys/queue.h>
! 124:
! 125: #include <machine/intr.h>
! 126:
! 127: #include <scsi/scsi_all.h>
! 128: #include <scsi/scsi_message.h>
! 129: #include <scsi/scsiconf.h>
! 130:
! 131: #include <hp300/dev/mb89352reg.h>
! 132: #include <hp300/dev/mb89352var.h>
! 133:
! 134: #ifdef SPC_DEBUG
! 135: int spc_debug = 0x00; /* SPC_SHOWSTART|SPC_SHOWMISC|SPC_SHOWTRACE; */
! 136: #endif
! 137:
! 138: void spc_done (struct spc_softc *, struct spc_acb *);
! 139: void spc_dequeue (struct spc_softc *, struct spc_acb *);
! 140: int spc_scsi_cmd (struct scsi_xfer *);
! 141: int spc_poll (struct spc_softc *, struct scsi_xfer *, int);
! 142: void spc_sched_msgout(struct spc_softc *, u_char);
! 143: void spc_setsync(struct spc_softc *, struct spc_tinfo *);
! 144: void spc_select (struct spc_softc *, struct spc_acb *);
! 145: void spc_timeout (void *);
! 146: void spc_scsi_reset (struct spc_softc *);
! 147: void spc_free_acb (struct spc_softc *, struct spc_acb *, int);
! 148: struct spc_acb* spc_get_acb(struct spc_softc *, int);
! 149: int spc_reselect (struct spc_softc *, int);
! 150: void spc_sense (struct spc_softc *, struct spc_acb *);
! 151: void spc_msgin (struct spc_softc *);
! 152: void spc_abort (struct spc_softc *, struct spc_acb *);
! 153: void spc_msgout (struct spc_softc *);
! 154: int spc_dataout_pio (struct spc_softc *, u_char *, int);
! 155: int spc_datain_pio (struct spc_softc *, u_char *, int);
! 156: void spc_process_intr(void *, u_char);
! 157: #ifdef SPC_DEBUG
! 158: void spc_print_acb (struct spc_acb *);
! 159: void spc_dump_driver (struct spc_softc *);
! 160: void spc_dump89352 (struct spc_softc *);
! 161: void spc_show_scsi_cmd(struct spc_acb *);
! 162: void spc_print_active_acb(void);
! 163: #endif
! 164:
! 165: extern struct cfdriver spc_cd;
! 166:
! 167: struct scsi_device spc_dev = {
! 168: NULL, /* Use default error handler */
! 169: NULL, /* have a queue, served by this */
! 170: NULL, /* have no async handler */
! 171: NULL, /* Use default 'done' routine */
! 172: };
! 173:
! 174: struct scsi_adapter spc_switch = {
! 175: spc_scsi_cmd,
! 176: minphys,
! 177: NULL,
! 178: NULL
! 179: };
! 180:
! 181: /*
! 182: * INITIALIZATION ROUTINES (probe, attach ++)
! 183: */
! 184:
! 185: void
! 186: spc_attach(struct spc_softc *sc)
! 187: {
! 188: struct scsibus_attach_args saa;
! 189:
! 190: SPC_TRACE(("spc_attach "));
! 191: sc->sc_state = SPC_INIT;
! 192:
! 193: sc->sc_freq = 20; /* XXX Assume 20 MHz. */
! 194:
! 195: #if SPC_USE_SYNCHRONOUS
! 196: /*
! 197: * These are the bounds of the sync period, based on the frequency of
! 198: * the chip's clock input and the size and offset of the sync period
! 199: * register.
! 200: *
! 201: * For a 20MHz clock, this gives us 25, or 100nS, or 10MB/s, as a
! 202: * maximum transfer rate, and 112.5, or 450nS, or 2.22MB/s, as a
! 203: * minimum transfer rate.
! 204: */
! 205: sc->sc_minsync = (2 * 250) / sc->sc_freq;
! 206: sc->sc_maxsync = (9 * 250) / sc->sc_freq;
! 207: #endif
! 208:
! 209: spc_init(sc); /* Init chip and driver */
! 210:
! 211: /*
! 212: * Fill in the adapter.
! 213: */
! 214: sc->sc_link.adapter_softc = sc;
! 215: sc->sc_link.adapter_target = sc->sc_initiator;
! 216: sc->sc_link.adapter = &spc_switch;
! 217: sc->sc_link.device = &spc_dev;
! 218: sc->sc_link.openings = 2;
! 219:
! 220: bzero(&saa, sizeof(saa));
! 221: saa.saa_sc_link = &sc->sc_link;
! 222:
! 223: /*
! 224: * ask the adapter what subunits are present
! 225: */
! 226: config_found(&sc->sc_dev, &saa, scsiprint);
! 227: }
! 228:
! 229: /*
! 230: * Initialize the MB89352 chip itself.
! 231: */
! 232: void
! 233: spc_reset(struct spc_softc *sc)
! 234: {
! 235: SPC_TRACE(("spc_reset "));
! 236: /*
! 237: * Disable interrupts then reset the FUJITSU chip.
! 238: */
! 239: spc_write(SCTL, SCTL_DISABLE | SCTL_CTRLRST);
! 240: spc_write(SCMD, 0);
! 241: spc_write(TMOD, 0);
! 242: spc_write(PCTL, 0);
! 243: spc_write(TEMP, 0);
! 244: spc_write(TCH, 0);
! 245: spc_write(TCM, 0);
! 246: spc_write(TCL, 0);
! 247: spc_write(INTS, 0);
! 248: spc_write(SCTL, sc->sc_ctlflags |
! 249: SCTL_DISABLE | SCTL_ABRT_ENAB | SCTL_SEL_ENAB | SCTL_RESEL_ENAB);
! 250: spc_write(BDID, sc->sc_initiator);
! 251: delay(400);
! 252: spc_write(SCTL, spc_read(SCTL) & ~SCTL_DISABLE);
! 253: }
! 254:
! 255:
! 256: /*
! 257: * Pull the SCSI RST line for 500us.
! 258: */
! 259: void
! 260: spc_scsi_reset(struct spc_softc *sc)
! 261: {
! 262: SPC_TRACE(("spc_scsi_reset "));
! 263: spc_write(SCMD, spc_read(SCMD) | SCMD_RST);
! 264: delay(500);
! 265: spc_write(SCMD, spc_read(SCMD) & ~SCMD_RST);
! 266: delay(50);
! 267: }
! 268:
! 269: /*
! 270: * Initialize spc SCSI driver.
! 271: */
! 272: void
! 273: spc_init(struct spc_softc *sc)
! 274: {
! 275: struct spc_acb *acb;
! 276: int r;
! 277:
! 278: SPC_TRACE(("spc_init "));
! 279: (*sc->sc_reset)(sc);
! 280: spc_scsi_reset(sc);
! 281: (*sc->sc_reset)(sc);
! 282:
! 283: if (sc->sc_state == SPC_INIT) {
! 284: /* First time through; initialize. */
! 285: TAILQ_INIT(&sc->ready_list);
! 286: TAILQ_INIT(&sc->nexus_list);
! 287: TAILQ_INIT(&sc->free_list);
! 288: sc->sc_nexus = NULL;
! 289: acb = sc->sc_acb;
! 290: bzero(acb, sizeof(sc->sc_acb));
! 291: for (r = 0; r < sizeof(sc->sc_acb) / sizeof(*acb); r++) {
! 292: TAILQ_INSERT_TAIL(&sc->free_list, acb, chain);
! 293: acb++;
! 294: }
! 295: bzero(&sc->sc_tinfo, sizeof(sc->sc_tinfo));
! 296: } else {
! 297: /* Cancel any active commands. */
! 298: sc->sc_state = SPC_CLEANING;
! 299: if ((acb = sc->sc_nexus) != NULL) {
! 300: acb->xs->error = XS_DRIVER_STUFFUP;
! 301: spc_done(sc, acb);
! 302: }
! 303: while ((acb = TAILQ_FIRST(&sc->nexus_list)) != NULL) {
! 304: acb->xs->error = XS_DRIVER_STUFFUP;
! 305: spc_done(sc, acb);
! 306: }
! 307: }
! 308:
! 309: sc->sc_prevphase = PH_INVALID;
! 310: for (r = 0; r < 8; r++) {
! 311: struct spc_tinfo *ti = &sc->sc_tinfo[r];
! 312:
! 313: ti->flags = 0;
! 314: #if SPC_USE_SYNCHRONOUS
! 315: ti->flags |= DO_SYNC;
! 316: ti->period = sc->sc_minsync;
! 317: ti->offset = SPC_SYNC_REQ_ACK_OFS;
! 318: #else
! 319: ti->period = ti->offset = 0;
! 320: #endif
! 321: #if SPC_USE_WIDE
! 322: ti->flags |= DO_WIDE;
! 323: ti->width = SPC_MAX_WIDTH;
! 324: #else
! 325: ti->width = 0;
! 326: #endif
! 327: }
! 328:
! 329: sc->sc_state = SPC_IDLE;
! 330: spc_write(SCTL, spc_read(SCTL) | SCTL_INTR_ENAB);
! 331: }
! 332:
! 333: void
! 334: spc_free_acb(struct spc_softc *sc, struct spc_acb *acb, int flags)
! 335: {
! 336: int s;
! 337:
! 338: SPC_TRACE(("spc_free_acb "));
! 339: s = splbio();
! 340:
! 341: acb->flags = 0;
! 342: TAILQ_INSERT_HEAD(&sc->free_list, acb, chain);
! 343:
! 344: /*
! 345: * If there were none, wake anybody waiting for one to come free,
! 346: * starting with queued entries.
! 347: */
! 348: if (TAILQ_NEXT(acb, chain) == NULL)
! 349: wakeup(&sc->free_list);
! 350:
! 351: splx(s);
! 352: }
! 353:
! 354: struct spc_acb *
! 355: spc_get_acb(struct spc_softc *sc, int flags)
! 356: {
! 357: struct spc_acb *acb;
! 358: int s;
! 359:
! 360: SPC_TRACE(("spc_get_acb "));
! 361: s = splbio();
! 362:
! 363: while ((acb = TAILQ_FIRST(&sc->free_list)) == NULL &&
! 364: (flags & SCSI_NOSLEEP) == 0)
! 365: tsleep(&sc->free_list, PRIBIO, "spcacb", 0);
! 366: if (acb) {
! 367: TAILQ_REMOVE(&sc->free_list, acb, chain);
! 368: acb->flags |= ACB_ALLOC;
! 369: }
! 370:
! 371: splx(s);
! 372: return acb;
! 373: }
! 374:
! 375: /*
! 376: * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS
! 377: */
! 378:
! 379: /*
! 380: * Expected sequence:
! 381: * 1) Command inserted into ready list
! 382: * 2) Command selected for execution
! 383: * 3) Command won arbitration and has selected target device
! 384: * 4) Send message out (identify message, eventually also sync.negotiations)
! 385: * 5) Send command
! 386: * 5a) Receive disconnect message, disconnect.
! 387: * 5b) Reselected by target
! 388: * 5c) Receive identify message from target.
! 389: * 6) Send or receive data
! 390: * 7) Receive status
! 391: * 8) Receive message (command complete etc.)
! 392: * 9) If status == SCSI_CHECK construct a synthetic request sense SCSI cmd.
! 393: * Repeat 2-8 (no disconnects please...)
! 394: */
! 395:
! 396: /*
! 397: * Start a SCSI-command
! 398: * This function is called by the higher level SCSI-driver to queue/run
! 399: * SCSI-commands.
! 400: */
! 401: int
! 402: spc_scsi_cmd(struct scsi_xfer *xs)
! 403: {
! 404: struct scsi_link *sc_link = xs->sc_link;
! 405: struct spc_softc *sc = sc_link->adapter_softc;
! 406: struct spc_acb *acb;
! 407: int s, flags;
! 408:
! 409: SPC_TRACE(("spc_scsi_cmd "));
! 410: SPC_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
! 411: sc_link->target));
! 412:
! 413: flags = xs->flags;
! 414: if ((acb = spc_get_acb(sc, flags)) == NULL) {
! 415: return TRY_AGAIN_LATER;
! 416: }
! 417:
! 418: /* Initialize acb */
! 419: acb->xs = xs;
! 420: acb->timeout = xs->timeout;
! 421:
! 422: if (xs->flags & SCSI_RESET) {
! 423: acb->flags |= ACB_RESET;
! 424: acb->scsi_cmd_length = 0;
! 425: acb->data_length = 0;
! 426: } else {
! 427: bcopy(xs->cmd, &acb->scsi_cmd, xs->cmdlen);
! 428: acb->scsi_cmd_length = xs->cmdlen;
! 429: acb->data_addr = xs->data;
! 430: acb->data_length = xs->datalen;
! 431: }
! 432: acb->target_stat = 0;
! 433:
! 434: s = splbio();
! 435:
! 436: TAILQ_INSERT_TAIL(&sc->ready_list, acb, chain);
! 437: /*
! 438: * Start scheduling unless a queue process is in progress.
! 439: */
! 440: if (sc->sc_state == SPC_IDLE)
! 441: spc_sched(sc);
! 442: /*
! 443: * After successful sending, check if we should return just now.
! 444: * If so, return SUCCESSFULLY_QUEUED.
! 445: */
! 446:
! 447: splx(s);
! 448:
! 449: if ((flags & SCSI_POLL) == 0)
! 450: return SUCCESSFULLY_QUEUED;
! 451:
! 452: /* Not allowed to use interrupts, use polling instead */
! 453: s = splbio();
! 454: if (spc_poll(sc, xs, acb->timeout)) {
! 455: spc_timeout(acb);
! 456: if (spc_poll(sc, xs, acb->timeout))
! 457: spc_timeout(acb);
! 458: }
! 459: splx(s);
! 460: return COMPLETE;
! 461: }
! 462:
! 463: /*
! 464: * Used when interrupt driven I/O isn't allowed, e.g. during boot.
! 465: */
! 466: int
! 467: spc_poll(struct spc_softc *sc, struct scsi_xfer *xs, int count)
! 468: {
! 469: u_char intr;
! 470:
! 471: SPC_TRACE(("spc_poll "));
! 472: while (count) {
! 473: /*
! 474: * If we had interrupts enabled, would we
! 475: * have got an interrupt?
! 476: */
! 477: intr = spc_read(INTS);
! 478: if (intr != 0)
! 479: spc_process_intr(sc, intr);
! 480: if ((xs->flags & ITSDONE) != 0)
! 481: return 0;
! 482: delay(1000);
! 483: count--;
! 484: }
! 485: return 1;
! 486: }
! 487:
! 488: /*
! 489: * LOW LEVEL SCSI UTILITIES
! 490: */
! 491:
! 492: void
! 493: spc_sched_msgout(struct spc_softc *sc, u_char m)
! 494: {
! 495: SPC_TRACE(("spc_sched_msgout "));
! 496: if (sc->sc_msgpriq == 0)
! 497: spc_write(SCMD, SCMD_SET_ATN);
! 498: sc->sc_msgpriq |= m;
! 499: }
! 500:
! 501: /*
! 502: * Set synchronous transfer offset and period.
! 503: */
! 504: void
! 505: spc_setsync(struct spc_softc *sc, struct spc_tinfo *ti)
! 506: {
! 507: #if SPC_USE_SYNCHRONOUS
! 508: SPC_TRACE(("spc_setsync "));
! 509: if (ti->offset != 0)
! 510: spc_write(TMOD,
! 511: ((ti->period * sc->sc_freq) / 250 - 2) << 4 | ti->offset);
! 512: else
! 513: spc_write(TMOD, 0);
! 514: #endif
! 515: }
! 516:
! 517: /*
! 518: * Start a selection. This is used by spc_sched() to select an idle target,
! 519: * and by spc_done() to immediately reselect a target to get sense information.
! 520: */
! 521: void
! 522: spc_select(struct spc_softc *sc, struct spc_acb *acb)
! 523: {
! 524: struct scsi_link *sc_link = acb->xs->sc_link;
! 525: int target = sc_link->target;
! 526: struct spc_tinfo *ti = &sc->sc_tinfo[target];
! 527:
! 528: SPC_TRACE(("spc_select "));
! 529: spc_setsync(sc, ti);
! 530:
! 531: #if 0
! 532: spc_write(SCMD, SCMD_SET_ATN);
! 533: #endif
! 534:
! 535: spc_write(PCTL, 0);
! 536: spc_write(TEMP, (1 << sc->sc_initiator) | (1 << target));
! 537:
! 538: /*
! 539: * Setup BSY timeout (selection timeout).
! 540: * 250ms according to the SCSI specification.
! 541: * T = (X * 256 + 15) * Tclf * 2 (Tclf = 200ns on x68k)
! 542: * To setup 256ms timeout,
! 543: * 128000ns/200ns = X * 256 + 15
! 544: * 640 - 15 = X * 256
! 545: * X = 625 / 256
! 546: * X = 2 + 113 / 256
! 547: * ==> tch = 2, tcm = 113 (correct?)
! 548: */
! 549: /* Time to the information transfer phase start. */
! 550: /* XXX These values should be calculated from sc_freq */
! 551: spc_write(TCH, 2);
! 552: spc_write(TCM, 113);
! 553: spc_write(TCL, 3);
! 554: spc_write(SCMD, SCMD_SELECT);
! 555:
! 556: sc->sc_state = SPC_SELECTING;
! 557: }
! 558:
! 559: int
! 560: spc_reselect(struct spc_softc *sc, int message)
! 561: {
! 562: u_char selid, target, lun;
! 563: struct spc_acb *acb;
! 564: struct scsi_link *sc_link;
! 565: struct spc_tinfo *ti;
! 566:
! 567: SPC_TRACE(("spc_reselect "));
! 568: /*
! 569: * The SCSI chip made a snapshot of the data bus while the reselection
! 570: * was being negotiated. This enables us to determine which target did
! 571: * the reselect.
! 572: */
! 573: selid = sc->sc_selid & ~(1 << sc->sc_initiator);
! 574: if (selid & (selid - 1)) {
! 575: printf("%s: reselect with invalid selid %02x; "
! 576: "sending DEVICE RESET\n", sc->sc_dev.dv_xname, selid);
! 577: SPC_BREAK();
! 578: goto reset;
! 579: }
! 580:
! 581: /*
! 582: * Search wait queue for disconnected cmd
! 583: * The list should be short, so I haven't bothered with
! 584: * any more sophisticated structures than a simple
! 585: * singly linked list.
! 586: */
! 587: target = ffs(selid) - 1;
! 588: lun = message & 0x07;
! 589: TAILQ_FOREACH(acb, &sc->nexus_list, chain) {
! 590: sc_link = acb->xs->sc_link;
! 591: if (sc_link->target == target &&
! 592: sc_link->lun == lun)
! 593: break;
! 594: }
! 595: if (acb == NULL) {
! 596: printf("%s: reselect from target %d lun %d with no nexus; "
! 597: "sending ABORT\n", sc->sc_dev.dv_xname, target, lun);
! 598: SPC_BREAK();
! 599: goto abort;
! 600: }
! 601:
! 602: /* Make this nexus active again. */
! 603: TAILQ_REMOVE(&sc->nexus_list, acb, chain);
! 604: sc->sc_state = SPC_CONNECTED;
! 605: sc->sc_nexus = acb;
! 606: ti = &sc->sc_tinfo[target];
! 607: ti->lubusy |= (1 << lun);
! 608: spc_setsync(sc, ti);
! 609:
! 610: if (acb->flags & ACB_RESET)
! 611: spc_sched_msgout(sc, SEND_DEV_RESET);
! 612: else if (acb->flags & ACB_ABORT)
! 613: spc_sched_msgout(sc, SEND_ABORT);
! 614:
! 615: /* Do an implicit RESTORE POINTERS. */
! 616: sc->sc_dp = acb->data_addr;
! 617: sc->sc_dleft = acb->data_length;
! 618: sc->sc_cp = (u_char *)&acb->scsi_cmd;
! 619: sc->sc_cleft = acb->scsi_cmd_length;
! 620:
! 621: return (0);
! 622:
! 623: reset:
! 624: spc_sched_msgout(sc, SEND_DEV_RESET);
! 625: return (1);
! 626:
! 627: abort:
! 628: spc_sched_msgout(sc, SEND_ABORT);
! 629: return (1);
! 630: }
! 631:
! 632: /*
! 633: * Schedule a SCSI operation. This has now been pulled out of the interrupt
! 634: * handler so that we may call it from spc_scsi_cmd and spc_done. This may
! 635: * save us an unnecessary interrupt just to get things going. Should only be
! 636: * called when state == SPC_IDLE and at bio ipl.
! 637: */
! 638: void
! 639: spc_sched(struct spc_softc *sc)
! 640: {
! 641: struct spc_acb *acb;
! 642: struct scsi_link *sc_link;
! 643: struct spc_tinfo *ti;
! 644:
! 645: splassert(IPL_BIO);
! 646:
! 647: /* missing the hw, just return and wait for our hw */
! 648: if (sc->sc_flags & SPC_INACTIVE)
! 649: return;
! 650: SPC_TRACE(("spc_sched "));
! 651: /*
! 652: * Find first acb in ready queue that is for a target/lunit pair that
! 653: * is not busy.
! 654: */
! 655: TAILQ_FOREACH(acb, &sc->ready_list, chain) {
! 656: sc_link = acb->xs->sc_link;
! 657: ti = &sc->sc_tinfo[sc_link->target];
! 658: if ((ti->lubusy & (1 << sc_link->lun)) == 0) {
! 659: SPC_MISC(("selecting %d:%d ",
! 660: sc_link->target, sc_link->lun));
! 661: TAILQ_REMOVE(&sc->ready_list, acb, chain);
! 662: sc->sc_nexus = acb;
! 663: spc_select(sc, acb);
! 664: return;
! 665: } else
! 666: SPC_MISC(("%d:%d busy\n",
! 667: sc_link->target, sc_link->lun));
! 668: }
! 669: SPC_MISC(("idle "));
! 670: /* Nothing to start; just enable reselections and wait. */
! 671: }
! 672:
! 673: void
! 674: spc_sense(struct spc_softc *sc, struct spc_acb *acb)
! 675: {
! 676: struct scsi_xfer *xs = acb->xs;
! 677: struct scsi_link *sc_link = xs->sc_link;
! 678: struct spc_tinfo *ti = &sc->sc_tinfo[sc_link->target];
! 679: struct scsi_sense *ss = (void *)&acb->scsi_cmd;
! 680:
! 681: SPC_MISC(("requesting sense "));
! 682: /* Next, setup a request sense command block */
! 683: bzero(ss, sizeof(*ss));
! 684: ss->opcode = REQUEST_SENSE;
! 685: ss->byte2 = sc_link->lun << 5;
! 686: ss->length = sizeof(struct scsi_sense_data);
! 687: acb->scsi_cmd_length = sizeof(*ss);
! 688: acb->data_addr = (char *)&xs->sense;
! 689: acb->data_length = sizeof(struct scsi_sense_data);
! 690: acb->flags |= ACB_SENSE;
! 691: ti->senses++;
! 692: if (acb->flags & ACB_NEXUS)
! 693: ti->lubusy &= ~(1 << sc_link->lun);
! 694: if (acb == sc->sc_nexus) {
! 695: spc_select(sc, acb);
! 696: } else {
! 697: spc_dequeue(sc, acb);
! 698: TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
! 699: if (sc->sc_state == SPC_IDLE)
! 700: spc_sched(sc);
! 701: }
! 702: }
! 703:
! 704: /*
! 705: * POST PROCESSING OF SCSI_CMD (usually current)
! 706: */
! 707: void
! 708: spc_done(struct spc_softc *sc, struct spc_acb *acb)
! 709: {
! 710: struct scsi_xfer *xs = acb->xs;
! 711: struct scsi_link *sc_link = xs->sc_link;
! 712: struct spc_tinfo *ti = &sc->sc_tinfo[sc_link->target];
! 713:
! 714: SPC_TRACE(("spc_done "));
! 715:
! 716: timeout_del(&acb->xs->stimeout);
! 717:
! 718: /*
! 719: * Now, if we've come here with no error code, i.e. we've kept the
! 720: * initial XS_NOERROR, and the status code signals that we should
! 721: * check sense, we'll need to set up a request sense cmd block and
! 722: * push the command back into the ready queue *before* any other
! 723: * commands for this target/lunit, else we lose the sense info.
! 724: * We don't support chk sense conditions for the request sense cmd.
! 725: */
! 726: if (xs->error == XS_NOERROR) {
! 727: if (acb->flags & ACB_ABORT) {
! 728: xs->error = XS_DRIVER_STUFFUP;
! 729: } else if (acb->flags & ACB_SENSE) {
! 730: xs->error = XS_SENSE;
! 731: } else {
! 732: switch (acb->target_stat) {
! 733: case SCSI_CHECK:
! 734: /* First, save the return values */
! 735: xs->resid = acb->data_length;
! 736: xs->status = acb->target_stat;
! 737: spc_sense(sc, acb);
! 738: return;
! 739: case SCSI_BUSY:
! 740: xs->error = XS_BUSY;
! 741: break;
! 742: case SCSI_OK:
! 743: xs->resid = acb->data_length;
! 744: break;
! 745: default:
! 746: xs->error = XS_DRIVER_STUFFUP;
! 747: #ifdef SPC_DEBUG
! 748: printf("%s: spc_done: bad stat 0x%x\n",
! 749: sc->sc_dev.dv_xname, acb->target_stat);
! 750: #endif
! 751: break;
! 752: }
! 753: }
! 754: }
! 755:
! 756: xs->flags |= ITSDONE;
! 757:
! 758: #ifdef SPC_DEBUG
! 759: if ((spc_debug & SPC_SHOWMISC) != 0) {
! 760: if (xs->resid != 0)
! 761: printf("resid=%d ", xs->resid);
! 762: if (xs->error == XS_SENSE)
! 763: printf("sense=0x%02x\n", xs->sense.error_code);
! 764: else
! 765: printf("error=%d\n", xs->error);
! 766: }
! 767: #endif
! 768:
! 769: /*
! 770: * Remove the ACB from whatever queue it happens to be on.
! 771: */
! 772: if (acb->flags & ACB_NEXUS)
! 773: ti->lubusy &= ~(1 << sc_link->lun);
! 774: if (acb == sc->sc_nexus) {
! 775: sc->sc_nexus = NULL;
! 776: sc->sc_state = SPC_IDLE;
! 777: spc_sched(sc);
! 778: } else
! 779: spc_dequeue(sc, acb);
! 780:
! 781: spc_free_acb(sc, acb, xs->flags);
! 782: ti->cmds++;
! 783: scsi_done(xs);
! 784: }
! 785:
! 786: void
! 787: spc_dequeue(struct spc_softc *sc, struct spc_acb *acb)
! 788: {
! 789: SPC_TRACE(("spc_dequeue "));
! 790: if (acb->flags & ACB_NEXUS)
! 791: TAILQ_REMOVE(&sc->nexus_list, acb, chain);
! 792: else
! 793: TAILQ_REMOVE(&sc->ready_list, acb, chain);
! 794: }
! 795:
! 796: /*
! 797: * INTERRUPT/PROTOCOL ENGINE
! 798: */
! 799:
! 800: #define IS1BYTEMSG(m) (((m) != 0x01 && (m) < 0x20) || (m) >= 0x80)
! 801: #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
! 802: #define ISEXTMSG(m) ((m) == 0x01)
! 803:
! 804: /*
! 805: * Precondition:
! 806: * The SCSI bus is already in the MSGI phase and there is a message byte
! 807: * on the bus, along with an asserted REQ signal.
! 808: */
! 809: void
! 810: spc_msgin(struct spc_softc *sc)
! 811: {
! 812: int n;
! 813: u_int8_t msg;
! 814:
! 815: SPC_TRACE(("spc_msgin "));
! 816:
! 817: if (sc->sc_prevphase == PH_MSGIN) {
! 818: /* This is a continuation of the previous message. */
! 819: n = sc->sc_imp - sc->sc_imess;
! 820: goto nextbyte;
! 821: }
! 822:
! 823: /* This is a new MESSAGE IN phase. Clean up our state. */
! 824: sc->sc_flags &= ~SPC_DROP_MSGIN;
! 825:
! 826: nextmsg:
! 827: n = 0;
! 828: sc->sc_imp = &sc->sc_imess[n];
! 829:
! 830: nextbyte:
! 831: /*
! 832: * Read a whole message, but don't ack the last byte. If we reject the
! 833: * message, we have to assert ATN during the message transfer phase
! 834: * itself.
! 835: */
! 836: for (;;) {
! 837: /* If parity error, just dump everything on the floor. */
! 838: if ((spc_read(SERR) & (SERR_SCSI_PAR|SERR_SPC_PAR)) != 0) {
! 839: sc->sc_flags |= SPC_DROP_MSGIN;
! 840: spc_sched_msgout(sc, SEND_PARITY_ERROR);
! 841: }
! 842:
! 843: if ((spc_read(PSNS) & PSNS_ATN) != 0)
! 844: spc_write(SCMD, SCMD_RST_ATN);
! 845: spc_write(PCTL, PCTL_BFINT_ENAB | PH_MSGIN);
! 846:
! 847: while ((spc_read(PSNS) & PSNS_REQ) == 0) {
! 848: if (((spc_read(PSNS) & PH_MASK) != PH_MSGIN &&
! 849: (spc_read(SSTS) & SSTS_INITIATOR) == 0) ||
! 850: spc_read(INTS) != 0)
! 851: /*
! 852: * Target left MESSAGE IN, probably because it
! 853: * a) noticed our ATN signal, or
! 854: * b) ran out of messages.
! 855: */
! 856: goto out;
! 857: DELAY(1);
! 858: }
! 859:
! 860: msg = spc_read(TEMP);
! 861:
! 862: /* Gather incoming message bytes if needed. */
! 863: if ((sc->sc_flags & SPC_DROP_MSGIN) == 0) {
! 864: if (n >= SPC_MAX_MSG_LEN) {
! 865: sc->sc_flags |= SPC_DROP_MSGIN;
! 866: spc_sched_msgout(sc, SEND_REJECT);
! 867: } else {
! 868: *sc->sc_imp++ = msg;
! 869: n++;
! 870: /*
! 871: * This testing is suboptimal, but most
! 872: * messages will be of the one byte variety, so
! 873: * it should not affect performance
! 874: * significantly.
! 875: */
! 876: if (n == 1 && IS1BYTEMSG(sc->sc_imess[0]))
! 877: break;
! 878: if (n == 2 && IS2BYTEMSG(sc->sc_imess[0]))
! 879: break;
! 880: if (n >= 3 && ISEXTMSG(sc->sc_imess[0]) &&
! 881: n == sc->sc_imess[1] + 2)
! 882: break;
! 883: }
! 884: }
! 885:
! 886: /*
! 887: * If we reach this spot we're either:
! 888: * a) in the middle of a multi-byte message, or
! 889: * b) dropping bytes.
! 890: */
! 891:
! 892: /* Ack the last byte read. */
! 893: spc_write(SCMD, SCMD_SET_ACK);
! 894: while ((spc_read(PSNS) & PSNS_REQ) != 0)
! 895: DELAY(1); /* XXX needs timeout */
! 896: spc_write(SCMD, SCMD_RST_ACK);
! 897: }
! 898:
! 899: SPC_MISC(("n=%d imess=0x%02x ", n, sc->sc_imess[0]));
! 900:
! 901: /* We now have a complete message. Parse it. */
! 902: switch (sc->sc_state) {
! 903: struct spc_acb *acb;
! 904: struct scsi_link *sc_link;
! 905: struct spc_tinfo *ti;
! 906:
! 907: case SPC_CONNECTED:
! 908: SPC_ASSERT(sc->sc_nexus != NULL);
! 909: acb = sc->sc_nexus;
! 910: ti = &sc->sc_tinfo[acb->xs->sc_link->target];
! 911:
! 912: switch (sc->sc_imess[0]) {
! 913: case MSG_CMDCOMPLETE:
! 914: if (sc->sc_dleft < 0) {
! 915: sc_link = acb->xs->sc_link;
! 916: printf("%s: %d extra bytes from %d:%d\n",
! 917: sc->sc_dev.dv_xname, -sc->sc_dleft,
! 918: sc_link->target, sc_link->lun);
! 919: sc->sc_dleft = 0;
! 920: }
! 921: acb->xs->resid = acb->data_length = sc->sc_dleft;
! 922: sc->sc_state = SPC_CMDCOMPLETE;
! 923: break;
! 924:
! 925: case MSG_PARITY_ERROR:
! 926: /* Resend the last message. */
! 927: spc_sched_msgout(sc, sc->sc_lastmsg);
! 928: break;
! 929:
! 930: case MSG_MESSAGE_REJECT:
! 931: SPC_MISC(("message rejected %02x ", sc->sc_lastmsg));
! 932: switch (sc->sc_lastmsg) {
! 933: #if SPC_USE_SYNCHRONOUS + SPC_USE_WIDE
! 934: case SEND_IDENTIFY:
! 935: ti->flags &= ~(DO_SYNC | DO_WIDE);
! 936: ti->period = ti->offset = 0;
! 937: spc_setsync(sc, ti);
! 938: ti->width = 0;
! 939: break;
! 940: #endif
! 941: #if SPC_USE_SYNCHRONOUS
! 942: case SEND_SDTR:
! 943: ti->flags &= ~DO_SYNC;
! 944: ti->period = ti->offset = 0;
! 945: spc_setsync(sc, ti);
! 946: break;
! 947: #endif
! 948: #if SPC_USE_WIDE
! 949: case SEND_WDTR:
! 950: ti->flags &= ~DO_WIDE;
! 951: ti->width = 0;
! 952: break;
! 953: #endif
! 954: case SEND_INIT_DET_ERR:
! 955: spc_sched_msgout(sc, SEND_ABORT);
! 956: break;
! 957: }
! 958: break;
! 959:
! 960: case MSG_NOOP:
! 961: break;
! 962:
! 963: case MSG_DISCONNECT:
! 964: ti->dconns++;
! 965: sc->sc_state = SPC_DISCONNECT;
! 966: break;
! 967:
! 968: case MSG_SAVEDATAPOINTER:
! 969: acb->data_addr = sc->sc_dp;
! 970: acb->data_length = sc->sc_dleft;
! 971: break;
! 972:
! 973: case MSG_RESTOREPOINTERS:
! 974: sc->sc_dp = acb->data_addr;
! 975: sc->sc_dleft = acb->data_length;
! 976: sc->sc_cp = (u_char *)&acb->scsi_cmd;
! 977: sc->sc_cleft = acb->scsi_cmd_length;
! 978: break;
! 979:
! 980: case MSG_EXTENDED:
! 981: switch (sc->sc_imess[2]) {
! 982: #if SPC_USE_SYNCHRONOUS
! 983: case MSG_EXT_SDTR:
! 984: if (sc->sc_imess[1] != 3)
! 985: goto reject;
! 986: ti->period = sc->sc_imess[3];
! 987: ti->offset = sc->sc_imess[4];
! 988: ti->flags &= ~DO_SYNC;
! 989: if (ti->offset == 0) {
! 990: } else if (ti->period < sc->sc_minsync ||
! 991: ti->period > sc->sc_maxsync ||
! 992: ti->offset > 8) {
! 993: ti->period = ti->offset = 0;
! 994: spc_sched_msgout(sc, SEND_SDTR);
! 995: } else {
! 996: sc_print_addr(acb->xs->sc_link);
! 997: printf("sync, offset %d, "
! 998: "period %dnsec\n",
! 999: ti->offset, ti->period * 4);
! 1000: }
! 1001: spc_setsync(sc, ti);
! 1002: break;
! 1003: #endif
! 1004:
! 1005: #if SPC_USE_WIDE
! 1006: case MSG_EXT_WDTR:
! 1007: if (sc->sc_imess[1] != 2)
! 1008: goto reject;
! 1009: ti->width = sc->sc_imess[3];
! 1010: ti->flags &= ~DO_WIDE;
! 1011: if (ti->width == 0) {
! 1012: } else if (ti->width > SPC_MAX_WIDTH) {
! 1013: ti->width = 0;
! 1014: spc_sched_msgout(sc, SEND_WDTR);
! 1015: } else {
! 1016: sc_print_addr(acb->xs->sc_link);
! 1017: printf("wide, width %d\n",
! 1018: 1 << (3 + ti->width));
! 1019: }
! 1020: break;
! 1021: #endif
! 1022:
! 1023: default:
! 1024: printf("%s: unrecognized MESSAGE EXTENDED 0x%x;"
! 1025: " sending REJECT\n",
! 1026: sc->sc_imess[2], sc->sc_dev.dv_xname);
! 1027: SPC_BREAK();
! 1028: goto reject;
! 1029: }
! 1030: break;
! 1031:
! 1032: default:
! 1033: printf("%s: unrecognized MESSAGE; sending REJECT\n",
! 1034: sc->sc_dev.dv_xname);
! 1035: SPC_BREAK();
! 1036: reject:
! 1037: spc_sched_msgout(sc, SEND_REJECT);
! 1038: break;
! 1039: }
! 1040: break;
! 1041:
! 1042: case SPC_RESELECTED:
! 1043: if (!MSG_ISIDENTIFY(sc->sc_imess[0])) {
! 1044: printf("%s: reselect without IDENTIFY; "
! 1045: "sending DEVICE RESET\n", sc->sc_dev.dv_xname);
! 1046: SPC_BREAK();
! 1047: goto reset;
! 1048: }
! 1049:
! 1050: (void) spc_reselect(sc, sc->sc_imess[0]);
! 1051: break;
! 1052:
! 1053: default:
! 1054: printf("%s: unexpected MESSAGE IN; sending DEVICE RESET\n",
! 1055: sc->sc_dev.dv_xname);
! 1056: SPC_BREAK();
! 1057: reset:
! 1058: spc_sched_msgout(sc, SEND_DEV_RESET);
! 1059: break;
! 1060:
! 1061: #ifdef notdef
! 1062: abort:
! 1063: spc_sched_msgout(sc, SEND_ABORT);
! 1064: break;
! 1065: #endif
! 1066: }
! 1067:
! 1068: /* Ack the last message byte. */
! 1069: spc_write(SCMD, SCMD_SET_ACK);
! 1070: while ((spc_read(PSNS) & PSNS_REQ) != 0)
! 1071: DELAY(1); /* XXX needs timeout */
! 1072: spc_write(SCMD, SCMD_RST_ACK);
! 1073:
! 1074: /* Go get the next message, if any. */
! 1075: goto nextmsg;
! 1076:
! 1077: out:
! 1078: SPC_MISC(("n=%d imess=0x%02x ", n, sc->sc_imess[0]));
! 1079: }
! 1080:
! 1081: /*
! 1082: * Send the highest priority, scheduled message.
! 1083: */
! 1084: void
! 1085: spc_msgout(struct spc_softc *sc)
! 1086: {
! 1087: #if SPC_USE_SYNCHRONOUS
! 1088: struct spc_tinfo *ti;
! 1089: #endif
! 1090: int n;
! 1091:
! 1092: SPC_TRACE(("spc_msgout "));
! 1093:
! 1094: if (sc->sc_prevphase == PH_MSGOUT) {
! 1095: if (sc->sc_omp == sc->sc_omess) {
! 1096: /*
! 1097: * This is a retransmission.
! 1098: *
! 1099: * We get here if the target stayed in MESSAGE OUT
! 1100: * phase. Section 5.1.9.2 of the SCSI 2 spec indicates
! 1101: * that all of the previously transmitted messages must
! 1102: * be sent again, in the same order. Therefore, we
! 1103: * requeue all the previously transmitted messages, and
! 1104: * start again from the top. Our simple priority
! 1105: * scheme keeps the messages in the right order.
! 1106: */
! 1107: SPC_MISC(("retransmitting "));
! 1108: sc->sc_msgpriq |= sc->sc_msgoutq;
! 1109: /*
! 1110: * Set ATN. If we're just sending a trivial 1-byte
! 1111: * message, we'll clear ATN later on anyway.
! 1112: */
! 1113: spc_write(SCMD, SCMD_SET_ATN); /* XXX? */
! 1114: } else {
! 1115: /* This is a continuation of the previous message. */
! 1116: n = sc->sc_omp - sc->sc_omess;
! 1117: goto nextbyte;
! 1118: }
! 1119: }
! 1120:
! 1121: /* No messages transmitted so far. */
! 1122: sc->sc_msgoutq = 0;
! 1123: sc->sc_lastmsg = 0;
! 1124:
! 1125: nextmsg:
! 1126: /* Pick up highest priority message. */
! 1127: sc->sc_currmsg = sc->sc_msgpriq & -sc->sc_msgpriq;
! 1128: sc->sc_msgpriq &= ~sc->sc_currmsg;
! 1129: sc->sc_msgoutq |= sc->sc_currmsg;
! 1130:
! 1131: /* Build the outgoing message data. */
! 1132: switch (sc->sc_currmsg) {
! 1133: case SEND_IDENTIFY:
! 1134: SPC_ASSERT(sc->sc_nexus != NULL);
! 1135: sc->sc_omess[0] =
! 1136: MSG_IDENTIFY(sc->sc_nexus->xs->sc_link->lun, 1);
! 1137: n = 1;
! 1138: break;
! 1139:
! 1140: #if SPC_USE_SYNCHRONOUS
! 1141: case SEND_SDTR:
! 1142: SPC_ASSERT(sc->sc_nexus != NULL);
! 1143: ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
! 1144: sc->sc_omess[4] = MSG_EXTENDED;
! 1145: sc->sc_omess[3] = MSG_EXT_SDTR_LEN;
! 1146: sc->sc_omess[2] = MSG_EXT_SDTR;
! 1147: sc->sc_omess[1] = ti->period >> 2;
! 1148: sc->sc_omess[0] = ti->offset;
! 1149: n = 5;
! 1150: break;
! 1151: #endif
! 1152:
! 1153: #if SPC_USE_WIDE
! 1154: case SEND_WDTR:
! 1155: SPC_ASSERT(sc->sc_nexus != NULL);
! 1156: ti = &sc->sc_tinfo[sc->sc_nexus->xs->sc_link->target];
! 1157: sc->sc_omess[3] = MSG_EXTENDED;
! 1158: sc->sc_omess[2] = MSG_EXT_WDTR_LEN;
! 1159: sc->sc_omess[1] = MSG_EXT_WDTR;
! 1160: sc->sc_omess[0] = ti->width;
! 1161: n = 4;
! 1162: break;
! 1163: #endif
! 1164:
! 1165: case SEND_DEV_RESET:
! 1166: sc->sc_flags |= SPC_ABORTING;
! 1167: sc->sc_omess[0] = MSG_BUS_DEV_RESET;
! 1168: n = 1;
! 1169: break;
! 1170:
! 1171: case SEND_REJECT:
! 1172: sc->sc_omess[0] = MSG_MESSAGE_REJECT;
! 1173: n = 1;
! 1174: break;
! 1175:
! 1176: case SEND_PARITY_ERROR:
! 1177: sc->sc_omess[0] = MSG_PARITY_ERROR;
! 1178: n = 1;
! 1179: break;
! 1180:
! 1181: case SEND_INIT_DET_ERR:
! 1182: sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
! 1183: n = 1;
! 1184: break;
! 1185:
! 1186: case SEND_ABORT:
! 1187: sc->sc_flags |= SPC_ABORTING;
! 1188: sc->sc_omess[0] = MSG_ABORT;
! 1189: n = 1;
! 1190: break;
! 1191:
! 1192: default:
! 1193: printf("%s: unexpected MESSAGE OUT; sending NOOP\n",
! 1194: sc->sc_dev.dv_xname);
! 1195: SPC_BREAK();
! 1196: sc->sc_omess[0] = MSG_NOOP;
! 1197: n = 1;
! 1198: break;
! 1199: }
! 1200: sc->sc_omp = &sc->sc_omess[n];
! 1201:
! 1202: nextbyte:
! 1203: /* Send message bytes. */
! 1204: /* send TRANSFER command. */
! 1205: spc_write(TCH, n >> 16);
! 1206: spc_write(TCM, n >> 8);
! 1207: spc_write(TCL, n);
! 1208: spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
! 1209: spc_write(SCMD, SCMD_XFR | SCMD_PROG_XFR);
! 1210: for (;;) {
! 1211: if ((spc_read(SSTS) & SSTS_BUSY) != 0)
! 1212: break;
! 1213: if (spc_read(INTS) != 0)
! 1214: goto out;
! 1215: }
! 1216: for (;;) {
! 1217: #if 0
! 1218: for (;;) {
! 1219: if ((spc_read(PSNS) & PSNS_REQ) != 0)
! 1220: break;
! 1221: /* Wait for REQINIT. XXX Need timeout. */
! 1222: }
! 1223: #endif
! 1224: if (spc_read(INTS) != 0) {
! 1225: /*
! 1226: * Target left MESSAGE OUT, possibly to reject
! 1227: * our message.
! 1228: *
! 1229: * If this is the last message being sent, then we
! 1230: * deassert ATN, since either the target is going to
! 1231: * ignore this message, or it's going to ask for a
! 1232: * retransmission via MESSAGE PARITY ERROR (in which
! 1233: * case we reassert ATN anyway).
! 1234: */
! 1235: #if 0
! 1236: if (sc->sc_msgpriq == 0)
! 1237: spc_write(SCMD, SCMD_RST_ATN);
! 1238: #endif
! 1239: goto out;
! 1240: }
! 1241:
! 1242: #if 0
! 1243: /* Clear ATN before last byte if this is the last message. */
! 1244: if (n == 1 && sc->sc_msgpriq == 0)
! 1245: spc_write(SCMD, SCMD_RST_ATN);
! 1246: #endif
! 1247:
! 1248: while ((spc_read(SSTS) & SSTS_DREG_FULL) != 0)
! 1249: DELAY(1);
! 1250: /* Send message byte. */
! 1251: spc_write(DREG, *--sc->sc_omp);
! 1252: --n;
! 1253: /* Keep track of the last message we've sent any bytes of. */
! 1254: sc->sc_lastmsg = sc->sc_currmsg;
! 1255: #if 0
! 1256: /* Wait for ACK to be negated. XXX Need timeout. */
! 1257: while ((spc_read(PSNS) & ACKI) != 0)
! 1258: ;
! 1259: #endif
! 1260:
! 1261: if (n == 0)
! 1262: break;
! 1263: }
! 1264:
! 1265: /* We get here only if the entire message has been transmitted. */
! 1266: if (sc->sc_msgpriq != 0) {
! 1267: /* There are more outgoing messages. */
! 1268: goto nextmsg;
! 1269: }
! 1270:
! 1271: /*
! 1272: * The last message has been transmitted. We need to remember the last
! 1273: * message transmitted (in case the target switches to MESSAGE IN phase
! 1274: * and sends a MESSAGE REJECT), and the list of messages transmitted
! 1275: * this time around (in case the target stays in MESSAGE OUT phase to
! 1276: * request a retransmit).
! 1277: */
! 1278:
! 1279: out:
! 1280: /* Disable REQ/ACK protocol. */
! 1281: return;
! 1282: }
! 1283:
! 1284: /*
! 1285: * spc_dataout_pio: perform a data transfer using the FIFO datapath in the spc
! 1286: * Precondition: The SCSI bus should be in the DOUT phase, with REQ asserted
! 1287: * and ACK deasserted (i.e. waiting for a data byte).
! 1288: *
! 1289: * This new revision has been optimized (I tried) to make the common case fast,
! 1290: * and the rarer cases (as a result) somewhat more complex.
! 1291: */
! 1292: int
! 1293: spc_dataout_pio(struct spc_softc *sc, u_char *p, int n)
! 1294: {
! 1295: u_char intstat = 0;
! 1296: int out = 0;
! 1297: #define DOUTAMOUNT 8 /* Full FIFO */
! 1298:
! 1299: SPC_TRACE(("spc_dataout_pio "));
! 1300: /* send TRANSFER command. */
! 1301: spc_write(TCH, n >> 16);
! 1302: spc_write(TCM, n >> 8);
! 1303: spc_write(TCL, n);
! 1304: spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
! 1305: spc_write(SCMD, SCMD_XFR | SCMD_PROG_XFR); /* XXX */
! 1306: for (;;) {
! 1307: if ((spc_read(SSTS) & SSTS_BUSY) != 0)
! 1308: break;
! 1309: if (spc_read(INTS) != 0)
! 1310: break;
! 1311: }
! 1312:
! 1313: /*
! 1314: * I have tried to make the main loop as tight as possible. This
! 1315: * means that some of the code following the loop is a bit more
! 1316: * complex than otherwise.
! 1317: */
! 1318: while (n > 0) {
! 1319: int xfer;
! 1320:
! 1321: for (;;) {
! 1322: intstat = spc_read(INTS);
! 1323: /* Wait till buffer is empty. */
! 1324: if ((spc_read(SSTS) & SSTS_DREG_EMPTY) != 0)
! 1325: break;
! 1326: /* Break on interrupt. */
! 1327: if (intstat != 0)
! 1328: goto phasechange;
! 1329: DELAY(1);
! 1330: }
! 1331:
! 1332: xfer = min(DOUTAMOUNT, n);
! 1333:
! 1334: SPC_MISC(("%d> ", xfer));
! 1335:
! 1336: n -= xfer;
! 1337: out += xfer;
! 1338:
! 1339: while (xfer-- > 0)
! 1340: spc_write(DREG, *p++);
! 1341: }
! 1342:
! 1343: if (out == 0) {
! 1344: for (;;) {
! 1345: if (spc_read(INTS) != 0)
! 1346: break;
! 1347: DELAY(1);
! 1348: }
! 1349: SPC_MISC(("extra data "));
! 1350: } else {
! 1351: /* See the bytes off chip */
! 1352: for (;;) {
! 1353: /* Wait till buffer is empty. */
! 1354: if ((spc_read(SSTS) & SSTS_DREG_EMPTY) != 0)
! 1355: break;
! 1356: intstat = spc_read(INTS);
! 1357: /* Break on interrupt. */
! 1358: if (intstat != 0)
! 1359: goto phasechange;
! 1360: DELAY(1);
! 1361: }
! 1362: }
! 1363:
! 1364: phasechange:
! 1365: /* Stop the FIFO data path. */
! 1366:
! 1367: if (intstat != 0) {
! 1368: /* Some sort of phase change. */
! 1369: int amount;
! 1370:
! 1371: amount = ((spc_read(TCH) << 16) |
! 1372: (spc_read(TCM) << 8) | spc_read(TCL));
! 1373: if (amount > 0) {
! 1374: out -= amount;
! 1375: SPC_MISC(("+%d ", amount));
! 1376: }
! 1377: }
! 1378:
! 1379: return out;
! 1380: }
! 1381:
! 1382: /*
! 1383: * spc_datain_pio: perform data transfers using the FIFO datapath in the spc
! 1384: * Precondition: The SCSI bus should be in the DIN phase, with REQ asserted
! 1385: * and ACK deasserted (i.e. at least one byte is ready).
! 1386: *
! 1387: * For now, uses a pretty dumb algorithm, hangs around until all data has been
! 1388: * transferred. This, is OK for fast targets, but not so smart for slow
! 1389: * targets which don't disconnect or for huge transfers.
! 1390: */
! 1391: int
! 1392: spc_datain_pio(struct spc_softc *sc, u_char *p, int n)
! 1393: {
! 1394: int in = 0;
! 1395: u_int8_t intstat, sstat;
! 1396: #define DINAMOUNT 8 /* Full FIFO */
! 1397:
! 1398: SPC_TRACE(("spc_datain_pio "));
! 1399: /* send TRANSFER command. */
! 1400: spc_write(TCH, n >> 16);
! 1401: spc_write(TCM, n >> 8);
! 1402: spc_write(TCL, n);
! 1403: spc_write(PCTL, sc->sc_phase | PCTL_BFINT_ENAB);
! 1404: spc_write(SCMD, SCMD_XFR | SCMD_PROG_XFR); /* XXX */
! 1405:
! 1406: /*
! 1407: * We leave this loop if one or more of the following is true:
! 1408: * a) phase != PH_DATAIN && FIFOs are empty
! 1409: * b) reset has occurred or busfree is detected.
! 1410: */
! 1411: intstat = 0;
! 1412: while (n > 0) {
! 1413: int xfer;
! 1414:
! 1415: sstat = spc_read(SSTS);
! 1416: if ((sstat & SSTS_DREG_FULL) != 0) {
! 1417: xfer = DINAMOUNT;
! 1418: n -= xfer;
! 1419: in += xfer;
! 1420: while (xfer-- > 0)
! 1421: *p++ = spc_read(DREG);
! 1422: } else if ((sstat & SSTS_DREG_EMPTY) == 0) {
! 1423: n--;
! 1424: in++;
! 1425: *p++ = spc_read(DREG);
! 1426: } else {
! 1427: if (intstat != 0)
! 1428: goto phasechange;
! 1429: intstat = spc_read(INTS);
! 1430: }
! 1431: }
! 1432:
! 1433: /*
! 1434: * Some SCSI-devices are rude enough to transfer more data than what
! 1435: * was requested, e.g. 2048 bytes from a CD-ROM instead of the
! 1436: * requested 512. Test for progress, i.e. real transfers. If no real
! 1437: * transfers have been performed (n is probably already zero) and the
! 1438: * FIFO is not empty, waste some bytes....
! 1439: */
! 1440: if (in == 0) {
! 1441: for (;;) {
! 1442: sstat = spc_read(SSTS);
! 1443: if ((sstat & SSTS_DREG_EMPTY) == 0) {
! 1444: (void) spc_read(DREG);
! 1445: } else {
! 1446: if (intstat != 0)
! 1447: goto phasechange;
! 1448: intstat = spc_read(INTS);
! 1449: }
! 1450: DELAY(1);
! 1451: }
! 1452: SPC_MISC(("extra data "));
! 1453: }
! 1454:
! 1455: phasechange:
! 1456: /* Stop the FIFO data path. */
! 1457:
! 1458: return in;
! 1459: }
! 1460:
! 1461: /*
! 1462: * Catch an interrupt from the adaptor
! 1463: */
! 1464: int
! 1465: spc_intr(void *arg)
! 1466: {
! 1467: struct spc_softc *sc = arg;
! 1468: u_char ints;
! 1469:
! 1470: SPC_TRACE(("spc_intr "));
! 1471:
! 1472: /*
! 1473: * Disable interrupt.
! 1474: */
! 1475: spc_write(SCTL, spc_read(SCTL) & ~SCTL_INTR_ENAB);
! 1476:
! 1477: ints = spc_read(INTS);
! 1478: if (ints != 0)
! 1479: spc_process_intr(arg, ints);
! 1480:
! 1481: spc_write(SCTL, spc_read(SCTL) | SCTL_INTR_ENAB);
! 1482: return 1;
! 1483: }
! 1484:
! 1485: void
! 1486: spc_process_intr(void *arg, u_char ints)
! 1487: {
! 1488: struct spc_softc *sc = arg;
! 1489: struct spc_acb *acb;
! 1490: struct scsi_link *sc_link;
! 1491: struct spc_tinfo *ti;
! 1492: int n;
! 1493:
! 1494: SPC_TRACE(("spc_process_intr "));
! 1495:
! 1496: goto start;
! 1497:
! 1498: loop:
! 1499: /*
! 1500: * Loop until transfer completion.
! 1501: */
! 1502: ints = spc_read(INTS);
! 1503: start:
! 1504: SPC_MISC(("ints = 0x%x ", ints));
! 1505:
! 1506: /*
! 1507: * Check for the end of a DMA operation before doing anything else...
! 1508: */
! 1509: if ((sc->sc_flags & SPC_DOINGDMA) != 0) {
! 1510: (*sc->sc_dma_done)(sc);
! 1511: }
! 1512:
! 1513: /*
! 1514: * Then check for abnormal conditions, such as reset.
! 1515: */
! 1516: if ((ints & INTS_RST) != 0) {
! 1517: printf("%s: SCSI bus reset\n", sc->sc_dev.dv_xname);
! 1518: goto reset;
! 1519: }
! 1520:
! 1521: /*
! 1522: * Check for less serious errors.
! 1523: */
! 1524: if ((spc_read(SERR) & (SERR_SCSI_PAR|SERR_SPC_PAR))
! 1525: != 0) {
! 1526: printf("%s: SCSI bus parity error\n", sc->sc_dev.dv_xname);
! 1527: if (sc->sc_prevphase == PH_MSGIN) {
! 1528: sc->sc_flags |= SPC_DROP_MSGIN;
! 1529: spc_sched_msgout(sc, SEND_PARITY_ERROR);
! 1530: } else
! 1531: spc_sched_msgout(sc, SEND_INIT_DET_ERR);
! 1532: }
! 1533:
! 1534: /*
! 1535: * If we're not already busy doing something test for the following
! 1536: * conditions:
! 1537: * 1) We have been reselected by something
! 1538: * 2) We have selected something successfully
! 1539: * 3) Our selection process has timed out
! 1540: * 4) This is really a bus free interrupt just to get a new command
! 1541: * going?
! 1542: * 5) Spurious interrupt?
! 1543: */
! 1544: switch (sc->sc_state) {
! 1545: case SPC_IDLE:
! 1546: case SPC_SELECTING:
! 1547: SPC_MISC(("ints:0x%02x ", ints));
! 1548:
! 1549: if ((ints & INTS_SEL) != 0) {
! 1550: /*
! 1551: * We don't currently support target mode.
! 1552: */
! 1553: printf("%s: target mode selected; going to BUS FREE\n",
! 1554: sc->sc_dev.dv_xname);
! 1555:
! 1556: goto sched;
! 1557: } else if ((ints & INTS_RESEL) != 0) {
! 1558: SPC_MISC(("reselected "));
! 1559:
! 1560: /*
! 1561: * If we're trying to select a target ourselves,
! 1562: * push our command back into the ready list.
! 1563: */
! 1564: if (sc->sc_state == SPC_SELECTING) {
! 1565: SPC_MISC(("backoff selector "));
! 1566: SPC_ASSERT(sc->sc_nexus != NULL);
! 1567: acb = sc->sc_nexus;
! 1568: sc->sc_nexus = NULL;
! 1569: TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
! 1570: }
! 1571:
! 1572: /* Save reselection ID. */
! 1573: sc->sc_selid = spc_read(TEMP);
! 1574:
! 1575: sc->sc_state = SPC_RESELECTED;
! 1576: } else if ((ints & INTS_CMD_DONE) != 0) {
! 1577: SPC_MISC(("selected "));
! 1578:
! 1579: /*
! 1580: * We have selected a target. Things to do:
! 1581: * a) Determine what message(s) to send.
! 1582: * b) Verify that we're still selecting the target.
! 1583: * c) Mark device as busy.
! 1584: */
! 1585: if (sc->sc_state != SPC_SELECTING) {
! 1586: printf("%s: selection out while idle; "
! 1587: "resetting\n", sc->sc_dev.dv_xname);
! 1588: SPC_BREAK();
! 1589: goto reset;
! 1590: }
! 1591: SPC_ASSERT(sc->sc_nexus != NULL);
! 1592: acb = sc->sc_nexus;
! 1593: sc_link = acb->xs->sc_link;
! 1594: ti = &sc->sc_tinfo[sc_link->target];
! 1595:
! 1596: sc->sc_msgpriq = SEND_IDENTIFY;
! 1597: if (acb->flags & ACB_RESET)
! 1598: sc->sc_msgpriq |= SEND_DEV_RESET;
! 1599: else if (acb->flags & ACB_ABORT)
! 1600: sc->sc_msgpriq |= SEND_ABORT;
! 1601: else {
! 1602: #if SPC_USE_SYNCHRONOUS
! 1603: if ((ti->flags & DO_SYNC) != 0)
! 1604: sc->sc_msgpriq |= SEND_SDTR;
! 1605: #endif
! 1606: #if SPC_USE_WIDE
! 1607: if ((ti->flags & DO_WIDE) != 0)
! 1608: sc->sc_msgpriq |= SEND_WDTR;
! 1609: #endif
! 1610: }
! 1611:
! 1612: acb->flags |= ACB_NEXUS;
! 1613: ti->lubusy |= (1 << sc_link->lun);
! 1614:
! 1615: /* Do an implicit RESTORE POINTERS. */
! 1616: sc->sc_dp = acb->data_addr;
! 1617: sc->sc_dleft = acb->data_length;
! 1618: sc->sc_cp = (u_char *)&acb->scsi_cmd;
! 1619: sc->sc_cleft = acb->scsi_cmd_length;
! 1620:
! 1621: /* On our first connection, schedule a timeout. */
! 1622: if ((acb->xs->flags & SCSI_POLL) == 0) {
! 1623: timeout_set(&acb->xs->stimeout, spc_timeout,
! 1624: acb);
! 1625: timeout_add(&acb->xs->stimeout,
! 1626: (acb->timeout * hz) / 1000);
! 1627: }
! 1628: sc->sc_state = SPC_CONNECTED;
! 1629: } else if ((ints & INTS_TIMEOUT) != 0) {
! 1630: SPC_MISC(("selection timeout "));
! 1631:
! 1632: if (sc->sc_state != SPC_SELECTING) {
! 1633: printf("%s: selection timeout while idle; "
! 1634: "resetting\n", sc->sc_dev.dv_xname);
! 1635: SPC_BREAK();
! 1636: goto reset;
! 1637: }
! 1638: SPC_ASSERT(sc->sc_nexus != NULL);
! 1639: acb = sc->sc_nexus;
! 1640:
! 1641: delay(250);
! 1642:
! 1643: acb->xs->error = XS_SELTIMEOUT;
! 1644: goto finish;
! 1645: } else {
! 1646: if (sc->sc_state != SPC_IDLE) {
! 1647: printf("%s: BUS FREE while not idle; "
! 1648: "state=%d\n",
! 1649: sc->sc_dev.dv_xname, sc->sc_state);
! 1650: SPC_BREAK();
! 1651: goto out;
! 1652: }
! 1653:
! 1654: goto sched;
! 1655: }
! 1656:
! 1657: /*
! 1658: * Turn off selection stuff, and prepare to catch bus free
! 1659: * interrupts, parity errors, and phase changes.
! 1660: */
! 1661:
! 1662: sc->sc_flags = 0;
! 1663: sc->sc_prevphase = PH_INVALID;
! 1664: goto dophase;
! 1665: }
! 1666:
! 1667: if ((ints & INTS_DISCON) != 0) {
! 1668: /* disable disconnect interrupt */
! 1669: spc_write(PCTL, spc_read(PCTL) & ~PCTL_BFINT_ENAB);
! 1670: /* XXX reset interrput */
! 1671: spc_write(INTS, ints);
! 1672:
! 1673: switch (sc->sc_state) {
! 1674: case SPC_RESELECTED:
! 1675: goto sched;
! 1676:
! 1677: case SPC_CONNECTED:
! 1678: SPC_ASSERT(sc->sc_nexus != NULL);
! 1679: acb = sc->sc_nexus;
! 1680:
! 1681: #if SPC_USE_SYNCHRONOUS + SPC_USE_WIDE
! 1682: if (sc->sc_prevphase == PH_MSGOUT) {
! 1683: /*
! 1684: * If the target went to BUS FREE phase during
! 1685: * or immediately after sending a SDTR or WDTR
! 1686: * message, disable negotiation.
! 1687: */
! 1688: sc_link = acb->xs->sc_link;
! 1689: ti = &sc->sc_tinfo[sc_link->target];
! 1690: switch (sc->sc_lastmsg) {
! 1691: #if SPC_USE_SYNCHRONOUS
! 1692: case SEND_SDTR:
! 1693: ti->flags &= ~DO_SYNC;
! 1694: ti->period = ti->offset = 0;
! 1695: break;
! 1696: #endif
! 1697: #if SPC_USE_WIDE
! 1698: case SEND_WDTR:
! 1699: ti->flags &= ~DO_WIDE;
! 1700: ti->width = 0;
! 1701: break;
! 1702: #endif
! 1703: }
! 1704: }
! 1705: #endif
! 1706:
! 1707: if ((sc->sc_flags & SPC_ABORTING) == 0) {
! 1708: /*
! 1709: * Section 5.1.1 of the SCSI 2 spec suggests
! 1710: * issuing a REQUEST SENSE following an
! 1711: * unexpected disconnect. Some devices go into
! 1712: * a contingent allegiance condition when
! 1713: * disconnecting, and this is necessary to
! 1714: * clean up their state.
! 1715: */
! 1716: printf("%s: unexpected disconnect; "
! 1717: "sending REQUEST SENSE\n",
! 1718: sc->sc_dev.dv_xname);
! 1719: SPC_BREAK();
! 1720: spc_sense(sc, acb);
! 1721: goto out;
! 1722: }
! 1723:
! 1724: acb->xs->error = XS_DRIVER_STUFFUP;
! 1725: goto finish;
! 1726:
! 1727: case SPC_DISCONNECT:
! 1728: SPC_ASSERT(sc->sc_nexus != NULL);
! 1729: acb = sc->sc_nexus;
! 1730: TAILQ_INSERT_HEAD(&sc->nexus_list, acb, chain);
! 1731: sc->sc_nexus = NULL;
! 1732: goto sched;
! 1733:
! 1734: case SPC_CMDCOMPLETE:
! 1735: SPC_ASSERT(sc->sc_nexus != NULL);
! 1736: acb = sc->sc_nexus;
! 1737: goto finish;
! 1738: }
! 1739: }
! 1740: else if ((ints & INTS_CMD_DONE) != 0 &&
! 1741: sc->sc_prevphase == PH_MSGIN &&
! 1742: sc->sc_state != SPC_CONNECTED)
! 1743: goto out;
! 1744:
! 1745: /*
! 1746: * Do not change phase (yet) if we have a pending DMA operation.
! 1747: */
! 1748: if ((sc->sc_flags & SPC_DOINGDMA) != 0) {
! 1749: goto out;
! 1750: }
! 1751:
! 1752: dophase:
! 1753: #if 0
! 1754: if ((spc_read(PSNS) & PSNS_REQ) == 0) {
! 1755: /* Wait for REQINIT. */
! 1756: goto out;
! 1757: }
! 1758: #else
! 1759: spc_write(INTS, ints);
! 1760: while ((spc_read(PSNS) & PSNS_REQ) == 0)
! 1761: DELAY(1); /* need timeout XXX */
! 1762: #endif
! 1763:
! 1764: /*
! 1765: * State transition.
! 1766: */
! 1767: sc->sc_phase = spc_read(PSNS) & PH_MASK;
! 1768: #if 0
! 1769: spc_write(PCTL, sc->sc_phase);
! 1770: #endif
! 1771:
! 1772: SPC_MISC(("phase=%d\n", sc->sc_phase));
! 1773: switch (sc->sc_phase) {
! 1774: case PH_MSGOUT:
! 1775: if (sc->sc_state != SPC_CONNECTED &&
! 1776: sc->sc_state != SPC_RESELECTED)
! 1777: break;
! 1778: spc_msgout(sc);
! 1779: sc->sc_prevphase = PH_MSGOUT;
! 1780: goto loop;
! 1781:
! 1782: case PH_MSGIN:
! 1783: if (sc->sc_state != SPC_CONNECTED &&
! 1784: sc->sc_state != SPC_RESELECTED)
! 1785: break;
! 1786: spc_msgin(sc);
! 1787: sc->sc_prevphase = PH_MSGIN;
! 1788: goto loop;
! 1789:
! 1790: case PH_CMD:
! 1791: if (sc->sc_state != SPC_CONNECTED)
! 1792: break;
! 1793: #ifdef SPC_DEBUG
! 1794: if ((spc_debug & SPC_SHOWMISC) != 0) {
! 1795: SPC_ASSERT(sc->sc_nexus != NULL);
! 1796: acb = sc->sc_nexus;
! 1797: printf("cmd=0x%02x+%d ",
! 1798: acb->scsi_cmd.opcode, acb->scsi_cmd_length - 1);
! 1799: }
! 1800: #endif
! 1801: n = spc_dataout_pio(sc, sc->sc_cp, sc->sc_cleft);
! 1802: sc->sc_cp += n;
! 1803: sc->sc_cleft -= n;
! 1804: sc->sc_prevphase = PH_CMD;
! 1805: goto loop;
! 1806:
! 1807: case PH_DATAOUT:
! 1808: if (sc->sc_state != SPC_CONNECTED)
! 1809: break;
! 1810: SPC_MISC(("dataout dleft=%d ", sc->sc_dleft));
! 1811: if (sc->sc_dma_start != NULL &&
! 1812: sc->sc_dleft > SPC_MIN_DMA_LEN) {
! 1813: if ((*sc->sc_dma_start)
! 1814: (sc, sc->sc_dp, sc->sc_dleft, 0) == 0) {
! 1815: sc->sc_prevphase = PH_DATAOUT;
! 1816: goto out;
! 1817: }
! 1818: }
! 1819: n = spc_dataout_pio(sc, sc->sc_dp, sc->sc_dleft);
! 1820: sc->sc_dp += n;
! 1821: sc->sc_dleft -= n;
! 1822: sc->sc_prevphase = PH_DATAOUT;
! 1823: goto loop;
! 1824:
! 1825: case PH_DATAIN:
! 1826: if (sc->sc_state != SPC_CONNECTED)
! 1827: break;
! 1828: SPC_MISC(("datain "));
! 1829: if (sc->sc_dma_start != NULL &&
! 1830: sc->sc_dleft > SPC_MIN_DMA_LEN) {
! 1831: if ((*sc->sc_dma_start)
! 1832: (sc, sc->sc_dp, sc->sc_dleft, 1) == 0) {
! 1833: sc->sc_prevphase = PH_DATAIN;
! 1834: goto out;
! 1835: }
! 1836: }
! 1837: n = spc_datain_pio(sc, sc->sc_dp, sc->sc_dleft);
! 1838: sc->sc_dp += n;
! 1839: sc->sc_dleft -= n;
! 1840: sc->sc_prevphase = PH_DATAIN;
! 1841: goto loop;
! 1842:
! 1843: case PH_STAT:
! 1844: if (sc->sc_state != SPC_CONNECTED)
! 1845: break;
! 1846: SPC_ASSERT(sc->sc_nexus != NULL);
! 1847: acb = sc->sc_nexus;
! 1848: if ((spc_read(PSNS) & PSNS_ATN) != 0)
! 1849: spc_write(SCMD, SCMD_RST_ATN);
! 1850: spc_write(PCTL, PCTL_BFINT_ENAB | PH_STAT);
! 1851: while ((spc_read(PSNS) & PSNS_REQ) == 0)
! 1852: DELAY(1); /* XXX needs timeout */
! 1853: acb->target_stat = spc_read(TEMP);
! 1854: spc_write(SCMD, SCMD_SET_ACK);
! 1855: while ((spc_read(PSNS) & PSNS_REQ) != 0)
! 1856: DELAY(1); /* XXX needs timeout */
! 1857: spc_write(SCMD, SCMD_RST_ACK);
! 1858:
! 1859: SPC_MISC(("target_stat=0x%02x ", acb->target_stat));
! 1860: sc->sc_prevphase = PH_STAT;
! 1861: goto loop;
! 1862: }
! 1863:
! 1864: printf("%s: unexpected bus phase; resetting\n", sc->sc_dev.dv_xname);
! 1865: SPC_BREAK();
! 1866: reset:
! 1867: spc_init(sc);
! 1868: return;
! 1869:
! 1870: finish:
! 1871: spc_write(INTS, ints);
! 1872: ints = 0;
! 1873: spc_done(sc, acb);
! 1874: return;
! 1875:
! 1876: sched:
! 1877: sc->sc_state = SPC_IDLE;
! 1878: spc_sched(sc);
! 1879: goto out;
! 1880:
! 1881: out:
! 1882: if (ints != 0)
! 1883: spc_write(INTS, ints);
! 1884: }
! 1885:
! 1886: void
! 1887: spc_abort(struct spc_softc *sc, struct spc_acb *acb)
! 1888: {
! 1889: /* 2 secs for the abort */
! 1890: acb->timeout = SPC_ABORT_TIMEOUT;
! 1891: acb->flags |= ACB_ABORT;
! 1892:
! 1893: if (acb == sc->sc_nexus) {
! 1894: /*
! 1895: * If we're still selecting, the message will be scheduled
! 1896: * after selection is complete.
! 1897: */
! 1898: if (sc->sc_state == SPC_CONNECTED)
! 1899: spc_sched_msgout(sc, SEND_ABORT);
! 1900: } else {
! 1901: spc_dequeue(sc, acb);
! 1902: TAILQ_INSERT_HEAD(&sc->ready_list, acb, chain);
! 1903: if (sc->sc_state == SPC_IDLE)
! 1904: spc_sched(sc);
! 1905: }
! 1906: }
! 1907:
! 1908: void
! 1909: spc_timeout(void *arg)
! 1910: {
! 1911: struct spc_acb *acb = arg;
! 1912: struct scsi_xfer *xs = acb->xs;
! 1913: struct scsi_link *sc_link = xs->sc_link;
! 1914: struct spc_softc *sc = sc_link->adapter_softc;
! 1915: int s;
! 1916:
! 1917: sc_print_addr(sc_link);
! 1918:
! 1919: s = splbio();
! 1920:
! 1921: /*
! 1922: * We might have missed a DMA completion.
! 1923: * If so, fake an interrupt (even if the INTS register is zero - what
! 1924: * we want here is to change phase).
! 1925: */
! 1926: if ((sc->sc_flags & SPC_DOINGDMA) != 0) {
! 1927: if ((*sc->sc_dma_done)(sc)) {
! 1928: printf("missed DMA completion\n");
! 1929: spc_process_intr(sc, spc_read(INTS));
! 1930: splx(s);
! 1931: return;
! 1932: }
! 1933: }
! 1934:
! 1935: printf("timed out");
! 1936: if (acb->flags & ACB_ABORT) {
! 1937: /* abort timed out */
! 1938: printf(" AGAIN\n");
! 1939: /* XXX Must reset! */
! 1940: } else {
! 1941: /* abort the operation that has timed out */
! 1942: printf("\n");
! 1943: acb->xs->error = XS_TIMEOUT;
! 1944: spc_abort(sc, acb);
! 1945: }
! 1946:
! 1947: splx(s);
! 1948: }
! 1949:
! 1950: #ifdef SPC_DEBUG
! 1951: /*
! 1952: * The following functions are mostly used for debugging purposes, either
! 1953: * directly called from the driver or from the kernel debugger.
! 1954: */
! 1955:
! 1956: void
! 1957: spc_show_scsi_cmd(struct spc_acb *acb)
! 1958: {
! 1959: u_char *b = (u_char *)&acb->scsi_cmd;
! 1960: struct scsi_link *sc_link = acb->xs->sc_link;
! 1961: int i;
! 1962:
! 1963: sc_print_addr(sc_link);
! 1964: if ((acb->xs->flags & SCSI_RESET) == 0) {
! 1965: for (i = 0; i < acb->scsi_cmd_length; i++) {
! 1966: if (i)
! 1967: printf(",");
! 1968: printf("%x", b[i]);
! 1969: }
! 1970: printf("\n");
! 1971: } else
! 1972: printf("RESET\n");
! 1973: }
! 1974:
! 1975: void
! 1976: spc_print_acb(struct spc_acb *acb)
! 1977: {
! 1978: printf("acb@%p xs=%p flags=%x", acb, acb->xs, acb->flags);
! 1979: printf(" dp=%p dleft=%d target_stat=%x\n",
! 1980: acb->data_addr, acb->data_length, acb->target_stat);
! 1981: spc_show_scsi_cmd(acb);
! 1982: }
! 1983:
! 1984: void
! 1985: spc_print_active_acb(void)
! 1986: {
! 1987: struct spc_acb *acb;
! 1988: struct spc_softc *sc = spc_cd.cd_devs[0]; /* XXX */
! 1989:
! 1990: printf("ready list:\n");
! 1991: TAILQ_FOREACH(acb, &sc->ready_list, chain)
! 1992: spc_print_acb(acb);
! 1993: printf("nexus:\n");
! 1994: if (sc->sc_nexus != NULL)
! 1995: spc_print_acb(sc->sc_nexus);
! 1996: printf("nexus list:\n");
! 1997: TAILQ_FOREACH(acb, &sc->nexus_list, chain)
! 1998: spc_print_acb(acb);
! 1999: }
! 2000:
! 2001: void
! 2002: spc_dump89352(struct spc_softc *sc)
! 2003: {
! 2004: printf("mb89352: BDID=%x SCTL=%x SCMD=%x TMOD=%x\n",
! 2005: spc_read(BDID), spc_read(SCTL), spc_read(SCMD), spc_read(TMOD));
! 2006: printf(" INTS=%x PSNS=%x SSTS=%x SERR=%x PCTL=%x\n",
! 2007: spc_read(INTS), spc_read(PSNS), spc_read(SSTS), spc_read(SERR),
! 2008: spc_read(PCTL));
! 2009: printf(" MBC=%x DREG=%x TEMP=%x TCH=%x TCM=%x\n",
! 2010: spc_read(MBC),
! 2011: #if 0
! 2012: spc_read(DREG),
! 2013: #else
! 2014: 0,
! 2015: #endif
! 2016: spc_read(TEMP), spc_read(TCH), spc_read(TCM));
! 2017: printf(" TCL=%x EXBF=%x\n", spc_read(TCL), spc_read(EXBF));
! 2018: }
! 2019:
! 2020: void
! 2021: spc_dump_driver(struct spc_softc *sc)
! 2022: {
! 2023: struct spc_tinfo *ti;
! 2024: int i;
! 2025:
! 2026: printf("nexus=%p phase=%x prevphase=%x\n",
! 2027: sc->sc_nexus, sc->sc_phase, sc->sc_prevphase);
! 2028: printf("state=%x msgin=%x msgpriq=%x msgoutq=%x lastmsg=%x "
! 2029: "currmsg=%x\n", sc->sc_state, sc->sc_imess[0],
! 2030: sc->sc_msgpriq, sc->sc_msgoutq, sc->sc_lastmsg, sc->sc_currmsg);
! 2031: for (i = 0; i < 7; i++) {
! 2032: ti = &sc->sc_tinfo[i];
! 2033: printf("tinfo%d: %d cmds %d disconnects %d timeouts",
! 2034: i, ti->cmds, ti->dconns, ti->touts);
! 2035: printf(" %d senses flags=%x\n", ti->senses, ti->flags);
! 2036: }
! 2037: }
! 2038: #endif
CVSweb