Index: sys/dev/fb/fbd.c =================================================================== --- sys/dev/fb/fbd.c +++ sys/dev/fb/fbd.c @@ -332,22 +332,6 @@ 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 @@ DEVMETHOD(device_detach, fbd_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, fbd_suspend), - DEVMETHOD(device_resume, fbd_resume), { 0, 0 } }; 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 @@ -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; 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 @@ -53,6 +53,8 @@ .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); @@ -441,15 +443,15 @@ } 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); } Index: sys/dev/vt/vt.h =================================================================== --- sys/dev/vt/vt.h +++ sys/dev/vt/vt.h @@ -90,8 +90,6 @@ struct vt_driver; void vt_allocate(struct vt_driver *, void *); -void vt_resume(void); -void vt_suspend(void); typedef unsigned int vt_axis_t; @@ -161,6 +159,9 @@ #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. * @@ -308,6 +309,8 @@ 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]; @@ -331,6 +334,10 @@ /* 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 Index: sys/dev/vt/vt_core.c =================================================================== --- sys/dev/vt/vt_core.c +++ sys/dev/vt/vt_core.c @@ -166,6 +166,8 @@ #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); @@ -2542,6 +2544,12 @@ 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); @@ -2643,26 +2651,54 @@ termcn_cnregister(vd->vd_windows[VT_CONSWINDOW]->vw_terminal); } +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() +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; }