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