esp_sbus.c revision 330897
1139735Simp/*-
2129198Scognet * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-2-Clause-NetBSD
3129198Scognet *
4129198Scognet * Copyright (c) 2004 Scott Long
5129198Scognet * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
6129198Scognet * All rights reserved.
7129198Scognet *
8129198Scognet * Redistribution and use in source and binary forms, with or without
9129198Scognet * modification, are permitted provided that the following conditions
10129198Scognet * are met:
11129198Scognet * 1. Redistributions of source code must retain the above copyright
12129198Scognet *    notice, this list of conditions and the following disclaimer.
13129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
14129198Scognet *    notice, this list of conditions and the following disclaimer in the
15129198Scognet *    documentation and/or other materials provided with the distribution.
16129198Scognet *
17129198Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18129198Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19129198Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20129198Scognet * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21129198Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22129198Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23129198Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24129198Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25129198Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26129198Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27129198Scognet * SUCH DAMAGE.
28129198Scognet *
29129198Scognet */
30129198Scognet
31129198Scognet/*	$NetBSD: esp_sbus.c,v 1.51 2009/09/17 16:28:12 tsutsui Exp $	*/
32129198Scognet
33129198Scognet/*-
34129198Scognet * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
35129198Scognet * All rights reserved.
36129198Scognet *
37129198Scognet * This code is derived from software contributed to The NetBSD Foundation
38129198Scognet * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
39129198Scognet * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
40129198Scognet *
41129198Scognet * Redistribution and use in source and binary forms, with or without
42129198Scognet * modification, are permitted provided that the following conditions
43129198Scognet * are met:
44129198Scognet * 1. Redistributions of source code must retain the above copyright
45129198Scognet *    notice, this list of conditions and the following disclaimer.
46129198Scognet * 2. Redistributions in binary form must reproduce the above copyright
47129198Scognet *    notice, this list of conditions and the following disclaimer in the
48129198Scognet *    documentation and/or other materials provided with the distribution.
49129198Scognet *
50129198Scognet * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
51129198Scognet * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
52129198Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53129198Scognet * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
54159100Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
55129198Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
56129198Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
57129198Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
58129198Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59129198Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
60137362Scognet * POSSIBILITY OF SUCH DAMAGE.
61129198Scognet */
62129198Scognet
63129198Scognet#include <sys/cdefs.h>
64129198Scognet__FBSDID("$FreeBSD: stable/11/sys/dev/esp/esp_sbus.c 330897 2018-03-14 03:19:51Z eadler $");
65159325Salc
66159325Salc#include <sys/param.h>
67129198Scognet#include <sys/systm.h>
68129198Scognet#include <sys/bus.h>
69129198Scognet#include <sys/kernel.h>
70129198Scognet#include <sys/lock.h>
71129198Scognet#include <sys/module.h>
72129198Scognet#include <sys/mutex.h>
73135641Scognet#include <sys/rman.h>
74135641Scognet
75129198Scognet#include <dev/ofw/ofw_bus.h>
76129198Scognet#include <dev/ofw/openfirm.h>
77129198Scognet#include <machine/bus.h>
78135641Scognet#include <machine/ofw_machdep.h>
79129198Scognet#include <machine/resource.h>
80137362Scognet
81129198Scognet#include <cam/cam.h>
82129198Scognet#include <cam/cam_ccb.h>
83129198Scognet#include <cam/scsi/scsi_all.h>
84129198Scognet#include <cam/scsi/scsi_message.h>
85129198Scognet
86129198Scognet#include <sparc64/sbus/lsi64854reg.h>
87129198Scognet#include <sparc64/sbus/lsi64854var.h>
88129198Scognet#include <sparc64/sbus/sbusvar.h>
89129198Scognet
90129198Scognet#include <dev/esp/ncr53c9xreg.h>
91129198Scognet#include <dev/esp/ncr53c9xvar.h>
92129198Scognet
93129198Scognet/* #define ESP_SBUS_DEBUG */
94129198Scognet
95129198Scognetstruct esp_softc {
96129198Scognet	struct ncr53c9x_softc	sc_ncr53c9x;	/* glue to MI code */
97194459Sthompsa	device_t		sc_dev;
98129198Scognet
99129198Scognet	struct resource		*sc_res;
100129198Scognet
101129198Scognet	struct resource		*sc_irqres;
102129198Scognet	void			*sc_irq;
103129198Scognet
104129198Scognet	struct lsi64854_softc	*sc_dma;	/* pointer to my DMA */
105129198Scognet};
106129198Scognet
107129198Scognetstatic int	esp_probe(device_t);
108129198Scognetstatic int	esp_dma_attach(device_t);
109129198Scognetstatic int	esp_dma_detach(device_t);
110129198Scognetstatic int	esp_sbus_attach(device_t);
111129198Scognetstatic int	esp_sbus_detach(device_t);
112129198Scognetstatic int	esp_suspend(device_t);
113129198Scognetstatic int	esp_resume(device_t);
114129198Scognet
115129198Scognetstatic device_method_t esp_dma_methods[] = {
116129198Scognet	DEVMETHOD(device_probe,		esp_probe),
117129198Scognet	DEVMETHOD(device_attach,	esp_dma_attach),
118129198Scognet	DEVMETHOD(device_detach,	esp_dma_detach),
119129198Scognet	DEVMETHOD(device_suspend,	esp_suspend),
120129198Scognet	DEVMETHOD(device_resume,	esp_resume),
121129198Scognet
122129198Scognet	DEVMETHOD_END
123129198Scognet};
124129198Scognet
125129198Scognetstatic driver_t esp_dma_driver = {
126129198Scognet	"esp",
127129198Scognet	esp_dma_methods,
128129198Scognet	sizeof(struct esp_softc)
129159325Salc};
130129198Scognet
131129198ScognetDRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0);
132129198ScognetMODULE_DEPEND(esp, dma, 1, 1, 1);
133129198Scognet
134129198Scognetstatic device_method_t esp_sbus_methods[] = {
135129198Scognet	DEVMETHOD(device_probe,		esp_probe),
136144760Scognet	DEVMETHOD(device_attach,	esp_sbus_attach),
137129198Scognet	DEVMETHOD(device_detach,	esp_sbus_detach),
138129198Scognet	DEVMETHOD(device_suspend,	esp_suspend),
139129198Scognet	DEVMETHOD(device_resume,	esp_resume),
140129198Scognet
141129198Scognet	DEVMETHOD_END
142191873Salc};
143191873Salc
144129198Scognetstatic driver_t esp_sbus_driver = {
145137362Scognet	"esp",
146159325Salc	esp_sbus_methods,
147159325Salc	sizeof(struct esp_softc)
148159325Salc};
149159325Salc
150159325SalcDRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0);
151159325SalcMODULE_DEPEND(esp, sbus, 1, 1, 1);
152159325Salc
153159325Salc/*
154159325Salc * Functions and the switch for the MI code
155159325Salc */
156129198Scognetstatic uint8_t	esp_read_reg(struct ncr53c9x_softc *sc, int reg);
157129198Scognetstatic void	esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v);
158135641Scognetstatic int	esp_dma_isintr(struct ncr53c9x_softc *sc);
159129198Scognetstatic void	esp_dma_reset(struct ncr53c9x_softc *sc);
160129198Scognetstatic int	esp_dma_intr(struct ncr53c9x_softc *sc);
161164250Srustatic int	esp_dma_setup(struct ncr53c9x_softc *sc, void **addr,
162129198Scognet		    size_t *len, int datain, size_t *dmasize);
163129198Scognetstatic void	esp_dma_go(struct ncr53c9x_softc *sc);
164138413Scognetstatic void	esp_dma_stop(struct ncr53c9x_softc *sc);
165138413Scognetstatic int	esp_dma_isactive(struct ncr53c9x_softc *sc);
166138413Scognetstatic int	espattach(struct esp_softc *esc,
167144760Scognet		    const struct ncr53c9x_glue *gluep);
168129198Scognetstatic int	espdetach(struct esp_softc *esc);
169129198Scognet
170129198Scognetstatic const struct ncr53c9x_glue esp_sbus_glue = {
171129198Scognet	esp_read_reg,
172129198Scognet	esp_write_reg,
173129198Scognet	esp_dma_isintr,
174129198Scognet	esp_dma_reset,
175129198Scognet	esp_dma_intr,
176129198Scognet	esp_dma_setup,
177129198Scognet	esp_dma_go,
178129198Scognet	esp_dma_stop,
179129198Scognet	esp_dma_isactive,
180129198Scognet};
181129198Scognet
182135641Scognetstatic int
183135641Scognetesp_probe(device_t dev)
184135641Scognet{
185135641Scognet	const char *name;
186135641Scognet
187132056Scognet	name = ofw_bus_get_name(dev);
188132056Scognet	if (strcmp("SUNW,fas", name) == 0) {
189129198Scognet		device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI");
190129198Scognet	        return (BUS_PROBE_DEFAULT);
191129198Scognet	} else if (strcmp("esp", name) == 0) {
192129198Scognet		device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI");
193129198Scognet	        return (BUS_PROBE_DEFAULT);
194129198Scognet	}
195129198Scognet
196129198Scognet	return (ENXIO);
197129198Scognet}
198129198Scognet
199129198Scognetstatic int
200129198Scognetesp_sbus_attach(device_t dev)
201129198Scognet{
202129198Scognet	struct esp_softc *esc;
203129198Scognet	struct ncr53c9x_softc *sc;
204129198Scognet	struct lsi64854_softc *lsc;
205129198Scognet	device_t *children;
206129198Scognet	int error, i, nchildren;
207129198Scognet
208156191Scognet	esc = device_get_softc(dev);
209184728Sraj	sc = &esc->sc_ncr53c9x;
210142570Scognet
211129198Scognet	lsc = NULL;
212129198Scognet	esc->sc_dev = dev;
213129198Scognet	sc->sc_freq = sbus_get_clockfreq(dev);
214129198Scognet
215129198Scognet	if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") == 0) {
216129198Scognet		/*
217129198Scognet		 * Allocate space for DMA, in SUNW,fas there are no
218129198Scognet		 * separate DMA devices.
219129198Scognet		 */
220129198Scognet		lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF,
221129198Scognet		    M_NOWAIT | M_ZERO);
222129198Scognet		if (lsc == NULL) {
223129198Scognet			device_printf(dev, "out of memory (lsi64854_softc)\n");
224129198Scognet			return (ENOMEM);
225129198Scognet		}
226129198Scognet		esc->sc_dma = lsc;
227169756Scognet
228169756Scognet		/*
229129198Scognet		 * SUNW,fas have 2 register spaces: DMA (lsi64854) and
230129198Scognet		 * SCSI core (ncr53c9x).
231129198Scognet		 */
232129198Scognet
233129198Scognet		/* Allocate DMA registers. */
234129198Scognet		i = 0;
235129198Scognet		if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
236129198Scognet		    &i, RF_ACTIVE)) == NULL) {
237129198Scognet			device_printf(dev, "cannot allocate DMA registers\n");
238129198Scognet			error = ENXIO;
239129198Scognet			goto fail_sbus_lsc;
240129198Scognet		}
241129198Scognet
242129198Scognet		/* Create a parent DMA tag based on this bus. */
243129198Scognet		error = bus_dma_tag_create(
244129198Scognet		    bus_get_dma_tag(dev),	/* parent */
245129198Scognet		    1, 0,			/* alignment, boundary */
246129198Scognet		    BUS_SPACE_MAXADDR,		/* lowaddr */
247129198Scognet		    BUS_SPACE_MAXADDR,		/* highaddr */
248129198Scognet		    NULL, NULL,			/* filter, filterarg */
249129198Scognet		    BUS_SPACE_MAXSIZE,		/* maxsize */
250129198Scognet		    BUS_SPACE_UNRESTRICTED,	/* nsegments */
251129198Scognet		    BUS_SPACE_MAXSIZE,		/* maxsegsize */
252129198Scognet		    0,				/* flags */
253129198Scognet		    NULL, NULL,			/* no locking */
254171620Scognet		    &lsc->sc_parent_dmat);
255171620Scognet		if (error != 0) {
256129198Scognet			device_printf(dev, "cannot allocate parent DMA tag\n");
257129198Scognet			goto fail_sbus_lres;
258129198Scognet		}
259129198Scognet
260129198Scognet		i = sbus_get_burstsz(dev);
261129198Scognet
262171620Scognet#ifdef ESP_SBUS_DEBUG
263171620Scognet		printf("%s: burst 0x%x\n", __func__, i);
264129198Scognet#endif
265129198Scognet
266129198Scognet		lsc->sc_burst = (i & SBUS_BURST_32) ? 32 :
267129198Scognet		    (i & SBUS_BURST_16) ? 16 : 0;
268129198Scognet
269129198Scognet		lsc->sc_channel = L64854_CHANNEL_SCSI;
270129198Scognet		lsc->sc_client = sc;
271129198Scognet		lsc->sc_dev = dev;
272129198Scognet
273129198Scognet		/*
274171620Scognet		 * Allocate SCSI core registers.
275171620Scognet		 */
276129198Scognet		i = 1;
277129198Scognet		if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
278129198Scognet		    &i, RF_ACTIVE)) == NULL) {
279129198Scognet			device_printf(dev,
280129198Scognet			    "cannot allocate SCSI core registers\n");
281129198Scognet			error = ENXIO;
282129198Scognet			goto fail_sbus_lpdma;
283129198Scognet		}
284129198Scognet	} else {
285129198Scognet		/*
286129198Scognet		 * Search accompanying DMA engine.  It should have been
287129198Scognet		 * already attached otherwise there isn't much we can do.
288129198Scognet		 */
289129198Scognet		if (device_get_children(device_get_parent(dev), &children,
290129198Scognet		    &nchildren) != 0) {
291129198Scognet			device_printf(dev, "cannot determine siblings\n");
292129198Scognet			return (ENXIO);
293129198Scognet		}
294129198Scognet		for (i = 0; i < nchildren; i++) {
295129198Scognet			if (device_is_attached(children[i]) &&
296129198Scognet			    sbus_get_slot(children[i]) ==
297129198Scognet			    sbus_get_slot(dev) &&
298129198Scognet			    strcmp(ofw_bus_get_name(children[i]),
299129198Scognet			    "dma") == 0) {
300129198Scognet				/* XXX hackery */
301129198Scognet				esc->sc_dma = (struct lsi64854_softc *)
302129198Scognet				    device_get_softc(children[i]);
303129198Scognet				break;
304129198Scognet			}
305129198Scognet		}
306129198Scognet		free(children, M_TEMP);
307129198Scognet		if (esc->sc_dma == NULL) {
308129198Scognet			device_printf(dev, "cannot find DMA engine\n");
309129198Scognet			return (ENXIO);
310129198Scognet		}
311129198Scognet		esc->sc_dma->sc_client = sc;
312129198Scognet
313129198Scognet		/*
314129198Scognet		 * Allocate SCSI core registers.
315129198Scognet		 */
316129198Scognet		i = 0;
317129198Scognet		if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
318129198Scognet		    &i, RF_ACTIVE)) == NULL) {
319129198Scognet			device_printf(dev,
320129198Scognet			    "cannot allocate SCSI core registers\n");
321129198Scognet			return (ENXIO);
322129198Scognet		}
323129198Scognet	}
324129198Scognet
325129198Scognet	error = espattach(esc, &esp_sbus_glue);
326129198Scognet	if (error != 0) {
327129198Scognet		device_printf(dev, "espattach failed\n");
328129198Scognet		goto fail_sbus_eres;
329129198Scognet	}
330129198Scognet
331129198Scognet	return (0);
332129198Scognet
333129198Scognet fail_sbus_eres:
334158531Scognet	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
335158531Scognet	    esc->sc_res);
336158531Scognet	if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0)
337158531Scognet		return (error);
338129198Scognet fail_sbus_lpdma:
339129198Scognet	bus_dma_tag_destroy(lsc->sc_parent_dmat);
340129198Scognet fail_sbus_lres:
341171620Scognet	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
342171620Scognet	    lsc->sc_res);
343171620Scognet fail_sbus_lsc:
344129198Scognet	free(lsc, M_DEVBUF);
345129198Scognet	return (error);
346129198Scognet}
347158531Scognet
348129198Scognetstatic int
349129198Scognetesp_sbus_detach(device_t dev)
350129198Scognet{
351129198Scognet	struct esp_softc *esc;
352129198Scognet	struct lsi64854_softc *lsc;
353129198Scognet	int error;
354129198Scognet
355129198Scognet	esc = device_get_softc(dev);
356129198Scognet	lsc = esc->sc_dma;
357129198Scognet
358129198Scognet	error = espdetach(esc);
359129198Scognet	if (error != 0)
360129198Scognet		return (error);
361129198Scognet	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
362129198Scognet		esc->sc_res);
363129198Scognet	if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0)
364129198Scognet		return (0);
365129198Scognet	bus_dma_tag_destroy(lsc->sc_parent_dmat);
366129198Scognet	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(lsc->sc_res),
367129198Scognet	    lsc->sc_res);
368129198Scognet	free(lsc, M_DEVBUF);
369129198Scognet
370129198Scognet	return (0);
371129198Scognet}
372129198Scognet
373129198Scognetstatic int
374129198Scognetesp_dma_attach(device_t dev)
375129198Scognet{
376129198Scognet	struct esp_softc *esc;
377129198Scognet	struct ncr53c9x_softc *sc;
378129198Scognet	int error, i;
379129198Scognet
380129198Scognet	esc = device_get_softc(dev);
381129198Scognet	sc = &esc->sc_ncr53c9x;
382129198Scognet
383171620Scognet	esc->sc_dev = dev;
384129198Scognet	if (OF_getprop(ofw_bus_get_node(dev), "clock-frequency",
385171620Scognet	    &sc->sc_freq, sizeof(sc->sc_freq)) == -1) {
386171620Scognet		printf("failed to query OFW for clock-frequency\n");
387129198Scognet		return (ENXIO);
388129198Scognet	}
389129198Scognet
390129198Scognet	/* XXX hackery */
391129198Scognet	esc->sc_dma = (struct lsi64854_softc *)
392129198Scognet	    device_get_softc(device_get_parent(dev));
393129198Scognet	esc->sc_dma->sc_client = sc;
394171620Scognet
395171620Scognet	/*
396129198Scognet	 * Allocate SCSI core registers.
397129198Scognet	 */
398129198Scognet	i = 0;
399129198Scognet	if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
400129198Scognet	    &i, RF_ACTIVE)) == NULL) {
401129198Scognet		device_printf(dev, "cannot allocate SCSI core registers\n");
402129198Scognet		return (ENXIO);
403129198Scognet	}
404129198Scognet
405129198Scognet	error = espattach(esc, &esp_sbus_glue);
406129198Scognet	if (error != 0) {
407129198Scognet		device_printf(dev, "espattach failed\n");
408129198Scognet		goto fail_dma_eres;
409129198Scognet	}
410129198Scognet
411129198Scognet	return (0);
412129198Scognet
413129198Scognet fail_dma_eres:
414129198Scognet	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
415129198Scognet	    esc->sc_res);
416129198Scognet	return (error);
417129198Scognet}
418129198Scognet
419129198Scognetstatic int
420129198Scognetesp_dma_detach(device_t dev)
421129198Scognet{
422129198Scognet	struct esp_softc *esc;
423164080Scognet	int error;
424129198Scognet
425129198Scognet	esc = device_get_softc(dev);
426129198Scognet
427129198Scognet	error = espdetach(esc);
428129198Scognet	if (error != 0)
429129198Scognet		return (error);
430129198Scognet	bus_release_resource(dev, SYS_RES_MEMORY, rman_get_rid(esc->sc_res),
431129198Scognet	    esc->sc_res);
432129198Scognet
433129198Scognet	return (0);
434129198Scognet}
435129198Scognet
436129198Scognetstatic int
437129198Scognetesp_suspend(device_t dev)
438129198Scognet{
439129198Scognet
440129198Scognet	return (ENXIO);
441129198Scognet}
442129198Scognet
443129198Scognetstatic int
444129198Scognetesp_resume(device_t dev)
445129198Scognet{
446129198Scognet
447129198Scognet	return (ENXIO);
448129198Scognet}
449129198Scognet
450129198Scognetstatic int
451135641Scognetespattach(struct esp_softc *esc, const struct ncr53c9x_glue *gluep)
452129198Scognet{
453171620Scognet	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
454171620Scognet	unsigned int uid = 0;
455171620Scognet	int error, i;
456171620Scognet
457129198Scognet	NCR_LOCK_INIT(sc);
458129198Scognet
459129198Scognet	sc->sc_id = OF_getscsinitid(esc->sc_dev);
460129198Scognet
461129198Scognet#ifdef ESP_SBUS_DEBUG
462129198Scognet	device_printf(esc->sc_dev, "%s: sc_id %d, freq %d\n",
463129198Scognet	    __func__, sc->sc_id, sc->sc_freq);
464129198Scognet#endif
465129198Scognet
466129198Scognet	/*
467129198Scognet	 * The `ESC' DMA chip must be reset before we can access
468129198Scognet	 * the ESP registers.
469129198Scognet	 */
470129198Scognet	if (esc->sc_dma->sc_rev == DMAREV_ESC)
471129198Scognet		DMA_RESET(esc->sc_dma);
472129198Scognet
473129198Scognet	/*
474129198Scognet	 * Set up glue for MI code early; we use some of it here.
475129198Scognet	 */
476129198Scognet	sc->sc_glue = gluep;
477129198Scognet
478129198Scognet	/* gimme MHz */
479129198Scognet	sc->sc_freq /= 1000000;
480129198Scognet
481129198Scognet	/*
482129198Scognet	 * XXX More of this should be in ncr53c9x_attach(), but
483129198Scognet	 * XXX should we really poke around the chip that much in
484129198Scognet	 * XXX the MI code?  Think about this more...
485129198Scognet	 */
486129198Scognet
487129198Scognet	/*
488129198Scognet	 * Read the part-unique ID code of the SCSI chip.  The contained
489129198Scognet	 * value is only valid if all of the following conditions are met:
490129198Scognet	 * - After power-up or chip reset.
491129198Scognet	 * - Before any value is written to this register.
492129198Scognet	 * - The NCRCFG2_FE bit is set.
493129198Scognet	 * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued.
494129198Scognet	 */
495129198Scognet	NCRCMD(sc, NCRCMD_RSTCHIP);
496175840Scognet	NCRCMD(sc, NCRCMD_NOP);
497175840Scognet	sc->sc_cfg2 = NCRCFG2_FE;
498194459Sthompsa	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
499129198Scognet	NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
500129198Scognet	uid = NCR_READ_REG(sc, NCR_UID);
501135641Scognet
502135641Scognet	/*
503135641Scognet	 * It is necessary to try to load the 2nd config register here,
504129198Scognet	 * to find out what rev the esp chip is, else the ncr53c9x_reset
505135641Scognet	 * will not set up the defaults correctly.
506135641Scognet	 */
507129198Scognet	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
508135641Scognet	NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
509135641Scognet	sc->sc_cfg2 = 0;
510135641Scognet	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
511135641Scognet	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
512135641Scognet	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
513135641Scognet
514135641Scognet	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
515129198Scognet	    (NCRCFG2_SCSI2 | NCRCFG2_RPE))
516135641Scognet		sc->sc_rev = NCR_VARIANT_ESP100;
517135641Scognet	else {
518129198Scognet		sc->sc_cfg2 = NCRCFG2_SCSI2;
519135641Scognet		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
520135641Scognet		sc->sc_cfg3 = 0;
521137362Scognet		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
522147114Scognet		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
523147114Scognet		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
524147114Scognet		if (NCR_READ_REG(sc, NCR_CFG3) !=
525171620Scognet		    (NCRCFG3_CDB | NCRCFG3_FCLK))
526170582Scognet			sc->sc_rev = NCR_VARIANT_ESP100A;
527171620Scognet		else {
528147114Scognet			/* NCRCFG2_FE enables > 64K transfers. */
529137362Scognet			sc->sc_cfg2 |= NCRCFG2_FE;
530137362Scognet			sc->sc_cfg3 = 0;
531152128Scognet			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
532152128Scognet			if (sc->sc_freq <= 25)
533147114Scognet				sc->sc_rev = NCR_VARIANT_ESP200;
534147114Scognet			else {
535161105Scognet				switch ((uid & 0xf8) >> 3) {
536161105Scognet				case 0x00:
537147114Scognet					sc->sc_rev = NCR_VARIANT_FAS100A;
538147114Scognet					break;
539147114Scognet
540147114Scognet				case 0x02:
541150867Scognet					if ((uid & 0x07) == 0x02)
542150936Scognet						sc->sc_rev =
543156191Scognet						    NCR_VARIANT_FAS216;
544166063Scognet					else
545156191Scognet						sc->sc_rev =
546156191Scognet						    NCR_VARIANT_FAS236;
547156191Scognet					break;
548156191Scognet
549150867Scognet				case 0x0a:
550129198Scognet					sc->sc_rev = NCR_VARIANT_FAS366;
551129198Scognet					break;
552129198Scognet
553129198Scognet				default:
554129198Scognet					/*
555					 * We could just treat unknown chips
556					 * as ESP200 but then we would most
557					 * likely drive them out of specs.
558					 */
559					device_printf(esc->sc_dev,
560					    "Unknown chip\n");
561					error = ENXIO;
562					goto fail_lock;
563				}
564			}
565		}
566	}
567
568#ifdef ESP_SBUS_DEBUG
569	printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid);
570#endif
571
572	/*
573	 * This is the value used to start sync negotiations
574	 * Note that the NCR register "SYNCTP" is programmed
575	 * in "clocks per byte", and has a minimum value of 4.
576	 * The SCSI period used in negotiation is one-fourth
577	 * of the time (in nanoseconds) needed to transfer one byte.
578	 * Since the chip's clock is given in MHz, we have the following
579	 * formula: 4 * period = (1000 / freq) * 4
580	 */
581	sc->sc_minsync = 1000 / sc->sc_freq;
582
583	/*
584	 * Except for some variants the maximum transfer size is 64k.
585	 */
586	sc->sc_maxxfer = 64 * 1024;
587	sc->sc_maxoffset = 15;
588	sc->sc_extended_geom = 1;
589
590	/*
591	 * Alas, we must now modify the value a bit, because it's
592	 * only valid when we can switch on FASTCLK and FASTSCSI bits
593	 * in the config register 3...
594	 */
595	switch (sc->sc_rev) {
596	case NCR_VARIANT_ESP100:
597		sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT;
598		sc->sc_minsync = 0;	/* No synch on old chip? */
599		break;
600
601	case NCR_VARIANT_ESP100A:
602	case NCR_VARIANT_ESP200:
603		sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT;
604		/* Min clocks/byte is 5 */
605		sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
606		break;
607
608	case NCR_VARIANT_FAS100A:
609	case NCR_VARIANT_FAS216:
610	case NCR_VARIANT_FAS236:
611		/*
612		 * The onboard SCSI chips in Sun Ultra 1 are actually
613		 * documented to be NCR53C9X which use NCRCFG3_FCLK and
614		 * NCRCFG3_FSCSI.  BSD/OS however probes these chips as
615		 * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI
616		 * instead which seems to be correct as otherwise sync
617		 * negotiation just doesn't work.  Using NCRF9XCFG3_FCLK
618		 * and NCRF9XCFG3_FSCSI with these chips in fact also
619		 * yields Fast-SCSI speed.
620		 */
621		sc->sc_features = NCR_F_FASTSCSI;
622		sc->sc_cfg3 = NCRF9XCFG3_FCLK;
623		sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI;
624		sc->sc_maxwidth = MSG_EXT_WDTR_BUS_8_BIT;
625		sc->sc_maxxfer = 16 * 1024 * 1024;
626		break;
627
628	case NCR_VARIANT_FAS366:
629		sc->sc_maxwidth = MSG_EXT_WDTR_BUS_16_BIT;
630		sc->sc_maxxfer = 16 * 1024 * 1024;
631		break;
632	}
633
634	/*
635	 * Given that we allocate resources based on sc->sc_maxxfer it doesn't
636	 * make sense to supply a value higher than the maximum actually used.
637	 */
638	sc->sc_maxxfer = min(sc->sc_maxxfer, MAXPHYS);
639
640	/* Attach the DMA engine. */
641	error = lsi64854_attach(esc->sc_dma);
642	if (error != 0) {
643		device_printf(esc->sc_dev, "lsi64854_attach failed\n");
644		goto fail_lock;
645	}
646
647	/* Establish interrupt channel. */
648	i = 0;
649	if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ,
650	    &i, RF_SHAREABLE|RF_ACTIVE)) == NULL) {
651		device_printf(esc->sc_dev, "cannot allocate interrupt\n");
652		goto fail_lsi;
653	}
654	if (bus_setup_intr(esc->sc_dev, esc->sc_irqres,
655	    INTR_MPSAFE | INTR_TYPE_CAM, NULL, ncr53c9x_intr, sc,
656	    &esc->sc_irq)) {
657		device_printf(esc->sc_dev, "cannot set up interrupt\n");
658		error = ENXIO;
659		goto fail_ires;
660	}
661
662	/* Turn on target selection using the `DMA' method. */
663	if (sc->sc_rev != NCR_VARIANT_FAS366)
664		sc->sc_features |= NCR_F_DMASELECT;
665
666	/* Do the common parts of attachment. */
667	sc->sc_dev = esc->sc_dev;
668	error = ncr53c9x_attach(sc);
669	if (error != 0) {
670		device_printf(esc->sc_dev, "ncr53c9x_attach failed\n");
671		goto fail_intr;
672	}
673
674	return (0);
675
676 fail_intr:
677	bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
678 fail_ires:
679	bus_release_resource(esc->sc_dev, SYS_RES_IRQ,
680	    rman_get_rid(esc->sc_irqres), esc->sc_irqres);
681 fail_lsi:
682	lsi64854_detach(esc->sc_dma);
683 fail_lock:
684	NCR_LOCK_DESTROY(sc);
685	return (error);
686}
687
688static int
689espdetach(struct esp_softc *esc)
690{
691	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
692	int error;
693
694	bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
695	error = ncr53c9x_detach(sc);
696	if (error != 0)
697		return (error);
698	error = lsi64854_detach(esc->sc_dma);
699	if (error != 0)
700		return (error);
701	NCR_LOCK_DESTROY(sc);
702	bus_release_resource(esc->sc_dev, SYS_RES_IRQ,
703	    rman_get_rid(esc->sc_irqres), esc->sc_irqres);
704
705	return (0);
706}
707
708/*
709 * Glue functions
710 */
711
712#ifdef ESP_SBUS_DEBUG
713static int esp_sbus_debug = 0;
714
715static const struct {
716	const char *r_name;
717	int r_flag;
718} const esp__read_regnames [] = {
719	{ "TCL", 0},			/* 0/00 */
720	{ "TCM", 0},			/* 1/04 */
721	{ "FIFO", 0},			/* 2/08 */
722	{ "CMD", 0},			/* 3/0c */
723	{ "STAT", 0},			/* 4/10 */
724	{ "INTR", 0},			/* 5/14 */
725	{ "STEP", 0},			/* 6/18 */
726	{ "FFLAGS", 1},			/* 7/1c */
727	{ "CFG1", 1},			/* 8/20 */
728	{ "STAT2", 0},			/* 9/24 */
729	{ "CFG4", 1},			/* a/28 */
730	{ "CFG2", 1},			/* b/2c */
731	{ "CFG3", 1},			/* c/30 */
732	{ "-none", 1},			/* d/34 */
733	{ "TCH", 1},			/* e/38 */
734	{ "TCX", 1},			/* f/3c */
735};
736
737static const const struct {
738	const char *r_name;
739	int r_flag;
740} const esp__write_regnames[] = {
741	{ "TCL", 1},			/* 0/00 */
742	{ "TCM", 1},			/* 1/04 */
743	{ "FIFO", 0},			/* 2/08 */
744	{ "CMD", 0},			/* 3/0c */
745	{ "SELID", 1},			/* 4/10 */
746	{ "TIMEOUT", 1},		/* 5/14 */
747	{ "SYNCTP", 1},			/* 6/18 */
748	{ "SYNCOFF", 1},		/* 7/1c */
749	{ "CFG1", 1},			/* 8/20 */
750	{ "CCF", 1},			/* 9/24 */
751	{ "TEST", 1},			/* a/28 */
752	{ "CFG2", 1},			/* b/2c */
753	{ "CFG3", 1},			/* c/30 */
754	{ "-none", 1},			/* d/34 */
755	{ "TCH", 1},			/* e/38 */
756	{ "TCX", 1},			/* f/3c */
757};
758#endif
759
760static uint8_t
761esp_read_reg(struct ncr53c9x_softc *sc, int reg)
762{
763	struct esp_softc *esc = (struct esp_softc *)sc;
764	uint8_t v;
765
766	v = bus_read_1(esc->sc_res, reg * 4);
767
768#ifdef ESP_SBUS_DEBUG
769	if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
770		printf("RD:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ?
771		    esp__read_regnames[reg].r_name : "<***>", v);
772#endif
773
774	return (v);
775}
776
777static void
778esp_write_reg(struct ncr53c9x_softc *sc, int reg, uint8_t v)
779{
780	struct esp_softc *esc = (struct esp_softc *)sc;
781
782#ifdef ESP_SBUS_DEBUG
783	if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
784		printf("WR:%x <%s> %x\n", reg * 4, ((unsigned)reg < 0x10) ?
785		    esp__write_regnames[reg].r_name : "<***>", v);
786#endif
787
788	bus_write_1(esc->sc_res, reg * 4, v);
789}
790
791static int
792esp_dma_isintr(struct ncr53c9x_softc *sc)
793{
794	struct esp_softc *esc = (struct esp_softc *)sc;
795
796	return (DMA_ISINTR(esc->sc_dma));
797}
798
799static void
800esp_dma_reset(struct ncr53c9x_softc *sc)
801{
802	struct esp_softc *esc = (struct esp_softc *)sc;
803
804	DMA_RESET(esc->sc_dma);
805}
806
807static int
808esp_dma_intr(struct ncr53c9x_softc *sc)
809{
810	struct esp_softc *esc = (struct esp_softc *)sc;
811
812	return (DMA_INTR(esc->sc_dma));
813}
814
815static int
816esp_dma_setup(struct ncr53c9x_softc *sc, void **addr, size_t *len,
817    int datain, size_t *dmasize)
818{
819	struct esp_softc *esc = (struct esp_softc *)sc;
820
821	return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
822}
823
824static void
825esp_dma_go(struct ncr53c9x_softc *sc)
826{
827	struct esp_softc *esc = (struct esp_softc *)sc;
828
829	DMA_GO(esc->sc_dma);
830}
831
832static void
833esp_dma_stop(struct ncr53c9x_softc *sc)
834{
835	struct esp_softc *esc = (struct esp_softc *)sc;
836
837	L64854_SCSR(esc->sc_dma, L64854_GCSR(esc->sc_dma) & ~D_EN_DMA);
838}
839
840static int
841esp_dma_isactive(struct ncr53c9x_softc *sc)
842{
843	struct esp_softc *esc = (struct esp_softc *)sc;
844
845	return (DMA_ISACTIVE(esc->sc_dma));
846}
847