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