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