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