1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * All advertising materials mentioning features or use of this software 10 * must display the following acknowledgement: 11 * This product includes software developed by the University of 12 * California, Lawrence Berkeley Laboratory. 13 * 14 * %sccs.include.redist.c% 15 * 16 * @(#)sbus.c 8.1 (Berkeley) 06/11/93 17 * 18 * from: $Header: sbus.c,v 1.10 92/11/26 02:28:13 torek Exp $ (LBL) 19 */ 20 21 /* 22 * Sbus stuff. 23 */ 24 25 #include <sys/param.h> 26 #include <sys/device.h> 27 28 #include <machine/autoconf.h> 29 30 #include <sparc/sbus/sbusreg.h> 31 #include <sparc/sbus/sbusvar.h> 32 33 /* autoconfiguration driver */ 34 void sbus_attach __P((struct device *, struct device *, void *)); 35 struct cfdriver sbuscd = 36 { NULL, "sbus", matchbyname, sbus_attach, 37 DV_DULL, sizeof(struct sbus_softc) }; 38 39 /* 40 * Print the location of some sbus-attached device (called just 41 * before attaching that device). If `sbus' is not NULL, the 42 * device was found but not configured; print the sbus as well. 43 * Return UNCONF (config_find ignores this if the device was configured). 44 */ 45 int 46 sbus_print(args, sbus) 47 void *args; 48 char *sbus; 49 { 50 register struct sbus_attach_args *sa = args; 51 52 if (sbus) 53 printf("%s at %s", sa->sa_ra.ra_name, sbus); 54 printf(" slot %d offset 0x%x", sa->sa_slot, sa->sa_offset); 55 return (UNCONF); 56 } 57 58 /* 59 * Attach an Sbus. 60 */ 61 void 62 sbus_attach(parent, self, aux) 63 struct device *parent; 64 struct device *self; 65 void *aux; 66 { 67 register struct sbus_softc *sc = (struct sbus_softc *)self; 68 register int base, node, slot; 69 register char *name; 70 struct sbus_attach_args sa; 71 register struct romaux *ra; 72 73 /* 74 * XXX there is only one Sbus, for now -- do not know how to 75 * address children on others 76 */ 77 if (sc->sc_dev.dv_unit > 0) { 78 printf(" unsupported\n"); 79 return; 80 } 81 82 /* 83 * Record clock frequency for synchronous SCSI. 84 * IS THIS THE CORRECT DEFAULT?? 85 */ 86 ra = aux; 87 node = ra->ra_node; 88 sc->sc_clockfreq = getpropint(node, "clock-frequency", 25*1000*1000); 89 printf(": clock = %s MHz\n", clockfreq(sc->sc_clockfreq)); 90 91 if (ra->ra_bp != NULL && strcmp(ra->ra_bp->name, "sbus") == 0) 92 sa.sa_ra.ra_bp = ra->ra_bp + 1; 93 else 94 sa.sa_ra.ra_bp = NULL; 95 96 /* 97 * Loop through ROM children, fixing any relative addresses 98 * and then configuring each device. 99 */ 100 for (node = firstchild(node); node; node = nextsibling(node)) { 101 name = getpropstring(node, "name"); 102 if (!romprop(&sa.sa_ra, name, node)) 103 continue; 104 base = (int)sa.sa_ra.ra_paddr; 105 if (SBUS_ABS(base)) { 106 sa.sa_slot = SBUS_ABS_TO_SLOT(base); 107 sa.sa_offset = SBUS_ABS_TO_OFFSET(base); 108 } else { 109 sa.sa_slot = slot = sa.sa_ra.ra_iospace; 110 sa.sa_offset = base; 111 sa.sa_ra.ra_paddr = (void *)SBUS_ADDR(slot, base); 112 } 113 (void) config_found(&sc->sc_dev, (void *)&sa, sbus_print); 114 } 115 } 116 117 /* 118 * Each attached device calls sbus_establish after it initializes 119 * its sbusdev portion. 120 */ 121 void 122 sbus_establish(sd, dev) 123 register struct sbusdev *sd; 124 register struct device *dev; 125 { 126 register struct sbus_softc *sc = (struct sbus_softc *)dev->dv_parent; 127 128 sd->sd_dev = dev; 129 sd->sd_bchain = sc->sc_sbdev; 130 sc->sc_sbdev = sd; 131 } 132 133 /* 134 * Reset the given sbus. (???) 135 */ 136 void 137 sbusreset(sbus) 138 int sbus; 139 { 140 register struct sbusdev *sd; 141 struct sbus_softc *sc = sbuscd.cd_devs[sbus]; 142 struct device *dev; 143 144 printf("reset %s:", sc->sc_dev.dv_xname); 145 for (sd = sc->sc_sbdev; sd != NULL; sd = sd->sd_bchain) { 146 if (sd->sd_reset) { 147 dev = sd->sd_dev; 148 (*sd->sd_reset)(dev); 149 printf(" %s", dev->dv_xname); 150 } 151 } 152 } 153