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