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