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