esp_sbus.c revision 1.22
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
57struct 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
64struct 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
73static int esp_unit_offset;
74
75struct 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
87void	espattach_sbus(struct device *, struct device *, void *);
88void	espattach_dma(struct device *, struct device *, void *);
89int	espmatch_sbus(struct device *, void *, void *);
90
91
92/* Linkup to the rest of the kernel */
93struct cfattach esp_sbus_ca = {
94	sizeof(struct esp_softc), espmatch_sbus, espattach_sbus
95};
96struct 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 */
103static u_char	esp_read_reg(struct ncr53c9x_softc *, int);
104static void	esp_write_reg(struct ncr53c9x_softc *, int, u_char);
105static u_char	esp_rdreg1(struct ncr53c9x_softc *, int);
106static void	esp_wrreg1(struct ncr53c9x_softc *, int, u_char);
107static int	esp_dma_isintr(struct ncr53c9x_softc *);
108static void	esp_dma_reset(struct ncr53c9x_softc *);
109static int	esp_dma_intr(struct ncr53c9x_softc *);
110static int	esp_dma_setup(struct ncr53c9x_softc *, caddr_t *,
111				    size_t *, int, size_t *);
112static void	esp_dma_go(struct ncr53c9x_softc *);
113static void	esp_dma_stop(struct ncr53c9x_softc *);
114static int	esp_dma_isactive(struct ncr53c9x_softc *);
115
116static 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
129static 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
142static void	espattach(struct esp_softc *, struct ncr53c9x_glue *);
143
144int
145espmatch_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
159void
160espattach_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
346void
347espattach_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 */
405void
406espattach(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
525int esp_sbus_debug = 0;
526
527static 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
549static 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
572u_char
573esp_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
587void
588esp_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
600u_char
601esp_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
608void
609esp_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
616int
617esp_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
624void
625esp_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
632int
633esp_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
640int
641esp_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
649void
650esp_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
657void
658esp_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
668int
669esp_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
680void db_esp(db_expr_t, int, db_expr_t, char *);
681
682void
683db_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