Home | History | Annotate | Line # | Download | only in ic
ncr53c9x.c revision 1.18
      1  1.18   bouyer /*	$NetBSD: ncr53c9x.c,v 1.18 1997/08/27 11:24:59 bouyer Exp $	*/
      2   1.1  thorpej 
      3   1.1  thorpej /*
      4   1.1  thorpej  * Copyright (c) 1996 Charles M. Hannum.  All rights reserved.
      5   1.1  thorpej  *
      6   1.1  thorpej  * Redistribution and use in source and binary forms, with or without
      7   1.1  thorpej  * modification, are permitted provided that the following conditions
      8   1.1  thorpej  * are met:
      9   1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     10   1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     11   1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     12   1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     13   1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     14   1.1  thorpej  * 3. All advertising materials mentioning features or use of this software
     15   1.1  thorpej  *    must display the following acknowledgement:
     16   1.1  thorpej  *	This product includes software developed by Charles M. Hannum.
     17   1.1  thorpej  * 4. The name of the author may not be used to endorse or promote products
     18   1.1  thorpej  *    derived from this software without specific prior written permission.
     19   1.1  thorpej  *
     20   1.1  thorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     21   1.1  thorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     22   1.1  thorpej  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     23   1.1  thorpej  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     24   1.1  thorpej  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     25   1.1  thorpej  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26   1.1  thorpej  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27   1.1  thorpej  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28   1.1  thorpej  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     29   1.1  thorpej  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30   1.1  thorpej  */
     31   1.1  thorpej 
     32   1.1  thorpej /*
     33   1.1  thorpej  * Copyright (c) 1994 Peter Galbavy
     34   1.1  thorpej  * Copyright (c) 1995 Paul Kranenburg
     35   1.1  thorpej  * All rights reserved.
     36   1.1  thorpej  *
     37   1.1  thorpej  * Redistribution and use in source and binary forms, with or without
     38   1.1  thorpej  * modification, are permitted provided that the following conditions
     39   1.1  thorpej  * are met:
     40   1.1  thorpej  * 1. Redistributions of source code must retain the above copyright
     41   1.1  thorpej  *    notice, this list of conditions and the following disclaimer.
     42   1.1  thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     43   1.1  thorpej  *    notice, this list of conditions and the following disclaimer in the
     44   1.1  thorpej  *    documentation and/or other materials provided with the distribution.
     45   1.1  thorpej  * 3. All advertising materials mentioning features or use of this software
     46   1.1  thorpej  *    must display the following acknowledgement:
     47   1.1  thorpej  *	This product includes software developed by Peter Galbavy
     48   1.1  thorpej  * 4. The name of the author may not be used to endorse or promote products
     49   1.1  thorpej  *    derived from this software without specific prior written permission.
     50   1.1  thorpej  *
     51   1.1  thorpej  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     52   1.1  thorpej  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     53   1.1  thorpej  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     54   1.1  thorpej  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     55   1.1  thorpej  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     56   1.1  thorpej  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     57   1.1  thorpej  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58   1.1  thorpej  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     59   1.1  thorpej  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     60   1.1  thorpej  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     61   1.1  thorpej  * POSSIBILITY OF SUCH DAMAGE.
     62   1.1  thorpej  */
     63   1.1  thorpej 
     64   1.1  thorpej /*
     65   1.1  thorpej  * Based on aic6360 by Jarle Greipsland
     66   1.1  thorpej  *
     67   1.1  thorpej  * Acknowledgements: Many of the algorithms used in this driver are
     68   1.1  thorpej  * inspired by the work of Julian Elischer (julian (at) tfs.com) and
     69   1.1  thorpej  * Charles Hannum (mycroft (at) duality.gnu.ai.mit.edu).  Thanks a million!
     70   1.1  thorpej  */
     71   1.1  thorpej 
     72   1.1  thorpej #include <sys/types.h>
     73   1.1  thorpej #include <sys/param.h>
     74   1.1  thorpej #include <sys/systm.h>
     75   1.1  thorpej #include <sys/kernel.h>
     76   1.1  thorpej #include <sys/errno.h>
     77   1.1  thorpej #include <sys/ioctl.h>
     78   1.1  thorpej #include <sys/device.h>
     79   1.1  thorpej #include <sys/buf.h>
     80   1.1  thorpej #include <sys/proc.h>
     81   1.1  thorpej #include <sys/user.h>
     82   1.1  thorpej #include <sys/queue.h>
     83   1.1  thorpej 
     84  1.18   bouyer #include <dev/scsipi/scsi_all.h>
     85  1.18   bouyer #include <dev/scsipi/scsipi_all.h>
     86  1.18   bouyer #include <dev/scsipi/scsiconf.h>
     87  1.18   bouyer #include <dev/scsipi/scsi_message.h>
     88   1.1  thorpej 
     89   1.1  thorpej #include <machine/cpu.h>
     90   1.1  thorpej 
     91   1.1  thorpej #include <dev/ic/ncr53c9xreg.h>
     92   1.1  thorpej #include <dev/ic/ncr53c9xvar.h>
     93   1.1  thorpej 
     94   1.1  thorpej int ncr53c9x_debug = 0; /*NCR_SHOWPHASE|NCR_SHOWMISC|NCR_SHOWTRAC|NCR_SHOWCMDS;*/
     95   1.1  thorpej 
     96   1.1  thorpej /*static*/ void	ncr53c9x_readregs	__P((struct ncr53c9x_softc *));
     97   1.1  thorpej /*static*/ void	ncr53c9x_select		__P((struct ncr53c9x_softc *,
     98   1.1  thorpej 					    struct ncr53c9x_ecb *));
     99   1.1  thorpej /*static*/ int ncr53c9x_reselect	__P((struct ncr53c9x_softc *, int));
    100   1.1  thorpej /*static*/ void	ncr53c9x_scsi_reset	__P((struct ncr53c9x_softc *));
    101   1.1  thorpej /*static*/ void	ncr53c9x_init		__P((struct ncr53c9x_softc *, int));
    102   1.1  thorpej /*static*/ int	ncr53c9x_poll		__P((struct ncr53c9x_softc *,
    103  1.18   bouyer 					    struct scsipi_xfer *, int));
    104   1.1  thorpej /*static*/ void	ncr53c9x_sched		__P((struct ncr53c9x_softc *));
    105   1.1  thorpej /*static*/ void	ncr53c9x_done		__P((struct ncr53c9x_softc *,
    106   1.1  thorpej 					    struct ncr53c9x_ecb *));
    107   1.1  thorpej /*static*/ void	ncr53c9x_msgin		__P((struct ncr53c9x_softc *));
    108   1.1  thorpej /*static*/ void	ncr53c9x_msgout		__P((struct ncr53c9x_softc *));
    109   1.1  thorpej /*static*/ void	ncr53c9x_timeout	__P((void *arg));
    110   1.1  thorpej /*static*/ void	ncr53c9x_abort		__P((struct ncr53c9x_softc *,
    111   1.1  thorpej 					    struct ncr53c9x_ecb *));
    112   1.1  thorpej /*static*/ void ncr53c9x_dequeue	__P((struct ncr53c9x_softc *,
    113   1.1  thorpej 					    struct ncr53c9x_ecb *));
    114   1.1  thorpej 
    115   1.1  thorpej void ncr53c9x_sense			__P((struct ncr53c9x_softc *,
    116   1.1  thorpej 					    struct ncr53c9x_ecb *));
    117   1.1  thorpej void ncr53c9x_free_ecb			__P((struct ncr53c9x_softc *,
    118   1.1  thorpej 					    struct ncr53c9x_ecb *, int));
    119   1.1  thorpej struct ncr53c9x_ecb *ncr53c9x_get_ecb	__P((struct ncr53c9x_softc *, int));
    120   1.1  thorpej 
    121   1.1  thorpej static inline int ncr53c9x_stp2cpb	__P((struct ncr53c9x_softc *, int));
    122   1.1  thorpej static inline void ncr53c9x_setsync	__P((struct ncr53c9x_softc *,
    123   1.1  thorpej 					    struct ncr53c9x_tinfo *));
    124   1.1  thorpej 
    125   1.1  thorpej /*
    126   1.1  thorpej  * Names for the NCR53c9x variants, correspnding to the variant tags
    127   1.1  thorpej  * in ncr53c9xvar.h.
    128   1.1  thorpej  */
    129   1.1  thorpej const char *ncr53c9x_variant_names[] = {
    130   1.1  thorpej 	"ESP100",
    131   1.1  thorpej 	"ESP100A",
    132   1.1  thorpej 	"ESP200",
    133   1.1  thorpej 	"NCR53C94",
    134   1.2   briggs 	"NCR53C96",
    135  1.10       pk 	"ESP406",
    136  1.10       pk 	"FAS408",
    137   1.1  thorpej };
    138   1.1  thorpej 
    139   1.1  thorpej /*
    140   1.1  thorpej  * Attach this instance, and then all the sub-devices
    141   1.1  thorpej  */
    142   1.1  thorpej void
    143   1.1  thorpej ncr53c9x_attach(sc, adapter, dev)
    144   1.1  thorpej 	struct ncr53c9x_softc *sc;
    145  1.18   bouyer 	struct scsipi_adapter *adapter;
    146  1.18   bouyer 	struct scsipi_device *dev;
    147   1.1  thorpej {
    148   1.1  thorpej 
    149   1.1  thorpej 	/*
    150   1.1  thorpej 	 * Note, the front-end has set us up to print the chip variation.
    151   1.1  thorpej 	 */
    152   1.1  thorpej 
    153   1.1  thorpej 	if (sc->sc_rev >= NCR_VARIANT_MAX) {
    154   1.1  thorpej 		printf("\n%s: unknown variant %d, devices not attached\n",
    155   1.1  thorpej 		    sc->sc_dev.dv_xname, sc->sc_rev);
    156   1.1  thorpej 		return;
    157   1.1  thorpej 	}
    158   1.1  thorpej 
    159   1.1  thorpej 	printf(": %s, %dMHz, SCSI ID %d\n",
    160   1.1  thorpej 	    ncr53c9x_variant_names[sc->sc_rev], sc->sc_freq, sc->sc_id);
    161   1.1  thorpej 
    162   1.1  thorpej 	sc->sc_ccf = FREQTOCCF(sc->sc_freq);
    163   1.1  thorpej 
    164   1.1  thorpej 	/* The value *must not* be == 1. Make it 2 */
    165   1.1  thorpej 	if (sc->sc_ccf == 1)
    166   1.1  thorpej 		sc->sc_ccf = 2;
    167   1.1  thorpej 
    168   1.1  thorpej 	/*
    169   1.1  thorpej 	 * The recommended timeout is 250ms. This register is loaded
    170   1.1  thorpej 	 * with a value calculated as follows, from the docs:
    171   1.1  thorpej 	 *
    172   1.1  thorpej 	 *		(timout period) x (CLK frequency)
    173   1.1  thorpej 	 *	reg = -------------------------------------
    174   1.1  thorpej 	 *		 8192 x (Clock Conversion Factor)
    175   1.1  thorpej 	 *
    176   1.1  thorpej 	 * Since CCF has a linear relation to CLK, this generally computes
    177   1.1  thorpej 	 * to the constant of 153.
    178   1.1  thorpej 	 */
    179   1.1  thorpej 	sc->sc_timeout = ((250 * 1000) * sc->sc_freq) / (8192 * sc->sc_ccf);
    180   1.1  thorpej 
    181   1.1  thorpej 	/* CCF register only has 3 bits; 0 is actually 8 */
    182   1.1  thorpej 	sc->sc_ccf &= 7;
    183   1.1  thorpej 
    184   1.1  thorpej 	/* Reset state & bus */
    185  1.16       pk 	sc->sc_cfflags = sc->sc_dev.dv_cfdata->cf_flags;
    186   1.1  thorpej 	sc->sc_state = 0;
    187   1.1  thorpej 	ncr53c9x_init(sc, 1);
    188   1.1  thorpej 
    189   1.1  thorpej 	/*
    190  1.18   bouyer 	 * fill in the prototype scsipi_link.
    191   1.1  thorpej 	 */
    192  1.18   bouyer 	sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
    193   1.1  thorpej 	sc->sc_link.adapter_softc = sc;
    194  1.18   bouyer 	sc->sc_link.scsipi_scsi.adapter_target = sc->sc_id;
    195   1.1  thorpej 	sc->sc_link.adapter = adapter;
    196   1.1  thorpej 	sc->sc_link.device = dev;
    197   1.1  thorpej 	sc->sc_link.openings = 2;
    198  1.18   bouyer 	sc->sc_link.scsipi_scsi.max_target = 7;
    199  1.18   bouyer 	sc->sc_link.type = BUS_SCSI;
    200   1.1  thorpej 
    201   1.1  thorpej 	/*
    202   1.1  thorpej 	 * Now try to attach all the sub-devices
    203   1.1  thorpej 	 */
    204   1.1  thorpej 	config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
    205  1.10       pk 
    206  1.10       pk 	/*
    207  1.10       pk 	 * Enable interupts from the SCSI core
    208  1.10       pk 	 */
    209  1.10       pk 	if ((sc->sc_rev == NCR_VARIANT_ESP406) ||
    210  1.10       pk 	    (sc->sc_rev == NCR_VARIANT_FAS408)) {
    211  1.10       pk 		NCR_PIOREGS(sc);
    212  1.10       pk 		NCR_WRITE_REG(sc, NCR_CFG5, NCRCFG5_SINT |
    213  1.10       pk 		    NCR_READ_REG(sc, NCR_CFG5));
    214  1.10       pk 		NCR_SCSIREGS(sc);
    215  1.10       pk 	}
    216   1.1  thorpej }
    217   1.1  thorpej 
    218   1.1  thorpej /*
    219   1.1  thorpej  * This is the generic esp reset function. It does not reset the SCSI bus,
    220   1.1  thorpej  * only this controllers, but kills any on-going commands, and also stops
    221   1.1  thorpej  * and resets the DMA.
    222   1.1  thorpej  *
    223   1.1  thorpej  * After reset, registers are loaded with the defaults from the attach
    224   1.1  thorpej  * routine above.
    225   1.1  thorpej  */
    226   1.1  thorpej void
    227   1.1  thorpej ncr53c9x_reset(sc)
    228   1.1  thorpej 	struct ncr53c9x_softc *sc;
    229   1.1  thorpej {
    230   1.1  thorpej 
    231   1.1  thorpej 	/* reset DMA first */
    232   1.1  thorpej 	NCRDMA_RESET(sc);
    233   1.1  thorpej 
    234   1.1  thorpej 	/* reset SCSI chip */
    235   1.1  thorpej 	NCRCMD(sc, NCRCMD_RSTCHIP);
    236   1.1  thorpej 	NCRCMD(sc, NCRCMD_NOP);
    237   1.1  thorpej 	DELAY(500);
    238   1.1  thorpej 
    239   1.1  thorpej 	/* do these backwards, and fall through */
    240   1.1  thorpej 	switch (sc->sc_rev) {
    241  1.10       pk 	case NCR_VARIANT_ESP406:
    242  1.10       pk 	case NCR_VARIANT_FAS408:
    243  1.10       pk 		NCR_SCSIREGS(sc);
    244   1.1  thorpej 	case NCR_VARIANT_NCR53C94:
    245   1.2   briggs 	case NCR_VARIANT_NCR53C96:
    246   1.1  thorpej 	case NCR_VARIANT_ESP200:
    247   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
    248   1.1  thorpej 	case NCR_VARIANT_ESP100A:
    249   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
    250   1.1  thorpej 	case NCR_VARIANT_ESP100:
    251   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
    252   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf);
    253   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
    254   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
    255   1.1  thorpej 		break;
    256   1.1  thorpej 	default:
    257   1.1  thorpej 		printf("%s: unknown revision code, assuming ESP100\n",
    258   1.1  thorpej 		    sc->sc_dev.dv_xname);
    259   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
    260   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_CCF, sc->sc_ccf);
    261   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
    262   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
    263   1.1  thorpej 	}
    264   1.1  thorpej }
    265   1.1  thorpej 
    266   1.1  thorpej /*
    267   1.1  thorpej  * Reset the SCSI bus, but not the chip
    268   1.1  thorpej  */
    269   1.1  thorpej void
    270   1.1  thorpej ncr53c9x_scsi_reset(sc)
    271   1.1  thorpej 	struct ncr53c9x_softc *sc;
    272   1.1  thorpej {
    273   1.1  thorpej 
    274   1.1  thorpej 	(*sc->sc_glue->gl_dma_stop)(sc);
    275   1.1  thorpej 
    276   1.1  thorpej 	printf("%s: resetting SCSI bus\n", sc->sc_dev.dv_xname);
    277   1.1  thorpej 	NCRCMD(sc, NCRCMD_RSTSCSI);
    278   1.1  thorpej }
    279   1.1  thorpej 
    280   1.1  thorpej /*
    281   1.1  thorpej  * Initialize esp state machine
    282   1.1  thorpej  */
    283   1.1  thorpej void
    284   1.1  thorpej ncr53c9x_init(sc, doreset)
    285   1.1  thorpej 	struct ncr53c9x_softc *sc;
    286   1.1  thorpej 	int doreset;
    287   1.1  thorpej {
    288   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    289   1.1  thorpej 	int r;
    290   1.1  thorpej 
    291   1.1  thorpej 	NCR_TRACE(("[NCR_INIT(%d)] ", doreset));
    292   1.1  thorpej 
    293   1.1  thorpej 	if (sc->sc_state == 0) {
    294   1.1  thorpej 		/* First time through; initialize. */
    295   1.1  thorpej 		TAILQ_INIT(&sc->ready_list);
    296   1.1  thorpej 		TAILQ_INIT(&sc->nexus_list);
    297   1.1  thorpej 		TAILQ_INIT(&sc->free_list);
    298   1.1  thorpej 		sc->sc_nexus = NULL;
    299   1.1  thorpej 		ecb = sc->sc_ecb;
    300   1.1  thorpej 		bzero(ecb, sizeof(sc->sc_ecb));
    301   1.1  thorpej 		for (r = 0; r < sizeof(sc->sc_ecb) / sizeof(*ecb); r++) {
    302   1.1  thorpej 			TAILQ_INSERT_TAIL(&sc->free_list, ecb, chain);
    303   1.1  thorpej 			ecb++;
    304   1.1  thorpej 		}
    305   1.1  thorpej 		bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
    306   1.1  thorpej 	} else {
    307   1.1  thorpej 		/* Cancel any active commands. */
    308   1.1  thorpej 		sc->sc_state = NCR_CLEANING;
    309   1.1  thorpej 		if ((ecb = sc->sc_nexus) != NULL) {
    310  1.16       pk 			ecb->xs->error = XS_TIMEOUT;
    311   1.1  thorpej 			ncr53c9x_done(sc, ecb);
    312   1.1  thorpej 		}
    313   1.1  thorpej 		while ((ecb = sc->nexus_list.tqh_first) != NULL) {
    314  1.16       pk 			ecb->xs->error = XS_TIMEOUT;
    315   1.1  thorpej 			ncr53c9x_done(sc, ecb);
    316   1.1  thorpej 		}
    317   1.1  thorpej 	}
    318   1.1  thorpej 
    319   1.1  thorpej 	/*
    320   1.1  thorpej 	 * reset the chip to a known state
    321   1.1  thorpej 	 */
    322   1.1  thorpej 	ncr53c9x_reset(sc);
    323   1.1  thorpej 
    324   1.1  thorpej 	sc->sc_phase = sc->sc_prevphase = INVALID_PHASE;
    325   1.1  thorpej 	for (r = 0; r < 8; r++) {
    326   1.1  thorpej 		struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[r];
    327   1.1  thorpej /* XXX - config flags per target: low bits: no reselect; high bits: no synch */
    328   1.1  thorpej 
    329  1.16       pk 		ti->flags = ((sc->sc_minsync && !(sc->sc_cfflags & (1<<(r+8))))
    330   1.1  thorpej 				? T_NEGOTIATE : 0) |
    331  1.16       pk 				((sc->sc_cfflags & (1<<r)) ? T_RSELECTOFF : 0) |
    332   1.1  thorpej 				T_NEED_TO_RESET;
    333   1.1  thorpej 		ti->period = sc->sc_minsync;
    334   1.1  thorpej 		ti->offset = 0;
    335   1.1  thorpej 	}
    336   1.1  thorpej 
    337   1.1  thorpej 	if (doreset) {
    338   1.1  thorpej 		sc->sc_state = NCR_SBR;
    339   1.1  thorpej 		NCRCMD(sc, NCRCMD_RSTSCSI);
    340   1.1  thorpej 	} else {
    341   1.1  thorpej 		sc->sc_state = NCR_IDLE;
    342  1.15       pk 		ncr53c9x_sched(sc);
    343   1.1  thorpej 	}
    344   1.1  thorpej }
    345   1.1  thorpej 
    346   1.1  thorpej /*
    347   1.1  thorpej  * Read the NCR registers, and save their contents for later use.
    348   1.1  thorpej  * NCR_STAT, NCR_STEP & NCR_INTR are mostly zeroed out when reading
    349   1.1  thorpej  * NCR_INTR - so make sure it is the last read.
    350   1.1  thorpej  *
    351   1.1  thorpej  * I think that (from reading the docs) most bits in these registers
    352   1.1  thorpej  * only make sense when he DMA CSR has an interrupt showing. Call only
    353   1.1  thorpej  * if an interrupt is pending.
    354   1.1  thorpej  */
    355   1.1  thorpej void
    356   1.1  thorpej ncr53c9x_readregs(sc)
    357   1.1  thorpej 	struct ncr53c9x_softc *sc;
    358   1.1  thorpej {
    359   1.1  thorpej 
    360   1.1  thorpej 	sc->sc_espstat = NCR_READ_REG(sc, NCR_STAT);
    361   1.1  thorpej 	/* Only the stepo bits are of interest */
    362   1.1  thorpej 	sc->sc_espstep = NCR_READ_REG(sc, NCR_STEP) & NCRSTEP_MASK;
    363   1.1  thorpej 	sc->sc_espintr = NCR_READ_REG(sc, NCR_INTR);
    364   1.1  thorpej 
    365   1.1  thorpej 	if (sc->sc_glue->gl_clear_latched_intr != NULL)
    366   1.1  thorpej 		(*sc->sc_glue->gl_clear_latched_intr)(sc);
    367   1.1  thorpej 
    368   1.1  thorpej 	/*
    369   1.1  thorpej 	 * Determine the SCSI bus phase, return either a real SCSI bus phase
    370   1.1  thorpej 	 * or some pseudo phase we use to detect certain exceptions.
    371   1.1  thorpej 	 */
    372   1.1  thorpej 
    373   1.1  thorpej 	sc->sc_phase = (sc->sc_espintr & NCRINTR_DIS)
    374   1.1  thorpej 			? /* Disconnected */ BUSFREE_PHASE
    375   1.1  thorpej 			: sc->sc_espstat & NCRSTAT_PHASE;
    376   1.1  thorpej 
    377   1.1  thorpej 	NCR_MISC(("regs[intr=%02x,stat=%02x,step=%02x] ",
    378   1.1  thorpej 		sc->sc_espintr, sc->sc_espstat, sc->sc_espstep));
    379   1.1  thorpej }
    380   1.1  thorpej 
    381   1.1  thorpej /*
    382   1.1  thorpej  * Convert Synchronous Transfer Period to chip register Clock Per Byte value.
    383   1.1  thorpej  */
    384   1.1  thorpej static inline int
    385   1.1  thorpej ncr53c9x_stp2cpb(sc, period)
    386   1.1  thorpej 	struct ncr53c9x_softc *sc;
    387   1.1  thorpej 	int period;
    388   1.1  thorpej {
    389   1.1  thorpej 	int v;
    390   1.1  thorpej 	v = (sc->sc_freq * period) / 250;
    391   1.1  thorpej 	if (ncr53c9x_cpb2stp(sc, v) < period)
    392   1.1  thorpej 		/* Correct round-down error */
    393   1.1  thorpej 		v++;
    394   1.1  thorpej 	return v;
    395   1.1  thorpej }
    396   1.1  thorpej 
    397   1.1  thorpej static inline void
    398   1.1  thorpej ncr53c9x_setsync(sc, ti)
    399   1.1  thorpej 	struct ncr53c9x_softc *sc;
    400   1.1  thorpej 	struct ncr53c9x_tinfo *ti;
    401   1.1  thorpej {
    402   1.1  thorpej 
    403   1.1  thorpej 	if (ti->flags & T_SYNCMODE) {
    404   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_SYNCOFF, ti->offset);
    405   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_SYNCTP,
    406   1.1  thorpej 		    ncr53c9x_stp2cpb(sc, ti->period));
    407   1.1  thorpej 	} else {
    408   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
    409   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_SYNCTP, 0);
    410   1.1  thorpej 	}
    411   1.1  thorpej }
    412   1.1  thorpej 
    413   1.8       pk int ncr53c9x_dmaselect = 0;
    414   1.1  thorpej /*
    415   1.1  thorpej  * Send a command to a target, set the driver state to NCR_SELECTING
    416   1.1  thorpej  * and let the caller take care of the rest.
    417   1.1  thorpej  *
    418   1.1  thorpej  * Keeping this as a function allows me to say that this may be done
    419   1.1  thorpej  * by DMA instead of programmed I/O soon.
    420   1.1  thorpej  */
    421   1.1  thorpej void
    422   1.1  thorpej ncr53c9x_select(sc, ecb)
    423   1.1  thorpej 	struct ncr53c9x_softc *sc;
    424   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    425   1.1  thorpej {
    426  1.18   bouyer 	struct scsipi_link *sc_link = ecb->xs->sc_link;
    427  1.18   bouyer 	int target = sc_link->scsipi_scsi.target;
    428   1.1  thorpej 	struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[target];
    429   1.1  thorpej 	u_char *cmd;
    430   1.1  thorpej 	int clen;
    431   1.1  thorpej 
    432   1.1  thorpej 	NCR_TRACE(("[ncr53c9x_select(t%d,l%d,cmd:%x)] ",
    433  1.18   bouyer 	    sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun, ecb->cmd.cmd.opcode));
    434   1.1  thorpej 
    435   1.1  thorpej 	/* new state NCR_SELECTING */
    436   1.1  thorpej 	sc->sc_state = NCR_SELECTING;
    437   1.1  thorpej 
    438   1.7      gwr 	/*
    439   1.7      gwr 	 * Schedule the timeout now, the first time we will go away
    440   1.7      gwr 	 * expecting to come back due to an interrupt, because it is
    441   1.7      gwr 	 * always possible that the interrupt may never happen.
    442   1.7      gwr 	 */
    443   1.7      gwr 	if ((ecb->xs->flags & SCSI_POLL) == 0)
    444   1.7      gwr 		timeout(ncr53c9x_timeout, ecb,
    445   1.7      gwr 		    (ecb->timeout * hz) / 1000);
    446   1.7      gwr 
    447   1.1  thorpej 	NCRCMD(sc, NCRCMD_FLUSH);
    448   1.1  thorpej 
    449   1.1  thorpej 	/*
    450   1.1  thorpej 	 * The docs say the target register is never reset, and I
    451   1.1  thorpej 	 * can't think of a better place to set it
    452   1.1  thorpej 	 */
    453   1.1  thorpej 	NCR_WRITE_REG(sc, NCR_SELID, target);
    454   1.1  thorpej 	ncr53c9x_setsync(sc, ti);
    455   1.1  thorpej 
    456   1.8       pk 	if (ncr53c9x_dmaselect && (ti->flags & T_NEGOTIATE) == 0) {
    457   1.9   mjacob 		size_t dmacl;
    458   1.8       pk 		ecb->cmd.id =
    459  1.18   bouyer 		    MSG_IDENTIFY(sc_link->scsipi_scsi.lun,
    460  1.18   bouyer 				(ti->flags & T_RSELECTOFF)?0:1);
    461   1.8       pk 
    462   1.8       pk 		/* setup DMA transfer for command */
    463   1.8       pk 		clen = ecb->clen + 1;
    464   1.8       pk 		sc->sc_cmdlen = clen;
    465   1.8       pk 		sc->sc_cmdp = (caddr_t)&ecb->cmd;
    466   1.9   mjacob 		dmacl = clen;
    467   1.9   mjacob 		NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmacl);
    468   1.8       pk 		/* Program the SCSI counter */
    469   1.8       pk 		NCR_WRITE_REG(sc, NCR_TCL, clen);
    470   1.8       pk 		NCR_WRITE_REG(sc, NCR_TCM, clen >> 8);
    471   1.8       pk 		if (sc->sc_cfg2 & NCRCFG2_FE) {
    472   1.8       pk 			NCR_WRITE_REG(sc, NCR_TCH, clen >> 16);
    473   1.8       pk 		}
    474   1.8       pk 
    475   1.8       pk 		/* And get the targets attention */
    476   1.8       pk 		NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);
    477   1.8       pk 		NCRDMA_GO(sc);
    478   1.8       pk 		return;
    479   1.8       pk 	}
    480   1.1  thorpej 	/*
    481   1.1  thorpej 	 * Who am I. This is where we tell the target that we are
    482   1.1  thorpej 	 * happy for it to disconnect etc.
    483   1.1  thorpej 	 */
    484   1.1  thorpej 	NCR_WRITE_REG(sc, NCR_FIFO,
    485  1.18   bouyer 		MSG_IDENTIFY(sc_link->scsipi_scsi.lun, (ti->flags & T_RSELECTOFF)?0:1));
    486   1.1  thorpej 
    487   1.1  thorpej 	if (ti->flags & T_NEGOTIATE) {
    488   1.1  thorpej 		/* Arbitrate, select and stop after IDENTIFY message */
    489   1.1  thorpej 		NCRCMD(sc, NCRCMD_SELATNS);
    490   1.1  thorpej 		return;
    491   1.1  thorpej 	}
    492   1.1  thorpej 
    493   1.1  thorpej 	/* Now the command into the FIFO */
    494   1.8       pk 	cmd = (u_char *)&ecb->cmd.cmd;
    495   1.1  thorpej 	clen = ecb->clen;
    496   1.1  thorpej 	while (clen--)
    497   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_FIFO, *cmd++);
    498   1.1  thorpej 
    499   1.1  thorpej 	/* And get the targets attention */
    500   1.1  thorpej 	NCRCMD(sc, NCRCMD_SELATN);
    501   1.1  thorpej }
    502   1.1  thorpej 
    503   1.1  thorpej void
    504   1.1  thorpej ncr53c9x_free_ecb(sc, ecb, flags)
    505   1.1  thorpej 	struct ncr53c9x_softc *sc;
    506   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    507   1.1  thorpej 	int flags;
    508   1.1  thorpej {
    509   1.1  thorpej 	int s;
    510   1.1  thorpej 
    511   1.1  thorpej 	s = splbio();
    512   1.1  thorpej 
    513   1.1  thorpej 	ecb->flags = 0;
    514   1.1  thorpej 	TAILQ_INSERT_HEAD(&sc->free_list, ecb, chain);
    515   1.1  thorpej 
    516   1.1  thorpej 	/*
    517   1.1  thorpej 	 * If there were none, wake anybody waiting for one to come free,
    518   1.1  thorpej 	 * starting with queued entries.
    519   1.1  thorpej 	 */
    520   1.1  thorpej 	if (ecb->chain.tqe_next == 0)
    521   1.1  thorpej 		wakeup(&sc->free_list);
    522   1.1  thorpej 
    523   1.1  thorpej 	splx(s);
    524   1.1  thorpej }
    525   1.1  thorpej 
    526   1.1  thorpej struct ncr53c9x_ecb *
    527   1.1  thorpej ncr53c9x_get_ecb(sc, flags)
    528   1.1  thorpej 	struct ncr53c9x_softc *sc;
    529   1.1  thorpej 	int flags;
    530   1.1  thorpej {
    531   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    532   1.1  thorpej 	int s;
    533   1.1  thorpej 
    534   1.1  thorpej 	s = splbio();
    535   1.1  thorpej 
    536   1.1  thorpej 	while ((ecb = sc->free_list.tqh_first) == NULL &&
    537   1.1  thorpej 	       (flags & SCSI_NOSLEEP) == 0)
    538   1.1  thorpej 		tsleep(&sc->free_list, PRIBIO, "especb", 0);
    539   1.1  thorpej 	if (ecb) {
    540   1.1  thorpej 		TAILQ_REMOVE(&sc->free_list, ecb, chain);
    541   1.1  thorpej 		ecb->flags |= ECB_ALLOC;
    542   1.1  thorpej 	}
    543   1.1  thorpej 
    544   1.1  thorpej 	splx(s);
    545   1.1  thorpej 	return ecb;
    546   1.1  thorpej }
    547   1.1  thorpej 
    548   1.1  thorpej /*
    549   1.1  thorpej  * DRIVER FUNCTIONS CALLABLE FROM HIGHER LEVEL DRIVERS
    550   1.1  thorpej  */
    551   1.1  thorpej 
    552   1.1  thorpej /*
    553   1.1  thorpej  * Start a SCSI-command
    554   1.1  thorpej  * This function is called by the higher level SCSI-driver to queue/run
    555   1.1  thorpej  * SCSI-commands.
    556   1.1  thorpej  */
    557   1.1  thorpej int
    558   1.1  thorpej ncr53c9x_scsi_cmd(xs)
    559  1.18   bouyer 	struct scsipi_xfer *xs;
    560   1.1  thorpej {
    561  1.18   bouyer 	struct scsipi_link *sc_link = xs->sc_link;
    562   1.1  thorpej 	struct ncr53c9x_softc *sc = sc_link->adapter_softc;
    563   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    564   1.1  thorpej 	int s, flags;
    565   1.1  thorpej 
    566   1.1  thorpej 	NCR_TRACE(("[ncr53c9x_scsi_cmd] "));
    567   1.1  thorpej 	NCR_CMDS(("[0x%x, %d]->%d ", (int)xs->cmd->opcode, xs->cmdlen,
    568  1.18   bouyer 	    sc_link->scsipi_scsi.target));
    569   1.1  thorpej 
    570   1.1  thorpej 	flags = xs->flags;
    571  1.16       pk 	if ((ecb = ncr53c9x_get_ecb(sc, flags)) == NULL)
    572   1.1  thorpej 		return TRY_AGAIN_LATER;
    573   1.1  thorpej 
    574   1.1  thorpej 	/* Initialize ecb */
    575   1.1  thorpej 	ecb->xs = xs;
    576   1.1  thorpej 	ecb->timeout = xs->timeout;
    577   1.1  thorpej 
    578   1.4      gwr 	if (flags & SCSI_RESET) {
    579   1.1  thorpej 		ecb->flags |= ECB_RESET;
    580   1.1  thorpej 		ecb->clen = 0;
    581   1.1  thorpej 		ecb->dleft = 0;
    582   1.1  thorpej 	} else {
    583   1.8       pk 		bcopy(xs->cmd, &ecb->cmd.cmd, xs->cmdlen);
    584   1.1  thorpej 		ecb->clen = xs->cmdlen;
    585   1.1  thorpej 		ecb->daddr = xs->data;
    586   1.1  thorpej 		ecb->dleft = xs->datalen;
    587   1.1  thorpej 	}
    588   1.1  thorpej 	ecb->stat = 0;
    589   1.1  thorpej 
    590   1.1  thorpej 	s = splbio();
    591   1.1  thorpej 
    592   1.1  thorpej 	TAILQ_INSERT_TAIL(&sc->ready_list, ecb, chain);
    593   1.1  thorpej 	if (sc->sc_state == NCR_IDLE)
    594   1.1  thorpej 		ncr53c9x_sched(sc);
    595   1.1  thorpej 
    596   1.1  thorpej 	splx(s);
    597   1.1  thorpej 
    598   1.1  thorpej 	if ((flags & SCSI_POLL) == 0)
    599   1.1  thorpej 		return SUCCESSFULLY_QUEUED;
    600   1.1  thorpej 
    601   1.1  thorpej 	/* Not allowed to use interrupts, use polling instead */
    602   1.1  thorpej 	if (ncr53c9x_poll(sc, xs, ecb->timeout)) {
    603   1.1  thorpej 		ncr53c9x_timeout(ecb);
    604   1.1  thorpej 		if (ncr53c9x_poll(sc, xs, ecb->timeout))
    605   1.1  thorpej 			ncr53c9x_timeout(ecb);
    606   1.1  thorpej 	}
    607   1.1  thorpej 	return COMPLETE;
    608   1.1  thorpej }
    609   1.1  thorpej 
    610   1.1  thorpej /*
    611   1.1  thorpej  * Used when interrupt driven I/O isn't allowed, e.g. during boot.
    612   1.1  thorpej  */
    613   1.1  thorpej int
    614   1.1  thorpej ncr53c9x_poll(sc, xs, count)
    615   1.1  thorpej 	struct ncr53c9x_softc *sc;
    616  1.18   bouyer 	struct scsipi_xfer *xs;
    617   1.1  thorpej 	int count;
    618   1.1  thorpej {
    619   1.1  thorpej 
    620   1.1  thorpej 	NCR_TRACE(("[ncr53c9x_poll] "));
    621   1.1  thorpej 	while (count) {
    622   1.1  thorpej 		if (NCRDMA_ISINTR(sc)) {
    623   1.1  thorpej 			ncr53c9x_intr(sc);
    624   1.1  thorpej 		}
    625   1.1  thorpej #if alternatively
    626   1.1  thorpej 		if (NCR_READ_REG(sc, NCR_STAT) & NCRSTAT_INT)
    627   1.1  thorpej 			ncr53c9x_intr(sc);
    628   1.1  thorpej #endif
    629   1.1  thorpej 		if ((xs->flags & ITSDONE) != 0)
    630   1.1  thorpej 			return 0;
    631   1.1  thorpej 		if (sc->sc_state == NCR_IDLE) {
    632   1.1  thorpej 			NCR_TRACE(("[ncr53c9x_poll: rescheduling] "));
    633   1.1  thorpej 			ncr53c9x_sched(sc);
    634   1.1  thorpej 		}
    635   1.1  thorpej 		DELAY(1000);
    636   1.1  thorpej 		count--;
    637   1.1  thorpej 	}
    638   1.1  thorpej 	return 1;
    639   1.1  thorpej }
    640   1.1  thorpej 
    641   1.1  thorpej 
    642   1.1  thorpej /*
    643   1.1  thorpej  * LOW LEVEL SCSI UTILITIES
    644   1.1  thorpej  */
    645   1.1  thorpej 
    646   1.1  thorpej /*
    647   1.1  thorpej  * Schedule a scsi operation.  This has now been pulled out of the interrupt
    648   1.1  thorpej  * handler so that we may call it from ncr53c9x_scsi_cmd and ncr53c9x_done.
    649   1.1  thorpej  * This may save us an unecessary interrupt just to get things going.
    650   1.1  thorpej  * Should only be called when state == NCR_IDLE and at bio pl.
    651   1.1  thorpej  */
    652   1.1  thorpej void
    653   1.1  thorpej ncr53c9x_sched(sc)
    654   1.1  thorpej 	struct ncr53c9x_softc *sc;
    655   1.1  thorpej {
    656   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    657  1.18   bouyer 	struct scsipi_link *sc_link;
    658   1.1  thorpej 	struct ncr53c9x_tinfo *ti;
    659   1.1  thorpej 
    660   1.1  thorpej 	NCR_TRACE(("[ncr53c9x_sched] "));
    661   1.1  thorpej 	if (sc->sc_state != NCR_IDLE)
    662   1.1  thorpej 		panic("ncr53c9x_sched: not IDLE (state=%d)", sc->sc_state);
    663   1.1  thorpej 
    664   1.1  thorpej 	/*
    665   1.1  thorpej 	 * Find first ecb in ready queue that is for a target/lunit
    666   1.1  thorpej 	 * combinations that is not busy.
    667   1.1  thorpej 	 */
    668   1.1  thorpej 	for (ecb = sc->ready_list.tqh_first; ecb; ecb = ecb->chain.tqe_next) {
    669   1.1  thorpej 		sc_link = ecb->xs->sc_link;
    670  1.18   bouyer 		ti = &sc->sc_tinfo[sc_link->scsipi_scsi.target];
    671  1.18   bouyer 		if ((ti->lubusy & (1 << sc_link->scsipi_scsi.lun)) == 0) {
    672   1.1  thorpej 			TAILQ_REMOVE(&sc->ready_list, ecb, chain);
    673   1.1  thorpej 			sc->sc_nexus = ecb;
    674   1.1  thorpej 			ncr53c9x_select(sc, ecb);
    675   1.1  thorpej 			break;
    676   1.1  thorpej 		} else
    677   1.1  thorpej 			NCR_MISC(("%d:%d busy\n",
    678  1.18   bouyer 			    sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun));
    679   1.1  thorpej 	}
    680   1.1  thorpej }
    681   1.1  thorpej 
    682   1.1  thorpej void
    683   1.1  thorpej ncr53c9x_sense(sc, ecb)
    684   1.1  thorpej 	struct ncr53c9x_softc *sc;
    685   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    686   1.1  thorpej {
    687  1.18   bouyer 	struct scsipi_xfer *xs = ecb->xs;
    688  1.18   bouyer 	struct scsipi_link *sc_link = xs->sc_link;
    689  1.18   bouyer 	struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[sc_link->scsipi_scsi.target];
    690  1.18   bouyer 	struct scsipi_sense *ss = (void *)&ecb->cmd.cmd;
    691   1.1  thorpej 
    692   1.1  thorpej 	NCR_MISC(("requesting sense "));
    693   1.1  thorpej 	/* Next, setup a request sense command block */
    694   1.1  thorpej 	bzero(ss, sizeof(*ss));
    695   1.1  thorpej 	ss->opcode = REQUEST_SENSE;
    696  1.18   bouyer 	ss->byte2 = sc_link->scsipi_scsi.lun << 5;
    697  1.18   bouyer 	ss->length = sizeof(struct scsipi_sense_data);
    698   1.1  thorpej 	ecb->clen = sizeof(*ss);
    699  1.18   bouyer 	ecb->daddr = (char *)&xs->sense.scsi_sense;
    700  1.18   bouyer 	ecb->dleft = sizeof(struct scsipi_sense_data);
    701   1.1  thorpej 	ecb->flags |= ECB_SENSE;
    702   1.7      gwr 	ecb->timeout = NCR_SENSE_TIMEOUT;
    703   1.1  thorpej 	ti->senses++;
    704   1.1  thorpej 	if (ecb->flags & ECB_NEXUS)
    705  1.18   bouyer 		ti->lubusy &= ~(1 << sc_link->scsipi_scsi.lun);
    706   1.1  thorpej 	if (ecb == sc->sc_nexus) {
    707   1.1  thorpej 		ncr53c9x_select(sc, ecb);
    708   1.1  thorpej 	} else {
    709   1.1  thorpej 		ncr53c9x_dequeue(sc, ecb);
    710   1.1  thorpej 		TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
    711   1.1  thorpej 		if (sc->sc_state == NCR_IDLE)
    712   1.1  thorpej 			ncr53c9x_sched(sc);
    713   1.1  thorpej 	}
    714   1.1  thorpej }
    715   1.1  thorpej 
    716   1.1  thorpej /*
    717   1.1  thorpej  * POST PROCESSING OF SCSI_CMD (usually current)
    718   1.1  thorpej  */
    719   1.1  thorpej void
    720   1.1  thorpej ncr53c9x_done(sc, ecb)
    721   1.1  thorpej 	struct ncr53c9x_softc *sc;
    722   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    723   1.1  thorpej {
    724  1.18   bouyer 	struct scsipi_xfer *xs = ecb->xs;
    725  1.18   bouyer 	struct scsipi_link *sc_link = xs->sc_link;
    726  1.18   bouyer 	struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[sc_link->scsipi_scsi.target];
    727   1.1  thorpej 
    728   1.1  thorpej 	NCR_TRACE(("[ncr53c9x_done(error:%x)] ", xs->error));
    729   1.1  thorpej 
    730   1.7      gwr 	untimeout(ncr53c9x_timeout, ecb);
    731   1.7      gwr 
    732   1.1  thorpej 	/*
    733   1.1  thorpej 	 * Now, if we've come here with no error code, i.e. we've kept the
    734   1.1  thorpej 	 * initial XS_NOERROR, and the status code signals that we should
    735   1.1  thorpej 	 * check sense, we'll need to set up a request sense cmd block and
    736   1.1  thorpej 	 * push the command back into the ready queue *before* any other
    737   1.1  thorpej 	 * commands for this target/lunit, else we lose the sense info.
    738   1.1  thorpej 	 * We don't support chk sense conditions for the request sense cmd.
    739   1.1  thorpej 	 */
    740   1.1  thorpej 	if (xs->error == XS_NOERROR) {
    741  1.12       pk 		xs->status = ecb->stat;
    742   1.1  thorpej 		if ((ecb->flags & ECB_ABORT) != 0) {
    743  1.16       pk 			xs->error = XS_TIMEOUT;
    744   1.1  thorpej 		} else if ((ecb->flags & ECB_SENSE) != 0) {
    745   1.1  thorpej 			xs->error = XS_SENSE;
    746   1.1  thorpej 		} else if ((ecb->stat & ST_MASK) == SCSI_CHECK) {
    747   1.1  thorpej 			/* First, save the return values */
    748   1.1  thorpej 			xs->resid = ecb->dleft;
    749   1.1  thorpej 			ncr53c9x_sense(sc, ecb);
    750   1.1  thorpej 			return;
    751   1.1  thorpej 		} else {
    752   1.1  thorpej 			xs->resid = ecb->dleft;
    753   1.1  thorpej 		}
    754   1.1  thorpej 	}
    755   1.1  thorpej 
    756   1.1  thorpej 	xs->flags |= ITSDONE;
    757   1.1  thorpej 
    758   1.1  thorpej #ifdef NCR53C9X_DEBUG
    759   1.1  thorpej 	if (ncr53c9x_debug & NCR_SHOWMISC) {
    760   1.1  thorpej 		if (xs->resid != 0)
    761   1.1  thorpej 			printf("resid=%d ", xs->resid);
    762   1.1  thorpej 		if (xs->error == XS_SENSE)
    763  1.18   bouyer 			printf("sense=0x%02x\n", xs->sense.scsi_sense.error_code);
    764   1.1  thorpej 		else
    765   1.1  thorpej 			printf("error=%d\n", xs->error);
    766   1.1  thorpej 	}
    767   1.1  thorpej #endif
    768   1.1  thorpej 
    769   1.1  thorpej 	/*
    770   1.1  thorpej 	 * Remove the ECB from whatever queue it's on.
    771   1.1  thorpej 	 */
    772   1.1  thorpej 	if (ecb->flags & ECB_NEXUS)
    773  1.18   bouyer 		ti->lubusy &= ~(1 << sc_link->scsipi_scsi.lun);
    774   1.1  thorpej 	if (ecb == sc->sc_nexus) {
    775   1.1  thorpej 		sc->sc_nexus = NULL;
    776  1.15       pk 		if (sc->sc_state != NCR_CLEANING) {
    777  1.15       pk 			sc->sc_state = NCR_IDLE;
    778  1.15       pk 			ncr53c9x_sched(sc);
    779  1.15       pk 		}
    780   1.1  thorpej 	} else
    781   1.1  thorpej 		ncr53c9x_dequeue(sc, ecb);
    782   1.1  thorpej 
    783   1.1  thorpej 	ncr53c9x_free_ecb(sc, ecb, xs->flags);
    784   1.1  thorpej 	ti->cmds++;
    785  1.18   bouyer 	scsipi_done(xs);
    786   1.1  thorpej }
    787   1.1  thorpej 
    788   1.1  thorpej void
    789   1.1  thorpej ncr53c9x_dequeue(sc, ecb)
    790   1.1  thorpej 	struct ncr53c9x_softc *sc;
    791   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    792   1.1  thorpej {
    793   1.1  thorpej 
    794   1.1  thorpej 	if (ecb->flags & ECB_NEXUS) {
    795   1.1  thorpej 		TAILQ_REMOVE(&sc->nexus_list, ecb, chain);
    796   1.1  thorpej 	} else {
    797   1.1  thorpej 		TAILQ_REMOVE(&sc->ready_list, ecb, chain);
    798   1.1  thorpej 	}
    799   1.1  thorpej }
    800   1.1  thorpej 
    801   1.1  thorpej /*
    802   1.1  thorpej  * INTERRUPT/PROTOCOL ENGINE
    803   1.1  thorpej  */
    804   1.1  thorpej 
    805   1.1  thorpej /*
    806   1.1  thorpej  * Schedule an outgoing message by prioritizing it, and asserting
    807   1.1  thorpej  * attention on the bus. We can only do this when we are the initiator
    808   1.1  thorpej  * else there will be an illegal command interrupt.
    809   1.1  thorpej  */
    810   1.1  thorpej #define ncr53c9x_sched_msgout(m) \
    811   1.1  thorpej 	do {							\
    812   1.1  thorpej 		NCR_MISC(("ncr53c9x_sched_msgout %d ", m));	\
    813   1.1  thorpej 		NCRCMD(sc, NCRCMD_SETATN);			\
    814   1.1  thorpej 		sc->sc_flags |= NCR_ATN;			\
    815   1.1  thorpej 		sc->sc_msgpriq |= (m);				\
    816   1.1  thorpej 	} while (0)
    817   1.1  thorpej 
    818   1.1  thorpej int
    819   1.1  thorpej ncr53c9x_reselect(sc, message)
    820   1.1  thorpej 	struct ncr53c9x_softc *sc;
    821   1.1  thorpej 	int message;
    822   1.1  thorpej {
    823   1.1  thorpej 	u_char selid, target, lun;
    824   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
    825  1.18   bouyer 	struct scsipi_link *sc_link;
    826   1.1  thorpej 	struct ncr53c9x_tinfo *ti;
    827   1.1  thorpej 
    828   1.1  thorpej 	/*
    829   1.1  thorpej 	 * The SCSI chip made a snapshot of the data bus while the reselection
    830   1.1  thorpej 	 * was being negotiated.  This enables us to determine which target did
    831   1.1  thorpej 	 * the reselect.
    832   1.1  thorpej 	 */
    833   1.1  thorpej 	selid = sc->sc_selid & ~(1 << sc->sc_id);
    834   1.1  thorpej 	if (selid & (selid - 1)) {
    835   1.1  thorpej 		printf("%s: reselect with invalid selid %02x;"
    836   1.1  thorpej 		    " sending DEVICE RESET\n", sc->sc_dev.dv_xname, selid);
    837   1.1  thorpej 		goto reset;
    838   1.1  thorpej 	}
    839   1.1  thorpej 
    840   1.1  thorpej 	/*
    841   1.1  thorpej 	 * Search wait queue for disconnected cmd
    842   1.1  thorpej 	 * The list should be short, so I haven't bothered with
    843   1.1  thorpej 	 * any more sophisticated structures than a simple
    844   1.1  thorpej 	 * singly linked list.
    845   1.1  thorpej 	 */
    846   1.1  thorpej 	target = ffs(selid) - 1;
    847   1.1  thorpej 	lun = message & 0x07;
    848   1.1  thorpej 	for (ecb = sc->nexus_list.tqh_first; ecb != NULL;
    849   1.1  thorpej 	     ecb = ecb->chain.tqe_next) {
    850   1.1  thorpej 		sc_link = ecb->xs->sc_link;
    851  1.18   bouyer 		if (sc_link->scsipi_scsi.target == target && sc_link->scsipi_scsi.lun == lun)
    852   1.1  thorpej 			break;
    853   1.1  thorpej 	}
    854   1.1  thorpej 	if (ecb == NULL) {
    855   1.1  thorpej 		printf("%s: reselect from target %d lun %d with no nexus;"
    856   1.1  thorpej 		    " sending ABORT\n", sc->sc_dev.dv_xname, target, lun);
    857   1.1  thorpej 		goto abort;
    858   1.1  thorpej 	}
    859   1.1  thorpej 
    860   1.1  thorpej 	/* Make this nexus active again. */
    861   1.1  thorpej 	TAILQ_REMOVE(&sc->nexus_list, ecb, chain);
    862   1.1  thorpej 	sc->sc_state = NCR_CONNECTED;
    863   1.1  thorpej 	sc->sc_nexus = ecb;
    864   1.1  thorpej 	ti = &sc->sc_tinfo[target];
    865   1.1  thorpej 	ti->lubusy |= (1 << lun);
    866   1.1  thorpej 	ncr53c9x_setsync(sc, ti);
    867   1.1  thorpej 
    868   1.1  thorpej 	if (ecb->flags & ECB_RESET)
    869   1.1  thorpej 		ncr53c9x_sched_msgout(SEND_DEV_RESET);
    870   1.1  thorpej 	else if (ecb->flags & ECB_ABORT)
    871   1.1  thorpej 		ncr53c9x_sched_msgout(SEND_ABORT);
    872   1.1  thorpej 
    873   1.1  thorpej 	/* Do an implicit RESTORE POINTERS. */
    874   1.1  thorpej 	sc->sc_dp = ecb->daddr;
    875   1.1  thorpej 	sc->sc_dleft = ecb->dleft;
    876   1.1  thorpej 
    877   1.1  thorpej 	return (0);
    878   1.1  thorpej 
    879   1.1  thorpej reset:
    880   1.1  thorpej 	ncr53c9x_sched_msgout(SEND_DEV_RESET);
    881   1.1  thorpej 	return (1);
    882   1.1  thorpej 
    883   1.1  thorpej abort:
    884   1.1  thorpej 	ncr53c9x_sched_msgout(SEND_ABORT);
    885   1.1  thorpej 	return (1);
    886   1.1  thorpej }
    887   1.1  thorpej 
    888   1.1  thorpej #define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80)
    889   1.1  thorpej #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
    890   1.1  thorpej #define ISEXTMSG(m) ((m) == 1)
    891   1.1  thorpej 
    892   1.1  thorpej /*
    893   1.1  thorpej  * Get an incoming message as initiator.
    894   1.1  thorpej  *
    895   1.1  thorpej  * The SCSI bus must already be in MESSAGE_IN_PHASE and there is a
    896   1.1  thorpej  * byte in the FIFO
    897   1.1  thorpej  */
    898   1.1  thorpej void
    899   1.1  thorpej ncr53c9x_msgin(sc)
    900   1.1  thorpej 	register struct ncr53c9x_softc *sc;
    901   1.1  thorpej {
    902   1.1  thorpej 	register int v;
    903   1.1  thorpej 
    904   1.1  thorpej 	NCR_TRACE(("[ncr53c9x_msgin(curmsglen:%ld)] ", (long)sc->sc_imlen));
    905   1.1  thorpej 
    906   1.1  thorpej 	if ((NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) == 0) {
    907   1.1  thorpej 		printf("%s: msgin: no msg byte available\n",
    908   1.1  thorpej 			sc->sc_dev.dv_xname);
    909   1.1  thorpej 		return;
    910   1.1  thorpej 	}
    911   1.1  thorpej 
    912   1.1  thorpej 	/*
    913   1.1  thorpej 	 * Prepare for a new message.  A message should (according
    914   1.1  thorpej 	 * to the SCSI standard) be transmitted in one single
    915   1.1  thorpej 	 * MESSAGE_IN_PHASE. If we have been in some other phase,
    916   1.1  thorpej 	 * then this is a new message.
    917   1.1  thorpej 	 */
    918   1.1  thorpej 	if (sc->sc_prevphase != MESSAGE_IN_PHASE) {
    919   1.1  thorpej 		sc->sc_flags &= ~NCR_DROP_MSGI;
    920   1.1  thorpej 		sc->sc_imlen = 0;
    921   1.1  thorpej 	}
    922   1.1  thorpej 
    923   1.1  thorpej 	v = NCR_READ_REG(sc, NCR_FIFO);
    924   1.1  thorpej 	NCR_MISC(("<msgbyte:0x%02x>", v));
    925   1.1  thorpej 
    926   1.1  thorpej #if 0
    927   1.1  thorpej 	if (sc->sc_state == NCR_RESELECTED && sc->sc_imlen == 0) {
    928   1.1  thorpej 		/*
    929   1.1  thorpej 		 * Which target is reselecting us? (The ID bit really)
    930   1.1  thorpej 		 */
    931   1.1  thorpej 		sc->sc_selid = v;
    932   1.1  thorpej 		NCR_MISC(("selid=0x%2x ", sc->sc_selid));
    933   1.1  thorpej 		return;
    934   1.1  thorpej 	}
    935   1.1  thorpej #endif
    936   1.1  thorpej 
    937   1.1  thorpej 	sc->sc_imess[sc->sc_imlen] = v;
    938   1.1  thorpej 
    939   1.1  thorpej 	/*
    940   1.1  thorpej 	 * If we're going to reject the message, don't bother storing
    941   1.1  thorpej 	 * the incoming bytes.  But still, we need to ACK them.
    942   1.1  thorpej 	 */
    943   1.1  thorpej 
    944   1.1  thorpej 	if ((sc->sc_flags & NCR_DROP_MSGI)) {
    945   1.1  thorpej 		NCRCMD(sc, NCRCMD_MSGOK);
    946   1.1  thorpej 		printf("<dropping msg byte %x>",
    947   1.1  thorpej 			sc->sc_imess[sc->sc_imlen]);
    948   1.1  thorpej 		return;
    949   1.1  thorpej 	}
    950   1.1  thorpej 
    951   1.1  thorpej 	if (sc->sc_imlen >= NCR_MAX_MSG_LEN) {
    952   1.1  thorpej 		ncr53c9x_sched_msgout(SEND_REJECT);
    953   1.1  thorpej 		sc->sc_flags |= NCR_DROP_MSGI;
    954   1.1  thorpej 	} else {
    955   1.1  thorpej 		sc->sc_imlen++;
    956   1.1  thorpej 		/*
    957   1.1  thorpej 		 * This testing is suboptimal, but most
    958   1.1  thorpej 		 * messages will be of the one byte variety, so
    959   1.1  thorpej 		 * it should not effect performance
    960   1.1  thorpej 		 * significantly.
    961   1.1  thorpej 		 */
    962   1.1  thorpej 		if (sc->sc_imlen == 1 && IS1BYTEMSG(sc->sc_imess[0]))
    963   1.1  thorpej 			goto gotit;
    964   1.1  thorpej 		if (sc->sc_imlen == 2 && IS2BYTEMSG(sc->sc_imess[0]))
    965   1.1  thorpej 			goto gotit;
    966   1.1  thorpej 		if (sc->sc_imlen >= 3 && ISEXTMSG(sc->sc_imess[0]) &&
    967   1.1  thorpej 		    sc->sc_imlen == sc->sc_imess[1] + 2)
    968   1.1  thorpej 			goto gotit;
    969   1.1  thorpej 	}
    970   1.1  thorpej 	/* Ack what we have so far */
    971   1.1  thorpej 	NCRCMD(sc, NCRCMD_MSGOK);
    972   1.1  thorpej 	return;
    973   1.1  thorpej 
    974   1.1  thorpej gotit:
    975   1.1  thorpej 	NCR_MSGS(("gotmsg(%x)", sc->sc_imess[0]));
    976   1.1  thorpej 	/*
    977   1.1  thorpej 	 * Now we should have a complete message (1 byte, 2 byte
    978   1.1  thorpej 	 * and moderately long extended messages).  We only handle
    979   1.1  thorpej 	 * extended messages which total length is shorter than
    980   1.1  thorpej 	 * NCR_MAX_MSG_LEN.  Longer messages will be amputated.
    981   1.1  thorpej 	 */
    982   1.1  thorpej 	switch (sc->sc_state) {
    983   1.1  thorpej 		struct ncr53c9x_ecb *ecb;
    984   1.1  thorpej 		struct ncr53c9x_tinfo *ti;
    985   1.1  thorpej 
    986   1.1  thorpej 	case NCR_CONNECTED:
    987   1.1  thorpej 		ecb = sc->sc_nexus;
    988  1.18   bouyer 		ti = &sc->sc_tinfo[ecb->xs->sc_link->scsipi_scsi.target];
    989   1.1  thorpej 
    990   1.1  thorpej 		switch (sc->sc_imess[0]) {
    991   1.1  thorpej 		case MSG_CMDCOMPLETE:
    992   1.1  thorpej 			NCR_MSGS(("cmdcomplete "));
    993   1.1  thorpej 			if (sc->sc_dleft < 0) {
    994  1.18   bouyer 				struct scsipi_link *sc_link = ecb->xs->sc_link;
    995   1.1  thorpej 				printf("%s: %ld extra bytes from %d:%d\n",
    996   1.1  thorpej 				    sc->sc_dev.dv_xname, -(long)sc->sc_dleft,
    997  1.18   bouyer 				    sc_link->scsipi_scsi.target, sc_link->scsipi_scsi.lun);
    998   1.1  thorpej 				sc->sc_dleft = 0;
    999   1.1  thorpej 			}
   1000  1.13       pk 			ecb->dleft = (ecb->flags & ECB_TENTATIVE_DONE)
   1001  1.13       pk 				? 0
   1002  1.13       pk 				: sc->sc_dleft;
   1003  1.13       pk 			if ((ecb->flags & ECB_SENSE) == 0)
   1004  1.13       pk 				ecb->xs->resid = ecb->dleft;
   1005   1.1  thorpej 			sc->sc_state = NCR_CMDCOMPLETE;
   1006   1.1  thorpej 			break;
   1007   1.1  thorpej 
   1008   1.1  thorpej 		case MSG_MESSAGE_REJECT:
   1009   1.1  thorpej 			if (ncr53c9x_debug & NCR_SHOWMSGS)
   1010   1.1  thorpej 				printf("%s: our msg rejected by target\n",
   1011   1.1  thorpej 				    sc->sc_dev.dv_xname);
   1012   1.1  thorpej 			switch (sc->sc_msgout) {
   1013   1.1  thorpej 			case SEND_SDTR:
   1014   1.1  thorpej 				sc->sc_flags &= ~NCR_SYNCHNEGO;
   1015   1.1  thorpej 				ti->flags &= ~(T_NEGOTIATE | T_SYNCMODE);
   1016   1.1  thorpej 				ncr53c9x_setsync(sc, ti);
   1017   1.1  thorpej 				break;
   1018   1.1  thorpej 			case SEND_INIT_DET_ERR:
   1019   1.1  thorpej 				goto abort;
   1020   1.1  thorpej 			}
   1021   1.1  thorpej 			break;
   1022   1.1  thorpej 
   1023   1.1  thorpej 		case MSG_NOOP:
   1024   1.1  thorpej 			NCR_MSGS(("noop "));
   1025   1.1  thorpej 			break;
   1026   1.1  thorpej 
   1027   1.1  thorpej 		case MSG_DISCONNECT:
   1028   1.1  thorpej 			NCR_MSGS(("disconnect "));
   1029   1.1  thorpej 			ti->dconns++;
   1030   1.1  thorpej 			sc->sc_state = NCR_DISCONNECT;
   1031   1.8       pk 
   1032  1.13       pk 			/*
   1033  1.13       pk 			 * Mark the fact that all bytes have moved. The
   1034  1.13       pk 			 * target may not bother to do a SAVE POINTERS
   1035  1.13       pk 			 * at this stage. This flag will set the residual
   1036  1.13       pk 			 * count to zero on MSG COMPLETE.
   1037  1.13       pk 			 */
   1038  1.13       pk 			if (sc->sc_dleft == 0)
   1039  1.13       pk 				ecb->flags |= ECB_TENTATIVE_DONE;
   1040  1.13       pk 
   1041  1.13       pk 			break;
   1042   1.1  thorpej 
   1043   1.1  thorpej 		case MSG_SAVEDATAPOINTER:
   1044   1.1  thorpej 			NCR_MSGS(("save datapointer "));
   1045   1.1  thorpej 			ecb->daddr = sc->sc_dp;
   1046   1.1  thorpej 			ecb->dleft = sc->sc_dleft;
   1047   1.1  thorpej 			break;
   1048   1.1  thorpej 
   1049   1.1  thorpej 		case MSG_RESTOREPOINTERS:
   1050   1.1  thorpej 			NCR_MSGS(("restore datapointer "));
   1051   1.1  thorpej 			sc->sc_dp = ecb->daddr;
   1052   1.1  thorpej 			sc->sc_dleft = ecb->dleft;
   1053   1.1  thorpej 			break;
   1054   1.1  thorpej 
   1055   1.1  thorpej 		case MSG_EXTENDED:
   1056   1.1  thorpej 			NCR_MSGS(("extended(%x) ", sc->sc_imess[2]));
   1057   1.1  thorpej 			switch (sc->sc_imess[2]) {
   1058   1.1  thorpej 			case MSG_EXT_SDTR:
   1059   1.1  thorpej 				NCR_MSGS(("SDTR period %d, offset %d ",
   1060   1.1  thorpej 					sc->sc_imess[3], sc->sc_imess[4]));
   1061   1.1  thorpej 				if (sc->sc_imess[1] != 3)
   1062   1.1  thorpej 					goto reject;
   1063   1.1  thorpej 				ti->period = sc->sc_imess[3];
   1064   1.1  thorpej 				ti->offset = sc->sc_imess[4];
   1065   1.1  thorpej 				ti->flags &= ~T_NEGOTIATE;
   1066   1.1  thorpej 				if (sc->sc_minsync == 0 ||
   1067   1.1  thorpej 				    ti->offset == 0 ||
   1068   1.1  thorpej 				    ti->period > 124) {
   1069   1.1  thorpej 					printf("%s:%d: async\n", "esp",
   1070  1.18   bouyer 						ecb->xs->sc_link->scsipi_scsi.target);
   1071   1.1  thorpej 					if ((sc->sc_flags&NCR_SYNCHNEGO)
   1072   1.1  thorpej 					    == 0) {
   1073   1.1  thorpej 						/*
   1074   1.1  thorpej 						 * target initiated negotiation
   1075   1.1  thorpej 						 */
   1076   1.1  thorpej 						ti->offset = 0;
   1077   1.1  thorpej 						ti->flags &= ~T_SYNCMODE;
   1078   1.1  thorpej 						ncr53c9x_sched_msgout(
   1079   1.1  thorpej 						    SEND_SDTR);
   1080   1.1  thorpej 					} else {
   1081   1.1  thorpej 						/* we are async */
   1082   1.1  thorpej 						ti->flags &= ~T_SYNCMODE;
   1083   1.1  thorpej 					}
   1084   1.1  thorpej 				} else {
   1085   1.1  thorpej 					int r = 250/ti->period;
   1086   1.1  thorpej 					int s = (100*250)/ti->period - 100*r;
   1087   1.1  thorpej 					int p;
   1088   1.1  thorpej 
   1089   1.1  thorpej 					p = ncr53c9x_stp2cpb(sc, ti->period);
   1090   1.1  thorpej 					ti->period = ncr53c9x_cpb2stp(sc, p);
   1091   1.1  thorpej #ifdef NCR53C9X_DEBUG
   1092  1.18   bouyer 					scsi_print_addr(ecb->xs->sc_link);
   1093  1.18   bouyer 					printf("max sync rate %d.%02dMb/s\n",
   1094   1.1  thorpej 						r, s);
   1095   1.1  thorpej #endif
   1096   1.1  thorpej 					if ((sc->sc_flags&NCR_SYNCHNEGO)
   1097   1.1  thorpej 					    == 0) {
   1098   1.1  thorpej 						/*
   1099   1.1  thorpej 						 * target initiated negotiation
   1100   1.1  thorpej 						 */
   1101   1.1  thorpej 						if (ti->period <
   1102   1.1  thorpej 						    sc->sc_minsync)
   1103   1.1  thorpej 							ti->period =
   1104   1.1  thorpej 							    sc->sc_minsync;
   1105   1.1  thorpej 						if (ti->offset > 15)
   1106   1.1  thorpej 							ti->offset = 15;
   1107   1.1  thorpej 						ti->flags &= ~T_SYNCMODE;
   1108   1.1  thorpej 						ncr53c9x_sched_msgout(
   1109   1.1  thorpej 						    SEND_SDTR);
   1110   1.1  thorpej 					} else {
   1111   1.1  thorpej 						/* we are sync */
   1112   1.1  thorpej 						ti->flags |= T_SYNCMODE;
   1113   1.1  thorpej 					}
   1114   1.1  thorpej 				}
   1115   1.1  thorpej 				sc->sc_flags &= ~NCR_SYNCHNEGO;
   1116   1.1  thorpej 				ncr53c9x_setsync(sc, ti);
   1117   1.1  thorpej 				break;
   1118   1.1  thorpej 
   1119   1.1  thorpej 			default:
   1120   1.1  thorpej 				printf("%s: unrecognized MESSAGE EXTENDED;"
   1121   1.1  thorpej 				    " sending REJECT\n", sc->sc_dev.dv_xname);
   1122   1.1  thorpej 				goto reject;
   1123   1.1  thorpej 			}
   1124   1.1  thorpej 			break;
   1125   1.1  thorpej 
   1126   1.1  thorpej 		default:
   1127   1.1  thorpej 			NCR_MSGS(("ident "));
   1128   1.1  thorpej 			printf("%s: unrecognized MESSAGE; sending REJECT\n",
   1129   1.1  thorpej 			    sc->sc_dev.dv_xname);
   1130   1.1  thorpej 		reject:
   1131   1.1  thorpej 			ncr53c9x_sched_msgout(SEND_REJECT);
   1132   1.1  thorpej 			break;
   1133   1.1  thorpej 		}
   1134   1.1  thorpej 		break;
   1135   1.1  thorpej 
   1136   1.1  thorpej 	case NCR_RESELECTED:
   1137   1.1  thorpej 		if (!MSG_ISIDENTIFY(sc->sc_imess[0])) {
   1138   1.1  thorpej 			printf("%s: reselect without IDENTIFY;"
   1139   1.1  thorpej 			    " sending DEVICE RESET\n", sc->sc_dev.dv_xname);
   1140   1.1  thorpej 			goto reset;
   1141   1.1  thorpej 		}
   1142   1.1  thorpej 
   1143   1.1  thorpej 		(void) ncr53c9x_reselect(sc, sc->sc_imess[0]);
   1144   1.1  thorpej 		break;
   1145   1.1  thorpej 
   1146   1.1  thorpej 	default:
   1147   1.1  thorpej 		printf("%s: unexpected MESSAGE IN; sending DEVICE RESET\n",
   1148   1.1  thorpej 		    sc->sc_dev.dv_xname);
   1149   1.1  thorpej 	reset:
   1150   1.1  thorpej 		ncr53c9x_sched_msgout(SEND_DEV_RESET);
   1151   1.1  thorpej 		break;
   1152   1.1  thorpej 
   1153   1.1  thorpej 	abort:
   1154   1.1  thorpej 		ncr53c9x_sched_msgout(SEND_ABORT);
   1155   1.1  thorpej 		break;
   1156   1.1  thorpej 	}
   1157   1.1  thorpej 
   1158   1.1  thorpej 	/* Ack last message byte */
   1159   1.1  thorpej 	NCRCMD(sc, NCRCMD_MSGOK);
   1160   1.1  thorpej 
   1161   1.1  thorpej 	/* Done, reset message pointer. */
   1162   1.1  thorpej 	sc->sc_flags &= ~NCR_DROP_MSGI;
   1163   1.1  thorpej 	sc->sc_imlen = 0;
   1164   1.1  thorpej }
   1165   1.1  thorpej 
   1166   1.1  thorpej 
   1167   1.1  thorpej /*
   1168   1.1  thorpej  * Send the highest priority, scheduled message
   1169   1.1  thorpej  */
   1170   1.1  thorpej void
   1171   1.1  thorpej ncr53c9x_msgout(sc)
   1172   1.1  thorpej 	register struct ncr53c9x_softc *sc;
   1173   1.1  thorpej {
   1174   1.1  thorpej 	struct ncr53c9x_tinfo *ti;
   1175   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
   1176   1.1  thorpej 	size_t size;
   1177   1.1  thorpej 
   1178   1.1  thorpej 	NCR_TRACE(("[ncr53c9x_msgout(priq:%x, prevphase:%x)]",
   1179   1.1  thorpej 	    sc->sc_msgpriq, sc->sc_prevphase));
   1180   1.1  thorpej 
   1181   1.1  thorpej 	if (sc->sc_flags & NCR_ATN) {
   1182   1.1  thorpej 		if (sc->sc_prevphase != MESSAGE_OUT_PHASE) {
   1183   1.1  thorpej 		new:
   1184   1.1  thorpej 			NCRCMD(sc, NCRCMD_FLUSH);
   1185   1.1  thorpej 			DELAY(1);
   1186   1.1  thorpej 			sc->sc_msgoutq = 0;
   1187   1.1  thorpej 			sc->sc_omlen = 0;
   1188   1.1  thorpej 		}
   1189   1.1  thorpej 	} else {
   1190   1.1  thorpej 		if (sc->sc_prevphase == MESSAGE_OUT_PHASE) {
   1191   1.1  thorpej 			ncr53c9x_sched_msgout(sc->sc_msgoutq);
   1192   1.1  thorpej 			goto new;
   1193   1.1  thorpej 		} else {
   1194   1.1  thorpej 			printf("%s at line %d: unexpected MESSAGE OUT phase\n",
   1195   1.1  thorpej 			    sc->sc_dev.dv_xname, __LINE__);
   1196   1.1  thorpej 		}
   1197   1.1  thorpej 	}
   1198   1.1  thorpej 
   1199   1.1  thorpej 	if (sc->sc_omlen == 0) {
   1200   1.1  thorpej 		/* Pick up highest priority message */
   1201   1.1  thorpej 		sc->sc_msgout = sc->sc_msgpriq & -sc->sc_msgpriq;
   1202   1.1  thorpej 		sc->sc_msgoutq |= sc->sc_msgout;
   1203   1.1  thorpej 		sc->sc_msgpriq &= ~sc->sc_msgout;
   1204   1.1  thorpej 		sc->sc_omlen = 1;		/* "Default" message len */
   1205   1.1  thorpej 		switch (sc->sc_msgout) {
   1206   1.1  thorpej 		case SEND_SDTR:
   1207   1.1  thorpej 			ecb = sc->sc_nexus;
   1208  1.18   bouyer 			ti = &sc->sc_tinfo[ecb->xs->sc_link->scsipi_scsi.target];
   1209   1.1  thorpej 			sc->sc_omess[0] = MSG_EXTENDED;
   1210   1.1  thorpej 			sc->sc_omess[1] = 3;
   1211   1.1  thorpej 			sc->sc_omess[2] = MSG_EXT_SDTR;
   1212   1.1  thorpej 			sc->sc_omess[3] = ti->period;
   1213   1.1  thorpej 			sc->sc_omess[4] = ti->offset;
   1214   1.1  thorpej 			sc->sc_omlen = 5;
   1215   1.1  thorpej 			if ((sc->sc_flags & NCR_SYNCHNEGO) == 0) {
   1216   1.1  thorpej 				ti->flags |= T_SYNCMODE;
   1217   1.1  thorpej 				ncr53c9x_setsync(sc, ti);
   1218   1.1  thorpej 			}
   1219   1.1  thorpej 			break;
   1220   1.1  thorpej 		case SEND_IDENTIFY:
   1221   1.1  thorpej 			if (sc->sc_state != NCR_CONNECTED) {
   1222   1.1  thorpej 				printf("%s at line %d: no nexus\n",
   1223   1.1  thorpej 				    sc->sc_dev.dv_xname, __LINE__);
   1224   1.1  thorpej 			}
   1225   1.1  thorpej 			ecb = sc->sc_nexus;
   1226   1.1  thorpej 			sc->sc_omess[0] =
   1227  1.18   bouyer 			    MSG_IDENTIFY(ecb->xs->sc_link->scsipi_scsi.lun, 0);
   1228   1.1  thorpej 			break;
   1229   1.1  thorpej 		case SEND_DEV_RESET:
   1230   1.1  thorpej 			sc->sc_flags |= NCR_ABORTING;
   1231   1.1  thorpej 			sc->sc_omess[0] = MSG_BUS_DEV_RESET;
   1232   1.1  thorpej 			ecb = sc->sc_nexus;
   1233  1.18   bouyer 			ti = &sc->sc_tinfo[ecb->xs->sc_link->scsipi_scsi.target];
   1234   1.1  thorpej 			ti->flags &= ~T_SYNCMODE;
   1235   1.1  thorpej 			ti->flags |= T_NEGOTIATE;
   1236   1.1  thorpej 			break;
   1237   1.1  thorpej 		case SEND_PARITY_ERROR:
   1238   1.1  thorpej 			sc->sc_omess[0] = MSG_PARITY_ERROR;
   1239   1.1  thorpej 			break;
   1240   1.1  thorpej 		case SEND_ABORT:
   1241   1.1  thorpej 			sc->sc_flags |= NCR_ABORTING;
   1242   1.1  thorpej 			sc->sc_omess[0] = MSG_ABORT;
   1243   1.1  thorpej 			break;
   1244   1.1  thorpej 		case SEND_INIT_DET_ERR:
   1245   1.1  thorpej 			sc->sc_omess[0] = MSG_INITIATOR_DET_ERR;
   1246   1.1  thorpej 			break;
   1247   1.1  thorpej 		case SEND_REJECT:
   1248   1.1  thorpej 			sc->sc_omess[0] = MSG_MESSAGE_REJECT;
   1249   1.1  thorpej 			break;
   1250   1.1  thorpej 		default:
   1251   1.1  thorpej 			NCRCMD(sc, NCRCMD_RSTATN);
   1252   1.1  thorpej 			sc->sc_flags &= ~NCR_ATN;
   1253   1.1  thorpej 			sc->sc_omess[0] = MSG_NOOP;
   1254   1.1  thorpej 			break;
   1255   1.1  thorpej 		}
   1256   1.1  thorpej 		sc->sc_omp = sc->sc_omess;
   1257   1.1  thorpej 	}
   1258   1.1  thorpej 
   1259   1.1  thorpej #if 1
   1260   1.1  thorpej 	/* (re)send the message */
   1261   1.1  thorpej 	size = min(sc->sc_omlen, sc->sc_maxxfer);
   1262   1.1  thorpej 	NCRDMA_SETUP(sc, &sc->sc_omp, &sc->sc_omlen, 0, &size);
   1263   1.1  thorpej 	/* Program the SCSI counter */
   1264   1.1  thorpej 	NCR_WRITE_REG(sc, NCR_TCL, size);
   1265   1.1  thorpej 	NCR_WRITE_REG(sc, NCR_TCM, size >> 8);
   1266   1.1  thorpej 	if (sc->sc_cfg2 & NCRCFG2_FE) {
   1267   1.1  thorpej 		NCR_WRITE_REG(sc, NCR_TCH, size >> 16);
   1268   1.1  thorpej 	}
   1269   1.1  thorpej 	/* load the count in */
   1270   1.1  thorpej 	NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
   1271   1.1  thorpej 	NCRCMD(sc, NCRCMD_TRANS|NCRCMD_DMA);
   1272   1.1  thorpej 	NCRDMA_GO(sc);
   1273   1.1  thorpej #else
   1274   1.1  thorpej 	{	int i;
   1275   1.1  thorpej 		for (i = 0; i < sc->sc_omlen; i++)
   1276   1.1  thorpej 			NCR_WRITE_REG(sc, FIFO, sc->sc_omess[i]);
   1277   1.1  thorpej 		NCRCMD(sc, NCRCMD_TRANS);
   1278   1.1  thorpej 		sc->sc_omlen = 0;
   1279   1.1  thorpej 	}
   1280   1.1  thorpej #endif
   1281   1.1  thorpej }
   1282   1.1  thorpej 
   1283   1.1  thorpej /*
   1284   1.1  thorpej  * This is the most critical part of the driver, and has to know
   1285   1.1  thorpej  * how to deal with *all* error conditions and phases from the SCSI
   1286   1.1  thorpej  * bus. If there are no errors and the DMA was active, then call the
   1287   1.1  thorpej  * DMA pseudo-interrupt handler. If this returns 1, then that was it
   1288   1.1  thorpej  * and we can return from here without further processing.
   1289   1.1  thorpej  *
   1290   1.1  thorpej  * Most of this needs verifying.
   1291   1.1  thorpej  */
   1292   1.1  thorpej int
   1293   1.1  thorpej ncr53c9x_intr(sc)
   1294   1.1  thorpej 	register struct ncr53c9x_softc *sc;
   1295   1.1  thorpej {
   1296   1.1  thorpej 	register struct ncr53c9x_ecb *ecb;
   1297  1.18   bouyer 	register struct scsipi_link *sc_link;
   1298   1.1  thorpej 	struct ncr53c9x_tinfo *ti;
   1299   1.1  thorpej 	int loop;
   1300   1.1  thorpej 	size_t size;
   1301   1.5       pk 	int nfifo;
   1302   1.1  thorpej 
   1303  1.10       pk 	NCR_TRACE(("[ncr53c9x_intr] "));
   1304   1.1  thorpej 
   1305   1.1  thorpej 	/*
   1306   1.1  thorpej 	 * I have made some (maybe seriously flawed) assumptions here,
   1307   1.1  thorpej 	 * but basic testing (uncomment the printf() below), show that
   1308   1.1  thorpej 	 * certainly something happens when this loop is here.
   1309   1.1  thorpej 	 *
   1310   1.1  thorpej 	 * The idea is that many of the SCSI operations take very little
   1311   1.1  thorpej 	 * time, and going away and getting interrupted is too high an
   1312   1.1  thorpej 	 * overhead to pay. For example, selecting, sending a message
   1313   1.1  thorpej 	 * and command and then doing some work can be done in one "pass".
   1314   1.1  thorpej 	 *
   1315   1.1  thorpej 	 * The DELAY is not variable because I do not understand that the
   1316   1.1  thorpej 	 * DELAY loop should be fixed-time regardless of CPU speed, but
   1317   1.1  thorpej 	 * I am *assuming* that the faster SCSI processors get things done
   1318   1.1  thorpej 	 * quicker (sending a command byte etc), and so there is no
   1319   1.1  thorpej 	 * need to be too slow.
   1320   1.1  thorpej 	 *
   1321   1.1  thorpej 	 * This is a heuristic. It is 2 when at 20Mhz, 2 at 25Mhz and 1
   1322   1.1  thorpej 	 * at 40Mhz. This needs testing.
   1323   1.1  thorpej 	 */
   1324   1.1  thorpej 	for (loop = 0; 1;loop++, DELAY(50/sc->sc_freq)) {
   1325   1.1  thorpej 		/* a feeling of deja-vu */
   1326   1.1  thorpej 		if (!NCRDMA_ISINTR(sc))
   1327   1.1  thorpej 			return (loop != 0);
   1328   1.1  thorpej #if 0
   1329   1.1  thorpej 		if (loop)
   1330   1.1  thorpej 			printf("*");
   1331   1.1  thorpej #endif
   1332   1.1  thorpej 
   1333   1.1  thorpej 		/* and what do the registers say... */
   1334   1.1  thorpej 		ncr53c9x_readregs(sc);
   1335   1.1  thorpej 
   1336   1.1  thorpej 		sc->sc_intrcnt.ev_count++;
   1337   1.1  thorpej 
   1338   1.1  thorpej 		/*
   1339   1.1  thorpej 		 * At the moment, only a SCSI Bus Reset or Illegal
   1340   1.1  thorpej 		 * Command are classed as errors. A disconnect is a
   1341   1.1  thorpej 		 * valid condition, and we let the code check is the
   1342   1.1  thorpej 		 * "NCR_BUSFREE_OK" flag was set before declaring it
   1343   1.1  thorpej 		 * and error.
   1344   1.1  thorpej 		 *
   1345   1.1  thorpej 		 * Also, the status register tells us about "Gross
   1346   1.1  thorpej 		 * Errors" and "Parity errors". Only the Gross Error
   1347   1.1  thorpej 		 * is really bad, and the parity errors are dealt
   1348   1.1  thorpej 		 * with later
   1349   1.1  thorpej 		 *
   1350   1.1  thorpej 		 * TODO
   1351   1.1  thorpej 		 *	If there are too many parity error, go to slow
   1352   1.1  thorpej 		 *	cable mode ?
   1353   1.1  thorpej 		 */
   1354   1.1  thorpej 
   1355   1.1  thorpej 		/* SCSI Reset */
   1356   1.1  thorpej 		if (sc->sc_espintr & NCRINTR_SBR) {
   1357   1.1  thorpej 			if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
   1358   1.1  thorpej 				NCRCMD(sc, NCRCMD_FLUSH);
   1359   1.1  thorpej 				DELAY(1);
   1360   1.1  thorpej 			}
   1361   1.1  thorpej 			if (sc->sc_state != NCR_SBR) {
   1362   1.1  thorpej 				printf("%s: SCSI bus reset\n",
   1363   1.1  thorpej 					sc->sc_dev.dv_xname);
   1364   1.1  thorpej 				ncr53c9x_init(sc, 0); /* Restart everything */
   1365   1.1  thorpej 				return 1;
   1366   1.1  thorpej 			}
   1367   1.1  thorpej #if 0
   1368   1.1  thorpej 	/*XXX*/		printf("<expected bus reset: "
   1369   1.1  thorpej 				"[intr %x, stat %x, step %d]>\n",
   1370   1.1  thorpej 				sc->sc_espintr, sc->sc_espstat,
   1371   1.1  thorpej 				sc->sc_espstep);
   1372   1.1  thorpej #endif
   1373   1.1  thorpej 			if (sc->sc_nexus)
   1374   1.1  thorpej 				panic("%s: nexus in reset state",
   1375   1.1  thorpej 				      sc->sc_dev.dv_xname);
   1376   1.1  thorpej 			goto sched;
   1377   1.1  thorpej 		}
   1378   1.1  thorpej 
   1379   1.1  thorpej 		ecb = sc->sc_nexus;
   1380   1.1  thorpej 
   1381   1.1  thorpej #define NCRINTR_ERR (NCRINTR_SBR|NCRINTR_ILL)
   1382   1.1  thorpej 		if (sc->sc_espintr & NCRINTR_ERR ||
   1383   1.1  thorpej 		    sc->sc_espstat & NCRSTAT_GE) {
   1384   1.1  thorpej 
   1385   1.1  thorpej 			if (sc->sc_espstat & NCRSTAT_GE) {
   1386   1.1  thorpej 				/* no target ? */
   1387   1.1  thorpej 				if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
   1388   1.1  thorpej 					NCRCMD(sc, NCRCMD_FLUSH);
   1389   1.1  thorpej 					DELAY(1);
   1390   1.1  thorpej 				}
   1391   1.1  thorpej 				if (sc->sc_state == NCR_CONNECTED ||
   1392   1.1  thorpej 				    sc->sc_state == NCR_SELECTING) {
   1393  1.16       pk 					ecb->xs->error = XS_TIMEOUT;
   1394   1.1  thorpej 					ncr53c9x_done(sc, ecb);
   1395   1.1  thorpej 				}
   1396   1.1  thorpej 				return 1;
   1397   1.1  thorpej 			}
   1398   1.1  thorpej 
   1399   1.1  thorpej 			if (sc->sc_espintr & NCRINTR_ILL) {
   1400   1.8       pk 				if (sc->sc_flags & NCR_EXPECT_ILLCMD) {
   1401   1.8       pk printf("%s: ILL: ESP100 work-around activated\n", sc->sc_dev.dv_xname);
   1402   1.8       pk 					sc->sc_flags &= ~NCR_EXPECT_ILLCMD;
   1403   1.8       pk 					continue;
   1404   1.8       pk 				}
   1405   1.1  thorpej 				/* illegal command, out of sync ? */
   1406   1.1  thorpej 				printf("%s: illegal command: 0x%x "
   1407   1.1  thorpej 				    "(state %d, phase %x, prevphase %x)\n",
   1408   1.1  thorpej 					sc->sc_dev.dv_xname, sc->sc_lastcmd,
   1409   1.1  thorpej 					sc->sc_state, sc->sc_phase,
   1410   1.1  thorpej 					sc->sc_prevphase);
   1411   1.1  thorpej 				if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
   1412   1.1  thorpej 					NCRCMD(sc, NCRCMD_FLUSH);
   1413   1.1  thorpej 					DELAY(1);
   1414   1.1  thorpej 				}
   1415   1.8       pk 				ncr53c9x_init(sc, 1); /* Restart everything */
   1416   1.1  thorpej 				return 1;
   1417   1.1  thorpej 			}
   1418   1.1  thorpej 		}
   1419   1.8       pk 		sc->sc_flags &= ~NCR_EXPECT_ILLCMD;
   1420   1.1  thorpej 
   1421   1.1  thorpej 		/*
   1422   1.1  thorpej 		 * Call if DMA is active.
   1423   1.1  thorpej 		 *
   1424   1.1  thorpej 		 * If DMA_INTR returns true, then maybe go 'round the loop
   1425   1.1  thorpej 		 * again in case there is no more DMA queued, but a phase
   1426   1.1  thorpej 		 * change is expected.
   1427   1.1  thorpej 		 */
   1428   1.1  thorpej 		if (NCRDMA_ISACTIVE(sc)) {
   1429   1.1  thorpej 			int r = NCRDMA_INTR(sc);
   1430   1.1  thorpej 			if (r == -1) {
   1431   1.1  thorpej 				printf("%s: DMA error; resetting\n",
   1432   1.1  thorpej 					sc->sc_dev.dv_xname);
   1433   1.1  thorpej 				ncr53c9x_init(sc, 1);
   1434   1.1  thorpej 			}
   1435   1.1  thorpej 			/* If DMA active here, then go back to work... */
   1436   1.1  thorpej 			if (NCRDMA_ISACTIVE(sc))
   1437   1.1  thorpej 				return 1;
   1438   1.1  thorpej 
   1439  1.11  thorpej 			/*
   1440  1.11  thorpej 			 * Note that this can happen during normal operation
   1441  1.11  thorpej 			 * if we are reselected while using DMA to select
   1442  1.11  thorpej 			 * a target.  If this is the case, don't issue the
   1443  1.11  thorpej 			 * warning.
   1444  1.11  thorpej 			 */
   1445   1.1  thorpej 			if (sc->sc_dleft == 0 &&
   1446  1.11  thorpej 			    (sc->sc_espstat & NCRSTAT_TC) == 0 &&
   1447  1.14       pk 			    sc->sc_state != NCR_SELECTING)
   1448   1.1  thorpej 				printf("%s: !TC [intr %x, stat %x, step %d]"
   1449   1.1  thorpej 				       " prevphase %x, resid %x\n",
   1450   1.1  thorpej 					sc->sc_dev.dv_xname,
   1451   1.1  thorpej 					sc->sc_espintr,
   1452   1.1  thorpej 					sc->sc_espstat,
   1453   1.1  thorpej 					sc->sc_espstep,
   1454   1.1  thorpej 					sc->sc_prevphase,
   1455   1.1  thorpej 					ecb?ecb->dleft:-1);
   1456   1.1  thorpej 		}
   1457   1.1  thorpej 
   1458   1.1  thorpej #if 0	/* Unreliable on some NCR revisions? */
   1459   1.1  thorpej 		if ((sc->sc_espstat & NCRSTAT_INT) == 0) {
   1460   1.1  thorpej 			printf("%s: spurious interrupt\n",
   1461   1.1  thorpej 			    sc->sc_dev.dv_xname);
   1462   1.1  thorpej 			return 1;
   1463   1.1  thorpej 		}
   1464   1.1  thorpej #endif
   1465   1.1  thorpej 
   1466   1.1  thorpej 		/*
   1467   1.1  thorpej 		 * check for less serious errors
   1468   1.1  thorpej 		 */
   1469   1.1  thorpej 		if (sc->sc_espstat & NCRSTAT_PE) {
   1470   1.1  thorpej 			printf("%s: SCSI bus parity error\n",
   1471   1.1  thorpej 				sc->sc_dev.dv_xname);
   1472   1.1  thorpej 			if (sc->sc_prevphase == MESSAGE_IN_PHASE)
   1473   1.1  thorpej 				ncr53c9x_sched_msgout(SEND_PARITY_ERROR);
   1474   1.1  thorpej 			else
   1475   1.1  thorpej 				ncr53c9x_sched_msgout(SEND_INIT_DET_ERR);
   1476   1.1  thorpej 		}
   1477   1.1  thorpej 
   1478   1.1  thorpej 		if (sc->sc_espintr & NCRINTR_DIS) {
   1479   1.1  thorpej 			NCR_MISC(("<DISC [intr %x, stat %x, step %d]>",
   1480   1.1  thorpej 				sc->sc_espintr,sc->sc_espstat,sc->sc_espstep));
   1481   1.1  thorpej 			if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
   1482   1.1  thorpej 				NCRCMD(sc, NCRCMD_FLUSH);
   1483   1.1  thorpej 				DELAY(1);
   1484   1.1  thorpej 			}
   1485   1.1  thorpej 			/*
   1486   1.1  thorpej 			 * This command must (apparently) be issued within
   1487   1.1  thorpej 			 * 250mS of a disconnect. So here you are...
   1488   1.1  thorpej 			 */
   1489   1.1  thorpej 			NCRCMD(sc, NCRCMD_ENSEL);
   1490   1.1  thorpej 			switch (sc->sc_state) {
   1491   1.1  thorpej 			case NCR_RESELECTED:
   1492   1.1  thorpej 				goto sched;
   1493   1.1  thorpej 
   1494   1.1  thorpej 			case NCR_SELECTING:
   1495   1.1  thorpej 				ecb->xs->error = XS_SELTIMEOUT;
   1496   1.1  thorpej 				goto finish;
   1497   1.1  thorpej 
   1498   1.1  thorpej 			case NCR_CONNECTED:
   1499   1.1  thorpej 				if ((sc->sc_flags & NCR_SYNCHNEGO)) {
   1500   1.1  thorpej #ifdef NCR53C9X_DEBUG
   1501   1.1  thorpej 					if (ecb)
   1502  1.18   bouyer 						scsi_print_addr(ecb->xs->sc_link);
   1503   1.1  thorpej 					printf("sync nego not completed!\n");
   1504   1.1  thorpej #endif
   1505  1.18   bouyer 					ti = &sc->sc_tinfo[ecb->xs->sc_link->scsipi_scsi.target];
   1506   1.1  thorpej 					sc->sc_flags &= ~NCR_SYNCHNEGO;
   1507   1.1  thorpej 					ti->flags &=
   1508   1.1  thorpej 					    ~(T_NEGOTIATE | T_SYNCMODE);
   1509   1.1  thorpej 				}
   1510   1.1  thorpej 
   1511   1.1  thorpej 				/* it may be OK to disconnect */
   1512   1.1  thorpej 				if ((sc->sc_flags & NCR_ABORTING) == 0) {
   1513   1.1  thorpej 					/*
   1514   1.1  thorpej 					 * Section 5.1.1 of the SCSI 2 spec
   1515   1.1  thorpej 					 * suggests issuing a REQUEST SENSE
   1516   1.1  thorpej 					 * following an unexpected disconnect.
   1517   1.1  thorpej 					 * Some devices go into a contingent
   1518   1.1  thorpej 					 * allegiance condition when
   1519   1.1  thorpej 					 * disconnecting, and this is necessary
   1520   1.1  thorpej 					 * to clean up their state.
   1521   1.1  thorpej 					 */
   1522   1.1  thorpej 					printf("%s: unexpected disconnect; ",
   1523   1.1  thorpej 					    sc->sc_dev.dv_xname);
   1524   1.1  thorpej 					if (ecb->flags & ECB_SENSE) {
   1525   1.1  thorpej 						printf("resetting\n");
   1526   1.1  thorpej 						goto reset;
   1527   1.1  thorpej 					}
   1528   1.1  thorpej 					printf("sending REQUEST SENSE\n");
   1529   1.7      gwr 					untimeout(ncr53c9x_timeout, ecb);
   1530   1.1  thorpej 					ncr53c9x_sense(sc, ecb);
   1531   1.1  thorpej 					goto out;
   1532   1.1  thorpej 				}
   1533   1.1  thorpej 
   1534  1.16       pk 				ecb->xs->error = XS_TIMEOUT;
   1535   1.1  thorpej 				goto finish;
   1536   1.1  thorpej 
   1537   1.1  thorpej 			case NCR_DISCONNECT:
   1538   1.1  thorpej 				TAILQ_INSERT_HEAD(&sc->nexus_list, ecb, chain);
   1539   1.1  thorpej 				sc->sc_nexus = NULL;
   1540   1.1  thorpej 				goto sched;
   1541   1.1  thorpej 
   1542   1.1  thorpej 			case NCR_CMDCOMPLETE:
   1543   1.1  thorpej 				goto finish;
   1544   1.1  thorpej 			}
   1545   1.1  thorpej 		}
   1546   1.1  thorpej 
   1547   1.1  thorpej 		switch (sc->sc_state) {
   1548   1.1  thorpej 
   1549   1.1  thorpej 		case NCR_SBR:
   1550   1.1  thorpej 			printf("%s: waiting for SCSI Bus Reset to happen\n",
   1551   1.1  thorpej 				sc->sc_dev.dv_xname);
   1552   1.1  thorpej 			return 1;
   1553   1.1  thorpej 
   1554   1.1  thorpej 		case NCR_RESELECTED:
   1555   1.1  thorpej 			/*
   1556   1.1  thorpej 			 * we must be continuing a message ?
   1557   1.1  thorpej 			 */
   1558   1.1  thorpej 			if (sc->sc_phase != MESSAGE_IN_PHASE) {
   1559   1.1  thorpej 				printf("%s: target didn't identify\n",
   1560   1.1  thorpej 					sc->sc_dev.dv_xname);
   1561   1.1  thorpej 				ncr53c9x_init(sc, 1);
   1562   1.1  thorpej 				return 1;
   1563   1.1  thorpej 			}
   1564   1.1  thorpej printf("<<RESELECT CONT'd>>");
   1565   1.1  thorpej #if XXXX
   1566   1.1  thorpej 			ncr53c9x_msgin(sc);
   1567   1.1  thorpej 			if (sc->sc_state != NCR_CONNECTED) {
   1568   1.1  thorpej 				/* IDENTIFY fail?! */
   1569   1.1  thorpej 				printf("%s: identify failed\n",
   1570   1.1  thorpej 					sc->sc_dev.dv_xname);
   1571   1.1  thorpej 				ncr53c9x_init(sc, 1);
   1572   1.1  thorpej 				return 1;
   1573   1.1  thorpej 			}
   1574   1.1  thorpej #endif
   1575   1.1  thorpej 			break;
   1576   1.1  thorpej 
   1577   1.1  thorpej 		case NCR_IDLE:
   1578   1.1  thorpej if (sc->sc_flags & NCR_ICCS) printf("[[esp: BUMMER]]");
   1579   1.1  thorpej 		case NCR_SELECTING:
   1580   1.1  thorpej 			sc->sc_msgpriq = sc->sc_msgout = sc->sc_msgoutq = 0;
   1581   1.1  thorpej 			sc->sc_flags = 0;
   1582   1.7      gwr 			ecb = sc->sc_nexus;
   1583   1.1  thorpej 
   1584   1.1  thorpej 			if (sc->sc_espintr & NCRINTR_RESEL) {
   1585   1.1  thorpej 				/*
   1586   1.1  thorpej 				 * If we're trying to select a
   1587   1.1  thorpej 				 * target ourselves, push our command
   1588   1.1  thorpej 				 * back into the ready list.
   1589   1.1  thorpej 				 */
   1590   1.1  thorpej 				if (sc->sc_state == NCR_SELECTING) {
   1591   1.1  thorpej 					NCR_MISC(("backoff selector "));
   1592   1.7      gwr 					untimeout(ncr53c9x_timeout, ecb);
   1593   1.7      gwr 					sc_link = ecb->xs->sc_link;
   1594  1.18   bouyer 					ti = &sc->sc_tinfo[sc_link->scsipi_scsi.target];
   1595   1.1  thorpej 					TAILQ_INSERT_HEAD(&sc->ready_list,
   1596   1.7      gwr 					    ecb, chain);
   1597   1.1  thorpej 					ecb = sc->sc_nexus = NULL;
   1598   1.1  thorpej 				}
   1599   1.1  thorpej 				sc->sc_state = NCR_RESELECTED;
   1600   1.1  thorpej 				if (sc->sc_phase != MESSAGE_IN_PHASE) {
   1601   1.1  thorpej 					/*
   1602   1.1  thorpej 					 * Things are seriously fucked up.
   1603   1.1  thorpej 					 * Pull the brakes, i.e. reset
   1604   1.1  thorpej 					 */
   1605   1.1  thorpej 					printf("%s: target didn't identify\n",
   1606   1.1  thorpej 						sc->sc_dev.dv_xname);
   1607   1.1  thorpej 					ncr53c9x_init(sc, 1);
   1608   1.1  thorpej 					return 1;
   1609   1.1  thorpej 				}
   1610   1.5       pk 				/*
   1611   1.5       pk 				 * The C90 only inhibits FIFO writes until
   1612   1.5       pk 				 * reselection is complete, instead of
   1613   1.5       pk 				 * waiting until the interrupt status register
   1614   1.5       pk 				 * has been read. So, if the reselect happens
   1615   1.5       pk 				 * while we were entering a command bytes (for
   1616   1.5       pk 				 * another target) some of those bytes can
   1617   1.5       pk 				 * appear in the FIFO here, after the
   1618   1.5       pk 				 * interrupt is taken.
   1619   1.5       pk 				 */
   1620   1.5       pk 				nfifo = NCR_READ_REG(sc,NCR_FFLAG) & NCRFIFO_FF;
   1621   1.5       pk 				if (nfifo < 2 ||
   1622   1.5       pk 				    (nfifo > 2 &&
   1623   1.5       pk 				     sc->sc_rev != NCR_VARIANT_ESP100)) {
   1624   1.1  thorpej 					printf("%s: RESELECT: "
   1625   1.8       pk 					    "%d bytes in FIFO! "
   1626   1.8       pk 					    "[intr %x, stat %x, step %d, prevphase %x]\n",
   1627   1.1  thorpej 						sc->sc_dev.dv_xname,
   1628   1.8       pk 						nfifo,
   1629   1.8       pk 						sc->sc_espintr,
   1630   1.8       pk 						sc->sc_espstat,
   1631   1.8       pk 						sc->sc_espstep,
   1632   1.8       pk 						sc->sc_prevphase);
   1633   1.1  thorpej 					ncr53c9x_init(sc, 1);
   1634   1.1  thorpej 					return 1;
   1635   1.1  thorpej 				}
   1636   1.1  thorpej 				sc->sc_selid = NCR_READ_REG(sc, NCR_FIFO);
   1637   1.1  thorpej 				NCR_MISC(("selid=0x%2x ", sc->sc_selid));
   1638   1.1  thorpej 
   1639   1.1  thorpej 				/* Handle identify message */
   1640   1.1  thorpej 				ncr53c9x_msgin(sc);
   1641   1.8       pk 				if (nfifo != 2) {
   1642   1.8       pk 					sc->sc_flags |= NCR_EXPECT_ILLCMD;
   1643   1.5       pk 					NCRCMD(sc, NCRCMD_FLUSH);
   1644   1.8       pk 				}
   1645   1.1  thorpej 
   1646   1.1  thorpej 				if (sc->sc_state != NCR_CONNECTED) {
   1647   1.1  thorpej 					/* IDENTIFY fail?! */
   1648   1.1  thorpej 					printf("%s: identify failed\n",
   1649   1.1  thorpej 						sc->sc_dev.dv_xname);
   1650   1.1  thorpej 					ncr53c9x_init(sc, 1);
   1651   1.1  thorpej 					return 1;
   1652   1.1  thorpej 				}
   1653   1.1  thorpej 				continue; /* ie. next phase expected soon */
   1654   1.1  thorpej 			}
   1655   1.1  thorpej 
   1656   1.1  thorpej #define	NCRINTR_DONE	(NCRINTR_FC|NCRINTR_BS)
   1657   1.1  thorpej 			if ((sc->sc_espintr & NCRINTR_DONE) == NCRINTR_DONE) {
   1658   1.1  thorpej 				ecb = sc->sc_nexus;
   1659   1.1  thorpej 				if (!ecb)
   1660   1.1  thorpej 					panic("esp: not nexus at sc->sc_nexus");
   1661   1.1  thorpej 
   1662   1.1  thorpej 				sc_link = ecb->xs->sc_link;
   1663  1.18   bouyer 				ti = &sc->sc_tinfo[sc_link->scsipi_scsi.target];
   1664   1.1  thorpej 
   1665   1.1  thorpej 				switch (sc->sc_espstep) {
   1666   1.1  thorpej 				case 0:
   1667   1.1  thorpej 					printf("%s: select timeout/no "
   1668   1.1  thorpej 					    "disconnect\n",
   1669   1.1  thorpej 					    sc->sc_dev.dv_xname);
   1670   1.1  thorpej 					ecb->xs->error = XS_SELTIMEOUT;
   1671   1.1  thorpej 					goto finish;
   1672   1.1  thorpej 				case 1:
   1673   1.1  thorpej 					if ((ti->flags & T_NEGOTIATE) == 0) {
   1674   1.1  thorpej 						printf("%s: step 1 & !NEG\n",
   1675   1.1  thorpej 							sc->sc_dev.dv_xname);
   1676   1.1  thorpej 						goto reset;
   1677   1.1  thorpej 					}
   1678   1.1  thorpej 					if (sc->sc_phase != MESSAGE_OUT_PHASE) {
   1679   1.1  thorpej 						printf("%s: !MSGOUT\n",
   1680   1.1  thorpej 							sc->sc_dev.dv_xname);
   1681   1.1  thorpej 						goto reset;
   1682   1.1  thorpej 					}
   1683   1.1  thorpej 					/* Start negotiating */
   1684   1.1  thorpej 					ti->period = sc->sc_minsync;
   1685   1.1  thorpej 					ti->offset = 15;
   1686   1.1  thorpej 					sc->sc_flags |= NCR_SYNCHNEGO;
   1687   1.1  thorpej 					ncr53c9x_sched_msgout(SEND_SDTR);
   1688   1.1  thorpej 					break;
   1689   1.1  thorpej 				case 3:
   1690   1.1  thorpej 					/*
   1691   1.1  thorpej 					 * Grr, this is supposed to mean
   1692   1.1  thorpej 					 * "target left command phase
   1693   1.1  thorpej 					 *  prematurely". It seems to happen
   1694   1.1  thorpej 					 * regularly when sync mode is on.
   1695   1.1  thorpej 					 * Look at FIFO to see if command
   1696   1.1  thorpej 					 * went out.
   1697   1.1  thorpej 					 * (Timing problems?)
   1698   1.1  thorpej 					 */
   1699   1.8       pk 					if (ncr53c9x_dmaselect) {
   1700   1.8       pk 					    if (sc->sc_cmdlen == 0)
   1701   1.8       pk 						/* Hope for the best.. */
   1702   1.8       pk 						break;
   1703   1.8       pk 					} else if ((NCR_READ_REG(sc, NCR_FFLAG)
   1704   1.1  thorpej 					    & NCRFIFO_FF) == 0) {
   1705   1.1  thorpej 						/* Hope for the best.. */
   1706   1.1  thorpej 						break;
   1707   1.1  thorpej 					}
   1708   1.1  thorpej 					printf("(%s:%d:%d): selection failed;"
   1709   1.1  thorpej 						" %d left in FIFO "
   1710   1.1  thorpej 						"[intr %x, stat %x, step %d]\n",
   1711   1.1  thorpej 						sc->sc_dev.dv_xname,
   1712  1.18   bouyer 						sc_link->scsipi_scsi.target,
   1713  1.18   bouyer 						sc_link->scsipi_scsi.lun,
   1714   1.1  thorpej 						NCR_READ_REG(sc, NCR_FFLAG)
   1715   1.1  thorpej 						 & NCRFIFO_FF,
   1716   1.1  thorpej 						sc->sc_espintr, sc->sc_espstat,
   1717   1.1  thorpej 						sc->sc_espstep);
   1718   1.1  thorpej 					NCRCMD(sc, NCRCMD_FLUSH);
   1719   1.1  thorpej 					ncr53c9x_sched_msgout(SEND_ABORT);
   1720   1.1  thorpej 					return 1;
   1721   1.1  thorpej 				case 2:
   1722   1.1  thorpej 					/* Select stuck at Command Phase */
   1723   1.1  thorpej 					NCRCMD(sc, NCRCMD_FLUSH);
   1724   1.1  thorpej 				case 4:
   1725   1.8       pk 					if (ncr53c9x_dmaselect &&
   1726   1.8       pk 					    sc->sc_cmdlen != 0)
   1727   1.8       pk 						printf("(%s:%d:%d): select; "
   1728   1.8       pk 						      "%d left in DMA buffer\n",
   1729   1.8       pk 							sc->sc_dev.dv_xname,
   1730  1.18   bouyer 							sc_link->scsipi_scsi.target,
   1731  1.18   bouyer 							sc_link->scsipi_scsi.lun,
   1732   1.8       pk 							sc->sc_cmdlen);
   1733   1.1  thorpej 					/* So far, everything went fine */
   1734   1.1  thorpej 					break;
   1735   1.1  thorpej 				}
   1736   1.1  thorpej #if 0
   1737   1.1  thorpej 				if (ecb->xs->flags & SCSI_RESET)
   1738   1.1  thorpej 					ncr53c9x_sched_msgout(SEND_DEV_RESET);
   1739   1.1  thorpej 				else if (ti->flags & T_NEGOTIATE)
   1740   1.1  thorpej 					ncr53c9x_sched_msgout(
   1741   1.1  thorpej 					    SEND_IDENTIFY | SEND_SDTR);
   1742   1.1  thorpej 				else
   1743   1.1  thorpej 					ncr53c9x_sched_msgout(SEND_IDENTIFY);
   1744   1.1  thorpej #endif
   1745   1.1  thorpej 
   1746   1.1  thorpej 				ecb->flags |= ECB_NEXUS;
   1747  1.18   bouyer 				ti->lubusy |= (1 << sc_link->scsipi_scsi.lun);
   1748   1.1  thorpej 
   1749   1.1  thorpej 				sc->sc_prevphase = INVALID_PHASE; /* ?? */
   1750   1.1  thorpej 				/* Do an implicit RESTORE POINTERS. */
   1751   1.1  thorpej 				sc->sc_dp = ecb->daddr;
   1752   1.1  thorpej 				sc->sc_dleft = ecb->dleft;
   1753   1.1  thorpej 				sc->sc_state = NCR_CONNECTED;
   1754   1.1  thorpej 				break;
   1755   1.1  thorpej 			} else {
   1756   1.1  thorpej 				printf("%s: unexpected status after select"
   1757   1.1  thorpej 					": [intr %x, stat %x, step %x]\n",
   1758   1.1  thorpej 					sc->sc_dev.dv_xname,
   1759   1.1  thorpej 					sc->sc_espintr, sc->sc_espstat,
   1760   1.1  thorpej 					sc->sc_espstep);
   1761   1.1  thorpej 				NCRCMD(sc, NCRCMD_FLUSH);
   1762   1.1  thorpej 				DELAY(1);
   1763   1.1  thorpej 				goto reset;
   1764   1.1  thorpej 			}
   1765   1.1  thorpej 			if (sc->sc_state == NCR_IDLE) {
   1766   1.1  thorpej 				printf("%s: stray interrupt\n",
   1767   1.1  thorpej 				    sc->sc_dev.dv_xname);
   1768   1.1  thorpej 					return 0;
   1769   1.1  thorpej 			}
   1770   1.1  thorpej 			break;
   1771   1.1  thorpej 
   1772   1.1  thorpej 		case NCR_CONNECTED:
   1773   1.1  thorpej 			if (sc->sc_flags & NCR_ICCS) {
   1774   1.1  thorpej 				u_char msg;
   1775   1.1  thorpej 
   1776   1.1  thorpej 				sc->sc_flags &= ~NCR_ICCS;
   1777   1.1  thorpej 
   1778   1.1  thorpej 				if (!(sc->sc_espintr & NCRINTR_DONE)) {
   1779   1.1  thorpej 					printf("%s: ICCS: "
   1780   1.1  thorpej 					      ": [intr %x, stat %x, step %x]\n",
   1781   1.1  thorpej 						sc->sc_dev.dv_xname,
   1782   1.1  thorpej 						sc->sc_espintr, sc->sc_espstat,
   1783   1.1  thorpej 						sc->sc_espstep);
   1784   1.1  thorpej 				}
   1785   1.1  thorpej 				if ((NCR_READ_REG(sc, NCR_FFLAG)
   1786   1.1  thorpej 				    & NCRFIFO_FF) != 2) {
   1787   1.1  thorpej 					int i = (NCR_READ_REG(sc, NCR_FFLAG)
   1788   1.1  thorpej 					    & NCRFIFO_FF) - 2;
   1789   1.1  thorpej 					while (i--)
   1790   1.1  thorpej 						(void) NCR_READ_REG(sc,
   1791  1.13       pk 								    NCR_FIFO);
   1792   1.1  thorpej 				}
   1793   1.1  thorpej 				ecb->stat = NCR_READ_REG(sc, NCR_FIFO);
   1794   1.1  thorpej 				msg = NCR_READ_REG(sc, NCR_FIFO);
   1795   1.1  thorpej 				NCR_PHASE(("<stat:(%x,%x)>", ecb->stat, msg));
   1796   1.1  thorpej 				if (msg == MSG_CMDCOMPLETE) {
   1797  1.13       pk 					ecb->dleft =
   1798  1.13       pk 					  (ecb->flags & ECB_TENTATIVE_DONE)
   1799  1.13       pk 						? 0
   1800  1.13       pk 						: sc->sc_dleft;
   1801  1.13       pk 					if ((ecb->flags & ECB_SENSE) == 0)
   1802  1.13       pk 						ecb->xs->resid = ecb->dleft;
   1803   1.1  thorpej 					sc->sc_state = NCR_CMDCOMPLETE;
   1804   1.1  thorpej 				} else
   1805   1.1  thorpej 					printf("%s: STATUS_PHASE: msg %d\n",
   1806   1.1  thorpej 						sc->sc_dev.dv_xname, msg);
   1807   1.1  thorpej 				NCRCMD(sc, NCRCMD_MSGOK);
   1808   1.1  thorpej 				continue; /* ie. wait for disconnect */
   1809   1.1  thorpej 			}
   1810   1.1  thorpej 			break;
   1811   1.1  thorpej 		default:
   1812   1.1  thorpej 			panic("%s: invalid state: %d",
   1813   1.1  thorpej 			      sc->sc_dev.dv_xname,
   1814   1.1  thorpej 			      sc->sc_state);
   1815   1.1  thorpej 		}
   1816   1.1  thorpej 
   1817   1.1  thorpej 		/*
   1818   1.1  thorpej 		 * Driver is now in state NCR_CONNECTED, i.e. we
   1819   1.1  thorpej 		 * have a current command working the SCSI bus.
   1820   1.1  thorpej 		 */
   1821   1.1  thorpej 		if (sc->sc_state != NCR_CONNECTED || ecb == NULL) {
   1822   1.1  thorpej 			panic("esp no nexus");
   1823   1.1  thorpej 		}
   1824   1.1  thorpej 
   1825   1.1  thorpej 		switch (sc->sc_phase) {
   1826   1.1  thorpej 		case MESSAGE_OUT_PHASE:
   1827   1.1  thorpej 			NCR_PHASE(("MESSAGE_OUT_PHASE "));
   1828   1.1  thorpej 			ncr53c9x_msgout(sc);
   1829   1.1  thorpej 			sc->sc_prevphase = MESSAGE_OUT_PHASE;
   1830   1.1  thorpej 			break;
   1831   1.1  thorpej 		case MESSAGE_IN_PHASE:
   1832   1.1  thorpej 			NCR_PHASE(("MESSAGE_IN_PHASE "));
   1833   1.1  thorpej 			if (sc->sc_espintr & NCRINTR_BS) {
   1834   1.1  thorpej 				NCRCMD(sc, NCRCMD_FLUSH);
   1835   1.1  thorpej 				sc->sc_flags |= NCR_WAITI;
   1836   1.1  thorpej 				NCRCMD(sc, NCRCMD_TRANS);
   1837   1.1  thorpej 			} else if (sc->sc_espintr & NCRINTR_FC) {
   1838   1.1  thorpej 				if ((sc->sc_flags & NCR_WAITI) == 0) {
   1839   1.1  thorpej 					printf("%s: MSGIN: unexpected FC bit: "
   1840   1.1  thorpej 						"[intr %x, stat %x, step %x]\n",
   1841   1.1  thorpej 					sc->sc_dev.dv_xname,
   1842   1.1  thorpej 					sc->sc_espintr, sc->sc_espstat,
   1843   1.1  thorpej 					sc->sc_espstep);
   1844   1.1  thorpej 				}
   1845   1.1  thorpej 				sc->sc_flags &= ~NCR_WAITI;
   1846   1.1  thorpej 				ncr53c9x_msgin(sc);
   1847   1.1  thorpej 			} else {
   1848   1.1  thorpej 				printf("%s: MSGIN: weird bits: "
   1849   1.1  thorpej 					"[intr %x, stat %x, step %x]\n",
   1850   1.1  thorpej 					sc->sc_dev.dv_xname,
   1851   1.1  thorpej 					sc->sc_espintr, sc->sc_espstat,
   1852   1.1  thorpej 					sc->sc_espstep);
   1853   1.1  thorpej 			}
   1854   1.1  thorpej 			sc->sc_prevphase = MESSAGE_IN_PHASE;
   1855   1.1  thorpej 			break;
   1856   1.8       pk 		case COMMAND_PHASE:
   1857   1.8       pk 			/*
   1858   1.8       pk 			 * Send the command block. Normally we don't see this
   1859   1.8       pk 			 * phase because the SEL_ATN command takes care of
   1860   1.8       pk 			 * all this. However, we end up here if either the
   1861   1.8       pk 			 * target or we wanted exchange some more messages
   1862   1.8       pk 			 * first (e.g. to start negotiations).
   1863   1.8       pk 			 */
   1864   1.1  thorpej 
   1865   1.1  thorpej 			NCR_PHASE(("COMMAND_PHASE 0x%02x (%d) ",
   1866   1.8       pk 				ecb->cmd.cmd.opcode, ecb->clen));
   1867   1.1  thorpej 			if (NCR_READ_REG(sc, NCR_FFLAG) & NCRFIFO_FF) {
   1868   1.1  thorpej 				NCRCMD(sc, NCRCMD_FLUSH);
   1869   1.1  thorpej 				DELAY(1);
   1870   1.1  thorpej 			}
   1871   1.8       pk 			if (ncr53c9x_dmaselect) {
   1872   1.8       pk 				size_t size;
   1873   1.8       pk 				/* setup DMA transfer for command */
   1874   1.8       pk 				size = ecb->clen;
   1875   1.8       pk 				sc->sc_cmdlen = size;
   1876   1.8       pk 				sc->sc_cmdp = (caddr_t)&ecb->cmd.cmd;
   1877   1.8       pk 				NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen,
   1878   1.8       pk 					     0, &size);
   1879   1.8       pk 				/* Program the SCSI counter */
   1880   1.8       pk 				NCR_WRITE_REG(sc, NCR_TCL, size);
   1881   1.8       pk 				NCR_WRITE_REG(sc, NCR_TCM, size >> 8);
   1882   1.8       pk 				if (sc->sc_cfg2 & NCRCFG2_FE) {
   1883   1.8       pk 					NCR_WRITE_REG(sc, NCR_TCH, size >> 16);
   1884   1.8       pk 				}
   1885   1.8       pk 
   1886   1.8       pk 				NCRCMD(sc, NCRCMD_TRANS | NCRCMD_DMA);
   1887   1.8       pk 				NCRDMA_GO(sc);
   1888   1.8       pk 			} else {
   1889   1.8       pk 				u_char *cmd = (u_char *)&ecb->cmd.cmd;
   1890   1.8       pk 				int i;
   1891   1.8       pk 				/* Now the command into the FIFO */
   1892   1.8       pk 				for (i = 0; i < ecb->clen; i++)
   1893   1.8       pk 					NCR_WRITE_REG(sc, NCR_FIFO, *cmd++);
   1894   1.8       pk 				NCRCMD(sc, NCRCMD_TRANS);
   1895   1.8       pk 			}
   1896   1.1  thorpej 			sc->sc_prevphase = COMMAND_PHASE;
   1897   1.1  thorpej 			break;
   1898   1.1  thorpej 		case DATA_OUT_PHASE:
   1899   1.1  thorpej 			NCR_PHASE(("DATA_OUT_PHASE [%ld] ",(long)sc->sc_dleft));
   1900   1.1  thorpej 			NCRCMD(sc, NCRCMD_FLUSH);
   1901   1.1  thorpej 			size = min(sc->sc_dleft, sc->sc_maxxfer);
   1902   1.1  thorpej 			NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft,
   1903   1.1  thorpej 				  0, &size);
   1904   1.1  thorpej 			sc->sc_prevphase = DATA_OUT_PHASE;
   1905   1.1  thorpej 			goto setup_xfer;
   1906   1.1  thorpej 		case DATA_IN_PHASE:
   1907   1.1  thorpej 			NCR_PHASE(("DATA_IN_PHASE "));
   1908   1.1  thorpej 			if (sc->sc_rev == NCR_VARIANT_ESP100)
   1909   1.1  thorpej 				NCRCMD(sc, NCRCMD_FLUSH);
   1910   1.1  thorpej 			size = min(sc->sc_dleft, sc->sc_maxxfer);
   1911   1.1  thorpej 			NCRDMA_SETUP(sc, &sc->sc_dp, &sc->sc_dleft,
   1912   1.1  thorpej 				  1, &size);
   1913   1.1  thorpej 			sc->sc_prevphase = DATA_IN_PHASE;
   1914   1.1  thorpej 		setup_xfer:
   1915  1.13       pk 			/* Target returned to data phase: wipe "done" memory */
   1916  1.13       pk 			ecb->flags &= ~ECB_TENTATIVE_DONE;
   1917  1.13       pk 
   1918   1.1  thorpej 			/* Program the SCSI counter */
   1919   1.1  thorpej 			NCR_WRITE_REG(sc, NCR_TCL, size);
   1920   1.1  thorpej 			NCR_WRITE_REG(sc, NCR_TCM, size >> 8);
   1921   1.1  thorpej 			if (sc->sc_cfg2 & NCRCFG2_FE) {
   1922   1.1  thorpej 				NCR_WRITE_REG(sc, NCR_TCH, size >> 16);
   1923   1.1  thorpej 			}
   1924   1.1  thorpej 			/* load the count in */
   1925   1.1  thorpej 			NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
   1926   1.1  thorpej 
   1927   1.1  thorpej 			/*
   1928   1.1  thorpej 			 * Note that if `size' is 0, we've already transceived
   1929   1.1  thorpej 			 * all the bytes we want but we're still in DATA PHASE.
   1930   1.1  thorpej 			 * Apparently, the device needs padding. Also, a
   1931   1.1  thorpej 			 * transfer size of 0 means "maximum" to the chip
   1932   1.1  thorpej 			 * DMA logic.
   1933   1.1  thorpej 			 */
   1934   1.1  thorpej 			NCRCMD(sc,
   1935   1.1  thorpej 			       (size==0?NCRCMD_TRPAD:NCRCMD_TRANS)|NCRCMD_DMA);
   1936   1.1  thorpej 			NCRDMA_GO(sc);
   1937   1.1  thorpej 			return 1;
   1938   1.1  thorpej 		case STATUS_PHASE:
   1939   1.1  thorpej 			NCR_PHASE(("STATUS_PHASE "));
   1940   1.1  thorpej 			sc->sc_flags |= NCR_ICCS;
   1941   1.1  thorpej 			NCRCMD(sc, NCRCMD_ICCS);
   1942   1.1  thorpej 			sc->sc_prevphase = STATUS_PHASE;
   1943   1.1  thorpej 			break;
   1944   1.1  thorpej 		case INVALID_PHASE:
   1945   1.1  thorpej 			break;
   1946   1.1  thorpej 		default:
   1947   1.1  thorpej 			printf("%s: unexpected bus phase; resetting\n",
   1948   1.1  thorpej 			    sc->sc_dev.dv_xname);
   1949   1.1  thorpej 			goto reset;
   1950   1.1  thorpej 		}
   1951   1.1  thorpej 	}
   1952   1.1  thorpej 	panic("esp: should not get here..");
   1953   1.1  thorpej 
   1954   1.1  thorpej reset:
   1955   1.1  thorpej 	ncr53c9x_init(sc, 1);
   1956   1.1  thorpej 	return 1;
   1957   1.1  thorpej 
   1958   1.1  thorpej finish:
   1959   1.1  thorpej 	ncr53c9x_done(sc, ecb);
   1960   1.1  thorpej 	goto out;
   1961   1.1  thorpej 
   1962   1.1  thorpej sched:
   1963   1.1  thorpej 	sc->sc_state = NCR_IDLE;
   1964   1.1  thorpej 	ncr53c9x_sched(sc);
   1965   1.1  thorpej 	goto out;
   1966   1.1  thorpej 
   1967   1.1  thorpej out:
   1968   1.1  thorpej 	return 1;
   1969   1.1  thorpej }
   1970   1.1  thorpej 
   1971   1.1  thorpej void
   1972   1.1  thorpej ncr53c9x_abort(sc, ecb)
   1973   1.1  thorpej 	struct ncr53c9x_softc *sc;
   1974   1.1  thorpej 	struct ncr53c9x_ecb *ecb;
   1975   1.1  thorpej {
   1976   1.1  thorpej 
   1977   1.1  thorpej 	/* 2 secs for the abort */
   1978   1.1  thorpej 	ecb->timeout = NCR_ABORT_TIMEOUT;
   1979   1.1  thorpej 	ecb->flags |= ECB_ABORT;
   1980   1.1  thorpej 
   1981   1.1  thorpej 	if (ecb == sc->sc_nexus) {
   1982   1.1  thorpej 		/*
   1983   1.1  thorpej 		 * If we're still selecting, the message will be scheduled
   1984   1.1  thorpej 		 * after selection is complete.
   1985   1.1  thorpej 		 */
   1986   1.1  thorpej 		if (sc->sc_state == NCR_CONNECTED)
   1987   1.1  thorpej 			ncr53c9x_sched_msgout(SEND_ABORT);
   1988   1.1  thorpej 
   1989   1.1  thorpej 		/*
   1990   1.1  thorpej 		 * Reschedule timeout. First, cancel a queued timeout (if any)
   1991   1.1  thorpej 		 * in case someone decides to call ncr53c9x_abort() from
   1992   1.1  thorpej 		 * elsewhere.
   1993   1.1  thorpej 		 */
   1994   1.1  thorpej 		untimeout(ncr53c9x_timeout, ecb);
   1995   1.1  thorpej 		timeout(ncr53c9x_timeout, ecb, (ecb->timeout * hz) / 1000);
   1996   1.1  thorpej 	} else {
   1997   1.1  thorpej 		ncr53c9x_dequeue(sc, ecb);
   1998   1.1  thorpej 		TAILQ_INSERT_HEAD(&sc->ready_list, ecb, chain);
   1999   1.1  thorpej 		if (sc->sc_state == NCR_IDLE)
   2000   1.1  thorpej 			ncr53c9x_sched(sc);
   2001   1.1  thorpej 	}
   2002   1.1  thorpej }
   2003   1.1  thorpej 
   2004   1.1  thorpej void
   2005   1.1  thorpej ncr53c9x_timeout(arg)
   2006   1.1  thorpej 	void *arg;
   2007   1.1  thorpej {
   2008   1.1  thorpej 	struct ncr53c9x_ecb *ecb = arg;
   2009  1.18   bouyer 	struct scsipi_xfer *xs = ecb->xs;
   2010  1.18   bouyer 	struct scsipi_link *sc_link = xs->sc_link;
   2011   1.1  thorpej 	struct ncr53c9x_softc *sc = sc_link->adapter_softc;
   2012  1.18   bouyer 	struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[sc_link->scsipi_scsi.target];
   2013   1.1  thorpej 	int s;
   2014   1.1  thorpej 
   2015  1.18   bouyer 	scsi_print_addr(sc_link);
   2016   1.1  thorpej 	printf("%s: timed out [ecb %p (flags 0x%x, dleft %x, stat %x)], "
   2017   1.1  thorpej 	       "<state %d, nexus %p, phase(c %x, p %x), resid %lx, "
   2018   1.1  thorpej 	       "msg(q %x,o %x) %s>",
   2019   1.1  thorpej 		sc->sc_dev.dv_xname,
   2020   1.1  thorpej 		ecb, ecb->flags, ecb->dleft, ecb->stat,
   2021   1.1  thorpej 		sc->sc_state, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
   2022   1.1  thorpej 		(long)sc->sc_dleft, sc->sc_msgpriq, sc->sc_msgout,
   2023   1.1  thorpej 		NCRDMA_ISACTIVE(sc) ? "DMA active" : "");
   2024   1.7      gwr #if NCR53C9X_DEBUG > 1
   2025   1.1  thorpej 	printf("TRACE: %s.", ecb->trace);
   2026   1.1  thorpej #endif
   2027   1.1  thorpej 
   2028   1.1  thorpej 	s = splbio();
   2029   1.1  thorpej 
   2030   1.1  thorpej 	if (ecb->flags & ECB_ABORT) {
   2031   1.1  thorpej 		/* abort timed out */
   2032   1.1  thorpej 		printf(" AGAIN\n");
   2033  1.16       pk 
   2034   1.1  thorpej 		ncr53c9x_init(sc, 1);
   2035   1.1  thorpej 	} else {
   2036   1.1  thorpej 		/* abort the operation that has timed out */
   2037   1.1  thorpej 		printf("\n");
   2038   1.1  thorpej 		xs->error = XS_TIMEOUT;
   2039   1.1  thorpej 		ncr53c9x_abort(sc, ecb);
   2040  1.16       pk 
   2041  1.16       pk 		/* Disable sync mode if stuck in a data phase */
   2042  1.16       pk 		if (ecb == sc->sc_nexus &&
   2043  1.16       pk 		    (ti->flags & T_SYNCMODE) != 0 &&
   2044  1.16       pk 		    (sc->sc_phase & (MSGI|CDI)) == 0) {
   2045  1.18   bouyer 			scsi_print_addr(sc_link);
   2046  1.16       pk 			printf("sync negotiation disabled\n");
   2047  1.18   bouyer 			sc->sc_cfflags |= (1<<(sc_link->scsipi_scsi.target+8));
   2048  1.16       pk 		}
   2049   1.1  thorpej 	}
   2050   1.1  thorpej 
   2051   1.1  thorpej 	splx(s);
   2052   1.1  thorpej }
   2053