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