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