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