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