simplebus.c (e6e746bfb086d563bf0ad454a33ecbcab8836dbf) simplebus.c (ecaecbc7d8bc212d8e854088106b3b21e631bb52)
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

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

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);
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

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

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);
52
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);
53/*
54 * ofw_bus interface
55 */
56static const struct ofw_bus_devinfo *simplebus_get_devinfo(device_t bus,
57 device_t child);
58
59/*
60 * local methods
61 */
62
63static int simplebus_fill_ranges(phandle_t node,
64 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);
65static struct simplebus_devinfo *simplebus_setup_dinfo(device_t dev,
66 phandle_t node);
67
68/*
69 * Driver methods.
70 */
71static device_method_t simplebus_methods[] = {
72 /* Device interface */
73 DEVMETHOD(device_probe, simplebus_probe),
74 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),
75
76 /* Bus interface */
80
81 /* Bus interface */
82 DEVMETHOD(bus_add_child, simplebus_add_child),
77 DEVMETHOD(bus_print_child, simplebus_print_child),
78 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),
79 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
80 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
81 DEVMETHOD(bus_alloc_resource, simplebus_alloc_resource),
82 DEVMETHOD(bus_release_resource, bus_generic_release_resource),
83 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
84 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
85 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),
86 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),
87
88 /* ofw_bus interface */
89 DEVMETHOD(ofw_bus_get_devinfo, simplebus_get_devinfo),
90 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
91 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
92 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
93 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
94 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),

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

127
128 return (BUS_PROBE_GENERIC);
129}
130
131static int
132simplebus_attach(device_t dev)
133{
134 struct simplebus_softc *sc;
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),

--- 32 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;
135 struct simplebus_devinfo *di;
136 phandle_t node;
146 phandle_t node;
137 device_t cdev;
138
147
139 node = ofw_bus_get_node(dev);
140 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 }
141
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);
142 sc->dev = dev;
143 sc->node = node;
144
145 /*
146 * Some important numbers
147 */
148 sc->acells = 2;
149 OF_getencprop(node, "#address-cells", &sc->acells, sizeof(sc->acells));
150 sc->scells = 1;
151 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));
152
153 if (simplebus_fill_ranges(node, sc) < 0) {
154 device_printf(dev, "could not get ranges\n");
155 return (ENXIO);
156 }
157
158 /*
159 * In principle, simplebus could have an interrupt map, but ignore that
160 * for now
161 */
162
163 for (node = OF_child(node); node > 0; node = OF_peer(node)) {
164 if ((di = simplebus_setup_dinfo(dev, node)) == NULL)
165 continue;
166 cdev = device_add_child(dev, NULL, -1);
167 if (cdev == NULL) {
168 device_printf(dev, "<%s>: device_add_child failed\n",
169 di->obdinfo.obd_name);
170 resource_list_free(&di->rl);
171 ofw_bus_gen_destroy_devinfo(&di->obdinfo);
172 free(di, M_DEVBUF);
173 continue;
174 }
175 device_set_ivars(cdev, di);
176 }
177
178 return (bus_generic_attach(dev));
179}
180
181static int
182simplebus_fill_ranges(phandle_t node, struct simplebus_softc *sc)
183{
184 int host_address_cells;
185 cell_t *base_ranges;
186 ssize_t nbase_ranges;

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

222 sc->ranges[i].size |= base_ranges[j++];
223 }
224 }
225
226 free(base_ranges, M_DEVBUF);
227 return (sc->nranges);
228}
229
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
230static struct simplebus_devinfo *
231simplebus_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)
232{
233 struct simplebus_softc *sc;
234 struct simplebus_devinfo *ndi;
235
236 sc = device_get_softc(dev);
237{
238 struct simplebus_softc *sc;
239 struct simplebus_devinfo *ndi;
240
241 sc = device_get_softc(dev);
237
238 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;
239 if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
246 if (ofw_bus_gen_setup_devinfo(&ndi->obdinfo, node) != 0) {
240 free(ndi, M_DEVBUF);
247 if (di == NULL)
248 free(ndi, M_DEVBUF);
241 return (NULL);
242 }
243
244 resource_list_init(&ndi->rl);
245 ofw_bus_reg_to_rl(dev, node, sc->acells, sc->scells, &ndi->rl);
246 ofw_bus_intr_to_rl(dev, node, &ndi->rl);
247
248 return (ndi);
249}
250
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
251static const struct ofw_bus_devinfo *
252simplebus_get_devinfo(device_t bus __unused, device_t child)
253{
254 struct simplebus_devinfo *ndi;
255
256 ndi = device_get_ivars(child);
257 return (&ndi->obdinfo);
258}
259
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
260static struct resource *
261simplebus_alloc_resource(device_t bus, device_t child, int type, int *rid,
262 u_long start, u_long end, u_long count, u_int flags)
263{
264 struct simplebus_softc *sc;
265 struct simplebus_devinfo *di;
266 struct resource_list_entry *rle;
267 int j;

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

330static void
331simplebus_probe_nomatch(device_t bus, device_t child)
332{
333 const char *name, *type, *compat;
334
335 if (!bootverbose)
336 return;
337
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;
338 name = ofw_bus_get_name(child);
339 type = ofw_bus_get_type(child);
400 name = ofw_bus_get_name(child);
401 type = ofw_bus_get_type(child);
340 compat = ofw_bus_get_compat(child);
341
342 device_printf(bus, "<%s>", name != NULL ? name : "unknown");
343 simplebus_print_res(device_get_ivars(child));
344 if (!ofw_bus_status_okay(child))
345 printf(" disabled");
346 if (type)
347 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);
348 if (compat)
349 printf(" compat %s", compat);
350 printf(" (no driver attached)\n");
409 printf(" compat %s (no driver attached)\n", compat);
351}
352
353static int
354simplebus_print_child(device_t bus, device_t child)
355{
356 int rv;
357
358 rv = bus_print_child_header(bus, child);
359 rv += simplebus_print_res(device_get_ivars(child));
360 if (!ofw_bus_status_okay(child))
361 rv += printf(" disabled");
362 rv += bus_print_child_footer(bus, child);
363 return (rv);
364}
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}