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