xref: /original-bsd/sys/sparc/sbus/sbus.c (revision 3705696b)
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