kernel/syscons: First hacky steps to make syscons work with {i915,radeon}kms.
authorSascha Wildner <saw@online.de>
Wed, 3 Jun 2015 18:01:46 +0000 (20:01 +0200)
committerSascha Wildner <saw@online.de>
Fri, 5 Jun 2015 22:58:52 +0000 (00:58 +0200)
This is a joint effort of Imre Vadasz (all the drm/i915/radeon related
bits) and me (syscons rendering related bits, mainly).

To enable the support, the "kern.kms_console" tunable needs to be set
via loader.conf.

In-collaboration-with: ivadasz

13 files changed:
share/man/man4/syscons.4
sys/conf/files
sys/dev/drm/drm_fb_helper.c
sys/dev/drm/i915/Makefile
sys/dev/drm/i915/intel_fbdev.c [new file with mode: 0644]
sys/dev/drm/include/drm/drm_fb_helper.h
sys/dev/drm/include/linux/fb.h
sys/dev/drm/radeon/radeon_fb.c
sys/dev/misc/syscons/sckmsrndr.c [new file with mode: 0644]
sys/dev/misc/syscons/scvidctl.c
sys/dev/misc/syscons/syscons.c
sys/dev/misc/syscons/syscons.h
sys/platform/pc64/conf/files

index 4b405ea..55143cf 100644 (file)
@@ -360,6 +360,19 @@ This option implies the
 .Dv SC_NO_CUTPASTE
 option too.
 .El
+.Ss Loader Tunables
+The following tunable is available and can be set in
+.Xr loader.conf 5 .
+.Bl -tag -width ".Va kern.kms_console"
+.It Va kern.kms_console
+Setting this tunable to 1 enables experimental framebuffer support
+in conjunction with the
+.Nm i915kms
+or
+.Nm radeonkms
+drivers.
+It is 0 by default.
+.El
 .Ss Driver Flags
 The following driver flags can be used to control the
 .Nm
index 03663e8..b69a4cb 100644 (file)
@@ -1975,6 +1975,7 @@ dev/drm/ttm/ttm_bo_vm.c                   optional drm
 #dev/drm/i915/intel_dsi.c              optional i915kms drm
 #dev/drm/i915/intel_dsi_cmd.c          optional i915kms drm
 #dev/drm/i915/intel_dsi_pll.c          optional i915kms drm
+#dev/drm/i915/intel_fbdev.c            optional i915kms drm
 #dev/drm/i915/intel_hdmi.c             optional i915kms drm
 #dev/drm/i915/intel_i2c.c              optional i915kms drm
 #dev/drm/i915/intel_lvds.c             optional i915kms drm
index 7b81cab..0a41d51 100644 (file)
@@ -879,6 +879,31 @@ int drm_fb_helper_pan_display(struct fb_var_screeninfo *var,
 EXPORT_SYMBOL(drm_fb_helper_pan_display);
 #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);
+}
+
 /*
  * Allocates the backing storage and sets up the fbdev info structure through
  * the ->fb_probe callback and then registers the fbdev and sets up the panic
@@ -893,6 +918,7 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
        struct fb_info *info;
        struct drm_fb_helper_surface_size sizes;
        int gamma_size = 0;
+       int kms_console = 0;
 
        memset(&sizes, 0, sizeof(struct drm_fb_helper_surface_size));
        sizes.surface_depth = 24;
@@ -982,6 +1008,15 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
                if (fb_helper->crtc_info[i].mode_set.num_connectors)
                        fb_helper->crtc_info[i].mode_set.fb = fb_helper->fb;
 
+       TUNABLE_INT_FETCH("kern.kms_console", &kms_console);
+       if (kms_console) {
+               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;
+       }
 
 #if 0
        info->var.pixclock = 0;
index 29bb8a6..c4a2181 100644 (file)
@@ -18,6 +18,7 @@ SRCS  = \
        intel_ddi.c \
        intel_display.c \
        intel_dp.c \
+       intel_fbdev.c \
        intel_hdmi.c \
        intel_i2c.c \
        intel_lvds.c \
@@ -39,6 +40,7 @@ SRCS  = \
 SRCS   += acpi_if.h device_if.h bus_if.h pci_if.h iicbus_if.h iicbb_if.h \
          opt_acpi.h opt_drm.h opt_ktr.h
 
+CFLAGS+= -DCONFIG_DRM_I915_FBDEV
 CFLAGS+= -I${SYSDIR}/dev/drm/include
 CFLAGS+= -I${.CURDIR}/../../../contrib/dev/acpica/source/include
 
diff --git a/sys/dev/drm/i915/intel_fbdev.c b/sys/dev/drm/i915/intel_fbdev.c
new file mode 100644 (file)
index 0000000..8f4ff65
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright © 2007 David Airlie
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *     David Airlie
+ */
+
+#include <drm/drmP.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+
+#include <drm/drm_crtc.h>
+#include <drm/drm_fb_helper.h>
+#include "intel_drv.h"
+#include <drm/i915_drm.h>
+#include "i915_drv.h"
+
+#if 0
+static struct fb_ops intelfb_ops = {
+       .owner = THIS_MODULE,
+       .fb_check_var = drm_fb_helper_check_var,
+       .fb_set_par = drm_fb_helper_set_par,
+       .fb_fillrect = cfb_fillrect,
+       .fb_copyarea = cfb_copyarea,
+       .fb_imageblit = cfb_imageblit,
+       .fb_pan_display = drm_fb_helper_pan_display,
+       .fb_blank = drm_fb_helper_blank,
+       .fb_setcmap = drm_fb_helper_setcmap,
+       .fb_debug_enter = drm_fb_helper_debug_enter,
+       .fb_debug_leave = drm_fb_helper_debug_leave,
+};
+#endif
+
+static int intelfb_alloc(struct drm_fb_helper *helper,
+                        struct drm_fb_helper_surface_size *sizes)
+{
+       struct intel_fbdev *ifbdev =
+               container_of(helper, struct intel_fbdev, helper);
+       struct drm_device *dev = helper->dev;
+       struct drm_mode_fb_cmd2 mode_cmd = {};
+       struct drm_i915_gem_object *obj;
+       int size, ret;
+
+       /* we don't do packed 24bpp */
+       if (sizes->surface_bpp == 24)
+               sizes->surface_bpp = 32;
+
+       mode_cmd.width = sizes->surface_width;
+       mode_cmd.height = sizes->surface_height;
+
+       mode_cmd.pitches[0] = ALIGN(mode_cmd.width *
+                                   DIV_ROUND_UP(sizes->surface_bpp, 8), 64);
+       mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
+                                                         sizes->surface_depth);
+
+       size = mode_cmd.pitches[0] * mode_cmd.height;
+       size = ALIGN(size, PAGE_SIZE);
+       obj = i915_gem_object_create_stolen(dev, size);
+       if (obj == NULL)
+               obj = i915_gem_alloc_object(dev, size);
+       if (!obj) {
+               DRM_ERROR("failed to allocate framebuffer\n");
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* Flush everything out, we'll be doing GTT only from now on */
+       ret = intel_pin_and_fence_fb_obj(dev, obj, NULL);
+       if (ret) {
+               DRM_ERROR("failed to pin fb: %d\n", ret);
+               goto out_unref;
+       }
+
+       ret = intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, obj);
+       if (ret)
+               goto out_unpin;
+
+       return 0;
+
+out_unpin:
+       i915_gem_object_unpin(obj);
+out_unref:
+       drm_gem_object_unreference(&obj->base);
+out:
+       return ret;
+}
+
+static int intelfb_create(struct drm_fb_helper *helper,
+                         struct drm_fb_helper_surface_size *sizes)
+{
+       struct intel_fbdev *ifbdev =
+               container_of(helper, struct intel_fbdev, helper);
+       struct intel_framebuffer *intel_fb = &ifbdev->ifb;
+       struct drm_device *dev = helper->dev;
+#if 0
+       struct drm_i915_private *dev_priv = dev->dev_private;
+#endif
+       struct fb_info *info;
+       struct drm_framebuffer *fb;
+       struct drm_i915_gem_object *obj;
+       device_t vga_dev;
+       int size, ret;
+
+       mutex_lock(&dev->struct_mutex);
+
+       if (!intel_fb->obj) {
+               DRM_DEBUG_KMS("no BIOS fb, allocating a new one\n");
+               ret = intelfb_alloc(helper, sizes);
+               if (ret)
+                       goto out_unlock;
+       } else {
+               DRM_DEBUG_KMS("re-using BIOS fb\n");
+               sizes->fb_width = intel_fb->base.width;
+               sizes->fb_height = intel_fb->base.height;
+       }
+
+       obj = intel_fb->obj;
+       size = obj->base.size;
+
+#if 0
+       info = framebuffer_alloc(0, &dev->pdev->dev);
+       if (!info) {
+               ret = -ENOMEM;
+               goto out_unpin;
+       }
+
+       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 =
+           ALIGN(sizes->surface_width * ((sizes->surface_bpp + 7) / 8), 64);
+       info->depth = sizes->surface_bpp;
+       info->paddr = dev->agp->base + i915_gem_obj_ggtt_offset(obj);
+       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);
+
+       fb = &ifbdev->ifb.base;
+
+       ifbdev->helper.fb = fb;
+       ifbdev->helper.fbdev = info;
+
+#if 0
+       strcpy(info->fix.id, "inteldrmfb");
+
+       info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
+       info->fbops = &intelfb_ops;
+
+       ret = fb_alloc_cmap(&info->cmap, 256, 0);
+       if (ret) {
+               ret = -ENOMEM;
+               goto out_unpin;
+       }
+       /* setup aperture base/size for vesafb takeover */
+       info->apertures = alloc_apertures(1);
+       if (!info->apertures) {
+               ret = -ENOMEM;
+               goto out_unpin;
+       }
+       info->apertures->ranges[0].base = dev->mode_config.fb_base;
+       info->apertures->ranges[0].size = dev_priv->gtt.mappable_end;
+
+       info->fix.smem_start = dev->mode_config.fb_base + i915_gem_obj_ggtt_offset(obj);
+       info->fix.smem_len = size;
+
+       info->screen_base =
+               ioremap_wc(dev_priv->gtt.mappable_base + i915_gem_obj_ggtt_offset(obj),
+                          size);
+       if (!info->screen_base) {
+               ret = -ENOSPC;
+               goto out_unpin;
+       }
+       info->screen_size = size;
+
+       /* This driver doesn't need a VT switch to restore the mode on resume */
+       info->skip_vt_switch = true;
+
+       drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
+       drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height);
+
+       /* If the object is shmemfs backed, it will have given us zeroed pages.
+        * If the object is stolen however, it will be full of whatever
+        * garbage was left in there.
+        */
+       if (ifbdev->ifb.obj->stolen)
+               memset_io(info->screen_base, 0, info->screen_size);
+
+       /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
+#endif
+
+       DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08lx, bo %p\n",
+                     fb->width, fb->height,
+                     i915_gem_obj_ggtt_offset(obj), obj);
+
+       mutex_unlock(&dev->struct_mutex);
+#if 0
+       vga_switcheroo_client_fb_set(dev->pdev, info);
+#endif
+       return 0;
+
+#if 0
+out_unpin:
+       i915_gem_object_unpin(obj);
+       drm_gem_object_unreference(&obj->base);
+#endif
+out_unlock:
+       mutex_unlock(&dev->struct_mutex);
+       return ret;
+}
+
+/** Sets the color ramps on behalf of RandR */
+static void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
+                                   u16 blue, int regno)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       intel_crtc->lut_r[regno] = red >> 8;
+       intel_crtc->lut_g[regno] = green >> 8;
+       intel_crtc->lut_b[regno] = blue >> 8;
+}
+
+static void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
+                                   u16 *blue, int regno)
+{
+       struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+
+       *red = intel_crtc->lut_r[regno] << 8;
+       *green = intel_crtc->lut_g[regno] << 8;
+       *blue = intel_crtc->lut_b[regno] << 8;
+}
+
+static struct drm_fb_helper_funcs intel_fb_helper_funcs = {
+       .gamma_set = intel_crtc_fb_gamma_set,
+       .gamma_get = intel_crtc_fb_gamma_get,
+       .fb_probe = intelfb_create,
+};
+
+static void intel_fbdev_destroy(struct drm_device *dev,
+                               struct intel_fbdev *ifbdev)
+{
+#if 0
+       if (ifbdev->helper.fbdev) {
+               struct fb_info *info = ifbdev->helper.fbdev;
+
+               unregister_framebuffer(info);
+               iounmap(info->screen_base);
+               if (info->cmap.len)
+                       fb_dealloc_cmap(&info->cmap);
+
+               framebuffer_release(info);
+       }
+#endif
+
+       drm_fb_helper_fini(&ifbdev->helper);
+
+       drm_framebuffer_unregister_private(&ifbdev->ifb.base);
+       intel_framebuffer_fini(&ifbdev->ifb);
+}
+
+int intel_fbdev_init(struct drm_device *dev)
+{
+       struct intel_fbdev *ifbdev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       int ret;
+
+       ifbdev = kzalloc(sizeof(*ifbdev), GFP_KERNEL);
+       if (!ifbdev)
+               return -ENOMEM;
+
+       dev_priv->fbdev = ifbdev;
+       ifbdev->helper.funcs = &intel_fb_helper_funcs;
+
+       ret = drm_fb_helper_init(dev, &ifbdev->helper,
+                                INTEL_INFO(dev)->num_pipes,
+                                4);
+       if (ret) {
+               kfree(ifbdev);
+               return ret;
+       }
+
+       drm_fb_helper_single_add_all_connectors(&ifbdev->helper);
+
+       return 0;
+}
+
+void intel_fbdev_initial_config(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       /* Due to peculiar init order wrt to hpd handling this is separate. */
+       drm_fb_helper_initial_config(&dev_priv->fbdev->helper, 32);
+}
+
+void intel_fbdev_fini(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       if (!dev_priv->fbdev)
+               return;
+
+       intel_fbdev_destroy(dev, dev_priv->fbdev);
+       kfree(dev_priv->fbdev);
+       dev_priv->fbdev = NULL;
+}
+
+void intel_fbdev_set_suspend(struct drm_device *dev, int state)
+{
+#if 0
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       struct intel_fbdev *ifbdev = dev_priv->fbdev;
+       struct fb_info *info;
+
+       if (!ifbdev)
+               return;
+
+       info = ifbdev->helper.fbdev;
+
+       /* On resume from hibernation: If the object is shmemfs backed, it has
+        * been restored from swap. If the object is stolen however, it will be
+        * full of whatever garbage was left in there.
+        */
+       if (state == FBINFO_STATE_RUNNING && ifbdev->ifb.obj->stolen)
+               memset_io(info->screen_base, 0, info->screen_size);
+
+       fb_set_suspend(info, state);
+#endif
+}
+
+void intel_fbdev_output_poll_changed(struct drm_device *dev)
+{
+       struct drm_i915_private *dev_priv = dev->dev_private;
+       drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
+}
+
+void intel_fbdev_restore_mode(struct drm_device *dev)
+{
+       int ret;
+       struct drm_i915_private *dev_priv = dev->dev_private;
+
+       if (INTEL_INFO(dev)->num_pipes == 0)
+               return;
+
+       drm_modeset_lock_all(dev);
+
+       ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
+       if (ret)
+               DRM_DEBUG("failed to restore crtc mode\n");
+
+       drm_modeset_unlock_all(dev);
+}
index 08f7950..ae598ac 100644 (file)
@@ -86,6 +86,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;
index 22e2cb7..09ac33c 100644 (file)
 
 #define        KHZ2PICOS(a)    (1000000000UL/(a))
 
+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_ */
index 1fab672..4efb581 100644 (file)
@@ -191,9 +191,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
 {
        struct radeon_fbdev *rfbdev = (struct radeon_fbdev *)helper;
        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;
@@ -201,10 +199,9 @@ static int radeonfb_create(struct drm_fb_helper *helper,
 #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;
@@ -224,16 +221,7 @@ static int radeonfb_create(struct drm_fb_helper *helper,
 
        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) {
@@ -245,56 +233,23 @@ static int radeonfb_create(struct drm_fb_helper *helper,
 
        /* 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:
@@ -317,6 +272,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 (file)
index 0000000..0091cef
--- /dev/null
@@ -0,0 +1,302 @@
+/*-
+ * 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 <machine/console.h>
+
+#include <dev/drm/include/linux/fb.h>
+
+#include "syscons.h"
+
+#include <bus/isa/isareg.h>
+
+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, p;
+       int pos, line_width, pixel_size;
+
+       line_width = sc->fbi->stride;
+       pixel_size = 4;
+
+       draw_pos = sc->fbi->vaddr +
+           8 * pixel_size * (from % scp->xsize) +
+           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];
+               }
+
+               for (j = 0; j < scp->font_size; j++, char_data++) {
+                       for (pos = 7; pos >= 0; pos--, p += pixel_size)
+                               writel(p, *char_data & (1 << pos) ? fg : bg);
+                       p += line_width - 8 * pixel_size;
+               }
+               draw_pos += 8 * pixel_size;
+               if ((i % scp->xsize) == scp->xsize - 1) {
+                       draw_pos += (scp->font_size - 1) * line_width +
+                           scp->xpad * pixel_size;
+               }
+       }
+}
+
+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 +
+           8 * pixel_size * (at % scp->xsize) +
+           scp->font_size * line_width * (at / scp->xsize) +
+           (scp->font_size - scp->cursor_base - 1) * 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)
+                       writel(draw_pos, *char_data & (1 << pos) ? fg : bg);
+               draw_pos -= line_width + 8 * 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 * line_width + x * 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))
+                               writel(draw_pos + pixel_size * j, colormap[15]);
+                       else if (mouse_and_mask[i] & 1 << (15 - j))
+                               writel(draw_pos + pixel_size * j, colormap[0]);
+               }
+
+               draw_pos += 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 */
index a8cbe87..9a997bd 100644 (file)
@@ -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,91 @@ 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->xpixel = scp->fbi->width;
+               scp->ypixel = scp->fbi->height;
+               scp->xsize = scp->xpixel / 8;
+               scp->ysize = scp->ypixel / scp->font_size;
+               scp->xpad = scp->fbi->stride / 4 - scp->xsize * 8;
+
+               /* 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;
+               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();
+}
index feba21e..0065e5b 100644 (file)
@@ -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>
@@ -273,6 +274,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)
@@ -2636,6 +2672,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);
@@ -2651,6 +2688,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);
 }
 
@@ -3149,10 +3189,17 @@ 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->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;
+    }
+    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;
@@ -3199,6 +3246,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) {
@@ -3628,7 +3678,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;
     }
@@ -3640,9 +3690,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 */
@@ -3674,6 +3727,7 @@ set_mode(scr_stat *scp)
     sc_set_border(scp, scp->border);
     sc_set_cursor_image(scp);
 
+done:
     lwkt_reltoken(&tty_token);
     return 0;
 }
index 93d0540..d9bf126 100644 (file)
@@ -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 */
@@ -260,6 +262,7 @@ typedef struct scr_stat {
        int             ysize;                  /* Y text size */
        int             xpixel;                 /* X graphics size */
        int             ypixel;                 /* Y graphics size */
+       int             xpad;                   /* for fbi->stride % 8 != 0 */
        int             xoff;                   /* X offset in pixel mode */
        int             yoff;                   /* Y offset in pixel mode */
 
@@ -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, 
index 25aa8e4..b4bad61 100644 (file)
@@ -92,6 +92,7 @@ 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/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