1 /* $NetBSD: sbus.c,v 1.6 1995/02/01 12:37:28 pk Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratory. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. All advertising materials mentioning features or use of this software 25 * must display the following acknowledgement: 26 * This product includes software developed by the University of 27 * California, Berkeley and its contributors. 28 * 4. Neither the name of the University nor the names of its contributors 29 * may be used to endorse or promote products derived from this software 30 * without specific prior written permission. 31 * 32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42 * SUCH DAMAGE. 43 * 44 * @(#)sbus.c 8.1 (Berkeley) 6/11/93 45 */ 46 47 /* 48 * Sbus stuff. 49 */ 50 51 #include <sys/param.h> 52 #include <sys/device.h> 53 54 #include <machine/autoconf.h> 55 56 #include <sparc/dev/sbusreg.h> 57 #include <sparc/dev/sbusvar.h> 58 59 /* autoconfiguration driver */ 60 void sbus_attach __P((struct device *, struct device *, void *)); 61 int sbus_match __P((struct device *, void *, void *)); 62 struct cfdriver sbuscd = { 63 NULL, "sbus", sbus_match, sbus_attach, 64 DV_DULL, sizeof(struct sbus_softc) 65 }; 66 67 /* 68 * Print the location of some sbus-attached device (called just 69 * before attaching that device). If `sbus' is not NULL, the 70 * device was found but not configured; print the sbus as well. 71 * Return UNCONF (config_find ignores this if the device was configured). 72 */ 73 int 74 sbus_print(args, sbus) 75 void *args; 76 char *sbus; 77 { 78 register struct confargs *ca = args; 79 80 if (sbus) 81 printf("%s at %s", ca->ca_ra.ra_name, sbus); 82 printf(" slot %d offset 0x%x", ca->ca_slot, ca->ca_offset); 83 return (UNCONF); 84 } 85 86 int 87 sbus_match(parent, vcf, aux) 88 struct device *parent; 89 void *vcf, *aux; 90 { 91 struct cfdata *cf = vcf; 92 register struct confargs *ca = aux; 93 register struct romaux *ra = &ca->ca_ra; 94 95 if (cputyp==CPU_SUN4) 96 return (0); 97 return (strcmp(cf->cf_driver->cd_name, ra->ra_name) == 0); 98 } 99 100 /* 101 * Attach an Sbus. 102 */ 103 void 104 sbus_attach(parent, self, aux) 105 struct device *parent; 106 struct device *self; 107 void *aux; 108 { 109 register struct sbus_softc *sc = (struct sbus_softc *)self; 110 struct confargs *ca = aux; 111 register struct romaux *ra = &ca->ca_ra; 112 register int base, node, slot; 113 register int i; 114 register char *name; 115 struct confargs oca; 116 117 /* 118 * XXX there is only one Sbus, for now -- do not know how to 119 * address children on others 120 */ 121 if (sc->sc_dev.dv_unit > 0) { 122 printf(" unsupported\n"); 123 return; 124 } 125 126 /* 127 * Record clock frequency for synchronous SCSI. 128 * IS THIS THE CORRECT DEFAULT?? 129 */ 130 node = ra->ra_node; 131 sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000); 132 printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq)); 133 134 if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "sbus") == 0) 135 oca.ca_ra.ra_bp = ra->ra_bp + 1; 136 else 137 oca.ca_ra.ra_bp = NULL; 138 139 /* 140 * Loop through ROM children, fixing any relative addresses 141 * and then configuring each device. 142 */ 143 for (node = firstchild(node); node; node = nextsibling(node)) { 144 name = getpropstring(node, "name"); 145 if (!romprop(&oca.ca_ra, name, node)) 146 continue; 147 base = (int)oca.ca_ra.ra_paddr; 148 if (SBUS_ABS(base)) { 149 oca.ca_slot = SBUS_ABS_TO_SLOT(base); 150 oca.ca_offset = SBUS_ABS_TO_OFFSET(base); 151 } else { 152 oca.ca_slot = slot = oca.ca_ra.ra_iospace; 153 oca.ca_offset = base; 154 oca.ca_ra.ra_paddr = (void *)SBUS_ADDR(slot, base); 155 /* Fix any remaining register banks */ 156 for (i = 1; i < oca.ca_ra.ra_nreg; i++) { 157 base = (int)oca.ca_ra.ra_reg[i].rr_paddr; 158 oca.ca_ra.ra_reg[i].rr_paddr = 159 (void *)SBUS_ADDR(slot, base); 160 } 161 } 162 oca.ca_bustype = BUS_SBUS; 163 (void) config_found(&sc->sc_dev, (void *)&oca, sbus_print); 164 } 165 } 166 167 /* 168 * Each attached device calls sbus_establish after it initializes 169 * its sbusdev portion. 170 */ 171 void 172 sbus_establish(sd, dev) 173 register struct sbusdev *sd; 174 register struct device *dev; 175 { 176 register struct sbus_softc *sc = (struct sbus_softc *)dev->dv_parent; 177 178 sd->sd_dev = dev; 179 sd->sd_bchain = sc->sc_sbdev; 180 sc->sc_sbdev = sd; 181 } 182 183 /* 184 * Reset the given sbus. (???) 185 */ 186 void 187 sbusreset(sbus) 188 int sbus; 189 { 190 register struct sbusdev *sd; 191 struct sbus_softc *sc = sbuscd.cd_devs[sbus]; 192 struct device *dev; 193 194 printf("reset %s:", sc->sc_dev.dv_xname); 195 for (sd = sc->sc_sbdev; sd != NULL; sd = sd->sd_bchain) { 196 if (sd->sd_reset) { 197 dev = sd->sd_dev; 198 (*sd->sd_reset)(dev); 199 printf(" %s", dev->dv_xname); 200 } 201 } 202 } 203