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