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