summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormiod <miod@openbsd.org>2011-04-03 15:46:30 +0000
committermiod <miod@openbsd.org>2011-04-03 15:46:30 +0000
commit6dd23c8821eecebeb9ca486a17add8f4260e9528 (patch)
treeef37553633d81ce4ee16e39c64f0440c29c8f6f4
parentuse nitems(); no binary change for drivers that are compiled on amd64. (diff)
downloadwireguard-openbsd-6dd23c8821eecebeb9ca486a17add8f4260e9528.tar.xz
wireguard-openbsd-6dd23c8821eecebeb9ca486a17add8f4260e9528.zip
Sprinkle spltty around code which plays with either the video memory or
the backing store. The state of a VT is only coherent if both the active flag and the backing store are in order, which is not the case during VT switches. This fixes display glitches occuring during VT switches if one of the VT involved is doing a lot of tty updates. Noticed by deraadt@ on a machine too fast for mere mortals.
-rw-r--r--sys/dev/ic/pcdisplay_subr.c29
-rw-r--r--sys/dev/ic/vga.c27
2 files changed, 43 insertions, 13 deletions
diff --git a/sys/dev/ic/pcdisplay_subr.c b/sys/dev/ic/pcdisplay_subr.c
index d743fcaac7d..dba0ea9229e 100644
--- a/sys/dev/ic/pcdisplay_subr.c
+++ b/sys/dev/ic/pcdisplay_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pcdisplay_subr.c,v 1.9 2010/08/28 12:48:14 miod Exp $ */
+/* $OpenBSD: pcdisplay_subr.c,v 1.10 2011/04/03 15:46:30 miod Exp $ */
/* $NetBSD: pcdisplay_subr.c,v 1.16 2000/06/08 07:01:19 cgd Exp $ */
/*
@@ -88,6 +88,7 @@ pcdisplay_cursor(void *id, int on, int row, int col)
bus_space_tag_t memt = scr->hdl->ph_memt;
bus_space_handle_t memh = scr->hdl->ph_memh;
int off;
+ int s = spltty();
/* Remove old cursor image */
if (scr->cursoron) {
@@ -103,7 +104,7 @@ pcdisplay_cursor(void *id, int on, int row, int col)
scr->vc_ccol = col;
if ((scr->cursoron = on) == 0)
- return 0;
+ goto done;
off = (scr->vc_crow * scr->type->ncols + scr->vc_ccol);
if (scr->active) {
@@ -115,10 +116,13 @@ pcdisplay_cursor(void *id, int on, int row, int col)
scr->mem[off] = scr->cursortmp ^ 0x7700;
}
+ splx(s);
+done:
return 0;
#else /* PCDISPLAY_SOFTCURSOR */
struct pcdisplayscreen *scr = id;
int pos;
+ int s = spltty();
scr->vc_crow = row;
scr->vc_ccol = col;
@@ -135,6 +139,7 @@ pcdisplay_cursor(void *id, int on, int row, int col)
pcdisplay_6845_write(scr->hdl, cursorl, pos);
}
+ splx(s);
return 0;
#endif /* PCDISPLAY_SOFTCURSOR */
}
@@ -157,14 +162,17 @@ pcdisplay_putchar(void *id, int row, int col, u_int c, long attr)
bus_space_tag_t memt = scr->hdl->ph_memt;
bus_space_handle_t memh = scr->hdl->ph_memh;
int off;
+ int s;
off = row * scr->type->ncols + col;
+ s = spltty();
if (scr->active)
bus_space_write_2(memt, memh, scr->dispoffset + off * 2,
c | (attr << 8));
else
scr->mem[off] = c | (attr << 8);
+ splx(s);
return 0;
}
@@ -176,16 +184,19 @@ pcdisplay_getchar(void *id, int row, int col, struct wsdisplay_charcell *cell)
bus_space_tag_t memt = scr->hdl->ph_memt;
bus_space_handle_t memh = scr->hdl->ph_memh;
int off;
+ int s;
u_int16_t data;
off = row * scr->type->ncols + col;
/* XXX bounds check? */
+ s = spltty();
if (scr->active)
data = (bus_space_read_2(memt, memh,
scr->dispoffset + off * 2));
else
data = (scr->mem[off]);
+ splx(s);
cell->uc = data & 0xff;
cell->attr = data >> 8;
@@ -200,11 +211,13 @@ pcdisplay_copycols(void *id, int row, int srccol, int dstcol, int ncols)
bus_space_tag_t memt = scr->hdl->ph_memt;
bus_space_handle_t memh = scr->hdl->ph_memh;
bus_size_t srcoff, dstoff;
+ int s;
srcoff = dstoff = row * scr->type->ncols;
srcoff += srccol;
dstoff += dstcol;
+ s = spltty();
if (scr->active)
bus_space_copy_2(memt, memh,
scr->dispoffset + srcoff * 2,
@@ -212,6 +225,7 @@ pcdisplay_copycols(void *id, int row, int srccol, int dstcol, int ncols)
ncols);
else
bcopy(&scr->mem[srcoff], &scr->mem[dstoff], ncols * 2);
+ splx(s);
return 0;
}
@@ -225,17 +239,19 @@ pcdisplay_erasecols(void *id, int row, int startcol, int ncols, long fillattr)
bus_size_t off;
u_int16_t val;
int i;
+ int s;
off = row * scr->type->ncols + startcol;
-
val = (fillattr << 8) | ' ';
+ s = spltty();
if (scr->active)
bus_space_set_region_2(memt, memh, scr->dispoffset + off * 2,
val, ncols);
else
for (i = 0; i < ncols; i++)
scr->mem[off + i] = val;
+ splx(s);
return 0;
}
@@ -248,10 +264,12 @@ pcdisplay_copyrows(void *id, int srcrow, int dstrow, int nrows)
bus_space_handle_t memh = scr->hdl->ph_memh;
int ncols = scr->type->ncols;
bus_size_t srcoff, dstoff;
+ int s;
srcoff = srcrow * ncols + 0;
dstoff = dstrow * ncols + 0;
+ s = spltty();
if (scr->active)
bus_space_copy_2(memt, memh,
scr->dispoffset + srcoff * 2,
@@ -260,6 +278,7 @@ pcdisplay_copyrows(void *id, int srcrow, int dstrow, int nrows)
else
bcopy(&scr->mem[srcoff], &scr->mem[dstoff],
nrows * ncols * 2);
+ splx(s);
return 0;
}
@@ -272,18 +291,20 @@ pcdisplay_eraserows(void *id, int startrow, int nrows, long fillattr)
bus_space_handle_t memh = scr->hdl->ph_memh;
bus_size_t off, count, n;
u_int16_t val;
+ int s;
off = startrow * scr->type->ncols;
count = nrows * scr->type->ncols;
-
val = (fillattr << 8) | ' ';
+ s = spltty();
if (scr->active)
bus_space_set_region_2(memt, memh, scr->dispoffset + off * 2,
val, count);
else
for (n = 0; n < count; n++)
scr->mem[off + n] = val;
+ splx(s);
return 0;
}
diff --git a/sys/dev/ic/vga.c b/sys/dev/ic/vga.c
index b71a16c5fcc..ce40fc657c4 100644
--- a/sys/dev/ic/vga.c
+++ b/sys/dev/ic/vga.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vga.c,v 1.54 2010/08/28 12:48:14 miod Exp $ */
+/* $OpenBSD: vga.c,v 1.55 2011/04/03 15:46:30 miod Exp $ */
/* $NetBSD: vga.c,v 1.28.2.1 2000/06/30 16:27:47 simonb Exp $ */
/*-
@@ -770,6 +770,7 @@ vga_doswitch(struct vga_config *vc)
struct vgascreen *scr, *oldscr;
struct vga_handle *vh = &vc->hdl;
const struct wsscreen_descr *type;
+ int s;
scr = vc->wantedscreen;
if (!scr) {
@@ -777,8 +778,12 @@ vga_doswitch(struct vga_config *vc)
(*vc->switchcb)(vc->switchcbarg, EIO, 0);
return;
}
+
type = scr->pcs.type;
oldscr = vc->active; /* can be NULL! */
+ if (scr == oldscr)
+ return;
+ s = spltty();
#ifdef DIAGNOSTIC
if (oldscr) {
if (!oldscr->pcs.active)
@@ -786,11 +791,6 @@ vga_doswitch(struct vga_config *vc)
if (oldscr->pcs.type != vc->currenttype)
panic("vga_show_screen: bad type");
}
-#endif
- if (scr == oldscr) {
- return;
- }
-#ifdef DIAGNOSTIC
if (scr->pcs.active)
panic("vga_show_screen: active");
#endif
@@ -824,6 +824,7 @@ vga_doswitch(struct vga_config *vc)
scr->pcs.dispoffset, scr->pcs.mem,
type->ncols * type->nrows);
scr->pcs.active = 1;
+ splx(s);
vc->active = scr;
@@ -1007,10 +1008,12 @@ vga_copyrows(void *id, int srcrow, int dstrow, int nrows)
bus_space_handle_t memh = scr->pcs.hdl->ph_memh;
int ncols = scr->pcs.type->ncols;
bus_size_t srcoff, dstoff;
+ int s;
srcoff = srcrow * ncols + 0;
dstoff = dstrow * ncols + 0;
+ s = spltty();
if (scr->pcs.active) {
if (dstrow == 0 && (srcrow + nrows == scr->pcs.type->nrows)) {
#ifdef PCDISPLAY_SOFTCURSOR
@@ -1053,6 +1056,7 @@ vga_copyrows(void *id, int srcrow, int dstrow, int nrows)
} else
bcopy(&scr->pcs.mem[srcoff], &scr->pcs.mem[dstoff],
nrows * ncols * 2);
+ splx(s);
return 0;
}
@@ -1251,11 +1255,16 @@ int
vga_putchar(void *c, int row, int col, u_int uc, long attr)
{
struct vgascreen *scr = c;
-
- if (scr->pcs.visibleoffset != scr->pcs.dispoffset)
+ int rc;
+ int s;
+
+ s = spltty();
+ if (scr->pcs.active && scr->pcs.visibleoffset != scr->pcs.dispoffset)
vga_scrollback(scr->cfg, scr, 0);
+ rc = pcdisplay_putchar(c, row, col, uc, attr);
+ splx(s);
- return pcdisplay_putchar(c, row, col, uc, attr);
+ return rc;
}
void