Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Jan 2012 01:54:28 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r230519 - projects/pseries/powerpc/pseries
Message-ID:  <201201250154.q0P1sS59001694@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Wed Jan 25 01:54:28 2012
New Revision: 230519
URL: http://svn.freebsd.org/changeset/base/230519

Log:
  Undo the uart integration, as the PAPR VTY protocol doesn't mesh with it
  at all naturally. With some exceptions (below), this all works nicely now
  and I can boot FreeBSD multiuser on QEMU's emulated POWER7 with hypervisor.
  
  Exceptions:
  1. Interrupt-driven mode doesn't seem to work for obscure reasons.
  2. Input for hvterm-prot terminals is not implemented.

Modified:
  projects/pseries/powerpc/pseries/phyp_console.c
  projects/pseries/powerpc/pseries/vdevice.c

Modified: projects/pseries/powerpc/pseries/phyp_console.c
==============================================================================
--- projects/pseries/powerpc/pseries/phyp_console.c	Wed Jan 25 01:45:19 2012	(r230518)
+++ projects/pseries/powerpc/pseries/phyp_console.c	Wed Jan 25 01:54:28 2012	(r230519)
@@ -34,7 +34,6 @@ __FBSDID("$FreeBSD: projects/pseries/pow
 #include <sys/types.h>
 #include <sys/conf.h>
 #include <sys/cons.h>
-#include <sys/consio.h>
 #include <sys/tty.h>
 #include <machine/bus.h>
 
@@ -48,12 +47,33 @@ __FBSDID("$FreeBSD: projects/pseries/pow
 #include "phyp-hvcall.h"
 #include "uart_if.h"
 
-static union {
-	uint64_t u64[2];
-	char str[16];
-} phyp_inbuf;
-static uint64_t			phyp_inbuflen = 0;
-static uint8_t			phyp_outseqno = 0;
+struct uart_phyp_softc {
+	device_t dev;
+	phandle_t node;
+	int vtermid;
+
+	struct tty *tp;
+	struct resource *irqres;
+	int irqrid;
+	struct callout callout;
+	void *sc_icookie;
+	int polltime;
+
+	struct mtx sc_mtx;
+	int protocol;
+
+	union {
+		uint64_t u64[2];
+		char str[16];
+	} phyp_inbuf;
+	uint64_t inbuflen;
+	uint8_t outseqno;
+};
+
+static struct uart_phyp_softc	*console_sc = NULL;
+#if defined(KDB)
+static int			alt_break_state;
+#endif
 
 enum {
 	HVTERM1, HVTERMPROT
@@ -69,87 +89,53 @@ enum {
 #define  VSV_SEND_MODEM_CTL_STATUS	0x02
 #define VS_QUERY_RESPONSE_PACKET_HEADER	0xfc
 
-/*
- * High-level interface
- */
-
 static int uart_phyp_probe(device_t dev);
-static int phyp_uart_bus_probe(struct uart_softc *);
-static int phyp_uart_bus_attach(struct uart_softc *);
-static int phyp_uart_bus_transmit(struct uart_softc *sc);
-static int phyp_uart_bus_receive(struct uart_softc *sc);
-static int phyp_uart_bus_ipend(struct uart_softc *sc);
-static int phyp_uart_bus_flush(struct uart_softc *, int);
-static int phyp_uart_bus_getsig(struct uart_softc *);
-static int phyp_uart_bus_ioctl(struct uart_softc *, int, intptr_t);
-static int phyp_uart_bus_param(struct uart_softc *, int, int, int, int);
-static int phyp_uart_bus_setsig(struct uart_softc *, int);
+static int uart_phyp_attach(device_t dev);
+static void uart_phyp_intr(void *v);
 
 static device_method_t uart_phyp_methods[] = {
 	/* Device interface */
 	DEVMETHOD(device_probe,		uart_phyp_probe),
-	DEVMETHOD(device_attach,	uart_bus_attach),
+	DEVMETHOD(device_attach,	uart_phyp_attach),
 
 	DEVMETHOD_END
 };
 
 static driver_t uart_phyp_driver = {
-	uart_driver_name,
+	"uart",
 	uart_phyp_methods,
-	sizeof(struct uart_softc),
+	sizeof(struct uart_phyp_softc),
 };
  
-DRIVER_MODULE(uart, vdevice, uart_phyp_driver, uart_devclass, 0, 0);
-
-/*
- * Low-level UART interface
- */
-static int phyp_uart_probe(struct uart_bas *bas);
-static void phyp_uart_init(struct uart_bas *bas, int baudrate, int databits,
-    int stopbits, int parity);
-static void phyp_uart_term(struct uart_bas *bas);
-static void phyp_uart_putc(struct uart_bas *bas, int c);
-static int phyp_uart_rxready(struct uart_bas *bas);
-static int phyp_uart_getc(struct uart_bas *bas, struct mtx *hwmtx);
-
-static struct uart_ops phyp_uart_ops = {
-	.probe = phyp_uart_probe,
-	.init = phyp_uart_init,
-	.term = phyp_uart_term,
-	.putc = phyp_uart_putc,
-	.rxready = phyp_uart_rxready,
-	.getc = phyp_uart_getc,
-};
+DRIVER_MODULE(uart_phyp, vdevice, uart_phyp_driver, uart_devclass, 0, 0);
 
-static kobj_method_t phyp_uart_methods[] = {
-	KOBJMETHOD(uart_probe,	phyp_uart_bus_probe),
-	KOBJMETHOD(uart_attach,	phyp_uart_bus_attach),
-	KOBJMETHOD(uart_transmit,	phyp_uart_bus_transmit),
-	KOBJMETHOD(uart_receive,	phyp_uart_bus_receive),
-	KOBJMETHOD(uart_ipend,		phyp_uart_bus_ipend),
-	KOBJMETHOD(uart_flush,		phyp_uart_bus_flush),
-	KOBJMETHOD(uart_getsig,		phyp_uart_bus_getsig),
-	KOBJMETHOD(uart_ioctl,		phyp_uart_bus_ioctl),
-	KOBJMETHOD(uart_param,		phyp_uart_bus_param),
-	KOBJMETHOD(uart_setsig,		phyp_uart_bus_setsig),
-	{ 0, 0 }
-};
-
-struct uart_class uart_phyp_class = {
-	"uart",
-	phyp_uart_methods,
-	sizeof(struct uart_softc),
-	.uc_ops = &phyp_uart_ops,
-	.uc_range = 1,
-	.uc_rclk = 0x5bbc
+static cn_probe_t uart_phyp_cnprobe;
+static cn_init_t uart_phyp_cninit;
+static cn_term_t uart_phyp_cnterm;
+static cn_getc_t uart_phyp_cngetc;
+static cn_putc_t uart_phyp_cnputc;
+static cn_grab_t uart_phyp_cngrab;
+static cn_ungrab_t uart_phyp_cnungrab;
+
+CONSOLE_DRIVER(uart_phyp);
+
+static void uart_phyp_ttyoutwakeup(struct tty *tp);
+
+static struct ttydevsw uart_phyp_tty_class = {
+	.tsw_flags	= TF_INITLOCK|TF_CALLOUT,
+	.tsw_outwakeup	= uart_phyp_ttyoutwakeup,
 };
 
 static int
-phyp_uart_probe(struct uart_bas *bas)
+uart_phyp_probe_node(struct uart_phyp_softc *sc)
 {
-	phandle_t node = bas->chan;
+	phandle_t node = sc->node;
+	uint32_t reg;
 	char buf[64];
 
+	sc->inbuflen = 0;
+	sc->outseqno = 0;
+
 	if (OF_getprop(node, "name", buf, sizeof(buf)) <= 0)
 		return (ENXIO);
 	if (strcmp(buf, "vty") != 0)
@@ -160,92 +146,180 @@ phyp_uart_probe(struct uart_bas *bas)
 	if (strcmp(buf, "serial") != 0)
 		return (ENXIO);
 
+	reg = -1;
+	OF_getprop(node, "reg", &reg, sizeof(reg));
+	if (reg == -1)
+		return (ENXIO);
+	sc->node = node;
+
 	if (OF_getprop(node, "compatible", buf, sizeof(buf)) <= 0)
 		return (ENXIO);
 	if (strcmp(buf, "hvterm1") == 0) {
-		bas->regshft = HVTERM1;
+		sc->protocol = HVTERM1;
 		return (0);
 	} else if (strcmp(buf, "hvterm-protocol") == 0) {
-		bas->regshft = HVTERMPROT;
+		sc->protocol = HVTERMPROT;
 		return (0);
 	}
-		
-	return (ENXIO);
-}
 
-static int
-phyp_uart_bus_probe(struct uart_softc *sc)
-{
-	return (phyp_uart_probe(&sc->sc_bas));
+	return (ENXIO);
 }
 
 static int
 uart_phyp_probe(device_t dev)
 {
 	const char *name;
-	struct uart_softc *sc;
-	cell_t reg;
+	struct uart_phyp_softc sc;
+	int err;
 
 	name = ofw_bus_get_name(dev);
 	if (name == NULL || strcmp(name, "vty") != 0)
 		return (ENXIO);
 
-	sc = device_get_softc(dev);
-	sc->sc_class = &uart_phyp_class;
-	OF_getprop(ofw_bus_get_node(dev), "reg", &reg, sizeof(reg));
-	sc->sc_bas.bsh = reg;
-	sc->sc_bas.bst = NULL;
-	sc->sc_bas.chan = ofw_bus_get_node(dev);
+	sc.node = ofw_bus_get_node(dev);
+	err = uart_phyp_probe_node(&sc);
+	if (err != 0)
+		return (err);
 
 	device_set_desc(dev, "POWER Hypervisor Virtual Serial Port");
 
-	return (uart_bus_probe(dev, 0, 0, 0, ofw_bus_get_node(dev)));
+	return (err);
 }
 
+static void
+uart_phyp_cnprobe(struct consdev *cp)
+{
+	char buf[64];
+	ihandle_t stdout;
+	phandle_t input, opts, chosen;
+	static struct uart_phyp_softc sc;
+
+	if ((opts = OF_finddevice("/options")) == -1)
+		goto fail;
+	if ((chosen = OF_finddevice("/chosen")) == -1)
+		goto fail;
+
+	/* Check if OF has an active stdin/stdout */
+	input = -1;
+	if (OF_getprop(chosen, "stdout", &stdout,
+	    sizeof(stdout)) == sizeof(stdout) && stdout != 0)
+		input = OF_instance_to_package(stdout);
+	if (input == -1)
+		goto fail;
+
+	if (OF_getprop(input, "device_type", buf, sizeof(buf)) == -1)
+		goto fail;
+	if (strcmp(buf, "serial") != 0)
+		goto fail;
+
+	sc.node = input;
+	if (uart_phyp_probe_node(&sc) != 0)
+		goto fail;
+	mtx_init(&sc.sc_mtx, "uart_phyp", NULL, MTX_SPIN | MTX_QUIET |
+	    MTX_NOWITNESS);
+
+	cp->cn_pri = CN_NORMAL;
+	console_sc = &sc;
+	return;
+	
+fail:
+	cp->cn_pri = CN_DEAD;
+	return;
+}
+
+static int
+uart_phyp_attach(device_t dev)
+{
+	struct uart_phyp_softc *sc;
+	int unit;
+
+	sc = device_get_softc(dev);
+	sc->dev = dev;
+	sc->node = ofw_bus_get_node(dev);
+	uart_phyp_probe_node(sc);
+
+	unit = device_get_unit(dev);
+	sc->tp = tty_alloc(&uart_phyp_tty_class, sc);
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL,
+	    MTX_SPIN | MTX_QUIET | MTX_NOWITNESS);
+
+	if (console_sc != NULL && console_sc->vtermid == sc->vtermid) {
+		sc->outseqno = console_sc->outseqno;
+		console_sc = sc;
+		sprintf(uart_phyp_consdev.cn_name, "ttyu%r", unit);
+		tty_init_console(sc->tp, 0);
+	}
+
+	sc->irqrid = 0;
+#ifdef NOTYET
+	sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->irqrid,
+	    RF_ACTIVE | RF_SHAREABLE);
+#else
+	sc->irqres = NULL;
+#endif
+	if (sc->irqres != NULL) {
+		bus_setup_intr(dev, sc->irqres, INTR_TYPE_TTY | INTR_MPSAFE,
+		    NULL, uart_phyp_intr, sc, &sc->sc_icookie);
+	} else {
+		callout_init(&sc->callout, CALLOUT_MPSAFE);
+		sc->polltime = hz / 20;
+		if (sc->polltime < 1)
+			sc->polltime = 1;
+		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
+	}
+
+	tty_makedev(sc->tp, NULL, "u%r", unit);
+
+	return (0);
+}
 
 static void
-phyp_uart_init(struct uart_bas *bas, int baudrate __unused,
-    int databits __unused, int stopbits __unused, int parity __unused)
+uart_phyp_cninit(struct consdev *cp)
 {
+
+	strcpy(cp->cn_name, "phypcons");
 }
 
 static void
-phyp_uart_term(struct uart_bas *bas __unused)
+uart_phyp_cnterm(struct consdev *cp)
 {
 }
 
 static int
-phyp_uart_getc(struct uart_bas *bas, struct mtx *hwmtx)
+uart_phyp_get(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
 {
-	int ch, err;
+	int err;
 
-	uart_lock(hwmtx);
-	if (phyp_inbuflen == 0) {
-		err = phyp_pft_hcall(H_GET_TERM_CHAR, (uint64_t)bas->bsh,
-		    0, 0, 0, &phyp_inbuflen, &phyp_inbuf.u64[0],
-		    &phyp_inbuf.u64[1]);
+	uart_lock(&sc->sc_mtx);
+	if (sc->inbuflen == 0) {
+		err = phyp_pft_hcall(H_GET_TERM_CHAR, sc->vtermid,
+		    0, 0, 0, &sc->inbuflen, &sc->phyp_inbuf.u64[0],
+		    &sc->phyp_inbuf.u64[1]);
 		if (err != H_SUCCESS) {
-			uart_unlock(hwmtx);
+			uart_unlock(&sc->sc_mtx);
 			return (-1);
 		}
 	}
 
-	if (phyp_inbuflen == 0) {
-		uart_unlock(hwmtx);
-		return (-1);
+	if (sc->inbuflen == 0) {
+		uart_unlock(&sc->sc_mtx);
+		return (0);
 	}
 
-	ch = phyp_inbuf.str[0];
-	phyp_inbuflen--;
-	if (phyp_inbuflen > 0)
-		memcpy(&phyp_inbuf.str[0], &phyp_inbuf.str[1], phyp_inbuflen);
+	if (bufsize > sc->inbuflen)
+		bufsize = sc->inbuflen;
+	memcpy(buffer, sc->phyp_inbuf.str, bufsize);
+	sc->inbuflen -= bufsize;
+	if (sc->inbuflen > 0)
+		memmove(&sc->phyp_inbuf.str[0], &sc->phyp_inbuf.str[bufsize],
+		    sc->inbuflen);
 
-	uart_unlock(hwmtx);
-	return (ch);
+	uart_unlock(&sc->sc_mtx);
+	return (bufsize);
 }
 
-static void
-phyp_uart_putc(struct uart_bas *bas, int c)
+static int
+uart_phyp_put(struct uart_phyp_softc *sc, void *buffer, size_t bufsize)
 {
 	uint16_t seqno;
 	uint64_t len = 0;
@@ -254,93 +328,93 @@ phyp_uart_putc(struct uart_bas *bas, int
 		char bytes[8];
 	} cbuf;
 
-	switch (bas->regshft) {
+	uart_lock(&sc->sc_mtx);
+	switch (sc->protocol) {
 	case HVTERM1:
-		cbuf.bytes[0] = c;
-		len = 1;
+		if (bufsize > 8)
+			bufsize = 8;
+		memcpy(&cbuf, buffer, bufsize);
+		len = bufsize;
 		break;
 	case HVTERMPROT:
-		seqno = phyp_outseqno++;
+		if (bufsize > 4)
+			bufsize = 4;
+		seqno = sc->outseqno++;
 		cbuf.bytes[0] = VS_DATA_PACKET_HEADER;
-		cbuf.bytes[1] = 5; /* total length */
+		cbuf.bytes[1] = 4 + bufsize; /* total length */
 		cbuf.bytes[2] = (seqno >> 8) & 0xff;
 		cbuf.bytes[3] = seqno & 0xff;
-		cbuf.bytes[4] = c;
-		len = 5;
+		memcpy(&cbuf.bytes[4], buffer, bufsize);
+		len = 4 + bufsize;
 		break;
 	}
-	phyp_hcall(H_PUT_TERM_CHAR, (uint64_t)bas->bsh, len, cbuf.u64, 0);
-}
-
-static int
-phyp_uart_rxready(struct uart_bas *bas)
-{
-	return (1);
-}
+	phyp_hcall(H_PUT_TERM_CHAR, sc->vtermid, len, cbuf.u64, 0);
+	uart_unlock(&sc->sc_mtx);
 
-static int
-phyp_uart_bus_attach(struct uart_softc *sc)
-{
-	return (0);
+	return (bufsize);
 }
 
 static int
-phyp_uart_bus_transmit(struct uart_softc *sc)
+uart_phyp_cngetc(struct consdev *cp)
 {
-	int i;
-
-	uart_lock(sc->sc_hwmtx);
-	for (i = 0; i < sc->sc_txdatasz; i++)
-		phyp_uart_putc(&sc->sc_bas, sc->sc_txbuf[i]);
-	uart_unlock(sc->sc_hwmtx);
-
-	return (0);
-}
+	unsigned char c;
+	int retval;
 
-static int
-phyp_uart_bus_receive(struct uart_softc *sc)
-{
-	int c;
-	while ((c = phyp_uart_getc(&sc->sc_bas, sc->sc_hwmtx)) != -1)
-		uart_rx_put(sc, c);
+	retval = uart_phyp_get(console_sc, &c, 1);
+	if (retval != 1)
+		return (-1);
+#if defined(KDB)
+	kdb_alt_break(c, &alt_break_state);
+#endif
 
-	return (0);
+	return (c);
 }
 
-static int
-phyp_uart_bus_ipend(struct uart_softc *sc)
+static void
+uart_phyp_cnputc(struct consdev *cp, int c)
 {
-	return (0);
+	unsigned char ch = c;
+	uart_phyp_put(console_sc, &ch, 1);
 }
 
-static int
-phyp_uart_bus_flush(struct uart_softc *sc, int what)
+static void
+uart_phyp_cngrab(struct consdev *cp)
 {
-	return (0);
 }
 
-static int
-phyp_uart_bus_getsig(struct uart_softc *sc)
+static void
+uart_phyp_cnungrab(struct consdev *cp)
 {
-	return (0);
 }
 
-static int
-phyp_uart_bus_ioctl(struct uart_softc *sc, int req, intptr_t data)
+static void
+uart_phyp_ttyoutwakeup(struct tty *tp)
 {
-	return (EINVAL);
+	struct uart_phyp_softc *sc;
+	char buffer[8];
+	int len;
+
+	sc = tty_softc(tp);
+	
+	while ((len = ttydisc_getc(tp, buffer, sizeof(buffer))) != 0)
+		uart_phyp_put(sc, buffer, len);
 }
 
-static int
-phyp_uart_bus_param(struct uart_softc *sc, int baud, int db, int sb, int par)
+static void
+uart_phyp_intr(void *v)
 {
-	return (0);
-}
+	struct uart_phyp_softc *sc = v;
+	struct tty *tp = sc->tp;
+	unsigned char c;
+	int len;
+
+	tty_lock(tp);
+	while ((len = uart_phyp_get(sc, &c, 1)) > 0)
+		ttydisc_rint(tp, c, 0);
+	ttydisc_rint_done(tp);
+	tty_unlock(tp);
 
-static int
-phyp_uart_bus_setsig(struct uart_softc *sc, int sig)
-{
-	return (0);
+	if (sc->irqres == NULL)
+		callout_reset(&sc->callout, sc->polltime, uart_phyp_intr, sc);
 }
 
-

Modified: projects/pseries/powerpc/pseries/vdevice.c
==============================================================================
--- projects/pseries/powerpc/pseries/vdevice.c	Wed Jan 25 01:45:19 2012	(r230518)
+++ projects/pseries/powerpc/pseries/vdevice.c	Wed Jan 25 01:54:28 2012	(r230519)
@@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/bus.h>
 #include <sys/cpu.h>
 #include <machine/bus.h>
+#include <machine/intr_machdep.h>
 
 #include <dev/ofw/openfirm.h>
 #include <dev/ofw/ofw_bus.h>
@@ -44,6 +45,16 @@ static int	vdevice_probe(device_t);
 static int	vdevice_attach(device_t);
 static const struct ofw_bus_devinfo *vdevice_get_devinfo(device_t dev,
     device_t child);
+static int	vdevice_print_child(device_t dev, device_t child);
+static struct resource_list *vdevice_get_resource_list (device_t, device_t);
+
+/*
+ * VDevice devinfo
+ */
+struct vdevice_devinfo {
+	struct ofw_bus_devinfo mdi_obdinfo;
+	struct resource_list mdi_resources;
+};
 
 static device_method_t vdevice_methods[] = {
 	/* Device interface */
@@ -53,6 +64,14 @@ static device_method_t vdevice_methods[]
 	/* Bus interface */
 	DEVMETHOD(bus_add_child,	bus_generic_add_child),
 	DEVMETHOD(bus_child_pnpinfo_str, ofw_bus_gen_child_pnpinfo_str),
+	DEVMETHOD(bus_print_child,	vdevice_print_child),
+	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
+	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
+	DEVMETHOD(bus_alloc_resource,	bus_generic_rl_alloc_resource),
+	DEVMETHOD(bus_release_resource,	bus_generic_rl_release_resource),
+	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+	DEVMETHOD(bus_get_resource_list, vdevice_get_resource_list),
 
 	/* ofw_bus interface */
 	DEVMETHOD(ofw_bus_get_devinfo,	vdevice_get_devinfo),
@@ -98,22 +117,46 @@ vdevice_attach(device_t dev) 
 {
 	phandle_t root, child;
 	device_t cdev;
-	struct ofw_bus_devinfo *dinfo;
+	int icells, i, nintr, *intr;
+	phandle_t iparent;
+	struct vdevice_devinfo *dinfo;
 
 	root = ofw_bus_get_node(dev);
 
 	for (child = OF_child(root); child != 0; child = OF_peer(child)) {
 		dinfo = malloc(sizeof(*dinfo), M_DEVBUF, M_WAITOK | M_ZERO);
 
-                if (ofw_bus_gen_setup_devinfo(dinfo, child) != 0) {
+                if (ofw_bus_gen_setup_devinfo(&dinfo->mdi_obdinfo,
+		    child) != 0) {
                         free(dinfo, M_DEVBUF);
                         continue;
                 }
+		resource_list_init(&dinfo->mdi_resources);
+
+		if (OF_searchprop(child, "#interrupt-cells", &icells,
+		    sizeof(icells)) <= 0)
+			icells = 2;
+		if (OF_getprop(child, "interrupt-parent", &iparent,
+		    sizeof(iparent)) <= 0)
+			iparent = -1;
+		nintr = OF_getprop_alloc(child, "interrupts", sizeof(*intr),
+		    (void **)&intr);
+		if (nintr > 0) {
+			for (i = 0; i < nintr; i += icells) {
+				u_int irq = intr[i];
+				if (iparent != -1)
+					irq = MAP_IRQ(iparent, intr[i]);
+
+				resource_list_add(&dinfo->mdi_resources,
+				    SYS_RES_IRQ, i, irq, irq, i);
+			}
+		}
+
                 cdev = device_add_child(dev, NULL, -1);
                 if (cdev == NULL) {
                         device_printf(dev, "<%s>: device_add_child failed\n",
-                            dinfo->obd_name);
-                        ofw_bus_gen_destroy_devinfo(dinfo);
+                            dinfo->mdi_obdinfo.obd_name);
+                        ofw_bus_gen_destroy_devinfo(&dinfo->mdi_obdinfo);
                         free(dinfo, M_DEVBUF);
                         continue;
                 }
@@ -129,3 +172,31 @@ vdevice_get_devinfo(device_t dev, device
 	return (device_get_ivars(child));	
 }
 
+static int
+vdevice_print_child(device_t dev, device_t child)
+{
+	struct vdevice_devinfo *dinfo;
+	struct resource_list *rl;
+	int retval = 0;
+
+	dinfo = device_get_ivars(child);
+	rl = &dinfo->mdi_resources;
+
+	retval += bus_print_child_header(dev, child);
+
+	retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
+
+	retval += bus_print_child_footer(dev, child);
+
+	return (retval);
+}
+
+static struct resource_list *
+vdevice_get_resource_list (device_t dev, device_t child)
+{
+        struct vdevice_devinfo *dinfo;
+
+        dinfo = device_get_ivars(child);
+        return (&dinfo->mdi_resources);
+}
+



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201201250154.q0P1sS59001694>