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