Skip site navigation (1)Skip section navigation (2)
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>