Page MenuHomeFreeBSD

D687.id1259.diff
No OneTemporary

D687.id1259.diff

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(&regs);
+
+ 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(&regs, 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

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)

Event Timeline