Deleted Added
full compact
ofwbus.c (94755) ofwbus.c (99652)
1/*
2 * Copyright 1998 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all

--- 38 unchanged lines hidden (view full) ---

47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09
54 *
1/*
2 * Copyright 1998 Massachusetts Institute of Technology
3 *
4 * Permission to use, copy, modify, and distribute this software and
5 * its documentation for any purpose and without fee is hereby
6 * granted, provided that both the above copyright notice and this
7 * permission notice appear in all copies, that both the above
8 * copyright notice and this permission notice appear in all

--- 38 unchanged lines hidden (view full) ---

47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51 * SUCH DAMAGE.
52 *
53 * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09
54 *
55 * $FreeBSD: head/sys/powerpc/aim/nexus.c 94755 2002-04-15 12:29:18Z benno $
55 * $FreeBSD: head/sys/powerpc/aim/nexus.c 99652 2002-07-09 11:13:33Z benno $
56 */
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/bus.h>
61#include <sys/cons.h>
62#include <sys/kernel.h>
63#include <sys/malloc.h>
64
65#include <dev/ofw/openfirm.h>
66
67#include <machine/bus.h>
68#include <machine/frame.h>
56 */
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/bus.h>
61#include <sys/cons.h>
62#include <sys/kernel.h>
63#include <sys/malloc.h>
64
65#include <dev/ofw/openfirm.h>
66
67#include <machine/bus.h>
68#include <machine/frame.h>
69#include <machine/intr_machdep.h>
69#include <machine/nexusvar.h>
70#include <machine/resource.h>
71
70#include <machine/nexusvar.h>
71#include <machine/resource.h>
72
73#include <sys/rman.h>
74
75#include "pic_if.h"
76
72/*
73 * The nexus (which is a pseudo-bus actually) iterates over the nodes that
74 * exist in OpenFirmware and adds them as devices to this bus so that drivers
75 * can be attached to them.
76 *
77 * Maybe this code should get into dev/ofw to some extent, as some of it should
78 * work for all OpenFirmware based machines...
79 */
80
81static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information");
82
83struct nexus_devinfo {
84 phandle_t ndi_node;
85 /* Some common properties. */
86 char *ndi_name;
87 char *ndi_device_type;
77/*
78 * The nexus (which is a pseudo-bus actually) iterates over the nodes that
79 * exist in OpenFirmware and adds them as devices to this bus so that drivers
80 * can be attached to them.
81 *
82 * Maybe this code should get into dev/ofw to some extent, as some of it should
83 * work for all OpenFirmware based machines...
84 */
85
86static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information");
87
88struct nexus_devinfo {
89 phandle_t ndi_node;
90 /* Some common properties. */
91 char *ndi_name;
92 char *ndi_device_type;
93 char *ndi_compatible;
88};
89
90struct nexus_softc {
94};
95
96struct nexus_softc {
97 device_t sc_pic;
91};
92
98};
99
93static int nexus_probe(device_t);
94static void nexus_probe_nomatch(device_t, device_t);
95static int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
96static int nexus_write_ivar(device_t, device_t, int, uintptr_t);
100/*
101 * Device interface
102 */
103static int nexus_probe(device_t);
104static void nexus_probe_nomatch(device_t, device_t);
97
105
106/*
107 * Bus interface
108 */
109static int nexus_read_ivar(device_t, device_t, int, uintptr_t *);
110static int nexus_write_ivar(device_t, device_t, int, uintptr_t);
111static int nexus_setup_intr(device_t, device_t, struct resource *, int,
112 driver_intr_t *, void *, void **);
113static int nexus_teardown_intr(device_t, device_t, struct resource *,
114 void *);
115static struct resource *nexus_alloc_resource(device_t, device_t, int, int *,
116 u_long, u_long, u_long, u_int);
117static int nexus_activate_resource(device_t, device_t, int, int,
118 struct resource *);
119static int nexus_deactivate_resource(device_t, device_t, int, int,
120 struct resource *);
121static int nexus_release_resource(device_t, device_t, int, int,
122 struct resource *);
123
124/*
125 * Local routines
126 */
127static device_t create_device_from_node(device_t, phandle_t);
128
98static device_method_t nexus_methods[] = {
99 /* Device interface */
100 DEVMETHOD(device_probe, nexus_probe),
101 DEVMETHOD(device_attach, bus_generic_attach),
102 DEVMETHOD(device_detach, bus_generic_detach),
103 DEVMETHOD(device_shutdown, bus_generic_shutdown),
104 DEVMETHOD(device_suspend, bus_generic_suspend),
105 DEVMETHOD(device_resume, bus_generic_resume),
106
107 /* Bus interface. Resource management is business of the children... */
108 DEVMETHOD(bus_print_child, bus_generic_print_child),
109 DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
110 DEVMETHOD(bus_read_ivar, nexus_read_ivar),
111 DEVMETHOD(bus_write_ivar, nexus_write_ivar),
129static device_method_t nexus_methods[] = {
130 /* Device interface */
131 DEVMETHOD(device_probe, nexus_probe),
132 DEVMETHOD(device_attach, bus_generic_attach),
133 DEVMETHOD(device_detach, bus_generic_detach),
134 DEVMETHOD(device_shutdown, bus_generic_shutdown),
135 DEVMETHOD(device_suspend, bus_generic_suspend),
136 DEVMETHOD(device_resume, bus_generic_resume),
137
138 /* Bus interface. Resource management is business of the children... */
139 DEVMETHOD(bus_print_child, bus_generic_print_child),
140 DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
141 DEVMETHOD(bus_read_ivar, nexus_read_ivar),
142 DEVMETHOD(bus_write_ivar, nexus_write_ivar),
143 DEVMETHOD(bus_setup_intr, nexus_setup_intr),
144 DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
145 DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
146 DEVMETHOD(bus_activate_resource, nexus_activate_resource),
147 DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
148 DEVMETHOD(bus_release_resource, nexus_release_resource),
112
113 { 0, 0 }
114};
115
116static driver_t nexus_driver = {
117 "nexus",
118 nexus_methods,
119 sizeof(struct nexus_softc),
120};
121
122static devclass_t nexus_devclass;
123
124DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
125
126static int
127nexus_probe(device_t dev)
128{
129 phandle_t root;
149
150 { 0, 0 }
151};
152
153static driver_t nexus_driver = {
154 "nexus",
155 nexus_methods,
156 sizeof(struct nexus_softc),
157};
158
159static devclass_t nexus_devclass;
160
161DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
162
163static int
164nexus_probe(device_t dev)
165{
166 phandle_t root;
130 phandle_t child, new_node, temp_node;
131 device_t cdev;
132 struct nexus_devinfo *dinfo;
167 phandle_t pic, cpus, child, new_node, temp_node;
133 struct nexus_softc *sc;
168 struct nexus_softc *sc;
134 char *name, *type;
135
136 if ((root = OF_peer(0)) == -1)
137 panic("nexus_probe: OF_peer failed.");
138
169
170 if ((root = OF_peer(0)) == -1)
171 panic("nexus_probe: OF_peer failed.");
172
173 sc = device_get_softc(dev);
174
175 if ((cpus = OF_finddevice("/cpus")) != -1) {
176 for (child = OF_child(cpus); child; child = OF_peer(child))
177 (void)create_device_from_node(dev, child);
178 }
179
180 if ((child = OF_finddevice("/chosen")) == -1)
181 printf("nexus_probe: can't find /chosen");
182
183 if (OF_getprop(child, "interrupt-controller", &pic, 4) != 4)
184 printf("nexus_probe: can't get interrupt-controller");
185
186 sc->sc_pic = create_device_from_node(dev, pic);
187
188 if (sc->sc_pic == NULL)
189 printf("nexus_probe: failed to create PIC device");
190
139 child = root;
140 while (child != 0) {
191 child = root;
192 while (child != 0) {
141 OF_getprop_alloc(child, "name", 1, (void **)&name);
142 OF_getprop_alloc(child, "device_type", 1, (void **)&type);
143 cdev = device_add_child(dev, NULL, -1);
144 if (cdev != NULL) {
145 dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
146 dinfo->ndi_node = child;
147 dinfo->ndi_name = name;
148 dinfo->ndi_device_type = type;
149 device_set_ivars(cdev, dinfo);
150 } else
151 free(name, M_OFWPROP);
193 if (child != pic)
194 (void)create_device_from_node(dev, child);
152
195
153next:
154 new_node = OF_child(child);
196 if (child == cpus)
197 new_node = 0;
198 else
199 new_node = OF_child(child);
155 if (new_node == -1)
200 if (new_node == -1)
156 panic("nexus_probe: OF_child return -1");
201 panic("nexus_probe: OF_child returned -1");
157 if (new_node == 0)
158 new_node = OF_peer(child);
159 if (new_node == 0) {
160 temp_node = child;
161 while (new_node == 0) {
162 temp_node = OF_parent(temp_node);
163 if (temp_node == 0)
164 break;
165 new_node = OF_peer(temp_node);
166 }
167 }
168 child = new_node;
169 }
170 device_set_desc(dev, "OpenFirmware Nexus device");
202 if (new_node == 0)
203 new_node = OF_peer(child);
204 if (new_node == 0) {
205 temp_node = child;
206 while (new_node == 0) {
207 temp_node = OF_parent(temp_node);
208 if (temp_node == 0)
209 break;
210 new_node = OF_peer(temp_node);
211 }
212 }
213 child = new_node;
214 }
215 device_set_desc(dev, "OpenFirmware Nexus device");
216
217 {
218 u_int *foo = 0xf8000020;
219 pmap_kenter(0xf8000000, 0xf8000000);
220 printf(">>> uni_n_clock_ctl = %08x\n", *foo);
221 pmap_kremove(0xf8000000);
222 }
171 return (0);
172}
173
174static void
175nexus_probe_nomatch(device_t dev, device_t child)
176{
177 char *name, *type;
178

--- 23 unchanged lines hidden (view full) ---

202 *result = dinfo->ndi_node;
203 break;
204 case NEXUS_IVAR_NAME:
205 *result = (uintptr_t)dinfo->ndi_name;
206 break;
207 case NEXUS_IVAR_DEVICE_TYPE:
208 *result = (uintptr_t)dinfo->ndi_device_type;
209 break;
223 return (0);
224}
225
226static void
227nexus_probe_nomatch(device_t dev, device_t child)
228{
229 char *name, *type;
230

--- 23 unchanged lines hidden (view full) ---

254 *result = dinfo->ndi_node;
255 break;
256 case NEXUS_IVAR_NAME:
257 *result = (uintptr_t)dinfo->ndi_name;
258 break;
259 case NEXUS_IVAR_DEVICE_TYPE:
260 *result = (uintptr_t)dinfo->ndi_device_type;
261 break;
262 case NEXUS_IVAR_COMPATIBLE:
263 *result = (uintptr_t)dinfo->ndi_compatible;
264 break;
210 default:
211 return (ENOENT);
212 }
213 return 0;
214}
215
216static int
217nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)

--- 8 unchanged lines hidden (view full) ---

226 case NEXUS_IVAR_NAME:
227 case NEXUS_IVAR_DEVICE_TYPE:
228 return (EINVAL);
229 default:
230 return (ENOENT);
231 }
232 return 0;
233}
265 default:
266 return (ENOENT);
267 }
268 return 0;
269}
270
271static int
272nexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value)

--- 8 unchanged lines hidden (view full) ---

281 case NEXUS_IVAR_NAME:
282 case NEXUS_IVAR_DEVICE_TYPE:
283 return (EINVAL);
284 default:
285 return (ENOENT);
286 }
287 return 0;
288}
289
290static int
291nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
292 driver_intr_t *intr, void *arg, void **cookiep)
293{
294 struct nexus_softc *sc;
295
296 sc = device_get_softc(dev);
297
298 if (device_get_state(sc->sc_pic) != DS_ATTACHED)
299 panic("nexus_setup_intr: no pic attached\n");
300
301 return (PIC_SETUP_INTR(sc->sc_pic, child, res, flags, intr, arg,
302 cookiep));
303}
304
305static int
306nexus_teardown_intr(device_t dev, device_t child, struct resource *res,
307 void *ih)
308{
309 struct nexus_softc *sc;
310
311 sc = device_get_softc(dev);
312
313 if (device_get_state(sc->sc_pic) != DS_ATTACHED)
314 panic("nexus_teardown_intr: no pic attached\n");
315
316 return (PIC_TEARDOWN_INTR(sc->sc_pic, child, res, ih));
317}
318
319/*
320 * Allocate resources at the behest of a child. This only handles interrupts,
321 * since I/O resources are handled by child busses.
322 */
323static struct resource *
324nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
325 u_long start, u_long end, u_long count, u_int flags)
326{
327 struct nexus_softc *sc;
328 struct resource *rv;
329
330 sc = device_get_softc(bus);
331
332 if (type != SYS_RES_IRQ) {
333 device_printf(bus, "unknown resource request from %s\n",
334 device_get_nameunit(child));
335 return (NULL);
336 }
337
338 if (device_get_state(sc->sc_pic) != DS_ATTACHED)
339 panic("nexus_alloc_resource: no pic attached\n");
340
341 rv = PIC_ALLOCATE_INTR(sc->sc_pic, child, rid, start, flags);
342
343 return (rv);
344}
345
346static int
347nexus_activate_resource(device_t bus, device_t child, int type, int rid,
348 struct resource *res)
349{
350
351 /* Not much to be done yet... */
352 return (rman_activate_resource(res));
353}
354
355static int
356nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
357 struct resource *res)
358{
359
360 /* Not much to be done yet... */
361 return (rman_deactivate_resource(res));
362}
363
364static int
365nexus_release_resource(device_t bus, device_t child, int type, int rid,
366 struct resource *res)
367{
368 struct nexus_softc *sc;
369
370 sc = device_get_softc(bus);
371
372 if (type != SYS_RES_IRQ) {
373 device_printf(bus, "unknown resource request from %s\n",
374 device_get_nameunit(child));
375 return (NULL);
376 }
377
378 if (device_get_state(sc->sc_pic) != DS_ATTACHED)
379 panic("nexus_release_resource: no pic attached\n");
380
381 return (PIC_RELEASE_INTR(sc->sc_pic, child, rid, res));
382}
383
384static device_t
385create_device_from_node(device_t parent, phandle_t node)
386{
387 device_t cdev;
388 struct nexus_devinfo *dinfo;
389 char *name, *type, *compatible;
390
391 OF_getprop_alloc(node, "name", 1, (void **)&name);
392 OF_getprop_alloc(node, "device_type", 1, (void **)&type);
393 OF_getprop_alloc(node, "compatible", 1, (void **)&compatible);
394 cdev = device_add_child(parent, NULL, -1);
395 if (cdev != NULL) {
396 dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
397 dinfo->ndi_node = node;
398 dinfo->ndi_name = name;
399 dinfo->ndi_device_type = type;
400 dinfo->ndi_compatible = compatible;
401 device_set_ivars(cdev, dinfo);
402 } else
403 free(name, M_OFWPROP);
404
405 return (cdev);
406}