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