155140Storek /* 255140Storek * Copyright (c) 1992 The Regents of the University of California. 355140Storek * 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 12*59217Storek * California, Lawrence Berkeley Laboratory. 1355503Sbostic * 1455140Storek * %sccs.include.redist.c% 1555140Storek * 16*59217Storek * @(#)sbus.c 7.4 (Berkeley) 04/20/93 1755140Storek * 18*59217Storek * 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 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 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; 71*59217Storek 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 */ 86*59217Storek ra = aux; 87*59217Storek 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 91*59217Storek if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "sbus") == 0) 92*59217Storek sa.sa_ra.ra_bp = ra->ra_bp + 1; 93*59217Storek else 94*59217Storek sa.sa_ra.ra_bp = NULL; 95*59217Storek 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 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 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