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