esp_sbus.c revision 180692
1/*-
2 * Copyright (c) 2004 Scott Long
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28/*	$NetBSD: esp_sbus.c,v 1.31 2005/02/27 00:27:48 perry Exp $	*/
29
30/*-
31 * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
32 * All rights reserved.
33 *
34 * This code is derived from software contributed to The NetBSD Foundation
35 * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
36 * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 *    notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 *    notice, this list of conditions and the following disclaimer in the
45 *    documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 *    must display the following acknowledgement:
48 *	This product includes software developed by the NetBSD
49 *	Foundation, Inc. and its contributors.
50 * 4. Neither the name of The NetBSD Foundation nor the names of its
51 *    contributors may be used to endorse or promote products derived
52 *    from this software without specific prior written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
55 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67#include <sys/cdefs.h>
68__FBSDID("$FreeBSD: head/sys/dev/esp/esp_sbus.c 180692 2008-07-22 13:51:21Z marius $");
69
70#include <sys/param.h>
71#include <sys/systm.h>
72#include <sys/bus.h>
73#include <sys/kernel.h>
74#include <sys/module.h>
75#include <sys/resource.h>
76
77#include <dev/ofw/ofw_bus.h>
78#include <dev/ofw/openfirm.h>
79#include <machine/bus.h>
80#include <machine/resource.h>
81#include <sys/rman.h>
82
83#include <cam/cam.h>
84#include <cam/cam_ccb.h>
85#include <cam/scsi/scsi_all.h>
86
87#include <sparc64/sbus/lsi64854reg.h>
88#include <sparc64/sbus/lsi64854var.h>
89#include <sparc64/sbus/sbusvar.h>
90
91#include <dev/esp/ncr53c9xreg.h>
92#include <dev/esp/ncr53c9xvar.h>
93
94/* #define ESP_SBUS_DEBUG */
95
96struct esp_softc {
97	struct ncr53c9x_softc	sc_ncr53c9x;	/* glue to MI code */
98	struct device		*sc_dev;
99
100	int			sc_rid;
101	struct resource		*sc_res;
102	bus_space_handle_t	sc_regh;
103	bus_space_tag_t		sc_regt;
104
105	int			sc_irqrid;
106	struct resource		*sc_irqres;
107	void			*sc_irq;
108
109	struct lsi64854_softc	*sc_dma;	/* pointer to my DMA */
110};
111
112static devclass_t	esp_devclass;
113
114static int	esp_probe(device_t);
115static int	esp_dma_attach(device_t);
116static int	esp_dma_detach(device_t);
117static int	esp_sbus_attach(device_t);
118static int	esp_sbus_detach(device_t);
119static int	esp_suspend(device_t);
120static int	esp_resume(device_t);
121
122static device_method_t esp_dma_methods[] = {
123	DEVMETHOD(device_probe,		esp_probe),
124	DEVMETHOD(device_attach,	esp_dma_attach),
125	DEVMETHOD(device_detach,	esp_dma_detach),
126	DEVMETHOD(device_suspend,	esp_suspend),
127	DEVMETHOD(device_resume,	esp_resume),
128	{0, 0}
129};
130
131static driver_t esp_dma_driver = {
132	"esp",
133	esp_dma_methods,
134	sizeof(struct esp_softc)
135};
136
137DRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0);
138MODULE_DEPEND(esp, dma, 1, 1, 1);
139
140static device_method_t esp_sbus_methods[] = {
141	DEVMETHOD(device_probe,		esp_probe),
142	DEVMETHOD(device_attach,	esp_sbus_attach),
143	DEVMETHOD(device_detach,	esp_sbus_detach),
144	DEVMETHOD(device_suspend,	esp_suspend),
145	DEVMETHOD(device_resume,	esp_resume),
146	{0, 0}
147};
148
149static driver_t esp_sbus_driver = {
150	"esp",
151	esp_sbus_methods,
152	sizeof(struct esp_softc)
153};
154
155DRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0);
156MODULE_DEPEND(esp, sbus, 1, 1, 1);
157
158MODULE_DEPEND(esp, cam, 1, 1, 1);
159
160/*
161 * Functions and the switch for the MI code
162 */
163static u_char	esp_read_reg(struct ncr53c9x_softc *sc, int reg);
164static void	esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v);
165static int	esp_dma_isintr(struct ncr53c9x_softc *sc);
166static void	esp_dma_reset(struct ncr53c9x_softc *sc);
167static int	esp_dma_intr(struct ncr53c9x_softc *sc);
168static int	esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr,
169		    size_t *len, int datain, size_t *dmasize);
170static void	esp_dma_go(struct ncr53c9x_softc *sc);
171static void	esp_dma_stop(struct ncr53c9x_softc *sc);
172static int	esp_dma_isactive(struct ncr53c9x_softc *sc);
173static int	espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep);
174
175static struct ncr53c9x_glue esp_sbus_glue = {
176	esp_read_reg,
177	esp_write_reg,
178	esp_dma_isintr,
179	esp_dma_reset,
180	esp_dma_intr,
181	esp_dma_setup,
182	esp_dma_go,
183	esp_dma_stop,
184	esp_dma_isactive,
185	NULL,			/* gl_clear_latched_intr */
186};
187
188static int
189esp_probe(device_t dev)
190{
191	const char *name;
192
193	name = ofw_bus_get_name(dev);
194	if (strcmp("SUNW,fas", name) == 0) {
195		device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI");
196	        return (BUS_PROBE_DEFAULT);
197	} else if (strcmp("esp", name) == 0) {
198		device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI");
199	        return (BUS_PROBE_DEFAULT);
200	}
201
202	return (ENXIO);
203}
204
205static int
206esp_sbus_attach(device_t dev)
207{
208	struct esp_softc *esc;
209	struct ncr53c9x_softc *sc;
210	struct lsi64854_softc *lsc;
211	device_t *children;
212	const char *name;
213	phandle_t node;
214	int burst, error, i, nchildren, slot;
215
216	esc = device_get_softc(dev);
217	bzero(esc, sizeof(struct esp_softc));
218	sc = &esc->sc_ncr53c9x;
219
220	lsc = NULL;
221	esc->sc_dev = dev;
222	name = ofw_bus_get_name(dev);
223	node = ofw_bus_get_node(dev);
224	if (OF_getprop(node, "initiator-id", &sc->sc_id,
225	    sizeof(sc->sc_id)) == -1)
226		sc->sc_id = 7;
227	sc->sc_freq = sbus_get_clockfreq(dev);
228
229#ifdef ESP_SBUS_DEBUG
230	device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
231	    sc->sc_freq);
232#endif
233
234	if (strcmp(name, "SUNW,fas") == 0) {
235		/*
236		 * Allocate space for DMA, in SUNW,fas there are no
237		 * separate DMA devices.
238		 */
239		lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF,
240		    M_NOWAIT | M_ZERO);
241		if (lsc == NULL) {
242			device_printf(dev, "out of memory (lsi64854_softc)\n");
243			return (ENOMEM);
244		}
245		esc->sc_dma = lsc;
246
247		/*
248		 * SUNW,fas have 2 register spaces: DMA (lsi64854) and
249		 * SCSI core (ncr53c9x).
250		 */
251
252		/* Allocate DMA registers. */
253		lsc->sc_rid = 0;
254		if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
255		    &lsc->sc_rid, RF_ACTIVE)) == NULL) {
256			device_printf(dev, "cannot allocate DMA registers\n");
257			error = ENXIO;
258			goto fail_sbus_lsc;
259		}
260		lsc->sc_regt = rman_get_bustag(lsc->sc_res);
261		lsc->sc_regh = rman_get_bushandle(lsc->sc_res);
262
263		/* Create a parent DMA tag based on this bus. */
264		error = bus_dma_tag_create(
265		    bus_get_dma_tag(dev),	/* parent */
266		    PAGE_SIZE, 0,		/* alignment, boundary */
267		    BUS_SPACE_MAXADDR,		/* lowaddr */
268		    BUS_SPACE_MAXADDR,		/* highaddr */
269		    NULL, NULL,			/* filter, filterarg */
270		    BUS_SPACE_MAXSIZE_32BIT,	/* maxsize */
271		    0,				/* nsegments */
272		    BUS_SPACE_MAXSIZE_32BIT,	/* maxsegsize */
273		    0,				/* flags */
274		    NULL, NULL,			/* no locking */
275		    &lsc->sc_parent_dmat);
276		if (error != 0) {
277			device_printf(dev, "cannot allocate parent DMA tag\n");
278			goto fail_sbus_lres;
279		}
280		burst = sbus_get_burstsz(dev);
281
282#ifdef ESP_SBUS_DEBUG
283		printf("%s: burst 0x%x\n", __func__, burst);
284#endif
285
286		lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
287		    (burst & SBUS_BURST_16) ? 16 : 0;
288
289		lsc->sc_channel = L64854_CHANNEL_SCSI;
290		lsc->sc_client = sc;
291		lsc->sc_dev = dev;
292
293		error = lsi64854_attach(lsc);
294		if (error != 0) {
295			device_printf(dev, "lsi64854_attach failed\n");
296			goto fail_sbus_lpdma;
297		}
298
299		/*
300		 * Allocate SCSI core registers.
301		 */
302		esc->sc_rid = 1;
303		if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
304		    &esc->sc_rid, RF_ACTIVE)) == NULL) {
305			device_printf(dev,
306			    "cannot allocate SCSI core registers\n");
307			error = ENXIO;
308			goto fail_sbus_lsi;
309		}
310		esc->sc_regt = rman_get_bustag(esc->sc_res);
311		esc->sc_regh = rman_get_bushandle(esc->sc_res);
312	} else {
313		/*
314		 * Search accompanying DMA engine.  It should have been
315		 * already attached otherwise there isn't much we can do.
316		 */
317		if (device_get_children(device_get_parent(dev), &children,
318		    &nchildren) != 0) {
319			device_printf(dev, "cannot determine siblings\n");
320			return (ENXIO);
321		}
322		slot = sbus_get_slot(dev);
323		for (i = 0; i < nchildren; i++) {
324			if (device_is_attached(children[i]) &&
325			    sbus_get_slot(children[i]) == slot &&
326			    strcmp(ofw_bus_get_name(children[i]), "dma") == 0) {
327				/* XXX hackery */
328				esc->sc_dma = (struct lsi64854_softc *)
329				    device_get_softc(children[i]);
330				break;
331			}
332		}
333		free(children, M_TEMP);
334		if (esc->sc_dma == NULL) {
335			device_printf(dev, "cannot find DMA engine\n");
336			return (ENXIO);
337		}
338		esc->sc_dma->sc_client = sc;
339
340		/*
341		 * Allocate SCSI core registers.
342		 */
343		esc->sc_rid = 0;
344		if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
345		    &esc->sc_rid, RF_ACTIVE)) == NULL) {
346			device_printf(dev,
347			    "cannot allocate SCSI core registers\n");
348			return (ENXIO);
349		}
350		esc->sc_regt = rman_get_bustag(esc->sc_res);
351		esc->sc_regh = rman_get_bushandle(esc->sc_res);
352	}
353
354	error = espattach(esc, &esp_sbus_glue);
355	if (error != 0) {
356		device_printf(dev, "espattach failed\n");
357		goto fail_sbus_eres;
358	}
359
360	return (0);
361
362 fail_sbus_eres:
363	bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
364	if (strcmp(name, "SUNW,fas") != 0)
365		return (error);
366 fail_sbus_lsi:
367	lsi64854_detach(lsc);
368 fail_sbus_lpdma:
369	bus_dma_tag_destroy(lsc->sc_parent_dmat);
370 fail_sbus_lres:
371	bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
372 fail_sbus_lsc:
373	free(lsc, M_DEVBUF);
374	return (error);
375}
376
377static int
378esp_sbus_detach(device_t dev)
379{
380	struct esp_softc *esc;
381	struct ncr53c9x_softc *sc;
382	struct lsi64854_softc *lsc;
383	int error;
384
385	esc = device_get_softc(dev);
386	sc = &esc->sc_ncr53c9x;
387	lsc = esc->sc_dma;
388
389	bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
390	error = ncr53c9x_detach(sc);
391	if (error != 0)
392		return (error);
393	bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
394	    esc->sc_irqres);
395	bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
396	if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0)
397		return (0);
398	error = lsi64854_detach(lsc);
399	if (error != 0)
400		return (error);
401	bus_dma_tag_destroy(lsc->sc_parent_dmat);
402	bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
403	free(lsc, M_DEVBUF);
404
405	return (0);
406}
407
408static int
409esp_dma_attach(device_t dev)
410{
411	struct esp_softc *esc;
412	struct ncr53c9x_softc *sc;
413	phandle_t node;
414	int error;
415
416	esc = device_get_softc(dev);
417	bzero(esc, sizeof(struct esp_softc));
418	sc = &esc->sc_ncr53c9x;
419
420	esc->sc_dev = dev;
421	node = ofw_bus_get_node(dev);
422	if (OF_getprop(node, "initiator-id", &sc->sc_id,
423	    sizeof(sc->sc_id)) == -1)
424		sc->sc_id = 7;
425	if (OF_getprop(node, "clock-frequency", &sc->sc_freq,
426	    sizeof(sc->sc_freq)) == -1) {
427		printf("failed to query OFW for clock-frequency\n");
428		return (ENXIO);
429	}
430
431#ifdef ESP_SBUS_DEBUG
432	device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
433	    sc->sc_freq);
434#endif
435
436	/* XXX hackery */
437	esc->sc_dma = (struct lsi64854_softc *)
438	    device_get_softc(device_get_parent(dev));
439	esc->sc_dma->sc_client = sc;
440
441	/*
442	 * Allocate SCSI core registers.
443	 */
444	esc->sc_rid = 0;
445	if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
446	    &esc->sc_rid, RF_ACTIVE)) == NULL) {
447		device_printf(dev, "cannot allocate SCSI core registers\n");
448		return (ENXIO);
449	}
450	esc->sc_regt = rman_get_bustag(esc->sc_res);
451	esc->sc_regh = rman_get_bushandle(esc->sc_res);
452
453	error = espattach(esc, &esp_sbus_glue);
454	if (error != 0) {
455		device_printf(dev, "espattach failed\n");
456		goto fail_dma_eres;
457	}
458
459	return (0);
460
461 fail_dma_eres:
462	bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
463	return (error);
464}
465
466static int
467esp_dma_detach(device_t dev)
468{
469	struct esp_softc *esc;
470	struct ncr53c9x_softc *sc;
471	int error;
472
473	esc = device_get_softc(dev);
474	sc = &esc->sc_ncr53c9x;
475
476	bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
477	error = ncr53c9x_detach(sc);
478	if (error != 0)
479		return (error);
480	bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
481	    esc->sc_irqres);
482	bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
483
484	return (0);
485}
486
487static int
488esp_suspend(device_t dev)
489{
490
491	return (ENXIO);
492}
493
494static int
495esp_resume(device_t dev)
496{
497
498	return (ENXIO);
499}
500
501static int
502espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
503{
504	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
505	unsigned int uid = 0;
506	int error;
507
508	/*
509	 * The `ESC' DMA chip must be reset before we can access
510	 * the ESP registers.
511	 */
512	if (esc->sc_dma->sc_rev == DMAREV_ESC)
513		DMA_RESET(esc->sc_dma);
514
515	/*
516	 * Set up glue for MI code early; we use some of it here.
517	 */
518	sc->sc_glue = gluep;
519
520	/* gimme MHz */
521	sc->sc_freq /= 1000000;
522
523	/*
524	 * XXX More of this should be in ncr53c9x_attach(), but
525	 * XXX should we really poke around the chip that much in
526	 * XXX the MI code?  Think about this more...
527	 */
528
529	/*
530	 * Read the part-unique ID code of the SCSI chip.  The contained
531	 * value is only valid if all of the following conditions are met:
532	 * - After power-up or chip reset.
533	 * - Before any value is written to this register.
534	 * - The NCRCFG2_FE bit is set.
535	 * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued.
536	 */
537	NCRCMD(sc, NCRCMD_RSTCHIP);
538	NCRCMD(sc, NCRCMD_NOP);
539	sc->sc_cfg2 = NCRCFG2_FE;
540	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
541	NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
542	uid = NCR_READ_REG(sc, NCR_UID);
543
544	/*
545	 * It is necessary to try to load the 2nd config register here,
546	 * to find out what rev the esp chip is, else the ncr53c9x_reset
547	 * will not set up the defaults correctly.
548	 */
549	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
550	NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
551	sc->sc_cfg2 = 0;
552	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
553	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
554	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
555
556	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
557	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
558		sc->sc_rev = NCR_VARIANT_ESP100;
559	} else {
560		sc->sc_cfg2 = NCRCFG2_SCSI2;
561		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
562		sc->sc_cfg3 = 0;
563		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
564		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
565		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
566		if (NCR_READ_REG(sc, NCR_CFG3) !=
567		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
568			sc->sc_rev = NCR_VARIANT_ESP100A;
569		} else {
570			/* NCRCFG2_FE enables > 64K transfers. */
571			sc->sc_cfg2 |= NCRCFG2_FE;
572			sc->sc_cfg3 = 0;
573			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
574			if (sc->sc_freq <= 25)
575				sc->sc_rev = NCR_VARIANT_ESP200;
576			else {
577				switch ((uid & 0xf8) >> 3) {
578				case 0x00:
579					sc->sc_rev = NCR_VARIANT_FAS100A;
580					break;
581
582				case 0x02:
583					if ((uid & 0x07) == 0x02)
584						sc->sc_rev = NCR_VARIANT_FAS216;
585					else
586						sc->sc_rev = NCR_VARIANT_FAS236;
587					break;
588
589				case 0x0a:
590					sc->sc_rev = NCR_VARIANT_FAS366;
591					break;
592
593				default:
594					/*
595					 * We could just treat unknown chips
596					 * as ESP200 but then we would most
597					 * likely drive them out of specs.
598					 */
599					device_printf(esc->sc_dev,
600					    "Unknown chip\n");
601					return (ENXIO);
602				}
603			}
604		}
605	}
606
607#ifdef ESP_SBUS_DEBUG
608	printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid);
609#endif
610
611	/*
612	 * XXX minsync and maxxfer _should_ be set up in MI code,
613	 * XXX but it appears to have some dependency on what sort
614	 * XXX of DMA we're hooked up to, etc.
615	 */
616
617	/*
618	 * This is the value used to start sync negotiations
619	 * Note that the NCR register "SYNCTP" is programmed
620	 * in "clocks per byte", and has a minimum value of 4.
621	 * The SCSI period used in negotiation is one-fourth
622	 * of the time (in nanoseconds) needed to transfer one byte.
623	 * Since the chip's clock is given in MHz, we have the following
624	 * formula: 4 * period = (1000 / freq) * 4
625	 */
626	sc->sc_minsync = 1000 / sc->sc_freq;
627
628	sc->sc_maxoffset = 15;
629	sc->sc_extended_geom = 1;
630
631	/*
632	 * Alas, we must now modify the value a bit, because it's
633	 * only valid when can switch on FASTCLK and FASTSCSI bits
634	 * in config register 3...
635	 */
636	switch (sc->sc_rev) {
637	case NCR_VARIANT_ESP100:
638		sc->sc_maxwidth = 0;
639		sc->sc_maxxfer = 64 * 1024;
640		sc->sc_minsync = 0;	/* No synch on old chip? */
641		break;
642
643	case NCR_VARIANT_ESP100A:
644		sc->sc_maxwidth = 0;
645		sc->sc_maxxfer = 64 * 1024;
646		/* Min clocks/byte is 5 */
647		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
648		break;
649
650	case NCR_VARIANT_ESP200:
651		sc->sc_maxwidth = 0;
652		sc->sc_maxxfer = 16 * 1024 * 1024;
653		/* Min clocks/byte is 5 */
654		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
655		break;
656
657	case NCR_VARIANT_FAS100A:
658	case NCR_VARIANT_FAS216:
659	case NCR_VARIANT_FAS236:
660		/*
661		 * The onboard SCSI chips in Sun Ultra 1 are actually
662		 * documented to be NCR53C9X which use NCRCFG3_FCLK and
663		 * NCRCFG3_FSCSI.  BSD/OS however probes these chips as
664		 * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI
665		 * instead which seems to be correct as otherwise sync
666		 * negotiation just doesn't work.  Using NCRF9XCFG3_FCLK
667		 * and NCRF9XCFG3_FSCSI with these chips in fact also
668		 * yields Fast-SCSI speed.
669		 */
670		sc->sc_features = NCR_F_FASTSCSI;
671		sc->sc_cfg3 = NCRF9XCFG3_FCLK;
672		sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI;
673		sc->sc_maxwidth = 0;
674		sc->sc_maxxfer = 16 * 1024 * 1024;
675		break;
676
677	case NCR_VARIANT_FAS366:
678		sc->sc_maxwidth = 1;
679		sc->sc_maxxfer = 16 * 1024 * 1024;
680		break;
681	}
682
683	/* Limit minsync due to unsolved performance issues. */
684	sc->sc_maxsync = sc->sc_minsync;
685
686	/* Establish interrupt channel. */
687	esc->sc_irqrid = 0;
688	if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ,
689	    &esc->sc_irqrid, RF_SHAREABLE|RF_ACTIVE)) == NULL) {
690		device_printf(esc->sc_dev, "cannot allocate interrupt\n");
691		return (ENXIO);
692	}
693	if (bus_setup_intr(esc->sc_dev, esc->sc_irqres,
694	    INTR_TYPE_BIO, NULL, ncr53c9x_intr, sc, &esc->sc_irq)) {
695		device_printf(esc->sc_dev, "cannot set up interrupt\n");
696		error = ENXIO;
697		goto fail_ires;
698	}
699
700	/* Turn on target selection using the `DMA' method. */
701	if (sc->sc_rev != NCR_VARIANT_FAS366)
702		sc->sc_features |= NCR_F_DMASELECT;
703
704	/* Do the common parts of attachment. */
705	sc->sc_dev = esc->sc_dev;
706	error = ncr53c9x_attach(sc);
707	if (error != 0) {
708		device_printf(esc->sc_dev, "ncr53c9x_attach failed\n");
709		goto fail_intr;
710	}
711
712	return (0);
713
714 fail_intr:
715	bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
716 fail_ires:
717	bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
718	    esc->sc_irqres);
719	return (error);
720}
721
722/*
723 * Glue functions
724 */
725
726#ifdef ESP_SBUS_DEBUG
727int esp_sbus_debug = 0;
728
729static struct {
730	char *r_name;
731	int   r_flag;
732} esp__read_regnames [] = {
733	{ "TCL", 0},			/* 0/00 */
734	{ "TCM", 0},			/* 1/04 */
735	{ "FIFO", 0},			/* 2/08 */
736	{ "CMD", 0},			/* 3/0c */
737	{ "STAT", 0},			/* 4/10 */
738	{ "INTR", 0},			/* 5/14 */
739	{ "STEP", 0},			/* 6/18 */
740	{ "FFLAGS", 1},			/* 7/1c */
741	{ "CFG1", 1},			/* 8/20 */
742	{ "STAT2", 0},			/* 9/24 */
743	{ "CFG4", 1},			/* a/28 */
744	{ "CFG2", 1},			/* b/2c */
745	{ "CFG3", 1},			/* c/30 */
746	{ "-none", 1},			/* d/34 */
747	{ "TCH", 1},			/* e/38 */
748	{ "TCX", 1},			/* f/3c */
749};
750
751static struct {
752	char *r_name;
753	int   r_flag;
754} esp__write_regnames[] = {
755	{ "TCL", 1},			/* 0/00 */
756	{ "TCM", 1},			/* 1/04 */
757	{ "FIFO", 0},			/* 2/08 */
758	{ "CMD", 0},			/* 3/0c */
759	{ "SELID", 1},			/* 4/10 */
760	{ "TIMEOUT", 1},		/* 5/14 */
761	{ "SYNCTP", 1},			/* 6/18 */
762	{ "SYNCOFF", 1},		/* 7/1c */
763	{ "CFG1", 1},			/* 8/20 */
764	{ "CCF", 1},			/* 9/24 */
765	{ "TEST", 1},			/* a/28 */
766	{ "CFG2", 1},			/* b/2c */
767	{ "CFG3", 1},			/* c/30 */
768	{ "-none", 1},			/* d/34 */
769	{ "TCH", 1},			/* e/38 */
770	{ "TCX", 1},			/* f/3c */
771};
772#endif
773
774static u_char
775esp_read_reg(struct ncr53c9x_softc *sc, int reg)
776{
777	struct esp_softc *esc = (struct esp_softc *)sc;
778	u_char v;
779
780	v = bus_space_read_1(esc->sc_regt, esc->sc_regh, reg * 4);
781#ifdef ESP_SBUS_DEBUG
782	if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
783		printf("RD:%x <%s> %x\n", reg * 4,
784		    ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
785#endif
786	return v;
787}
788
789static void
790esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v)
791{
792	struct esp_softc *esc = (struct esp_softc *)sc;
793
794#ifdef ESP_SBUS_DEBUG
795	if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
796		printf("WR:%x <%s> %x\n", reg * 4,
797		    ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
798#endif
799	bus_space_write_1(esc->sc_regt, esc->sc_regh, reg * 4, v);
800}
801
802static int
803esp_dma_isintr(struct ncr53c9x_softc *sc)
804{
805	struct esp_softc *esc = (struct esp_softc *)sc;
806
807	return (DMA_ISINTR(esc->sc_dma));
808}
809
810static void
811esp_dma_reset(struct ncr53c9x_softc *sc)
812{
813	struct esp_softc *esc = (struct esp_softc *)sc;
814
815	DMA_RESET(esc->sc_dma);
816}
817
818static int
819esp_dma_intr(struct ncr53c9x_softc *sc)
820{
821	struct esp_softc *esc = (struct esp_softc *)sc;
822
823	return (DMA_INTR(esc->sc_dma));
824}
825
826static int
827esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
828	      int datain, size_t *dmasize)
829{
830	struct esp_softc *esc = (struct esp_softc *)sc;
831
832	return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
833}
834
835static void
836esp_dma_go(struct ncr53c9x_softc *sc)
837{
838	struct esp_softc *esc = (struct esp_softc *)sc;
839
840	DMA_GO(esc->sc_dma);
841}
842
843static void
844esp_dma_stop(struct ncr53c9x_softc *sc)
845{
846	struct esp_softc *esc = (struct esp_softc *)sc;
847
848	L64854_SCSR(esc->sc_dma, L64854_GCSR(esc->sc_dma) & ~D_EN_DMA);
849}
850
851static int
852esp_dma_isactive(struct ncr53c9x_softc *sc)
853{
854	struct esp_softc *esc = (struct esp_softc *)sc;
855
856	return (DMA_ISACTIVE(esc->sc_dma));
857}
858