1139825Simp/*- 294755Sbenno * Copyright 1998 Massachusetts Institute of Technology 394755Sbenno * 494755Sbenno * Permission to use, copy, modify, and distribute this software and 594755Sbenno * its documentation for any purpose and without fee is hereby 694755Sbenno * granted, provided that both the above copyright notice and this 794755Sbenno * permission notice appear in all copies, that both the above 894755Sbenno * copyright notice and this permission notice appear in all 994755Sbenno * supporting documentation, and that the name of M.I.T. not be used 1094755Sbenno * in advertising or publicity pertaining to distribution of the 1194755Sbenno * software without specific, written prior permission. M.I.T. makes 1294755Sbenno * no representations about the suitability of this software for any 1394755Sbenno * purpose. It is provided "as is" without express or implied 1494755Sbenno * warranty. 15125702Sgrehan * 1694755Sbenno * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS 1794755Sbenno * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, 1894755Sbenno * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1994755Sbenno * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT 2094755Sbenno * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2194755Sbenno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2294755Sbenno * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 2394755Sbenno * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 2494755Sbenno * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 2594755Sbenno * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 2694755Sbenno * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2794755Sbenno * SUCH DAMAGE. 2894755Sbenno */ 2994755Sbenno/*- 3094755Sbenno * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved. 3194755Sbenno * 3294755Sbenno * Redistribution and use in source and binary forms, with or without 3394755Sbenno * modification, are permitted provided that the following conditions 3494755Sbenno * are met: 3594755Sbenno * 1. Redistributions of source code must retain the above copyright 3694755Sbenno * notice, this list of conditions and the following disclaimer. 3794755Sbenno * 2. Redistributions in binary form must reproduce the above copyright 3894755Sbenno * notice, this list of conditions and the following disclaimer in the 3994755Sbenno * documentation and/or other materials provided with the distribution. 4094755Sbenno * 4194755Sbenno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 4294755Sbenno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4394755Sbenno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 4494755Sbenno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 4594755Sbenno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 4694755Sbenno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 4794755Sbenno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4894755Sbenno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 4994755Sbenno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 5094755Sbenno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 5194755Sbenno * SUCH DAMAGE. 5294755Sbenno * 5394755Sbenno * from: FreeBSD: src/sys/i386/i386/nexus.c,v 1.43 2001/02/09 5494755Sbenno */ 5594755Sbenno 56227843Smarius#include <sys/cdefs.h> 57227843Smarius__FBSDID("$FreeBSD$"); 58227843Smarius 5994755Sbenno#include <sys/param.h> 6094755Sbenno#include <sys/systm.h> 61131102Sgrehan#include <sys/module.h> 6294755Sbenno#include <sys/bus.h> 6394755Sbenno#include <sys/cons.h> 6494755Sbenno#include <sys/kernel.h> 6594755Sbenno#include <sys/malloc.h> 6694755Sbenno 67212239Smav#include <dev/ofw/ofw_bus_subr.h> 6894755Sbenno#include <dev/ofw/openfirm.h> 6994755Sbenno 7094755Sbenno#include <machine/bus.h> 7194755Sbenno#include <machine/frame.h> 7299652Sbenno#include <machine/intr_machdep.h> 7394755Sbenno#include <machine/resource.h> 7494755Sbenno 7599652Sbenno#include <sys/rman.h> 7699652Sbenno 77168885Sgrehan#include "ofw_bus_if.h" 7899652Sbenno#include "pic_if.h" 7999652Sbenno 8094755Sbenno/* 8194755Sbenno * The nexus (which is a pseudo-bus actually) iterates over the nodes that 82133862Smarius * exist in Open Firmware and adds them as devices to this bus so that drivers 8394755Sbenno * can be attached to them. 8494755Sbenno * 8594755Sbenno * Maybe this code should get into dev/ofw to some extent, as some of it should 86133862Smarius * work for all Open Firmware based machines... 8794755Sbenno */ 8894755Sbenno 8994755Sbennostatic MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information"); 9094755Sbenno 91183882Snwhitehornenum nexus_ivars { 92183882Snwhitehorn NEXUS_IVAR_NODE, 93183882Snwhitehorn NEXUS_IVAR_NAME, 94183882Snwhitehorn NEXUS_IVAR_DEVICE_TYPE, 95183882Snwhitehorn NEXUS_IVAR_COMPATIBLE, 96183882Snwhitehorn}; 97183882Snwhitehorn 9894755Sbennostruct nexus_devinfo { 9994755Sbenno phandle_t ndi_node; 10094755Sbenno /* Some common properties. */ 101125702Sgrehan const char *ndi_name; 102125702Sgrehan const char *ndi_device_type; 103125702Sgrehan const char *ndi_compatible; 10494755Sbenno}; 10594755Sbenno 10694755Sbennostruct nexus_softc { 107171805Smarcel struct rman sc_rman; 10894755Sbenno}; 10994755Sbenno 11099652Sbenno/* 11199652Sbenno * Device interface 11299652Sbenno */ 11399652Sbennostatic int nexus_probe(device_t); 114178367Smarcelstatic int nexus_attach(device_t); 11594755Sbenno 11699652Sbenno/* 11799652Sbenno * Bus interface 11899652Sbenno */ 119212413Savgstatic device_t nexus_add_child(device_t, u_int, const char *, int); 120178367Smarcelstatic void nexus_probe_nomatch(device_t, device_t); 12199652Sbennostatic int nexus_read_ivar(device_t, device_t, int, uintptr_t *); 12299652Sbennostatic int nexus_write_ivar(device_t, device_t, int, uintptr_t); 123209486Snwhitehorn#ifdef SMP 124209486Snwhitehornstatic int nexus_bind_intr(device_t dev, device_t child, 125209486Snwhitehorn struct resource *irq, int cpu); 126209486Snwhitehorn#endif 127209486Snwhitehornstatic int nexus_config_intr(device_t dev, int irq, enum intr_trigger trig, 128209486Snwhitehorn enum intr_polarity pol); 12999652Sbennostatic int nexus_setup_intr(device_t, device_t, struct resource *, int, 130167289Spiso driver_filter_t *, driver_intr_t *, void *, void **); 13199652Sbennostatic int nexus_teardown_intr(device_t, device_t, struct resource *, 13299652Sbenno void *); 13399652Sbennostatic struct resource *nexus_alloc_resource(device_t, device_t, int, int *, 13499652Sbenno u_long, u_long, u_long, u_int); 13599652Sbennostatic int nexus_activate_resource(device_t, device_t, int, int, 13699652Sbenno struct resource *); 13799652Sbennostatic int nexus_deactivate_resource(device_t, device_t, int, int, 13899652Sbenno struct resource *); 13999652Sbennostatic int nexus_release_resource(device_t, device_t, int, int, 14099652Sbenno struct resource *); 14199652Sbenno 142178367Smarcel/* 143178367Smarcel * OFW bus interface. 144178367Smarcel */ 145168885Sgrehanstatic phandle_t nexus_ofw_get_node(device_t, device_t); 146168885Sgrehanstatic const char *nexus_ofw_get_name(device_t, device_t); 147168885Sgrehanstatic const char *nexus_ofw_get_type(device_t, device_t); 148168885Sgrehanstatic const char *nexus_ofw_get_compat(device_t, device_t); 149168885Sgrehan 15099652Sbenno/* 15199652Sbenno * Local routines 15299652Sbenno */ 153124468Sgrehanstatic device_t nexus_device_from_node(device_t, phandle_t); 15499652Sbenno 15594755Sbennostatic device_method_t nexus_methods[] = { 15694755Sbenno /* Device interface */ 15794755Sbenno DEVMETHOD(device_probe, nexus_probe), 158178367Smarcel DEVMETHOD(device_attach, nexus_attach), 15994755Sbenno DEVMETHOD(device_detach, bus_generic_detach), 16094755Sbenno DEVMETHOD(device_shutdown, bus_generic_shutdown), 16194755Sbenno DEVMETHOD(device_suspend, bus_generic_suspend), 16294755Sbenno DEVMETHOD(device_resume, bus_generic_resume), 16394755Sbenno 16494755Sbenno /* Bus interface. Resource management is business of the children... */ 165124468Sgrehan DEVMETHOD(bus_add_child, nexus_add_child), 166212239Smav DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str), 16794755Sbenno DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch), 16894755Sbenno DEVMETHOD(bus_read_ivar, nexus_read_ivar), 16994755Sbenno DEVMETHOD(bus_write_ivar, nexus_write_ivar), 17099652Sbenno DEVMETHOD(bus_setup_intr, nexus_setup_intr), 17199652Sbenno DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), 172209486Snwhitehorn#ifdef SMP 173209486Snwhitehorn DEVMETHOD(bus_bind_intr, nexus_bind_intr), 174209486Snwhitehorn#endif 175209486Snwhitehorn DEVMETHOD(bus_config_intr, nexus_config_intr), 17699652Sbenno DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), 17799652Sbenno DEVMETHOD(bus_activate_resource, nexus_activate_resource), 17899652Sbenno DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), 17999652Sbenno DEVMETHOD(bus_release_resource, nexus_release_resource), 18094755Sbenno 181168885Sgrehan /* OFW bus interface */ 182168885Sgrehan DEVMETHOD(ofw_bus_get_node, nexus_ofw_get_node), 183168885Sgrehan DEVMETHOD(ofw_bus_get_name, nexus_ofw_get_name), 184168885Sgrehan DEVMETHOD(ofw_bus_get_type, nexus_ofw_get_type), 185168885Sgrehan DEVMETHOD(ofw_bus_get_compat, nexus_ofw_get_compat), 186168885Sgrehan 187227843Smarius DEVMETHOD_END 18894755Sbenno}; 18994755Sbenno 19094755Sbennostatic driver_t nexus_driver = { 19194755Sbenno "nexus", 19294755Sbenno nexus_methods, 19394755Sbenno sizeof(struct nexus_softc), 19494755Sbenno}; 19594755Sbenno 19694755Sbennostatic devclass_t nexus_devclass; 19794755Sbenno 198255419SnwhitehornEARLY_DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0, 199255419Snwhitehorn BUS_PASS_BUS); 20094755Sbenno 20194755Sbennostatic int 20294755Sbennonexus_probe(device_t dev) 20394755Sbenno{ 204178367Smarcel bus_generic_probe(dev); 205178367Smarcel device_set_desc(dev, "Open Firmware Nexus device"); 206178367Smarcel return (0); 207178367Smarcel} 208178367Smarcel 209178367Smarcelstatic int 210178367Smarcelnexus_attach(device_t dev) 211178367Smarcel{ 21294755Sbenno phandle_t root; 213124468Sgrehan phandle_t child; 21494755Sbenno struct nexus_softc *sc; 215171805Smarcel u_long start, end; 21694755Sbenno 21799652Sbenno sc = device_get_softc(dev); 21899652Sbenno 219171805Smarcel start = 0; 220255419Snwhitehorn end = ~0; 221171805Smarcel 222171805Smarcel sc->sc_rman.rm_start = start; 223171805Smarcel sc->sc_rman.rm_end = end; 224171805Smarcel sc->sc_rman.rm_type = RMAN_ARRAY; 225171805Smarcel sc->sc_rman.rm_descr = "Interrupt request lines"; 226171805Smarcel if (rman_init(&sc->sc_rman) || 227171805Smarcel rman_manage_region(&sc->sc_rman, start, end)) 228171805Smarcel panic("nexus_probe IRQ rman"); 229171805Smarcel 230215067Snwhitehorn if ((root = OF_peer(0)) == 0) 231215067Snwhitehorn return (bus_generic_attach(dev)); 232215067Snwhitehorn 233124468Sgrehan /* 234124468Sgrehan * Now walk the OFW tree to locate top-level devices 235124468Sgrehan */ 236124468Sgrehan for (child = OF_child(root); child != 0; child = OF_peer(child)) { 237124468Sgrehan if (child == -1) 238124468Sgrehan panic("nexus_probe(): OF_child failed."); 239124468Sgrehan (void)nexus_device_from_node(dev, child); 24099652Sbenno 24194755Sbenno } 242178367Smarcel 243178367Smarcel return (bus_generic_attach(dev)); 24494755Sbenno} 24594755Sbenno 24694755Sbennostatic void 24794755Sbennonexus_probe_nomatch(device_t dev, device_t child) 24894755Sbenno{ 24994755Sbenno char *name, *type; 25094755Sbenno 25194755Sbenno if (BUS_READ_IVAR(dev, child, NEXUS_IVAR_NAME, 25294755Sbenno (uintptr_t *)&name) != 0 || 25394755Sbenno BUS_READ_IVAR(dev, child, NEXUS_IVAR_DEVICE_TYPE, 25494755Sbenno (uintptr_t *)&type) != 0) 25594755Sbenno return; 25694755Sbenno 25794755Sbenno if (type == NULL) 25894755Sbenno type = "(unknown)"; 259124468Sgrehan 260124468Sgrehan if (bootverbose) 261124468Sgrehan device_printf(dev, "<%s>, type %s (no driver attached)\n", 262124468Sgrehan name, type); 26394755Sbenno} 26494755Sbenno 265124468Sgrehanstatic device_t 266212413Savgnexus_add_child(device_t dev, u_int order, const char *name, int unit) 267124468Sgrehan{ 268124468Sgrehan device_t child; 269124468Sgrehan struct nexus_devinfo *dinfo; 270124468Sgrehan 271124468Sgrehan child = device_add_child_ordered(dev, order, name, unit); 272125702Sgrehan if (child == NULL) 273124468Sgrehan return (NULL); 274125702Sgrehan 275124468Sgrehan dinfo = malloc(sizeof(struct nexus_devinfo), M_NEXUS, M_NOWAIT|M_ZERO); 276124468Sgrehan if (dinfo == NULL) 277124468Sgrehan return (NULL); 278124468Sgrehan 279124468Sgrehan dinfo->ndi_node = -1; 280124468Sgrehan dinfo->ndi_name = name; 281125702Sgrehan device_set_ivars(child, dinfo); 282125702Sgrehan 283124468Sgrehan return (child); 284124468Sgrehan} 285124468Sgrehan 286124468Sgrehan 28794755Sbennostatic int 28894755Sbennonexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) 28994755Sbenno{ 29094755Sbenno struct nexus_devinfo *dinfo; 29194755Sbenno 29294755Sbenno if ((dinfo = device_get_ivars(child)) == 0) 29394755Sbenno return (ENOENT); 29494755Sbenno switch (which) { 29594755Sbenno case NEXUS_IVAR_NODE: 29694755Sbenno *result = dinfo->ndi_node; 29794755Sbenno break; 29894755Sbenno case NEXUS_IVAR_NAME: 29994755Sbenno *result = (uintptr_t)dinfo->ndi_name; 30094755Sbenno break; 30194755Sbenno case NEXUS_IVAR_DEVICE_TYPE: 30294755Sbenno *result = (uintptr_t)dinfo->ndi_device_type; 30394755Sbenno break; 30499652Sbenno case NEXUS_IVAR_COMPATIBLE: 30599652Sbenno *result = (uintptr_t)dinfo->ndi_compatible; 30699652Sbenno break; 30794755Sbenno default: 30894755Sbenno return (ENOENT); 30994755Sbenno } 31094755Sbenno return 0; 31194755Sbenno} 31294755Sbenno 31394755Sbennostatic int 31494755Sbennonexus_write_ivar(device_t dev, device_t child, int which, uintptr_t value) 31594755Sbenno{ 31694755Sbenno struct nexus_devinfo *dinfo; 31794755Sbenno 31894755Sbenno if ((dinfo = device_get_ivars(child)) == 0) 31994755Sbenno return (ENOENT); 32094755Sbenno 32194755Sbenno switch (which) { 32294755Sbenno case NEXUS_IVAR_NAME: 323124468Sgrehan return (EINVAL); 324124468Sgrehan 325125434Sgrehan /* Identified devices may want to set these */ 326125434Sgrehan case NEXUS_IVAR_NODE: 327125434Sgrehan dinfo->ndi_node = (phandle_t)value; 328125434Sgrehan break; 329125434Sgrehan 33094755Sbenno case NEXUS_IVAR_DEVICE_TYPE: 331124468Sgrehan dinfo->ndi_device_type = (char *)value; 332124468Sgrehan break; 333124468Sgrehan 33494755Sbenno default: 33594755Sbenno return (ENOENT); 33694755Sbenno } 33794755Sbenno return 0; 33894755Sbenno} 33999652Sbenno 34099652Sbennostatic int 34199652Sbennonexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, 342171805Smarcel driver_filter_t *filter, driver_intr_t *ihand, void *arg, void **cookiep) 34399652Sbenno{ 344171805Smarcel int error; 34599652Sbenno 346171805Smarcel /* somebody tried to setup an irq that failed to allocate! */ 347171805Smarcel if (res == NULL) 348171805Smarcel panic("nexus_setup_intr: NULL irq resource!"); 34999652Sbenno 350171805Smarcel *cookiep = 0; 351171805Smarcel if ((rman_get_flags(res) & RF_SHAREABLE) == 0) 352171805Smarcel flags |= INTR_EXCL; 35399652Sbenno 354171805Smarcel /* 355171805Smarcel * We depend here on rman_activate_resource() being idempotent. 356171805Smarcel */ 357171805Smarcel error = rman_activate_resource(res); 358171805Smarcel if (error) 359171805Smarcel return (error); 360171805Smarcel 361171805Smarcel error = powerpc_setup_intr(device_get_nameunit(child), 362171805Smarcel rman_get_start(res), filter, ihand, arg, flags, cookiep); 363171805Smarcel 364171805Smarcel return (error); 36599652Sbenno} 36699652Sbenno 36799652Sbennostatic int 36899652Sbennonexus_teardown_intr(device_t dev, device_t child, struct resource *res, 369171805Smarcel void *cookie) 37099652Sbenno{ 37199652Sbenno 372171805Smarcel return (powerpc_teardown_intr(cookie)); 37399652Sbenno} 37499652Sbenno 375209486Snwhitehorn#ifdef SMP 376209486Snwhitehornstatic int 377209486Snwhitehornnexus_bind_intr(device_t dev, device_t child, struct resource *irq, int cpu) 378209486Snwhitehorn{ 379209486Snwhitehorn 380209486Snwhitehorn return (powerpc_bind_intr(rman_get_start(irq), cpu)); 381209486Snwhitehorn} 382209486Snwhitehorn#endif 383209486Snwhitehorn 384209486Snwhitehornstatic int 385209486Snwhitehornnexus_config_intr(device_t dev, int irq, enum intr_trigger trig, 386209486Snwhitehorn enum intr_polarity pol) 387209486Snwhitehorn{ 388209486Snwhitehorn 389209486Snwhitehorn return (powerpc_config_intr(irq, trig, pol)); 390209486Snwhitehorn} 391209486Snwhitehorn 39299652Sbenno/* 39399652Sbenno * Allocate resources at the behest of a child. This only handles interrupts, 39499652Sbenno * since I/O resources are handled by child busses. 39599652Sbenno */ 39699652Sbennostatic struct resource * 39799652Sbennonexus_alloc_resource(device_t bus, device_t child, int type, int *rid, 39899652Sbenno u_long start, u_long end, u_long count, u_int flags) 39999652Sbenno{ 400171805Smarcel struct nexus_softc *sc; 401171805Smarcel struct resource *rv; 40299652Sbenno 40399652Sbenno if (type != SYS_RES_IRQ) { 40499652Sbenno device_printf(bus, "unknown resource request from %s\n", 40599652Sbenno device_get_nameunit(child)); 40699652Sbenno return (NULL); 40799652Sbenno } 40899652Sbenno 409171805Smarcel if (count == 0 || start + count - 1 != end) { 410171805Smarcel device_printf(bus, "invalid IRQ allocation from %s\n", 411171805Smarcel device_get_nameunit(child)); 412171805Smarcel return (NULL); 413171805Smarcel } 41499652Sbenno 415171805Smarcel sc = device_get_softc(bus); 41699652Sbenno 417171805Smarcel rv = rman_reserve_resource(&sc->sc_rman, start, end, count, 418171805Smarcel flags, child); 419171805Smarcel if (rv == NULL) { 420171805Smarcel device_printf(bus, "IRQ allocation failed for %s\n", 421171805Smarcel device_get_nameunit(child)); 422171805Smarcel } else 423171805Smarcel rman_set_rid(rv, *rid); 424171805Smarcel 42599652Sbenno return (rv); 42699652Sbenno} 42799652Sbenno 42899652Sbennostatic int 42999652Sbennonexus_activate_resource(device_t bus, device_t child, int type, int rid, 43099652Sbenno struct resource *res) 43199652Sbenno{ 43299652Sbenno 43399652Sbenno /* Not much to be done yet... */ 43499652Sbenno return (rman_activate_resource(res)); 43599652Sbenno} 43699652Sbenno 43799652Sbennostatic int 43899652Sbennonexus_deactivate_resource(device_t bus, device_t child, int type, int rid, 43999652Sbenno struct resource *res) 44099652Sbenno{ 44199652Sbenno 44299652Sbenno /* Not much to be done yet... */ 44399652Sbenno return (rman_deactivate_resource(res)); 44499652Sbenno} 44599652Sbenno 44699652Sbennostatic int 44799652Sbennonexus_release_resource(device_t bus, device_t child, int type, int rid, 44899652Sbenno struct resource *res) 44999652Sbenno{ 45099652Sbenno 45199652Sbenno if (type != SYS_RES_IRQ) { 45299652Sbenno device_printf(bus, "unknown resource request from %s\n", 45399652Sbenno device_get_nameunit(child)); 454124468Sgrehan return (EINVAL); 45599652Sbenno } 45699652Sbenno 457171805Smarcel return (rman_release_resource(res)); 45899652Sbenno} 45999652Sbenno 46099652Sbennostatic device_t 461124468Sgrehannexus_device_from_node(device_t parent, phandle_t node) 46299652Sbenno{ 46399652Sbenno device_t cdev; 46499652Sbenno struct nexus_devinfo *dinfo; 46599652Sbenno char *name, *type, *compatible; 46699652Sbenno 46799652Sbenno OF_getprop_alloc(node, "name", 1, (void **)&name); 46899652Sbenno OF_getprop_alloc(node, "device_type", 1, (void **)&type); 46999652Sbenno OF_getprop_alloc(node, "compatible", 1, (void **)&compatible); 47099652Sbenno cdev = device_add_child(parent, NULL, -1); 47199652Sbenno if (cdev != NULL) { 472111119Simp dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK); 47399652Sbenno dinfo->ndi_node = node; 47499652Sbenno dinfo->ndi_name = name; 47599652Sbenno dinfo->ndi_device_type = type; 47699652Sbenno dinfo->ndi_compatible = compatible; 47799652Sbenno device_set_ivars(cdev, dinfo); 47899652Sbenno } else 47999652Sbenno free(name, M_OFWPROP); 48099652Sbenno 48199652Sbenno return (cdev); 48299652Sbenno} 483124468Sgrehan 484168885Sgrehanstatic const char * 485168885Sgrehannexus_ofw_get_name(device_t bus, device_t dev) 486168885Sgrehan{ 487168885Sgrehan struct nexus_devinfo *dinfo; 488168885Sgrehan 489168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 490168885Sgrehan return (NULL); 491168885Sgrehan 492168885Sgrehan return (dinfo->ndi_name); 493168885Sgrehan} 494168885Sgrehan 495168885Sgrehanstatic phandle_t 496168885Sgrehannexus_ofw_get_node(device_t bus, device_t dev) 497168885Sgrehan{ 498168885Sgrehan struct nexus_devinfo *dinfo; 499168885Sgrehan 500168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 501168885Sgrehan return (0); 502168885Sgrehan 503168885Sgrehan return (dinfo->ndi_node); 504168885Sgrehan} 505168885Sgrehan 506168885Sgrehanstatic const char * 507168885Sgrehannexus_ofw_get_type(device_t bus, device_t dev) 508168885Sgrehan{ 509168885Sgrehan struct nexus_devinfo *dinfo; 510168885Sgrehan 511168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 512168885Sgrehan return (NULL); 513168885Sgrehan 514168885Sgrehan return (dinfo->ndi_device_type); 515168885Sgrehan} 516168885Sgrehan 517168885Sgrehanstatic const char * 518168885Sgrehannexus_ofw_get_compat(device_t bus, device_t dev) 519168885Sgrehan{ 520168885Sgrehan struct nexus_devinfo *dinfo; 521168885Sgrehan 522168885Sgrehan if ((dinfo = device_get_ivars(dev)) == NULL) 523168885Sgrehan return (NULL); 524168885Sgrehan 525168885Sgrehan return (dinfo->ndi_compatible); 526168885Sgrehan} 527178367Smarcel 528