diff --git a/sys/dev/fb/fbd.c b/sys/dev/fb/fbd.c index ff2488d537c6..6bd5766543b5 100644 --- a/sys/dev/fb/fbd.c +++ b/sys/dev/fb/fbd.c @@ -332,22 +332,6 @@ fbd_detach(device_t dev) return (err); } -static int -fbd_suspend(device_t dev) -{ - - vt_fb_suspend(); - return (bus_generic_suspend(dev)); -} - -static int -fbd_resume(device_t dev) -{ - - vt_fb_resume(); - return (bus_generic_resume(dev)); -} - static device_method_t fbd_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fbd_probe), @@ -355,8 +339,6 @@ static device_method_t fbd_methods[] = { DEVMETHOD(device_detach, fbd_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, fbd_suspend), - DEVMETHOD(device_resume, fbd_resume), { 0, 0 } }; diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c index 044b64161099..5a0fe4f24854 100644 --- a/sys/dev/vt/hw/fb/vt_fb.c +++ b/sys/dev/vt/hw/fb/vt_fb.c @@ -53,6 +53,8 @@ static struct vt_driver vt_fb_driver = { .vd_priority = VD_PRIORITY_GENERIC+10, .vd_fb_ioctl = vt_fb_ioctl, .vd_fb_mmap = vt_fb_mmap, + .vd_suspend = vt_fb_suspend, + .vd_resume = vt_fb_resume, }; VT_DRIVER_DECLARE(vt_fb, vt_fb_driver); @@ -450,15 +452,15 @@ vt_fb_attach(struct fb_info *info) } void -vt_fb_resume(void) +vt_fb_suspend(struct vt_device *vd) { - vt_resume(); + vt_suspend(vd); } void -vt_fb_suspend(void) +vt_fb_resume(struct vt_device *vd) { - vt_suspend(); + vt_resume(vd); } diff --git a/sys/dev/vt/hw/fb/vt_fb.h b/sys/dev/vt/hw/fb/vt_fb.h index 43ce2b7b4c64..ac18cff49e36 100644 --- a/sys/dev/vt/hw/fb/vt_fb.h +++ b/sys/dev/vt/hw/fb/vt_fb.h @@ -33,8 +33,8 @@ #define _DEV_VT_HW_FB_VT_FB_H_ /* Generic framebuffer interface call vt_fb_attach to init VT(9) */ int vt_fb_attach(struct fb_info *info); -void vt_fb_resume(void); -void vt_fb_suspend(void); +void vt_fb_resume(struct vt_device *vd); +void vt_fb_suspend(struct vt_device *vd); vd_init_t vt_fb_init; vd_blank_t vt_fb_blank; diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h index 67fcf1e06491..0ad8ab5dffda 100644 --- a/sys/dev/vt/vt.h +++ b/sys/dev/vt/vt.h @@ -90,8 +90,6 @@ SYSCTL_INT(_kern_vt, OID_AUTO, _name, CTLFLAG_RWTUN, &vt_##_name, _default,\ struct vt_driver; void vt_allocate(struct vt_driver *, void *); -void vt_resume(void); -void vt_suspend(void); typedef unsigned int vt_axis_t; @@ -162,6 +160,9 @@ struct vt_device { #define VD_PASTEBUFSZ(vd) ((vd)->vd_pastebuf.vpb_bufsz) #define VD_PASTEBUFLEN(vd) ((vd)->vd_pastebuf.vpb_len) +void vt_resume(struct vt_device *vd); +void vt_suspend(struct vt_device *vd); + /* * Per-window terminal screen buffer. * @@ -314,6 +315,8 @@ typedef int vd_fb_mmap_t(struct vt_device *, vm_ooffset_t, vm_paddr_t *, int, typedef void vd_drawrect_t(struct vt_device *, int, int, int, int, int, term_color_t); typedef void vd_setpixel_t(struct vt_device *, int, int, term_color_t); +typedef void vd_suspend_t(struct vt_device *); +typedef void vd_resume_t(struct vt_device *); struct vt_driver { char vd_name[16]; @@ -337,6 +340,10 @@ struct vt_driver { /* Update display setting on vt switch. */ vd_postswitch_t *vd_postswitch; + /* Suspend/resume handlers. */ + vd_suspend_t *vd_suspend; + vd_resume_t *vd_resume; + /* Priority to know which one can override */ int vd_priority; #define VD_PRIORITY_DUMB 10 diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index bf0ae1a8f355..d70073090a93 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -167,6 +167,8 @@ static void vt_update_static(void *); #ifndef SC_NO_CUTPASTE static void vt_mouse_paste(void); #endif +static void vt_suspend_handler(void *priv); +static void vt_resume_handler(void *priv); SET_DECLARE(vt_drv_set, struct vt_driver); @@ -2552,6 +2554,12 @@ vt_upgrade(struct vt_device *vd) vd->vd_flags |= VDF_ASYNC; callout_reset(&vd->vd_timer, hz / VT_TIMERFREQ, vt_timer, vd); vd->vd_timer_armed = 1; + + /* Register suspend/resume handlers. */ + EVENTHANDLER_REGISTER(power_suspend, vt_suspend_handler, vd, + EVENTHANDLER_PRI_ANY); + EVENTHANDLER_REGISTER(power_resume, vt_resume_handler, vd, + EVENTHANDLER_PRI_ANY); } VT_UNLOCK(vd); @@ -2655,26 +2663,54 @@ vt_allocate(struct vt_driver *drv, void *softc) termcn_cnregister(vd->vd_windows[VT_CONSWINDOW]->vw_terminal); } -void -vt_suspend() +static void +vt_suspend_handler(void *priv) { + struct vt_device *vd; + + vd = priv; + if (vd->vd_driver != NULL && vd->vd_driver->vd_suspend != NULL) + vd->vd_driver->vd_suspend(vd); +} + +static void +vt_resume_handler(void *priv) +{ + struct vt_device *vd; + + vd = priv; + if (vd->vd_driver != NULL && vd->vd_driver->vd_resume != NULL) + vd->vd_driver->vd_resume(vd); +} + +void +vt_suspend(struct vt_device *vd) +{ + int error; if (vt_suspendswitch == 0) return; /* Save current window. */ - main_vd->vd_savedwindow = main_vd->vd_curwindow; + vd->vd_savedwindow = vd->vd_curwindow; /* Ask holding process to free window and switch to console window */ - vt_proc_window_switch(main_vd->vd_windows[VT_CONSWINDOW]); + vt_proc_window_switch(vd->vd_windows[VT_CONSWINDOW]); + + /* Wait for the window switch to complete. */ + error = 0; + VT_LOCK(vd); + while (vd->vd_curwindow != vd->vd_windows[VT_CONSWINDOW] && error == 0) + error = cv_wait_sig(&vd->vd_winswitch, &vd->vd_lock); + VT_UNLOCK(vd); } void -vt_resume() +vt_resume(struct vt_device *vd) { if (vt_suspendswitch == 0) return; /* Switch back to saved window */ - if (main_vd->vd_savedwindow != NULL) - vt_proc_window_switch(main_vd->vd_savedwindow); - main_vd->vd_savedwindow = NULL; + if (vd->vd_savedwindow != NULL) + vt_proc_window_switch(vd->vd_savedwindow); + vd->vd_savedwindow = NULL; }