Index: sys/arm/conf/EFIKA_MX =================================================================== --- sys/arm/conf/EFIKA_MX (revision 264608) +++ sys/arm/conf/EFIKA_MX (working copy) @@ -171,7 +171,7 @@ # NOTE: serial console will be disabled if syscons enabled # Uncomment following lines for framebuffer/syscons support -device sc +device vt device kbdmux options SC_DFLT_FONT # compile font in makeoptions SC_DFLT_FONT=cp437 Index: sys/arm/freescale/imx/imx51_machdep.c =================================================================== --- sys/arm/freescale/imx/imx51_machdep.c (revision 264608) +++ sys/arm/freescale/imx/imx51_machdep.c (working copy) @@ -84,6 +84,7 @@ arm_devmap_add_entry(0x70000000, 0x00100000); arm_devmap_add_entry(0x73f00000, 0x00100000); arm_devmap_add_entry(0x83f00000, 0x00100000); + arm_devmap_add_entry(0xaef00000, 0x00400000); return (0); } Index: sys/boot/fdt/dts/arm/efikamx.dts =================================================================== --- sys/boot/fdt/dts/arm/efikamx.dts (revision 264608) +++ sys/boot/fdt/dts/arm/efikamx.dts (working copy) @@ -37,6 +37,7 @@ / { model = "Genesi Efika MX"; compatible = "genesi,imx51-efikamx"; + memreserve = <0xaef00000 0x00300000>; /* U-Boot's FB */ memory { /* RAM 512M */ @@ -43,11 +44,19 @@ reg = <0x90000000 0x20000000>; }; + localbus@5e000000 { - ipu3@5e000000 { - status = "okay"; - }; - }; + display: ipu3@5e000000 { + device_type = "display"; + /* Have to be filled by u-boot. */ + address = <0xaef76c60>; + depth = <24>; + width = <1280>; + height = <720>; + linebytes = <3840>; + status = "okay"; + }; + }; soc@70000000 { aips@70000000 { @@ -118,6 +127,7 @@ aliases { UART1 = &UART1; SSI2 = &SSI2; + screen = &display; }; chosen { Index: sys/dev/vt/hw/efifb/efifb.c =================================================================== --- sys/dev/vt/hw/efifb/efifb.c (revision 264608) +++ sys/dev/vt/hw/efifb/efifb.c (working copy) @@ -51,10 +51,13 @@ #include #include -static vd_init_t vt_efb_init; +static vd_init_t vt_efifb_init; +static vd_probe_t vt_efifb_probe; -static struct vt_driver vt_efb_driver = { - .vd_init = vt_efb_init, +static struct vt_driver vt_efifb_driver = { + .vd_name = "efifb", + .vd_probe = vt_efifb_probe, + .vd_init = vt_efifb_init, .vd_blank = vt_fb_blank, .vd_bitbltchr = vt_fb_bitbltchr, /* Better than VGA, but still generic driver. */ @@ -61,26 +64,44 @@ .vd_priority = VD_PRIORITY_GENERIC + 1, }; -static struct fb_info info; -VT_CONSDEV_DECLARE(vt_efb_driver, - MAX(80, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)), - MAX(25, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)), &info); +static struct fb_info local_info; +VT_DRIVER_DECLARE(vt_efifb, vt_efifb_driver); static int -vt_efb_init(struct vt_device *vd) +vt_efifb_probe(struct vt_device *vd) { - int depth, d, disable, i, len; + int disabled; + struct efi_fb *efifb; + caddr_t kmdp; + + disabled = 0; + TUNABLE_INT_FETCH("hw.syscons.disable", &disabled); + if (disabled != 0) + return (CN_DEAD); + + kmdp = preload_search_by_type("elf kernel"); + if (kmdp == NULL) + kmdp = preload_search_by_type("elf64 kernel"); + efifb = (struct efi_fb *)preload_search_info(kmdp, + MODINFO_METADATA | MODINFOMD_EFI_FB); + if (efifb == NULL) + return (CN_DEAD); + + return (CN_INTERNAL); +} + +static int +vt_efifb_init(struct vt_device *vd) +{ + int depth, d, i, len; struct fb_info *info; struct efi_fb *efifb; caddr_t kmdp; info = vd->vd_softc; + if (info == NULL) + info = vd->vd_softc = (void *)&local_info; - disable = 0; - TUNABLE_INT_FETCH("hw.syscons.disable", &disable); - if (disable != 0) - return (CN_DEAD); - kmdp = preload_search_by_type("elf kernel"); if (kmdp == NULL) kmdp = preload_search_by_type("elf64 kernel"); Index: sys/dev/vt/hw/fb/vt_early_fb.c =================================================================== --- sys/dev/vt/hw/fb/vt_early_fb.c (revision 264608) +++ sys/dev/vt/hw/fb/vt_early_fb.c (working copy) @@ -52,8 +52,11 @@ #include static vd_init_t vt_efb_init; +static vd_probe_t vt_efb_probe; static struct vt_driver vt_fb_early_driver = { + .vd_name = "efb", + .vd_probe = vt_efb_probe, .vd_init = vt_efb_init, .vd_blank = vt_fb_blank, .vd_bitbltchr = vt_fb_bitbltchr, @@ -60,10 +63,8 @@ .vd_priority = VD_PRIORITY_GENERIC, }; -static struct fb_info info; -VT_CONSDEV_DECLARE(vt_fb_early_driver, - MAX(80, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)), - MAX(25, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)), &info); +static struct fb_info local_info; +VT_DRIVER_DECLARE(vt_efb, vt_fb_early_driver); static void #ifdef FDT @@ -126,32 +127,64 @@ } } -static int -vt_efb_init(struct vt_device *vd) +static phandle_t +vt_efb_get_fbnode() { - struct ofw_pci_register pciaddrs[8]; - struct fb_info *info; - int i, len, n_pciaddrs; phandle_t chosen, node; ihandle_t stdout; char type[64]; - info = vd->vd_softc; - chosen = OF_finddevice("/chosen"); OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); node = OF_instance_to_package(stdout); - if (node == -1) { - /* - * The "/chosen/stdout" does not exist try - * using "screen" directly. - */ - node = OF_finddevice("screen"); + if (node != -1) { + /* The "/chosen/stdout" present. */ + OF_getprop(node, "device_type", type, sizeof(type)); + /* Check if it has "display" type. */ + if (strcmp(type, "display") == 0) + return (node); } - OF_getprop(node, "device_type", type, sizeof(type)); - if (strcmp(type, "display") != 0) + /* Try device with name "screen". */ + node = OF_finddevice("screen"); + + return (node); +} + +static int +vt_efb_probe(struct vt_device *vd) +{ + phandle_t node; + + node = vt_efb_get_fbnode(); + if (node == -1) return (CN_DEAD); + if ((OF_getproplen(node, "height") <= 0) || + (OF_getproplen(node, "width") <= 0) || + (OF_getproplen(node, "depth") <= 0) || + (OF_getproplen(node, "linebytes") <= 0)) + return (CN_DEAD); + + return (CN_INTERNAL); +} + +static int +vt_efb_init(struct vt_device *vd) +{ + struct ofw_pci_register pciaddrs[8]; + struct fb_info *info; + int i, len, n_pciaddrs; + phandle_t node; + + if (vd->vd_softc == NULL) + vd->vd_softc = (void *)&local_info; + + info = vd->vd_softc; + + node = vt_efb_get_fbnode(); + if (node == -1) + return (CN_DEAD); + #define GET(name, var) \ if (OF_getproplen(node, (name)) != sizeof(info->fb_##var)) \ return (CN_DEAD); \ @@ -249,7 +282,6 @@ #endif } - /* blank full size */ len = info->fb_size / 4; for (i = 0; i < len; i++) { @@ -274,6 +306,5 @@ fb_probe(info); vt_fb_init(vd); - return (CN_INTERNAL); } Index: sys/dev/vt/hw/fb/vt_fb.c =================================================================== --- sys/dev/vt/hw/fb/vt_fb.c (revision 264608) +++ sys/dev/vt/hw/fb/vt_fb.c (working copy) @@ -50,6 +50,7 @@ void vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color); static struct vt_driver vt_fb_driver = { + .vd_name = "fb", .vd_init = vt_fb_init, .vd_blank = vt_fb_blank, .vd_bitbltchr = vt_fb_bitbltchr, @@ -61,6 +62,8 @@ .vd_fb_mmap = vt_fb_mmap, }; +VT_DRIVER_DECLARE(vt_fb, vt_fb_driver); + static int vt_fb_ioctl(struct vt_device *vd, u_long cmd, caddr_t data, struct thread *td) { Index: sys/dev/vt/hw/ofwfb/ofwfb.c =================================================================== --- sys/dev/vt/hw/ofwfb/ofwfb.c (revision 264608) +++ sys/dev/vt/hw/ofwfb/ofwfb.c (working copy) @@ -63,6 +63,7 @@ static vd_bitbltchr_t ofwfb_bitbltchr; static const struct vt_driver vt_ofwfb_driver = { + .vd_name = "ofwfb", .vd_init = ofwfb_init, .vd_blank = ofwfb_blank, .vd_bitbltchr = ofwfb_bitbltchr, Index: sys/dev/vt/hw/vga/vga.c =================================================================== --- sys/dev/vt/hw/vga/vga.c (revision 264608) +++ sys/dev/vt/hw/vga/vga.c (working copy) @@ -71,6 +71,7 @@ #define VT_VGA_HEIGHT 480 #define VT_VGA_MEMSIZE (VT_VGA_WIDTH * VT_VGA_HEIGHT / 8) +static vd_probe_t vga_probe; static vd_init_t vga_init; static vd_blank_t vga_blank; static vd_bitbltchr_t vga_bitbltchr; @@ -81,6 +82,8 @@ static vd_postswitch_t vga_postswitch; static const struct vt_driver vt_vga_driver = { + .vd_name = "vga", + .vd_probe = vga_probe, .vd_init = vga_init, .vd_blank = vga_blank, .vd_bitbltchr = vga_bitbltchr, @@ -97,8 +100,7 @@ * buffer is always big enough to support both. */ static struct vga_softc vga_conssoftc; -VT_CONSDEV_DECLARE(vt_vga_driver, MAX(80, PIXEL_WIDTH(VT_VGA_WIDTH)), - MAX(25, PIXEL_HEIGHT(VT_VGA_HEIGHT)), &vga_conssoftc); +VT_DRIVER_DECLARE(vt_vga, vt_vga_driver); static inline void vga_setcolor(struct vt_device *vd, term_color_t color) @@ -631,11 +633,23 @@ } static int +vga_probe(struct vt_device *vd) +{ + + return (CN_INTERNAL); +} + +static int vga_init(struct vt_device *vd) { - struct vga_softc *sc = vd->vd_softc; - int textmode = 0; + struct vga_softc *sc; + int textmode; + if (vd->vd_softc == NULL) + vd->vd_softc = (void *)&vga_conssoftc; + sc = vd->vd_softc; + textmode = 0; + #if defined(__amd64__) || defined(__i386__) sc->vga_fb_tag = X86_BUS_SPACE_MEM; sc->vga_fb_handle = KERNBASE + VGA_MEM_BASE; Index: sys/dev/vt/hw/xboxfb/xboxfb.c =================================================================== --- sys/dev/vt/hw/xboxfb/xboxfb.c (revision 264608) +++ sys/dev/vt/hw/xboxfb/xboxfb.c (working copy) @@ -57,6 +57,7 @@ static vd_init_t xboxfb_init; static struct vt_driver xboxfb_driver = { + .vd_name = "xboxfb", .vd_init = xboxfb_init, .vd_blank = vt_fb_blank, .vd_bitbltchr = vt_fb_bitbltchr, Index: sys/dev/vt/vt.h =================================================================== --- sys/dev/vt/vt.h (revision 264608) +++ sys/dev/vt/vt.h (working copy) @@ -277,6 +277,7 @@ */ typedef int vd_init_t(struct vt_device *vd); +typedef int vd_probe_t(struct vt_device *vd); typedef void vd_postswitch_t(struct vt_device *vd); typedef void vd_blank_t(struct vt_device *vd, term_color_t color); typedef void vd_bitbltchr_t(struct vt_device *vd, const uint8_t *src, @@ -295,7 +296,9 @@ typedef void vd_setpixel_t(struct vt_device *, int, int, term_color_t); struct vt_driver { + char vd_name[16]; /* Console attachment. */ + vd_probe_t *vd_probe; vd_init_t *vd_init; /* Drawing. */ @@ -391,6 +394,9 @@ SYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, \ vt_upgrade, &driver ## _consdev) +/* name argument is not used yet. */ +#define VT_DRIVER_DECLARE(name, drv) DATA_SET(vt_drv_set, drv) + /* * Fonts. * Index: sys/dev/vt/vt_core.c =================================================================== --- sys/dev/vt/vt_core.c (revision 264608) +++ sys/dev/vt/vt_core.c (working copy) @@ -851,9 +851,64 @@ } #endif +SET_DECLARE(vt_drv_set, struct vt_driver); + +#define _VTDEFH MAX(100, PIXEL_HEIGHT(VT_FB_DEFAULT_HEIGHT)) +#define _VTDEFW MAX(200, PIXEL_WIDTH(VT_FB_DEFAULT_WIDTH)) + +static struct terminal vt_consterm; +static struct vt_window vt_conswindow; +static struct vt_device vt_consdev = { + .vd_driver = NULL, + .vd_softc = NULL, + .vd_flags = VDF_INVALID, + .vd_windows = { [VT_CONSWINDOW] = &vt_conswindow, }, + .vd_curwindow = &vt_conswindow, + .vd_markedwin = NULL, + .vd_kbstate = 0, +}; +static term_char_t vt_constextbuf[(_VTDEFW) * (VBF_DEFAULT_HISTORY_SIZE)]; +static term_char_t *vt_constextbufrows[VBF_DEFAULT_HISTORY_SIZE]; +static struct vt_window vt_conswindow = { + .vw_number = VT_CONSWINDOW, + .vw_flags = VWF_CONSOLE, + .vw_buf = { + .vb_buffer = vt_constextbuf, + .vb_rows = vt_constextbufrows, + .vb_history_size = VBF_DEFAULT_HISTORY_SIZE, + .vb_curroffset = 0, + .vb_roffset = 0, + .vb_flags = VBF_STATIC, + .vb_mark_start = {.tp_row = 0, .tp_col = 0,}, + .vb_mark_end = {.tp_row = 0, .tp_col = 0,}, + .vb_scr_size = { + .tp_row = _VTDEFH, + .tp_col = _VTDEFW, + }, + }, + .vw_device = &vt_consdev, + .vw_terminal = &vt_consterm, + .vw_kbdmode = K_XLATE, +}; +static struct terminal vt_consterm = { + .tm_class = &vt_termclass, + .tm_softc = &vt_conswindow, + .tm_flags = TF_CONS, +}; +static struct consdev vt_consterm_consdev = { + .cn_ops = &termcn_cnops, + .cn_arg = &vt_consterm, + .cn_name = "ttyv0", +}; +DATA_SET(cons_set, vt_consterm_consdev); + +SYSINIT(vt_early_cons, SI_SUB_INT_CONFIG_HOOKS, SI_ORDER_ANY, vt_upgrade, + &vt_consdev); + static void vtterm_cnprobe(struct terminal *tm, struct consdev *cp) { + struct vt_driver *vtd, **vtdlist, *vtdbest = NULL; struct vt_window *vw = tm->tm_softc; struct vt_device *vd = vw->vw_device; struct winsize wsz; @@ -862,6 +917,24 @@ /* Initialization already done. */ return; + SET_FOREACH(vtdlist, vt_drv_set) { + vtd = *vtdlist; + if (vtd->vd_probe == NULL) + continue; + if (vtd->vd_probe(vd) == CN_DEAD) + continue; + if ((vtdbest == NULL) || + (vtd->vd_priority > vtdbest->vd_priority)) + vtdbest = vtd; + } + if (vtdbest == NULL) { + cp->cn_pri = CN_DEAD; + vd->vd_flags |= VDF_DEAD; + return; + } + + vd->vd_driver = vtdbest; + cp->cn_pri = vd->vd_driver->vd_init(vd); if (cp->cn_pri == CN_DEAD) { vd->vd_flags |= VDF_DEAD; @@ -1941,7 +2014,7 @@ main_vd->vd_driver->vd_priority); return; } - printf("%s: Replace existing VT driver.\n", __func__); + printf("%s: Replace existing VT driver \"%s\" with new \"%s\".\n", __func__, main_vd->vd_driver->vd_name, drv->vd_name); } vd = main_vd; if (drv->vd_maskbitbltchr == NULL)