Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160242798
D687.id1259.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D687.id1259.diff
View Options
Index: sys/dev/drm2/drm_fb_helper.c
===================================================================
--- sys/dev/drm2/drm_fb_helper.c
+++ sys/dev/drm2/drm_fb_helper.c
@@ -69,6 +69,21 @@
return (0);
}
+static int
+vt_kms_reset(void *arg)
+{
+ struct vt_kms_softc *sc;
+ device_t vga;
+ int ret;
+
+ sc = (struct vt_kms_softc *)arg;
+
+ vga = device_get_parent(sc->fb_helper->dev->device);
+ ret = vga_pci_repost(vga);
+
+ return (ret);
+}
+
static DRM_LIST_HEAD(kernel_fb_helper_list);
/* simple single crtc case helper function */
@@ -1024,6 +1039,7 @@
info->fb_stride = fb_helper->fb->pitches[0];
info->fb_priv = sc;
info->enter = &vt_kms_postswitch;
+ info->reset = &vt_kms_reset;
/* set the fb pointer */
for (i = 0; i < fb_helper->crtc_count; i++) {
@@ -1036,10 +1052,12 @@
kdev = fb_helper->dev->device;
fbd = device_add_child(kdev, "fbd", device_get_unit(kdev));
- if (fbd != NULL)
+ if (fbd != NULL) {
+ info->fbd_dev = fbd;
ret = device_probe_and_attach(fbd);
- else
+ } else {
ret = ENODEV;
+ }
#ifdef DEV_VT
if (ret != 0)
DRM_ERROR("Failed to attach fbd device: %d\n", ret);
Index: sys/dev/drm2/radeon/radeon_fb.c
===================================================================
--- sys/dev/drm2/radeon/radeon_fb.c
+++ sys/dev/drm2/radeon/radeon_fb.c
@@ -291,6 +291,8 @@
if (rfbdev->helper.fbdev) {
info = rfbdev->helper.fbdev;
+ vga_pci_repost(device_get_parent(dev->device));
+ free(info->fb_priv, DRM_MEM_KMS);
free(info, DRM_MEM_KMS);
}
Index: sys/dev/fb/fbd.c
===================================================================
--- sys/dev/fb/fbd.c
+++ sys/dev/fb/fbd.c
@@ -51,6 +51,8 @@
#include <dev/vt/vt.h>
#include <dev/vt/hw/fb/vt_fb.h>
+#include <dev/pci/pcivar.h>
+
#include "fb_if.h"
LIST_HEAD(fb_list_head_t, fb_list_entry) fb_list_head =
@@ -262,6 +264,8 @@
LIST_FOREACH_SAFE(entry, &fb_list_head, fb_list, tmp) {
if (entry->fb_info == info) {
LIST_REMOVE(entry, fb_list);
+ if (LIST_EMPTY(&fb_list_head))
+ vt_fb_detach(info);
free(entry, M_DEVBUF);
return (0);
}
Index: sys/dev/pci/pcivar.h
===================================================================
--- sys/dev/pci/pcivar.h
+++ sys/dev/pci/pcivar.h
@@ -565,5 +565,6 @@
int vga_pci_is_boot_display(device_t dev);
void * vga_pci_map_bios(device_t dev, size_t *size);
void vga_pci_unmap_bios(device_t dev, void *bios);
+int vga_pci_repost(device_t dev);
#endif /* _PCIVAR_H_ */
Index: sys/dev/pci/vga_pci.c
===================================================================
--- sys/dev/pci/vga_pci.c
+++ sys/dev/pci/vga_pci.c
@@ -51,6 +51,8 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
+#include <compat/x86bios/x86bios.h> /* To re-POST the card. */
+
struct vga_resource {
struct resource *vr_res;
int vr_refs;
@@ -194,6 +196,35 @@
vr->vr_res);
}
+int
+vga_pci_repost(device_t dev)
+{
+#if defined(__amd64__) || defined(__i386__)
+ x86regs_t regs;
+
+ if (!vga_pci_is_boot_display(dev))
+ return (EINVAL);
+
+ if (x86bios_get_orm(VGA_PCI_BIOS_SHADOW_ADDR) == NULL)
+ return (ENOTSUP);
+
+ x86bios_init_regs(®s);
+
+ regs.R_AH = pci_get_bus(dev);
+ regs.R_AL = (pci_get_slot(dev) << 3) | (pci_get_function(dev) & 0x07);
+ regs.R_DL = 0x80;
+
+ x86bios_call(®s, X86BIOS_PHYSTOSEG(VGA_PCI_BIOS_SHADOW_ADDR + 3),
+ X86BIOS_PHYSTOOFF(VGA_PCI_BIOS_SHADOW_ADDR + 3));
+
+ x86bios_get_intr(0x10);
+
+ return (0);
+#else
+ return (ENOTSUP);
+#endif
+}
+
static int
vga_pci_probe(device_t dev)
{
Index: sys/dev/vt/hw/fb/vt_fb.h
===================================================================
--- sys/dev/vt/hw/fb/vt_fb.h
+++ sys/dev/vt/hw/fb/vt_fb.h
@@ -35,8 +35,10 @@
int vt_fb_attach(struct fb_info *info);
void vt_fb_resume(void);
void vt_fb_suspend(void);
+int vt_fb_detach(struct fb_info *info);
vd_init_t vt_fb_init;
+vd_reset_t vt_fb_reset;
vd_blank_t vt_fb_blank;
vd_bitblt_text_t vt_fb_bitblt_text;
vd_bitblt_bmp_t vt_fb_bitblt_bitmap;
Index: sys/dev/vt/hw/fb/vt_fb.c
===================================================================
--- sys/dev/vt/hw/fb/vt_fb.c
+++ sys/dev/vt/hw/fb/vt_fb.c
@@ -47,6 +47,7 @@
static struct vt_driver vt_fb_driver = {
.vd_name = "fb",
.vd_init = vt_fb_init,
+ .vd_reset = vt_fb_reset,
.vd_blank = vt_fb_blank,
.vd_bitblt_text = vt_fb_bitblt_text,
.vd_bitblt_bmp = vt_fb_bitblt_bitmap,
@@ -439,6 +440,21 @@
}
int
+vt_fb_reset(struct vt_device *vd)
+{
+ struct fb_info *info;
+ int err;
+
+ info = vd->vd_softc;
+
+ err = 0;
+ if (info->reset != NULL)
+ err = info->reset(info->fb_priv);
+
+ return (err);
+}
+
+int
vt_fb_attach(struct fb_info *info)
{
@@ -447,6 +463,15 @@
return (0);
}
+int
+vt_fb_detach(struct fb_info *info)
+{
+
+ vt_deallocate(&vt_fb_driver, info);
+
+ return (0);
+}
+
void
vt_fb_resume(void)
{
Index: sys/dev/vt/vt.h
===================================================================
--- sys/dev/vt/vt.h
+++ sys/dev/vt/vt.h
@@ -95,9 +95,10 @@
struct vt_driver;
-void vt_allocate(struct vt_driver *, void *);
+void vt_allocate(const struct vt_driver *, void *);
void vt_resume(void);
void vt_suspend(void);
+void vt_deallocate(const struct vt_driver *, void *);
typedef unsigned int vt_axis_t;
@@ -126,6 +127,8 @@
struct vt_window *vd_markedwin; /* (?) Copy/paste buf owner. */
const struct vt_driver *vd_driver; /* (c) Graphics driver. */
void *vd_softc; /* (u) Driver data. */
+ const struct vt_driver *vd_old_driver; /* (?) Previous driver. */
+ void *vd_old_softc; /* (?) Previous driver data. */
#ifndef SC_NO_CUTPASTE
struct vt_mouse_cursor *vd_mcursor; /* (?) Cursor bitmap. */
term_color_t vd_mcursor_fg; /* (?) Cursor fg color. */
@@ -292,6 +295,7 @@
typedef int vd_init_t(struct vt_device *vd);
typedef int vd_probe_t(struct vt_device *vd);
+typedef int vd_reset_t(struct vt_device *vd);
typedef void vd_postswitch_t(struct vt_device *vd);
typedef void vd_blank_t(struct vt_device *vd, term_color_t color);
typedef void vd_bitblt_text_t(struct vt_device *vd, const struct vt_window *vw,
@@ -312,6 +316,7 @@
/* Console attachment. */
vd_probe_t *vd_probe;
vd_init_t *vd_init;
+ vd_reset_t *vd_reset;
/* Drawing. */
vd_blank_t *vd_blank;
Index: sys/dev/vt/vt_core.c
===================================================================
--- sys/dev/vt/vt_core.c
+++ sys/dev/vt/vt_core.c
@@ -157,6 +157,8 @@
static struct vt_device vt_consdev = {
.vd_driver = NULL,
.vd_softc = NULL,
+ .vd_old_driver = NULL,
+ .vd_old_softc = NULL,
.vd_flags = VDF_INVALID,
.vd_windows = { [VT_CONSWINDOW] = &vt_conswindow, },
.vd_curwindow = &vt_conswindow,
@@ -2178,31 +2180,11 @@
}
}
-void
-vt_allocate(struct vt_driver *drv, void *softc)
+static void
+vt_replace(const struct vt_driver *drv, void *softc, int is_downgrade)
{
struct vt_device *vd;
- if (!vty_enabled(VTY_VT))
- return;
-
- if (main_vd->vd_driver == NULL) {
- main_vd->vd_driver = drv;
- printf("VT: initialize with new VT driver \"%s\".\n",
- drv->vd_name);
- } else {
- /*
- * Check if have rights to replace current driver. For example:
- * it is bad idea to replace KMS driver with generic VGA one.
- */
- if (drv->vd_priority <= main_vd->vd_driver->vd_priority) {
- printf("VT: Driver priority %d too low. Current %d\n ",
- drv->vd_priority, main_vd->vd_driver->vd_priority);
- return;
- }
- printf("VT: Replacing driver \"%s\" with new \"%s\".\n",
- main_vd->vd_driver->vd_name, drv->vd_name);
- }
vd = main_vd;
VT_LOCK(vd);
@@ -2222,8 +2204,20 @@
*/
vd->vd_flags &= ~VDF_TEXTMODE;
+ if (!is_downgrade) {
+ vd->vd_old_driver = vd->vd_driver;
+ vd->vd_old_softc = vd->vd_softc;
+ } else {
+ if (vd->vd_driver->vd_reset)
+ vd->vd_driver->vd_reset(vd);
+
+ vd->vd_old_driver = NULL;
+ vd->vd_old_softc = NULL;
+ }
+
vd->vd_driver = drv;
vd->vd_softc = softc;
+
vd->vd_driver->vd_init(vd);
VT_UNLOCK(vd);
@@ -2250,6 +2244,50 @@
}
void
+vt_allocate(const struct vt_driver *drv, void *softc)
+{
+
+ if (!vty_enabled(VTY_VT))
+ return;
+
+ if (main_vd->vd_driver == NULL) {
+ main_vd->vd_driver = drv;
+ printf("VT: initialize with new VT driver \"%s\".\n",
+ drv->vd_name);
+ } else {
+ /*
+ * Check if have rights to replace current driver. For example:
+ * it is bad idea to replace KMS driver with generic VGA one.
+ */
+ if (drv->vd_priority <= main_vd->vd_driver->vd_priority) {
+ printf("VT: Driver priority %d too low. Current %d\n ",
+ drv->vd_priority, main_vd->vd_driver->vd_priority);
+ return;
+ }
+ printf("VT: Replacing driver \"%s\" with new \"%s\".\n",
+ main_vd->vd_driver->vd_name, drv->vd_name);
+ }
+
+ vt_replace(drv, softc, 0);
+}
+
+void
+vt_deallocate(const struct vt_driver *drv, void *softc)
+{
+
+ if (!vty_enabled(VTY_VT))
+ return;
+
+ if (main_vd->vd_old_driver == NULL)
+ return;
+
+ printf("VT: Switching back from \"%s\" to \"%s\".\n",
+ main_vd->vd_driver->vd_name, main_vd->vd_old_driver->vd_name);
+
+ vt_replace(main_vd->vd_old_driver, main_vd->vd_old_softc, 1);
+}
+
+void
vt_suspend()
{
Index: sys/sys/fbio.h
===================================================================
--- sys/sys/fbio.h
+++ sys/sys/fbio.h
@@ -115,6 +115,7 @@
typedef int fb_enter_t(void *priv);
typedef int fb_leave_t(void *priv);
+typedef int fb_reset_t(void *priv);
struct fb_info {
/* Raw copy of fbtype. Do not change. */
@@ -127,8 +128,11 @@
struct cdev *fb_cdev;
+ device_t fbd_dev; /* "fbd" device. */
+
fb_enter_t *enter;
fb_leave_t *leave;
+ fb_reset_t *reset;
intptr_t fb_pbase; /* For FB mmap. */
intptr_t fb_vbase; /* if NULL, use fb_write/fb_read. */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jun 23, 12:28 PM (4 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34245635
Default Alt Text
D687.id1259.diff (9 KB)
Attached To
Mode
D687: vt(4): Add support to "downgrade" from eg. vt_fb to vt_vga
Attached
Detach File
Event Timeline
Log In to Comment