diff options
author | dumbbell <dumbbell@FreeBSD.org> | 2014-09-18 14:38:18 +0000 |
---|---|---|
committer | dumbbell <dumbbell@FreeBSD.org> | 2014-09-18 14:38:18 +0000 |
commit | 4ed3581a3631193ad48bcea6cc7cdb082d6d5981 (patch) | |
tree | 39c1eb5f69b5197e87d789cdc00f0b3f1c497016 /sys | |
parent | 2bc2377c6618fb65f929f92715f7b128fe6e9a27 (diff) | |
download | FreeBSD-src-4ed3581a3631193ad48bcea6cc7cdb082d6d5981.zip FreeBSD-src-4ed3581a3631193ad48bcea6cc7cdb082d6d5981.tar.gz |
vt(4): Merge several bug fixes and improvements
SVN revisions in this MFC:
269779 270705 270706 271180 271250 271253 271682 271684
Detailed commit list:
r269779:
fbd: Fix a bug where vt_fb_attach() success would be considered a failure
vt_fb_attach() currently always returns 0, but it could return a code
defined in errno.h. However, it doesn't return a CN_* code. So checking
its return value against CN_DEAD (which is 0) is incorrect, and in this
case, a success becomes a failure.
The consequence was unimportant, because the caller (drm_fb_helper.c)
would only log an error message in this case. The console would still
work.
Approved by: nwhitehorn
r270705:
vt(4): Add cngrab() and cnungrab() callbacks
They are used when a panic occurs or when entering a DDB session for
instance.
cngrab() forces a vt-switch to the console window, no matter if the
original window is another terminal or an X session. However, cnungrab()
doesn't vt-switch back to the original window currently.
r270706:
drm: Don't "taskqueue" vt-switch if under DDB/panic situation
If DDB is active, we can't use a taskqueue thread to switch away from
the X window, because this thread can't run.
Reviewed by: ray@
Approved by: ray@
r271180:
vt_vga: vd_setpixel_t and vd_drawrect_t are noop in text mode
r271250:
vt(4): Change the terminal and buffer sizes, even without a font
This fixes a bug where scroll lock would not work for tty #0 when using
vt_vga's textmode. The reason was that this window is created with a
static 256x100 buffer, larger than the real size of 80x25.
Now, in vt_change_font() and vt_compute_drawable_area(), we still
perform operations even of the window has no font loaded (this is the
case in textmode here vw->vw_font == NULL). One of these operation
resizes the buffer accordingly.
In vt_compute_drawable_area(), we take the terminal size as is (ie.
80x25) for the drawable area.
The font argument to vt_set_border() is removed (it was never used) and
the code now uses the computed drawable area instead of re-doing its own
calculation.
Reported by: Harald Schmalzbauer <h.schmalzbauer_omnilan.de>
Tested by: Harald Schmalzbauer <h.schmalzbauer_omnilan.de>
r271253:
pause_sbt(): Take the cold path (ie. use DELAY()) if KDB is active
This fixes a panic in the i915 driver when one uses debug.kdb.enter=1
under vt(4).
PR: 193269
Reported by: emaste@
Submitted by: avg@
r271682:
vt(4): Fix a LOR which occurs during a call to vt_upgrade()
Reported by: kib@
Review: https://reviews.freebsd.org/D785
Reviewed by: ray@
Approved by: ray@
r271684:
vt(4): Use vt_fb_drawrect() and vt_fb_setpixel() in all vt_fb-derivative
Review: https://reviews.freebsd.org/D789
Reviewed by: nwhitehorn
Approved by: nwhitehorn
Approved by: re (gjb)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/drm2/drm_fb_helper.c | 9 | ||||
-rw-r--r-- | sys/dev/fb/fbd.c | 5 | ||||
-rw-r--r-- | sys/dev/vt/hw/efifb/efifb.c | 2 | ||||
-rw-r--r-- | sys/dev/vt/hw/fb/vt_early_fb.c | 2 | ||||
-rw-r--r-- | sys/dev/vt/hw/fb/vt_fb.c | 7 | ||||
-rw-r--r-- | sys/dev/vt/hw/fb/vt_fb.h | 2 | ||||
-rw-r--r-- | sys/dev/vt/hw/vga/vt_vga.c | 6 | ||||
-rw-r--r-- | sys/dev/vt/vt.h | 2 | ||||
-rw-r--r-- | sys/dev/vt/vt_core.c | 126 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 2 | ||||
-rw-r--r-- | sys/kern/subr_terminal.c | 4 | ||||
-rw-r--r-- | sys/powerpc/ps3/ps3_syscons.c | 2 | ||||
-rw-r--r-- | sys/sys/terminal.h | 7 |
13 files changed, 142 insertions, 34 deletions
diff --git a/sys/dev/drm2/drm_fb_helper.c b/sys/dev/drm2/drm_fb_helper.c index d797502..5c35e5b 100644 --- a/sys/dev/drm2/drm_fb_helper.c +++ b/sys/dev/drm2/drm_fb_helper.c @@ -37,6 +37,9 @@ __FBSDID("$FreeBSD$"); #include <dev/drm2/drm_crtc_helper.h> #if defined(__FreeBSD__) + +#include <sys/kdb.h> + struct vt_kms_softc { struct drm_fb_helper *fb_helper; struct task fb_mode_task; @@ -65,7 +68,11 @@ vt_kms_postswitch(void *arg) struct vt_kms_softc *sc; sc = (struct vt_kms_softc *)arg; - taskqueue_enqueue_fast(taskqueue_thread, &sc->fb_mode_task); + + if (!kdb_active && panicstr == NULL) + taskqueue_enqueue_fast(taskqueue_thread, &sc->fb_mode_task); + else + drm_fb_helper_restore_fbdev_mode(sc->fb_helper); return (0); } diff --git a/sys/dev/fb/fbd.c b/sys/dev/fb/fbd.c index 8c6b036..ff2488d 100644 --- a/sys/dev/fb/fbd.c +++ b/sys/dev/fb/fbd.c @@ -246,8 +246,9 @@ fbd_register(struct fb_info* info) return (err); if (first) { - if (vt_fb_attach(info) == CN_DEAD) - return (ENXIO); + err = vt_fb_attach(info); + if (err) + return (err); } return (0); diff --git a/sys/dev/vt/hw/efifb/efifb.c b/sys/dev/vt/hw/efifb/efifb.c index ff95391..05b2d79 100644 --- a/sys/dev/vt/hw/efifb/efifb.c +++ b/sys/dev/vt/hw/efifb/efifb.c @@ -62,6 +62,8 @@ static struct vt_driver vt_efifb_driver = { .vd_blank = vt_fb_blank, .vd_bitblt_text = vt_fb_bitblt_text, .vd_bitblt_bmp = vt_fb_bitblt_bitmap, + .vd_drawrect = vt_fb_drawrect, + .vd_setpixel = vt_fb_setpixel, .vd_fb_ioctl = vt_fb_ioctl, .vd_fb_mmap = vt_fb_mmap, /* Better than VGA, but still generic driver. */ diff --git a/sys/dev/vt/hw/fb/vt_early_fb.c b/sys/dev/vt/hw/fb/vt_early_fb.c index ff50a9c..187f7f7 100644 --- a/sys/dev/vt/hw/fb/vt_early_fb.c +++ b/sys/dev/vt/hw/fb/vt_early_fb.c @@ -61,6 +61,8 @@ static struct vt_driver vt_fb_early_driver = { .vd_blank = vt_fb_blank, .vd_bitblt_text = vt_fb_bitblt_text, .vd_bitblt_bmp = vt_fb_bitblt_bitmap, + .vd_drawrect = vt_fb_drawrect, + .vd_setpixel = vt_fb_setpixel, .vd_priority = VD_PRIORITY_GENERIC, }; diff --git a/sys/dev/vt/hw/fb/vt_fb.c b/sys/dev/vt/hw/fb/vt_fb.c index ddec76d..422bb03 100644 --- a/sys/dev/vt/hw/fb/vt_fb.c +++ b/sys/dev/vt/hw/fb/vt_fb.c @@ -41,9 +41,6 @@ __FBSDID("$FreeBSD$"); #include <dev/vt/hw/fb/vt_fb.h> #include <dev/vt/colors/vt_termcolors.h> -static vd_drawrect_t vt_fb_drawrect; -static vd_setpixel_t vt_fb_setpixel; - static struct vt_driver vt_fb_driver = { .vd_name = "fb", .vd_init = vt_fb_init, @@ -146,7 +143,7 @@ vt_fb_mmap(struct vt_device *vd, vm_ooffset_t offset, vm_paddr_t *paddr, return (EINVAL); } -static void +void vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color) { struct fb_info *info; @@ -181,7 +178,7 @@ vt_fb_setpixel(struct vt_device *vd, int x, int y, term_color_t color) } -static void +void vt_fb_drawrect(struct vt_device *vd, int x1, int y1, int x2, int y2, int fill, term_color_t color) { diff --git a/sys/dev/vt/hw/fb/vt_fb.h b/sys/dev/vt/hw/fb/vt_fb.h index 9a0da6e..43ce2b7 100644 --- a/sys/dev/vt/hw/fb/vt_fb.h +++ b/sys/dev/vt/hw/fb/vt_fb.h @@ -40,6 +40,8 @@ vd_init_t vt_fb_init; vd_blank_t vt_fb_blank; vd_bitblt_text_t vt_fb_bitblt_text; vd_bitblt_bmp_t vt_fb_bitblt_bitmap; +vd_drawrect_t vt_fb_drawrect; +vd_setpixel_t vt_fb_setpixel; vd_postswitch_t vt_fb_postswitch; vd_fb_ioctl_t vt_fb_ioctl; vd_fb_mmap_t vt_fb_mmap; diff --git a/sys/dev/vt/hw/vga/vt_vga.c b/sys/dev/vt/hw/vga/vt_vga.c index bf5263a..bce1c61 100644 --- a/sys/dev/vt/hw/vga/vt_vga.c +++ b/sys/dev/vt/hw/vga/vt_vga.c @@ -352,6 +352,9 @@ static void vga_setpixel(struct vt_device *vd, int x, int y, term_color_t color) { + if (vd->vd_flags & VDF_TEXTMODE) + return; + vga_bitblt_put(vd, (y * VT_VGA_WIDTH / 8) + (x / 8), color, 0x80 >> (x % 8)); } @@ -362,6 +365,9 @@ vga_drawrect(struct vt_device *vd, int x1, int y1, int x2, int y2, int fill, { int x, y; + if (vd->vd_flags & VDF_TEXTMODE) + return; + for (y = y1; y <= y2; y++) { if (fill || (y == y1) || (y == y2)) { for (x = x1; x <= x2; x++) diff --git a/sys/dev/vt/vt.h b/sys/dev/vt/vt.h index a667e1c..b660545 100644 --- a/sys/dev/vt/vt.h +++ b/sys/dev/vt/vt.h @@ -256,6 +256,8 @@ struct vt_window { term_rect_t vw_draw_area; /* (?) Drawable area. */ unsigned int vw_number; /* (c) Window number. */ int vw_kbdmode; /* (?) Keyboard mode. */ + int vw_prev_kbdmode;/* (?) Previous mode. */ + int vw_grabbed; /* (?) Grab count. */ char *vw_kbdsq; /* Escape sequence queue*/ unsigned int vw_flags; /* (d) Per-window flags. */ int vw_mouse_level;/* Mouse op mode. */ diff --git a/sys/dev/vt/vt_core.c b/sys/dev/vt/vt_core.c index 0911739..3372804 100644 --- a/sys/dev/vt/vt_core.c +++ b/sys/dev/vt/vt_core.c @@ -70,6 +70,9 @@ static tc_done_t vtterm_done; static tc_cnprobe_t vtterm_cnprobe; static tc_cngetc_t vtterm_cngetc; +static tc_cngrab_t vtterm_cngrab; +static tc_cnungrab_t vtterm_cnungrab; + static tc_opened_t vtterm_opened; static tc_ioctl_t vtterm_ioctl; static tc_mmap_t vtterm_mmap; @@ -86,6 +89,9 @@ const struct terminal_class vt_termclass = { .tc_cnprobe = vtterm_cnprobe, .tc_cngetc = vtterm_cngetc, + .tc_cngrab = vtterm_cngrab, + .tc_cnungrab = vtterm_cnungrab, + .tc_opened = vtterm_opened, .tc_ioctl = vtterm_ioctl, .tc_mmap = vtterm_mmap, @@ -188,6 +194,7 @@ static struct vt_window vt_conswindow = { .vw_device = &vt_consdev, .vw_terminal = &vt_consterm, .vw_kbdmode = K_XLATE, + .vw_grabbed = 0, }; static struct terminal vt_consterm = { .tm_class = &vt_termclass, @@ -420,10 +427,16 @@ vt_compute_drawable_area(struct vt_window *vw) struct vt_device *vd; struct vt_font *vf; - if (vw->vw_font == NULL) + vd = vw->vw_device; + + if (vw->vw_font == NULL) { + vw->vw_draw_area.tr_begin.tp_col = 0; + vw->vw_draw_area.tr_begin.tp_row = 0; + vw->vw_draw_area.tr_end.tp_col = vd->vd_width; + vw->vw_draw_area.tr_end.tp_row = vd->vd_height; return; + } - vd = vw->vw_device; vf = vw->vw_font; /* @@ -1211,6 +1224,64 @@ vtterm_cngetc(struct terminal *tm) } static void +vtterm_cngrab(struct terminal *tm) +{ + struct vt_device *vd; + struct vt_window *vw; + keyboard_t *kbd; + + vw = tm->tm_softc; + vd = vw->vw_device; + + if (!cold) + vt_window_switch(vw); + + kbd = kbd_get_keyboard(vd->vd_keyboard); + if (kbd == NULL) + return; + + if (vw->vw_grabbed++ > 0) + return; + + /* + * Make sure the keyboard is accessible even when the kbd device + * driver is disabled. + */ + kbdd_enable(kbd); + + /* We shall always use the keyboard in the XLATE mode here. */ + vw->vw_prev_kbdmode = vw->vw_kbdmode; + vw->vw_kbdmode = K_XLATE; + (void)kbdd_ioctl(kbd, KDSKBMODE, (caddr_t)&vw->vw_kbdmode); + + kbdd_poll(kbd, TRUE); +} + +static void +vtterm_cnungrab(struct terminal *tm) +{ + struct vt_device *vd; + struct vt_window *vw; + keyboard_t *kbd; + + vw = tm->tm_softc; + vd = vw->vw_device; + + kbd = kbd_get_keyboard(vd->vd_keyboard); + if (kbd == NULL) + return; + + if (--vw->vw_grabbed > 0) + return; + + kbdd_poll(kbd, FALSE); + + vw->vw_kbdmode = vw->vw_prev_kbdmode; + (void)kbdd_ioctl(kbd, KDSKBMODE, (caddr_t)&vw->vw_kbdmode); + kbdd_disable(kbd); +} + +static void vtterm_opened(struct terminal *tm, int opened) { struct vt_window *vw = tm->tm_softc; @@ -1228,30 +1299,40 @@ vtterm_opened(struct terminal *tm, int opened) } static int -vt_set_border(struct vt_window *vw, struct vt_font *vf, term_color_t c) +vt_set_border(struct vt_window *vw, term_color_t c) { struct vt_device *vd = vw->vw_device; - int x, y, off_x, off_y; if (vd->vd_driver->vd_drawrect == NULL) return (ENOTSUP); - x = vd->vd_width - 1; - y = vd->vd_height - 1; - off_x = vw->vw_draw_area.tr_begin.tp_col; - off_y = vw->vw_draw_area.tr_begin.tp_row; - /* Top bar. */ - if (off_y > 0) - vd->vd_driver->vd_drawrect(vd, 0, 0, x, off_y - 1, 1, c); + if (vw->vw_draw_area.tr_begin.tp_row > 0) + vd->vd_driver->vd_drawrect(vd, + 0, 0, + vd->vd_width - 1, vw->vw_draw_area.tr_begin.tp_row - 1, + 1, c); + /* Left bar. */ - if (off_x > 0) - vd->vd_driver->vd_drawrect(vd, 0, off_y, off_x - 1, y - off_y, + if (vw->vw_draw_area.tr_begin.tp_col > 0) + vd->vd_driver->vd_drawrect(vd, + 0, 0, + vw->vw_draw_area.tr_begin.tp_col - 1, vd->vd_height - 1, + 1, c); + + /* Right bar. */ + if (vw->vw_draw_area.tr_end.tp_col < vd->vd_width) + vd->vd_driver->vd_drawrect(vd, + vw->vw_draw_area.tr_end.tp_col - 1, 0, + vd->vd_width - 1, vd->vd_height - 1, + 1, c); + + /* Bottom bar. */ + if (vw->vw_draw_area.tr_end.tp_row < vd->vd_height) + vd->vd_driver->vd_drawrect(vd, + 0, vw->vw_draw_area.tr_end.tp_row - 1, + vd->vd_width - 1, vd->vd_height - 1, 1, c); - /* Right bar. May be 1 pixel wider than necessary due to rounding. */ - vd->vd_driver->vd_drawrect(vd, x - off_x, off_y, x, y - off_y, 1, c); - /* Bottom bar. May be 1 mixel taller than necessary due to rounding. */ - vd->vd_driver->vd_drawrect(vd, 0, y - off_y, x, y, 1, c); return (0); } @@ -1283,11 +1364,6 @@ vt_change_font(struct vt_window *vw, struct vt_font *vf) VT_UNLOCK(vd); return (EBUSY); } - if (vd->vd_flags & VDF_TEXTMODE) { - /* Our device doesn't need fonts. */ - VT_UNLOCK(vd); - return (ENOTTY); - } vw->vw_flags |= VWF_BUSY; VT_UNLOCK(vd); @@ -1302,7 +1378,7 @@ vt_change_font(struct vt_window *vw, struct vt_font *vf) /* Actually apply the font to the current window. */ VT_LOCK(vd); - if (vw->vw_font != vf) { + if (vw->vw_font != vf && vw->vw_font != NULL && vf != NULL) { /* * In case vt_change_font called to update size we don't need * to update font link. @@ -1325,7 +1401,7 @@ vt_change_font(struct vt_window *vw, struct vt_font *vf) /* Force a full redraw the next timer tick. */ if (vd->vd_curwindow == vw) { - vt_set_border(vw, vf, TC_BLACK); + vt_set_border(vw, TC_BLACK); vd->vd_flags |= VDF_INVALID; vt_resume_flush_timer(vw->vw_device, 0); } @@ -2247,7 +2323,6 @@ vt_allocate(struct vt_driver *drv, void *softc) main_vd->vd_driver->vd_name, drv->vd_name); } vd = main_vd; - VT_LOCK(vd); if (vd->vd_flags & VDF_ASYNC) { /* Stop vt_flush periodic task. */ @@ -2263,6 +2338,7 @@ vt_allocate(struct vt_driver *drv, void *softc) * Reset VDF_TEXTMODE flag, driver who require that flag (vt_vga) will * set it. */ + VT_LOCK(vd); vd->vd_flags &= ~VDF_TEXTMODE; vd->vd_driver = drv; diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index f30bf15..960865f 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -363,7 +363,7 @@ pause_sbt(const char *wmesg, sbintime_t sbt, sbintime_t pr, int flags) if (sbt == 0) sbt = tick_sbt; - if (cold) { + if (cold || kdb_active) { /* * We delay one second at a time to avoid overflowing the * system specific DELAY() function(s): diff --git a/sys/kern/subr_terminal.c b/sys/kern/subr_terminal.c index d8d1836..69345df 100644 --- a/sys/kern/subr_terminal.c +++ b/sys/kern/subr_terminal.c @@ -476,13 +476,17 @@ termcn_cnregister(struct terminal *tm) static void termcn_cngrab(struct consdev *cp) { + struct terminal *tm = cp->cn_arg; + tm->tm_class->tc_cngrab(tm); } static void termcn_cnungrab(struct consdev *cp) { + struct terminal *tm = cp->cn_arg; + tm->tm_class->tc_cnungrab(tm); } static void diff --git a/sys/powerpc/ps3/ps3_syscons.c b/sys/powerpc/ps3/ps3_syscons.c index 1c4f4d8..1b669aa 100644 --- a/sys/powerpc/ps3/ps3_syscons.c +++ b/sys/powerpc/ps3/ps3_syscons.c @@ -78,6 +78,8 @@ static struct vt_driver vt_ps3fb_driver = { .vd_blank = vt_fb_blank, .vd_bitblt_text = vt_fb_bitblt_text, .vd_bitblt_bmp = vt_fb_bitblt_bitmap, + .vd_drawrect = vt_fb_drawrect, + .vd_setpixel = vt_fb_setpixel, .vd_fb_ioctl = vt_fb_ioctl, .vd_fb_mmap = vt_fb_mmap, /* Better than VGA, but still generic driver. */ diff --git a/sys/sys/terminal.h b/sys/sys/terminal.h index 15641dc..133332f 100644 --- a/sys/sys/terminal.h +++ b/sys/sys/terminal.h @@ -155,6 +155,9 @@ typedef void tc_done_t(struct terminal *tm); typedef void tc_cnprobe_t(struct terminal *tm, struct consdev *cd); typedef int tc_cngetc_t(struct terminal *tm); +typedef void tc_cngrab_t(struct terminal *tm); +typedef void tc_cnungrab_t(struct terminal *tm); + typedef void tc_opened_t(struct terminal *tm, int opened); typedef int tc_ioctl_t(struct terminal *tm, u_long cmd, caddr_t data, struct thread *td); @@ -175,6 +178,10 @@ struct terminal_class { tc_cnprobe_t *tc_cnprobe; tc_cngetc_t *tc_cngetc; + /* DDB & panic handling. */ + tc_cngrab_t *tc_cngrab; + tc_cnungrab_t *tc_cnungrab; + /* Misc. */ tc_opened_t *tc_opened; tc_ioctl_t *tc_ioctl; |