From 84a8bc6368362bb08094718a283f6533e6c6626b Mon Sep 17 00:00:00 2001
From: Sascha Wildner <saw@online.de>
Date: Sun, 22 Feb 2015 20:32:35 +0100
Subject: [PATCH 3/3] kernel/syscons: Fix the console when {i915,radeon}kms.ko
 is loaded.

---
 sys/conf/files                          |  11 +
 sys/dev/drm/drm_fb_helper.c             | 138 ++++++++----
 sys/dev/drm/i915/intel_fb.c             |  17 +-
 sys/dev/drm/include/drm/drm_fb_helper.h |   1 +
 sys/dev/drm/include/linux/fb.h          |  14 ++
 sys/dev/drm/radeon/radeon_fb.c          |  70 ++----
 sys/dev/misc/syscons/sckmsrndr.c        | 365 ++++++++++++++++++++++++++++++++
 sys/dev/misc/syscons/scvidctl.c         | 127 ++++++++++-
 sys/dev/misc/syscons/syscons.c          |  78 ++++++-
 sys/dev/misc/syscons/syscons.h          |   6 +-
 sys/platform/pc32/conf/files            |  10 -
 sys/platform/pc64/conf/files            |  10 -
 12 files changed, 718 insertions(+), 129 deletions(-)
 create mode 100644 sys/dev/misc/syscons/sckmsrndr.c

diff --git a/sys/conf/files b/sys/conf/files
index 41a2dea..37abc7f 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -1767,6 +1767,17 @@ dev/misc/orm/orm.c		optional isa
 dev/misc/gpio/gpio.c		optional gpio
 dev/misc/gpio/gpio_led.c	optional gpio
 dev/misc/ichwd/ichwd.c		optional ichwd
+dev/misc/syscons/schistory.c	optional sc
+dev/misc/syscons/sckmsrndr.c	optional sc
+dev/misc/syscons/scmouse.c	optional sc
+dev/misc/syscons/scterm.c	optional sc
+dev/misc/syscons/scterm-dumb.c	optional sc
+dev/misc/syscons/scterm-sc.c	optional sc
+dev/misc/syscons/scvgarndr.c	optional sc vga
+dev/misc/syscons/scvidctl.c	optional sc
+dev/misc/syscons/scvtb.c	optional sc
+dev/misc/syscons/syscons.c	optional sc
+dev/misc/syscons/sysmouse.c	optional sc
 dev/misc/tbridge/safe_mem.c	optional tbridge
 dev/misc/tbridge/tbridge.c	optional tbridge
 bus/isa/pnp.c			optional isa
diff --git a/sys/dev/drm/drm_fb_helper.c b/sys/dev/drm/drm_fb_helper.c
index bb8d2d4..626b2bc 100644
--- a/sys/dev/drm/drm_fb_helper.c
+++ b/sys/dev/drm/drm_fb_helper.c
@@ -230,9 +230,12 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
 {
 	bool error = false;
 	int i, ret;
+
+	drm_warn_on_modeset_not_all_locked(fb_helper->dev);
+
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
-		ret = drm_crtc_helper_set_config(mode_set);
+		ret = drm_mode_set_config_internal(mode_set);
 		if (ret)
 			error = true;
 	}
@@ -273,6 +276,28 @@ static struct notifier_block paniced = {
 	.notifier_call = drm_fb_helper_panic,
 };
 
+#endif
+
+static bool drm_fb_helper_is_bound(struct drm_fb_helper *fb_helper)
+{
+	struct drm_device *dev = fb_helper->dev;
+	struct drm_crtc *crtc;
+	int bound = 0, crtcs_bound = 0;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc->fb)
+			crtcs_bound++;
+		if (crtc->fb == fb_helper->fb)
+			bound++;
+	}
+
+	if (bound < crtcs_bound)
+		return false;
+	return true;
+}
+
+#if 0
+
 /**
  * drm_fb_helper_restore - restore the framebuffer console (kernel) config
  *
@@ -370,7 +395,7 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
 	 * For each CRTC in this fb, find all associated encoders
 	 * and turn them off, then turn off the CRTC.
 	 */
-	sx_xlock(&dev->mode_config.mutex);
+	mutex_lock(&dev->mode_config.mutex);
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		crtc = fb_helper->crtc_info[i].mode_set.crtc;
 		crtc_funcs = crtc->helper_private;
@@ -397,7 +422,7 @@ static void drm_fb_helper_off(struct fb_info *info, int dpms_mode)
 		}
 		crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
 	}
-	sx_xunlock(&dev->mode_config.mutex);
+	mutex_unlock(&dev->mode_config.mutex);
 }
 #endif
 
@@ -779,15 +804,38 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
 }
 #endif
 
+static void
+do_restore_fbdev_mode(void *context, int pending)
+{
+	struct drm_fb_helper *fb_helper = context;
+	struct drm_device *dev = fb_helper->dev;
+
+	if (!fb_helper->fb)
+		return;
+
+	drm_modeset_lock_all(dev);
+	drm_fb_helper_restore_fbdev_mode(fb_helper);
+	drm_modeset_unlock_all(dev);
+}
+
+static void
+sc_restore_fbdev_mode(void *cookie)
+{
+	struct drm_fb_helper *fb_helper = cookie;
+
+	if (!fb_helper->fb)
+		return;
+
+	taskqueue_enqueue(taskqueue_thread[0], &fb_helper->fb_mode_task);
+}
+
 int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 				  int preferred_bpp)
 {
-	int new_fb = 0;
+	int ret = 0;
 	int crtc_count = 0;
 	int i;
-#if 0
 	struct fb_info *info;
-#endif
 	struct drm_fb_helper_surface_size sizes;
 	int gamma_size = 0;
 
@@ -862,30 +910,26 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 	}
 
 	/* push down into drivers */
-	new_fb = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
-	if (new_fb < 0)
-		return new_fb;
+	ret = (*fb_helper->funcs->fb_probe)(fb_helper, &sizes);
+	if (ret < 0)
+		return ret;
 
-#if 0
 	info = fb_helper->fbdev;
-#endif
 
 	/* set the fb pointer */
 	for (i = 0; i < fb_helper->crtc_count; i++)
-		fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
-
-#if 0
-	if (new_fb) {
-		info->var.pixclock = 0;
-		if (register_framebuffer(info) < 0)
-			return -EINVAL;
+		if (fb_helper->crtc_info[i].mode_set.num_connectors)
+			fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
 
-		dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
-				info->node, info->fix.id);
+	TASK_INIT(&fb_helper->fb_mode_task, 0, do_restore_fbdev_mode, fb_helper);
+	info->cookie = fb_helper;
+	info->restore = (void *)&sc_restore_fbdev_mode;
+	if (register_framebuffer(info) < 0)
+		return -EINVAL;
 
-	} else {
-		drm_fb_helper_set_par(info);
-	}
+#if 0
+	dev_info(fb_helper->dev->dev, "fb%d: %s frame buffer device\n",
+			info->node, info->fix.id);
 
 	/* Switch back to kernel console on panic */
 	/* multi card linked list maybe */
@@ -895,13 +939,12 @@ int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
 					       &paniced);
 		register_sysrq_key('v', &sysrq_drm_fb_helper_restore_op);
 	}
-	if (new_fb)
-		list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
+
+	list_add(&fb_helper->kernel_fb_list, &kernel_fb_helper_list);
 #endif
 
 	return 0;
 }
-EXPORT_SYMBOL(drm_fb_helper_single_fb_probe);
 
 #if 0
 void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
@@ -1362,6 +1405,7 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 	for (i = 0; i < fb_helper->crtc_count; i++) {
 		modeset = &fb_helper->crtc_info[i].mode_set;
 		modeset->num_connectors = 0;
+		modeset->fb = NULL;
 	}
 
 	for (i = 0; i < fb_helper->connector_count; i++) {
@@ -1378,6 +1422,19 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 			modeset->mode = drm_mode_duplicate(dev,
 							   fb_crtc->desired_mode);
 			modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector;
+			modeset->fb = fb_helper->fb;
+		}
+	}
+
+	/* Clear out any old modes if there are no more connected outputs. */
+	for (i = 0; i < fb_helper->crtc_count; i++) {
+		modeset = &fb_helper->crtc_info[i].mode_set;
+		if (modeset->num_connectors == 0) {
+			BUG_ON(modeset->fb);
+			BUG_ON(modeset->num_connectors);
+			if (modeset->mode)
+				drm_mode_destroy(dev, modeset->mode);
+			modeset->mode = NULL;
 		}
 	}
 
@@ -1405,9 +1462,6 @@ bool drm_fb_helper_initial_config(struct drm_fb_helper *fb_helper, int bpp_sel)
 	struct drm_device *dev = fb_helper->dev;
 	int count = 0;
 
-	/* disable all the possible outputs/crtcs before entering KMS mode */
-	drm_helper_disable_unused_functions(fb_helper->dev);
-
 	drm_fb_helper_parse_command_line(fb_helper);
 
 	count = drm_fb_helper_probe_connector_modes(fb_helper,
@@ -1429,23 +1483,14 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 	struct drm_device *dev = fb_helper->dev;
 	int count = 0;
 	u32 max_width, max_height, bpp_sel;
-	bool bound = false, crtcs_bound = false;
-	struct drm_crtc *crtc;
 
 	if (!fb_helper->fb)
 		return 0;
 
-	lockmgr(&dev->mode_config.mutex, LK_EXCLUSIVE);
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (crtc->fb)
-			crtcs_bound = true;
-		if (crtc->fb == fb_helper->fb)
-			bound = true;
-	}
-
-	if (!bound && crtcs_bound) {
+	mutex_lock(&fb_helper->dev->mode_config.mutex);
+	if (!drm_fb_helper_is_bound(fb_helper)) {
 		fb_helper->delayed_hotplug = true;
-		lockmgr(&dev->mode_config.mutex, LK_RELEASE);
+		mutex_unlock(&fb_helper->dev->mode_config.mutex);
 		return 0;
 	}
 	DRM_DEBUG_KMS("\n");
@@ -1456,9 +1501,18 @@ int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 
 	count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
 						    max_height);
+	mutex_unlock(&fb_helper->dev->mode_config.mutex);
+
+	drm_modeset_lock_all(dev);
 	drm_setup_crtcs(fb_helper);
-	lockmgr(&dev->mode_config.mutex, LK_RELEASE);
+	drm_modeset_unlock_all(dev);
 
+#if 1
 	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
+#else
+	drm_fb_helper_set_par(fb_helper->fbdev);
+
+	return 0;
+#endif
 }
 
diff --git a/sys/dev/drm/i915/intel_fb.c b/sys/dev/drm/i915/intel_fb.c
index ae03e13..05290b7 100644
--- a/sys/dev/drm/i915/intel_fb.c
+++ b/sys/dev/drm/i915/intel_fb.c
@@ -61,11 +61,12 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	struct drm_device *dev = helper->dev;
 #if 0
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct fb_info *info;
 #endif
+	struct fb_info *info;
 	struct drm_framebuffer *fb;
 	struct drm_mode_fb_cmd2 mode_cmd = {};
 	struct drm_i915_gem_object *obj;
+	device_t vga_dev;
 	int size, ret;
 
 	/* we don't do packed 24bpp */
@@ -109,6 +110,18 @@ static int intelfb_create(struct drm_fb_helper *helper,
 
 	info->par = helper;
 #endif
+	vga_dev = device_get_parent(dev->dev);
+	info = kmalloc(sizeof(struct fb_info), M_DRM, M_WAITOK | M_ZERO);
+	info->width = sizes->fb_width;
+	info->height = sizes->fb_height;
+	info->stride = mode_cmd.pitches[0];
+	info->depth = sizes->surface_bpp;
+	info->paddr = dev->agp->base + obj->gtt_offset;
+	info->is_vga_boot_display = vga_pci_is_boot_display(vga_dev);
+	info->vaddr =
+	    (vm_offset_t)pmap_mapdev_attr(info->paddr,
+		sizes->surface_height * info->stride,
+		VM_MEMATTR_WRITE_COMBINING);
 
 	ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
 	if (ret)
@@ -117,9 +130,9 @@ static int intelfb_create(struct drm_fb_helper *helper,
 	fb = &ifbdev->ifb.base;
 
 	ifbdev->helper.fb = fb;
-#if 0
 	ifbdev->helper.fbdev = info;
 
+#if 0
 	strcpy(info->fix.id, "inteldrmfb");
 
 	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
diff --git a/sys/dev/drm/include/drm/drm_fb_helper.h b/sys/dev/drm/include/drm/drm_fb_helper.h
index 0ae3ebe..144940c 100644
--- a/sys/dev/drm/include/drm/drm_fb_helper.h
+++ b/sys/dev/drm/include/drm/drm_fb_helper.h
@@ -71,6 +71,7 @@ struct drm_fb_helper {
 	int connector_count;
 	struct drm_fb_helper_connector **connector_info;
 	struct drm_fb_helper_funcs *funcs;
+	struct task fb_mode_task;
 	struct fb_info *fbdev;
 	u32 pseudo_palette[17];
 	struct list_head kernel_fb_list;
diff --git a/sys/dev/drm/include/linux/fb.h b/sys/dev/drm/include/linux/fb.h
index 1c95603..8a59612 100644
--- a/sys/dev/drm/include/linux/fb.h
+++ b/sys/dev/drm/include/linux/fb.h
@@ -29,4 +29,18 @@
 
 #include <linux/backlight.h>
 
+struct fb_info {
+	vm_offset_t vaddr;
+	vm_paddr_t paddr;
+	uint16_t width;
+	uint16_t height;
+	uint16_t stride;
+	uint16_t depth;
+	int is_vga_boot_display;
+	void *cookie;
+	void(*restore)(void *);
+};
+
+extern int register_framebuffer(struct fb_info *fb_info);
+
 #endif	/* _LINUX_FB_H_ */
diff --git a/sys/dev/drm/radeon/radeon_fb.c b/sys/dev/drm/radeon/radeon_fb.c
index c0c9c8c..1f0cdc7 100644
--- a/sys/dev/drm/radeon/radeon_fb.c
+++ b/sys/dev/drm/radeon/radeon_fb.c
@@ -190,9 +190,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 			   struct drm_fb_helper_surface_size *sizes)
 {
 	struct radeon_device *rdev = rfbdev->rdev;
-#ifdef DUMBBELL_WIP
 	struct fb_info *info;
-#endif /* DUMBBELL_WIP */
 	struct drm_framebuffer *fb = NULL;
 	struct drm_mode_fb_cmd2 mode_cmd;
 	struct drm_gem_object *gobj = NULL;
@@ -200,10 +198,9 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 #ifdef DUMBBELL_WIP
 	device_t device = rdev->dev;
 #endif /* DUMBBELL_WIP */
+	device_t vga_dev = device_get_parent(rdev->dev);
 	int ret;
-#ifdef DUMBBELL_WIP
 	unsigned long tmp;
-#endif /* DUMBBELL_WIP */
 
 	mode_cmd.width = sizes->surface_width;
 	mode_cmd.height = sizes->surface_height;
@@ -223,16 +220,7 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 
 	rbo = gem_to_radeon_bo(gobj);
 
-#ifdef DUMBBELL_WIP
-	/* okay we have an object now allocate the framebuffer */
-	info = framebuffer_alloc(0, device);
-	if (info == NULL) {
-		ret = -ENOMEM;
-		goto out_unref;
-	}
-
-	info->par = rfbdev;
-#endif /* DUMBBELL_WIP */
+	info = kmalloc(sizeof(*info), M_DRM, M_WAITOK | M_ZERO);
 
 	ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
 	if (ret) {
@@ -244,56 +232,23 @@ static int radeonfb_create(struct radeon_fbdev *rfbdev,
 
 	/* setup helper */
 	rfbdev->helper.fb = fb;
-#ifdef DUMBBELL_WIP
 	rfbdev->helper.fbdev = info;
 
-	memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo));
-
-	strcpy(info->fix.id, "radeondrmfb");
-
-	drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
-
-	info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
-	info->fbops = &radeonfb_ops;
-
+	memset(rbo->kptr, 0, radeon_bo_size(rbo));
 	tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start;
-	info->fix.smem_start = rdev->mc.aper_base + tmp;
-	info->fix.smem_len = radeon_bo_size(rbo);
-	info->screen_base = rbo->kptr;
-	info->screen_size = radeon_bo_size(rbo);
-
-	drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height);
-
-	/* setup aperture base/size for vesafb takeover */
-	info->apertures = alloc_apertures(1);
-	if (!info->apertures) {
-		ret = -ENOMEM;
-		goto out_unref;
-	}
-	info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
-	info->apertures->ranges[0].size = rdev->mc.aper_size;
-
-	/* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
-
-	if (info->screen_base == NULL) {
-		ret = -ENOSPC;
-		goto out_unref;
-	}
-
-	ret = fb_alloc_cmap(&info->cmap, 256, 0);
-	if (ret) {
-		ret = -ENOMEM;
-		goto out_unref;
-	}
-
-	DRM_INFO("fb mappable at 0x%lX\n",  info->fix.smem_start);
+	info->vaddr = (vm_offset_t)rbo->kptr;
+	info->paddr = rdev->mc.aper_base + tmp;
+	info->width = sizes->surface_width;
+	info->height = sizes->surface_height;
+	info->stride = sizes->surface_width * (sizes->surface_bpp/8);
+	info->depth = sizes->surface_bpp;
+	info->is_vga_boot_display = vga_pci_is_boot_display(vga_dev);
+
+	DRM_INFO("fb mappable at 0x%jX\n",  info->paddr);
 	DRM_INFO("vram apper at 0x%lX\n",  (unsigned long)rdev->mc.aper_base);
 	DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo));
 	DRM_INFO("fb depth is %d\n", fb->depth);
 	DRM_INFO("   pitch is %d\n", fb->pitches[0]);
-
-	vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
-#endif /* DUMBBELL_WIP */
 	return 0;
 
 out_unref:
@@ -331,6 +286,7 @@ void radeon_fb_output_poll_changed(struct radeon_device *rdev)
 
 static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
 {
+	/* XXX unconfigure fb_info from syscons */
 #ifdef DUMBBELL_WIP
 	struct fb_info *info;
 #endif /* DUMBBELL_WIP */
diff --git a/sys/dev/misc/syscons/sckmsrndr.c b/sys/dev/misc/syscons/sckmsrndr.c
new file mode 100644
index 0000000..6639f12
--- /dev/null
+++ b/sys/dev/misc/syscons/sckmsrndr.c
@@ -0,0 +1,365 @@
+/*-
+ * Copyright (c) 2014 Imre Vadász <imre@vdsz.com>
+ * All rights reserved.
+ *
+ * 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 as
+ *    the first lines of this file unmodified.
+ * 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 AUTHORS ``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 AUTHORS 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.
+ */
+
+#include "opt_syscons.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/thread.h>
+#include <sys/thread2.h>
+#include <sys/ktr.h>
+
+#include <machine/console.h>
+
+#include <dev/drm/include/linux/fb.h>
+
+#include "syscons.h"
+
+#include <bus/isa/isareg.h>
+
+#if !defined(KTR_CONSOLE)
+#define KTR_CONSOLE	KTR_ALL
+#endif
+KTR_INFO_MASTER(console);
+KTR_INFO(KTR_CONSOLE, console, kms_draw_enter, 0, "kms_draw: %d %d %d",
+    int from, int count, int flip);
+KTR_INFO(KTR_CONSOLE, console, kms_draw_char, 1, "drawing at vaddr+%p",
+    void *offset);
+
+static vr_draw_t		kms_draw;
+static vr_draw_cursor_t		kms_cursor;
+static vr_blink_cursor_t	kms_blink;
+static vr_draw_mouse_t		kms_mouse;
+
+static void			kms_nop(scr_stat *scp, ...);
+
+static sc_rndr_sw_t kmsrndrsw = {
+	(vr_draw_border_t *)kms_nop,
+	kms_draw,
+	(vr_set_cursor_t *)kms_nop,
+	kms_cursor,
+	kms_blink,
+#ifndef SC_NO_CUTPASTE
+	kms_mouse,
+#else
+	(vr_draw_mouse_t *)kms_nop;
+#endif
+};
+RENDERER(kms, V_INFO_MM_TEXT, kmsrndrsw, kms_set);
+
+#ifndef SC_NO_MODE_CHANGE
+static sc_rndr_sw_t grrndrsw = {
+	(vr_draw_border_t *)kms_nop,
+	(vr_draw_t *)kms_nop,
+	(vr_set_cursor_t *)kms_nop,
+	(vr_draw_cursor_t *)kms_nop,
+	(vr_blink_cursor_t *)kms_nop,
+	(vr_draw_mouse_t *)kms_nop,
+};
+RENDERER(kms, V_INFO_MM_OTHER, grrndrsw, kms_set);
+#endif /* SC_NO_MODE_CHANGE */
+
+RENDERER_MODULE(kms, kms_set);
+
+static uint32_t colormap[16] = {
+	0x00000000,	/* BLACK */
+	0x000000aa,	/* BLUE */
+	0x0000aa00,	/* GREEN */
+	0x0000aaaa,	/* CYAN */
+	0x00aa0000,	/* RED */
+	0x00aa00aa,	/* MAGENTA */
+	0x00aa5500,	/* BROWN */
+	0x00aaaaaa,	/* WHITE */
+	0x00555555,	/* HIGHLIGHT BLACK */
+	0x005555ff,	/* HIGHLIGHT BLUE */
+	0x0055ff55,	/* HIGHLIGHT GREEN */
+	0x0055ffff,	/* HIGHLIGHT CYAN */
+	0x00ff5555,	/* HIGHLIGHT RED */
+	0x00ff55ff,	/* HIGHLIGHT MAGENTA */
+	0x00ffff55,	/* HIGHLIGHT BROWN */
+	0x00ffffff,	/* HIGHLIGHT WHITE */
+};
+
+#ifndef SC_NO_CUTPASTE
+static u_short mouse_and_mask[16] = {
+	0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
+	0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
+};
+static u_short mouse_or_mask[16] = {
+	0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
+	0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
+};
+#endif
+
+static void
+kms_nop(scr_stat *scp, ...)
+{
+}
+
+/* KMS renderer */
+
+static void
+kms_draw(scr_stat *scp, int from, int count, int flip)
+{
+	sc_softc_t *sc = scp->sc;
+	u_char *char_data;
+	int a, i, j;
+	uint32_t fg, bg;
+	vm_offset_t draw_pos, idraw_pos, p;
+	int pos, line_width, pixel_size;
+
+	KTR_LOG(console_kms_draw_enter, from, count, flip);
+
+	line_width = sc->fbi->stride;
+	pixel_size = 4;
+
+	draw_pos = idraw_pos = sc->fbi->vaddr +
+#if 0 /* XXX fix xoff and yoff */
+	    8 * scp->font_mag * pixel_size * scp->xoff +
+	    scp->yoff * scp->font_size * scp->font_mag * line_width +
+#endif
+	    8 * scp->font_mag * pixel_size * (from % scp->xsize) +
+	    scp->font_mag * scp->font_size * line_width * (from / scp->xsize);
+
+	if (from + count > scp->xsize * scp->ysize)
+		count = scp->xsize * scp->ysize - from;
+
+	for (i = from; count-- > 0; i++) {
+		p = draw_pos;
+		char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
+		    scp->font_size]);
+
+		a = sc_vtb_geta(&scp->vtb, i);
+		if (flip) {
+			fg = colormap[((a & 0xf000) >> 4) >> 8];
+			bg = colormap[(a & 0x0f00) >> 8];
+		} else {
+			fg = colormap[(a & 0x0f00) >> 8];
+			bg = colormap[((a & 0xf000) >> 4) >> 8];
+		}
+
+		KTR_LOG(console_kms_draw_char, (void *)(draw_pos - idraw_pos));
+		for (j = 0; j < scp->font_size; j++, char_data++) {
+			for (pos = 7; pos >= 0; pos--, p += pixel_size * scp->font_mag) {
+				for (int xp = 0; xp < scp->font_mag; xp++) {
+					for (int yp = 0; yp < scp->font_mag; yp++) {
+						writel(p +
+						    xp * pixel_size +
+						    yp * line_width,
+						    *char_data & (1 << pos) ?
+						    fg : bg);
+					}
+				}
+			}
+
+			p += scp->font_mag * line_width -
+			    8 * scp->font_mag * pixel_size;
+		}
+		draw_pos += 8 * scp->font_mag * pixel_size;
+		if ((i % scp->xsize) == scp->xsize - 1) {
+			draw_pos +=
+#if 0 /* XXX fix xoff and yoff */
+			    scp->xoff * 16 * scp->font_mag * pixel_size +
+#endif
+			    (scp->font_size * scp->font_mag - 1) * line_width;
+		}
+	}
+}
+
+static void
+draw_kmscursor(scr_stat *scp, int at, int on, int flip)
+{
+	sc_softc_t *sc = scp->sc;
+	int line_width, pixel_size, height;
+	int a, i, pos;
+	uint32_t fg, bg;
+	unsigned char *char_data;
+	vm_offset_t draw_pos;
+
+	line_width = sc->fbi->stride;
+	pixel_size = 4;
+
+	draw_pos = sc->fbi->vaddr +
+#if 0 /* XXX fix xoff and yoff */
+	    8 * pixel_size * scp->xoff +
+	    scp->yoff * scp->font_size * line_width +
+#endif
+	    8 * scp->font_mag * pixel_size * (at % scp->xsize) +
+	    scp->font_mag * scp->font_size * line_width * (at / scp->xsize) +
+	    (scp->font_size - scp->cursor_base - 1) * scp->font_mag * line_width;
+
+	a = sc_vtb_geta(&scp->vtb, at);
+	if (flip) {
+		fg = colormap[((on) ? (a & 0x0f00) :
+		    ((a & 0xf000) >> 4)) >> 8];
+		bg = colormap[((on) ? ((a & 0xf000) >> 4) :
+		    (a & 0x0f00)) >> 8];
+	} else {
+		fg = colormap[((on) ? ((a & 0xf000) >> 4) :
+		    (a & 0x0f00)) >> 8];
+		bg = colormap[((on) ? (a & 0x0f00) :
+		    ((a & 0xf000) >> 4)) >> 8];
+	}
+
+	char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
+	    scp->font_size - scp->cursor_base - 1]);
+	height = imin(scp->cursor_height, scp->font_size);
+
+	for (i = 0; i < height; i++, char_data--) {
+		for (pos = 7; pos >= 0; pos--, draw_pos += pixel_size * scp->font_mag) {
+			for (int xp = 0; xp < scp->font_mag; xp++) {
+				for (int yp = 0; yp < scp->font_mag; yp++) {
+					writel(draw_pos +
+					    xp * pixel_size +
+					    yp * line_width,
+					    *char_data & (1 << pos) ?
+					    fg : bg);
+				}
+			}
+		}
+		draw_pos -= scp->font_mag * line_width +
+		    8 * scp->font_mag * pixel_size;
+	}
+}
+
+static int pxlblinkrate = 0;
+
+static void
+kms_cursor(scr_stat *scp, int at, int blink, int on, int flip)
+{
+	if (scp->cursor_height <= 0)	/* the text cursor is disabled */
+		return;
+
+	if (on) {
+		if (!blink) {
+			scp->status |= VR_CURSOR_ON;
+			draw_kmscursor(scp, at, on, flip);
+		} else if (++pxlblinkrate & 4) {
+			pxlblinkrate = 0;
+			scp->status ^= VR_CURSOR_ON;
+			draw_kmscursor(scp, at,
+			    scp->status & VR_CURSOR_ON, flip);
+		}
+	} else {
+		if (scp->status & VR_CURSOR_ON)
+			draw_kmscursor(scp, at, on, flip);
+		scp->status &= ~VR_CURSOR_ON;
+	}
+	if (blink)
+		scp->status |= VR_CURSOR_BLINK;
+	else
+		scp->status &= ~VR_CURSOR_BLINK;
+}
+
+static void
+kms_blink(scr_stat *scp, int at, int flip)
+{
+	if (!(scp->status & VR_CURSOR_BLINK))
+		return;
+	if (!(++pxlblinkrate & 4))
+		return;
+	pxlblinkrate = 0;
+	scp->status ^= VR_CURSOR_ON;
+	draw_kmscursor(scp, at, scp->status & VR_CURSOR_ON, flip);
+}
+
+#ifndef SC_NO_CUTPASTE
+
+static void
+draw_kmsmouse(scr_stat *scp, int x, int y)
+{
+	sc_softc_t *sc = scp->sc;
+	int line_width, pixel_size;
+	int xend, yend;
+	int i, j;
+	vm_offset_t draw_pos;
+
+	line_width = sc->fbi->stride;
+	pixel_size = 4;
+
+	xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
+	yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
+
+	draw_pos = sc->fbi->vaddr + y * scp->font_mag * line_width +
+	    x * scp->font_mag * pixel_size;
+
+	for (i = 0; i < (yend - y); i++) {
+		for (j = (xend - x - 1); j >= 0; j--) {
+			if (mouse_or_mask[i] & 1 << (15 - j)) {
+				for (int xp = 0; xp < scp->font_mag; xp++) {
+					for (int yp = 0; yp < scp->font_mag; yp++) {
+						writel(draw_pos +
+						    scp->font_mag * pixel_size * j +
+						    xp * pixel_size +
+						    yp * line_width,
+						    colormap[15]);
+					}
+				}
+			} else if (mouse_and_mask[i] & 1 << (15 - j)) {
+				for (int xp = 0; xp < scp->font_mag; xp++) {
+					for (int yp = 0; yp < scp->font_mag; yp++) {
+						writel(draw_pos +
+						    scp->font_mag * pixel_size * j +
+						    xp * pixel_size +
+						    yp * line_width,
+						    colormap[0]);
+					}
+				}
+			}
+		}
+
+		draw_pos += scp->font_mag * line_width;
+	}
+}
+
+static void
+remove_kmsmouse(scr_stat *scp, int x, int y)
+{
+	int col, row;
+	int pos;
+	int i;
+
+	/* erase the mouse cursor image */
+	col = x/8 - scp->xoff;
+	row = y/scp->font_size - scp->yoff;
+	pos = row*scp->xsize + col;
+	i = (col < scp->xsize - 1) ? 2 : 1;
+	(*scp->rndr->draw)(scp, pos, i, FALSE);
+	if (row < scp->ysize - 1)
+		(*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
+}
+
+static void
+kms_mouse(scr_stat *scp, int x, int y, int on)
+{
+	if (on)
+		draw_kmsmouse(scp, x, y);
+	else
+		remove_kmsmouse(scp, x, y);
+}
+
+#endif /* SC_NO_CUTPASTE */
diff --git a/sys/dev/misc/syscons/scvidctl.c b/sys/dev/misc/syscons/scvidctl.c
index a8cbe87..2bc54b3 100644
--- a/sys/dev/misc/syscons/scvidctl.c
+++ b/sys/dev/misc/syscons/scvidctl.c
@@ -29,7 +29,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/syscons/scvidctl.c,v 1.19.2.2 2000/05/05 09:16:08 nyan Exp $
- * $DragonFly: src/sys/dev/misc/syscons/scvidctl.c,v 1.16 2007/08/19 11:39:11 swildner Exp $
  */
 
 #include "opt_syscons.h"
@@ -44,6 +43,7 @@
 
 #include <machine/console.h>
 
+#include <dev/drm/include/linux/fb.h>
 #include <dev/video/fb/fbreg.h>
 #include "syscons.h"
 
@@ -109,7 +109,13 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
 	return error;
     }
 
-    if (sc_render_match(scp, scp->sc->adp->va_name, V_INFO_MM_TEXT) == NULL) {
+    if (scp->sc->fbi != NULL &&
+	sc_render_match(scp, "kms", V_INFO_MM_TEXT) == NULL) {
+	crit_exit();
+	return ENODEV;
+    }
+    if (scp->sc->fbi == NULL &&
+	sc_render_match(scp, scp->sc->adp->va_name, V_INFO_MM_TEXT) == NULL) {
 	crit_exit();
 	return ENODEV;
     }
@@ -192,7 +198,13 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
 	return error;
     }
 
-    if (sc_render_match(scp, scp->sc->adp->va_name, V_INFO_MM_OTHER) == NULL) {
+    if (scp->sc->fbi != NULL &&
+	sc_render_match(scp, "kms", V_INFO_MM_OTHER) == NULL) {
+	crit_exit();
+	return ENODEV;
+    }
+    if (scp->sc->fbi == NULL &&
+	sc_render_match(scp, scp->sc->adp->va_name, V_INFO_MM_OTHER) == NULL) {
 	crit_exit();
 	return ENODEV;
     }
@@ -405,7 +417,9 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag)
 {
     scr_stat *scp;
     video_adapter_t *adp;
+#ifndef SC_NO_MODE_CHANGE
     video_info_t info;
+#endif
     int error, ret;
 
 	KKASSERT(tp->t_dev);
@@ -729,3 +743,110 @@ sc_render_match(scr_stat *scp, char *name, int model)
 
 	return NULL;
 }
+
+#define VIRTUAL_TTY(sc, x) ((SC_DEV((sc),(x)) != NULL) ?	\
+	(SC_DEV((sc),(x))->si_tty) : NULL)
+
+void
+sc_update_render(scr_stat *scp)
+{
+	sc_rndr_sw_t *rndr;
+	sc_term_sw_t *sw;
+	struct tty *tp;
+	int prev_ysize, new_ysize;
+	int error;
+
+	sw = scp->tsw;
+	if (sw == NULL) {
+		return;
+	}
+
+	if (scp->rndr == NULL)
+		return;
+
+	if (scp->fbi == scp->sc->fbi)
+		return;
+
+	crit_enter();
+	scp->fbi = scp->sc->fbi;
+	rndr = NULL;
+	if (strcmp(sw->te_renderer, "*") != 0) {
+		rndr = sc_render_match(scp, sw->te_renderer, scp->model);
+	}
+	if (rndr == NULL && scp->sc->fbi != NULL) {
+		rndr = sc_render_match(scp, "kms", scp->model);
+	}
+	if (rndr != NULL) {
+		scp->rndr = rndr;
+		/* Mostly copied from sc_set_text_mode */
+		if ((error = sc_clean_up(scp))) {
+			crit_exit();
+			return;
+		}
+		new_ysize = 0;
+#ifndef SC_NO_HISTORY
+		if (scp->history != NULL) {
+			sc_hist_save(scp);
+			new_ysize = sc_vtb_rows(scp->history);
+		}
+#endif
+		prev_ysize = scp->ysize;
+		scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
+		scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE);
+		scp->model = V_INFO_MM_TEXT;
+		scp->font_mag = 1;
+		scp->xpixel = scp->fbi->width;
+		scp->ypixel = scp->fbi->height;
+		scp->xsize = scp->xpixel / 8;
+		scp->ysize = scp->ypixel / scp->font_size;
+		while (scp->xsize / (scp->font_mag + 1) >= 80 &&
+		    scp->ysize / (scp->font_mag + 1) >= 25)
+			scp->font_mag++;
+		scp->xsize /= scp->font_mag;
+		scp->ysize /= scp->font_mag;
+#if 0 /* test */
+		scp->xsize = 35;
+		scp->ysize = 10;
+		scp->font_mag = 6;
+#endif
+#if 0 /* XXX fix xoff and yoff */
+		scp->xoff =
+		    (scp->xpixel - (scp->xsize * 8 * scp->font_mag)) / 2;
+		scp->yoff =
+		    (scp->ypixel - (scp->ysize * scp->font_size * scp->font_mag)) / 2;
+#endif
+
+		/* allocate buffers */
+		sc_alloc_scr_buffer(scp, TRUE, TRUE);
+		sc_init_emulator(scp, NULL);
+#ifndef SC_NO_CUTPASTE
+		sc_alloc_cut_buffer(scp, FALSE);
+#endif
+#ifndef SC_NO_HISTORY
+		sc_alloc_history_buffer(scp, new_ysize, prev_ysize, FALSE);
+#endif
+		crit_exit();
+		scp->status &= ~UNKNOWN_MODE;
+		tp = VIRTUAL_TTY(scp->sc, scp->index);
+		if (tp == NULL)
+			return;
+		kprintf("syscons terminal resized from %dx%d to %dx%d, font magnification %d\n",
+		    tp->t_winsize.ws_col, tp->t_winsize.ws_row,
+		    scp->xsize, scp->ysize, scp->font_mag);
+		if (tp->t_winsize.ws_col != scp->xsize ||
+		    tp->t_winsize.ws_row != scp->ysize) {
+			tp->t_winsize.ws_col = scp->xsize;
+			tp->t_winsize.ws_row = scp->ysize;
+			pgsignal(tp->t_pgrp, SIGWINCH, 1);
+		}
+		return;
+	}
+	if (rndr == NULL) {
+		rndr = sc_render_match(scp, scp->sc->adp->va_name, scp->model);
+	}
+
+	if (rndr != NULL) {
+		scp->rndr = rndr;
+	}
+	crit_exit();
+}
diff --git a/sys/dev/misc/syscons/syscons.c b/sys/dev/misc/syscons/syscons.c
index dd0f82b..1227f3d 100644
--- a/sys/dev/misc/syscons/syscons.c
+++ b/sys/dev/misc/syscons/syscons.c
@@ -64,6 +64,7 @@
 #endif
 #include <machine/frame.h>
 
+#include <dev/drm/include/linux/fb.h>
 #include <dev/misc/kbd/kbdreg.h>
 #include <dev/video/fb/fbreg.h>
 #include <dev/video/fb/splashreg.h>
@@ -271,6 +272,41 @@ sc_probe_unit(int unit, int flags)
     return 0;
 }
 
+int
+register_framebuffer(struct fb_info *info)
+{
+    sc_softc_t *sc;
+
+    /* For now ignore framebuffers, which don't replace the vga display */
+    if (!info->is_vga_boot_display)
+	return 0;
+
+    lwkt_gettoken(&tty_token);
+    sc = sc_get_softc(0, (sc_console_unit == 0) ? SC_KERNEL_CONSOLE : 0);
+    if (sc == NULL) {
+	lwkt_reltoken(&tty_token);
+        kprintf("%s: sc_get_softc(%d, %d) returned NULL\n", __func__,
+	    0, (sc_console_unit == 0) ? SC_KERNEL_CONSOLE : 0);
+	return 0;
+    }
+
+    /* Ignore this framebuffer if we have already switched to a framebuffer */
+    if (sc->fbi != NULL) {
+	lwkt_reltoken(&tty_token);
+	return 0;
+    }
+
+    sc->fbi = info;
+
+    if (sc->fbi != NULL) {
+	sc_update_render(sc->cur_scp);
+	sc->fbi->restore(sc->fbi->cookie);
+    }
+
+    lwkt_reltoken(&tty_token);
+    return 0;
+}
+
 /* probe video adapters, return TRUE if found */ 
 static int
 scvidprobe(int unit, int flags, int cons)
@@ -2634,6 +2670,7 @@ exchange_scr(sc_softc_t *sc)
 	sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
 		    (void *)sc->adp->va_window, FALSE);
     scp->status |= MOUSE_HIDDEN;
+    sc_update_render(scp);     /* Switch to kms renderer if necessary */
     sc_move_cursor(scp, scp->xpos, scp->ypos);
     if (!ISGRAPHSC(scp))
 	sc_set_cursor_image(scp);
@@ -2649,6 +2686,9 @@ exchange_scr(sc_softc_t *sc)
     update_kbd_state(scp, scp->status, LOCK_MASK, TRUE);
 
     mark_all(scp);
+    if (scp->sc->fbi != NULL) {
+	scp->sc->fbi->restore(scp->sc->fbi->cookie);
+    }
     lwkt_reltoken(&tty_token);
 }
 
@@ -3147,10 +3187,33 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp)
 #endif
 	}
     }
-    sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
-    sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
     scp->xoff = scp->yoff = 0;
     scp->xpos = scp->ypos = 0;
+    scp->font_mag = 1;
+    scp->fbi = sc->fbi;
+    if (scp->fbi != NULL) {
+	scp->xpixel = scp->fbi->width;
+	scp->ypixel = scp->fbi->height;
+	scp->xsize = scp->xpixel / 8;
+	scp->ysize = scp->ypixel / scp->font_size;
+	while (scp->xsize / (scp->font_mag + 1) >= 80 &&
+	    scp->ysize / (scp->font_mag + 1) >= 25)
+		scp->font_mag++;
+	scp->xsize /= scp->font_mag;
+	scp->ysize /= scp->font_mag;
+#if 0 /* test */
+	scp->xsize = 35;
+	scp->ysize = 10;
+	scp->font_mag = 6;
+#endif
+#if 0 /* XXX fix xoff and yoff */
+	scp->xoff = (scp->xpixel - (scp->xsize * 8 * scp->font_mag)) / 2;
+	scp->yoff =
+	    (scp->ypixel - (scp->xsize * scp->font_size * scp->font_mag)) / 2;
+#endif
+    }
+    sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE);
+    sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE);
     scp->start = scp->xsize * scp->ysize - 1;
     scp->end = 0;
     scp->tsw = NULL;
@@ -3197,6 +3260,9 @@ sc_init_emulator(scr_stat *scp, char *name)
     if (strcmp(sw->te_renderer, "*") != 0) {
 	rndr = sc_render_match(scp, sw->te_renderer, scp->model);
     }
+    if (rndr == NULL && scp->sc->fbi != NULL) {
+	rndr = sc_render_match(scp, "kms", scp->model);
+    }
     if (rndr == NULL) {
 	rndr = sc_render_match(scp, scp->sc->adp->va_name, scp->model);
 	if (rndr == NULL) {
@@ -3609,7 +3675,7 @@ set_mode(scr_stat *scp)
 
     lwkt_gettoken(&tty_token);
     /* reject unsupported mode */
-    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) {
+    if (scp->sc->fbi == NULL && (*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) {
         lwkt_reltoken(&tty_token);
 	return 1;
     }
@@ -3621,9 +3687,12 @@ set_mode(scr_stat *scp)
     }
 
     /* setup video hardware for the given mode */
-    (*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
+    if (scp->sc->fbi == NULL)
+	(*vidsw[scp->sc->adapter]->set_mode)(scp->sc->adp, scp->mode);
     sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize,
 		(void *)scp->sc->adp->va_window, FALSE);
+    if (scp->sc->fbi != NULL)
+	goto done;
 
 #ifndef SC_NO_FONT_LOADING
     /* load appropriate font */
@@ -3655,6 +3724,7 @@ set_mode(scr_stat *scp)
     sc_set_border(scp, scp->border);
     sc_set_cursor_image(scp);
 
+done:
     lwkt_reltoken(&tty_token);
     return 0;
 }
diff --git a/sys/dev/misc/syscons/syscons.h b/sys/dev/misc/syscons/syscons.h
index 93d0540..c1a400f 100644
--- a/sys/dev/misc/syscons/syscons.h
+++ b/sys/dev/misc/syscons/syscons.h
@@ -29,7 +29,6 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/syscons/syscons.h,v 1.60.2.6 2002/09/15 22:30:45 dd Exp $
- * $DragonFly: src/sys/dev/misc/syscons/syscons.h,v 1.21 2008/08/03 03:00:21 dillon Exp $
  */
 
 #ifndef _DEV_SYSCONS_SYSCONS_H_
@@ -199,6 +198,8 @@ typedef struct sc_softc {
 	struct video_adapter *adp;
 	int		initial_mode;		/* initial video mode */
 
+	struct fb_info	*fbi;
+
 	int		first_vty;
 	int		vtys;
 	cdev_t		*dev;
@@ -253,6 +254,7 @@ typedef struct scr_stat {
 	struct sc_rndr_sw *rndr;		/* renderer */
 	sc_vtb_t	scr;
 	sc_vtb_t	vtb;
+	struct fb_info	*fbi;
 
 	int 		xpos;			/* current X position */
 	int 		ypos;			/* current Y position */
@@ -265,6 +267,7 @@ typedef struct scr_stat {
 
 	u_char		*font;			/* current font */
 	int		font_size;		/* fontsize in Y direction */
+	int		font_mag;		/* font magnification */
 
 	int		start;			/* modified area start */
 	int		end;			/* modified area end */
@@ -570,6 +573,7 @@ int		sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data,
 int		sc_render_add(sc_renderer_t *rndr);
 int		sc_render_remove(sc_renderer_t *rndr);
 sc_rndr_sw_t	*sc_render_match(scr_stat *scp, char *name, int model);
+void		sc_update_render(scr_stat *scp);
 
 /* scvtb.c */
 void		sc_vtb_init(sc_vtb_t *vtb, int type, int cols, int rows, 
diff --git a/sys/platform/pc32/conf/files b/sys/platform/pc32/conf/files
index df294e2..06e162c 100644
--- a/sys/platform/pc32/conf/files
+++ b/sys/platform/pc32/conf/files
@@ -149,16 +149,6 @@ dev/raid/pst/pst-iop.c			optional	pst
 dev/raid/pst/pst-raid.c			optional	pst
 dev/netif/sbni/if_sbni.c		optional	sbni
 dev/netif/sbni/if_sbni_pci.c		optional	sbni pci
-dev/misc/syscons/schistory.c		optional	sc
-dev/misc/syscons/scmouse.c		optional	sc
-dev/misc/syscons/scterm.c		optional	sc
-dev/misc/syscons/scterm-dumb.c		optional	sc
-dev/misc/syscons/scterm-sc.c		optional	sc
-dev/misc/syscons/scvgarndr.c		optional	sc vga
-dev/misc/syscons/scvidctl.c		optional	sc
-dev/misc/syscons/scvtb.c		optional	sc
-dev/misc/syscons/syscons.c		optional	sc
-dev/misc/syscons/sysmouse.c		optional	sc
 emulation/linux/i386/linprocfs/linprocfs_misc.c		optional	linprocfs
 emulation/linux/i386/linprocfs/linprocfs_subr.c		optional	linprocfs
 emulation/linux/i386/linprocfs/linprocfs_vfsops.c	optional	linprocfs
diff --git a/sys/platform/pc64/conf/files b/sys/platform/pc64/conf/files
index 25aa8e4..8d34940 100644
--- a/sys/platform/pc64/conf/files
+++ b/sys/platform/pc64/conf/files
@@ -91,16 +91,6 @@ dev/misc/kbd/kbd.c			optional	ukbd
 dev/misc/kbd/kbdsw.c			optional	atkbd
 dev/misc/kbd/kbdsw.c			optional	sc
 dev/misc/kbd/kbdsw.c			optional	ukbd
-dev/misc/syscons/schistory.c		optional	sc
-dev/misc/syscons/scmouse.c		optional	sc
-dev/misc/syscons/scterm.c		optional	sc
-dev/misc/syscons/scterm-dumb.c		optional	sc
-dev/misc/syscons/scterm-sc.c		optional	sc
-dev/misc/syscons/scvgarndr.c		optional	sc vga
-dev/misc/syscons/scvidctl.c		optional	sc
-dev/misc/syscons/scvtb.c		optional	sc
-dev/misc/syscons/syscons.c		optional	sc
-dev/misc/syscons/sysmouse.c		optional	sc
 kern/link_elf_obj.c		standard
 vfs/smbfs/smbfs_io.c		optional	smbfs
 vfs/smbfs/smbfs_node.c		optional	smbfs
-- 
2.3.0

