esp_sbus.c revision 165102
117680Spst/*-
217680Spst * Copyright (c) 2004 Scott Long
317680Spst * All rights reserved.
417680Spst *
517680Spst * Redistribution and use in source and binary forms, with or without
617680Spst * modification, are permitted provided that the following conditions
717680Spst * are met:
817680Spst * 1. Redistributions of source code must retain the above copyright
917680Spst *    notice, this list of conditions and the following disclaimer.
1017680Spst * 2. Redistributions in binary form must reproduce the above copyright
1117680Spst *    notice, this list of conditions and the following disclaimer in the
1217680Spst *    documentation and/or other materials provided with the distribution.
1317680Spst *
1417680Spst * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1517680Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1617680Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1717680Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1817680Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1917680Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2026183Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2117680Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2217680Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2356896Sfenner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2456896Sfenner * SUCH DAMAGE.
2517680Spst *
2626183Sfenner */
2717680Spst
28127675Sbms/*	$NetBSD: esp_sbus.c,v 1.31 2005/02/27 00:27:48 perry Exp $	*/
29190207Srpaulo
3017680Spst/*-
3117680Spst * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
3256896Sfenner * All rights reserved.
3356896Sfenner *
3456896Sfenner * This code is derived from software contributed to The NetBSD Foundation
3556896Sfenner * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
36127675Sbms * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
3717680Spst *
3817680Spst * Redistribution and use in source and binary forms, with or without
3917680Spst * modification, are permitted provided that the following conditions
4017680Spst * are met:
4117680Spst * 1. Redistributions of source code must retain the above copyright
4217680Spst *    notice, this list of conditions and the following disclaimer.
4317680Spst * 2. Redistributions in binary form must reproduce the above copyright
4417680Spst *    notice, this list of conditions and the following disclaimer in the
4517680Spst *    documentation and/or other materials provided with the distribution.
4617680Spst * 3. All advertising materials mentioning features or use of this software
4717680Spst *    must display the following acknowledgement:
4817680Spst *	This product includes software developed by the NetBSD
4917680Spst *	Foundation, Inc. and its contributors.
5017680Spst * 4. Neither the name of The NetBSD Foundation nor the names of its
5117680Spst *    contributors may be used to endorse or promote products derived
5217680Spst *    from this software without specific prior written permission.
5317680Spst *
5417680Spst * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
5517680Spst * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
5617680Spst * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
5717680Spst * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
5817680Spst * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5917680Spst * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
6017680Spst * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61146778Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62146778Ssam * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63146778Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
6417680Spst * POSSIBILITY OF SUCH DAMAGE.
65127675Sbms */
6617680Spst
6717680Spst#include <sys/cdefs.h>
6817680Spst__FBSDID("$FreeBSD: head/sys/dev/esp/esp_sbus.c 165102 2006-12-11 18:28:31Z mjacob $");
69146778Ssam
7017680Spst#include <sys/param.h>
7117680Spst#include <sys/systm.h>
7217680Spst#include <sys/bus.h>
7317680Spst#include <sys/kernel.h>
7417680Spst#include <sys/module.h>
7517680Spst#include <sys/resource.h>
7617680Spst
7717680Spst#include <dev/ofw/ofw_bus.h>
7817680Spst#include <dev/ofw/openfirm.h>
7917680Spst#include <machine/bus.h>
8017680Spst#include <machine/resource.h>
8117680Spst#include <sys/rman.h>
8217680Spst
8317680Spst#include <cam/cam.h>
8417680Spst#include <cam/cam_ccb.h>
8517680Spst#include <cam/scsi/scsi_all.h>
8617680Spst
8717680Spst#include <sparc64/sbus/lsi64854reg.h>
88127675Sbms#include <sparc64/sbus/lsi64854var.h>
8917680Spst#include <sparc64/sbus/sbusvar.h>
9017680Spst
9117680Spst#include <dev/esp/ncr53c9xreg.h>
9217680Spst#include <dev/esp/ncr53c9xvar.h>
9317680Spst
9417680Spst/* #define ESP_SBUS_DEBUG */
9517680Spst
9617680Spststruct esp_softc {
9717680Spst	struct ncr53c9x_softc	sc_ncr53c9x;	/* glue to MI code */
9817680Spst	struct device		*sc_dev;
9917680Spst
10017680Spst	int			sc_rid;
10117680Spst	struct resource		*sc_res;
102146778Ssam	bus_space_handle_t	sc_regh;
10317680Spst	bus_space_tag_t		sc_regt;
10417680Spst
10517680Spst	int			sc_irqrid;
10617680Spst	struct resource		*sc_irqres;
10717680Spst	void			*sc_irq;
10817680Spst
10917680Spst	struct lsi64854_softc	*sc_dma;	/* pointer to my DMA */
11017680Spst};
111146778Ssam
11298527Sfennerstatic devclass_t	esp_devclass;
11398527Sfenner
11498527Sfennerstatic int	esp_probe(device_t);
11517680Spststatic int	esp_dma_attach(device_t);
11617680Spststatic int	esp_dma_detach(device_t);
117146778Ssamstatic int	esp_sbus_attach(device_t);
11817680Spststatic int	esp_sbus_detach(device_t);
11998527Sfennerstatic int	esp_suspend(device_t);
120146778Ssamstatic int	esp_resume(device_t);
12198527Sfenner
12298527Sfennerstatic device_method_t esp_dma_methods[] = {
12398527Sfenner	DEVMETHOD(device_probe,		esp_probe),
12498527Sfenner	DEVMETHOD(device_attach,	esp_dma_attach),
12598527Sfenner	DEVMETHOD(device_detach,	esp_dma_detach),
126146778Ssam	DEVMETHOD(device_suspend,	esp_suspend),
12798527Sfenner	DEVMETHOD(device_resume,	esp_resume),
12817680Spst	{0, 0}
129146778Ssam};
13017680Spst
13117680Spststatic driver_t esp_dma_driver = {
13217680Spst	"esp",
13317680Spst	esp_dma_methods,
13417680Spst	sizeof(struct esp_softc)
13517680Spst};
13617680Spst
13717680SpstDRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0);
13817680SpstMODULE_DEPEND(esp, dma, 1, 1, 1);
13917680Spst
14017680Spststatic device_method_t esp_sbus_methods[] = {
14117680Spst	DEVMETHOD(device_probe,		esp_probe),
14217680Spst	DEVMETHOD(device_attach,	esp_sbus_attach),
14317680Spst	DEVMETHOD(device_detach,	esp_sbus_detach),
14417680Spst	DEVMETHOD(device_suspend,	esp_suspend),
14517680Spst	DEVMETHOD(device_resume,	esp_resume),
14617680Spst	{0, 0}
14717680Spst};
14817680Spst
14917680Spststatic driver_t esp_sbus_driver = {
15017680Spst	"esp",
15117680Spst	esp_sbus_methods,
15298527Sfenner	sizeof(struct esp_softc)
153127675Sbms};
15417680Spst
15517680SpstDRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0);
15617680SpstMODULE_DEPEND(esp, sbus, 1, 1, 1);
15717680Spst
15817680SpstMODULE_DEPEND(esp, cam, 1, 1, 1);
15917680Spst
16017680Spst/*
16117680Spst * Functions and the switch for the MI code.
16217680Spst */
16317680Spststatic u_char	esp_read_reg(struct ncr53c9x_softc *, int);
164147904Ssamstatic void	esp_write_reg(struct ncr53c9x_softc *, int, u_char);
165147904Ssamstatic int	esp_dma_isintr(struct ncr53c9x_softc *);
166147904Ssamstatic void	esp_dma_reset(struct ncr53c9x_softc *);
167147904Ssamstatic int	esp_dma_intr(struct ncr53c9x_softc *);
168147904Ssamstatic int	esp_dma_setup(struct ncr53c9x_softc *, caddr_t *, size_t *,
169147904Ssam			      int, size_t *);
17098527Sfennerstatic void	esp_dma_go(struct ncr53c9x_softc *);
17117680Spststatic void	esp_dma_stop(struct ncr53c9x_softc *);
17217680Spststatic int	esp_dma_isactive(struct ncr53c9x_softc *);
17317680Spststatic int	espattach(struct esp_softc *, struct ncr53c9x_glue *);
17417680Spst
17517680Spststatic struct ncr53c9x_glue esp_sbus_glue = {
17617680Spst	esp_read_reg,
17717680Spst	esp_write_reg,
17898527Sfenner	esp_dma_isintr,
17917680Spst	esp_dma_reset,
18017680Spst	esp_dma_intr,
18198527Sfenner	esp_dma_setup,
18217680Spst	esp_dma_go,
18398527Sfenner	esp_dma_stop,
18417680Spst	esp_dma_isactive,
18517680Spst	NULL,			/* gl_clear_latched_intr */
18617680Spst};
18717680Spst
18817680Spststatic int
18917680Spstesp_probe(device_t dev)
19017680Spst{
19117680Spst	const char *name;
19217680Spst
19317680Spst	name = ofw_bus_get_name(dev);
19417680Spst	if (strcmp("SUNW,fas", name) == 0) {
19517680Spst		device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI");
19617680Spst	        return (BUS_PROBE_DEFAULT);
19717680Spst	} else if (strcmp("esp", name) == 0) {
19817680Spst		device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI");
19917680Spst	        return (BUS_PROBE_DEFAULT);
20017680Spst	}
201162021Ssam
20217680Spst	return (ENXIO);
20317680Spst}
20417680Spst
20517680Spststatic int
20617680Spstesp_sbus_attach(device_t dev)
20717680Spst{
20817680Spst	struct esp_softc *esc;
209162021Ssam	struct ncr53c9x_softc *sc;
21017680Spst	struct lsi64854_softc *lsc;
21117680Spst	device_t *children;
21217680Spst	const char *name;
21317680Spst	phandle_t node;
21417680Spst	int burst, error, i, nchildren, slot;
21517680Spst
21617680Spst	esc = device_get_softc(dev);
21798527Sfenner	bzero(esc, sizeof(struct esp_softc));
21898527Sfenner	sc = &esc->sc_ncr53c9x;
21917680Spst
22098527Sfenner	lsc = NULL;
22117680Spst	esc->sc_dev = dev;
22298527Sfenner	name = ofw_bus_get_name(dev);
22317680Spst	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		    NULL,			/* 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
501/*
502 * Attach this instance, and then all the sub-devices
503 */
504static int
505espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
506{
507	struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
508	unsigned int uid = 0;
509	int error;
510
511	/*
512	 * The `ESC' DMA chip must be reset before we can access
513	 * the ESP registers.
514	 */
515	if (esc->sc_dma->sc_rev == DMAREV_ESC)
516		DMA_RESET(esc->sc_dma);
517
518	/*
519	 * Set up glue for MI code early; we use some of it here.
520	 */
521	sc->sc_glue = gluep;
522
523	/* gimme MHz */
524	sc->sc_freq /= 1000000;
525
526	/*
527	 * XXX More of this should be in ncr53c9x_attach(), but
528	 * XXX should we really poke around the chip that much in
529	 * XXX the MI code?  Think about this more...
530	 */
531
532	/*
533	 * Read the part-unique ID code of the SCSI chip. The contained
534	 * value is only valid if all of the following conditions are met:
535	 * - After power-up or chip reset.
536	 * - Before any value is written to this register.
537	 * - The NCRCFG2_FE bit is set.
538	 * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued.
539	 */
540	NCRCMD(sc, NCRCMD_RSTCHIP);
541	NCRCMD(sc, NCRCMD_NOP);
542	sc->sc_cfg2 = NCRCFG2_FE;
543	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
544	NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
545	uid = NCR_READ_REG(sc, NCR_UID);
546
547	/*
548	 * It is necessary to try to load the 2nd config register here,
549	 * to find out what rev the esp chip is, else the ncr53c9x_reset
550	 * will not set up the defaults correctly.
551	 */
552	sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
553	NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
554	sc->sc_cfg2 = 0;
555	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
556	sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
557	NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
558
559	if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
560	    (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
561		sc->sc_rev = NCR_VARIANT_ESP100;
562	} else {
563		sc->sc_cfg2 = NCRCFG2_SCSI2;
564		NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
565		sc->sc_cfg3 = 0;
566		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
567		sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
568		NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
569		if (NCR_READ_REG(sc, NCR_CFG3) !=
570		    (NCRCFG3_CDB | NCRCFG3_FCLK)) {
571			sc->sc_rev = NCR_VARIANT_ESP100A;
572		} else {
573			/* NCRCFG2_FE enables > 64K transfers */
574			sc->sc_cfg2 |= NCRCFG2_FE;
575			sc->sc_cfg3 = 0;
576			NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
577			if (sc->sc_freq <= 25)
578				sc->sc_rev = NCR_VARIANT_ESP200;
579			else {
580				switch ((uid & 0xf8) >> 3) {
581				case 0x00:
582					sc->sc_rev = NCR_VARIANT_FAS100A;
583					break;
584				case 0x02:
585					if ((uid & 0x07) == 0x02)
586						sc->sc_rev = NCR_VARIANT_FAS216;
587					else
588						sc->sc_rev = NCR_VARIANT_FAS236;
589					break;
590				case 0x0a:
591					sc->sc_rev = NCR_VARIANT_FAS366;
592					break;
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|INTR_MPSAFE, 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	uint32_t csr;
848
849	csr = L64854_GCSR(esc->sc_dma);
850	csr &= ~D_EN_DMA;
851	L64854_SCSR(esc->sc_dma, csr);
852}
853
854static int
855esp_dma_isactive(struct ncr53c9x_softc *sc)
856{
857	struct esp_softc *esc = (struct esp_softc *)sc;
858
859	return (DMA_ISACTIVE(esc->sc_dma));
860}
861