xref: /csrg-svn/sys/sparc/sbus/sbus.c (revision 63322)
155140Storek /*
2*63322Sbostic  * Copyright (c) 1992, 1993
3*63322Sbostic  *	The Regents of the University of California.  All rights reserved.
455140Storek  *
555140Storek  * This software was developed by the Computer Systems Engineering group
655140Storek  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
755140Storek  * contributed to Berkeley.
855140Storek  *
955503Sbostic  * All advertising materials mentioning features or use of this software
1055503Sbostic  * must display the following acknowledgement:
1155503Sbostic  *	This product includes software developed by the University of
1259217Storek  *	California, Lawrence Berkeley Laboratory.
1355503Sbostic  *
1455140Storek  * %sccs.include.redist.c%
1555140Storek  *
16*63322Sbostic  *	@(#)sbus.c	8.1 (Berkeley) 06/11/93
1755140Storek  *
1859217Storek  * from: $Header: sbus.c,v 1.10 92/11/26 02:28:13 torek Exp $ (LBL)
1955140Storek  */
2055140Storek 
2155140Storek /*
2255140Storek  * Sbus stuff.
2355140Storek  */
2455140Storek 
2556540Sbostic #include <sys/param.h>
2656540Sbostic #include <sys/device.h>
2755140Storek 
2856540Sbostic #include <machine/autoconf.h>
2955140Storek 
3056540Sbostic #include <sparc/sbus/sbusreg.h>
3156540Sbostic #include <sparc/sbus/sbusvar.h>
3255140Storek 
3355140Storek /* autoconfiguration driver */
3455140Storek void	sbus_attach __P((struct device *, struct device *, void *));
3555140Storek struct cfdriver sbuscd =
3655140Storek     { NULL, "sbus", matchbyname, sbus_attach,
3755140Storek       DV_DULL, sizeof(struct sbus_softc) };
3855140Storek 
3955140Storek /*
4055140Storek  * Print the location of some sbus-attached device (called just
4155140Storek  * before attaching that device).  If `sbus' is not NULL, the
4255140Storek  * device was found but not configured; print the sbus as well.
4355140Storek  * Return UNCONF (config_find ignores this if the device was configured).
4455140Storek  */
4555140Storek int
sbus_print(args,sbus)4655140Storek sbus_print(args, sbus)
4755140Storek 	void *args;
4855140Storek 	char *sbus;
4955140Storek {
5055140Storek 	register struct sbus_attach_args *sa = args;
5155140Storek 
5255140Storek 	if (sbus)
5355140Storek 		printf("%s at %s", sa->sa_ra.ra_name, sbus);
5455140Storek 	printf(" slot %d offset 0x%x", sa->sa_slot, sa->sa_offset);
5555140Storek 	return (UNCONF);
5655140Storek }
5755140Storek 
5855140Storek /*
5955140Storek  * Attach an Sbus.
6055140Storek  */
6155140Storek void
sbus_attach(parent,self,aux)6255140Storek sbus_attach(parent, self, aux)
6355140Storek 	struct device *parent;
6455140Storek 	struct device *self;
6555140Storek 	void *aux;
6655140Storek {
6755140Storek 	register struct sbus_softc *sc = (struct sbus_softc *)self;
6855140Storek 	register int base, node, slot;
6955140Storek 	register char *name;
7055140Storek 	struct sbus_attach_args sa;
7159217Storek 	register struct romaux *ra;
7255140Storek 
7355140Storek 	/*
7455140Storek 	 * XXX there is only one Sbus, for now -- do not know how to
7555140Storek 	 * address children on others
7655140Storek 	 */
7755140Storek 	if (sc->sc_dev.dv_unit > 0) {
7855140Storek 		printf(" unsupported\n");
7955140Storek 		return;
8055140Storek 	}
8155140Storek 
8255140Storek 	/*
8355140Storek 	 * Record clock frequency for synchronous SCSI.
8455140Storek 	 * IS THIS THE CORRECT DEFAULT??
8555140Storek 	 */
8659217Storek 	ra = aux;
8759217Storek 	node = ra->ra_node;
8855140Storek 	sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000);
8955140Storek 	printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq));
9055140Storek 
9159217Storek 	if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "sbus") == 0)
9259217Storek 		sa.sa_ra.ra_bp = ra->ra_bp + 1;
9359217Storek 	else
9459217Storek 		sa.sa_ra.ra_bp = NULL;
9559217Storek 
9655140Storek 	/*
9755140Storek 	 * Loop through ROM children, fixing any relative addresses
9855140Storek 	 * and then configuring each device.
9955140Storek 	 */
10055140Storek 	for (node = firstchild(node); node; node = nextsibling(node)) {
10155140Storek 		name = getpropstring(node, "name");
10255140Storek 		if (!romprop(&sa.sa_ra, name, node))
10355140Storek 			continue;
10455140Storek 		base = (int)sa.sa_ra.ra_paddr;
10555140Storek 		if (SBUS_ABS(base)) {
10655140Storek 			sa.sa_slot = SBUS_ABS_TO_SLOT(base);
10755140Storek 			sa.sa_offset = SBUS_ABS_TO_OFFSET(base);
10855140Storek 		} else {
10955140Storek 			sa.sa_slot = slot = sa.sa_ra.ra_iospace;
11055140Storek 			sa.sa_offset = base;
11155140Storek 			sa.sa_ra.ra_paddr = (void *)SBUS_ADDR(slot, base);
11255140Storek 		}
11355140Storek 		(void) config_found(&sc->sc_dev, (void *)&sa, sbus_print);
11455140Storek 	}
11555140Storek }
11655140Storek 
11755140Storek /*
11855140Storek  * Each attached device calls sbus_establish after it initializes
11955140Storek  * its sbusdev portion.
12055140Storek  */
12155140Storek void
sbus_establish(sd,dev)12255140Storek sbus_establish(sd, dev)
12355140Storek 	register struct sbusdev *sd;
12455140Storek 	register struct device *dev;
12555140Storek {
12655140Storek 	register struct sbus_softc *sc = (struct sbus_softc *)dev->dv_parent;
12755140Storek 
12855140Storek 	sd->sd_dev = dev;
12955140Storek 	sd->sd_bchain = sc->sc_sbdev;
13055140Storek 	sc->sc_sbdev = sd;
13155140Storek }
13255140Storek 
13355140Storek /*
13455140Storek  * Reset the given sbus. (???)
13555140Storek  */
13655140Storek void
sbusreset(sbus)13755140Storek sbusreset(sbus)
13855140Storek 	int sbus;
13955140Storek {
14055140Storek 	register struct sbusdev *sd;
14155140Storek 	struct sbus_softc *sc = sbuscd.cd_devs[sbus];
14255140Storek 	struct device *dev;
14355140Storek 
14455140Storek 	printf("reset %s:", sc->sc_dev.dv_xname);
14555140Storek 	for (sd = sc->sc_sbdev; sd != NULL; sd = sd->sd_bchain) {
14655140Storek 		if (sd->sd_reset) {
14755140Storek 			dev = sd->sd_dev;
14855140Storek 			(*sd->sd_reset)(dev);
14955140Storek 			printf(" %s", dev->dv_xname);
15055140Storek 		}
15155140Storek 	}
15255140Storek }
153