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