Index: sys/dev/vt/hw/ofwfb/ofwfb.c =================================================================== --- sys/dev/vt/hw/ofwfb/ofwfb.c +++ sys/dev/vt/hw/ofwfb/ofwfb.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -90,6 +91,7 @@ static int ofwfb_probe(struct vt_device *vd) { + struct ofwfb_softc *sc; phandle_t chosen, node; ihandle_t stdout; char type[64]; @@ -98,6 +100,7 @@ if (chosen == -1) return (CN_DEAD); + sc = &ofwfb_conssoftc; node = -1; if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == sizeof(stdout)) @@ -108,11 +111,17 @@ * using "screen" directly. */ node = OF_finddevice("screen"); + if (node == -1) + return (CN_DEAD); + stdout = OF_open("screen"); } OF_getprop(node, "device_type", type, sizeof(type)); if (strcmp(type, "display") != 0) return (CN_DEAD); + sc->sc_handle = stdout; + sc->sc_node = node; + /* Looks OK... */ return (CN_INTERNAL); } @@ -352,7 +361,6 @@ { struct ofwfb_softc *sc; char type[64]; - phandle_t chosen; phandle_t node; uint32_t depth, height, width, stride; uint32_t fb_phys; @@ -366,24 +374,12 @@ /* Initialize softc */ vd->vd_softc = sc = &ofwfb_conssoftc; - chosen = OF_finddevice("/chosen"); - OF_getprop(chosen, "stdout", &sc->sc_handle, sizeof(ihandle_t)); - node = OF_instance_to_package(sc->sc_handle); - if (node == -1) { - /* - * The "/chosen/stdout" does not exist try - * using "screen" directly. - */ - node = OF_finddevice("screen"); - sc->sc_handle = OF_open("screen"); - } + node = sc->sc_node; + OF_getprop(node, "device_type", type, sizeof(type)); if (strcmp(type, "display") != 0) return (CN_DEAD); - /* Keep track of the OF node */ - sc->sc_node = node; - /* * Try to use a 32-bit framebuffer if possible. This may be * unimplemented and fail. That's fine -- it just means we are @@ -517,3 +513,84 @@ return (CN_INTERNAL); } +static void +ofwfb_dev_identify(driver_t *driver, device_t parent) +{ + + /* Try to guess if we need a device attachment. */ + if (ofwfb_conssoftc.sc_node > 0) + return; + + if (device_find_child(parent, "fb", -1) != NULL) + return; + + device_add_child(parent, "fb", -1); +} + +static int +ofwfb_dev_probe(device_t dev) +{ + phandle_t node; + device_t check; + + check = dev; + node = ofw_bus_get_node(check); + + /* This may be a fake child of an OF node. */ + if (node == -1) { + /* Check the parent. */ + check = device_get_parent(check); + node = ofw_bus_get_node(check); + if (node == -1) + return (ENXIO); + } + + if (strcmp(ofw_bus_get_type(check), "display")) + return (ENXIO); + + device_set_desc(dev, "Open Firmware video console"); + return (BUS_PROBE_DEFAULT); +} + +static int +ofwfb_dev_attach(device_t dev) +{ + struct ofwfb_softc *sc = &ofwfb_conssoftc; + phandle_t node; + + device_set_softc(dev, sc); + + node = ofw_bus_get_node(dev); + + /* This may be a fake child of an OF node. */ + if (node == -1) { + /* Check the parent. */ + node = ofw_bus_get_node(device_get_parent(dev)); + if (node == -1) + return (ENXIO); + } + + sc->sc_node = node; + + vt_allocate(&vt_ofwfb_driver, &sc->fb); + + return (0); +} + +static device_method_t ofwfb_dev_methods[] = { + DEVMETHOD(device_identify, ofwfb_dev_identify), + DEVMETHOD(device_probe, ofwfb_dev_probe), + DEVMETHOD(device_attach, ofwfb_dev_attach), + DEVMETHOD_END +}; + + +static driver_t ofwfb_dev_driver = { + "fb", + ofwfb_dev_methods, + 0 /* Don't allocate a softc, one will be provided. */ +}; + +static devclass_t ofwfb_dev_devclass; + +DRIVER_MODULE(fb, vgapci, ofwfb_dev_driver, ofwfb_dev_devclass, 0, 0);