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