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