xref: /dflybsd-src/sys/dev/misc/syscons/scvgarndr.c (revision 22ff886e5769d1e8d4bf7faa7bdb9f608ede1714)
1 /*-
2  * (MPSAFE)
3  *
4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The DragonFly Project
8  * by Sascha Wildner <saw@online.de>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer as
15  *    the first lines of this file unmodified.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD: src/sys/dev/syscons/scvgarndr.c,v 1.5.2.3 2001/07/28 12:51:47 yokota Exp $
32  * $DragonFly: src/sys/dev/misc/syscons/scvgarndr.c,v 1.17 2008/08/10 19:45:01 swildner Exp $
33  */
34 
35 #include "opt_syscons.h"
36 #include "opt_vga.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/thread.h>
42 #include <sys/thread2.h>
43 
44 #include <machine/console.h>
45 
46 #include <dev/video/fb/fbreg.h>
47 #include <dev/video/fb/vgareg.h>
48 #include "syscons.h"
49 
50 #include <bus/isa/isareg.h>
51 
52 /*
53  * XXX: this still doesn't quite work with tokens (mainly vga_txtcursor*),
54  *	so temporarily disable tokens here.
55  */
56 #if 1
57 #define lwkt_gettoken(x)
58 #define lwkt_reltoken(x)
59 #endif
60 
61 static vr_draw_border_t		vga_txtborder;
62 static vr_draw_t		vga_txtdraw;
63 static vr_set_cursor_t		vga_txtcursor_shape;
64 static vr_draw_cursor_t		vga_txtcursor;
65 static vr_blink_cursor_t	vga_txtblink;
66 #ifndef SC_NO_CUTPASTE
67 static vr_draw_mouse_t		vga_txtmouse;
68 #else
69 #define	vga_txtmouse		(vr_draw_mouse_t *)vga_nop
70 #endif
71 
72 #ifdef SC_PIXEL_MODE
73 static vr_draw_border_t		vga_pxlborder_direct;
74 static vr_draw_border_t		vga_pxlborder_packed;
75 static vr_draw_border_t		vga_pxlborder_planar;
76 static vr_draw_t		vga_vgadraw_direct;
77 static vr_draw_t		vga_vgadraw_packed;
78 static vr_draw_t		vga_vgadraw_planar;
79 static vr_set_cursor_t		vga_pxlcursor_shape;
80 static vr_draw_cursor_t		vga_pxlcursor_direct;
81 static vr_draw_cursor_t		vga_pxlcursor_packed;
82 static vr_draw_cursor_t		vga_pxlcursor_planar;
83 static vr_blink_cursor_t	vga_pxlblink_direct;
84 static vr_blink_cursor_t	vga_pxlblink_packed;
85 static vr_blink_cursor_t	vga_pxlblink_planar;
86 #ifndef SC_NO_CUTPASTE
87 static vr_draw_mouse_t		vga_pxlmouse_direct;
88 static vr_draw_mouse_t		vga_pxlmouse_packed;
89 static vr_draw_mouse_t		vga_pxlmouse_planar;
90 #else
91 #define	vga_pxlmouse_direct	(vr_draw_mouse_t *)vga_nop
92 #define	vga_pxlmouse_packed	(vr_draw_mouse_t *)vga_nop
93 #define	vga_pxlmouse_planar	(vr_draw_mouse_t *)vga_nop
94 #endif
95 #endif /* SC_PIXEL_MODE */
96 
97 #ifndef SC_NO_MODE_CHANGE
98 static vr_draw_border_t		vga_grborder;
99 #endif
100 
101 static void			vga_nop(scr_stat *scp, ...);
102 
103 static sc_rndr_sw_t txtrndrsw = {
104 	vga_txtborder,
105 	vga_txtdraw,
106 	vga_txtcursor_shape,
107 	vga_txtcursor,
108 	vga_txtblink,
109 	vga_txtmouse,
110 };
111 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set);
112 
113 #ifdef SC_PIXEL_MODE
114 static sc_rndr_sw_t directrndrsw = {
115 	vga_pxlborder_direct,
116 	vga_vgadraw_direct,
117 	vga_pxlcursor_shape,
118 	vga_pxlcursor_direct,
119 	vga_pxlblink_direct,
120 	vga_pxlmouse_direct,
121 };
122 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set);
123 
124 static sc_rndr_sw_t packedrndrsw = {
125 	vga_pxlborder_packed,
126 	vga_vgadraw_packed,
127 	vga_pxlcursor_shape,
128 	vga_pxlcursor_packed,
129 	vga_pxlblink_packed,
130 	vga_pxlmouse_packed,
131 };
132 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set);
133 
134 static sc_rndr_sw_t planarrndrsw = {
135 	vga_pxlborder_planar,
136 	vga_vgadraw_planar,
137 	vga_pxlcursor_shape,
138 	vga_pxlcursor_planar,
139 	vga_pxlblink_planar,
140 	vga_pxlmouse_planar,
141 };
142 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set);
143 #endif /* SC_PIXEL_MODE */
144 
145 #ifndef SC_NO_MODE_CHANGE
146 static sc_rndr_sw_t grrndrsw = {
147 	vga_grborder,
148 	(vr_draw_t *)vga_nop,
149 	(vr_set_cursor_t *)vga_nop,
150 	(vr_draw_cursor_t *)vga_nop,
151 	(vr_blink_cursor_t *)vga_nop,
152 	(vr_draw_mouse_t *)vga_nop,
153 };
154 RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set);
155 #endif /* SC_NO_MODE_CHANGE */
156 
157 RENDERER_MODULE(vga, vga_set);
158 
159 #ifndef SC_NO_CUTPASTE
160 static u_short mouse_and_mask[16] = {
161 	0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
162 	0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
163 };
164 static u_short mouse_or_mask[16] = {
165 	0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
166 	0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
167 };
168 #endif
169 
170 static void
171 vga_nop(scr_stat *scp, ...)
172 {
173 }
174 
175 /* text mode renderer */
176 
177 static void
178 vga_txtborder(scr_stat *scp, int color)
179 {
180 	lwkt_gettoken(&tty_token);
181 	(*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
182 	lwkt_reltoken(&tty_token);
183 }
184 
185 static void
186 vga_txtdraw(scr_stat *scp, int from, int count, int flip)
187 {
188 	uint16_t *p;
189 	int c;
190 	int a;
191 
192 	if (from + count > scp->xsize*scp->ysize)
193 		count = scp->xsize*scp->ysize - from;
194 
195 	if (flip) {
196 		for (p = scp->scr.vtb_buffer + from; count-- > 0; ++from) {
197 			c = sc_vtb_getc(&scp->vtb, from);
198 			a = sc_vtb_geta(&scp->vtb, from);
199 			a = (a & 0x8800) | ((a & 0x7000) >> 4)
200 				| ((a & 0x0700) << 4);
201 			p = sc_vtb_putchar(&scp->scr, p, c, a);
202 		}
203 	} else {
204 		sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
205 	}
206 }
207 
208 static void
209 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
210 {
211 	if (base < 0 || base >= scp->font_size)
212 		return;
213 	lwkt_gettoken(&tty_token);
214 	/* the caller may set height <= 0 in order to disable the cursor */
215 #if 0
216 	scp->cursor_base = base;
217 	scp->cursor_height = height;
218 #endif
219 	(*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
220 							base, height,
221 							scp->font_size, blink);
222 	lwkt_reltoken(&tty_token);
223 }
224 
225 static void
226 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
227 {
228 	sc_softc_t *sc;
229 
230 	sc = scp->sc;
231 	scp->cursor_saveunder_char = c;
232 	scp->cursor_saveunder_attr = a;
233 
234 	//lwkt_gettoken(&tty_token);
235 #ifndef SC_NO_FONT_LOADING
236 	if (sc->flags & SC_CHAR_CURSOR) {
237 		unsigned char *font;
238 		int h;
239 		int i;
240 
241 		if (scp->font_size < 14) {
242 			font = sc->font_8;
243 			h = 8;
244 		} else if (scp->font_size >= 16) {
245 			font = sc->font_16;
246 			h = 16;
247 		} else {
248 			font = sc->font_14;
249 			h = 14;
250 		}
251 		if (scp->cursor_base >= h) {
252 			lwkt_reltoken(&tty_token);
253 			return;
254 		}
255 		if (flip)
256 			a = (a & 0x8800)
257 				| ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
258 		bcopy(font + c*h, font + sc->cursor_char*h, h);
259 		font = font + sc->cursor_char*h;
260 		for (i = imax(h - scp->cursor_base - scp->cursor_height, 0);
261 			i < h - scp->cursor_base; ++i) {
262 			font[i] ^= 0xff;
263 		}
264 		sc->font_loading_in_progress = TRUE;
265 		/* XXX */
266 		(*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font,
267 						 sc->cursor_char, 1);
268 		sc->font_loading_in_progress = FALSE;
269 		sc_vtb_putc(&scp->scr, at, sc->cursor_char, a);
270 	} else
271 #endif /* SC_NO_FONT_LOADING */
272 	{
273 		if ((a & 0x7000) == 0x7000) {
274 			a &= 0x8f00;
275 			if ((a & 0x0700) == 0)
276 				a |= 0x0700;
277 		} else {
278 			a |= 0x7000;
279 			if ((a & 0x0700) == 0x0700)
280 				a &= 0xf000;
281 		}
282 		if (flip)
283 			a = (a & 0x8800)
284 				| ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
285 		sc_vtb_putc(&scp->scr, at, c, a);
286 	}
287 	//lwkt_reltoken(&tty_token);
288 }
289 
290 static void
291 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
292 {
293 	video_adapter_t *adp;
294 	int cursor_attr;
295 
296 	if (scp->cursor_height <= 0)	/* the text cursor is disabled */
297 		return;
298 
299 	//lwkt_gettoken(&tty_token);
300 	adp = scp->sc->adp;
301 	if (blink) {
302 		scp->status |= VR_CURSOR_BLINK;
303 		if (on) {
304 			scp->status |= VR_CURSOR_ON;
305 			(*vidsw[adp->va_index]->set_hw_cursor)(adp,
306 							       at%scp->xsize,
307 							       at/scp->xsize);
308 		} else {
309 			if (scp->status & VR_CURSOR_ON)
310 				(*vidsw[adp->va_index]->set_hw_cursor)(adp,
311 								       -1, -1);
312 			scp->status &= ~VR_CURSOR_ON;
313 		}
314 	} else {
315 		scp->status &= ~VR_CURSOR_BLINK;
316 		if (on) {
317 			scp->status |= VR_CURSOR_ON;
318 			draw_txtcharcursor(scp, at,
319 					   sc_vtb_getc(&scp->scr, at),
320 					   sc_vtb_geta(&scp->scr, at),
321 					   flip);
322 		} else {
323 			cursor_attr = scp->cursor_saveunder_attr;
324 			if (flip)
325 				cursor_attr = (cursor_attr & 0x8800)
326 					| ((cursor_attr & 0x7000) >> 4)
327 					| ((cursor_attr & 0x0700) << 4);
328 			if (scp->status & VR_CURSOR_ON)
329 				sc_vtb_putc(&scp->scr, at,
330 					    scp->cursor_saveunder_char,
331 					    cursor_attr);
332 			scp->status &= ~VR_CURSOR_ON;
333 		}
334 	}
335 	//lwkt_reltoken(&tty_token);
336 }
337 
338 static void
339 vga_txtblink(scr_stat *scp, int at, int flip)
340 {
341 }
342 
343 #ifndef SC_NO_CUTPASTE
344 
345 static void
346 draw_txtmouse(scr_stat *scp, int x, int y)
347 {
348 #ifndef SC_ALT_MOUSE_IMAGE
349     if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
350 	u_char font_buf[128];
351 	u_short cursor[32];
352 	u_char c;
353 	int pos;
354 	int xoffset, yoffset;
355 	int i;
356 
357 	lwkt_gettoken(&tty_token);
358 
359 	/* prepare mousepointer char's bitmaps */
360 	pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
361 	bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
362 	      &font_buf[0], scp->font_size);
363 	bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size,
364 	      &font_buf[32], scp->font_size);
365 	bcopy(scp->font
366 		 + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size,
367 	      &font_buf[64], scp->font_size);
368 	bcopy(scp->font
369 		 + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size,
370 	      &font_buf[96], scp->font_size);
371 	for (i = 0; i < scp->font_size; ++i) {
372 		cursor[i] = font_buf[i]<<8 | font_buf[i+32];
373 		cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
374 	}
375 
376 	/* now and-or in the mousepointer image */
377 	xoffset = x%8;
378 	yoffset = y%scp->font_size;
379 	for (i = 0; i < 16; ++i) {
380 		cursor[i + yoffset] =
381 	    		(cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
382 	    		| (mouse_or_mask[i] >> xoffset);
383 	}
384 	for (i = 0; i < scp->font_size; ++i) {
385 		font_buf[i] = (cursor[i] & 0xff00) >> 8;
386 		font_buf[i + 32] = cursor[i] & 0xff;
387 		font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
388 		font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
389 	}
390 
391 #if 1
392 	/* wait for vertical retrace to avoid jitter on some videocards */
393 	while (!(inb(CRTC + 6) & 0x08)) /* idle */ ;
394 #endif
395 	c = scp->sc->mouse_char;
396 	(*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
397 					      c, 4);
398 
399 	sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
400 	/* FIXME: may be out of range! */
401 	sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
402 		    sc_vtb_geta(&scp->scr, pos + scp->xsize));
403 	if (x < (scp->xsize - 1)*8) {
404 		sc_vtb_putc(&scp->scr, pos + 1, c + 1,
405 			    sc_vtb_geta(&scp->scr, pos + 1));
406 		sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
407 			    sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
408 	}
409     } else
410 #endif /* SC_ALT_MOUSE_IMAGE */
411     {
412 	/* Red, magenta and brown are mapped to green to to keep it readable */
413 	static const int col_conv[16] = {
414 		6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
415 	};
416 	int pos;
417 	int color;
418 	int a;
419 
420 	pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
421 	a = sc_vtb_geta(&scp->scr, pos);
422 	if (scp->sc->adp->va_flags & V_ADP_COLOR)
423 		color = (col_conv[(a & 0xf000) >> 12] << 12)
424 			| ((a & 0x0f00) | 0x0800);
425 	else
426 		color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
427 	sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
428     }
429 
430     lwkt_reltoken(&tty_token);
431 }
432 
433 static void
434 remove_txtmouse(scr_stat *scp, int x, int y)
435 {
436 }
437 
438 static void
439 vga_txtmouse(scr_stat *scp, int x, int y, int on)
440 {
441 	if (on)
442 		draw_txtmouse(scp, x, y);
443 	else
444 		remove_txtmouse(scp, x, y);
445 }
446 
447 #endif /* SC_NO_CUTPASTE */
448 
449 #ifdef SC_PIXEL_MODE
450 
451 /* pixel (raster text) mode renderer */
452 
453 static void
454 vga_pxlborder_direct(scr_stat *scp, int color)
455 {
456 	int i, x, y;
457 	int line_width, pixel_size;
458 	uint32_t u32 = 0;
459 	vm_offset_t draw_pos, draw_end, p;
460 
461 	line_width = scp->sc->adp->va_line_width;
462 	pixel_size = scp->sc->adp->va_info.vi_pixel_size;
463 
464 	for (i = 0; i < 4 / pixel_size; ++i)
465 		u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
466 
467 	if (scp->yoff > 0) {
468 		draw_pos = scp->sc->adp->va_window;
469 		draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
470 
471 		for (p = draw_pos; p < draw_end; p += 4)
472 			writel(p, u32);
473 	}
474 
475 	y = (scp->yoff + scp->ysize) * scp->font_size;
476 
477 	if (scp->ypixel > y) {
478 		draw_pos = scp->sc->adp->va_window + line_width * y;
479 		draw_end = draw_pos + line_width * (scp->ypixel - y);
480 
481 		for (p = draw_pos; p < draw_end; p += 4)
482 			writel(p, u32);
483 	}
484 
485 	y = scp->yoff * scp->font_size;
486 	x = scp->xpixel / 8 - scp->xoff - scp->xsize;
487 
488 	for (i = 0; i < scp->ysize * scp->font_size; ++i) {
489 		if (scp->xoff > 0) {
490 			draw_pos = scp->sc->adp->va_window +
491 			    line_width * (y + i);
492 			draw_end = draw_pos + scp->xoff * 8 * pixel_size;
493 
494 			for (p = draw_pos; p < draw_end; p += 4)
495 				writel(p, u32);
496 		}
497 
498 		if (x > 0) {
499 			draw_pos = scp->sc->adp->va_window +
500 			    line_width * (y + i) +
501 			    scp->xoff * 8 * pixel_size +
502 			    scp->xsize * 8 * pixel_size;
503 			draw_end = draw_pos + x * 8 * pixel_size;
504 
505 			for (p = draw_pos; p < draw_end; p += 4)
506 				writel(p, u32);
507 		}
508 	}
509 }
510 
511 static void
512 vga_pxlborder_packed(scr_stat *scp, int color)
513 {
514 	int i, x, y;
515 	int line_width;
516 	uint32_t u32;
517 	vm_offset_t draw_pos, draw_end, p;
518 
519 	line_width = scp->sc->adp->va_line_width;
520 	u32 = (color << 24) + (color << 16) + (color << 8) + color;
521 
522 	if (scp->yoff > 0) {
523 		draw_pos = scp->sc->adp->va_window;
524 		draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
525 
526 		for (p = draw_pos; p < draw_end; p += 4)
527 			writel(p, u32);
528 	}
529 
530 	y = (scp->yoff + scp->ysize) * scp->font_size;
531 
532 	if (scp->ypixel > y) {
533 		draw_pos = scp->sc->adp->va_window + line_width * y;
534 		draw_end = draw_pos + line_width * (scp->ypixel - y);
535 
536 		for (p = draw_pos; p < draw_end; p += 4)
537 			writel(p, u32);
538 	}
539 
540 	y = scp->yoff * scp->font_size;
541 	x = scp->xpixel / 8 - scp->xoff - scp->xsize;
542 
543 	for (i = 0; i < scp->ysize * scp->font_size; ++i) {
544 		if (scp->xoff > 0) {
545 			draw_pos = scp->sc->adp->va_window +
546 			    line_width * (y + i);
547 			draw_end = draw_pos + scp->xoff * 8;
548 
549 			for (p = draw_pos; p < draw_end; p += 4)
550 				writel(p, u32);
551 		}
552 
553 		if (x > 0) {
554 			draw_pos = scp->sc->adp->va_window +
555 			    line_width * (y + i) + scp->xoff * 8 +
556 			    scp->xsize * 8;
557 			draw_end = draw_pos + x * 8;
558 
559 			for (p = draw_pos; p < draw_end; p += 4)
560 				writel(p, u32);
561 		}
562 	}
563 }
564 
565 static void
566 vga_pxlborder_planar(scr_stat *scp, int color)
567 {
568 	vm_offset_t p;
569 	int line_width;
570 	int x;
571 	int y;
572 	int i;
573 
574 	lwkt_gettoken(&tty_token);
575 
576 	(*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
577 
578 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
579 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
580 	outw(GDCIDX, 0x0f01);		/* set/reset enable */
581 	outw(GDCIDX, 0xff08);		/* bit mask */
582 	outw(GDCIDX, (color << 8) | 0x00);	/* set/reset */
583 	line_width = scp->sc->adp->va_line_width;
584 	p = scp->sc->adp->va_window;
585 	if (scp->yoff > 0)
586 		bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
587 	y = (scp->yoff + scp->ysize)*scp->font_size;
588 	if (scp->ypixel > y)
589 		bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y));
590 	y = scp->yoff*scp->font_size;
591 	x = scp->xpixel/8 - scp->xoff - scp->xsize;
592 	for (i = 0; i < scp->ysize*scp->font_size; ++i) {
593 		if (scp->xoff > 0)
594 			bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
595 		if (x > 0)
596 			bzero_io((void *)(p + line_width*(y + i)
597 				     + scp->xoff + scp->xsize), x);
598 	}
599 	outw(GDCIDX, 0x0000);		/* set/reset */
600 	outw(GDCIDX, 0x0001);		/* set/reset enable */
601 	lwkt_reltoken(&tty_token);
602 }
603 
604 static void
605 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
606 {
607 	int line_width, pixel_size;
608 	int a, i, j, k, l, pos;
609 	uint32_t fg, bg, u32;
610 	unsigned char *char_data;
611 	vm_offset_t draw_pos, p;
612 
613 	line_width = scp->sc->adp->va_line_width;
614 	pixel_size = scp->sc->adp->va_info.vi_pixel_size;
615 
616 	draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
617 
618 	if (from + count > scp->xsize * scp->ysize)
619 		count = scp->xsize * scp->ysize - from;
620 
621 	for (i = from; count-- > 0; ++i) {
622 		a = sc_vtb_geta(&scp->vtb, i);
623 
624 		if (flip) {
625 			fg = scp->ega_palette[(((a & 0x7000) >> 4) |
626 			    (a & 0x0800)) >> 8];
627 			bg = scp->ega_palette[(((a & 0x8000) >> 4) |
628 			    (a & 0x0700)) >> 8];
629 		} else {
630 			fg = scp->ega_palette[(a & 0x0f00) >> 8];
631 			bg = scp->ega_palette[(a & 0xf000) >> 12];
632 		}
633 
634 		p = draw_pos;
635 		char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
636 		    scp->font_size]);
637 
638 		for (j = 0; j < scp->font_size; ++j, ++char_data) {
639 			pos = 7;
640 
641 			for (k = 0; k < 2 * pixel_size; ++k) {
642 				u32 = 0;
643 
644 				for (l = 0; l < 4 / pixel_size; ++l) {
645 					u32 += (*char_data & (1 << pos--) ?
646 					    fg : bg) << (l * 8 * pixel_size);
647 				}
648 
649 				writel(p, u32);
650 				p += 4;
651 			}
652 
653 			p += line_width - 8 * pixel_size;
654 		}
655 
656 		draw_pos += 8 * pixel_size;
657 
658 		if ((i % scp->xsize) == scp->xsize - 1)
659 			draw_pos += scp->xoff * 16 * pixel_size +
660 			     (scp->font_size - 1) * line_width;
661 	}
662 }
663 
664 static void
665 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
666 {
667 	int line_width;
668 	int a, i, j;
669 	uint32_t fg, bg, u32;
670 	unsigned char *char_data;
671 	vm_offset_t draw_pos, p;
672 
673 	line_width = scp->sc->adp->va_line_width;
674 
675 	draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
676 
677 	if (from + count > scp->xsize * scp->ysize)
678 		count = scp->xsize * scp->ysize - from;
679 
680 	for (i = from; count-- > 0; ++i) {
681 		a = sc_vtb_geta(&scp->vtb, i);
682 
683 		if (flip) {
684 			fg = ((a & 0xf000) >> 4) >> 8;
685 			bg = (a & 0x0f00) >> 8;
686 		} else {
687 			fg = (a & 0x0f00) >> 8;
688 			bg = ((a & 0xf000) >> 4) >> 8;
689 		}
690 
691 		p = draw_pos;
692 		char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
693 		    scp->font_size]);
694 
695 		for (j = 0; j < scp->font_size; ++j, ++char_data) {
696 			u32 = ((*char_data & 1 ? fg : bg) << 24) +
697 			      ((*char_data & 2 ? fg : bg) << 16) +
698 			      ((*char_data & 4 ? fg : bg) << 8) +
699 			      (*char_data & 8 ? fg : bg);
700 			writel(p + 4, u32);
701 
702 			u32 = ((*char_data & 16 ? fg : bg) << 24) +
703 			      ((*char_data & 32 ? fg : bg) << 16) +
704 			      ((*char_data & 64 ? fg : bg) << 8) +
705 			      (*char_data & 128 ? fg : bg);
706 			writel(p, u32);
707 
708 			p += line_width;
709 		}
710 
711 		draw_pos += 8;
712 
713 		if ((i % scp->xsize) == scp->xsize - 1)
714 			draw_pos += scp->xoff * 16 +
715 			     (scp->font_size - 1) * line_width;
716 	}
717 }
718 
719 static void
720 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
721 {
722 	vm_offset_t d;
723 	vm_offset_t e;
724 	u_char *f;
725 	u_short bg;
726 	u_short col1, col2;
727 	int line_width;
728 	int i, j;
729 	int a;
730 	u_char c;
731 
732 	d = VIDEO_MEMORY_POS(scp, from, 1);
733 
734 	line_width = scp->sc->adp->va_line_width;
735 
736 	outw(GDCIDX, 0x0305);		/* read mode 0, write mode 3 */
737 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
738 	outw(GDCIDX, 0x0f01);		/* set/reset enable */
739 	outw(GDCIDX, 0xff08);		/* bit mask */
740 	bg = -1;
741 	if (from + count > scp->xsize*scp->ysize)
742 		count = scp->xsize*scp->ysize - from;
743 	for (i = from; count-- > 0; ++i) {
744 		a = sc_vtb_geta(&scp->vtb, i);
745 		if (flip) {
746 			col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
747 			col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
748 		} else {
749 			col1 = (a & 0x0f00);
750 			col2 = (a & 0xf000) >> 4;
751 		}
752 		/* set background color in EGA/VGA latch */
753 		if (bg != col2) {
754 			bg = col2;
755 			outw(GDCIDX, 0x0005);	/* read mode 0, write mode 0 */
756 			outw(GDCIDX, bg | 0x00); /* set/reset */
757 			writeb(d, 0);
758 			c = readb(d);		/* set bg color in the latch */
759 			outw(GDCIDX, 0x0305);	/* read mode 0, write mode 3 */
760 		}
761 		/* foreground color */
762 		outw(GDCIDX, col1 | 0x00);	/* set/reset */
763 		e = d;
764 		f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
765 		for (j = 0; j < scp->font_size; ++j, ++f) {
766 	        	writeb(e, *f);
767 			e += line_width;
768 		}
769 		++d;
770 		if ((i % scp->xsize) == scp->xsize - 1)
771 			d += scp->xoff*2
772 				 + (scp->font_size - 1)*line_width;
773 	}
774 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
775 	outw(GDCIDX, 0x0000);		/* set/reset */
776 	outw(GDCIDX, 0x0001);		/* set/reset enable */
777 }
778 
779 static void
780 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
781 {
782 	if (base < 0 || base >= scp->font_size)
783 		return;
784 	/* the caller may set height <= 0 in order to disable the cursor */
785 #if 0
786 	scp->cursor_base = base;
787 	scp->cursor_height = height;
788 #endif
789 }
790 
791 static void
792 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
793 {
794 	int line_width, pixel_size, height;
795 	int a, i, j, k, pos;
796 	uint32_t fg, bg, u32;
797 	unsigned char *char_data;
798 	vm_offset_t draw_pos;
799 
800 	line_width = scp->sc->adp->va_line_width;
801 	pixel_size = scp->sc->adp->va_info.vi_pixel_size;
802 
803 	draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
804 	    (scp->font_size - scp->cursor_base - 1) * line_width;
805 
806 	a = sc_vtb_geta(&scp->vtb, at);
807 
808 	if (flip) {
809 		fg = scp->ega_palette[((on) ? (a & 0x0f00) :
810 		    ((a & 0xf000) >> 4)) >> 8];
811 		bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
812 		    (a & 0x0f00)) >> 8];
813 	} else {
814 		fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
815 		    (a & 0x0f00)) >> 8];
816 		bg = scp->ega_palette[((on) ? (a & 0x0f00) :
817 		    ((a & 0xf000) >> 4)) >> 8];
818 	}
819 
820 	char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
821 	    scp->font_size - scp->cursor_base - 1]);
822 
823 	height = imin(scp->cursor_height, scp->font_size);
824 
825 	for (i = 0; i < height; ++i, --char_data) {
826 		pos = 7;
827 
828 		for (j = 0; j < 2 * pixel_size; ++j) {
829 			u32 = 0;
830 
831 			for (k = 0; k < 4 / pixel_size; ++k) {
832 				u32 += (*char_data & (1 << pos--) ?
833 				    fg : bg) << (k * 8 * pixel_size);
834 			}
835 
836 			writel(draw_pos, u32);
837 			draw_pos += 4;
838 		}
839 
840 		draw_pos -= line_width + 8 * pixel_size;
841 	}
842 }
843 
844 static void
845 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
846 {
847 	int line_width, height;
848 	int a, i;
849 	uint32_t fg, bg, u32;
850 	unsigned char *char_data;
851 	vm_offset_t draw_pos;
852 
853 	line_width = scp->sc->adp->va_line_width;
854 
855 	draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
856 	    (scp->font_size - scp->cursor_base - 1) * line_width;
857 
858 	a = sc_vtb_geta(&scp->vtb, at);
859 
860 	if (flip) {
861 		fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
862 		bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
863 	} else {
864 		fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
865 		bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
866 	}
867 
868 	char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
869 	    scp->font_size - scp->cursor_base - 1]);
870 
871 	height = imin(scp->cursor_height, scp->font_size);
872 
873 	for (i = 0; i < height; ++i, --char_data) {
874 		u32 = ((*char_data & 1 ? fg : bg) << 24) +
875 		      ((*char_data & 2 ? fg : bg) << 16) +
876 		      ((*char_data & 4 ? fg : bg) << 8) +
877 		      (*char_data & 8 ? fg : bg);
878 		writel(draw_pos + 4, u32);
879 
880 		u32 = ((*char_data & 16 ? fg : bg) << 24) +
881 		      ((*char_data & 32 ? fg : bg) << 16) +
882 		      ((*char_data & 64 ? fg : bg) << 8) +
883 		      (*char_data & 128 ? fg : bg);
884 		writel(draw_pos, u32);
885 
886 		draw_pos -= line_width;
887 	}
888 }
889 
890 static void
891 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
892 {
893 	vm_offset_t d;
894 	u_char *f;
895 	int line_width;
896 	int height;
897 	int col;
898 	int a;
899 	int i;
900 	u_char c;
901 
902 	line_width = scp->sc->adp->va_line_width;
903 
904 	d = VIDEO_MEMORY_POS(scp, at, 1) +
905 	    (scp->font_size - scp->cursor_base - 1) * line_width;
906 
907 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
908 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
909 	outw(GDCIDX, 0x0f01);		/* set/reset enable */
910 	/* set background color in EGA/VGA latch */
911 	a = sc_vtb_geta(&scp->vtb, at);
912 	if (flip)
913 		col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
914 	else
915 		col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
916 	outw(GDCIDX, col | 0x00);	/* set/reset */
917 	outw(GDCIDX, 0xff08);		/* bit mask */
918 	writeb(d, 0);
919 	c = readb(d);			/* set bg color in the latch */
920 	/* foreground color */
921 	if (flip)
922 		col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
923 	else
924 		col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
925 	outw(GDCIDX, col | 0x00);	/* set/reset */
926 	f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
927 		+ scp->font_size - scp->cursor_base - 1]);
928 	height = imin(scp->cursor_height, scp->font_size);
929 	for (i = 0; i < height; ++i, --f) {
930 		outw(GDCIDX, (*f << 8) | 0x08);	/* bit mask */
931 	       	writeb(d, 0);
932 		d -= line_width;
933 	}
934 	outw(GDCIDX, 0x0000);		/* set/reset */
935 	outw(GDCIDX, 0x0001);		/* set/reset enable */
936 	outw(GDCIDX, 0xff08);		/* bit mask */
937 }
938 
939 static int pxlblinkrate = 0;
940 
941 static void
942 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
943 {
944 	if (scp->cursor_height <= 0)	/* the text cursor is disabled */
945 		return;
946 
947 	if (on) {
948 		if (!blink) {
949 			scp->status |= VR_CURSOR_ON;
950 			draw_pxlcursor_direct(scp, at, on, flip);
951 		} else if (++pxlblinkrate & 4) {
952 			pxlblinkrate = 0;
953 			scp->status ^= VR_CURSOR_ON;
954 			draw_pxlcursor_direct(scp, at,
955 					      scp->status & VR_CURSOR_ON,
956 					      flip);
957 		}
958 	} else {
959 		if (scp->status & VR_CURSOR_ON)
960 			draw_pxlcursor_direct(scp, at, on, flip);
961 		scp->status &= ~VR_CURSOR_ON;
962 	}
963 	if (blink)
964 		scp->status |= VR_CURSOR_BLINK;
965 	else
966 		scp->status &= ~VR_CURSOR_BLINK;
967 }
968 
969 static void
970 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
971 {
972 	if (scp->cursor_height <= 0)	/* the text cursor is disabled */
973 		return;
974 
975 	if (on) {
976 		if (!blink) {
977 			scp->status |= VR_CURSOR_ON;
978 			draw_pxlcursor_packed(scp, at, on, flip);
979 		} else if (++pxlblinkrate & 4) {
980 			pxlblinkrate = 0;
981 			scp->status ^= VR_CURSOR_ON;
982 			draw_pxlcursor_packed(scp, at,
983 					      scp->status & VR_CURSOR_ON,
984 					      flip);
985 		}
986 	} else {
987 		if (scp->status & VR_CURSOR_ON)
988 			draw_pxlcursor_packed(scp, at, on, flip);
989 		scp->status &= ~VR_CURSOR_ON;
990 	}
991 	if (blink)
992 		scp->status |= VR_CURSOR_BLINK;
993 	else
994 		scp->status &= ~VR_CURSOR_BLINK;
995 }
996 
997 static void
998 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
999 {
1000 	if (scp->cursor_height <= 0)	/* the text cursor is disabled */
1001 		return;
1002 
1003 	if (on) {
1004 		if (!blink) {
1005 			scp->status |= VR_CURSOR_ON;
1006 			draw_pxlcursor_planar(scp, at, on, flip);
1007 		} else if (++pxlblinkrate & 4) {
1008 			pxlblinkrate = 0;
1009 			scp->status ^= VR_CURSOR_ON;
1010 			draw_pxlcursor_planar(scp, at,
1011 					      scp->status & VR_CURSOR_ON,
1012 					      flip);
1013 		}
1014 	} else {
1015 		if (scp->status & VR_CURSOR_ON)
1016 			draw_pxlcursor_planar(scp, at, on, flip);
1017 		scp->status &= ~VR_CURSOR_ON;
1018 	}
1019 	if (blink)
1020 		scp->status |= VR_CURSOR_BLINK;
1021 	else
1022 		scp->status &= ~VR_CURSOR_BLINK;
1023 }
1024 
1025 static void
1026 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1027 {
1028 	if (!(scp->status & VR_CURSOR_BLINK))
1029 		return;
1030 	if (!(++pxlblinkrate & 4))
1031 		return;
1032 	pxlblinkrate = 0;
1033 	scp->status ^= VR_CURSOR_ON;
1034 	draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1035 }
1036 
1037 static void
1038 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1039 {
1040 	if (!(scp->status & VR_CURSOR_BLINK))
1041 		return;
1042 	if (!(++pxlblinkrate & 4))
1043 		return;
1044 	pxlblinkrate = 0;
1045 	scp->status ^= VR_CURSOR_ON;
1046 	draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1047 }
1048 
1049 static void
1050 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1051 {
1052 	if (!(scp->status & VR_CURSOR_BLINK))
1053 		return;
1054 	if (!(++pxlblinkrate & 4))
1055 		return;
1056 	pxlblinkrate = 0;
1057 	scp->status ^= VR_CURSOR_ON;
1058 	draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1059 }
1060 
1061 #ifndef SC_NO_CUTPASTE
1062 
1063 static void
1064 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1065 {
1066 	int line_width, pixel_size;
1067 	int xend, yend;
1068 	int i, j;
1069 	vm_offset_t draw_pos;
1070 
1071 	line_width = scp->sc->adp->va_line_width;
1072 	pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1073 
1074 	xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1075 	yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1076 
1077 	draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1078 
1079 	for (i = 0; i < (yend - y); i++) {
1080 		for (j = (xend - x - 1); j >= 0; j--) {
1081 			switch (scp->sc->adp->va_info.vi_depth) {
1082 			case 32:
1083 				if (mouse_or_mask[i] & 1 << (15 - j))
1084 					writel(draw_pos + 4 * j,
1085 					    scp->ega_palette[15]);
1086 				else if (mouse_and_mask[i] & 1 << (15 - j))
1087 					writel(draw_pos + 4 * j,
1088 					    scp->ega_palette[0]);
1089 				break;
1090 			case 16:
1091 				/* FALLTHROUGH */
1092 			case 15:
1093 				if (mouse_or_mask[i] & 1 << (15 - j))
1094 					writew(draw_pos + 2 * j,
1095 					    scp->ega_palette[15]);
1096 				else if (mouse_and_mask[i] & 1 << (15 - j))
1097 					writew(draw_pos + 2 * j,
1098 					    scp->ega_palette[0]);
1099 				break;
1100 			}
1101 		}
1102 
1103 		draw_pos += line_width;
1104 	}
1105 }
1106 
1107 static void
1108 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1109 {
1110 	int line_width;
1111 	int xend, yend;
1112 	int i, j;
1113 	vm_offset_t draw_pos;
1114 
1115 	line_width = scp->sc->adp->va_line_width;
1116 
1117 	xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel));
1118 	yend = imin(scp->font_size * (scp->yoff + scp->ysize),
1119 	    imin(y + 16, scp->ypixel));
1120 
1121 	draw_pos = scp->sc->adp->va_window + y * line_width + x;
1122 
1123 	for (i = 0; i < (yend - y); i++) {
1124 		for (j = (xend - x - 1); j >= 0; j--) {
1125 			if (mouse_or_mask[i] & 1 << (15 - j))
1126 				writeb(draw_pos + j, 15);
1127 			else if (mouse_and_mask[i] & 1 << (15 - j))
1128 				writeb(draw_pos + j, 0);
1129 		}
1130 
1131 		draw_pos += line_width;
1132 	}
1133 }
1134 
1135 static void
1136 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1137 {
1138 	vm_offset_t p;
1139 	int line_width;
1140 	int xoff;
1141 	int ymax;
1142 	u_short m;
1143 	int i, j;
1144 
1145 	line_width = scp->sc->adp->va_line_width;
1146 	xoff = (x - scp->xoff*8)%8;
1147 	ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1148 
1149 	outw(GDCIDX, 0x0805);		/* read mode 1, write mode 0 */
1150 	outw(GDCIDX, 0x0001);		/* set/reset enable */
1151 	outw(GDCIDX, 0x0002);		/* color compare */
1152 	outw(GDCIDX, 0x0007);		/* color don't care */
1153 	outw(GDCIDX, 0xff08);		/* bit mask */
1154 	outw(GDCIDX, 0x0803);		/* data rotate/function select (and) */
1155 	p = scp->sc->adp->va_window + line_width*y + x/8;
1156 	if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1157 		for (i = y, j = 0; i < ymax; ++i, ++j) {
1158 			m = ~(mouse_and_mask[j] >> xoff);
1159 			*(u_char *)p &= m >> 8;
1160 			*(u_char *)(p + 1) &= m;
1161 			p += line_width;
1162 		}
1163 	} else {
1164 		xoff += 8;
1165 		for (i = y, j = 0; i < ymax; ++i, ++j) {
1166 			m = ~(mouse_and_mask[j] >> xoff);
1167 			*(u_char *)p &= m;
1168 			p += line_width;
1169 		}
1170 	}
1171 	outw(GDCIDX, 0x1003);		/* data rotate/function select (or) */
1172 	p = scp->sc->adp->va_window + line_width*y + x/8;
1173 	if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1174 		for (i = y, j = 0; i < ymax; ++i, ++j) {
1175 			m = mouse_or_mask[j] >> xoff;
1176 			*(u_char *)p &= m >> 8;
1177 			*(u_char *)(p + 1) &= m;
1178 			p += line_width;
1179 		}
1180 	} else {
1181 		for (i = y, j = 0; i < ymax; ++i, ++j) {
1182 			m = mouse_or_mask[j] >> xoff;
1183 			*(u_char *)p &= m;
1184 			p += line_width;
1185 		}
1186 	}
1187 	outw(GDCIDX, 0x0005);		/* read mode 0, write mode 0 */
1188 	outw(GDCIDX, 0x0003);		/* data rotate/function select */
1189 }
1190 
1191 static void
1192 remove_pxlmouse(scr_stat *scp, int x, int y)
1193 {
1194 	int col, row;
1195 	int pos;
1196 	int i;
1197 
1198 	/* erase the mouse cursor image */
1199 	col = x/8 - scp->xoff;
1200 	row = y/scp->font_size - scp->yoff;
1201 	pos = row*scp->xsize + col;
1202 	i = (col < scp->xsize - 1) ? 2 : 1;
1203 	(*scp->rndr->draw)(scp, pos, i, FALSE);
1204 	if (row < scp->ysize - 1)
1205 		(*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1206 }
1207 
1208 static void
1209 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1210 {
1211 	if (on)
1212 		draw_pxlmouse_direct(scp, x, y);
1213 	else
1214 		remove_pxlmouse(scp, x, y);
1215 }
1216 
1217 static void
1218 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1219 {
1220 	if (on)
1221 		draw_pxlmouse_packed(scp, x, y);
1222 	else
1223 		remove_pxlmouse(scp, x, y);
1224 }
1225 
1226 static void
1227 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1228 {
1229 	if (on)
1230 		draw_pxlmouse_planar(scp, x, y);
1231 	else
1232 		remove_pxlmouse(scp, x, y);
1233 }
1234 
1235 #endif /* SC_NO_CUTPASTE */
1236 #endif /* SC_PIXEL_MODE */
1237 
1238 #ifndef SC_NO_MODE_CHANGE
1239 
1240 /* graphics mode renderer */
1241 
1242 static void
1243 vga_grborder(scr_stat *scp, int color)
1244 {
1245 	lwkt_gettoken(&tty_token);
1246 	(*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1247 	lwkt_reltoken(&tty_token);
1248 }
1249 
1250 #endif
1251