Deleted Added
full compact
simplebus.c (283334) simplebus.c (283477)
1/*-
2 * Copyright (c) 2013 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2013 Nathan Whitehorn
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

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

20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: stable/10/sys/dev/fdt/simplebus.c 283334 2015-05-23 22:36:41Z ian $");
28__FBSDID("$FreeBSD: stable/10/sys/dev/fdt/simplebus.c 283477 2015-05-24 17:51:57Z ian $");
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/module.h>
32#include <sys/bus.h>
33#include <sys/conf.h>
34#include <sys/kernel.h>
35#include <sys/rman.h>
36
37#include <dev/ofw/openfirm.h>
38#include <dev/ofw/ofw_bus.h>
39#include <dev/ofw/ofw_bus_subr.h>
40
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/module.h>
32#include <sys/bus.h>
33#include <sys/conf.h>
34#include <sys/kernel.h>
35#include <sys/rman.h>
36
37#include <dev/ofw/openfirm.h>
38#include <dev/ofw/ofw_bus.h>
39#include <dev/ofw/ofw_bus_subr.h>
40
41struct simplebus_range {
42 uint64_t bus;
43 uint64_t host;
44 uint64_t size;
45};
41#include <dev/fdt/simplebus.h>
46
42
47struct simplebus_softc {
48 device_t dev;
49 phandle_t node;
50
51 struct simplebus_range *ranges;
52 int nranges;
53
54 pcell_t acells, scells;
55};
56
57struct simplebus_devinfo {
58 struct ofw_bus_devinfo obdinfo;
59 struct resource_list rl;
60};
61
62/*
63 * Bus interface.
64 */
65static int simplebus_probe(device_t dev);
66static int simplebus_attach(device_t dev);
67static struct resource *simplebus_alloc_resource(device_t, device_t, int,
68 int *, u_long, u_long, u_long, u_int);
69static void simplebus_probe_nomatch(device_t bus, device_t child);
70static int simplebus_print_child(device_t bus, device_t child);
43/*
44 * Bus interface.
45 */
46static int simplebus_probe(device_t dev);
47static int simplebus_attach(device_t dev);
48static struct resource *simplebus_alloc_resource(device_t, device_t, int,
49 int *, u_long, u_long, u_long, u_int);
50static void simplebus_probe_nomatch(device_t bus, device_t child);
51static int simplebus_print_child(device_t bus, device_t child);
71
52static device_t simplebus_add_child(device_t dev, u_int order,
53 const char *name, int unit);
54static struct resource_list *simplebus_get_resource_list(device_t bus,
55 device_t child);
72/*
73 * ofw_bus interface
74 */
75static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus,
76 device_t child);
77
78/*
79 * local methods
80 */
81
82static int simplebus_fill_ranges(phandle_t node,
83 struct simplebus_softc *sc);
56/*
57 * ofw_bus interface
58 */
59static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus,
60 device_t child);
61
62/*
63 * local methods
64 */
65
66static int simplebus_fill_ranges(phandle_t node,
67 struct simplebus_softc *sc);
84static struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev,
85 phandle_t node);
86
87/*
88 * Driver methods.
89 */
90static device_method_t simplebus_methods[] = {
91 /* Device interface */
92 DEVMETHOD(device_probe, simplebus_probe),
93 DEVMETHOD(device_attach, simplebus_attach),
68
69/*
70 * Driver methods.
71 */
72static device_method_t simplebus_methods[] = {
73 /* Device interface */
74 DEVMETHOD(device_probe, simplebus_probe),
75 DEVMETHOD(device_attach, simplebus_attach),
76 DEVMETHOD(device_detach, bus_generic_detach),
77 DEVMETHOD(device_shutdown, bus_generic_shutdown),
78 DEVMETHOD(device_suspend, bus_generic_suspend),
79 DEVMETHOD(device_resume, bus_generic_resume),
94
95 /* Bus interface */
80
81 /* Bus interface */
82 DEVMETHOD(bus_add_child, simplebus_add_child),
96 DEVMETHOD(bus_print_child, simplebus_print_child),
97 DEVMETHOD(bus_probe_nomatch, simplebus_probe_nomatch),
83 DEVMETHOD(bus_print_child, simplebus_print_child),
84 DEVMETHOD(bus_probe_nomatch, simplebus_probe_nomatch),
85 DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
86 DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
98 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
99 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
100 DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource),
101 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
102 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
103 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
104 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
87 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
88 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
89 DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource),
90 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
91 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
92 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
93 DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
94 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
95 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
105 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
96 DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
97 DEVMETHOD(bus_get_resource_list, simplebus_get_resource_list),
106
107 /* ofw_bus interface */
108 DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo),
109 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
110 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
111 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
112 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
113 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
114
115 DEVMETHOD_END
116};
117
98
99 /* ofw_bus interface */
100 DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo),
101 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
102 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
103 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
104 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
105 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
106
107 DEVMETHOD_END
108};
109
118static driver_t simplebus_driver = {
119 "simplebus",
120 simplebus_methods,
121 sizeof(struct simplebus_softc)
122};
110DEFINE_CLASS_0(simplebus, simplebus_driver, simplebus_methods,
111 sizeof(struct simplebus_softc));
112
123static devclass_t simplebus_devclass;
124EARLY_DRIVER_MODULE(simplebus, ofwbus, simplebus_driver, simplebus_devclass,
125 0, 0, BUS_PASS_BUS);
126EARLY_DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass,
127 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
128
129static int
130simplebus_probe(device_t dev)

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

148
149 return (BUS_PROBE_GENERIC);
150}
151
152static int
153simplebus_attach(device_t dev)
154{
155 struct simplebus_softc *sc;
113static devclass_t simplebus_devclass;
114EARLY_DRIVER_MODULE(simplebus, ofwbus, simplebus_driver, simplebus_devclass,
115 0, 0, BUS_PASS_BUS);
116EARLY_DRIVER_MODULE(simplebus, simplebus, simplebus_driver, simplebus_devclass,
117 0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
118
119static int
120simplebus_probe(device_t dev)

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

138
139 return (BUS_PROBE_GENERIC);
140}
141
142static int
143simplebus_attach(device_t dev)
144{
145 struct simplebus_softc *sc;
156 struct simplebus_devinfo *di;
157 phandle_t node;
146 phandle_t node;
158 device_t cdev;
159
147
160 node = ofw_bus_get_node(dev);
161 sc = device_get_softc(dev);
148 sc = device_get_softc(dev);
149 simplebus_init(dev, 0);
150 if (simplebus_fill_ranges(sc->node, sc) < 0) {
151 device_printf(dev, "could not get ranges\n");
152 return (ENXIO);
153 }
162
154
155 /*
156 * In principle, simplebus could have an interrupt map, but ignore that
157 * for now
158 */
159
160 for (node = OF_child(sc->node); node > 0; node = OF_peer(node))
161 simplebus_add_device(dev, node, 0, NULL, -1, NULL);
162 return (bus_generic_attach(dev));
163}
164
165void
166simplebus_init(device_t dev, phandle_t node)
167{
168 struct simplebus_softc *sc;
169
170 sc = device_get_softc(dev);
171 if (node == 0)
172 node = ofw_bus_get_node(dev);
163 sc->dev = dev;
164 sc->node = node;
165
166 /*
167 * Some important numbers
168 */
169 sc->acells = 2;
170 OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
171 sc->scells = 1;
172 OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));
173 sc->dev = dev;
174 sc->node = node;
175
176 /*
177 * Some important numbers
178 */
179 sc->acells = 2;
180 OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
181 sc->scells = 1;
182 OF_getencprop(node, "#size-cells", &sc->scells, sizeof(sc->scells));
173
174 if (simplebus_fill_ranges(node, sc) < 0) {
175 device_printf(dev, "could not get ranges\n");
176 return (ENXIO);
177 }
178
179 /*
180 * In principle, simplebus could have an interrupt map, but ignore that
181 * for now
182 */
183
184 for (node = OF_child(node); node > 0; node = OF_peer(node)) {
185 if ((di = simplebus_setup_dinfo(dev, node)) == NULL)
186 continue;
187 cdev = device_add_child(dev, NULL, -1);
188 if (cdev == NULL) {
189 device_printf(dev, "<%s>: device_add_child failed\n",
190 di->obdinfo.obd_name);
191 resource_list_free(&di->rl);
192 ofw_bus_gen_destroy_devinfo(&di->obdinfo);
193 free(di, M_DEVBUF);
194 continue;
195 }
196 device_set_ivars(cdev, di);
197 }
198
199 return (bus_generic_attach(dev));
200}
201
202static int
203simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc)
204{
205 int host_address_cells;
206 cell_t *base_ranges;
207 ssize_t nbase_ranges;

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

243 sc->ranges[i].size |= base_ranges[j++];
244 }
245 }
246
247 free(base_ranges, M_DEVBUF);
248 return (sc->nranges);
249}
250
183}
184
185static int
186simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc)
187{
188 int host_address_cells;
189 cell_t *base_ranges;
190 ssize_t nbase_ranges;

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

226 sc->ranges[i].size |= base_ranges[j++];
227 }
228 }
229
230 free(base_ranges, M_DEVBUF);
231 return (sc->nranges);
232}
233
251static struct simplebus_devinfo *
252simplebus_setup_dinfo(device_t dev, phandle_t node)
234struct simplebus_devinfo *
235simplebus_setup_dinfo(device_t dev, phandle_t node,
236 struct simplebus_devinfo *di)
253{
254 struct simplebus_softc *sc;
255 struct simplebus_devinfo *ndi;
256
257 sc = device_get_softc(dev);
237{
238 struct simplebus_softc *sc;
239 struct simplebus_devinfo *ndi;
240
241 sc = device_get_softc(dev);
258
259 ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
242 if (di == NULL)
243 ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
244 else
245 ndi = di;
260 if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
246 if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
261 free(ndi, M_DEVBUF);
247 if (di == NULL)
248 free(ndi, M_DEVBUF);
262 return (NULL);
263 }
264
265 resource_list_init(&ndi->rl);
266 ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &ndi->rl);
267 ofw_bus_intr_to_rl(dev, node, &ndi->rl);
268
269 return (ndi);
270}
271
249 return (NULL);
250 }
251
252 resource_list_init(&ndi->rl);
253 ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &ndi->rl);
254 ofw_bus_intr_to_rl(dev, node, &ndi->rl);
255
256 return (ndi);
257}
258
259device_t
260simplebus_add_device(device_t dev, phandle_t node, u_int order,
261 const char *name, int unit, struct simplebus_devinfo *di)
262{
263 struct simplebus_devinfo *ndi;
264 device_t cdev;
265
266 if ((ndi = simplebus_setup_dinfo(dev, node, di)) == NULL)
267 return (NULL);
268 cdev = device_add_child_ordered(dev, order, name, unit);
269 if (cdev == NULL) {
270 device_printf(dev, "<%s>: device_add_child failed\n",
271 ndi->obdinfo.obd_name);
272 resource_list_free(&ndi->rl);
273 ofw_bus_gen_destroy_devinfo(&ndi->obdinfo);
274 if (di == NULL)
275 free(ndi, M_DEVBUF);
276 return (NULL);
277 }
278 device_set_ivars(cdev, ndi);
279
280 return(cdev);
281}
282
283static device_t
284simplebus_add_child(device_t dev, u_int order, const char *name, int unit)
285{
286 device_t cdev;
287 struct simplebus_devinfo *ndi;
288
289 cdev = device_add_child_ordered(dev, order, name, unit);
290 if (cdev == NULL)
291 return (NULL);
292
293 ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
294 ndi->obdinfo.obd_node = -1;
295 resource_list_init(&ndi->rl);
296 device_set_ivars(cdev, ndi);
297
298 return (cdev);
299}
300
272static const struct ofw_bus_devinfo *
273simplebus_get_devinfo(device_t bus __unused, device_t child)
274{
275 struct simplebus_devinfo *ndi;
276
277 ndi = device_get_ivars(child);
278 return (&ndi->obdinfo);
279}
280
301static const struct ofw_bus_devinfo *
302simplebus_get_devinfo(device_t bus __unused, device_t child)
303{
304 struct simplebus_devinfo *ndi;
305
306 ndi = device_get_ivars(child);
307 return (&ndi->obdinfo);
308}
309
310static struct resource_list *
311simplebus_get_resource_list(device_t bus __unused, device_t child)
312{
313 struct simplebus_devinfo *ndi;
314
315 ndi = device_get_ivars(child);
316 return (&ndi->rl);
317}
318
281static struct resource *
282simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
283 u_long start, u_long end, u_long count, u_int flags)
284{
285 struct simplebus_softc *sc;
286 struct simplebus_devinfo *di;
287 struct resource_list_entry *rle;
288 int j;

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

351static void
352simplebus_probe_nomatch(device_t bus, device_t child)
353{
354 const char *name, *type, *compat;
355
356 if (!bootverbose)
357 return;
358
319static struct resource *
320simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
321 u_long start, u_long end, u_long count, u_int flags)
322{
323 struct simplebus_softc *sc;
324 struct simplebus_devinfo *di;
325 struct resource_list_entry *rle;
326 int j;

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

389static void
390simplebus_probe_nomatch(device_t bus, device_t child)
391{
392 const char *name, *type, *compat;
393
394 if (!bootverbose)
395 return;
396
397 compat = ofw_bus_get_compat(child);
398 if (compat == NULL)
399 return;
359 name = ofw_bus_get_name(child);
360 type = ofw_bus_get_type(child);
400 name = ofw_bus_get_name(child);
401 type = ofw_bus_get_type(child);
361 compat = ofw_bus_get_compat(child);
362
363 device_printf(bus, "<%s>", name != NULL ? name : "unknown");
364 simplebus_print_res(device_get_ivars(child));
365 if (!ofw_bus_status_okay(child))
366 printf(" disabled");
367 if (type)
368 printf(" type %s", type);
402
403 device_printf(bus, "<%s>", name != NULL ? name : "unknown");
404 simplebus_print_res(device_get_ivars(child));
405 if (!ofw_bus_status_okay(child))
406 printf(" disabled");
407 if (type)
408 printf(" type %s", type);
369 if (compat)
370 printf(" compat %s", compat);
371 printf(" (no driver attached)\n");
409 printf(" compat %s (no driver attached)\n", compat);
372}
373
374static int
375simplebus_print_child(device_t bus, device_t child)
376{
377 int rv;
378
379 rv = bus_print_child_header(bus, child);
380 rv += simplebus_print_res(device_get_ivars(child));
381 if (!ofw_bus_status_okay(child))
382 rv += printf(" disabled");
383 rv += bus_print_child_footer(bus, child);
384 return (rv);
385}
410}
411
412static int
413simplebus_print_child(device_t bus, device_t child)
414{
415 int rv;
416
417 rv = bus_print_child_header(bus, child);
418 rv += simplebus_print_res(device_get_ivars(child));
419 if (!ofw_bus_status_okay(child))
420 rv += printf(" disabled");
421 rv += bus_print_child_footer(bus, child);
422 return (rv);
423}