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