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 @@ -61,6 +62,8 @@ }; static void ofwfb_initialize(struct vt_device *vd); +static int ofwfb_setup(struct ofwfb_softc *sc, phandle_t node); +static vd_init_t ofwfb_delayed_init; static vd_probe_t ofwfb_probe; static vd_init_t ofwfb_init; static vd_bitblt_text_t ofwfb_bitblt_text; @@ -78,6 +81,17 @@ .vd_priority = VD_PRIORITY_GENERIC+1, }; +static const struct vt_driver vt_ofwfb_delayed_driver = { + .vd_name = "ofwfb", + .vd_init = ofwfb_delayed_init, + .vd_blank = vt_fb_blank, + .vd_bitblt_text = ofwfb_bitblt_text, + .vd_bitblt_bmp = ofwfb_bitblt_bitmap, + .vd_fb_ioctl = vt_fb_ioctl, + .vd_fb_mmap = vt_fb_mmap, + .vd_priority = VD_PRIORITY_GENERIC+1, +}; + static unsigned char ofw_colors[16] = { /* See "16-color Text Extension" Open Firmware document, page 4 */ 0, 4, 2, 6, 1, 5, 3, 7, @@ -86,6 +100,7 @@ static struct ofwfb_softc ofwfb_conssoftc; VT_DRIVER_DECLARE(vt_ofwfb, vt_ofwfb_driver); +VT_DRIVER_DECLARE(vt_ofwfb_delayed, vt_ofwfb_delayed_driver); static int ofwfb_probe(struct vt_device *vd) @@ -354,14 +369,6 @@ char type[64]; phandle_t chosen; phandle_t node; - uint32_t depth, height, width, stride; - uint32_t fb_phys; - int i, len; -#ifdef __sparc64__ - static struct bus_space_tag ofwfb_memt[1]; - bus_addr_t phys; - int space; -#endif /* Initialize softc */ vd->vd_softc = sc = &ofwfb_conssoftc; @@ -381,6 +388,27 @@ if (strcmp(type, "display") != 0) return (CN_DEAD); + if (ofwfb_setup(sc, node) != 0) + return (CN_DEAD); + + ofwfb_initialize(vd); + vt_fb_init(vd); + + return (CN_NORMAL); +} + +static int +ofwfb_setup(struct ofwfb_softc *sc, phandle_t node) +{ +#ifdef __sparc64__ + static struct bus_space_tag ofwfb_memt[1]; + bus_addr_t phys; + int space; +#endif + uint32_t depth, height, width, stride; + uint32_t fb_phys; + int i, len; + /* Keep track of the OF node */ sc->sc_node = node; @@ -395,12 +423,12 @@ if (OF_getproplen(node, "height") != sizeof(height) || OF_getproplen(node, "width") != sizeof(width) || OF_getproplen(node, "depth") != sizeof(depth)) - return (CN_DEAD); + return (ENXIO); /* Only support 8 and 32-bit framebuffers */ OF_getprop(node, "depth", &depth, sizeof(depth)); if (depth != 8 && depth != 32) - return (CN_DEAD); + return (ENXIO); sc->fb.fb_bpp = sc->fb.fb_depth = depth; OF_getprop(node, "height", &height, sizeof(height)); @@ -487,7 +515,7 @@ } if (fb_phys == num_pciaddrs) /* No candidates found */ - return (CN_DEAD); + return (ENXIO); #if defined(__powerpc__) OF_decode_addr(node, fb_phys, &sc->sc_memt, &sc->fb.fb_vbase, @@ -495,7 +523,7 @@ sc->fb.fb_pbase = sc->fb.fb_vbase & ~DMAP_BASE_ADDRESS; #else /* No ability to interpret assigned-addresses otherwise */ - return (CN_DEAD); + return (ENXIO); #endif } @@ -511,9 +539,101 @@ if (!(cpu_features & PPC_FEATURE_BOOKE) && !(mfmsr() & PSL_DR)) sc->fb.fb_flags |= FB_FLAG_NOWRITE; #endif + + return (0); +} + +static int +ofwfb_delayed_init(struct vt_device *vd) +{ ofwfb_initialize(vd); vt_fb_init(vd); - return (CN_INTERNAL); + return (0); } +static void +ofwfb_dev_identify(driver_t *driver, device_t parent) +{ + + /* Try to guess if we need a device attachment. */ + if (ofwfb_conssoftc.sc_handle != 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, "OpenFirmware video console"); + return (BUS_PROBE_DEFAULT); +} + +static int +ofwfb_dev_attach(device_t dev) +{ + struct ofwfb_softc *sc = &ofwfb_conssoftc; + phandle_t node; + int rv; + + 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); + } + + rv = ofwfb_setup(sc, node); + + if (rv) + return (rv); + + vt_allocate(&vt_ofwfb_delayed_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);