Date: Tue, 5 Nov 2013 23:09:36 +0000 (UTC) From: Aleksandr Rybalko <ray@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r257726 - user/ed/newcons/sys/dev/vt/hw/fb Message-ID: <201311052309.rA5N9aSV082671@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ray Date: Tue Nov 5 23:09:36 2013 New Revision: 257726 URL: http://svnweb.freebsd.org/changeset/base/257726 Log: Early console with FDT/OFW support. TODO - done PPC, SPARC64 and FDT-less variants. Sponsored by: The FreeBSD Foundation Added: user/ed/newcons/sys/dev/vt/hw/fb/vt_early_fb.c (contents, props changed) Added: user/ed/newcons/sys/dev/vt/hw/fb/vt_early_fb.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/ed/newcons/sys/dev/vt/hw/fb/vt_early_fb.c Tue Nov 5 23:09:36 2013 (r257726) @@ -0,0 +1,278 @@ +/*- + * Copyright (c) 2013 The FreeBSD Foundation + * All rights reserved. + * + * This software was developed by Aleksandr Rybalko under sponsorship from the + * FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/fbio.h> + +#include "opt_platform.h" + +#ifdef FDT +#include <dev/fdt/fdt_common.h> +#include <dev/ofw/ofw_bus.h> +#include <dev/ofw/ofw_bus_subr.h> +#include <dev/ofw/ofw_pci.h> +#endif + +#include <dev/vt/vt.h> +#include <dev/vt/hw/fb/vt_fb.h> +#include <dev/vt/colors/vt_termcolors.h> + +static vd_init_t vt_efb_init; + +static struct vt_driver vt_fb_early_driver = { + .vd_init = vt_efb_init, + .vd_blank = vt_fb_blank, + .vd_bitbltchr = vt_fb_bitbltchr, + .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 void +#ifdef FDT +vt_efb_initialize(struct fb_info *info, phandle_t node) +#else +vt_efb_initialize(struct fb_info *info) +#endif +{ +#ifdef FDT + char name[64]; + cell_t retval; + ihandle_t ih; + int i; + + /* Open display device, thereby initializing it */ + memset(name, 0, sizeof(name)); + OF_package_to_path(node, name, sizeof(name)); + ih = OF_open(name); +#endif + + /* + * Set up the color map + */ + switch (info->fb_depth) { + case 8: + vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB, + 0x7, 5, 0x7, 2, 0x3, 0); + break; + case 15: + vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB, + 0x1f, 10, 0x1f, 5, 0x1f, 0); + break; + case 16: + vt_generate_vga_palette(info->fb_cmap, COLOR_FORMAT_RGB, + 0x1f, 11, 0x3f, 5, 0x1f, 0); + break; + case 24: + case 32: +#if BYTE_ORDER == BIG_ENDIAN + vt_generate_vga_palette(info->fb_cmap, + COLOR_FORMAT_RGB, 255, 16, 255, 8, 255, 0); +#else + vt_generate_vga_palette(info->fb_cmap, + COLOR_FORMAT_RGB, 255, 0, 255, 8, 255, 16); +#endif +#ifdef FDT + for (i = 0; i < 16; i++) { + OF_call_method("color!", ih, 4, 1, + (cell_t)((info->fb_cmap[i] >> 16) & 0xff), + (cell_t)((info->fb_cmap[i] >> 8) & 0xff), + (cell_t)((info->fb_cmap[i] >> 0) & 0xff), + (cell_t)i, &retval); + } +#endif + break; + + default: + panic("Unknown color space fb_depth %d", info->fb_depth); + break; + } +} + +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 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"); + } + OF_getprop(node, "device_type", type, sizeof(type)); + if (strcmp(type, "display") != 0) + return (CN_DEAD); + +#define GET(name, var) \ + if (OF_getproplen(node, (name)) != sizeof(info->fb_##var)) \ + return (CN_DEAD); \ + OF_getencprop(node, (name), &info->fb_##var, sizeof(info->fb_##var)); \ + if (info->fb_##var == 0) \ + return (CN_DEAD); + + GET("height", height) + GET("width", width) + GET("depth", depth) + GET("linebytes", stride) +#undef GET + + info->fb_size = info->fb_height * info->fb_stride; + + /* + * Get the PCI addresses of the adapter, if present. The node may be the + * child of the PCI device: in that case, try the parent for + * the assigned-addresses property. + */ + len = OF_getprop(node, "assigned-addresses", pciaddrs, + sizeof(pciaddrs)); + if (len == -1) { + len = OF_getprop(OF_parent(node), "assigned-addresses", + pciaddrs, sizeof(pciaddrs)); + } + if (len == -1) + len = 0; + n_pciaddrs = len / sizeof(struct ofw_pci_register); + + /* + * Grab the physical address of the framebuffer, and then map it + * into our memory space. If the MMU is not yet up, it will be + * remapped for us when relocation turns on. + */ + if (OF_getproplen(node, "address") == sizeof(info->fb_pbase)) { + /* XXX We assume #address-cells is 1 at this point. */ + OF_getencprop(node, "address", &info->fb_pbase, + sizeof(info->fb_pbase)); + + #if defined(__powerpc__) + sc->sc_memt = &bs_be_tag; + bus_space_map(sc->sc_memt, info->fb_pbase, info->fb_size, + BUS_SPACE_MAP_PREFETCHABLE, &info->fb_vbase); + #elif defined(__sparc64__) + OF_decode_addr(node, 0, &space, &phys); + sc->sc_memt = &vt_efb_memt[0]; + info->addr = sparc64_fake_bustag(space, fb_phys, sc->sc_memt); + #else + bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size, + BUS_SPACE_MAP_PREFETCHABLE, + (bus_space_handle_t *)&info->fb_vbase); + #endif + } else { + /* + * Some IBM systems don't have an address property. Try to + * guess the framebuffer region from the assigned addresses. + * This is ugly, but there doesn't seem to be an alternative. + * Linux does the same thing. + */ + + info->fb_pbase = n_pciaddrs; + for (i = 0; i < n_pciaddrs; i++) { + /* If it is too small, not the framebuffer */ + if (pciaddrs[i].size_lo < info->fb_size) + continue; + /* If it is not memory, it isn't either */ + if (!(pciaddrs[i].phys_hi & + OFW_PCI_PHYS_HI_SPACE_MEM32)) + continue; + + /* This could be the framebuffer */ + info->fb_pbase = i; + + /* If it is prefetchable, it certainly is */ + if (pciaddrs[i].phys_hi & OFW_PCI_PHYS_HI_PREFETCHABLE) + break; + } + + if (info->fb_pbase == n_pciaddrs) /* No candidates found */ + return (CN_DEAD); + + #if defined(__powerpc__) + OF_decode_addr(node, info->fb_pbase, &sc->sc_memt, + &info->fb_vbase); + #elif defined(__sparc64__) + OF_decode_addr(node, info->fb_pbase, &space, &info->fb_pbase); + sc->sc_memt = &vt_efb_memt[0]; + info->fb_vbase = sparc64_fake_bustag(space, info->fb_pbase, + sc->sc_memt); + #else + bus_space_map(fdtbus_bs_tag, info->fb_pbase, info->fb_size, + BUS_SPACE_MAP_PREFETCHABLE, + (bus_space_handle_t *)&info->fb_vbase); + #endif + } + + + /* blank full size */ + len = info->fb_size / 4; + for (i = 0; i < len; i++) { + ((uint32_t *)info->fb_vbase)[i] = 0; + } + + /* Get pixel storage size. */ + info->fb_bpp = info->fb_stride / info->fb_width * 8; + + /* + * Early FB driver work with static window buffer 80x25, so reduce + * size to 640x480. + */ + info->fb_width = VT_FB_DEFAULT_WIDTH; + info->fb_height = VT_FB_DEFAULT_HEIGHT; + +#ifdef FDT + vt_efb_initialize(info, node); +#else + vt_efb_initialize(info); +#endif + fb_probe(info); + vt_fb_init(vd); + + + return (CN_INTERNAL); +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201311052309.rA5N9aSV082671>