xref: /openbsd-src/sys/dev/sbus/esp_sbus.c (revision 2b0358df1d88d06ef4139321dd05bd5e05d91eaf)
1 /*	$OpenBSD: esp_sbus.c,v 1.22 2009/02/16 21:19:07 miod Exp $	*/
2 /*	$NetBSD: esp_sbus.c,v 1.14 2001/04/25 17:53:37 bouyer Exp $	*/
3 
4 /*-
5  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to The NetBSD Foundation
9  * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
10  * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/device.h>
38 #include <sys/buf.h>
39 #include <sys/malloc.h>
40 
41 #include <scsi/scsi_all.h>
42 #include <scsi/scsiconf.h>
43 #include <scsi/scsi_message.h>
44 
45 #include <machine/bus.h>
46 #include <machine/intr.h>
47 #include <machine/autoconf.h>
48 
49 #include <dev/ic/lsi64854reg.h>
50 #include <dev/ic/lsi64854var.h>
51 
52 #include <dev/ic/ncr53c9xreg.h>
53 #include <dev/ic/ncr53c9xvar.h>
54 
55 #include <dev/sbus/sbusvar.h>
56 
57 struct scsi_adapter esp_switch = {
58 	ncr53c9x_scsi_cmd,
59 	scsi_minphys,		/* no max at this level; handled by DMA code */
60 	NULL,
61 	NULL,
62 };
63 
64 struct scsi_device esp_dev = {
65 	NULL,			/* Use default error handler */
66 	NULL,			/* have a queue, served by this */
67 	NULL,			/* have no async handler */
68 	NULL,			/* Use default 'done' routine */
69 };
70 
71 /* #define ESP_SBUS_DEBUG */
72 
73 static int esp_unit_offset;
74 
75 struct esp_softc {
76 	struct ncr53c9x_softc sc_ncr53c9x;	/* glue to MI code */
77 
78 	bus_space_tag_t	sc_bustag;
79 	bus_dma_tag_t	sc_dmatag;
80 
81 	bus_space_handle_t sc_reg;		/* the registers */
82 	struct lsi64854_softc *sc_dma;		/* pointer to my dma */
83 
84 	int	sc_pri;				/* SBUS priority */
85 };
86 
87 void	espattach_sbus(struct device *, struct device *, void *);
88 void	espattach_dma(struct device *, struct device *, void *);
89 int	espmatch_sbus(struct device *, void *, void *);
90 
91 
92 /* Linkup to the rest of the kernel */
93 struct cfattach esp_sbus_ca = {
94 	sizeof(struct esp_softc), espmatch_sbus, espattach_sbus
95 };
96 struct cfattach esp_dma_ca = {
97 	sizeof(struct esp_softc), espmatch_sbus, espattach_dma
98 };
99 
100 /*
101  * Functions and the switch for the MI code.
102  */
103 static u_char	esp_read_reg(struct ncr53c9x_softc *, int);
104 static void	esp_write_reg(struct ncr53c9x_softc *, int, u_char);
105 static u_char	esp_rdreg1(struct ncr53c9x_softc *, int);
106 static void	esp_wrreg1(struct ncr53c9x_softc *, int, u_char);
107 static int	esp_dma_isintr(struct ncr53c9x_softc *);
108 static void	esp_dma_reset(struct ncr53c9x_softc *);
109 static int	esp_dma_intr(struct ncr53c9x_softc *);
110 static int	esp_dma_setup(struct ncr53c9x_softc *, caddr_t *,
111 				    size_t *, int, size_t *);
112 static void	esp_dma_go(struct ncr53c9x_softc *);
113 static void	esp_dma_stop(struct ncr53c9x_softc *);
114 static int	esp_dma_isactive(struct ncr53c9x_softc *);
115 
116 static struct ncr53c9x_glue esp_sbus_glue = {
117 	esp_read_reg,
118 	esp_write_reg,
119 	esp_dma_isintr,
120 	esp_dma_reset,
121 	esp_dma_intr,
122 	esp_dma_setup,
123 	esp_dma_go,
124 	esp_dma_stop,
125 	esp_dma_isactive,
126 	NULL,			/* gl_clear_latched_intr */
127 };
128 
129 static struct ncr53c9x_glue esp_sbus_glue1 = {
130 	esp_rdreg1,
131 	esp_wrreg1,
132 	esp_dma_isintr,
133 	esp_dma_reset,
134 	esp_dma_intr,
135 	esp_dma_setup,
136 	esp_dma_go,
137 	esp_dma_stop,
138 	esp_dma_isactive,
139 	NULL,			/* gl_clear_latched_intr */
140 };
141 
142 static void	espattach(struct esp_softc *, struct ncr53c9x_glue *);
143 
144 int
145 espmatch_sbus(struct device *parent, void *vcf, void *aux)
146 {
147 	struct cfdata *cf = vcf;
148 	int rv;
149 	struct sbus_attach_args *sa = aux;
150 
151 	if (strcmp("SUNW,fas", sa->sa_name) == 0)
152 	        return 1;
153 
154 	rv = (strcmp(cf->cf_driver->cd_name, sa->sa_name) == 0 ||
155 	    strcmp("ptscII", sa->sa_name) == 0);
156 	return (rv);
157 }
158 
159 void
160 espattach_sbus(struct device *parent, struct device *self, void *aux)
161 {
162 	struct esp_softc *esc = (void *)self;
163 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
164 	struct sbus_attach_args *sa = aux;
165 	struct lsi64854_softc *lsc;
166 	int burst, sbusburst;
167 
168 	esc->sc_bustag = sa->sa_bustag;
169 	esc->sc_dmatag = sa->sa_dmatag;
170 
171 	sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
172 	sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
173 	if (sc->sc_freq < 0)
174 		sc->sc_freq = sa->sa_frequency;
175 
176 #ifdef ESP_SBUS_DEBUG
177 	printf("%s: espattach_sbus: sc_id %d, freq %d\n",
178 	       self->dv_xname, sc->sc_id, sc->sc_freq);
179 #endif
180 
181 	if (strcmp("SUNW,fas", sa->sa_name) == 0) {
182 		/*
183 		 * offset searches for other esp/dma devices.
184 		 */
185 		esp_unit_offset++;
186 
187 		/*
188 		 * fas has 2 register spaces: dma(lsi64854) and SCSI core (ncr53c9x)
189 		 */
190 		if (sa->sa_nreg != 2) {
191 			printf("%s: %d register spaces\n", self->dv_xname, sa->sa_nreg);
192 			return;
193 		}
194 
195 		/*
196 		 * allocate space for dma, in SUNW,fas there are no separate
197 		 * dma device
198 		 */
199 		lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF, M_NOWAIT);
200 
201 		if (lsc == NULL) {
202 			printf("%s: out of memory (lsi64854_softc)\n",
203 			       self->dv_xname);
204 			return;
205 		}
206 		esc->sc_dma = lsc;
207 
208 		lsc->sc_bustag = sa->sa_bustag;
209 		lsc->sc_dmatag = sa->sa_dmatag;
210 
211 		bcopy(sc->sc_dev.dv_xname, lsc->sc_dev.dv_xname,
212 		      sizeof (lsc->sc_dev.dv_xname));
213 
214 		/* Map dma registers */
215 		if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[0].sbr_slot,
216 		    sa->sa_reg[0].sbr_offset, sa->sa_reg[0].sbr_size,
217 		    0, 0, &lsc->sc_regs) != 0) {
218 			printf("%s: cannot map dma registers\n", self->dv_xname);
219 			return;
220 		}
221 
222 		/*
223 		 * XXX is this common(from bpp.c), the same in dma_sbus...etc.
224 		 *
225 		 * Get transfer burst size from PROM and plug it into the
226 		 * controller registers. This is needed on the Sun4m; do
227 		 * others need it too?
228 		 */
229 		sbusburst = ((struct sbus_softc *)parent)->sc_burst;
230 		if (sbusburst == 0)
231 			sbusburst = SBUS_BURST_32 - 1; /* 1->16 */
232 
233 		burst = getpropint(sa->sa_node, "burst-sizes", -1);
234 
235 #ifdef ESP_SBUS_DEBUG
236 		printf("espattach_sbus: burst 0x%x, sbus 0x%x\n",
237 		    burst, sbusburst);
238 #endif
239 
240 		if (burst == -1)
241 			/* take SBus burst sizes */
242 			burst = sbusburst;
243 
244 		/* Clamp at parent's burst sizes */
245 		burst &= sbusburst;
246 		lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
247 		    (burst & SBUS_BURST_16) ? 16 : 0;
248 
249 		lsc->sc_channel = L64854_CHANNEL_SCSI;
250 		lsc->sc_client = sc;
251 
252 		lsi64854_attach(lsc);
253 
254 		/*
255 		 * map SCSI core registers
256 		 */
257 		if (sbus_bus_map(sa->sa_bustag, sa->sa_reg[1].sbr_slot,
258 		    sa->sa_reg[1].sbr_offset, sa->sa_reg[1].sbr_size,
259 		    0, 0, &esc->sc_reg) != 0) {
260 			printf("%s: cannot map scsi core registers\n",
261 			       self->dv_xname);
262 			return;
263 		}
264 
265 		if (sa->sa_nintr == 0) {
266 			printf("%s: no interrupt property\n", self->dv_xname);
267 			return;
268 		}
269 
270 		esc->sc_pri = sa->sa_pri;
271 
272 		printf("%s", self->dv_xname);
273 		espattach(esc, &esp_sbus_glue);
274 
275 		return;
276 	}
277 
278 	/*
279 	 * Find the DMA by poking around the dma device structures
280 	 *
281 	 * What happens here is that if the dma driver has not been
282 	 * configured, then this returns a NULL pointer. Then when the
283 	 * dma actually gets configured, it does the opposing test, and
284 	 * if the sc->sc_esp field in its softc is NULL, then tries to
285 	 * find the matching esp driver.
286 	 */
287 	esc->sc_dma = (struct lsi64854_softc *)
288 	    getdevunit("dma", sc->sc_dev.dv_unit - esp_unit_offset);
289 
290 	/*
291 	 * and a back pointer to us, for DMA
292 	 */
293 	if (esc->sc_dma)
294 		esc->sc_dma->sc_client = sc;
295 	else {
296 		printf("\n");
297 		panic("espattach: no dma found");
298 	}
299 
300 	/*
301 	 * The `ESC' DMA chip must be reset before we can access
302 	 * the esp registers.
303 	 */
304 	if (esc->sc_dma->sc_rev == DMAREV_ESC)
305 		DMA_RESET(esc->sc_dma);
306 
307 	/*
308 	 * Map my registers in, if they aren't already in virtual
309 	 * address space.
310 	 */
311 	if (sa->sa_npromvaddrs) {
312 		if (bus_space_map(sa->sa_bustag, sa->sa_promvaddrs[0],
313 		    sa->sa_size, BUS_SPACE_MAP_PROMADDRESS,
314 		    &esc->sc_reg) != 0) {
315 			printf("%s @ sbus: cannot map registers\n",
316 				self->dv_xname);
317 			return;
318 		}
319 	} else {
320 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
321 		    sa->sa_offset, sa->sa_size, 0, 0, &esc->sc_reg) != 0) {
322 			printf("%s @ sbus: cannot map registers\n",
323 				self->dv_xname);
324 			return;
325 		}
326 	}
327 
328 	if (sa->sa_nintr == 0) {
329 		/*
330 		 * No interrupt properties: we quit; this might
331 		 * happen on e.g. a Sparc X terminal.
332 		 */
333 		printf("\n%s: no interrupt property\n", self->dv_xname);
334 		return;
335 	}
336 
337 	esc->sc_pri = sa->sa_pri;
338 
339 	if (strcmp("ptscII", sa->sa_name) == 0) {
340 		espattach(esc, &esp_sbus_glue1);
341 	} else {
342 		espattach(esc, &esp_sbus_glue);
343 	}
344 }
345 
346 void
347 espattach_dma(struct device *parent, struct device *self, void *aux)
348 {
349 	struct esp_softc *esc = (void *)self;
350 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
351 	struct sbus_attach_args *sa = aux;
352 
353 	if (strcmp("ptscII", sa->sa_name) == 0) {
354 		return;
355 	}
356 
357 	esc->sc_bustag = sa->sa_bustag;
358 	esc->sc_dmatag = sa->sa_dmatag;
359 
360 	sc->sc_id = getpropint(sa->sa_node, "initiator-id", 7);
361 	sc->sc_freq = getpropint(sa->sa_node, "clock-frequency", -1);
362 
363 	esc->sc_dma = (struct lsi64854_softc *)parent;
364 	esc->sc_dma->sc_client = sc;
365 
366 	/*
367 	 * Map my registers in, if they aren't already in virtual
368 	 * address space.
369 	 */
370 	if (sa->sa_npromvaddrs) {
371 		if (bus_space_map(sa->sa_bustag, sa->sa_promvaddrs[0],
372 		    sa->sa_size /* ??? */, BUS_SPACE_MAP_PROMADDRESS,
373 		    &esc->sc_reg) != 0) {
374 			printf("%s @ dma: cannot map registers\n",
375 				self->dv_xname);
376 			return;
377 		}
378 	} else {
379 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, sa->sa_offset,
380 		    sa->sa_size, 0, 0, &esc->sc_reg) != 0) {
381 			printf("%s @ dma: cannot map registers\n",
382 				self->dv_xname);
383 			return;
384 		}
385 	}
386 
387 	if (sa->sa_nintr == 0) {
388 		/*
389 		 * No interrupt properties: we quit; this might
390 		 * happen on e.g. a Sparc X terminal.
391 		 */
392 		printf("\n%s: no interrupt property\n", self->dv_xname);
393 		return;
394 	}
395 
396 	esc->sc_pri = sa->sa_pri;
397 
398 	espattach(esc, &esp_sbus_glue);
399 }
400 
401 
402 /*
403  * Attach this instance, and then all the sub-devices
404  */
405 void
406 espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
407 {
408 	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
409 	void *icookie;
410 	unsigned int uid = 0;
411 
412 	/*
413 	 * Set up glue for MI code early; we use some of it here.
414 	 */
415 	sc->sc_glue = gluep;
416 
417 	/* gimme MHz */
418 	sc->sc_freq /= 1000000;
419 
420 	/*
421 	 * XXX More of this should be in ncr53c9x_attach(), but
422 	 * XXX should we really poke around the chip that much in
423 	 * XXX the MI code?  Think about this more...
424 	 */
425 
426 	/*
427 	 * It is necessary to try to load the 2nd config register here,
428 	 * to find out what rev the esp chip is, else the ncr53c9x_reset
429 	 * will not set up the defaults correctly.
430 	 */
431 	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
432 	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
433 	sc->sc_cfg3 = NCRCFG3_CDB;
434 	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
435 
436 	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
437 	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
438 		sc->sc_rev = NCR_VARIANT_ESP100;
439 	} else {
440 		sc->sc_cfg2 = NCRCFG2_SCSI2;
441 		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
442 		sc->sc_cfg3 = 0;
443 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
444 		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
445 		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
446 		if (NCR_READ_REG(sc, NCR_CFG3) !=
447 		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
448 			sc->sc_rev = NCR_VARIANT_ESP100A;
449 		} else {
450 			/* NCRCFG2_FE enables > 64K transfers */
451 			sc->sc_cfg2 |= NCRCFG2_FE;
452 			sc->sc_cfg3 = 0;
453 			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
454 			sc->sc_rev = NCR_VARIANT_ESP200;
455 
456 			/* XXX spec says it's valid after power up or chip reset */
457 			uid = NCR_READ_REG(sc, NCR_UID);
458 			if (((uid & 0xf8) >> 3) == 0x0a) /* XXX */
459 				sc->sc_rev = NCR_VARIANT_FAS366;
460 		}
461 	}
462 
463 #ifdef ESP_SBUS_DEBUG
464 	printf("espattach: revision %d, uid 0x%x\n", sc->sc_rev, uid);
465 #endif
466 
467 	/*
468 	 * XXX minsync and maxxfer _should_ be set up in MI code,
469 	 * XXX but it appears to have some dependency on what sort
470 	 * XXX of DMA we're hooked up to, etc.
471 	 */
472 
473 	/*
474 	 * This is the value used to start sync negotiations
475 	 * Note that the NCR register "SYNCTP" is programmed
476 	 * in "clocks per byte", and has a minimum value of 4.
477 	 * The SCSI period used in negotiation is one-fourth
478 	 * of the time (in nanoseconds) needed to transfer one byte.
479 	 * Since the chip's clock is given in MHz, we have the following
480 	 * formula: 4 * period = (1000 / freq) * 4
481 	 */
482 	sc->sc_minsync = 1000 / sc->sc_freq;
483 
484 	/*
485 	 * Alas, we must now modify the value a bit, because it's
486 	 * only valid when can switch on FASTCLK and FASTSCSI bits
487 	 * in config register 3...
488 	 */
489 	switch (sc->sc_rev) {
490 	case NCR_VARIANT_ESP100:
491 		sc->sc_maxxfer = 64 * 1024;
492 		sc->sc_minsync = 0;	/* No synch on old chip? */
493 		break;
494 
495 	case NCR_VARIANT_ESP100A:
496 		sc->sc_maxxfer = 64 * 1024;
497 		/* Min clocks/byte is 5 */
498 		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
499 		break;
500 
501 	case NCR_VARIANT_ESP200:
502 	case NCR_VARIANT_FAS366:
503 		sc->sc_maxxfer = 16 * 1024 * 1024;
504 		/* XXX - do actually set FAST* bits */
505 		break;
506 	}
507 
508 	/* Establish interrupt channel */
509 	icookie = bus_intr_establish(esc->sc_bustag, esc->sc_pri, IPL_BIO, 0,
510 				     ncr53c9x_intr, sc, sc->sc_dev.dv_xname);
511 
512 	/* Turn on target selection using the `dma' method */
513 	if (sc->sc_rev != NCR_VARIANT_FAS366)
514 		sc->sc_features |= NCR_F_DMASELECT;
515 
516 	/* Do the common parts of attachment. */
517 	ncr53c9x_attach(sc, &esp_switch, &esp_dev);
518 }
519 
520 /*
521  * Glue functions.
522  */
523 
524 #ifdef ESP_SBUS_DEBUG
525 int esp_sbus_debug = 0;
526 
527 static struct {
528 	char *r_name;
529 	int   r_flag;
530 } esp__read_regnames [] = {
531 	{ "TCL", 0},			/* 0/00 */
532 	{ "TCM", 0},			/* 1/04 */
533 	{ "FIFO", 0},			/* 2/08 */
534 	{ "CMD", 0},			/* 3/0c */
535 	{ "STAT", 0},			/* 4/10 */
536 	{ "INTR", 0},			/* 5/14 */
537 	{ "STEP", 0},			/* 6/18 */
538 	{ "FFLAGS", 1},			/* 7/1c */
539 	{ "CFG1", 1},			/* 8/20 */
540 	{ "STAT2", 0},			/* 9/24 */
541 	{ "CFG4", 1},			/* a/28 */
542 	{ "CFG2", 1},			/* b/2c */
543 	{ "CFG3", 1},			/* c/30 */
544 	{ "-none", 1},			/* d/34 */
545 	{ "TCH", 1},			/* e/38 */
546 	{ "TCX", 1},			/* f/3c */
547 };
548 
549 static struct {
550 	char *r_name;
551 	int   r_flag;
552 } esp__write_regnames[] = {
553 	{ "TCL", 1},			/* 0/00 */
554 	{ "TCM", 1},			/* 1/04 */
555 	{ "FIFO", 0},			/* 2/08 */
556 	{ "CMD", 0},			/* 3/0c */
557 	{ "SELID", 1},			/* 4/10 */
558 	{ "TIMEOUT", 1},		/* 5/14 */
559 	{ "SYNCTP", 1},			/* 6/18 */
560 	{ "SYNCOFF", 1},		/* 7/1c */
561 	{ "CFG1", 1},			/* 8/20 */
562 	{ "CCF", 1},			/* 9/24 */
563 	{ "TEST", 1},			/* a/28 */
564 	{ "CFG2", 1},			/* b/2c */
565 	{ "CFG3", 1},			/* c/30 */
566 	{ "-none", 1},			/* d/34 */
567 	{ "TCH", 1},			/* e/38 */
568 	{ "TCX", 1},			/* f/3c */
569 };
570 #endif
571 
572 u_char
573 esp_read_reg(struct ncr53c9x_softc *sc, int reg)
574 {
575 	struct esp_softc *esc = (struct esp_softc *)sc;
576 	u_char v;
577 
578 	v = bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg * 4);
579 #ifdef ESP_SBUS_DEBUG
580 	if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
581 		printf("RD:%x <%s> %x\n", reg * 4,
582 		    ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
583 #endif
584 	return v;
585 }
586 
587 void
588 esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v)
589 {
590 	struct esp_softc *esc = (struct esp_softc *)sc;
591 
592 #ifdef ESP_SBUS_DEBUG
593 	if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
594 		printf("WR:%x <%s> %x\n", reg * 4,
595 		    ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
596 #endif
597 	bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg * 4, v);
598 }
599 
600 u_char
601 esp_rdreg1(struct ncr53c9x_softc *sc, int reg)
602 {
603 	struct esp_softc *esc = (struct esp_softc *)sc;
604 
605 	return (bus_space_read_1(esc->sc_bustag, esc->sc_reg, reg));
606 }
607 
608 void
609 esp_wrreg1(struct ncr53c9x_softc *sc, int reg, u_char v)
610 {
611 	struct esp_softc *esc = (struct esp_softc *)sc;
612 
613 	bus_space_write_1(esc->sc_bustag, esc->sc_reg, reg, v);
614 }
615 
616 int
617 esp_dma_isintr(struct ncr53c9x_softc *sc)
618 {
619 	struct esp_softc *esc = (struct esp_softc *)sc;
620 
621 	return (DMA_ISINTR(esc->sc_dma));
622 }
623 
624 void
625 esp_dma_reset(struct ncr53c9x_softc *sc)
626 {
627 	struct esp_softc *esc = (struct esp_softc *)sc;
628 
629 	DMA_RESET(esc->sc_dma);
630 }
631 
632 int
633 esp_dma_intr(struct ncr53c9x_softc *sc)
634 {
635 	struct esp_softc *esc = (struct esp_softc *)sc;
636 
637 	return (DMA_INTR(esc->sc_dma));
638 }
639 
640 int
641 esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
642     int datain, size_t *dmasize)
643 {
644 	struct esp_softc *esc = (struct esp_softc *)sc;
645 
646 	return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
647 }
648 
649 void
650 esp_dma_go(struct ncr53c9x_softc *sc)
651 {
652 	struct esp_softc *esc = (struct esp_softc *)sc;
653 
654 	DMA_GO(esc->sc_dma);
655 }
656 
657 void
658 esp_dma_stop(struct ncr53c9x_softc *sc)
659 {
660 	struct esp_softc *esc = (struct esp_softc *)sc;
661 	u_int32_t csr;
662 
663 	csr = L64854_GCSR(esc->sc_dma);
664 	csr &= ~D_EN_DMA;
665 	L64854_SCSR(esc->sc_dma, csr);
666 }
667 
668 int
669 esp_dma_isactive(struct ncr53c9x_softc *sc)
670 {
671 	struct esp_softc *esc = (struct esp_softc *)sc;
672 
673 	return (DMA_ISACTIVE(esc->sc_dma));
674 }
675 
676 #if defined(DDB) && defined(notyet)
677 #include <machine/db_machdep.h>
678 #include <ddb/db_output.h>
679 
680 void db_esp(db_expr_t, int, db_expr_t, char *);
681 
682 void
683 db_esp(db_expr_t addr, int have_addr, db_expr_t count, char *modif)
684 {
685 	struct ncr53c9x_softc *sc;
686 	struct ncr53c9x_ecb *ecb;
687 	struct ncr53c9x_linfo *li;
688 	int u, t, i;
689 
690 	for (u=0; u<10; u++) {
691 		sc = (struct ncr53c9x_softc *)
692 			getdevunit("esp", u);
693 		if (!sc) continue;
694 
695 		db_printf("esp%d: nexus %p phase %x prev %x dp %p dleft %lx ify %x\n",
696 			  u, sc->sc_nexus, sc->sc_phase, sc->sc_prevphase,
697 			  sc->sc_dp, sc->sc_dleft, sc->sc_msgify);
698 		db_printf("\tmsgout %x msgpriq %x msgin %x:%x:%x:%x:%x\n",
699 			  sc->sc_msgout, sc->sc_msgpriq, sc->sc_imess[0],
700 			  sc->sc_imess[1], sc->sc_imess[2], sc->sc_imess[3],
701 			  sc->sc_imess[0]);
702 		db_printf("ready: ");
703 		TAILQ_FOREACH(ecb, &sc->ready_list, chain) {
704 			db_printf("ecb %p ", ecb);
705 			if (ecb == TAILQ_NEXT(ecb, chain)) {
706 				db_printf("\nWARNING: tailq loop on ecb %p", ecb);
707 				break;
708 			}
709 		}
710 		db_printf("\n");
711 
712 		for (t=0; t<NCR_NTARG; t++) {
713 			LIST_FOREACH(li, &sc->sc_tinfo[t].luns, link) {
714 				db_printf("t%d lun %d untagged %p busy %d used %x\n",
715 					  t, (int)li->lun, li->untagged, li->busy,
716 					  li->used);
717 				for (i=0; i<256; i++)
718 					if ((ecb = li->queued[i])) {
719 						db_printf("ecb %p tag %x\n", ecb, i);
720 					}
721 			}
722 		}
723 	}
724 }
725 #endif
726 
727