Home | History | Annotate | Line # | Download | only in dev
mesh.c revision 1.7
      1  1.7   tsubai /*	$NetBSD: mesh.c,v 1.7 2000/10/31 16:57:07 tsubai Exp $	*/
      2  1.1   tsubai 
      3  1.1   tsubai /*-
      4  1.6   tsubai  * Copyright (c) 2000	Tsubai Masanari.
      5  1.6   tsubai  * Copyright (c) 1999	Internet Research Institute, Inc.
      6  1.1   tsubai  * All rights reserved.
      7  1.1   tsubai  *
      8  1.1   tsubai  * Redistribution and use in source and binary forms, with or without
      9  1.1   tsubai  * modification, are permitted provided that the following conditions
     10  1.1   tsubai  * are met:
     11  1.1   tsubai  * 1. Redistributions of source code must retain the above copyright
     12  1.1   tsubai  *    notice, this list of conditions and the following disclaimer.
     13  1.1   tsubai  * 2. Redistributions in binary form must reproduce the above copyright
     14  1.1   tsubai  *    notice, this list of conditions and the following disclaimer in the
     15  1.1   tsubai  *    documentation and/or other materials provided with the distribution.
     16  1.1   tsubai  * 3. All advertising materials mentioning features or use of this software
     17  1.1   tsubai  *    must display the following acknowledgement:
     18  1.1   tsubai  *	This product includes software developed by
     19  1.1   tsubai  *	Internet Research Institute, Inc.
     20  1.1   tsubai  * 4. The name of the author may not be used to endorse or promote products
     21  1.1   tsubai  *    derived from this software without specific prior written permission.
     22  1.1   tsubai  *
     23  1.1   tsubai  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24  1.1   tsubai  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25  1.1   tsubai  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  1.1   tsubai  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27  1.1   tsubai  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28  1.1   tsubai  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29  1.1   tsubai  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30  1.1   tsubai  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31  1.1   tsubai  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     32  1.1   tsubai  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33  1.1   tsubai  */
     34  1.1   tsubai 
     35  1.1   tsubai #include <sys/param.h>
     36  1.1   tsubai #include <sys/buf.h>
     37  1.1   tsubai #include <sys/device.h>
     38  1.1   tsubai #include <sys/errno.h>
     39  1.1   tsubai #include <sys/kernel.h>
     40  1.1   tsubai #include <sys/malloc.h>
     41  1.1   tsubai #include <sys/queue.h>
     42  1.1   tsubai #include <sys/systm.h>
     43  1.1   tsubai 
     44  1.5      mrg #include <uvm/uvm_extern.h>
     45  1.1   tsubai 
     46  1.1   tsubai #include <dev/scsipi/scsi_all.h>
     47  1.1   tsubai #include <dev/scsipi/scsipi_all.h>
     48  1.1   tsubai #include <dev/scsipi/scsiconf.h>
     49  1.1   tsubai #include <dev/scsipi/scsi_message.h>
     50  1.1   tsubai 
     51  1.1   tsubai #include <dev/ofw/openfirm.h>
     52  1.1   tsubai 
     53  1.1   tsubai #include <machine/autoconf.h>
     54  1.1   tsubai #include <machine/cpu.h>
     55  1.1   tsubai #include <machine/pio.h>
     56  1.1   tsubai 
     57  1.1   tsubai #include <macppc/dev/dbdma.h>
     58  1.1   tsubai #include <macppc/dev/meshreg.h>
     59  1.1   tsubai 
     60  1.6   tsubai #ifdef MESH_DEBUG
     61  1.6   tsubai # define DPRINTF printf
     62  1.6   tsubai #else
     63  1.6   tsubai # define DPRINTF while (0) printf
     64  1.6   tsubai #endif
     65  1.6   tsubai 
     66  1.1   tsubai #define T_SYNCMODE 0x01		/* target uses sync mode */
     67  1.1   tsubai #define T_SYNCNEGO 0x02		/* sync negotiation done */
     68  1.1   tsubai 
     69  1.1   tsubai struct mesh_tinfo {
     70  1.1   tsubai 	int flags;
     71  1.1   tsubai 	int period;
     72  1.1   tsubai 	int offset;
     73  1.1   tsubai };
     74  1.1   tsubai 
     75  1.1   tsubai /* scb flags */
     76  1.1   tsubai #define MESH_POLL	0x01
     77  1.1   tsubai #define MESH_CHECK	0x02
     78  1.1   tsubai #define MESH_SENSE	0x04
     79  1.1   tsubai #define MESH_READ	0x80
     80  1.1   tsubai 
     81  1.1   tsubai struct mesh_scb {
     82  1.1   tsubai 	TAILQ_ENTRY(mesh_scb) chain;
     83  1.1   tsubai 	int flags;
     84  1.1   tsubai 	struct scsipi_xfer *xs;
     85  1.1   tsubai 	struct scsi_generic cmd;
     86  1.1   tsubai 	int cmdlen;
     87  1.1   tsubai 	int target;			/* target SCSI ID */
     88  1.1   tsubai 	int resid;
     89  1.1   tsubai 	vaddr_t daddr;
     90  1.1   tsubai 	vsize_t dlen;
     91  1.1   tsubai 	int status;
     92  1.1   tsubai };
     93  1.1   tsubai 
     94  1.1   tsubai /* sc_flags value */
     95  1.1   tsubai #define MESH_DMA_ACTIVE	0x01
     96  1.1   tsubai 
     97  1.1   tsubai struct mesh_softc {
     98  1.1   tsubai 	struct device sc_dev;		/* us as a device */
     99  1.1   tsubai 	struct scsipi_link sc_link;
    100  1.1   tsubai 	struct scsipi_adapter sc_adapter;
    101  1.1   tsubai 
    102  1.1   tsubai 	u_char *sc_reg;			/* MESH base address */
    103  1.1   tsubai 	dbdma_regmap_t *sc_dmareg;	/* DMA register address */
    104  1.1   tsubai 	dbdma_command_t *sc_dmacmd;	/* DMA command area */
    105  1.1   tsubai 
    106  1.1   tsubai 	int sc_flags;
    107  1.1   tsubai 	int sc_cfflags;			/* copy of config flags */
    108  1.1   tsubai 	int sc_meshid;			/* MESH version */
    109  1.1   tsubai 	int sc_minsync;			/* minimum sync period */
    110  1.1   tsubai 	int sc_irq;
    111  1.1   tsubai 	int sc_freq;			/* SCSI bus frequency in MHz */
    112  1.1   tsubai 	int sc_id;			/* our SCSI ID */
    113  1.1   tsubai 	struct mesh_tinfo sc_tinfo[8];	/* target information */
    114  1.1   tsubai 
    115  1.1   tsubai 	int sc_nextstate;
    116  1.1   tsubai 	int sc_prevphase;
    117  1.1   tsubai 	struct mesh_scb *sc_nexus;	/* current command */
    118  1.1   tsubai 
    119  1.1   tsubai 	int sc_msgout;
    120  1.1   tsubai 	int sc_imsglen;
    121  1.1   tsubai 	u_char sc_imsg[16];
    122  1.1   tsubai 	u_char sc_omsg[16];
    123  1.1   tsubai 
    124  1.1   tsubai 	TAILQ_HEAD(, mesh_scb) free_scb;
    125  1.1   tsubai 	TAILQ_HEAD(, mesh_scb) ready_scb;
    126  1.1   tsubai 	struct mesh_scb sc_scb[16];
    127  1.1   tsubai };
    128  1.1   tsubai 
    129  1.1   tsubai /* mesh_msgout() values */
    130  1.1   tsubai #define SEND_REJECT	1
    131  1.1   tsubai #define SEND_IDENTIFY	2
    132  1.1   tsubai #define SEND_SDTR	4
    133  1.1   tsubai 
    134  1.1   tsubai static __inline int mesh_read_reg __P((struct mesh_softc *, int));
    135  1.1   tsubai static __inline void mesh_set_reg __P((struct mesh_softc *, int, int));
    136  1.1   tsubai 
    137  1.1   tsubai int mesh_match __P((struct device *, struct cfdata *, void *));
    138  1.1   tsubai void mesh_attach __P((struct device *, struct device *, void *));
    139  1.1   tsubai void mesh_shutdownhook __P((void *));
    140  1.1   tsubai int mesh_intr __P((void *));
    141  1.1   tsubai void mesh_error __P((struct mesh_softc *, struct mesh_scb *, int, int));
    142  1.1   tsubai void mesh_select __P((struct mesh_softc *, struct mesh_scb *));
    143  1.1   tsubai void mesh_identify __P((struct mesh_softc *, struct mesh_scb *));
    144  1.1   tsubai void mesh_command __P((struct mesh_softc *, struct mesh_scb *));
    145  1.1   tsubai void mesh_dma_setup __P((struct mesh_softc *, struct mesh_scb *));
    146  1.1   tsubai void mesh_dataio __P((struct mesh_softc *, struct mesh_scb *));
    147  1.1   tsubai void mesh_status __P((struct mesh_softc *, struct mesh_scb *));
    148  1.1   tsubai void mesh_msgin __P((struct mesh_softc *, struct mesh_scb *));
    149  1.1   tsubai void mesh_msgout __P((struct mesh_softc *, int));
    150  1.1   tsubai void mesh_bus_reset __P((struct mesh_softc *));
    151  1.1   tsubai void mesh_reset __P((struct mesh_softc *));
    152  1.1   tsubai int mesh_stp __P((struct mesh_softc *, int));
    153  1.1   tsubai void mesh_setsync __P((struct mesh_softc *, struct mesh_tinfo *));
    154  1.1   tsubai struct mesh_scb *mesh_get_scb __P((struct mesh_softc *));
    155  1.1   tsubai void mesh_free_scb __P((struct mesh_softc *, struct mesh_scb *));
    156  1.1   tsubai int mesh_scsi_cmd __P((struct scsipi_xfer *));
    157  1.1   tsubai void mesh_sched __P((struct mesh_softc *));
    158  1.1   tsubai int mesh_poll __P((struct mesh_softc *, struct scsipi_xfer *));
    159  1.1   tsubai void mesh_done __P((struct mesh_softc *, struct mesh_scb *));
    160  1.1   tsubai void mesh_timeout __P((void *));
    161  1.1   tsubai void mesh_sense __P((struct mesh_softc *, struct mesh_scb *));
    162  1.1   tsubai void mesh_minphys __P((struct buf *));
    163  1.1   tsubai 
    164  1.1   tsubai 
    165  1.1   tsubai #define MESH_DATAOUT	0
    166  1.1   tsubai #define MESH_DATAIN	MESH_STATUS0_IO
    167  1.1   tsubai #define MESH_COMMAND	MESH_STATUS0_CD
    168  1.1   tsubai #define MESH_STATUS	(MESH_STATUS0_CD | MESH_STATUS0_IO)
    169  1.1   tsubai #define MESH_MSGOUT	(MESH_STATUS0_MSG | MESH_STATUS0_CD)
    170  1.1   tsubai #define MESH_MSGIN	(MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
    171  1.1   tsubai 
    172  1.1   tsubai #define MESH_SELECTING	8
    173  1.1   tsubai #define MESH_IDENTIFY	9
    174  1.1   tsubai #define MESH_COMPLETE	10
    175  1.1   tsubai #define MESH_BUSFREE	11
    176  1.1   tsubai #define MESH_UNKNOWN	-1
    177  1.1   tsubai 
    178  1.1   tsubai #define MESH_PHASE_MASK	(MESH_STATUS0_MSG | MESH_STATUS0_CD | MESH_STATUS0_IO)
    179  1.1   tsubai 
    180  1.1   tsubai struct cfattach mesh_ca = {
    181  1.1   tsubai 	sizeof(struct mesh_softc), mesh_match, mesh_attach
    182  1.1   tsubai };
    183  1.1   tsubai 
    184  1.1   tsubai struct scsipi_device mesh_dev = {
    185  1.1   tsubai 	NULL,			/* Use default error handler */
    186  1.1   tsubai 	NULL,			/* have a queue, served by this */
    187  1.1   tsubai 	NULL,			/* have no async handler */
    188  1.1   tsubai 	NULL,			/* Use default 'done' routine */
    189  1.1   tsubai };
    190  1.1   tsubai 
    191  1.1   tsubai int
    192  1.1   tsubai mesh_match(parent, cf, aux)
    193  1.1   tsubai 	struct device *parent;
    194  1.1   tsubai 	struct cfdata *cf;
    195  1.1   tsubai 	void *aux;
    196  1.1   tsubai {
    197  1.1   tsubai 	struct confargs *ca = aux;
    198  1.7   tsubai 	char compat[32];
    199  1.1   tsubai 
    200  1.7   tsubai 	if (strcmp(ca->ca_name, "mesh") == 0)
    201  1.7   tsubai 		return 1;
    202  1.1   tsubai 
    203  1.7   tsubai 	bzero(compat, sizeof(compat));
    204  1.7   tsubai 	OF_getprop(ca->ca_node, "compatible", compat, sizeof(compat));
    205  1.7   tsubai 	if (strcmp(compat, "chrp,mesh0") == 0)
    206  1.7   tsubai 		return 1;
    207  1.7   tsubai 
    208  1.7   tsubai 	return 0;
    209  1.1   tsubai }
    210  1.1   tsubai 
    211  1.1   tsubai void
    212  1.1   tsubai mesh_attach(parent, self, aux)
    213  1.1   tsubai 	struct device *parent, *self;
    214  1.1   tsubai 	void *aux;
    215  1.1   tsubai {
    216  1.1   tsubai 	struct mesh_softc *sc = (void *)self;
    217  1.1   tsubai 	struct confargs *ca = aux;
    218  1.1   tsubai 	int i;
    219  1.1   tsubai 	u_int *reg;
    220  1.1   tsubai 
    221  1.1   tsubai 	reg = ca->ca_reg;
    222  1.1   tsubai 	reg[0] += ca->ca_baseaddr;
    223  1.1   tsubai 	reg[2] += ca->ca_baseaddr;
    224  1.1   tsubai 	sc->sc_reg = mapiodev(reg[0], reg[1]);
    225  1.1   tsubai 	sc->sc_irq = ca->ca_intr[0];
    226  1.1   tsubai 	sc->sc_dmareg = mapiodev(reg[2], reg[3]);
    227  1.1   tsubai 
    228  1.1   tsubai 	sc->sc_cfflags = self->dv_cfdata->cf_flags;
    229  1.1   tsubai 	sc->sc_meshid = mesh_read_reg(sc, MESH_MESH_ID) & 0x1f;
    230  1.1   tsubai #if 0
    231  1.1   tsubai 	if (sc->sc_meshid != (MESH_SIGNATURE & 0x1f) {
    232  1.1   tsubai 		printf(": unknown MESH ID (0x%x)\n", sc->sc_meshid);
    233  1.1   tsubai 		return;
    234  1.1   tsubai 	}
    235  1.1   tsubai #endif
    236  1.1   tsubai 	if (OF_getprop(ca->ca_node, "clock-frequency", &sc->sc_freq, 4) != 4) {
    237  1.1   tsubai 		printf(": cannot get clock-frequency\n");
    238  1.1   tsubai 		return;
    239  1.1   tsubai 	}
    240  1.1   tsubai 	sc->sc_freq /= 1000000;	/* in MHz */
    241  1.1   tsubai 	sc->sc_minsync = 25;	/* maximum sync rate = 10MB/sec */
    242  1.1   tsubai 	sc->sc_id = 7;
    243  1.1   tsubai 
    244  1.1   tsubai 	TAILQ_INIT(&sc->free_scb);
    245  1.1   tsubai 	TAILQ_INIT(&sc->ready_scb);
    246  1.1   tsubai 	for (i = 0; i < sizeof(sc->sc_scb)/sizeof(sc->sc_scb[0]); i++)
    247  1.1   tsubai 		TAILQ_INSERT_TAIL(&sc->free_scb, &sc->sc_scb[i], chain);
    248  1.1   tsubai 
    249  1.1   tsubai 	sc->sc_dmacmd = dbdma_alloc(sizeof(dbdma_command_t) * 20);
    250  1.1   tsubai 
    251  1.1   tsubai 	mesh_reset(sc);
    252  1.1   tsubai 	mesh_bus_reset(sc);
    253  1.1   tsubai 
    254  1.1   tsubai 	printf(" irq %d: %dMHz, SCSI ID %d\n",
    255  1.1   tsubai 		sc->sc_irq, sc->sc_freq, sc->sc_id);
    256  1.1   tsubai 
    257  1.1   tsubai 	sc->sc_adapter.scsipi_cmd = mesh_scsi_cmd;
    258  1.1   tsubai 	sc->sc_adapter.scsipi_minphys = mesh_minphys;
    259  1.1   tsubai 
    260  1.1   tsubai 	sc->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;
    261  1.1   tsubai 	sc->sc_link.adapter_softc = sc;
    262  1.1   tsubai 	sc->sc_link.scsipi_scsi.adapter_target = sc->sc_id;
    263  1.1   tsubai 	sc->sc_link.adapter = &sc->sc_adapter;
    264  1.1   tsubai 	sc->sc_link.device = &mesh_dev;
    265  1.1   tsubai 	sc->sc_link.openings = 2;
    266  1.1   tsubai 	sc->sc_link.scsipi_scsi.max_target = 7;
    267  1.1   tsubai 	sc->sc_link.scsipi_scsi.max_lun = 7;
    268  1.1   tsubai 	sc->sc_link.type = BUS_SCSI;
    269  1.1   tsubai 
    270  1.1   tsubai 	config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
    271  1.1   tsubai 
    272  1.1   tsubai 	intr_establish(sc->sc_irq, IST_LEVEL, IPL_BIO, mesh_intr, sc);
    273  1.1   tsubai 
    274  1.1   tsubai 	/* Reset SCSI bus when halt. */
    275  1.1   tsubai 	shutdownhook_establish(mesh_shutdownhook, sc);
    276  1.1   tsubai }
    277  1.1   tsubai 
    278  1.1   tsubai #define MESH_SET_XFER(sc, count) do {					\
    279  1.1   tsubai 	mesh_set_reg(sc, MESH_XFER_COUNT0, count);			\
    280  1.1   tsubai 	mesh_set_reg(sc, MESH_XFER_COUNT1, count >> 8);			\
    281  1.1   tsubai } while (0)
    282  1.1   tsubai 
    283  1.1   tsubai #define MESH_GET_XFER(sc) ((mesh_read_reg(sc, MESH_XFER_COUNT1) << 8) |	\
    284  1.1   tsubai 			   mesh_read_reg(sc, MESH_XFER_COUNT0))
    285  1.1   tsubai 
    286  1.1   tsubai int
    287  1.1   tsubai mesh_read_reg(sc, reg)
    288  1.1   tsubai 	struct mesh_softc *sc;
    289  1.1   tsubai 	int reg;
    290  1.1   tsubai {
    291  1.1   tsubai 	return in8(sc->sc_reg + reg);
    292  1.1   tsubai }
    293  1.1   tsubai 
    294  1.1   tsubai void
    295  1.1   tsubai mesh_set_reg(sc, reg, val)
    296  1.1   tsubai 	struct mesh_softc *sc;
    297  1.1   tsubai 	int reg, val;
    298  1.1   tsubai {
    299  1.1   tsubai 	out8(sc->sc_reg + reg, val);
    300  1.1   tsubai }
    301  1.1   tsubai 
    302  1.1   tsubai void
    303  1.1   tsubai mesh_shutdownhook(arg)
    304  1.1   tsubai 	void *arg;
    305  1.1   tsubai {
    306  1.1   tsubai 	struct mesh_softc *sc = arg;
    307  1.1   tsubai 
    308  1.1   tsubai 	/* Set to async mode. */
    309  1.1   tsubai 	mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
    310  1.1   tsubai }
    311  1.1   tsubai 
    312  1.6   tsubai #ifdef MESH_DEBUG
    313  1.6   tsubai static char scsi_phase[][8] = {
    314  1.6   tsubai 	"DATAOUT",
    315  1.6   tsubai 	"DATAIN",
    316  1.6   tsubai 	"COMMAND",
    317  1.6   tsubai 	"STATUS",
    318  1.6   tsubai 	"",
    319  1.6   tsubai 	"",
    320  1.6   tsubai 	"MSGOUT",
    321  1.6   tsubai 	"MSGIN"
    322  1.6   tsubai };
    323  1.6   tsubai #endif
    324  1.6   tsubai 
    325  1.1   tsubai int
    326  1.1   tsubai mesh_intr(arg)
    327  1.1   tsubai 	void *arg;
    328  1.1   tsubai {
    329  1.1   tsubai 	struct mesh_softc *sc = arg;
    330  1.1   tsubai 	struct mesh_scb *scb;
    331  1.3   tsubai 	int fifocnt;
    332  1.1   tsubai 	u_char intr, exception, error, status0, status1;
    333  1.1   tsubai 
    334  1.1   tsubai 	intr = mesh_read_reg(sc, MESH_INTERRUPT);
    335  1.1   tsubai 	if (intr == 0) {
    336  1.6   tsubai 		DPRINTF("%s: stray interrupt\n", sc->sc_dev.dv_xname);
    337  1.1   tsubai 		return 0;
    338  1.1   tsubai 	}
    339  1.1   tsubai 
    340  1.1   tsubai 	exception = mesh_read_reg(sc, MESH_EXCEPTION);
    341  1.1   tsubai 	error = mesh_read_reg(sc, MESH_ERROR);
    342  1.1   tsubai 	status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
    343  1.1   tsubai 	status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
    344  1.1   tsubai 
    345  1.1   tsubai 	/* clear interrupt */
    346  1.1   tsubai 	mesh_set_reg(sc, MESH_INTERRUPT, intr);
    347  1.1   tsubai 
    348  1.6   tsubai #ifdef MESH_DEBUG
    349  1.6   tsubai {
    350  1.6   tsubai 	char buf1[64], buf2[64];
    351  1.6   tsubai 
    352  1.6   tsubai 	bitmask_snprintf(status0, MESH_STATUS0_BITMASK, buf1, sizeof buf1);
    353  1.6   tsubai 	bitmask_snprintf(exception, MESH_EXC_BITMASK, buf2, sizeof buf2);
    354  1.6   tsubai 	printf("mesh_intr status0 = 0x%s (%s), exc = 0x%s\n",
    355  1.6   tsubai 	    buf1, scsi_phase[status0 & 7], buf2);
    356  1.6   tsubai }
    357  1.6   tsubai #endif
    358  1.6   tsubai 
    359  1.1   tsubai 	scb = sc->sc_nexus;
    360  1.1   tsubai 	if (scb == NULL) {
    361  1.6   tsubai 		DPRINTF("%s: NULL nexus\n", sc->sc_dev.dv_xname);
    362  1.1   tsubai 		return 1;
    363  1.1   tsubai 	}
    364  1.1   tsubai 
    365  1.1   tsubai 	if (sc->sc_flags & MESH_DMA_ACTIVE) {
    366  1.1   tsubai 		dbdma_stop(sc->sc_dmareg);
    367  1.1   tsubai 
    368  1.1   tsubai 		sc->sc_flags &= ~MESH_DMA_ACTIVE;
    369  1.1   tsubai 		scb->resid = MESH_GET_XFER(sc);
    370  1.1   tsubai 
    371  1.3   tsubai 		fifocnt = mesh_read_reg(sc, MESH_FIFO_COUNT);
    372  1.3   tsubai 		if (fifocnt != 0 && (scb->flags & MESH_READ)) {
    373  1.3   tsubai 			char *cp = (char *)scb->daddr + scb->dlen - fifocnt;
    374  1.3   tsubai 
    375  1.6   tsubai 			DPRINTF("fifocnt = %d, resid = %d\n", fifocnt,
    376  1.6   tsubai 				scb->resid);
    377  1.3   tsubai 			while (fifocnt > 0) {
    378  1.3   tsubai 				*cp++ = mesh_read_reg(sc, MESH_FIFO);
    379  1.3   tsubai 				fifocnt--;
    380  1.3   tsubai 			}
    381  1.3   tsubai 		} else
    382  1.3   tsubai 			mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
    383  1.1   tsubai 	}
    384  1.1   tsubai 
    385  1.1   tsubai 	if (intr & MESH_INTR_ERROR) {
    386  1.1   tsubai 		mesh_error(sc, scb, error, 0);
    387  1.1   tsubai 		return 1;
    388  1.1   tsubai 	}
    389  1.1   tsubai 
    390  1.1   tsubai 	if (intr & MESH_INTR_EXCEPTION) {
    391  1.1   tsubai 		/* selection timeout */
    392  1.1   tsubai 		if (exception & MESH_EXC_SELTO) {
    393  1.1   tsubai 			mesh_error(sc, scb, 0, exception);
    394  1.1   tsubai 			return 1;
    395  1.1   tsubai 		}
    396  1.1   tsubai 
    397  1.1   tsubai 		/* phase mismatch */
    398  1.1   tsubai 		if (exception & MESH_EXC_PHASEMM) {
    399  1.6   tsubai 			DPRINTF("%s: PHASE MISMATCH; nextstate = %d -> ",
    400  1.6   tsubai 				sc->sc_dev.dv_xname, sc->sc_nextstate);
    401  1.1   tsubai 			sc->sc_nextstate = status0 & MESH_PHASE_MASK;
    402  1.6   tsubai 
    403  1.6   tsubai 			DPRINTF("%d, resid = %d\n",
    404  1.6   tsubai 				sc->sc_nextstate, scb->resid);
    405  1.1   tsubai 		}
    406  1.1   tsubai 	}
    407  1.1   tsubai 
    408  1.1   tsubai 	if (sc->sc_nextstate == MESH_UNKNOWN)
    409  1.1   tsubai 		sc->sc_nextstate = status0 & MESH_PHASE_MASK;
    410  1.1   tsubai 
    411  1.1   tsubai 	switch (sc->sc_nextstate) {
    412  1.1   tsubai 
    413  1.1   tsubai 	case MESH_IDENTIFY:
    414  1.1   tsubai 		mesh_identify(sc, scb);
    415  1.1   tsubai 		break;
    416  1.1   tsubai 	case MESH_COMMAND:
    417  1.1   tsubai 		mesh_command(sc, scb);
    418  1.1   tsubai 		break;
    419  1.1   tsubai 	case MESH_DATAIN:
    420  1.1   tsubai 	case MESH_DATAOUT:
    421  1.1   tsubai 		mesh_dataio(sc, scb);
    422  1.1   tsubai 		break;
    423  1.1   tsubai 	case MESH_STATUS:
    424  1.1   tsubai 		mesh_status(sc, scb);
    425  1.1   tsubai 		break;
    426  1.1   tsubai 	case MESH_MSGIN:
    427  1.1   tsubai 		mesh_msgin(sc, scb);
    428  1.1   tsubai 		break;
    429  1.1   tsubai 	case MESH_COMPLETE:
    430  1.1   tsubai 		mesh_done(sc, scb);
    431  1.1   tsubai 		break;
    432  1.1   tsubai 
    433  1.1   tsubai 	default:
    434  1.6   tsubai 		printf("%s: unknown state (%d)\n", sc->sc_dev.dv_xname,
    435  1.6   tsubai 		    sc->sc_nextstate);
    436  1.6   tsubai 		scb->xs->error = XS_DRIVER_STUFFUP;
    437  1.6   tsubai 		mesh_done(sc, scb);
    438  1.1   tsubai 	}
    439  1.1   tsubai 
    440  1.1   tsubai 	return 1;
    441  1.1   tsubai }
    442  1.1   tsubai 
    443  1.1   tsubai void
    444  1.1   tsubai mesh_error(sc, scb, error, exception)
    445  1.1   tsubai 	struct mesh_softc *sc;
    446  1.1   tsubai 	struct mesh_scb *scb;
    447  1.1   tsubai 	int error, exception;
    448  1.1   tsubai {
    449  1.1   tsubai 	if (error & MESH_ERR_SCSI_RESET) {
    450  1.6   tsubai 		printf("%s: SCSI RESET\n", sc->sc_dev.dv_xname);
    451  1.1   tsubai 
    452  1.1   tsubai 		/* Wait until the RST signal is deasserted. */
    453  1.1   tsubai 		while (mesh_read_reg(sc, MESH_BUS_STATUS1) & MESH_STATUS1_RST);
    454  1.1   tsubai 		mesh_reset(sc);
    455  1.1   tsubai 		return;
    456  1.1   tsubai 	}
    457  1.1   tsubai 
    458  1.1   tsubai 	if (error & MESH_ERR_PARITY_ERR0) {
    459  1.6   tsubai 		printf("%s: parity error\n", sc->sc_dev.dv_xname);
    460  1.1   tsubai 		scb->xs->error = XS_DRIVER_STUFFUP;
    461  1.1   tsubai 	}
    462  1.1   tsubai 
    463  1.1   tsubai 	if (error & MESH_ERR_DISCONNECT) {
    464  1.6   tsubai 		printf("%s: unexpected disconnect\n", sc->sc_dev.dv_xname);
    465  1.1   tsubai 		if (sc->sc_nextstate != MESH_COMPLETE)
    466  1.1   tsubai 			scb->xs->error = XS_DRIVER_STUFFUP;
    467  1.1   tsubai 	}
    468  1.1   tsubai 
    469  1.1   tsubai 	if (exception & MESH_EXC_SELTO) {
    470  1.1   tsubai 		/* XXX should reset bus here? */
    471  1.6   tsubai 		scb->xs->error = XS_SELTIMEOUT;
    472  1.1   tsubai 	}
    473  1.1   tsubai 
    474  1.1   tsubai 	mesh_done(sc, scb);
    475  1.1   tsubai }
    476  1.1   tsubai 
    477  1.1   tsubai void
    478  1.1   tsubai mesh_select(sc, scb)
    479  1.1   tsubai 	struct mesh_softc *sc;
    480  1.1   tsubai 	struct mesh_scb *scb;
    481  1.1   tsubai {
    482  1.1   tsubai 	struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
    483  1.1   tsubai 
    484  1.6   tsubai 	DPRINTF("mesh_select\n");
    485  1.6   tsubai 
    486  1.1   tsubai 	mesh_setsync(sc, ti);
    487  1.1   tsubai 	MESH_SET_XFER(sc, 0);
    488  1.1   tsubai 
    489  1.1   tsubai 	/* arbitration */
    490  1.1   tsubai 
    491  1.1   tsubai 	/*
    492  1.1   tsubai 	 * MESH mistakenly asserts TARGET ID bit along with its own ID bit
    493  1.1   tsubai 	 * in arbitration phase (like selection).  So we should load
    494  1.1   tsubai 	 * initiator ID to DestID register temporarily.
    495  1.1   tsubai 	 */
    496  1.1   tsubai 	mesh_set_reg(sc, MESH_DEST_ID, sc->sc_id);
    497  1.1   tsubai 	mesh_set_reg(sc, MESH_INTR_MASK, 0);	/* disable intr. */
    498  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ARBITRATE);
    499  1.1   tsubai 
    500  1.1   tsubai 	while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
    501  1.1   tsubai 	mesh_set_reg(sc, MESH_INTERRUPT, 1);
    502  1.1   tsubai 	mesh_set_reg(sc, MESH_INTR_MASK, 7);
    503  1.1   tsubai 
    504  1.1   tsubai 	/* selection */
    505  1.1   tsubai 	mesh_set_reg(sc, MESH_DEST_ID, scb->target);
    506  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_SELECT | MESH_SEQ_ATN);
    507  1.1   tsubai 
    508  1.1   tsubai 	sc->sc_prevphase = MESH_SELECTING;
    509  1.1   tsubai 	sc->sc_nextstate = MESH_IDENTIFY;
    510  1.1   tsubai 
    511  1.4  thorpej 	callout_reset(&scb->xs->xs_callout, 10 * hz, mesh_timeout, scb);
    512  1.1   tsubai }
    513  1.1   tsubai 
    514  1.1   tsubai void
    515  1.1   tsubai mesh_identify(sc, scb)
    516  1.1   tsubai 	struct mesh_softc *sc;
    517  1.1   tsubai 	struct mesh_scb *scb;
    518  1.1   tsubai {
    519  1.6   tsubai 	struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
    520  1.6   tsubai 
    521  1.6   tsubai 	DPRINTF("mesh_identify\n");
    522  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
    523  1.1   tsubai 
    524  1.6   tsubai 	if ((ti->flags & T_SYNCNEGO) == 0) {
    525  1.6   tsubai 		ti->period = sc->sc_minsync;
    526  1.6   tsubai 		ti->offset = 15;
    527  1.6   tsubai 		mesh_msgout(sc, SEND_IDENTIFY | SEND_SDTR);
    528  1.6   tsubai 		sc->sc_nextstate = MESH_MSGIN;
    529  1.6   tsubai 	} else {
    530  1.6   tsubai 		mesh_msgout(sc, SEND_IDENTIFY);
    531  1.6   tsubai 		sc->sc_nextstate = MESH_COMMAND;
    532  1.6   tsubai 	}
    533  1.1   tsubai }
    534  1.1   tsubai 
    535  1.1   tsubai void
    536  1.1   tsubai mesh_command(sc, scb)
    537  1.1   tsubai 	struct mesh_softc *sc;
    538  1.1   tsubai 	struct mesh_scb *scb;
    539  1.1   tsubai {
    540  1.1   tsubai 	int i;
    541  1.1   tsubai 	char *cmdp;
    542  1.1   tsubai 
    543  1.6   tsubai #ifdef MESH_DEBUG
    544  1.6   tsubai 	printf("mesh_command cdb = %02x", scb->cmd.opcode);
    545  1.6   tsubai 	for (i = 0; i < 5; i++)
    546  1.6   tsubai 		printf(" %02x", scb->cmd.bytes[i]);
    547  1.6   tsubai 	printf("\n");
    548  1.6   tsubai #endif
    549  1.1   tsubai 
    550  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
    551  1.1   tsubai 
    552  1.1   tsubai 	MESH_SET_XFER(sc, scb->cmdlen);
    553  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_COMMAND);
    554  1.1   tsubai 
    555  1.1   tsubai 	cmdp = (char *)&scb->cmd;
    556  1.1   tsubai 	for (i = 0; i < scb->cmdlen; i++)
    557  1.1   tsubai 		mesh_set_reg(sc, MESH_FIFO, *cmdp++);
    558  1.1   tsubai 
    559  1.1   tsubai 	if (scb->resid == 0)
    560  1.1   tsubai 		sc->sc_nextstate = MESH_STATUS;		/* no data xfer */
    561  1.1   tsubai 	else
    562  1.1   tsubai 		sc->sc_nextstate = MESH_DATAIN;
    563  1.1   tsubai }
    564  1.1   tsubai 
    565  1.1   tsubai void
    566  1.1   tsubai mesh_dma_setup(sc, scb)
    567  1.1   tsubai 	struct mesh_softc *sc;
    568  1.1   tsubai 	struct mesh_scb *scb;
    569  1.1   tsubai {
    570  1.1   tsubai 	int datain = scb->flags & MESH_READ;
    571  1.1   tsubai 	dbdma_command_t *cmdp;
    572  1.1   tsubai 	u_int cmd;
    573  1.1   tsubai 	vaddr_t va;
    574  1.1   tsubai 	int count, offset;
    575  1.1   tsubai 
    576  1.1   tsubai 	cmdp = sc->sc_dmacmd;
    577  1.1   tsubai 	cmd = datain ? DBDMA_CMD_IN_MORE : DBDMA_CMD_OUT_MORE;
    578  1.1   tsubai 
    579  1.1   tsubai 	count = scb->dlen;
    580  1.1   tsubai 
    581  1.1   tsubai 	if (count / NBPG > 32)
    582  1.1   tsubai 		panic("mesh: transfer size >= 128k");
    583  1.1   tsubai 
    584  1.1   tsubai 	va = scb->daddr;
    585  1.1   tsubai 	offset = va & PGOFSET;
    586  1.1   tsubai 
    587  1.1   tsubai 	/* if va is not page-aligned, setup the first page */
    588  1.1   tsubai 	if (offset != 0) {
    589  1.1   tsubai 		int rest = NBPG - offset;	/* the rest in the page */
    590  1.1   tsubai 
    591  1.1   tsubai 		if (count > rest) {		/* if continues to next page */
    592  1.1   tsubai 			DBDMA_BUILD(cmdp, cmd, 0, rest, vtophys(va),
    593  1.1   tsubai 				DBDMA_INT_NEVER, DBDMA_WAIT_NEVER,
    594  1.1   tsubai 				DBDMA_BRANCH_NEVER);
    595  1.1   tsubai 			count -= rest;
    596  1.1   tsubai 			va += rest;
    597  1.1   tsubai 			cmdp++;
    598  1.1   tsubai 		}
    599  1.1   tsubai 	}
    600  1.1   tsubai 
    601  1.1   tsubai 	/* now va is page-aligned */
    602  1.1   tsubai 	while (count > NBPG) {
    603  1.1   tsubai 		DBDMA_BUILD(cmdp, cmd, 0, NBPG, vtophys(va),
    604  1.1   tsubai 			DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    605  1.1   tsubai 		count -= NBPG;
    606  1.1   tsubai 		va += NBPG;
    607  1.1   tsubai 		cmdp++;
    608  1.1   tsubai 	}
    609  1.1   tsubai 
    610  1.1   tsubai 	/* the last page (count <= NBPG here) */
    611  1.1   tsubai 	cmd = datain ? DBDMA_CMD_IN_LAST : DBDMA_CMD_OUT_LAST;
    612  1.1   tsubai 	DBDMA_BUILD(cmdp, cmd , 0, count, vtophys(va),
    613  1.1   tsubai 		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    614  1.1   tsubai 	cmdp++;
    615  1.1   tsubai 
    616  1.1   tsubai 	DBDMA_BUILD(cmdp, DBDMA_CMD_STOP, 0, 0, 0,
    617  1.1   tsubai 		DBDMA_INT_NEVER, DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);
    618  1.1   tsubai }
    619  1.1   tsubai 
    620  1.1   tsubai void
    621  1.1   tsubai mesh_dataio(sc, scb)
    622  1.1   tsubai 	struct mesh_softc *sc;
    623  1.1   tsubai 	struct mesh_scb *scb;
    624  1.1   tsubai {
    625  1.6   tsubai 	DPRINTF("mesh_dataio len = %ld (%s)\n", scb->dlen,
    626  1.6   tsubai 		scb->flags & MESH_READ ? "read" : "write");
    627  1.6   tsubai 
    628  1.1   tsubai 	mesh_dma_setup(sc, scb);
    629  1.1   tsubai 
    630  1.1   tsubai 	if (scb->dlen == 65536)
    631  1.1   tsubai 		MESH_SET_XFER(sc, 0);	/* TC = 0 means 64KB transfer */
    632  1.1   tsubai 	else
    633  1.1   tsubai 		MESH_SET_XFER(sc, scb->dlen);
    634  1.1   tsubai 
    635  1.1   tsubai 	if (scb->flags & MESH_READ)
    636  1.1   tsubai 		mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAIN | MESH_SEQ_DMA);
    637  1.1   tsubai 	else
    638  1.1   tsubai 		mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_DATAOUT | MESH_SEQ_DMA);
    639  1.1   tsubai 	dbdma_start(sc->sc_dmareg, sc->sc_dmacmd);
    640  1.1   tsubai 	sc->sc_flags |= MESH_DMA_ACTIVE;
    641  1.1   tsubai 	sc->sc_nextstate = MESH_STATUS;
    642  1.1   tsubai }
    643  1.1   tsubai 
    644  1.1   tsubai void
    645  1.1   tsubai mesh_status(sc, scb)
    646  1.1   tsubai 	struct mesh_softc *sc;
    647  1.1   tsubai 	struct mesh_scb *scb;
    648  1.1   tsubai {
    649  1.1   tsubai 	if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) {	/* XXX cheat */
    650  1.6   tsubai 		DPRINTF("mesh_status(0)\n");
    651  1.1   tsubai 		MESH_SET_XFER(sc, 1);
    652  1.1   tsubai 		mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_STATUS);
    653  1.1   tsubai 		sc->sc_nextstate = MESH_STATUS;
    654  1.1   tsubai 		return;
    655  1.1   tsubai 	}
    656  1.1   tsubai 
    657  1.1   tsubai 	scb->status = mesh_read_reg(sc, MESH_FIFO);
    658  1.6   tsubai 	DPRINTF("mesh_status(1): status = 0x%x\n", scb->status);
    659  1.6   tsubai 	if (mesh_read_reg(sc, MESH_FIFO_COUNT) != 0)
    660  1.6   tsubai 		DPRINTF("FIFO_COUNT=%d\n", mesh_read_reg(sc, MESH_FIFO_COUNT));
    661  1.1   tsubai 
    662  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_FLUSH_FIFO);
    663  1.1   tsubai 	MESH_SET_XFER(sc, 1);
    664  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
    665  1.1   tsubai 
    666  1.1   tsubai 	sc->sc_nextstate = MESH_MSGIN;
    667  1.1   tsubai }
    668  1.1   tsubai 
    669  1.1   tsubai #define IS1BYTEMSG(m) (((m) != 1 && (m) < 0x20) || (m) & 0x80)
    670  1.1   tsubai #define IS2BYTEMSG(m) (((m) & 0xf0) == 0x20)
    671  1.1   tsubai #define ISEXTMSG(m) ((m) == 1)
    672  1.1   tsubai 
    673  1.1   tsubai void
    674  1.1   tsubai mesh_msgin(sc, scb)
    675  1.1   tsubai 	struct mesh_softc *sc;
    676  1.1   tsubai 	struct mesh_scb *scb;
    677  1.1   tsubai {
    678  1.1   tsubai 	int i;
    679  1.1   tsubai 
    680  1.6   tsubai 	DPRINTF("mesh_msgin\n");
    681  1.6   tsubai 
    682  1.1   tsubai 	if (mesh_read_reg(sc, MESH_FIFO_COUNT) == 0) {	/* XXX cheat */
    683  1.1   tsubai 		MESH_SET_XFER(sc, 1);
    684  1.1   tsubai 		mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
    685  1.1   tsubai 		sc->sc_imsglen = 0;
    686  1.1   tsubai 		sc->sc_nextstate = MESH_MSGIN;
    687  1.1   tsubai 		return;
    688  1.1   tsubai 	}
    689  1.1   tsubai 
    690  1.1   tsubai 	sc->sc_imsg[sc->sc_imsglen++] = mesh_read_reg(sc, MESH_FIFO);
    691  1.1   tsubai 
    692  1.1   tsubai 	if (sc->sc_imsglen == 1 && IS1BYTEMSG(sc->sc_imsg[0]))
    693  1.1   tsubai 		goto gotit;
    694  1.1   tsubai 	if (sc->sc_imsglen == 2 && IS2BYTEMSG(sc->sc_imsg[0]))
    695  1.1   tsubai 		goto gotit;
    696  1.1   tsubai 	if (sc->sc_imsglen >= 3 && ISEXTMSG(sc->sc_imsg[0]) &&
    697  1.1   tsubai 	    sc->sc_imsglen == sc->sc_imsg[1] + 2)
    698  1.1   tsubai 		goto gotit;
    699  1.1   tsubai 
    700  1.1   tsubai 	sc->sc_nextstate = MESH_MSGIN;
    701  1.1   tsubai 	MESH_SET_XFER(sc, 1);
    702  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGIN);
    703  1.1   tsubai 	return;
    704  1.1   tsubai 
    705  1.1   tsubai gotit:
    706  1.6   tsubai #ifdef MESH_DEBUG
    707  1.1   tsubai 	printf("msgin:");
    708  1.1   tsubai 	for (i = 0; i < sc->sc_imsglen; i++)
    709  1.1   tsubai 		printf(" 0x%02x", sc->sc_imsg[i]);
    710  1.1   tsubai 	printf("\n");
    711  1.1   tsubai #endif
    712  1.1   tsubai 
    713  1.1   tsubai 	switch (sc->sc_imsg[0]) {
    714  1.1   tsubai 	case MSG_CMDCOMPLETE:
    715  1.1   tsubai 		mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
    716  1.1   tsubai 		sc->sc_nextstate = MESH_COMPLETE;
    717  1.1   tsubai 		sc->sc_imsglen = 0;
    718  1.1   tsubai 		return;
    719  1.1   tsubai 
    720  1.1   tsubai 	case MSG_MESSAGE_REJECT:
    721  1.6   tsubai 		if (sc->sc_msgout & SEND_SDTR) {
    722  1.1   tsubai 			printf("SDTR rejected\n");
    723  1.1   tsubai 			printf("using async mode\n");
    724  1.1   tsubai 			sc->sc_tinfo[scb->target].period = 0;
    725  1.1   tsubai 			sc->sc_tinfo[scb->target].offset = 0;
    726  1.1   tsubai 			mesh_setsync(sc, &sc->sc_tinfo[scb->target]);
    727  1.1   tsubai 			break;
    728  1.1   tsubai 		}
    729  1.1   tsubai 		break;
    730  1.1   tsubai 
    731  1.1   tsubai 	case MSG_NOOP:
    732  1.1   tsubai 		break;
    733  1.1   tsubai 
    734  1.1   tsubai 	case MSG_EXTENDED:
    735  1.1   tsubai 		goto extended_msg;
    736  1.1   tsubai 
    737  1.1   tsubai 	default:
    738  1.1   tsubai 		scsi_print_addr(scb->xs->sc_link);
    739  1.1   tsubai 		printf("unrecognized MESSAGE(0x%02x); sending REJECT\n",
    740  1.1   tsubai 			sc->sc_imsg[0]);
    741  1.1   tsubai 
    742  1.1   tsubai 	reject:
    743  1.1   tsubai 		mesh_msgout(sc, SEND_REJECT);
    744  1.1   tsubai 		return;
    745  1.1   tsubai 	}
    746  1.1   tsubai 	goto done;
    747  1.1   tsubai 
    748  1.1   tsubai extended_msg:
    749  1.1   tsubai 	/* process an extended message */
    750  1.1   tsubai 	switch (sc->sc_imsg[2]) {
    751  1.1   tsubai 	case MSG_EXT_SDTR:
    752  1.1   tsubai 	  {
    753  1.1   tsubai 		struct mesh_tinfo *ti = &sc->sc_tinfo[scb->target];
    754  1.1   tsubai 		int period = sc->sc_imsg[3];
    755  1.1   tsubai 		int offset = sc->sc_imsg[4];
    756  1.1   tsubai 		int r = 250 / period;
    757  1.1   tsubai 		int s = (100*250) / period - 100 * r;
    758  1.1   tsubai 
    759  1.1   tsubai 		if (period < sc->sc_minsync) {
    760  1.1   tsubai 			ti->period = sc->sc_minsync;
    761  1.1   tsubai 			ti->offset = 15;
    762  1.1   tsubai 			mesh_msgout(sc, SEND_SDTR);
    763  1.1   tsubai 			return;
    764  1.1   tsubai 		}
    765  1.1   tsubai 		scsi_print_addr(scb->xs->sc_link);
    766  1.1   tsubai 		/* XXX if (offset != 0) ... */
    767  1.1   tsubai 		printf("max sync rate %d.%02dMb/s\n", r, s);
    768  1.1   tsubai 		ti->period = period;
    769  1.1   tsubai 		ti->offset = offset;
    770  1.1   tsubai 		ti->flags |= T_SYNCNEGO;
    771  1.1   tsubai 		ti->flags |= T_SYNCMODE;
    772  1.1   tsubai 		mesh_setsync(sc, ti);
    773  1.1   tsubai 		goto done;
    774  1.1   tsubai 	  }
    775  1.1   tsubai 	default:
    776  1.1   tsubai 		printf("%s target %d: rejecting extended message 0x%x\n",
    777  1.1   tsubai 			sc->sc_dev.dv_xname, scb->target, sc->sc_imsg[0]);
    778  1.1   tsubai 		goto reject;
    779  1.1   tsubai 	}
    780  1.1   tsubai 
    781  1.1   tsubai done:
    782  1.1   tsubai 	sc->sc_imsglen = 0;
    783  1.1   tsubai 	sc->sc_nextstate = MESH_UNKNOWN;
    784  1.1   tsubai 
    785  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE); /* XXX really? */
    786  1.1   tsubai }
    787  1.1   tsubai 
    788  1.1   tsubai void
    789  1.1   tsubai mesh_msgout(sc, msg)
    790  1.1   tsubai 	struct mesh_softc *sc;
    791  1.1   tsubai 	int msg;
    792  1.1   tsubai {
    793  1.1   tsubai 	struct mesh_scb *scb = sc->sc_nexus;
    794  1.1   tsubai 	struct mesh_tinfo *ti;
    795  1.6   tsubai 	int lun, len, i;
    796  1.6   tsubai 
    797  1.6   tsubai 	DPRINTF("mesh_msgout: sending");
    798  1.6   tsubai 
    799  1.6   tsubai 	sc->sc_msgout = msg;
    800  1.6   tsubai 	len = 0;
    801  1.1   tsubai 
    802  1.6   tsubai 	if (msg & SEND_REJECT) {
    803  1.6   tsubai 		DPRINTF(" REJECT");
    804  1.6   tsubai 		sc->sc_omsg[len++] = MSG_MESSAGE_REJECT;
    805  1.6   tsubai 	}
    806  1.6   tsubai 	if (msg & SEND_IDENTIFY) {
    807  1.6   tsubai 		DPRINTF(" IDENTIFY");
    808  1.1   tsubai 		lun = scb->xs->sc_link->scsipi_scsi.lun;
    809  1.6   tsubai 		sc->sc_omsg[len++] = MSG_IDENTIFY(lun, 0);
    810  1.6   tsubai 	}
    811  1.6   tsubai 	if (msg & SEND_SDTR) {
    812  1.6   tsubai 		DPRINTF(" SDTR");
    813  1.1   tsubai 		ti = &sc->sc_tinfo[scb->target];
    814  1.6   tsubai 		sc->sc_omsg[len++] = MSG_EXTENDED;
    815  1.6   tsubai 		sc->sc_omsg[len++] = 3;
    816  1.6   tsubai 		sc->sc_omsg[len++] = MSG_EXT_SDTR;
    817  1.6   tsubai 		sc->sc_omsg[len++] = ti->period;
    818  1.6   tsubai 		sc->sc_omsg[len++] = ti->offset;
    819  1.6   tsubai 	}
    820  1.6   tsubai 	DPRINTF("\n");
    821  1.6   tsubai 
    822  1.6   tsubai 	MESH_SET_XFER(sc, len);
    823  1.6   tsubai 	if (len == 1) {
    824  1.6   tsubai 		mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT);
    825  1.6   tsubai 		mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[0]);
    826  1.6   tsubai 	} else {
    827  1.6   tsubai 		mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_MSGOUT | MESH_SEQ_ATN);
    828  1.6   tsubai 
    829  1.6   tsubai 		for (i = 0; i < len - 1; i++)
    830  1.6   tsubai 			mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
    831  1.1   tsubai 
    832  1.6   tsubai 		/* Wait for the FIFO empty... */
    833  1.6   tsubai 		while (mesh_read_reg(sc, MESH_FIFO_COUNT) > 0);
    834  1.1   tsubai 
    835  1.6   tsubai 		/* ...then write the last byte. */
    836  1.1   tsubai 		mesh_set_reg(sc, MESH_FIFO, sc->sc_omsg[i]);
    837  1.6   tsubai 	}
    838  1.1   tsubai 	sc->sc_nextstate = MESH_UNKNOWN;
    839  1.1   tsubai }
    840  1.1   tsubai 
    841  1.1   tsubai void
    842  1.1   tsubai mesh_bus_reset(sc)
    843  1.1   tsubai 	struct mesh_softc *sc;
    844  1.1   tsubai {
    845  1.6   tsubai 	DPRINTF("mesh_bus_reset\n");
    846  1.6   tsubai 
    847  1.1   tsubai 	/* Disable interrupts. */
    848  1.1   tsubai 	mesh_set_reg(sc, MESH_INTR_MASK, 0);
    849  1.1   tsubai 
    850  1.1   tsubai 	/* Assert RST line. */
    851  1.1   tsubai 	mesh_set_reg(sc, MESH_BUS_STATUS1, MESH_STATUS1_RST);
    852  1.1   tsubai 	delay(50);
    853  1.1   tsubai 	mesh_set_reg(sc, MESH_BUS_STATUS1, 0);
    854  1.1   tsubai 
    855  1.1   tsubai 	mesh_reset(sc);
    856  1.1   tsubai }
    857  1.1   tsubai 
    858  1.1   tsubai void
    859  1.1   tsubai mesh_reset(sc)
    860  1.1   tsubai 	struct mesh_softc *sc;
    861  1.1   tsubai {
    862  1.1   tsubai 	int i;
    863  1.1   tsubai 
    864  1.6   tsubai 	DPRINTF("mesh_reset\n");
    865  1.6   tsubai 
    866  1.1   tsubai 	/* Reset DMA first. */
    867  1.1   tsubai 	dbdma_reset(sc->sc_dmareg);
    868  1.1   tsubai 
    869  1.1   tsubai 	/* Disable interrupts. */
    870  1.1   tsubai 	mesh_set_reg(sc, MESH_INTR_MASK, 0);
    871  1.1   tsubai 
    872  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_RESET_MESH);
    873  1.1   tsubai 	delay(1);
    874  1.1   tsubai 
    875  1.1   tsubai 	/* Wait for reset done. */
    876  1.1   tsubai 	while (mesh_read_reg(sc, MESH_INTERRUPT) == 0);
    877  1.1   tsubai 
    878  1.1   tsubai 	/* Clear interrupts */
    879  1.1   tsubai 	mesh_set_reg(sc, MESH_INTERRUPT, 0x7);
    880  1.1   tsubai 
    881  1.1   tsubai 	/* Set SCSI ID */
    882  1.1   tsubai 	mesh_set_reg(sc, MESH_SOURCE_ID, sc->sc_id);
    883  1.1   tsubai 
    884  1.1   tsubai 	/* Set to async mode by default. */
    885  1.1   tsubai 	mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
    886  1.1   tsubai 
    887  1.1   tsubai 	/* Set selection timeout to 250ms. */
    888  1.1   tsubai 	mesh_set_reg(sc, MESH_SEL_TIMEOUT, 250 * sc->sc_freq / 500);
    889  1.1   tsubai 
    890  1.1   tsubai 	/* Enable parity check. */
    891  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_ENABLE_PARITY);
    892  1.1   tsubai 
    893  1.1   tsubai 	/* Enable all interrupts. */
    894  1.1   tsubai 	mesh_set_reg(sc, MESH_INTR_MASK, 0x7);
    895  1.1   tsubai 
    896  1.1   tsubai 	for (i = 0; i < 7; i++) {
    897  1.1   tsubai 		struct mesh_tinfo *ti = &sc->sc_tinfo[i];
    898  1.1   tsubai 
    899  1.1   tsubai 		ti->flags = 0;
    900  1.1   tsubai 		ti->period = ti->offset = 0;
    901  1.6   tsubai 		if (sc->sc_cfflags & (0x100 << i))
    902  1.1   tsubai 			ti->flags |= T_SYNCNEGO;
    903  1.1   tsubai 	}
    904  1.1   tsubai 	sc->sc_nexus = NULL;
    905  1.1   tsubai }
    906  1.1   tsubai 
    907  1.1   tsubai int
    908  1.1   tsubai mesh_stp(sc, v)
    909  1.1   tsubai 	struct mesh_softc *sc;
    910  1.1   tsubai 	int v;
    911  1.1   tsubai {
    912  1.1   tsubai 	/*
    913  1.1   tsubai 	 * stp(v) = 5 * clock_period         (v == 0)
    914  1.1   tsubai 	 *        = (v + 2) * 2 clock_period (v > 0)
    915  1.1   tsubai 	 */
    916  1.1   tsubai 
    917  1.1   tsubai 	if (v == 0)
    918  1.1   tsubai 		return 5 * 250 / sc->sc_freq;
    919  1.1   tsubai 	else
    920  1.1   tsubai 		return (v + 2) * 2 * 250 / sc->sc_freq;
    921  1.1   tsubai }
    922  1.1   tsubai 
    923  1.1   tsubai void
    924  1.1   tsubai mesh_setsync(sc, ti)
    925  1.1   tsubai 	struct mesh_softc *sc;
    926  1.1   tsubai 	struct mesh_tinfo *ti;
    927  1.1   tsubai {
    928  1.1   tsubai 	int period = ti->period;
    929  1.1   tsubai 	int offset = ti->offset;
    930  1.1   tsubai 	int v;
    931  1.1   tsubai 
    932  1.1   tsubai 	if ((ti->flags & T_SYNCMODE) == 0)
    933  1.1   tsubai 		offset = 0;
    934  1.1   tsubai 
    935  1.1   tsubai 	if (offset == 0) {	/* async mode */
    936  1.1   tsubai 		mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
    937  1.1   tsubai 		return;
    938  1.1   tsubai 	}
    939  1.1   tsubai 
    940  1.1   tsubai 	v = period * sc->sc_freq / 250 / 2 - 2;
    941  1.1   tsubai 	if (v < 0)
    942  1.1   tsubai 		v = 0;
    943  1.1   tsubai 	if (mesh_stp(sc, v) < period)
    944  1.1   tsubai 		v++;
    945  1.1   tsubai 	if (v > 15)
    946  1.1   tsubai 		v = 15;
    947  1.1   tsubai 	mesh_set_reg(sc, MESH_SYNC_PARAM, (offset << 4) | v);
    948  1.1   tsubai }
    949  1.1   tsubai 
    950  1.1   tsubai struct mesh_scb *
    951  1.1   tsubai mesh_get_scb(sc)
    952  1.1   tsubai 	struct mesh_softc *sc;
    953  1.1   tsubai {
    954  1.1   tsubai 	struct mesh_scb *scb;
    955  1.1   tsubai 	int s;
    956  1.1   tsubai 
    957  1.1   tsubai 	s = splbio();
    958  1.6   tsubai 	if ((scb = sc->free_scb.tqh_first) != NULL)
    959  1.6   tsubai 		TAILQ_REMOVE(&sc->free_scb, scb, chain);
    960  1.1   tsubai 	splx(s);
    961  1.1   tsubai 
    962  1.1   tsubai 	return scb;
    963  1.1   tsubai }
    964  1.1   tsubai 
    965  1.1   tsubai void
    966  1.1   tsubai mesh_free_scb(sc, scb)
    967  1.1   tsubai 	struct mesh_softc *sc;
    968  1.1   tsubai 	struct mesh_scb *scb;
    969  1.1   tsubai {
    970  1.1   tsubai 	int s;
    971  1.1   tsubai 
    972  1.1   tsubai 	s = splbio();
    973  1.1   tsubai 	TAILQ_INSERT_HEAD(&sc->free_scb, scb, chain);
    974  1.1   tsubai 	splx(s);
    975  1.1   tsubai }
    976  1.1   tsubai 
    977  1.1   tsubai int
    978  1.1   tsubai mesh_scsi_cmd(xs)
    979  1.1   tsubai 	struct scsipi_xfer *xs;
    980  1.1   tsubai {
    981  1.1   tsubai 	struct scsipi_link *sc_link = xs->sc_link;
    982  1.1   tsubai 	struct mesh_softc *sc = sc_link->adapter_softc;
    983  1.1   tsubai 	struct mesh_scb *scb;
    984  1.6   tsubai 	u_int flags = xs->xs_control;
    985  1.1   tsubai 	int s;
    986  1.1   tsubai 
    987  1.6   tsubai 	if ((scb = mesh_get_scb(sc)) == NULL)
    988  1.6   tsubai 		return TRY_AGAIN_LATER;
    989  1.1   tsubai 	scb->xs = xs;
    990  1.1   tsubai 	scb->flags = 0;
    991  1.1   tsubai 	scb->status = 0;
    992  1.1   tsubai 	scb->daddr = (vaddr_t)xs->data;
    993  1.1   tsubai 	scb->dlen = xs->datalen;
    994  1.1   tsubai 	scb->resid = xs->datalen;
    995  1.1   tsubai 	bcopy(xs->cmd, &scb->cmd, xs->cmdlen);
    996  1.1   tsubai 	scb->cmdlen = xs->cmdlen;
    997  1.1   tsubai 	scb->target = sc_link->scsipi_scsi.target;
    998  1.1   tsubai 	sc->sc_imsglen = 0;	/* XXX ? */
    999  1.1   tsubai 
   1000  1.6   tsubai #ifdef MESH_DEBUG
   1001  1.6   tsubai {
   1002  1.6   tsubai 	int i;
   1003  1.6   tsubai 	printf("mesh_scsi_cmd: target = %d, cdb = %02x",
   1004  1.6   tsubai 	       scb->target, scb->cmd.opcode);
   1005  1.6   tsubai 	for (i = 0; i < 5; i++)
   1006  1.6   tsubai 		printf(" %02x", scb->cmd.bytes[i]);
   1007  1.6   tsubai 	printf("\n");
   1008  1.6   tsubai }
   1009  1.6   tsubai #endif
   1010  1.6   tsubai 
   1011  1.2  thorpej 	if (flags & XS_CTL_POLL)
   1012  1.1   tsubai 		scb->flags |= MESH_POLL;
   1013  1.1   tsubai #if 0
   1014  1.2  thorpej 	if (flags & XS_CTL_DATA_OUT)
   1015  1.1   tsubai 		scb->flags &= ~MESH_READ;
   1016  1.1   tsubai #endif
   1017  1.2  thorpej 	if (flags & XS_CTL_DATA_IN)
   1018  1.1   tsubai 		scb->flags |= MESH_READ;
   1019  1.1   tsubai 
   1020  1.1   tsubai 	s = splbio();
   1021  1.1   tsubai 
   1022  1.1   tsubai 	TAILQ_INSERT_TAIL(&sc->ready_scb, scb, chain);
   1023  1.1   tsubai 
   1024  1.1   tsubai 	if (sc->sc_nexus == NULL)	/* IDLE */
   1025  1.1   tsubai 		mesh_sched(sc);
   1026  1.1   tsubai 
   1027  1.1   tsubai 	splx(s);
   1028  1.1   tsubai 
   1029  1.2  thorpej 	if ((flags & XS_CTL_POLL) == 0)
   1030  1.1   tsubai 		return SUCCESSFULLY_QUEUED;
   1031  1.1   tsubai 
   1032  1.1   tsubai 	if (mesh_poll(sc, xs)) {
   1033  1.6   tsubai 		printf("%s: timeout\n", sc->sc_dev.dv_xname);
   1034  1.1   tsubai 		if (mesh_poll(sc, xs))
   1035  1.6   tsubai 			printf("%s: timeout again\n", sc->sc_dev.dv_xname);
   1036  1.1   tsubai 	}
   1037  1.1   tsubai 	return COMPLETE;
   1038  1.1   tsubai }
   1039  1.1   tsubai 
   1040  1.1   tsubai void
   1041  1.1   tsubai mesh_sched(sc)
   1042  1.1   tsubai 	struct mesh_softc *sc;
   1043  1.1   tsubai {
   1044  1.1   tsubai 	struct scsipi_xfer *xs;
   1045  1.1   tsubai 	struct mesh_scb *scb;
   1046  1.1   tsubai 
   1047  1.1   tsubai 	scb = sc->ready_scb.tqh_first;
   1048  1.1   tsubai start:
   1049  1.1   tsubai 	if (scb == NULL)
   1050  1.1   tsubai 		return;
   1051  1.1   tsubai 
   1052  1.1   tsubai 	xs = scb->xs;
   1053  1.1   tsubai 
   1054  1.1   tsubai 	if (sc->sc_nexus == NULL) {
   1055  1.1   tsubai 		TAILQ_REMOVE(&sc->ready_scb, scb, chain);
   1056  1.1   tsubai 		sc->sc_nexus = scb;
   1057  1.1   tsubai 		mesh_select(sc, scb);
   1058  1.1   tsubai 		return;
   1059  1.1   tsubai 	}
   1060  1.1   tsubai 
   1061  1.1   tsubai 	scb = scb->chain.tqe_next;
   1062  1.1   tsubai 	goto start;
   1063  1.1   tsubai }
   1064  1.1   tsubai 
   1065  1.1   tsubai int
   1066  1.1   tsubai mesh_poll(sc, xs)
   1067  1.1   tsubai 	struct mesh_softc *sc;
   1068  1.1   tsubai 	struct scsipi_xfer *xs;
   1069  1.1   tsubai {
   1070  1.1   tsubai 	int count = xs->timeout;
   1071  1.1   tsubai 
   1072  1.1   tsubai 	while (count) {
   1073  1.1   tsubai 		if (mesh_read_reg(sc, MESH_INTERRUPT))
   1074  1.1   tsubai 			mesh_intr(sc);
   1075  1.1   tsubai 
   1076  1.2  thorpej 		if (xs->xs_status & XS_STS_DONE)
   1077  1.1   tsubai 			return 0;
   1078  1.6   tsubai 		delay(1000);
   1079  1.1   tsubai 		count--;
   1080  1.1   tsubai 	};
   1081  1.1   tsubai 	return 1;
   1082  1.1   tsubai }
   1083  1.1   tsubai 
   1084  1.1   tsubai void
   1085  1.1   tsubai mesh_done(sc, scb)
   1086  1.1   tsubai 	struct mesh_softc *sc;
   1087  1.1   tsubai 	struct mesh_scb *scb;
   1088  1.1   tsubai {
   1089  1.1   tsubai 	struct scsipi_xfer *xs = scb->xs;
   1090  1.1   tsubai 
   1091  1.6   tsubai 	DPRINTF("mesh_done\n");
   1092  1.1   tsubai 
   1093  1.1   tsubai 	sc->sc_nextstate = MESH_BUSFREE;
   1094  1.1   tsubai 	sc->sc_nexus = NULL;
   1095  1.1   tsubai 
   1096  1.4  thorpej 	callout_stop(&scb->xs->xs_callout);
   1097  1.1   tsubai 
   1098  1.1   tsubai 	if (scb->status == SCSI_BUSY) {
   1099  1.1   tsubai 		xs->error = XS_BUSY;
   1100  1.1   tsubai 		printf("Target busy\n");
   1101  1.1   tsubai 	}
   1102  1.1   tsubai 
   1103  1.1   tsubai 	if (scb->status == SCSI_CHECK) {
   1104  1.6   tsubai 		DPRINTF("mesh_done: CHECK CONDITION\n");
   1105  1.3   tsubai 		if (scb->flags & MESH_SENSE) {
   1106  1.3   tsubai 			printf("mesh: SCSI_CHECK && MESH_SENSE?\n");
   1107  1.3   tsubai 			xs->xs_status |= XS_STS_DONE;
   1108  1.3   tsubai 			xs->error = XS_DRIVER_STUFFUP;
   1109  1.3   tsubai 			scsipi_done(xs);
   1110  1.3   tsubai 			mesh_free_scb(sc, scb);
   1111  1.3   tsubai 			return;
   1112  1.3   tsubai 		}
   1113  1.1   tsubai 		xs->resid = scb->resid;
   1114  1.1   tsubai 		mesh_sense(sc, scb);
   1115  1.1   tsubai 		return;
   1116  1.1   tsubai 	}
   1117  1.1   tsubai 
   1118  1.1   tsubai 	if (xs->error == XS_NOERROR) {
   1119  1.1   tsubai 		xs->status = scb->status;
   1120  1.1   tsubai 		if (scb->flags & MESH_SENSE)
   1121  1.1   tsubai 			xs->error = XS_SENSE;
   1122  1.1   tsubai 		else
   1123  1.1   tsubai 			xs->resid = scb->resid;
   1124  1.1   tsubai 	}
   1125  1.1   tsubai 
   1126  1.6   tsubai #ifdef MESH_DEBUG
   1127  1.6   tsubai 	if (scb->flags & MESH_SENSE) {
   1128  1.6   tsubai 		struct scsipi_sense_data *sp = &xs->sense.scsi_sense;
   1129  1.6   tsubai 		printf("sense: 0x%02x 0x%02x 0x%02x\n",
   1130  1.6   tsubai 		       sp->error_code, sp->segment, sp->flags);
   1131  1.6   tsubai 	}
   1132  1.6   tsubai #endif
   1133  1.6   tsubai 
   1134  1.2  thorpej 	xs->xs_status |= XS_STS_DONE;
   1135  1.1   tsubai 
   1136  1.1   tsubai 	mesh_set_reg(sc, MESH_SYNC_PARAM, 2);
   1137  1.1   tsubai 
   1138  1.2  thorpej 	if ((xs->xs_control & XS_CTL_POLL) == 0)
   1139  1.1   tsubai 		mesh_sched(sc);
   1140  1.1   tsubai 
   1141  1.1   tsubai 	scsipi_done(xs);
   1142  1.1   tsubai 	mesh_free_scb(sc, scb);
   1143  1.1   tsubai }
   1144  1.1   tsubai 
   1145  1.1   tsubai void
   1146  1.1   tsubai mesh_timeout(arg)
   1147  1.1   tsubai 	void *arg;
   1148  1.1   tsubai {
   1149  1.1   tsubai 	struct mesh_scb *scb = arg;
   1150  1.1   tsubai 	struct mesh_softc *sc = scb->xs->sc_link->adapter_softc;
   1151  1.1   tsubai 	int s;
   1152  1.1   tsubai 	int status0, status1;
   1153  1.1   tsubai 	int intr, error, exception;
   1154  1.1   tsubai 
   1155  1.6   tsubai 	printf("%s: timeout state %d\n", sc->sc_dev.dv_xname, sc->sc_nextstate);
   1156  1.1   tsubai 
   1157  1.1   tsubai 	intr = mesh_read_reg(sc, MESH_INTERRUPT);
   1158  1.1   tsubai 	exception = mesh_read_reg(sc, MESH_EXCEPTION);
   1159  1.1   tsubai 	error = mesh_read_reg(sc, MESH_ERROR);
   1160  1.1   tsubai 	status0 = mesh_read_reg(sc, MESH_BUS_STATUS0);
   1161  1.1   tsubai 	status1 = mesh_read_reg(sc, MESH_BUS_STATUS1);
   1162  1.1   tsubai 
   1163  1.1   tsubai 	s = splbio();
   1164  1.1   tsubai 	if (sc->sc_flags & MESH_DMA_ACTIVE) {
   1165  1.1   tsubai 		printf("mesh: resetting dma\n");
   1166  1.1   tsubai 		dbdma_reset(sc->sc_dmareg);
   1167  1.1   tsubai 	}
   1168  1.1   tsubai 	scb->xs->error = XS_TIMEOUT;
   1169  1.1   tsubai 
   1170  1.1   tsubai 	mesh_set_reg(sc, MESH_SEQUENCE, MESH_CMD_BUSFREE);
   1171  1.1   tsubai 	sc->sc_nextstate = MESH_COMPLETE;
   1172  1.1   tsubai 
   1173  1.1   tsubai 	splx(s);
   1174  1.1   tsubai }
   1175  1.1   tsubai 
   1176  1.1   tsubai void
   1177  1.1   tsubai mesh_sense(sc, scb)
   1178  1.1   tsubai 	struct mesh_softc *sc;
   1179  1.1   tsubai 	struct mesh_scb *scb;
   1180  1.1   tsubai {
   1181  1.1   tsubai 	struct scsipi_xfer *xs = scb->xs;
   1182  1.1   tsubai 	struct scsipi_link *sc_link = xs->sc_link;
   1183  1.1   tsubai 	struct scsipi_sense *ss = (void *)&scb->cmd;
   1184  1.1   tsubai 
   1185  1.6   tsubai 	DPRINTF("mesh_sense\n");
   1186  1.1   tsubai 	bzero(ss, sizeof(*ss));
   1187  1.1   tsubai 	ss->opcode = REQUEST_SENSE;
   1188  1.1   tsubai 	ss->byte2 = sc_link->scsipi_scsi.lun << 5;
   1189  1.1   tsubai 	ss->length = sizeof(struct scsipi_sense_data);
   1190  1.1   tsubai 	scb->cmdlen = sizeof(*ss);
   1191  1.1   tsubai 	scb->daddr = (vaddr_t)&xs->sense.scsi_sense;
   1192  1.1   tsubai 	scb->dlen = sizeof(struct scsipi_sense_data);
   1193  1.1   tsubai 	scb->resid = scb->dlen;
   1194  1.1   tsubai 	bzero((void *)scb->daddr, scb->dlen);
   1195  1.1   tsubai 
   1196  1.1   tsubai 	scb->flags |= MESH_SENSE | MESH_READ;
   1197  1.1   tsubai 
   1198  1.1   tsubai 	TAILQ_INSERT_HEAD(&sc->ready_scb, scb, chain);
   1199  1.1   tsubai 	if (sc->sc_nexus == NULL)
   1200  1.1   tsubai 		mesh_sched(sc);
   1201  1.1   tsubai }
   1202  1.1   tsubai 
   1203  1.1   tsubai void
   1204  1.1   tsubai mesh_minphys(bp)
   1205  1.1   tsubai 	struct buf *bp;
   1206  1.1   tsubai {
   1207  1.1   tsubai 	if (bp->b_bcount > 64*1024)
   1208  1.1   tsubai 		bp->b_bcount = 64*1024;
   1209  1.1   tsubai 
   1210  1.1   tsubai 	minphys(bp);
   1211  1.1   tsubai }
   1212