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} |