Thu Jan 28 17:40:00 2021 UTC ()
fix logic botch from previous - if we're asked to draw the cursor somewhere
else and it's still visible we need to clear it


(macallan)
diff -r1.50 -r1.51 src/sys/dev/wscons/wsdisplay_vcons.c

cvs diff -r1.50 -r1.51 src/sys/dev/wscons/wsdisplay_vcons.c (switch to unified diff)

--- src/sys/dev/wscons/wsdisplay_vcons.c 2021/01/26 16:24:17 1.50
+++ src/sys/dev/wscons/wsdisplay_vcons.c 2021/01/28 17:40:00 1.51
@@ -1,1641 +1,1641 @@ @@ -1,1641 +1,1641 @@
1/* $NetBSD: wsdisplay_vcons.c,v 1.50 2021/01/26 16:24:17 macallan Exp $ */ 1/* $NetBSD: wsdisplay_vcons.c,v 1.51 2021/01/28 17:40:00 macallan Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2005, 2006 Michael Lorenz 4 * Copyright (c) 2005, 2006 Michael Lorenz
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE. 26 * POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.50 2021/01/26 16:24:17 macallan Exp $"); 30__KERNEL_RCSID(0, "$NetBSD: wsdisplay_vcons.c,v 1.51 2021/01/28 17:40:00 macallan Exp $");
31 31
32#include <sys/param.h> 32#include <sys/param.h>
33#include <sys/systm.h> 33#include <sys/systm.h>
34#include <sys/kernel.h> 34#include <sys/kernel.h>
35#include <sys/buf.h> 35#include <sys/buf.h>
36#include <sys/device.h> 36#include <sys/device.h>
37#include <sys/ioctl.h> 37#include <sys/ioctl.h>
38#include <sys/malloc.h> 38#include <sys/malloc.h>
39#include <sys/mman.h> 39#include <sys/mman.h>
40#include <sys/tty.h> 40#include <sys/tty.h>
41#include <sys/conf.h> 41#include <sys/conf.h>
42#include <sys/proc.h> 42#include <sys/proc.h>
43#include <sys/kthread.h> 43#include <sys/kthread.h>
44#include <sys/tprintf.h> 44#include <sys/tprintf.h>
45#include <sys/atomic.h> 45#include <sys/atomic.h>
46 46
47#include <dev/wscons/wsdisplayvar.h> 47#include <dev/wscons/wsdisplayvar.h>
48#include <dev/wscons/wsconsio.h> 48#include <dev/wscons/wsconsio.h>
49#include <dev/wsfont/wsfont.h> 49#include <dev/wsfont/wsfont.h>
50#include <dev/rasops/rasops.h> 50#include <dev/rasops/rasops.h>
51 51
52#include <dev/wscons/wsdisplay_vconsvar.h> 52#include <dev/wscons/wsdisplay_vconsvar.h>
53 53
54#ifdef _KERNEL_OPT 54#ifdef _KERNEL_OPT
55#include "opt_wsemul.h" 55#include "opt_wsemul.h"
56#include "opt_wsdisplay_compat.h" 56#include "opt_wsdisplay_compat.h"
57#include "opt_vcons.h" 57#include "opt_vcons.h"
58#endif 58#endif
59 59
60#ifdef VCONS_DEBUG 60#ifdef VCONS_DEBUG
61#define DPRINTF printf 61#define DPRINTF printf
62#else 62#else
63#define DPRINTF if (0) printf 63#define DPRINTF if (0) printf
64#endif 64#endif
65 65
66static void vcons_dummy_init_screen(void *, struct vcons_screen *, int,  66static void vcons_dummy_init_screen(void *, struct vcons_screen *, int,
67 long *); 67 long *);
68 68
69static int vcons_ioctl(void *, void *, u_long, void *, int, struct lwp *); 69static int vcons_ioctl(void *, void *, u_long, void *, int, struct lwp *);
70static int vcons_alloc_screen(void *, const struct wsscreen_descr *, void **,  70static int vcons_alloc_screen(void *, const struct wsscreen_descr *, void **,
71 int *, int *, long *); 71 int *, int *, long *);
72static void vcons_free_screen(void *, void *); 72static void vcons_free_screen(void *, void *);
73static int vcons_show_screen(void *, void *, int, void (*)(void *, int, int), 73static int vcons_show_screen(void *, void *, int, void (*)(void *, int, int),
74 void *); 74 void *);
75static int vcons_load_font(void *, void *, struct wsdisplay_font *); 75static int vcons_load_font(void *, void *, struct wsdisplay_font *);
76 76
77#ifdef WSDISPLAY_SCROLLSUPPORT 77#ifdef WSDISPLAY_SCROLLSUPPORT
78static void vcons_scroll(void *, void *, int); 78static void vcons_scroll(void *, void *, int);
79static void vcons_do_scroll(struct vcons_screen *); 79static void vcons_do_scroll(struct vcons_screen *);
80#endif 80#endif
81 81
82static void vcons_do_switch(void *); 82static void vcons_do_switch(void *);
83 83
84/* methods that work only on text buffers */ 84/* methods that work only on text buffers */
85static void vcons_copycols_buffer(void *, int, int, int, int); 85static void vcons_copycols_buffer(void *, int, int, int, int);
86static void vcons_erasecols_buffer(void *, int, int, int, long); 86static void vcons_erasecols_buffer(void *, int, int, int, long);
87static void vcons_copyrows_buffer(void *, int, int, int); 87static void vcons_copyrows_buffer(void *, int, int, int);
88static void vcons_eraserows_buffer(void *, int, int, long); 88static void vcons_eraserows_buffer(void *, int, int, long);
89static void vcons_putchar_buffer(void *, int, int, u_int, long); 89static void vcons_putchar_buffer(void *, int, int, u_int, long);
90 90
91/* 91/*
92 * actual wrapper methods which call both the _buffer ones above and the 92 * actual wrapper methods which call both the _buffer ones above and the
93 * driver supplied ones to do the drawing 93 * driver supplied ones to do the drawing
94 */ 94 */
95static void vcons_copycols(void *, int, int, int, int); 95static void vcons_copycols(void *, int, int, int, int);
96static void vcons_erasecols(void *, int, int, int, long); 96static void vcons_erasecols(void *, int, int, int, long);
97static void vcons_copyrows(void *, int, int, int); 97static void vcons_copyrows(void *, int, int, int);
98static void vcons_eraserows(void *, int, int, long); 98static void vcons_eraserows(void *, int, int, long);
99static void vcons_putchar(void *, int, int, u_int, long); 99static void vcons_putchar(void *, int, int, u_int, long);
100#ifdef VCONS_DRAW_INTR 100#ifdef VCONS_DRAW_INTR
101static void vcons_erasecols_cached(void *, int, int, int, long); 101static void vcons_erasecols_cached(void *, int, int, int, long);
102static void vcons_eraserows_cached(void *, int, int, long); 102static void vcons_eraserows_cached(void *, int, int, long);
103static void vcons_putchar_cached(void *, int, int, u_int, long); 103static void vcons_putchar_cached(void *, int, int, u_int, long);
104#endif 104#endif
105static void vcons_cursor(void *, int, int, int); 105static void vcons_cursor(void *, int, int, int);
106static void vcons_cursor_noread(void *, int, int, int); 106static void vcons_cursor_noread(void *, int, int, int);
107 107
108/* 108/*
109 * methods that avoid framebuffer reads 109 * methods that avoid framebuffer reads
110 */ 110 */
111static void vcons_copycols_noread(void *, int, int, int, int); 111static void vcons_copycols_noread(void *, int, int, int, int);
112static void vcons_copyrows_noread(void *, int, int, int); 112static void vcons_copyrows_noread(void *, int, int, int);
113 113
114 114
115/* support for reading/writing text buffers. For wsmoused */ 115/* support for reading/writing text buffers. For wsmoused */
116static int vcons_putwschar(struct vcons_screen *, struct wsdisplay_char *); 116static int vcons_putwschar(struct vcons_screen *, struct wsdisplay_char *);
117static int vcons_getwschar(struct vcons_screen *, struct wsdisplay_char *); 117static int vcons_getwschar(struct vcons_screen *, struct wsdisplay_char *);
118 118
119static void vcons_lock(struct vcons_screen *); 119static void vcons_lock(struct vcons_screen *);
120static void vcons_unlock(struct vcons_screen *); 120static void vcons_unlock(struct vcons_screen *);
121 121
122#ifdef VCONS_DRAW_INTR 122#ifdef VCONS_DRAW_INTR
123static void vcons_intr(void *); 123static void vcons_intr(void *);
124static void vcons_softintr(void *); 124static void vcons_softintr(void *);
125static void vcons_init_thread(void *); 125static void vcons_init_thread(void *);
126#endif 126#endif
127 127
128static int 128static int
129vcons_init_common(struct vcons_data *vd, void *cookie, 129vcons_init_common(struct vcons_data *vd, void *cookie,
130 struct wsscreen_descr *def, struct wsdisplay_accessops *ao, 130 struct wsscreen_descr *def, struct wsdisplay_accessops *ao,
131 int enable_intr) 131 int enable_intr)
132{ 132{
133 133
134 /* zero out everything so we can rely on untouched fields being 0 */ 134 /* zero out everything so we can rely on untouched fields being 0 */
135 memset(vd, 0, sizeof(struct vcons_data)); 135 memset(vd, 0, sizeof(struct vcons_data));
136 136
137 vd->cookie = cookie; 137 vd->cookie = cookie;
138 138
139 vd->init_screen = vcons_dummy_init_screen; 139 vd->init_screen = vcons_dummy_init_screen;
140 vd->show_screen_cb = NULL; 140 vd->show_screen_cb = NULL;
141 141
142 /* keep a copy of the accessops that we replace below with our 142 /* keep a copy of the accessops that we replace below with our
143 * own wrappers */ 143 * own wrappers */
144 vd->ioctl = ao->ioctl; 144 vd->ioctl = ao->ioctl;
145 145
146 /* configure the accessops */ 146 /* configure the accessops */
147 ao->ioctl = vcons_ioctl; 147 ao->ioctl = vcons_ioctl;
148 ao->alloc_screen = vcons_alloc_screen; 148 ao->alloc_screen = vcons_alloc_screen;
149 ao->free_screen = vcons_free_screen; 149 ao->free_screen = vcons_free_screen;
150 ao->show_screen = vcons_show_screen; 150 ao->show_screen = vcons_show_screen;
151 ao->load_font = vcons_load_font; 151 ao->load_font = vcons_load_font;
152#ifdef WSDISPLAY_SCROLLSUPPORT 152#ifdef WSDISPLAY_SCROLLSUPPORT
153 ao->scroll = vcons_scroll; 153 ao->scroll = vcons_scroll;
154#endif 154#endif
155 155
156 LIST_INIT(&vd->screens); 156 LIST_INIT(&vd->screens);
157 vd->active = NULL; 157 vd->active = NULL;
158 vd->wanted = NULL; 158 vd->wanted = NULL;
159 vd->currenttype = def; 159 vd->currenttype = def;
160 vd->defaulttype = def; 160 vd->defaulttype = def;
161 callout_init(&vd->switch_callout, 0); 161 callout_init(&vd->switch_callout, 0);
162 callout_setfunc(&vd->switch_callout, vcons_do_switch, vd); 162 callout_setfunc(&vd->switch_callout, vcons_do_switch, vd);
163#ifdef VCONS_DRAW_INTR 163#ifdef VCONS_DRAW_INTR
164 vd->cells = 0; 164 vd->cells = 0;
165 vd->attrs = NULL; 165 vd->attrs = NULL;
166 vd->chars = NULL; 166 vd->chars = NULL;
167 vd->cursor_offset = -1; 167 vd->cursor_offset = -1;
168#endif 168#endif
169 169
170 /* 170 /*
171 * a lock to serialize access to the framebuffer. 171 * a lock to serialize access to the framebuffer.
172 * when switching screens we need to make sure there's no rasops 172 * when switching screens we need to make sure there's no rasops
173 * operation in progress 173 * operation in progress
174 */ 174 */
175#ifdef DIAGNOSTIC 175#ifdef DIAGNOSTIC
176 vd->switch_poll_count = 0; 176 vd->switch_poll_count = 0;
177#endif 177#endif
178#ifdef VCONS_DRAW_INTR 178#ifdef VCONS_DRAW_INTR
179 if (enable_intr) { 179 if (enable_intr) {
180 vd->intr_softint = softint_establish(SOFTINT_SERIAL, 180 vd->intr_softint = softint_establish(SOFTINT_SERIAL,
181 vcons_softintr, vd); 181 vcons_softintr, vd);
182 callout_init(&vd->intr, CALLOUT_MPSAFE); 182 callout_init(&vd->intr, CALLOUT_MPSAFE);
183 callout_setfunc(&vd->intr, vcons_intr, vd); 183 callout_setfunc(&vd->intr, vcons_intr, vd);
184 vd->intr_valid = 1; 184 vd->intr_valid = 1;
185 185
186 if (kthread_create(PRI_NONE, 0, NULL, vcons_init_thread, vd, 186 if (kthread_create(PRI_NONE, 0, NULL, vcons_init_thread, vd,
187 NULL, "vcons_init") != 0) { 187 NULL, "vcons_init") != 0) {
188 printf("%s: unable to create thread.\n", __func__); 188 printf("%s: unable to create thread.\n", __func__);
189 return -1; 189 return -1;
190 } 190 }
191 } 191 }
192#endif 192#endif
193 return 0; 193 return 0;
194} 194}
195 195
196int 196int
197vcons_init(struct vcons_data *vd, void *cookie, 197vcons_init(struct vcons_data *vd, void *cookie,
198 struct wsscreen_descr *def, struct wsdisplay_accessops *ao) 198 struct wsscreen_descr *def, struct wsdisplay_accessops *ao)
199{ 199{
200 return vcons_init_common(vd, cookie, def, ao, 1); 200 return vcons_init_common(vd, cookie, def, ao, 1);
201} 201}
202 202
203int 203int
204vcons_earlyinit(struct vcons_data *vd, void *cookie, 204vcons_earlyinit(struct vcons_data *vd, void *cookie,
205 struct wsscreen_descr *def, struct wsdisplay_accessops *ao) 205 struct wsscreen_descr *def, struct wsdisplay_accessops *ao)
206{ 206{
207 return vcons_init_common(vd, cookie, def, ao, 0); 207 return vcons_init_common(vd, cookie, def, ao, 0);
208} 208}
209 209
210static void 210static void
211vcons_lock(struct vcons_screen *scr) 211vcons_lock(struct vcons_screen *scr)
212{ 212{
213#ifdef VCONS_PARANOIA 213#ifdef VCONS_PARANOIA
214 int s; 214 int s;
215 215
216 s = splhigh(); 216 s = splhigh();
217#endif 217#endif
218 SCREEN_BUSY(scr); 218 SCREEN_BUSY(scr);
219#ifdef VCONS_PARANOIA 219#ifdef VCONS_PARANOIA
220 splx(s); 220 splx(s);
221#endif 221#endif
222} 222}
223 223
224static void 224static void
225vcons_unlock(struct vcons_screen *scr) 225vcons_unlock(struct vcons_screen *scr)
226{ 226{
227#ifdef VCONS_PARANOIA 227#ifdef VCONS_PARANOIA
228 int s; 228 int s;
229 229
230 s = splhigh(); 230 s = splhigh();
231#endif 231#endif
232 SCREEN_IDLE(scr); 232 SCREEN_IDLE(scr);
233#ifdef VCONS_PARANOIA 233#ifdef VCONS_PARANOIA
234 splx(s); 234 splx(s);
235#endif 235#endif
236} 236}
237 237
238static void 238static void
239vcons_dummy_init_screen(void *cookie, 239vcons_dummy_init_screen(void *cookie,
240 struct vcons_screen *scr, int exists, 240 struct vcons_screen *scr, int exists,
241 long *defattr) 241 long *defattr)
242{ 242{
243 243
244 /* 244 /*
245 * default init_screen() method. 245 * default init_screen() method.
246 * Needs to be overwritten so we bitch and whine in case anyone ends 246 * Needs to be overwritten so we bitch and whine in case anyone ends
247 * up in here. 247 * up in here.
248 */ 248 */
249 printf("vcons_init_screen: dummy function called. Your driver is " 249 printf("vcons_init_screen: dummy function called. Your driver is "
250 "supposed to supply a replacement for proper operation\n"); 250 "supposed to supply a replacement for proper operation\n");
251} 251}
252 252
253static int 253static int
254vcons_alloc_buffers(struct vcons_data *vd, struct vcons_screen *scr) 254vcons_alloc_buffers(struct vcons_data *vd, struct vcons_screen *scr)
255{ 255{
256 struct rasops_info *ri = &scr->scr_ri; 256 struct rasops_info *ri = &scr->scr_ri;
257 int cnt, i; 257 int cnt, i;
258#ifdef VCONS_DRAW_INTR 258#ifdef VCONS_DRAW_INTR
259 int size; 259 int size;
260#endif 260#endif
261 261
262 /*  262 /*
263 * we allocate both chars and attributes in one chunk, attributes first  263 * we allocate both chars and attributes in one chunk, attributes first
264 * because they have the (potentially) bigger alignment  264 * because they have the (potentially) bigger alignment
265 */ 265 */
266#ifdef WSDISPLAY_SCROLLSUPPORT 266#ifdef WSDISPLAY_SCROLLSUPPORT
267 cnt = (ri->ri_rows + WSDISPLAY_SCROLLBACK_LINES) * ri->ri_cols; 267 cnt = (ri->ri_rows + WSDISPLAY_SCROLLBACK_LINES) * ri->ri_cols;
268 scr->scr_lines_in_buffer = WSDISPLAY_SCROLLBACK_LINES; 268 scr->scr_lines_in_buffer = WSDISPLAY_SCROLLBACK_LINES;
269 scr->scr_current_line = 0; 269 scr->scr_current_line = 0;
270 scr->scr_line_wanted = 0; 270 scr->scr_line_wanted = 0;
271 scr->scr_offset_to_zero = ri->ri_cols * WSDISPLAY_SCROLLBACK_LINES; 271 scr->scr_offset_to_zero = ri->ri_cols * WSDISPLAY_SCROLLBACK_LINES;
272 scr->scr_current_offset = scr->scr_offset_to_zero; 272 scr->scr_current_offset = scr->scr_offset_to_zero;
273#else 273#else
274 cnt = ri->ri_rows * ri->ri_cols; 274 cnt = ri->ri_rows * ri->ri_cols;
275#endif 275#endif
276 scr->scr_attrs = malloc(cnt * (sizeof(long) +  276 scr->scr_attrs = malloc(cnt * (sizeof(long) +
277 sizeof(uint32_t)), M_DEVBUF, M_WAITOK); 277 sizeof(uint32_t)), M_DEVBUF, M_WAITOK);
278 if (scr->scr_attrs == NULL) 278 if (scr->scr_attrs == NULL)
279 return ENOMEM; 279 return ENOMEM;
280 280
281 scr->scr_chars = (uint32_t *)&scr->scr_attrs[cnt]; 281 scr->scr_chars = (uint32_t *)&scr->scr_attrs[cnt];
282 282
283 /*  283 /*
284 * fill the attribute buffer with *defattr, chars with 0x20  284 * fill the attribute buffer with *defattr, chars with 0x20
285 * since we don't know if the driver tries to mimic firmware output or 285 * since we don't know if the driver tries to mimic firmware output or
286 * reset everything we do nothing to VRAM here, any driver that feels 286 * reset everything we do nothing to VRAM here, any driver that feels
287 * the need to clear screen or something will have to do it on its own 287 * the need to clear screen or something will have to do it on its own
288 * Additional screens will start out in the background anyway so 288 * Additional screens will start out in the background anyway so
289 * cleaning or not only really affects the initial console screen 289 * cleaning or not only really affects the initial console screen
290 */ 290 */
291 for (i = 0; i < cnt; i++) { 291 for (i = 0; i < cnt; i++) {
292 scr->scr_attrs[i] = scr->scr_defattr; 292 scr->scr_attrs[i] = scr->scr_defattr;
293 scr->scr_chars[i] = 0x20; 293 scr->scr_chars[i] = 0x20;
294 } 294 }
295 295
296#ifdef VCONS_DRAW_INTR 296#ifdef VCONS_DRAW_INTR
297 size = ri->ri_cols * ri->ri_rows; 297 size = ri->ri_cols * ri->ri_rows;
298 if (size > vd->cells) { 298 if (size > vd->cells) {
299 if (vd->chars != NULL) free(vd->chars, M_DEVBUF); 299 if (vd->chars != NULL) free(vd->chars, M_DEVBUF);
300 if (vd->attrs != NULL) free(vd->attrs, M_DEVBUF); 300 if (vd->attrs != NULL) free(vd->attrs, M_DEVBUF);
301 vd->cells = size; 301 vd->cells = size;
302 vd->chars = malloc(size * sizeof(uint32_t), M_DEVBUF, 302 vd->chars = malloc(size * sizeof(uint32_t), M_DEVBUF,
303 M_WAITOK|M_ZERO); 303 M_WAITOK|M_ZERO);
304 vd->attrs = malloc(size * sizeof(long), M_DEVBUF, 304 vd->attrs = malloc(size * sizeof(long), M_DEVBUF,
305 M_WAITOK|M_ZERO); 305 M_WAITOK|M_ZERO);
306 vcons_invalidate_cache(vd); 306 vcons_invalidate_cache(vd);
307 } else if (SCREEN_IS_VISIBLE(scr)) 307 } else if (SCREEN_IS_VISIBLE(scr))
308 vcons_invalidate_cache(vd); 308 vcons_invalidate_cache(vd);
309#endif 309#endif
310 return 0; 310 return 0;
311} 311}
312 312
313int 313int
314vcons_init_screen(struct vcons_data *vd, struct vcons_screen *scr, 314vcons_init_screen(struct vcons_data *vd, struct vcons_screen *scr,
315 int existing, long *defattr) 315 int existing, long *defattr)
316{ 316{
317 struct rasops_info *ri = &scr->scr_ri; 317 struct rasops_info *ri = &scr->scr_ri;
318 int i; 318 int i;
319 319
320 scr->scr_cookie = vd->cookie; 320 scr->scr_cookie = vd->cookie;
321 scr->scr_vd = scr->scr_origvd = vd; 321 scr->scr_vd = scr->scr_origvd = vd;
322 scr->scr_busy = 0; 322 scr->scr_busy = 0;
323 323
324 if (scr->scr_type == NULL) 324 if (scr->scr_type == NULL)
325 scr->scr_type = vd->defaulttype; 325 scr->scr_type = vd->defaulttype;
326  326
327 /* 327 /*
328 * call the driver-supplied init_screen function which is expected 328 * call the driver-supplied init_screen function which is expected
329 * to set up rasops_info, override cursor() and probably others 329 * to set up rasops_info, override cursor() and probably others
330 */ 330 */
331 vd->init_screen(vd->cookie, scr, existing, defattr); 331 vd->init_screen(vd->cookie, scr, existing, defattr);
332 332
333 /*  333 /*
334 * save the non virtual console aware rasops and replace them with  334 * save the non virtual console aware rasops and replace them with
335 * our wrappers 335 * our wrappers
336 */ 336 */
337 vd->eraserows = ri->ri_ops.eraserows; 337 vd->eraserows = ri->ri_ops.eraserows;
338 vd->erasecols = ri->ri_ops.erasecols; 338 vd->erasecols = ri->ri_ops.erasecols;
339 scr->putchar = ri->ri_ops.putchar; 339 scr->putchar = ri->ri_ops.putchar;
340 340
341 if (scr->scr_flags & VCONS_NO_COPYCOLS) { 341 if (scr->scr_flags & VCONS_NO_COPYCOLS) {
342 vd->copycols = vcons_copycols_noread; 342 vd->copycols = vcons_copycols_noread;
343 } else { 343 } else {
344 vd->copycols = ri->ri_ops.copycols; 344 vd->copycols = ri->ri_ops.copycols;
345 } 345 }
346 346
347 if (scr->scr_flags & VCONS_NO_COPYROWS) { 347 if (scr->scr_flags & VCONS_NO_COPYROWS) {
348 vd->copyrows = vcons_copyrows_noread; 348 vd->copyrows = vcons_copyrows_noread;
349 } else { 349 } else {
350 vd->copyrows = ri->ri_ops.copyrows; 350 vd->copyrows = ri->ri_ops.copyrows;
351 } 351 }
352 352
353 if (scr->scr_flags & VCONS_NO_CURSOR) { 353 if (scr->scr_flags & VCONS_NO_CURSOR) {
354 vd->cursor = vcons_cursor_noread; 354 vd->cursor = vcons_cursor_noread;
355 } else { 355 } else {
356 vd->cursor = ri->ri_ops.cursor; 356 vd->cursor = ri->ri_ops.cursor;
357 } 357 }
358 358
359 ri->ri_ops.eraserows = vcons_eraserows;  359 ri->ri_ops.eraserows = vcons_eraserows;
360 ri->ri_ops.erasecols = vcons_erasecols;  360 ri->ri_ops.erasecols = vcons_erasecols;
361 ri->ri_ops.putchar = vcons_putchar; 361 ri->ri_ops.putchar = vcons_putchar;
362 ri->ri_ops.cursor = vcons_cursor; 362 ri->ri_ops.cursor = vcons_cursor;
363 ri->ri_ops.copycols = vcons_copycols; 363 ri->ri_ops.copycols = vcons_copycols;
364 ri->ri_ops.copyrows = vcons_copyrows; 364 ri->ri_ops.copyrows = vcons_copyrows;
365 365
366 366
367 ri->ri_hw = scr; 367 ri->ri_hw = scr;
368 368
369 i = ri->ri_ops.allocattr(ri, WS_DEFAULT_FG, WS_DEFAULT_BG, 0, defattr); 369 i = ri->ri_ops.allocattr(ri, WS_DEFAULT_FG, WS_DEFAULT_BG, 0, defattr);
370 if (i != 0) { 370 if (i != 0) {
371#ifdef DIAGNOSTIC 371#ifdef DIAGNOSTIC
372 printf("vcons: error allocating attribute %d\n", i); 372 printf("vcons: error allocating attribute %d\n", i);
373#endif 373#endif
374 scr->scr_defattr = 0; 374 scr->scr_defattr = 0;
375 } else 375 } else
376 scr->scr_defattr = *defattr; 376 scr->scr_defattr = *defattr;
377 377
378 vcons_alloc_buffers(vd, scr); 378 vcons_alloc_buffers(vd, scr);
379 379
380 if(vd->active == NULL) { 380 if(vd->active == NULL) {
381 vd->active = scr; 381 vd->active = scr;
382 SCREEN_VISIBLE(scr); 382 SCREEN_VISIBLE(scr);
383 } 383 }
384  384
385 if (existing) { 385 if (existing) {
386 SCREEN_VISIBLE(scr); 386 SCREEN_VISIBLE(scr);
387 vd->active = scr; 387 vd->active = scr;
388 } else { 388 } else {
389 SCREEN_INVISIBLE(scr); 389 SCREEN_INVISIBLE(scr);
390 } 390 }
391  391
392 LIST_INSERT_HEAD(&vd->screens, scr, next); 392 LIST_INSERT_HEAD(&vd->screens, scr, next);
393 return 0; 393 return 0;
394} 394}
395 395
396static int 396static int
397vcons_load_font(void *v, void *cookie, struct wsdisplay_font *f) 397vcons_load_font(void *v, void *cookie, struct wsdisplay_font *f)
398{ 398{
399 struct vcons_data *vd = v; 399 struct vcons_data *vd = v;
400 struct vcons_screen *scr = cookie; 400 struct vcons_screen *scr = cookie;
401 struct rasops_info *ri; 401 struct rasops_info *ri;
402 struct wsdisplay_font *font; 402 struct wsdisplay_font *font;
403 int flags = WSFONT_FIND_BITMAP, fcookie; 403 int flags = WSFONT_FIND_BITMAP, fcookie;
404 404
405 /* see if we're asked to add a font or use it */ 405 /* see if we're asked to add a font or use it */
406 if (scr == NULL) 406 if (scr == NULL)
407 return 0; 407 return 0;
408 408
409 ri = &scr->scr_ri; 409 ri = &scr->scr_ri;
410 410
411 /* see if the driver knows how to handle multiple fonts */ 411 /* see if the driver knows how to handle multiple fonts */
412 if ((scr->scr_flags & VCONS_LOADFONT) == 0) { 412 if ((scr->scr_flags & VCONS_LOADFONT) == 0) {
413 return EOPNOTSUPP; 413 return EOPNOTSUPP;
414 } 414 }
415 415
416 /* now see what fonts we can use */ 416 /* now see what fonts we can use */
417 if (ri->ri_flg & RI_ENABLE_ALPHA) { 417 if (ri->ri_flg & RI_ENABLE_ALPHA) {
418 flags |= WSFONT_FIND_ALPHA; 418 flags |= WSFONT_FIND_ALPHA;
419 } 419 }
420 420
421 fcookie = wsfont_find(f->name, 0, 0, 0, 0, 0, flags); 421 fcookie = wsfont_find(f->name, 0, 0, 0, 0, 0, flags);
422 if (fcookie == -1) 422 if (fcookie == -1)
423 return EINVAL; 423 return EINVAL;
424 424
425 wsfont_lock(fcookie, &font); 425 wsfont_lock(fcookie, &font);
426 if (font == NULL) 426 if (font == NULL)
427 return EINVAL; 427 return EINVAL;
428 428
429 /* ok, we got a font. Now clear the screen with the old parameters */ 429 /* ok, we got a font. Now clear the screen with the old parameters */
430 if (SCREEN_IS_VISIBLE(scr)) 430 if (SCREEN_IS_VISIBLE(scr))
431 vd->eraserows(ri, 0, ri->ri_rows, scr->scr_defattr); 431 vd->eraserows(ri, 0, ri->ri_rows, scr->scr_defattr);
432 432
433 vcons_lock(vd->active); 433 vcons_lock(vd->active);
434#ifdef VCONS_DRAW_INTR 434#ifdef VCONS_DRAW_INTR
435 callout_halt(&vd->intr, NULL); 435 callout_halt(&vd->intr, NULL);
436#endif 436#endif
437 /* set the new font and re-initialize things */ 437 /* set the new font and re-initialize things */
438 ri->ri_font = font; 438 ri->ri_font = font;
439 wsfont_unlock(ri->ri_wsfcookie); 439 wsfont_unlock(ri->ri_wsfcookie);
440 ri->ri_wsfcookie = fcookie; 440 ri->ri_wsfcookie = fcookie;
441 441
442 vd->init_screen(vd->cookie, scr, 1, &scr->scr_defattr); 442 vd->init_screen(vd->cookie, scr, 1, &scr->scr_defattr);
443 DPRINTF("caps %x %x\n", scr->scr_type->capabilities, ri->ri_caps); 443 DPRINTF("caps %x %x\n", scr->scr_type->capabilities, ri->ri_caps);
444 if (scr->scr_type->capabilities & WSSCREEN_RESIZE) { 444 if (scr->scr_type->capabilities & WSSCREEN_RESIZE) {
445 scr->scr_type->nrows = ri->ri_rows; 445 scr->scr_type->nrows = ri->ri_rows;
446 scr->scr_type->ncols = ri->ri_cols; 446 scr->scr_type->ncols = ri->ri_cols;
447 DPRINTF("new size %d %d\n", ri->ri_rows, ri->ri_cols); 447 DPRINTF("new size %d %d\n", ri->ri_rows, ri->ri_cols);
448 } 448 }
449 449
450 450
451 /* now, throw the old buffers away */ 451 /* now, throw the old buffers away */
452 if (scr->scr_attrs) 452 if (scr->scr_attrs)
453 free(scr->scr_attrs, M_DEVBUF); 453 free(scr->scr_attrs, M_DEVBUF);
454 /* allocate new buffers */ 454 /* allocate new buffers */
455 vcons_alloc_buffers(vd, scr); 455 vcons_alloc_buffers(vd, scr);
456  456
457 /* save the potentially changed ri_ops */  457 /* save the potentially changed ri_ops */
458 vd->eraserows = ri->ri_ops.eraserows; 458 vd->eraserows = ri->ri_ops.eraserows;
459 vd->erasecols = ri->ri_ops.erasecols; 459 vd->erasecols = ri->ri_ops.erasecols;
460 scr->putchar = ri->ri_ops.putchar; 460 scr->putchar = ri->ri_ops.putchar;
461 vd->cursor = ri->ri_ops.cursor; 461 vd->cursor = ri->ri_ops.cursor;
462 462
463 if (scr->scr_flags & VCONS_NO_COPYCOLS) { 463 if (scr->scr_flags & VCONS_NO_COPYCOLS) {
464 vd->copycols = vcons_copycols_noread; 464 vd->copycols = vcons_copycols_noread;
465 } else { 465 } else {
466 vd->copycols = ri->ri_ops.copycols; 466 vd->copycols = ri->ri_ops.copycols;
467 } 467 }
468 468
469 if (scr->scr_flags & VCONS_NO_COPYROWS) { 469 if (scr->scr_flags & VCONS_NO_COPYROWS) {
470 vd->copyrows = vcons_copyrows_noread; 470 vd->copyrows = vcons_copyrows_noread;
471 } else { 471 } else {
472 vd->copyrows = ri->ri_ops.copyrows; 472 vd->copyrows = ri->ri_ops.copyrows;
473 } 473 }
474 474
475 if (scr->scr_flags & VCONS_NO_CURSOR) { 475 if (scr->scr_flags & VCONS_NO_CURSOR) {
476 vd->cursor = vcons_cursor_noread; 476 vd->cursor = vcons_cursor_noread;
477 } else { 477 } else {
478 vd->cursor = ri->ri_ops.cursor; 478 vd->cursor = ri->ri_ops.cursor;
479 } 479 }
480 480
481 /* and put our wrappers back */ 481 /* and put our wrappers back */
482 ri->ri_ops.eraserows = vcons_eraserows;  482 ri->ri_ops.eraserows = vcons_eraserows;
483 ri->ri_ops.erasecols = vcons_erasecols;  483 ri->ri_ops.erasecols = vcons_erasecols;
484 ri->ri_ops.putchar = vcons_putchar; 484 ri->ri_ops.putchar = vcons_putchar;
485 ri->ri_ops.cursor = vcons_cursor; 485 ri->ri_ops.cursor = vcons_cursor;
486 ri->ri_ops.copycols = vcons_copycols; 486 ri->ri_ops.copycols = vcons_copycols;
487 ri->ri_ops.copyrows = vcons_copyrows; 487 ri->ri_ops.copyrows = vcons_copyrows;
488 vcons_unlock(vd->active); 488 vcons_unlock(vd->active);
489 489
490 /* notify things that we're about to redraw */ 490 /* notify things that we're about to redraw */
491 if (vd->show_screen_cb != NULL) 491 if (vd->show_screen_cb != NULL)
492 vd->show_screen_cb(scr, vd->show_screen_cookie); 492 vd->show_screen_cb(scr, vd->show_screen_cookie);
493  493
494#ifdef VCONS_DRAW_INTR 494#ifdef VCONS_DRAW_INTR
495 /* 495 /*
496 * XXX 496 * XXX
497 * Something(tm) craps all over VRAM somewhere up there if we're  497 * Something(tm) craps all over VRAM somewhere up there if we're
498 * using VCONS_DRAW_INTR. Until I figure out what causes it, just 498 * using VCONS_DRAW_INTR. Until I figure out what causes it, just
499 * redraw the screen for now. 499 * redraw the screen for now.
500 */ 500 */
501 vcons_redraw_screen(vd->active); 501 vcons_redraw_screen(vd->active);
502 callout_schedule(&vd->intr, mstohz(33)); 502 callout_schedule(&vd->intr, mstohz(33));
503#endif 503#endif
504 /* no need to draw anything, wsdisplay should reset the terminal */ 504 /* no need to draw anything, wsdisplay should reset the terminal */
505 505
506 return 0; 506 return 0;
507}  507}
508 508
509static void 509static void
510vcons_do_switch(void *arg) 510vcons_do_switch(void *arg)
511{ 511{
512 struct vcons_data *vd = arg; 512 struct vcons_data *vd = arg;
513 struct vcons_screen *scr, *oldscr; 513 struct vcons_screen *scr, *oldscr;
514 514
515 scr = vd->wanted; 515 scr = vd->wanted;
516 if (!scr) { 516 if (!scr) {
517 printf("vcons_switch_screen: disappeared\n"); 517 printf("vcons_switch_screen: disappeared\n");
518 vd->switch_cb(vd->switch_cb_arg, EIO, 0); 518 vd->switch_cb(vd->switch_cb_arg, EIO, 0);
519 return; 519 return;
520 } 520 }
521 oldscr = vd->active; /* can be NULL! */ 521 oldscr = vd->active; /* can be NULL! */
522 522
523 /*  523 /*
524 * if there's an old, visible screen we mark it invisible and wait 524 * if there's an old, visible screen we mark it invisible and wait
525 * until it's not busy so we can safely switch  525 * until it's not busy so we can safely switch
526 */ 526 */
527 if (oldscr != NULL) { 527 if (oldscr != NULL) {
528 SCREEN_INVISIBLE(oldscr); 528 SCREEN_INVISIBLE(oldscr);
529 if (SCREEN_IS_BUSY(oldscr)) { 529 if (SCREEN_IS_BUSY(oldscr)) {
530 callout_schedule(&vd->switch_callout, 1); 530 callout_schedule(&vd->switch_callout, 1);
531#ifdef DIAGNOSTIC 531#ifdef DIAGNOSTIC
532 /* bitch if we wait too long */ 532 /* bitch if we wait too long */
533 vd->switch_poll_count++; 533 vd->switch_poll_count++;
534 if (vd->switch_poll_count > 100) { 534 if (vd->switch_poll_count > 100) {
535 panic("vcons: screen still busy"); 535 panic("vcons: screen still busy");
536 } 536 }
537#endif 537#endif
538 return; 538 return;
539 } 539 }
540 /* invisible screen -> no visible cursor image */ 540 /* invisible screen -> no visible cursor image */
541 oldscr->scr_ri.ri_flg &= ~RI_CURSOR; 541 oldscr->scr_ri.ri_flg &= ~RI_CURSOR;
542#ifdef DIAGNOSTIC 542#ifdef DIAGNOSTIC
543 vd->switch_poll_count = 0; 543 vd->switch_poll_count = 0;
544#endif 544#endif
545 } 545 }
546 546
547 if (scr == oldscr) 547 if (scr == oldscr)
548 return; 548 return;
549 549
550#ifdef DIAGNOSTIC 550#ifdef DIAGNOSTIC
551 if (SCREEN_IS_VISIBLE(scr)) 551 if (SCREEN_IS_VISIBLE(scr))
552 printf("vcons_switch_screen: already active"); 552 printf("vcons_switch_screen: already active");
553#endif 553#endif
554 554
555#ifdef notyet 555#ifdef notyet
556 if (vd->currenttype != type) { 556 if (vd->currenttype != type) {
557 vcons_set_screentype(vd, type); 557 vcons_set_screentype(vd, type);
558 vd->currenttype = type; 558 vd->currenttype = type;
559 } 559 }
560#endif 560#endif
561 561
562 SCREEN_VISIBLE(scr); 562 SCREEN_VISIBLE(scr);
563 vd->active = scr; 563 vd->active = scr;
564 vd->wanted = NULL; 564 vd->wanted = NULL;
565 565
566#ifdef VCONS_DRAW_INTR 566#ifdef VCONS_DRAW_INTR
567 vcons_invalidate_cache(vd); 567 vcons_invalidate_cache(vd);
568#endif 568#endif
569 569
570 if (vd->show_screen_cb != NULL) 570 if (vd->show_screen_cb != NULL)
571 vd->show_screen_cb(scr, vd->show_screen_cookie); 571 vd->show_screen_cb(scr, vd->show_screen_cookie);
572 572
573 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0) 573 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0)
574 vcons_redraw_screen(scr); 574 vcons_redraw_screen(scr);
575 575
576 if (vd->switch_cb) 576 if (vd->switch_cb)
577 vd->switch_cb(vd->switch_cb_arg, 0, 0); 577 vd->switch_cb(vd->switch_cb_arg, 0, 0);
578} 578}
579 579
580void 580void
581vcons_redraw_screen(struct vcons_screen *scr) 581vcons_redraw_screen(struct vcons_screen *scr)
582{ 582{
583 uint32_t *charptr = scr->scr_chars, c; 583 uint32_t *charptr = scr->scr_chars, c;
584 long *attrptr = scr->scr_attrs, a, last_a = 0, mask, cmp, acmp; 584 long *attrptr = scr->scr_attrs, a, last_a = 0, mask, cmp, acmp;
585 struct rasops_info *ri = &scr->scr_ri; 585 struct rasops_info *ri = &scr->scr_ri;
586 struct vcons_data *vd = scr->scr_vd; 586 struct vcons_data *vd = scr->scr_vd;
587 int i, j, offset, boffset = 0, start = -1; 587 int i, j, offset, boffset = 0, start = -1;
588 588
589 mask = 0x00ff00ff; /* background and flags */ 589 mask = 0x00ff00ff; /* background and flags */
590 cmp = 0xffffffff; /* never match anything */ 590 cmp = 0xffffffff; /* never match anything */
591 vcons_lock(scr); 591 vcons_lock(scr);
592 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 592 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
593 593
594 /* 594 /*
595 * only clear the screen when RI_FULLCLEAR is set since we're 595 * only clear the screen when RI_FULLCLEAR is set since we're
596 * going to overwrite every single character cell anyway 596 * going to overwrite every single character cell anyway
597 */ 597 */
598 if (ri->ri_flg & RI_FULLCLEAR) { 598 if (ri->ri_flg & RI_FULLCLEAR) {
599 vd->eraserows(ri, 0, ri->ri_rows, 599 vd->eraserows(ri, 0, ri->ri_rows,
600 scr->scr_defattr); 600 scr->scr_defattr);
601 cmp = scr->scr_defattr & mask; 601 cmp = scr->scr_defattr & mask;
602 } 602 }
603 603
604 /* redraw the screen */ 604 /* redraw the screen */
605#ifdef WSDISPLAY_SCROLLSUPPORT 605#ifdef WSDISPLAY_SCROLLSUPPORT
606 offset = scr->scr_current_offset; 606 offset = scr->scr_current_offset;
607#else 607#else
608 offset = 0; 608 offset = 0;
609#endif 609#endif
610 for (i = 0; i < ri->ri_rows; i++) { 610 for (i = 0; i < ri->ri_rows; i++) {
611 start = -1; 611 start = -1;
612 for (j = 0; j < ri->ri_cols; j++) { 612 for (j = 0; j < ri->ri_cols; j++) {
613 /* 613 /*
614 * no need to use the wrapper function - we  614 * no need to use the wrapper function - we
615 * don't change any characters or attributes 615 * don't change any characters or attributes
616 * and we already made sure the screen we're 616 * and we already made sure the screen we're
617 * working on is visible 617 * working on is visible
618 */ 618 */
619 c = charptr[offset]; 619 c = charptr[offset];
620 a = attrptr[offset]; 620 a = attrptr[offset];
621 acmp = a & mask; 621 acmp = a & mask;
622 if (c == ' ') { 622 if (c == ' ') {
623 /* 623 /*
624 * if we already erased the background 624 * if we already erased the background
625 * and if this blank uses the same  625 * and if this blank uses the same
626 * colour and flags we don't need to do 626 * colour and flags we don't need to do
627 * anything here 627 * anything here
628 */ 628 */
629 if (acmp == cmp && start == -1) 629 if (acmp == cmp && start == -1)
630 goto next; 630 goto next;
631 /* 631 /*
632 * see if we can optimize things a 632 * see if we can optimize things a
633 * little bit by drawing stretches of 633 * little bit by drawing stretches of
634 * blanks using erasecols 634 * blanks using erasecols
635 */ 635 */
636  636
637 if (start == -1) { 637 if (start == -1) {
638 start = j; 638 start = j;
639 last_a = acmp; 639 last_a = acmp;
640 } else if (acmp != last_a) { 640 } else if (acmp != last_a) {
641 /* 641 /*
642 * different attr, need to 642 * different attr, need to
643 * flush & restart  643 * flush & restart
644 */ 644 */
645 vd->erasecols(ri, i, start, 645 vd->erasecols(ri, i, start,
646 j - start, last_a); 646 j - start, last_a);
647 start = j; 647 start = j;
648 last_a = acmp; 648 last_a = acmp;
649 } 649 }
650 } else { 650 } else {
651 if (start != -1) { 651 if (start != -1) {
652 vd->erasecols(ri, i, start, 652 vd->erasecols(ri, i, start,
653 j - start, last_a); 653 j - start, last_a);
654 start = -1; 654 start = -1;
655 } 655 }
656  656
657 scr->putchar(ri, i, j, c, a); 657 scr->putchar(ri, i, j, c, a);
658 } 658 }
659next: 659next:
660#ifdef VCONS_DRAW_INTR 660#ifdef VCONS_DRAW_INTR
661 vd->chars[boffset] = charptr[offset]; 661 vd->chars[boffset] = charptr[offset];
662 vd->attrs[boffset] = attrptr[offset]; 662 vd->attrs[boffset] = attrptr[offset];
663#endif 663#endif
664 offset++; 664 offset++;
665 boffset++; 665 boffset++;
666 } 666 }
667 /* end of the line - draw all defered blanks, if any */ 667 /* end of the line - draw all defered blanks, if any */
668 if (start != -1) { 668 if (start != -1) {
669 vd->erasecols(ri, i, start, j - start, last_a); 669 vd->erasecols(ri, i, start, j - start, last_a);
670 }  670 }
671 } 671 }
672 ri->ri_flg &= ~RI_CURSOR; 672 ri->ri_flg &= ~RI_CURSOR;
673 scr->scr_vd->cursor(ri, 1, ri->ri_crow, ri->ri_ccol); 673 scr->scr_vd->cursor(ri, 1, ri->ri_crow, ri->ri_ccol);
674#ifdef VCONS_DRAW_INTR 674#ifdef VCONS_DRAW_INTR
675 vd->cursor_offset = ri->ri_crow * ri->ri_cols + ri->ri_ccol; 675 vd->cursor_offset = ri->ri_crow * ri->ri_cols + ri->ri_ccol;
676#endif 676#endif
677 } 677 }
678 vcons_unlock(scr); 678 vcons_unlock(scr);
679} 679}
680 680
681#ifdef VCONS_DRAW_INTR 681#ifdef VCONS_DRAW_INTR
682void 682void
683vcons_update_screen(struct vcons_screen *scr) 683vcons_update_screen(struct vcons_screen *scr)
684{ 684{
685 uint32_t *charptr = scr->scr_chars; 685 uint32_t *charptr = scr->scr_chars;
686 long *attrptr = scr->scr_attrs; 686 long *attrptr = scr->scr_attrs;
687 struct rasops_info *ri = &scr->scr_ri; 687 struct rasops_info *ri = &scr->scr_ri;
688 struct vcons_data *vd = scr->scr_vd; 688 struct vcons_data *vd = scr->scr_vd;
689 int i, j, offset, boffset = 0; 689 int i, j, offset, boffset = 0;
690 690
691 vcons_lock(scr); 691 vcons_lock(scr);
692 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 692 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
693 693
694 /* redraw the screen */ 694 /* redraw the screen */
695#ifdef WSDISPLAY_SCROLLSUPPORT 695#ifdef WSDISPLAY_SCROLLSUPPORT
696 offset = scr->scr_current_offset; 696 offset = scr->scr_current_offset;
697#else 697#else
698 offset = 0; 698 offset = 0;
699#endif 699#endif
700 /* 700 /*
701 * we mark the character cell occupied by the cursor as dirty 701 * we mark the character cell occupied by the cursor as dirty
702 * so we don't have to deal with it 702 * so we don't have to deal with it
703 * notice that this isn't necessarily the position where rasops 703 * notice that this isn't necessarily the position where rasops
704 * thinks it is, just where we drew it the last time 704 * thinks it is, just where we drew it the last time
705 */ 705 */
706 if (vd->cursor_offset >= 0) 706 if (vd->cursor_offset >= 0)
707 vd->attrs[vd->cursor_offset] = 0xffffffff; 707 vd->attrs[vd->cursor_offset] = 0xffffffff;
708 708
709 for (i = 0; i < ri->ri_rows; i++) { 709 for (i = 0; i < ri->ri_rows; i++) {
710 for (j = 0; j < ri->ri_cols; j++) { 710 for (j = 0; j < ri->ri_cols; j++) {
711 /* 711 /*
712 * no need to use the wrapper function - we  712 * no need to use the wrapper function - we
713 * don't change any characters or attributes 713 * don't change any characters or attributes
714 * and we already made sure the screen we're 714 * and we already made sure the screen we're
715 * working on is visible 715 * working on is visible
716 */ 716 */
717 if ((vd->chars[boffset] != charptr[offset]) || 717 if ((vd->chars[boffset] != charptr[offset]) ||
718 (vd->attrs[boffset] != attrptr[offset])) { 718 (vd->attrs[boffset] != attrptr[offset])) {
719 scr->putchar(ri, i, j,  719 scr->putchar(ri, i, j,
720 charptr[offset], attrptr[offset]); 720 charptr[offset], attrptr[offset]);
721 vd->chars[boffset] = charptr[offset]; 721 vd->chars[boffset] = charptr[offset];
722 vd->attrs[boffset] = attrptr[offset]; 722 vd->attrs[boffset] = attrptr[offset];
723 } 723 }
724 offset++; 724 offset++;
725 boffset++; 725 boffset++;
726 } 726 }
727 } 727 }
728 ri->ri_flg &= ~RI_CURSOR; 728 ri->ri_flg &= ~RI_CURSOR;
729 scr->scr_vd->cursor(ri, 1, ri->ri_crow, ri->ri_ccol); 729 scr->scr_vd->cursor(ri, 1, ri->ri_crow, ri->ri_ccol);
730 vd->cursor_offset = ri->ri_crow * ri->ri_cols + ri->ri_ccol; 730 vd->cursor_offset = ri->ri_crow * ri->ri_cols + ri->ri_ccol;
731 } 731 }
732 vcons_unlock(scr); 732 vcons_unlock(scr);
733} 733}
734#endif 734#endif
735 735
736static int 736static int
737vcons_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 737vcons_ioctl(void *v, void *vs, u_long cmd, void *data, int flag,
738 struct lwp *l) 738 struct lwp *l)
739{ 739{
740 struct vcons_data *vd = v; 740 struct vcons_data *vd = v;
741 int error = 0; 741 int error = 0;
742 742
743 743
744 switch (cmd) { 744 switch (cmd) {
745 case WSDISPLAYIO_GETWSCHAR: 745 case WSDISPLAYIO_GETWSCHAR:
746 error = vcons_getwschar((struct vcons_screen *)vs, 746 error = vcons_getwschar((struct vcons_screen *)vs,
747 (struct wsdisplay_char *)data); 747 (struct wsdisplay_char *)data);
748 break; 748 break;
749 749
750 case WSDISPLAYIO_PUTWSCHAR: 750 case WSDISPLAYIO_PUTWSCHAR:
751 error = vcons_putwschar((struct vcons_screen *)vs, 751 error = vcons_putwschar((struct vcons_screen *)vs,
752 (struct wsdisplay_char *)data); 752 (struct wsdisplay_char *)data);
753 break; 753 break;
754 754
755 case WSDISPLAYIO_SET_POLLING: { 755 case WSDISPLAYIO_SET_POLLING: {
756 int poll = *(int *)data; 756 int poll = *(int *)data;
757 757
758 /* first call the driver's ioctl handler */ 758 /* first call the driver's ioctl handler */
759 if (vd->ioctl != NULL) 759 if (vd->ioctl != NULL)
760 error = (*vd->ioctl)(v, vs, cmd, data, flag, l); 760 error = (*vd->ioctl)(v, vs, cmd, data, flag, l);
761 if (poll) { 761 if (poll) {
762 vcons_enable_polling(vd); 762 vcons_enable_polling(vd);
763 vcons_hard_switch(LIST_FIRST(&vd->screens)); 763 vcons_hard_switch(LIST_FIRST(&vd->screens));
764 } else 764 } else
765 vcons_disable_polling(vd); 765 vcons_disable_polling(vd);
766 } 766 }
767 break; 767 break;
768 768
769 default: 769 default:
770 if (vd->ioctl != NULL) 770 if (vd->ioctl != NULL)
771 error = (*vd->ioctl)(v, vs, cmd, data, flag, l); 771 error = (*vd->ioctl)(v, vs, cmd, data, flag, l);
772 else 772 else
773 error = EPASSTHROUGH; 773 error = EPASSTHROUGH;
774 } 774 }
775 775
776 return error; 776 return error;
777} 777}
778 778
779static int 779static int
780vcons_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 780vcons_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
781 int *curxp, int *curyp, long *defattrp) 781 int *curxp, int *curyp, long *defattrp)
782{ 782{
783 struct vcons_data *vd = v; 783 struct vcons_data *vd = v;
784 struct vcons_screen *scr; 784 struct vcons_screen *scr;
785 struct wsscreen_descr *t = __UNCONST(type); 785 struct wsscreen_descr *t = __UNCONST(type);
786 int ret; 786 int ret;
787 787
788 scr = malloc(sizeof(struct vcons_screen), M_DEVBUF, M_WAITOK | M_ZERO); 788 scr = malloc(sizeof(struct vcons_screen), M_DEVBUF, M_WAITOK | M_ZERO);
789 if (scr == NULL) 789 if (scr == NULL)
790 return ENOMEM; 790 return ENOMEM;
791 791
792 scr->scr_flags = 0;  792 scr->scr_flags = 0;
793 scr->scr_status = 0; 793 scr->scr_status = 0;
794 scr->scr_busy = 0; 794 scr->scr_busy = 0;
795 scr->scr_type = __UNCONST(type); 795 scr->scr_type = __UNCONST(type);
796 796
797 ret = vcons_init_screen(vd, scr, 0, defattrp); 797 ret = vcons_init_screen(vd, scr, 0, defattrp);
798 if (ret != 0) { 798 if (ret != 0) {
799 free(scr, M_DEVBUF); 799 free(scr, M_DEVBUF);
800 return ret; 800 return ret;
801 } 801 }
802 if (t->capabilities & WSSCREEN_RESIZE) { 802 if (t->capabilities & WSSCREEN_RESIZE) {
803 t->nrows = scr->scr_ri.ri_rows; 803 t->nrows = scr->scr_ri.ri_rows;
804 t->ncols = scr->scr_ri.ri_cols; 804 t->ncols = scr->scr_ri.ri_cols;
805 } 805 }
806 806
807 if (vd->active == NULL) { 807 if (vd->active == NULL) {
808 SCREEN_VISIBLE(scr); 808 SCREEN_VISIBLE(scr);
809 vd->active = scr; 809 vd->active = scr;
810 vd->currenttype = type; 810 vd->currenttype = type;
811 } 811 }
812 812
813 *cookiep = scr; 813 *cookiep = scr;
814 *curxp = scr->scr_ri.ri_ccol; 814 *curxp = scr->scr_ri.ri_ccol;
815 *curyp = scr->scr_ri.ri_crow; 815 *curyp = scr->scr_ri.ri_crow;
816 return 0; 816 return 0;
817} 817}
818 818
819static void 819static void
820vcons_free_screen(void *v, void *cookie) 820vcons_free_screen(void *v, void *cookie)
821{ 821{
822 struct vcons_data *vd = v; 822 struct vcons_data *vd = v;
823 struct vcons_screen *scr = cookie; 823 struct vcons_screen *scr = cookie;
824 824
825 vcons_lock(scr); 825 vcons_lock(scr);
826 /* there should be no rasops activity here */ 826 /* there should be no rasops activity here */
827 827
828 LIST_REMOVE(scr, next); 828 LIST_REMOVE(scr, next);
829 829
830 if ((scr->scr_flags & VCONS_SCREEN_IS_STATIC) == 0) { 830 if ((scr->scr_flags & VCONS_SCREEN_IS_STATIC) == 0) {
831 free(scr->scr_attrs, M_DEVBUF); 831 free(scr->scr_attrs, M_DEVBUF);
832 free(scr, M_DEVBUF); 832 free(scr, M_DEVBUF);
833 } else { 833 } else {
834 /* 834 /*
835 * maybe we should just restore the old rasops_info methods 835 * maybe we should just restore the old rasops_info methods
836 * and free the character/attribute buffer here? 836 * and free the character/attribute buffer here?
837 */ 837 */
838#ifdef VCONS_DEBUG 838#ifdef VCONS_DEBUG
839 panic("vcons_free_screen: console"); 839 panic("vcons_free_screen: console");
840#else 840#else
841 printf("vcons_free_screen: console\n"); 841 printf("vcons_free_screen: console\n");
842#endif 842#endif
843 } 843 }
844 844
845 if (vd->active == scr) 845 if (vd->active == scr)
846 vd->active = NULL; 846 vd->active = NULL;
847} 847}
848 848
849static int 849static int
850vcons_show_screen(void *v, void *cookie, int waitok, 850vcons_show_screen(void *v, void *cookie, int waitok,
851 void (*cb)(void *, int, int), void *cb_arg) 851 void (*cb)(void *, int, int), void *cb_arg)
852{ 852{
853 struct vcons_data *vd = v; 853 struct vcons_data *vd = v;
854 struct vcons_screen *scr; 854 struct vcons_screen *scr;
855 855
856 scr = cookie; 856 scr = cookie;
857 if (scr == vd->active) 857 if (scr == vd->active)
858 return 0; 858 return 0;
859 859
860 vd->wanted = scr; 860 vd->wanted = scr;
861 vd->switch_cb = cb; 861 vd->switch_cb = cb;
862 vd->switch_cb_arg = cb_arg; 862 vd->switch_cb_arg = cb_arg;
863 if (cb) { 863 if (cb) {
864 callout_schedule(&vd->switch_callout, 0); 864 callout_schedule(&vd->switch_callout, 0);
865 return EAGAIN; 865 return EAGAIN;
866 } 866 }
867 867
868 vcons_do_switch(vd); 868 vcons_do_switch(vd);
869 return 0; 869 return 0;
870} 870}
871 871
872/* wrappers for rasops_info methods */ 872/* wrappers for rasops_info methods */
873 873
874static void 874static void
875vcons_copycols_buffer(void *cookie, int row, int srccol, int dstcol, int ncols) 875vcons_copycols_buffer(void *cookie, int row, int srccol, int dstcol, int ncols)
876{ 876{
877 struct rasops_info *ri = cookie; 877 struct rasops_info *ri = cookie;
878 struct vcons_screen *scr = ri->ri_hw; 878 struct vcons_screen *scr = ri->ri_hw;
879 int from = srccol + row * ri->ri_cols; 879 int from = srccol + row * ri->ri_cols;
880 int to = dstcol + row * ri->ri_cols; 880 int to = dstcol + row * ri->ri_cols;
881 881
882#ifdef WSDISPLAY_SCROLLSUPPORT 882#ifdef WSDISPLAY_SCROLLSUPPORT
883 int offset; 883 int offset;
884 offset = scr->scr_offset_to_zero; 884 offset = scr->scr_offset_to_zero;
885 885
886 memmove(&scr->scr_attrs[offset + to], &scr->scr_attrs[offset + from], 886 memmove(&scr->scr_attrs[offset + to], &scr->scr_attrs[offset + from],
887 ncols * sizeof(long)); 887 ncols * sizeof(long));
888 memmove(&scr->scr_chars[offset + to], &scr->scr_chars[offset + from], 888 memmove(&scr->scr_chars[offset + to], &scr->scr_chars[offset + from],
889 ncols * sizeof(uint32_t)); 889 ncols * sizeof(uint32_t));
890#else 890#else
891 memmove(&scr->scr_attrs[to], &scr->scr_attrs[from], 891 memmove(&scr->scr_attrs[to], &scr->scr_attrs[from],
892 ncols * sizeof(long)); 892 ncols * sizeof(long));
893 memmove(&scr->scr_chars[to], &scr->scr_chars[from], 893 memmove(&scr->scr_chars[to], &scr->scr_chars[from],
894 ncols * sizeof(uint32_t)); 894 ncols * sizeof(uint32_t));
895#endif 895#endif
896 896
897#ifdef VCONS_DRAW_INTR 897#ifdef VCONS_DRAW_INTR
898 atomic_inc_uint(&scr->scr_dirty); 898 atomic_inc_uint(&scr->scr_dirty);
899#endif 899#endif
900} 900}
901 901
902static void 902static void
903vcons_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 903vcons_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
904{ 904{
905 struct rasops_info *ri = cookie; 905 struct rasops_info *ri = cookie;
906 struct vcons_screen *scr = ri->ri_hw; 906 struct vcons_screen *scr = ri->ri_hw;
907 907
908 vcons_copycols_buffer(cookie, row, srccol, dstcol, ncols); 908 vcons_copycols_buffer(cookie, row, srccol, dstcol, ncols);
909 909
910#if defined(VCONS_DRAW_INTR) 910#if defined(VCONS_DRAW_INTR)
911 if (scr->scr_vd->use_intr) 911 if (scr->scr_vd->use_intr)
912 return; 912 return;
913#endif 913#endif
914 914
915 vcons_lock(scr); 915 vcons_lock(scr);
916 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 916 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
917#if defined(VCONS_DRAW_INTR) 917#if defined(VCONS_DRAW_INTR)
918 vcons_update_screen(scr); 918 vcons_update_screen(scr);
919#else 919#else
920 scr->scr_vd->copycols(cookie, row, srccol, dstcol, ncols); 920 scr->scr_vd->copycols(cookie, row, srccol, dstcol, ncols);
921#endif 921#endif
922 } 922 }
923 vcons_unlock(scr); 923 vcons_unlock(scr);
924} 924}
925 925
926static void 926static void
927vcons_copycols_noread(void *cookie, int row, int srccol, int dstcol, int ncols) 927vcons_copycols_noread(void *cookie, int row, int srccol, int dstcol, int ncols)
928{ 928{
929 struct rasops_info *ri = cookie; 929 struct rasops_info *ri = cookie;
930 struct vcons_screen *scr = ri->ri_hw; 930 struct vcons_screen *scr = ri->ri_hw;
931#ifdef VCONS_DRAW_INTR 931#ifdef VCONS_DRAW_INTR
932 struct vcons_data *vd = scr->scr_vd; 932 struct vcons_data *vd = scr->scr_vd;
933#endif 933#endif
934 934
935 vcons_lock(scr); 935 vcons_lock(scr);
936 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 936 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
937 int pos, c, offset, ppos; 937 int pos, c, offset, ppos;
938 938
939#ifdef WSDISPLAY_SCROLLSUPPORT 939#ifdef WSDISPLAY_SCROLLSUPPORT
940 offset = scr->scr_current_offset; 940 offset = scr->scr_current_offset;
941#else 941#else
942 offset = 0; 942 offset = 0;
943#endif 943#endif
944 ppos = ri->ri_cols * row + dstcol; 944 ppos = ri->ri_cols * row + dstcol;
945 pos = ppos + offset; 945 pos = ppos + offset;
946 for (c = dstcol; c < (dstcol + ncols); c++) { 946 for (c = dstcol; c < (dstcol + ncols); c++) {
947#ifdef VCONS_DRAW_INTR 947#ifdef VCONS_DRAW_INTR
948 if ((scr->scr_chars[pos] != vd->chars[ppos]) || 948 if ((scr->scr_chars[pos] != vd->chars[ppos]) ||
949 (scr->scr_attrs[pos] != vd->attrs[ppos])) { 949 (scr->scr_attrs[pos] != vd->attrs[ppos])) {
950 scr->putchar(cookie, row, c,  950 scr->putchar(cookie, row, c,
951 scr->scr_chars[pos], scr->scr_attrs[pos]); 951 scr->scr_chars[pos], scr->scr_attrs[pos]);
952 vd->chars[ppos] = scr->scr_chars[pos]; 952 vd->chars[ppos] = scr->scr_chars[pos];
953 vd->attrs[ppos] = scr->scr_attrs[pos]; 953 vd->attrs[ppos] = scr->scr_attrs[pos];
954 } 954 }
955#else 955#else
956 scr->putchar(cookie, row, c, scr->scr_chars[pos], 956 scr->putchar(cookie, row, c, scr->scr_chars[pos],
957 scr->scr_attrs[pos]); 957 scr->scr_attrs[pos]);
958#endif 958#endif
959 pos++; 959 pos++;
960 ppos++; 960 ppos++;
961 } 961 }
962 if (ri->ri_crow == row &&  962 if (ri->ri_crow == row &&
963 (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols ))) 963 (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols )))
964 ri->ri_flg &= ~RI_CURSOR; 964 ri->ri_flg &= ~RI_CURSOR;
965 } 965 }
966 vcons_unlock(scr); 966 vcons_unlock(scr);
967} 967}
968 968
969static void 969static void
970vcons_erasecols_buffer(void *cookie, int row, int startcol, int ncols, long fillattr) 970vcons_erasecols_buffer(void *cookie, int row, int startcol, int ncols, long fillattr)
971{ 971{
972 struct rasops_info *ri = cookie; 972 struct rasops_info *ri = cookie;
973 struct vcons_screen *scr = ri->ri_hw; 973 struct vcons_screen *scr = ri->ri_hw;
974 int start = startcol + row * ri->ri_cols; 974 int start = startcol + row * ri->ri_cols;
975 int end = start + ncols, i; 975 int end = start + ncols, i;
976 976
977#ifdef WSDISPLAY_SCROLLSUPPORT 977#ifdef WSDISPLAY_SCROLLSUPPORT
978 int offset; 978 int offset;
979 offset = scr->scr_offset_to_zero; 979 offset = scr->scr_offset_to_zero;
980 980
981 for (i = start; i < end; i++) { 981 for (i = start; i < end; i++) {
982 scr->scr_attrs[offset + i] = fillattr; 982 scr->scr_attrs[offset + i] = fillattr;
983 scr->scr_chars[offset + i] = 0x20; 983 scr->scr_chars[offset + i] = 0x20;
984 } 984 }
985#else 985#else
986 for (i = start; i < end; i++) { 986 for (i = start; i < end; i++) {
987 scr->scr_attrs[i] = fillattr; 987 scr->scr_attrs[i] = fillattr;
988 scr->scr_chars[i] = 0x20; 988 scr->scr_chars[i] = 0x20;
989 } 989 }
990#endif 990#endif
991 991
992#ifdef VCONS_DRAW_INTR 992#ifdef VCONS_DRAW_INTR
993 atomic_inc_uint(&scr->scr_dirty); 993 atomic_inc_uint(&scr->scr_dirty);
994#endif 994#endif
995} 995}
996 996
997#ifdef VCONS_DRAW_INTR 997#ifdef VCONS_DRAW_INTR
998static void 998static void
999vcons_erasecols_cached(void *cookie, int row, int startcol, int ncols, long fillattr) 999vcons_erasecols_cached(void *cookie, int row, int startcol, int ncols, long fillattr)
1000{ 1000{
1001 struct rasops_info *ri = cookie; 1001 struct rasops_info *ri = cookie;
1002 struct vcons_screen *scr = ri->ri_hw; 1002 struct vcons_screen *scr = ri->ri_hw;
1003 struct vcons_data *vd = scr->scr_vd; 1003 struct vcons_data *vd = scr->scr_vd;
1004 int i, pos = row * ri->ri_cols + startcol; 1004 int i, pos = row * ri->ri_cols + startcol;
1005 1005
1006 for (i = pos; i < ncols; i++) { 1006 for (i = pos; i < ncols; i++) {
1007 vd->chars[i] = 0x20; 1007 vd->chars[i] = 0x20;
1008 vd->attrs[i] = fillattr; 1008 vd->attrs[i] = fillattr;
1009 } 1009 }
1010 vd->erasecols(cookie, row, startcol, ncols, fillattr); 1010 vd->erasecols(cookie, row, startcol, ncols, fillattr);
1011} 1011}
1012#endif 1012#endif
1013 1013
1014static void 1014static void
1015vcons_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1015vcons_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr)
1016{ 1016{
1017 struct rasops_info *ri = cookie; 1017 struct rasops_info *ri = cookie;
1018 struct vcons_screen *scr = ri->ri_hw; 1018 struct vcons_screen *scr = ri->ri_hw;
1019 1019
1020 vcons_erasecols_buffer(cookie, row, startcol, ncols, fillattr); 1020 vcons_erasecols_buffer(cookie, row, startcol, ncols, fillattr);
1021 1021
1022#if defined(VCONS_DRAW_INTR) 1022#if defined(VCONS_DRAW_INTR)
1023 if (scr->scr_vd->use_intr) 1023 if (scr->scr_vd->use_intr)
1024 return; 1024 return;
1025#endif 1025#endif
1026 1026
1027 vcons_lock(scr); 1027 vcons_lock(scr);
1028 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 1028 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
1029#ifdef VCONS_DRAW_INTR 1029#ifdef VCONS_DRAW_INTR
1030 vcons_erasecols_cached(cookie, row, startcol, ncols,  1030 vcons_erasecols_cached(cookie, row, startcol, ncols,
1031 fillattr); 1031 fillattr);
1032#else 1032#else
1033 scr->scr_vd->erasecols(cookie, row, startcol, ncols, fillattr); 1033 scr->scr_vd->erasecols(cookie, row, startcol, ncols, fillattr);
1034#endif  1034#endif
1035 } 1035 }
1036 vcons_unlock(scr); 1036 vcons_unlock(scr);
1037} 1037}
1038 1038
1039static void 1039static void
1040vcons_copyrows_buffer(void *cookie, int srcrow, int dstrow, int nrows) 1040vcons_copyrows_buffer(void *cookie, int srcrow, int dstrow, int nrows)
1041{ 1041{
1042 struct rasops_info *ri = cookie; 1042 struct rasops_info *ri = cookie;
1043 struct vcons_screen *scr = ri->ri_hw; 1043 struct vcons_screen *scr = ri->ri_hw;
1044 int from, to, len; 1044 int from, to, len;
1045 1045
1046#ifdef WSDISPLAY_SCROLLSUPPORT 1046#ifdef WSDISPLAY_SCROLLSUPPORT
1047 int offset; 1047 int offset;
1048 offset = scr->scr_offset_to_zero; 1048 offset = scr->scr_offset_to_zero;
1049 1049
1050 /* do we need to scroll the back buffer? */ 1050 /* do we need to scroll the back buffer? */
1051 if (dstrow == 0) { 1051 if (dstrow == 0) {
1052 from = ri->ri_cols * srcrow; 1052 from = ri->ri_cols * srcrow;
1053 to = ri->ri_cols * dstrow; 1053 to = ri->ri_cols * dstrow;
1054 1054
1055 memmove(&scr->scr_attrs[to], &scr->scr_attrs[from], 1055 memmove(&scr->scr_attrs[to], &scr->scr_attrs[from],
1056 scr->scr_offset_to_zero * sizeof(long)); 1056 scr->scr_offset_to_zero * sizeof(long));
1057 memmove(&scr->scr_chars[to], &scr->scr_chars[from], 1057 memmove(&scr->scr_chars[to], &scr->scr_chars[from],
1058 scr->scr_offset_to_zero * sizeof(uint32_t)); 1058 scr->scr_offset_to_zero * sizeof(uint32_t));
1059 } 1059 }
1060 from = ri->ri_cols * srcrow + offset; 1060 from = ri->ri_cols * srcrow + offset;
1061 to = ri->ri_cols * dstrow + offset; 1061 to = ri->ri_cols * dstrow + offset;
1062 len = ri->ri_cols * nrows;  1062 len = ri->ri_cols * nrows;
1063  1063
1064#else 1064#else
1065 from = ri->ri_cols * srcrow; 1065 from = ri->ri_cols * srcrow;
1066 to = ri->ri_cols * dstrow; 1066 to = ri->ri_cols * dstrow;
1067 len = ri->ri_cols * nrows; 1067 len = ri->ri_cols * nrows;
1068#endif 1068#endif
1069 memmove(&scr->scr_attrs[to], &scr->scr_attrs[from], 1069 memmove(&scr->scr_attrs[to], &scr->scr_attrs[from],
1070 len * sizeof(long)); 1070 len * sizeof(long));
1071 memmove(&scr->scr_chars[to], &scr->scr_chars[from], 1071 memmove(&scr->scr_chars[to], &scr->scr_chars[from],
1072 len * sizeof(uint32_t)); 1072 len * sizeof(uint32_t));
1073 1073
1074#ifdef VCONS_DRAW_INTR 1074#ifdef VCONS_DRAW_INTR
1075 atomic_inc_uint(&scr->scr_dirty); 1075 atomic_inc_uint(&scr->scr_dirty);
1076#endif 1076#endif
1077} 1077}
1078 1078
1079static void 1079static void
1080vcons_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1080vcons_copyrows(void *cookie, int srcrow, int dstrow, int nrows)
1081{ 1081{
1082 struct rasops_info *ri = cookie; 1082 struct rasops_info *ri = cookie;
1083 struct vcons_screen *scr = ri->ri_hw; 1083 struct vcons_screen *scr = ri->ri_hw;
1084 1084
1085 vcons_copyrows_buffer(cookie, srcrow, dstrow, nrows); 1085 vcons_copyrows_buffer(cookie, srcrow, dstrow, nrows);
1086 1086
1087#if defined(VCONS_DRAW_INTR) 1087#if defined(VCONS_DRAW_INTR)
1088 if (scr->scr_vd->use_intr) 1088 if (scr->scr_vd->use_intr)
1089 return; 1089 return;
1090#endif 1090#endif
1091 1091
1092 vcons_lock(scr); 1092 vcons_lock(scr);
1093 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 1093 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
1094#if defined(VCONS_DRAW_INTR) 1094#if defined(VCONS_DRAW_INTR)
1095 vcons_update_screen(scr); 1095 vcons_update_screen(scr);
1096#else 1096#else
1097 scr->scr_vd->copyrows(cookie, srcrow, dstrow, nrows); 1097 scr->scr_vd->copyrows(cookie, srcrow, dstrow, nrows);
1098#endif 1098#endif
1099 } 1099 }
1100 vcons_unlock(scr); 1100 vcons_unlock(scr);
1101} 1101}
1102 1102
1103static void 1103static void
1104vcons_copyrows_noread(void *cookie, int srcrow, int dstrow, int nrows) 1104vcons_copyrows_noread(void *cookie, int srcrow, int dstrow, int nrows)
1105{ 1105{
1106 struct rasops_info *ri = cookie; 1106 struct rasops_info *ri = cookie;
1107 struct vcons_screen *scr = ri->ri_hw; 1107 struct vcons_screen *scr = ri->ri_hw;
1108#ifdef VCONS_DRAW_INTR 1108#ifdef VCONS_DRAW_INTR
1109 struct vcons_data *vd = scr->scr_vd; 1109 struct vcons_data *vd = scr->scr_vd;
1110#endif 1110#endif
1111 vcons_lock(scr); 1111 vcons_lock(scr);
1112 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 1112 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
1113 int pos, l, c, offset, ppos; 1113 int pos, l, c, offset, ppos;
1114 1114
1115#ifdef WSDISPLAY_SCROLLSUPPORT 1115#ifdef WSDISPLAY_SCROLLSUPPORT
1116 offset = scr->scr_current_offset; 1116 offset = scr->scr_current_offset;
1117#else 1117#else
1118 offset = 0; 1118 offset = 0;
1119#endif 1119#endif
1120 ppos = ri->ri_cols * dstrow; 1120 ppos = ri->ri_cols * dstrow;
1121 pos = ppos + offset; 1121 pos = ppos + offset;
1122 for (l = dstrow; l < (dstrow + nrows); l++) { 1122 for (l = dstrow; l < (dstrow + nrows); l++) {
1123 for (c = 0; c < ri->ri_cols; c++) { 1123 for (c = 0; c < ri->ri_cols; c++) {
1124#ifdef VCONS_DRAW_INTR 1124#ifdef VCONS_DRAW_INTR
1125 if ((scr->scr_chars[pos] != vd->chars[ppos]) || 1125 if ((scr->scr_chars[pos] != vd->chars[ppos]) ||
1126 (scr->scr_attrs[pos] != vd->attrs[ppos])) { 1126 (scr->scr_attrs[pos] != vd->attrs[ppos])) {
1127 scr->putchar(cookie, l, c,  1127 scr->putchar(cookie, l, c,
1128 scr->scr_chars[pos], scr->scr_attrs[pos]); 1128 scr->scr_chars[pos], scr->scr_attrs[pos]);
1129 vd->chars[ppos] = scr->scr_chars[pos]; 1129 vd->chars[ppos] = scr->scr_chars[pos];
1130 vd->attrs[ppos] = scr->scr_attrs[pos]; 1130 vd->attrs[ppos] = scr->scr_attrs[pos];
1131 } 1131 }
1132#else 1132#else
1133 scr->putchar(cookie, l, c, scr->scr_chars[pos], 1133 scr->putchar(cookie, l, c, scr->scr_chars[pos],
1134 scr->scr_attrs[pos]); 1134 scr->scr_attrs[pos]);
1135#endif 1135#endif
1136 pos++; 1136 pos++;
1137 ppos++; 1137 ppos++;
1138 } 1138 }
1139 } 1139 }
1140 if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows)) 1140 if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows))
1141 ri->ri_flg &= ~RI_CURSOR; 1141 ri->ri_flg &= ~RI_CURSOR;
1142 } 1142 }
1143 vcons_unlock(scr); 1143 vcons_unlock(scr);
1144} 1144}
1145 1145
1146static void 1146static void
1147vcons_eraserows_buffer(void *cookie, int row, int nrows, long fillattr) 1147vcons_eraserows_buffer(void *cookie, int row, int nrows, long fillattr)
1148{ 1148{
1149 struct rasops_info *ri = cookie; 1149 struct rasops_info *ri = cookie;
1150 struct vcons_screen *scr = ri->ri_hw; 1150 struct vcons_screen *scr = ri->ri_hw;
1151 int start, end, i; 1151 int start, end, i;
1152 1152
1153#ifdef WSDISPLAY_SCROLLSUPPORT 1153#ifdef WSDISPLAY_SCROLLSUPPORT
1154 int offset; 1154 int offset;
1155 offset = scr->scr_offset_to_zero; 1155 offset = scr->scr_offset_to_zero;
1156 1156
1157 start = ri->ri_cols * row + offset; 1157 start = ri->ri_cols * row + offset;
1158 end = ri->ri_cols * (row + nrows) + offset; 1158 end = ri->ri_cols * (row + nrows) + offset;
1159#else 1159#else
1160 start = ri->ri_cols * row; 1160 start = ri->ri_cols * row;
1161 end = ri->ri_cols * (row + nrows); 1161 end = ri->ri_cols * (row + nrows);
1162#endif 1162#endif
1163 1163
1164 for (i = start; i < end; i++) { 1164 for (i = start; i < end; i++) {
1165 scr->scr_attrs[i] = fillattr; 1165 scr->scr_attrs[i] = fillattr;
1166 scr->scr_chars[i] = 0x20; 1166 scr->scr_chars[i] = 0x20;
1167 } 1167 }
1168 1168
1169#ifdef VCONS_DRAW_INTR 1169#ifdef VCONS_DRAW_INTR
1170 atomic_inc_uint(&scr->scr_dirty); 1170 atomic_inc_uint(&scr->scr_dirty);
1171#endif 1171#endif
1172} 1172}
1173 1173
1174#ifdef VCONS_DRAW_INTR 1174#ifdef VCONS_DRAW_INTR
1175static void 1175static void
1176vcons_eraserows_cached(void *cookie, int row, int nrows, long fillattr) 1176vcons_eraserows_cached(void *cookie, int row, int nrows, long fillattr)
1177{ 1177{
1178 struct rasops_info *ri = cookie; 1178 struct rasops_info *ri = cookie;
1179 struct vcons_screen *scr = ri->ri_hw; 1179 struct vcons_screen *scr = ri->ri_hw;
1180 struct vcons_data *vd = scr->scr_vd; 1180 struct vcons_data *vd = scr->scr_vd;
1181 int i, pos = row * ri->ri_cols, end = (row+nrows) * ri->ri_cols; 1181 int i, pos = row * ri->ri_cols, end = (row+nrows) * ri->ri_cols;
1182 1182
1183 for (i = pos; i < end; i++) { 1183 for (i = pos; i < end; i++) {
1184 vd->chars[i] = 0x20; 1184 vd->chars[i] = 0x20;
1185 vd->attrs[i] = fillattr; 1185 vd->attrs[i] = fillattr;
1186 } 1186 }
1187 vd->eraserows(cookie, row, nrows, fillattr); 1187 vd->eraserows(cookie, row, nrows, fillattr);
1188} 1188}
1189#endif 1189#endif
1190 1190
1191static void 1191static void
1192vcons_eraserows(void *cookie, int row, int nrows, long fillattr) 1192vcons_eraserows(void *cookie, int row, int nrows, long fillattr)
1193{ 1193{
1194 struct rasops_info *ri = cookie; 1194 struct rasops_info *ri = cookie;
1195 struct vcons_screen *scr = ri->ri_hw; 1195 struct vcons_screen *scr = ri->ri_hw;
1196 1196
1197 vcons_eraserows_buffer(cookie, row, nrows, fillattr); 1197 vcons_eraserows_buffer(cookie, row, nrows, fillattr);
1198 1198
1199#if defined(VCONS_DRAW_INTR) 1199#if defined(VCONS_DRAW_INTR)
1200 if (scr->scr_vd->use_intr) 1200 if (scr->scr_vd->use_intr)
1201 return; 1201 return;
1202#endif 1202#endif
1203 1203
1204 vcons_lock(scr); 1204 vcons_lock(scr);
1205 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 1205 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
1206#ifdef VCONS_DRAW_INTR 1206#ifdef VCONS_DRAW_INTR
1207 vcons_eraserows_cached(cookie, row, nrows, fillattr); 1207 vcons_eraserows_cached(cookie, row, nrows, fillattr);
1208#else 1208#else
1209 scr->scr_vd->eraserows(cookie, row, nrows, fillattr); 1209 scr->scr_vd->eraserows(cookie, row, nrows, fillattr);
1210#endif 1210#endif
1211 } 1211 }
1212 vcons_unlock(scr); 1212 vcons_unlock(scr);
1213} 1213}
1214 1214
1215static void 1215static void
1216vcons_putchar_buffer(void *cookie, int row, int col, u_int c, long attr) 1216vcons_putchar_buffer(void *cookie, int row, int col, u_int c, long attr)
1217{ 1217{
1218 struct rasops_info *ri = cookie; 1218 struct rasops_info *ri = cookie;
1219 struct vcons_screen *scr = ri->ri_hw; 1219 struct vcons_screen *scr = ri->ri_hw;
1220 int pos; 1220 int pos;
1221  1221
1222#ifdef WSDISPLAY_SCROLLSUPPORT 1222#ifdef WSDISPLAY_SCROLLSUPPORT
1223 int offset; 1223 int offset;
1224 offset = scr->scr_offset_to_zero; 1224 offset = scr->scr_offset_to_zero;
1225 1225
1226 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) &&  1226 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) &&
1227 (col < ri->ri_cols)) { 1227 (col < ri->ri_cols)) {
1228 pos = col + row * ri->ri_cols; 1228 pos = col + row * ri->ri_cols;
1229 scr->scr_attrs[pos + offset] = attr; 1229 scr->scr_attrs[pos + offset] = attr;
1230 scr->scr_chars[pos + offset] = c; 1230 scr->scr_chars[pos + offset] = c;
1231 } 1231 }
1232#else 1232#else
1233 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) &&  1233 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) &&
1234 (col < ri->ri_cols)) { 1234 (col < ri->ri_cols)) {
1235 pos = col + row * ri->ri_cols; 1235 pos = col + row * ri->ri_cols;
1236 scr->scr_attrs[pos] = attr; 1236 scr->scr_attrs[pos] = attr;
1237 scr->scr_chars[pos] = c; 1237 scr->scr_chars[pos] = c;
1238 } 1238 }
1239#endif 1239#endif
1240 1240
1241#ifdef VCONS_DRAW_INTR 1241#ifdef VCONS_DRAW_INTR
1242 atomic_inc_uint(&scr->scr_dirty); 1242 atomic_inc_uint(&scr->scr_dirty);
1243#endif 1243#endif
1244} 1244}
1245 1245
1246#ifdef VCONS_DRAW_INTR 1246#ifdef VCONS_DRAW_INTR
1247static void 1247static void
1248vcons_putchar_cached(void *cookie, int row, int col, u_int c, long attr) 1248vcons_putchar_cached(void *cookie, int row, int col, u_int c, long attr)
1249{ 1249{
1250 struct rasops_info *ri = cookie; 1250 struct rasops_info *ri = cookie;
1251 struct vcons_screen *scr = ri->ri_hw; 1251 struct vcons_screen *scr = ri->ri_hw;
1252 struct vcons_data *vd = scr->scr_vd; 1252 struct vcons_data *vd = scr->scr_vd;
1253 int pos = row * ri->ri_cols + col; 1253 int pos = row * ri->ri_cols + col;
1254 1254
1255 if ((vd->chars == NULL) || (vd->attrs == NULL)) { 1255 if ((vd->chars == NULL) || (vd->attrs == NULL)) {
1256 scr->putchar(cookie, row, col, c, attr); 1256 scr->putchar(cookie, row, col, c, attr);
1257 return; 1257 return;
1258 } 1258 }
1259 if ((vd->chars[pos] != c) || (vd->attrs[pos] != attr)) { 1259 if ((vd->chars[pos] != c) || (vd->attrs[pos] != attr)) {
1260 vd->attrs[pos] = attr; 1260 vd->attrs[pos] = attr;
1261 vd->chars[pos] = c; 1261 vd->chars[pos] = c;
1262 scr->putchar(cookie, row, col, c, attr); 1262 scr->putchar(cookie, row, col, c, attr);
1263 } 1263 }
1264} 1264}
1265#endif 1265#endif
1266 1266
1267static void 1267static void
1268vcons_putchar(void *cookie, int row, int col, u_int c, long attr) 1268vcons_putchar(void *cookie, int row, int col, u_int c, long attr)
1269{ 1269{
1270 struct rasops_info *ri = cookie; 1270 struct rasops_info *ri = cookie;
1271 struct vcons_screen *scr = ri->ri_hw; 1271 struct vcons_screen *scr = ri->ri_hw;
1272  1272
1273 vcons_putchar_buffer(cookie, row, col, c, attr); 1273 vcons_putchar_buffer(cookie, row, col, c, attr);
1274 1274
1275#if defined(VCONS_DRAW_INTR) 1275#if defined(VCONS_DRAW_INTR)
1276 if (scr->scr_vd->use_intr) 1276 if (scr->scr_vd->use_intr)
1277 return; 1277 return;
1278#endif 1278#endif
1279 1279
1280 vcons_lock(scr); 1280 vcons_lock(scr);
1281 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 1281 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
1282#ifdef VCONS_DRAW_INTR 1282#ifdef VCONS_DRAW_INTR
1283 vcons_putchar_cached(cookie, row, col, c, attr); 1283 vcons_putchar_cached(cookie, row, col, c, attr);
1284#else 1284#else
1285 if (row == ri->ri_crow && col == ri->ri_ccol) { 1285 if (row == ri->ri_crow && col == ri->ri_ccol) {
1286 ri->ri_flg &= ~RI_CURSOR; 1286 ri->ri_flg &= ~RI_CURSOR;
1287 } 1287 }
1288 scr->putchar(cookie, row, col, c, attr); 1288 scr->putchar(cookie, row, col, c, attr);
1289#endif 1289#endif
1290 } 1290 }
1291 vcons_unlock(scr); 1291 vcons_unlock(scr);
1292} 1292}
1293 1293
1294static void 1294static void
1295vcons_cursor(void *cookie, int on, int row, int col) 1295vcons_cursor(void *cookie, int on, int row, int col)
1296{ 1296{
1297 struct rasops_info *ri = cookie; 1297 struct rasops_info *ri = cookie;
1298 struct vcons_screen *scr = ri->ri_hw; 1298 struct vcons_screen *scr = ri->ri_hw;
1299 1299
1300 1300
1301#if defined(VCONS_DRAW_INTR) 1301#if defined(VCONS_DRAW_INTR)
1302 if (scr->scr_vd->use_intr) { 1302 if (scr->scr_vd->use_intr) {
1303 vcons_lock(scr); 1303 vcons_lock(scr);
1304 if (scr->scr_ri.ri_crow != row || scr->scr_ri.ri_ccol != col) { 1304 if (scr->scr_ri.ri_crow != row || scr->scr_ri.ri_ccol != col) {
1305 scr->scr_ri.ri_crow = row; 1305 scr->scr_ri.ri_crow = row;
1306 scr->scr_ri.ri_ccol = col; 1306 scr->scr_ri.ri_ccol = col;
1307 atomic_inc_uint(&scr->scr_dirty); 1307 atomic_inc_uint(&scr->scr_dirty);
1308 } 1308 }
1309 vcons_unlock(scr); 1309 vcons_unlock(scr);
1310 return; 1310 return;
1311 } 1311 }
1312#endif 1312#endif
1313 1313
1314 vcons_lock(scr); 1314 vcons_lock(scr);
1315 1315
1316 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) { 1316 if (SCREEN_IS_VISIBLE(scr) && SCREEN_CAN_DRAW(scr)) {
1317 scr->scr_vd->cursor(cookie, on, row, col); 1317 scr->scr_vd->cursor(cookie, on, row, col);
1318 } else { 1318 } else {
1319 scr->scr_ri.ri_crow = row; 1319 scr->scr_ri.ri_crow = row;
1320 scr->scr_ri.ri_ccol = col; 1320 scr->scr_ri.ri_ccol = col;
1321 } 1321 }
1322 vcons_unlock(scr); 1322 vcons_unlock(scr);
1323} 1323}
1324 1324
1325static void 1325static void
1326vcons_cursor_noread(void *cookie, int on, int row, int col) 1326vcons_cursor_noread(void *cookie, int on, int row, int col)
1327{ 1327{
1328 struct rasops_info *ri = cookie; 1328 struct rasops_info *ri = cookie;
1329 struct vcons_screen *scr = ri->ri_hw; 1329 struct vcons_screen *scr = ri->ri_hw;
1330 int offset = 0, ofs; 1330 int offset = 0, ofs;
1331 1331
1332#ifdef WSDISPLAY_SCROLLSUPPORT 1332#ifdef WSDISPLAY_SCROLLSUPPORT
1333 offset = scr->scr_current_offset; 1333 offset = scr->scr_current_offset;
1334#endif 1334#endif
1335 ofs = offset + ri->ri_crow * ri->ri_cols + ri->ri_ccol; 1335 ofs = offset + ri->ri_crow * ri->ri_cols + ri->ri_ccol;
1336 if ((ri->ri_flg & RI_CURSOR) &&  1336 if ((ri->ri_flg & RI_CURSOR) &&
1337 ((scr->scr_flags & VCONS_DONT_READ) != VCONS_DONT_READ)) { 1337 (((scr->scr_flags & VCONS_DONT_READ) != VCONS_DONT_READ) || on)) {
1338 scr->putchar(cookie, ri->ri_crow, ri->ri_ccol, 1338 scr->putchar(cookie, ri->ri_crow, ri->ri_ccol,
1339 scr->scr_chars[ofs], scr->scr_attrs[ofs]); 1339 scr->scr_chars[ofs], scr->scr_attrs[ofs]);
1340 ri->ri_flg &= ~RI_CURSOR; 1340 ri->ri_flg &= ~RI_CURSOR;
1341 } 1341 }
1342 ri->ri_crow = row; 1342 ri->ri_crow = row;
1343 ri->ri_ccol = col; 1343 ri->ri_ccol = col;
1344 ofs = offset + ri->ri_crow * ri->ri_cols + ri->ri_ccol; 1344 ofs = offset + ri->ri_crow * ri->ri_cols + ri->ri_ccol;
1345 if (on) { 1345 if (on) {
1346 scr->putchar(cookie, row, col, scr->scr_chars[ofs], 1346 scr->putchar(cookie, row, col, scr->scr_chars[ofs],
1347#ifdef VCONS_DEBUG_CURSOR_NOREAD 1347#ifdef VCONS_DEBUG_CURSOR_NOREAD
1348 /* draw a red cursor so we can tell which cursor()  1348 /* draw a red cursor so we can tell which cursor()
1349 * implementation is being used */ 1349 * implementation is being used */
1350 ((scr->scr_attrs[ofs] & 0xff00ffff) ^ 0x0f000000) | 1350 ((scr->scr_attrs[ofs] & 0xff00ffff) ^ 0x0f000000) |
1351 0x00010000); 1351 0x00010000);
1352#else 1352#else
1353 scr->scr_attrs[ofs] ^ 0x0f0f0000); 1353 scr->scr_attrs[ofs] ^ 0x0f0f0000);
1354#endif 1354#endif
1355 ri->ri_flg |= RI_CURSOR; 1355 ri->ri_flg |= RI_CURSOR;
1356 } 1356 }
1357} 1357}
1358 1358
1359/* methods to read/write characters via ioctl() */ 1359/* methods to read/write characters via ioctl() */
1360 1360
1361static int 1361static int
1362vcons_putwschar(struct vcons_screen *scr, struct wsdisplay_char *wsc) 1362vcons_putwschar(struct vcons_screen *scr, struct wsdisplay_char *wsc)
1363{ 1363{
1364 long attr; 1364 long attr;
1365 struct rasops_info *ri; 1365 struct rasops_info *ri;
1366 int error; 1366 int error;
1367 1367
1368 KASSERT(scr != NULL && wsc != NULL); 1368 KASSERT(scr != NULL && wsc != NULL);
1369 1369
1370 ri = &scr->scr_ri; 1370 ri = &scr->scr_ri;
1371 1371
1372 /* allow col as linear index if row == 0 */ 1372 /* allow col as linear index if row == 0 */
1373 if (wsc->row == 0) { 1373 if (wsc->row == 0) {
1374 if (wsc->col < 0 || wsc->col > (ri->ri_cols * ri->ri_rows)) 1374 if (wsc->col < 0 || wsc->col > (ri->ri_cols * ri->ri_rows))
1375 return EINVAL; 1375 return EINVAL;
1376 int rem; 1376 int rem;
1377 rem = wsc->col % ri->ri_cols; 1377 rem = wsc->col % ri->ri_cols;
1378 wsc->row = wsc->col / ri->ri_cols; 1378 wsc->row = wsc->col / ri->ri_cols;
1379 DPRINTF("off %d -> %d, %d\n", wsc->col, rem, wsc->row); 1379 DPRINTF("off %d -> %d, %d\n", wsc->col, rem, wsc->row);
1380 wsc->col = rem; 1380 wsc->col = rem;
1381 } else { 1381 } else {
1382 if (__predict_false(wsc->col < 0 || wsc->col >= ri->ri_cols)) 1382 if (__predict_false(wsc->col < 0 || wsc->col >= ri->ri_cols))
1383 return (EINVAL); 1383 return (EINVAL);
1384  1384
1385 if (__predict_false(wsc->row < 0 || wsc->row >= ri->ri_rows)) 1385 if (__predict_false(wsc->row < 0 || wsc->row >= ri->ri_rows))
1386 return (EINVAL); 1386 return (EINVAL);
1387 } 1387 }
1388 1388
1389 error = ri->ri_ops.allocattr(ri, wsc->foreground, 1389 error = ri->ri_ops.allocattr(ri, wsc->foreground,
1390 wsc->background, wsc->flags, &attr); 1390 wsc->background, wsc->flags, &attr);
1391 if (error) 1391 if (error)
1392 return error; 1392 return error;
1393 vcons_putchar(ri, wsc->row, wsc->col, wsc->letter, attr); 1393 vcons_putchar(ri, wsc->row, wsc->col, wsc->letter, attr);
1394#ifdef VCONS_DEBUG 1394#ifdef VCONS_DEBUG
1395 printf("vcons_putwschar(%d, %d, %x, %lx\n", wsc->row, wsc->col, 1395 printf("vcons_putwschar(%d, %d, %x, %lx\n", wsc->row, wsc->col,
1396 wsc->letter, attr); 1396 wsc->letter, attr);
1397#endif 1397#endif
1398 return 0; 1398 return 0;
1399} 1399}
1400 1400
1401static int 1401static int
1402vcons_getwschar(struct vcons_screen *scr, struct wsdisplay_char *wsc) 1402vcons_getwschar(struct vcons_screen *scr, struct wsdisplay_char *wsc)
1403{ 1403{
1404 int offset; 1404 int offset;
1405 long attr; 1405 long attr;
1406 struct rasops_info *ri; 1406 struct rasops_info *ri;
1407 1407
1408 KASSERT(scr != NULL && wsc != NULL); 1408 KASSERT(scr != NULL && wsc != NULL);
1409 1409
1410 ri = &scr->scr_ri; 1410 ri = &scr->scr_ri;
1411 1411
1412 /* allow col as linear index if row == 0 */ 1412 /* allow col as linear index if row == 0 */
1413 if (wsc->row == 0) { 1413 if (wsc->row == 0) {
1414 if (wsc->col < 0 || wsc->col > (ri->ri_cols * ri->ri_rows)) 1414 if (wsc->col < 0 || wsc->col > (ri->ri_cols * ri->ri_rows))
1415 return EINVAL; 1415 return EINVAL;
1416 int rem; 1416 int rem;
1417 rem = wsc->col % ri->ri_cols; 1417 rem = wsc->col % ri->ri_cols;
1418 wsc->row = wsc->col / ri->ri_cols; 1418 wsc->row = wsc->col / ri->ri_cols;
1419 DPRINTF("off %d -> %d, %d\n", wsc->col, rem, wsc->row); 1419 DPRINTF("off %d -> %d, %d\n", wsc->col, rem, wsc->row);
1420 wsc->col = rem; 1420 wsc->col = rem;
1421 } else { 1421 } else {
1422 if (__predict_false(wsc->col < 0 || wsc->col >= ri->ri_cols)) 1422 if (__predict_false(wsc->col < 0 || wsc->col >= ri->ri_cols))
1423 return (EINVAL); 1423 return (EINVAL);
1424  1424
1425 if (__predict_false(wsc->row < 0 || wsc->row >= ri->ri_rows)) 1425 if (__predict_false(wsc->row < 0 || wsc->row >= ri->ri_rows))
1426 return (EINVAL); 1426 return (EINVAL);
1427 } 1427 }
1428 1428
1429 offset = ri->ri_cols * wsc->row + wsc->col; 1429 offset = ri->ri_cols * wsc->row + wsc->col;
1430#ifdef WSDISPLAY_SCROLLSUPPORT 1430#ifdef WSDISPLAY_SCROLLSUPPORT
1431 offset += scr->scr_offset_to_zero; 1431 offset += scr->scr_offset_to_zero;
1432#endif 1432#endif
1433 wsc->letter = scr->scr_chars[offset]; 1433 wsc->letter = scr->scr_chars[offset];
1434 attr = scr->scr_attrs[offset]; 1434 attr = scr->scr_attrs[offset];
1435 1435
1436 /*  1436 /*
1437 * this is ugly. We need to break up an attribute into colours and 1437 * this is ugly. We need to break up an attribute into colours and
1438 * flags but there's no rasops method to do that so we must rely on 1438 * flags but there's no rasops method to do that so we must rely on
1439 * the 'canonical' encoding. 1439 * the 'canonical' encoding.
1440 */ 1440 */
1441#ifdef VCONS_DEBUG 1441#ifdef VCONS_DEBUG
1442 printf("vcons_getwschar: %d, %d, %x, %lx\n", wsc->row, 1442 printf("vcons_getwschar: %d, %d, %x, %lx\n", wsc->row,
1443 wsc->col, wsc->letter, attr); 1443 wsc->col, wsc->letter, attr);
1444#endif 1444#endif
1445 wsc->foreground = (attr >> 24) & 0xff; 1445 wsc->foreground = (attr >> 24) & 0xff;
1446 wsc->background = (attr >> 16) & 0xff; 1446 wsc->background = (attr >> 16) & 0xff;
1447 wsc->flags = attr & 0xff; 1447 wsc->flags = attr & 0xff;
1448 return 0; 1448 return 0;
1449} 1449}
1450 1450
1451#ifdef WSDISPLAY_SCROLLSUPPORT 1451#ifdef WSDISPLAY_SCROLLSUPPORT
1452 1452
1453static void 1453static void
1454vcons_scroll(void *cookie, void *vs, int where) 1454vcons_scroll(void *cookie, void *vs, int where)
1455{ 1455{
1456 struct vcons_screen *scr = vs; 1456 struct vcons_screen *scr = vs;
1457 1457
1458 if (where == 0) { 1458 if (where == 0) {
1459 scr->scr_line_wanted = 0; 1459 scr->scr_line_wanted = 0;
1460 } else { 1460 } else {
1461 scr->scr_line_wanted = scr->scr_line_wanted - where; 1461 scr->scr_line_wanted = scr->scr_line_wanted - where;
1462 if (scr->scr_line_wanted < 0) 1462 if (scr->scr_line_wanted < 0)
1463 scr->scr_line_wanted = 0; 1463 scr->scr_line_wanted = 0;
1464 if (scr->scr_line_wanted > scr->scr_lines_in_buffer) 1464 if (scr->scr_line_wanted > scr->scr_lines_in_buffer)
1465 scr->scr_line_wanted = scr->scr_lines_in_buffer; 1465 scr->scr_line_wanted = scr->scr_lines_in_buffer;
1466 } 1466 }
1467 1467
1468 if (scr->scr_line_wanted != scr->scr_current_line) { 1468 if (scr->scr_line_wanted != scr->scr_current_line) {
1469 1469
1470 vcons_do_scroll(scr); 1470 vcons_do_scroll(scr);
1471 } 1471 }
1472} 1472}
1473 1473
1474static void 1474static void
1475vcons_do_scroll(struct vcons_screen *scr) 1475vcons_do_scroll(struct vcons_screen *scr)
1476{ 1476{
1477 int dist, from, to, num; 1477 int dist, from, to, num;
1478 int r_offset, r_start; 1478 int r_offset, r_start;
1479 int i, j; 1479 int i, j;
1480 1480
1481 if (scr->scr_line_wanted == scr->scr_current_line) 1481 if (scr->scr_line_wanted == scr->scr_current_line)
1482 return; 1482 return;
1483 dist = scr->scr_line_wanted - scr->scr_current_line; 1483 dist = scr->scr_line_wanted - scr->scr_current_line;
1484 scr->scr_current_line = scr->scr_line_wanted; 1484 scr->scr_current_line = scr->scr_line_wanted;
1485 scr->scr_current_offset = scr->scr_ri.ri_cols * 1485 scr->scr_current_offset = scr->scr_ri.ri_cols *
1486 (scr->scr_lines_in_buffer - scr->scr_current_line); 1486 (scr->scr_lines_in_buffer - scr->scr_current_line);
1487 if (abs(dist) >= scr->scr_ri.ri_rows) { 1487 if (abs(dist) >= scr->scr_ri.ri_rows) {
1488 vcons_redraw_screen(scr); 1488 vcons_redraw_screen(scr);
1489 return; 1489 return;
1490 } 1490 }
1491 /* scroll and redraw only what we really have to */ 1491 /* scroll and redraw only what we really have to */
1492 if (dist > 0) { 1492 if (dist > 0) {
1493 /* we scroll down */ 1493 /* we scroll down */
1494 from = 0; 1494 from = 0;
1495 to = dist; 1495 to = dist;
1496 num = scr->scr_ri.ri_rows - dist; 1496 num = scr->scr_ri.ri_rows - dist;
1497 /* now the redraw parameters */ 1497 /* now the redraw parameters */
1498 r_offset = scr->scr_current_offset; 1498 r_offset = scr->scr_current_offset;
1499 r_start = 0; 1499 r_start = 0;
1500 } else { 1500 } else {
1501 /* scrolling up */ 1501 /* scrolling up */
1502 to = 0; 1502 to = 0;
1503 from = -dist; 1503 from = -dist;
1504 num = scr->scr_ri.ri_rows + dist; 1504 num = scr->scr_ri.ri_rows + dist;
1505 r_offset = scr->scr_current_offset + num * scr->scr_ri.ri_cols; 1505 r_offset = scr->scr_current_offset + num * scr->scr_ri.ri_cols;
1506 r_start = num; 1506 r_start = num;
1507 } 1507 }
1508 scr->scr_vd->copyrows(scr, from, to, num); 1508 scr->scr_vd->copyrows(scr, from, to, num);
1509 for (i = 0; i < abs(dist); i++) { 1509 for (i = 0; i < abs(dist); i++) {
1510 for (j = 0; j < scr->scr_ri.ri_cols; j++) { 1510 for (j = 0; j < scr->scr_ri.ri_cols; j++) {
1511#ifdef VCONS_DRAW_INTR 1511#ifdef VCONS_DRAW_INTR
1512 vcons_putchar_cached(scr, i + r_start, j, 1512 vcons_putchar_cached(scr, i + r_start, j,
1513 scr->scr_chars[r_offset], 1513 scr->scr_chars[r_offset],
1514 scr->scr_attrs[r_offset]); 1514 scr->scr_attrs[r_offset]);
1515#else 1515#else
1516 scr->putchar(scr, i + r_start, j, 1516 scr->putchar(scr, i + r_start, j,
1517 scr->scr_chars[r_offset], 1517 scr->scr_chars[r_offset],
1518 scr->scr_attrs[r_offset]); 1518 scr->scr_attrs[r_offset]);
1519#endif 1519#endif
1520 r_offset++; 1520 r_offset++;
1521 } 1521 }
1522 } 1522 }
1523 1523
1524 if (scr->scr_line_wanted == 0) { 1524 if (scr->scr_line_wanted == 0) {
1525 /* this was a reset - need to draw the cursor */ 1525 /* this was a reset - need to draw the cursor */
1526 scr->scr_ri.ri_flg &= ~RI_CURSOR; 1526 scr->scr_ri.ri_flg &= ~RI_CURSOR;
1527 scr->scr_vd->cursor(scr, 1, scr->scr_ri.ri_crow, 1527 scr->scr_vd->cursor(scr, 1, scr->scr_ri.ri_crow,
1528 scr->scr_ri.ri_ccol); 1528 scr->scr_ri.ri_ccol);
1529 } 1529 }
1530} 1530}
1531 1531
1532#endif /* WSDISPLAY_SCROLLSUPPORT */ 1532#endif /* WSDISPLAY_SCROLLSUPPORT */
1533 1533
1534#ifdef VCONS_DRAW_INTR 1534#ifdef VCONS_DRAW_INTR
1535static void 1535static void
1536vcons_intr(void *cookie) 1536vcons_intr(void *cookie)
1537{ 1537{
1538 struct vcons_data *vd = cookie; 1538 struct vcons_data *vd = cookie;
1539 1539
1540 softint_schedule(vd->intr_softint); 1540 softint_schedule(vd->intr_softint);
1541} 1541}
1542 1542
1543static void 1543static void
1544vcons_softintr(void *cookie) 1544vcons_softintr(void *cookie)
1545{ 1545{
1546 struct vcons_data *vd = cookie; 1546 struct vcons_data *vd = cookie;
1547 struct vcons_screen *scr = vd->active; 1547 struct vcons_screen *scr = vd->active;
1548 unsigned int dirty; 1548 unsigned int dirty;
1549 1549
1550 if (scr && vd->use_intr) { 1550 if (scr && vd->use_intr) {
1551 if (!SCREEN_IS_BUSY(scr)) { 1551 if (!SCREEN_IS_BUSY(scr)) {
1552 dirty = atomic_swap_uint(&scr->scr_dirty, 0); 1552 dirty = atomic_swap_uint(&scr->scr_dirty, 0);
1553 if (vd->use_intr == 2) { 1553 if (vd->use_intr == 2) {
1554 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0) { 1554 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0) {
1555 vd->use_intr = 1; 1555 vd->use_intr = 1;
1556 vcons_redraw_screen(scr); 1556 vcons_redraw_screen(scr);
1557 } 1557 }
1558 } else if (dirty > 0) { 1558 } else if (dirty > 0) {
1559 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0) 1559 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0)
1560 vcons_update_screen(scr); 1560 vcons_update_screen(scr);
1561 } 1561 }
1562 } 1562 }
1563 } 1563 }
1564 1564
1565 callout_schedule(&vd->intr, mstohz(33)); 1565 callout_schedule(&vd->intr, mstohz(33));
1566} 1566}
1567 1567
1568static void 1568static void
1569vcons_init_thread(void *cookie) 1569vcons_init_thread(void *cookie)
1570{ 1570{
1571 struct vcons_data *vd = (struct vcons_data *)cookie; 1571 struct vcons_data *vd = (struct vcons_data *)cookie;
1572 1572
1573 vd->use_intr = 2; 1573 vd->use_intr = 2;
1574 callout_schedule(&vd->intr, mstohz(33)); 1574 callout_schedule(&vd->intr, mstohz(33));
1575 kthread_exit(0); 1575 kthread_exit(0);
1576} 1576}
1577#endif /* VCONS_DRAW_INTR */ 1577#endif /* VCONS_DRAW_INTR */
1578 1578
1579void 1579void
1580vcons_enable_polling(struct vcons_data *vd) 1580vcons_enable_polling(struct vcons_data *vd)
1581{ 1581{
1582 struct vcons_screen *scr = vd->active; 1582 struct vcons_screen *scr = vd->active;
1583 1583
1584#ifdef VCONS_DRAW_INTR 1584#ifdef VCONS_DRAW_INTR
1585 vd->use_intr = 0; 1585 vd->use_intr = 0;
1586#endif 1586#endif
1587 1587
1588 if (scr && !SCREEN_IS_BUSY(scr)) { 1588 if (scr && !SCREEN_IS_BUSY(scr)) {
1589 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0) 1589 if ((scr->scr_flags & VCONS_NO_REDRAW) == 0)
1590 vcons_redraw_screen(scr); 1590 vcons_redraw_screen(scr);
1591 } 1591 }
1592} 1592}
1593 1593
1594void 1594void
1595vcons_disable_polling(struct vcons_data *vd) 1595vcons_disable_polling(struct vcons_data *vd)
1596{ 1596{
1597#ifdef VCONS_DRAW_INTR 1597#ifdef VCONS_DRAW_INTR
1598 struct vcons_screen *scr = vd->active; 1598 struct vcons_screen *scr = vd->active;
1599 1599
1600 if (!vd->intr_valid) 1600 if (!vd->intr_valid)
1601 return; 1601 return;
1602 1602
1603 vd->use_intr = 2; 1603 vd->use_intr = 2;
1604 if (scr) 1604 if (scr)
1605 atomic_inc_uint(&scr->scr_dirty); 1605 atomic_inc_uint(&scr->scr_dirty);
1606#endif 1606#endif
1607} 1607}
1608 1608
1609void 1609void
1610vcons_hard_switch(struct vcons_screen *scr) 1610vcons_hard_switch(struct vcons_screen *scr)
1611{ 1611{
1612 struct vcons_data *vd = scr->scr_vd; 1612 struct vcons_data *vd = scr->scr_vd;
1613 struct vcons_screen *oldscr = vd->active; 1613 struct vcons_screen *oldscr = vd->active;
1614 1614
1615 if (oldscr) { 1615 if (oldscr) {
1616 SCREEN_INVISIBLE(oldscr); 1616 SCREEN_INVISIBLE(oldscr);
1617 oldscr->scr_ri.ri_flg &= ~RI_CURSOR; 1617 oldscr->scr_ri.ri_flg &= ~RI_CURSOR;
1618 } 1618 }
1619 SCREEN_VISIBLE(scr); 1619 SCREEN_VISIBLE(scr);
1620 vd->active = scr; 1620 vd->active = scr;
1621 vd->wanted = NULL; 1621 vd->wanted = NULL;
1622 1622
1623 if (vd->show_screen_cb != NULL) 1623 if (vd->show_screen_cb != NULL)
1624 vd->show_screen_cb(scr, vd->show_screen_cookie); 1624 vd->show_screen_cb(scr, vd->show_screen_cookie);
1625} 1625}
1626 1626
1627#ifdef VCONS_DRAW_INTR 1627#ifdef VCONS_DRAW_INTR
1628void 1628void
1629vcons_invalidate_cache(struct vcons_data *vd) 1629vcons_invalidate_cache(struct vcons_data *vd)
1630{ 1630{
1631 int i; 1631 int i;
1632 1632
1633 if (vd->cells == 0) 1633 if (vd->cells == 0)
1634 return; 1634 return;
1635 1635
1636 for (i = 0; i < vd->cells; i++) { 1636 for (i = 0; i < vd->cells; i++) {
1637 vd->chars[i] = -1; 1637 vd->chars[i] = -1;
1638 vd->attrs[i] = -1; 1638 vd->attrs[i] = -1;
1639 } 1639 }
1640} 1640}
1641#endif 1641#endif