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