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