2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * This code is derived from software contributed to The DragonFly Project
6 * by Sascha Wildner <saw@online.de>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
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.17 2008/08/10 19:45:01 swildner Exp $
33 #include "opt_syscons.h"
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
40 #include <machine/console.h>
42 #include <dev/video/fb/fbreg.h>
43 #include <dev/video/fb/vgareg.h>
46 #include <bus/isa/isareg.h>
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;
56 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop
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;
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
82 #endif /* SC_PIXEL_MODE */
84 #ifndef SC_NO_MODE_CHANGE
85 static vr_draw_border_t vga_grborder;
88 static void vga_nop(scr_stat *scp, ...);
90 static sc_rndr_sw_t txtrndrsw = {
98 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set);
101 static sc_rndr_sw_t directrndrsw = {
102 vga_pxlborder_direct,
105 vga_pxlcursor_direct,
109 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set);
111 static sc_rndr_sw_t packedrndrsw = {
112 vga_pxlborder_packed,
115 vga_pxlcursor_packed,
119 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set);
121 static sc_rndr_sw_t planarrndrsw = {
122 vga_pxlborder_planar,
125 vga_pxlcursor_planar,
129 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set);
130 #endif /* SC_PIXEL_MODE */
132 #ifndef SC_NO_MODE_CHANGE
133 static sc_rndr_sw_t grrndrsw = {
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,
141 RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set);
142 #endif /* SC_NO_MODE_CHANGE */
144 RENDERER_MODULE(vga, vga_set);
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
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
158 vga_nop(scr_stat *scp, ...)
162 /* text mode renderer */
165 vga_txtborder(scr_stat *scp, int color)
167 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
171 vga_txtdraw(scr_stat *scp, int from, int count, int flip)
177 if (from + count > scp->xsize*scp->ysize)
178 count = scp->xsize*scp->ysize - from;
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);
189 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
194 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
196 if (base < 0 || base >= scp->font_size)
198 /* the caller may set height <= 0 in order to disable the cursor */
200 scp->cursor_base = base;
201 scp->cursor_height = height;
203 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
205 scp->font_size, blink);
209 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
214 scp->cursor_saveunder_char = c;
215 scp->cursor_saveunder_attr = a;
217 #ifndef SC_NO_FONT_LOADING
218 if (sc->flags & SC_CHAR_CURSOR) {
223 if (scp->font_size < 14) {
226 } else if (scp->font_size >= 16) {
233 if (scp->cursor_base >= h)
237 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
238 bcopy(font + c*h, font + sc->cursor_char*h, h);
239 font = font + sc->cursor_char*h;
240 for (i = imax(h - scp->cursor_base - scp->cursor_height, 0);
241 i < h - scp->cursor_base; ++i) {
244 sc->font_loading_in_progress = TRUE;
246 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font,
248 sc->font_loading_in_progress = FALSE;
249 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a);
251 #endif /* SC_NO_FONT_LOADING */
253 if ((a & 0x7000) == 0x7000) {
255 if ((a & 0x0700) == 0)
259 if ((a & 0x0700) == 0x0700)
264 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
265 sc_vtb_putc(&scp->scr, at, c, a);
270 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
272 video_adapter_t *adp;
275 if (scp->cursor_height <= 0) /* the text cursor is disabled */
280 scp->status |= VR_CURSOR_BLINK;
282 scp->status |= VR_CURSOR_ON;
283 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
287 if (scp->status & VR_CURSOR_ON)
288 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
290 scp->status &= ~VR_CURSOR_ON;
293 scp->status &= ~VR_CURSOR_BLINK;
295 scp->status |= VR_CURSOR_ON;
296 draw_txtcharcursor(scp, at,
297 sc_vtb_getc(&scp->scr, at),
298 sc_vtb_geta(&scp->scr, at),
301 cursor_attr = scp->cursor_saveunder_attr;
303 cursor_attr = (cursor_attr & 0x8800)
304 | ((cursor_attr & 0x7000) >> 4)
305 | ((cursor_attr & 0x0700) << 4);
306 if (scp->status & VR_CURSOR_ON)
307 sc_vtb_putc(&scp->scr, at,
308 scp->cursor_saveunder_char,
310 scp->status &= ~VR_CURSOR_ON;
316 vga_txtblink(scr_stat *scp, int at, int flip)
320 #ifndef SC_NO_CUTPASTE
323 draw_txtmouse(scr_stat *scp, int x, int y)
325 #ifndef SC_ALT_MOUSE_IMAGE
326 if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
327 u_char font_buf[128];
331 int xoffset, yoffset;
334 /* prepare mousepointer char's bitmaps */
335 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
336 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
337 &font_buf[0], scp->font_size);
338 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size,
339 &font_buf[32], scp->font_size);
341 + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size,
342 &font_buf[64], scp->font_size);
344 + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size,
345 &font_buf[96], scp->font_size);
346 for (i = 0; i < scp->font_size; ++i) {
347 cursor[i] = font_buf[i]<<8 | font_buf[i+32];
348 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
351 /* now and-or in the mousepointer image */
353 yoffset = y%scp->font_size;
354 for (i = 0; i < 16; ++i) {
355 cursor[i + yoffset] =
356 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
357 | (mouse_or_mask[i] >> xoffset);
359 for (i = 0; i < scp->font_size; ++i) {
360 font_buf[i] = (cursor[i] & 0xff00) >> 8;
361 font_buf[i + 32] = cursor[i] & 0xff;
362 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
363 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
367 /* wait for vertical retrace to avoid jitter on some videocards */
368 while (!(inb(CRTC + 6) & 0x08)) /* idle */ ;
370 c = scp->sc->mouse_char;
371 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
374 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
375 /* FIXME: may be out of range! */
376 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
377 sc_vtb_geta(&scp->scr, pos + scp->xsize));
378 if (x < (scp->xsize - 1)*8) {
379 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
380 sc_vtb_geta(&scp->scr, pos + 1));
381 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
382 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
385 #endif /* SC_ALT_MOUSE_IMAGE */
387 /* Red, magenta and brown are mapped to green to to keep it readable */
388 static const int col_conv[16] = {
389 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
395 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
396 a = sc_vtb_geta(&scp->scr, pos);
397 if (scp->sc->adp->va_flags & V_ADP_COLOR)
398 color = (col_conv[(a & 0xf000) >> 12] << 12)
399 | ((a & 0x0f00) | 0x0800);
401 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
402 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
407 remove_txtmouse(scr_stat *scp, int x, int y)
412 vga_txtmouse(scr_stat *scp, int x, int y, int on)
415 draw_txtmouse(scp, x, y);
417 remove_txtmouse(scp, x, y);
420 #endif /* SC_NO_CUTPASTE */
424 /* pixel (raster text) mode renderer */
427 vga_pxlborder_direct(scr_stat *scp, int color)
430 int line_width, pixel_size;
432 vm_offset_t draw_pos, draw_end, p;
434 line_width = scp->sc->adp->va_line_width;
435 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
437 for (i = 0; i < 4 / pixel_size; ++i)
438 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
441 draw_pos = scp->sc->adp->va_window;
442 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
444 for (p = draw_pos; p < draw_end; p += 4)
448 y = (scp->yoff + scp->ysize) * scp->font_size;
450 if (scp->ypixel > y) {
451 draw_pos = scp->sc->adp->va_window + line_width * y;
452 draw_end = draw_pos + line_width * (scp->ypixel - y);
454 for (p = draw_pos; p < draw_end; p += 4)
458 y = scp->yoff * scp->font_size;
459 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
461 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
463 draw_pos = scp->sc->adp->va_window +
464 line_width * (y + i);
465 draw_end = draw_pos + scp->xoff * 8 * pixel_size;
467 for (p = draw_pos; p < draw_end; p += 4)
472 draw_pos = scp->sc->adp->va_window +
473 line_width * (y + i) +
474 scp->xoff * 8 * pixel_size +
475 scp->xsize * 8 * pixel_size;
476 draw_end = draw_pos + x * 8 * pixel_size;
478 for (p = draw_pos; p < draw_end; p += 4)
485 vga_pxlborder_packed(scr_stat *scp, int color)
490 vm_offset_t draw_pos, draw_end, p;
492 line_width = scp->sc->adp->va_line_width;
493 u32 = (color << 24) + (color << 16) + (color << 8) + color;
496 draw_pos = scp->sc->adp->va_window;
497 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
499 for (p = draw_pos; p < draw_end; p += 4)
503 y = (scp->yoff + scp->ysize) * scp->font_size;
505 if (scp->ypixel > y) {
506 draw_pos = scp->sc->adp->va_window + line_width * y;
507 draw_end = draw_pos + line_width * (scp->ypixel - y);
509 for (p = draw_pos; p < draw_end; p += 4)
513 y = scp->yoff * scp->font_size;
514 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
516 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
518 draw_pos = scp->sc->adp->va_window +
519 line_width * (y + i);
520 draw_end = draw_pos + scp->xoff * 8;
522 for (p = draw_pos; p < draw_end; p += 4)
527 draw_pos = scp->sc->adp->va_window +
528 line_width * (y + i) + scp->xoff * 8 +
530 draw_end = draw_pos + x * 8;
532 for (p = draw_pos; p < draw_end; p += 4)
539 vga_pxlborder_planar(scr_stat *scp, int color)
547 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
549 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
550 outw(GDCIDX, 0x0003); /* data rotate/function select */
551 outw(GDCIDX, 0x0f01); /* set/reset enable */
552 outw(GDCIDX, 0xff08); /* bit mask */
553 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
554 line_width = scp->sc->adp->va_line_width;
555 p = scp->sc->adp->va_window;
557 bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
558 y = (scp->yoff + scp->ysize)*scp->font_size;
560 bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y));
561 y = scp->yoff*scp->font_size;
562 x = scp->xpixel/8 - scp->xoff - scp->xsize;
563 for (i = 0; i < scp->ysize*scp->font_size; ++i) {
565 bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
567 bzero_io((void *)(p + line_width*(y + i)
568 + scp->xoff + scp->xsize), x);
570 outw(GDCIDX, 0x0000); /* set/reset */
571 outw(GDCIDX, 0x0001); /* set/reset enable */
575 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
577 int line_width, pixel_size;
578 int a, i, j, k, l, pos;
579 uint32_t fg, bg, u32;
580 unsigned char *char_data;
581 vm_offset_t draw_pos, p;
583 line_width = scp->sc->adp->va_line_width;
584 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
586 draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
588 if (from + count > scp->xsize * scp->ysize)
589 count = scp->xsize * scp->ysize - from;
591 for (i = from; count-- > 0; ++i) {
592 a = sc_vtb_geta(&scp->vtb, i);
595 fg = scp->ega_palette[(((a & 0x7000) >> 4) |
597 bg = scp->ega_palette[(((a & 0x8000) >> 4) |
600 fg = scp->ega_palette[(a & 0x0f00) >> 8];
601 bg = scp->ega_palette[(a & 0xf000) >> 12];
605 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
608 for (j = 0; j < scp->font_size; ++j, ++char_data) {
611 for (k = 0; k < 2 * pixel_size; ++k) {
614 for (l = 0; l < 4 / pixel_size; ++l) {
615 u32 += (*char_data & (1 << pos--) ?
616 fg : bg) << (l * 8 * pixel_size);
623 p += line_width - 8 * pixel_size;
626 draw_pos += 8 * pixel_size;
628 if ((i % scp->xsize) == scp->xsize - 1)
629 draw_pos += scp->xoff * 16 * pixel_size +
630 (scp->font_size - 1) * line_width;
635 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
639 uint32_t fg, bg, u32;
640 unsigned char *char_data;
641 vm_offset_t draw_pos, p;
643 line_width = scp->sc->adp->va_line_width;
645 draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
647 if (from + count > scp->xsize * scp->ysize)
648 count = scp->xsize * scp->ysize - from;
650 for (i = from; count-- > 0; ++i) {
651 a = sc_vtb_geta(&scp->vtb, i);
654 fg = ((a & 0xf000) >> 4) >> 8;
655 bg = (a & 0x0f00) >> 8;
657 fg = (a & 0x0f00) >> 8;
658 bg = ((a & 0xf000) >> 4) >> 8;
662 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
665 for (j = 0; j < scp->font_size; ++j, ++char_data) {
666 u32 = ((*char_data & 1 ? fg : bg) << 24) +
667 ((*char_data & 2 ? fg : bg) << 16) +
668 ((*char_data & 4 ? fg : bg) << 8) +
669 (*char_data & 8 ? fg : bg);
672 u32 = ((*char_data & 16 ? fg : bg) << 24) +
673 ((*char_data & 32 ? fg : bg) << 16) +
674 ((*char_data & 64 ? fg : bg) << 8) +
675 (*char_data & 128 ? fg : bg);
683 if ((i % scp->xsize) == scp->xsize - 1)
684 draw_pos += scp->xoff * 16 +
685 (scp->font_size - 1) * line_width;
690 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
702 d = VIDEO_MEMORY_POS(scp, from, 1);
704 line_width = scp->sc->adp->va_line_width;
706 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
707 outw(GDCIDX, 0x0003); /* data rotate/function select */
708 outw(GDCIDX, 0x0f01); /* set/reset enable */
709 outw(GDCIDX, 0xff08); /* bit mask */
711 if (from + count > scp->xsize*scp->ysize)
712 count = scp->xsize*scp->ysize - from;
713 for (i = from; count-- > 0; ++i) {
714 a = sc_vtb_geta(&scp->vtb, i);
716 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
717 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
720 col2 = (a & 0xf000) >> 4;
722 /* set background color in EGA/VGA latch */
725 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
726 outw(GDCIDX, bg | 0x00); /* set/reset */
728 c = readb(d); /* set bg color in the latch */
729 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
731 /* foreground color */
732 outw(GDCIDX, col1 | 0x00); /* set/reset */
734 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
735 for (j = 0; j < scp->font_size; ++j, ++f) {
740 if ((i % scp->xsize) == scp->xsize - 1)
742 + (scp->font_size - 1)*line_width;
744 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
745 outw(GDCIDX, 0x0000); /* set/reset */
746 outw(GDCIDX, 0x0001); /* set/reset enable */
750 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
752 if (base < 0 || base >= scp->font_size)
754 /* the caller may set height <= 0 in order to disable the cursor */
756 scp->cursor_base = base;
757 scp->cursor_height = height;
762 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
764 int line_width, pixel_size, height;
766 uint32_t fg, bg, u32;
767 unsigned char *char_data;
768 vm_offset_t draw_pos;
770 line_width = scp->sc->adp->va_line_width;
771 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
773 draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
774 (scp->font_size - scp->cursor_base - 1) * line_width;
776 a = sc_vtb_geta(&scp->vtb, at);
779 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
780 ((a & 0xf000) >> 4)) >> 8];
781 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
784 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
786 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
787 ((a & 0xf000) >> 4)) >> 8];
790 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
791 scp->font_size - scp->cursor_base - 1]);
793 height = imin(scp->cursor_height, scp->font_size);
795 for (i = 0; i < height; ++i, --char_data) {
798 for (j = 0; j < 2 * pixel_size; ++j) {
801 for (k = 0; k < 4 / pixel_size; ++k) {
802 u32 += (*char_data & (1 << pos--) ?
803 fg : bg) << (k * 8 * pixel_size);
806 writel(draw_pos, u32);
810 draw_pos -= line_width + 8 * pixel_size;
815 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
817 int line_width, height;
819 uint32_t fg, bg, u32;
820 unsigned char *char_data;
821 vm_offset_t draw_pos;
823 line_width = scp->sc->adp->va_line_width;
825 draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
826 (scp->font_size - scp->cursor_base - 1) * line_width;
828 a = sc_vtb_geta(&scp->vtb, at);
831 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
832 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
834 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
835 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
838 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
839 scp->font_size - scp->cursor_base - 1]);
841 height = imin(scp->cursor_height, scp->font_size);
843 for (i = 0; i < height; ++i, --char_data) {
844 u32 = ((*char_data & 1 ? fg : bg) << 24) +
845 ((*char_data & 2 ? fg : bg) << 16) +
846 ((*char_data & 4 ? fg : bg) << 8) +
847 (*char_data & 8 ? fg : bg);
848 writel(draw_pos + 4, u32);
850 u32 = ((*char_data & 16 ? fg : bg) << 24) +
851 ((*char_data & 32 ? fg : bg) << 16) +
852 ((*char_data & 64 ? fg : bg) << 8) +
853 (*char_data & 128 ? fg : bg);
854 writel(draw_pos, u32);
856 draw_pos -= line_width;
861 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
872 line_width = scp->sc->adp->va_line_width;
874 d = VIDEO_MEMORY_POS(scp, at, 1) +
875 (scp->font_size - scp->cursor_base - 1) * line_width;
877 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
878 outw(GDCIDX, 0x0003); /* data rotate/function select */
879 outw(GDCIDX, 0x0f01); /* set/reset enable */
880 /* set background color in EGA/VGA latch */
881 a = sc_vtb_geta(&scp->vtb, at);
883 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
885 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
886 outw(GDCIDX, col | 0x00); /* set/reset */
887 outw(GDCIDX, 0xff08); /* bit mask */
889 c = readb(d); /* set bg color in the latch */
890 /* foreground color */
892 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
894 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
895 outw(GDCIDX, col | 0x00); /* set/reset */
896 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
897 + scp->font_size - scp->cursor_base - 1]);
898 height = imin(scp->cursor_height, scp->font_size);
899 for (i = 0; i < height; ++i, --f) {
900 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
904 outw(GDCIDX, 0x0000); /* set/reset */
905 outw(GDCIDX, 0x0001); /* set/reset enable */
906 outw(GDCIDX, 0xff08); /* bit mask */
909 static int pxlblinkrate = 0;
912 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
914 if (scp->cursor_height <= 0) /* the text cursor is disabled */
919 scp->status |= VR_CURSOR_ON;
920 draw_pxlcursor_direct(scp, at, on, flip);
921 } else if (++pxlblinkrate & 4) {
923 scp->status ^= VR_CURSOR_ON;
924 draw_pxlcursor_direct(scp, at,
925 scp->status & VR_CURSOR_ON,
929 if (scp->status & VR_CURSOR_ON)
930 draw_pxlcursor_direct(scp, at, on, flip);
931 scp->status &= ~VR_CURSOR_ON;
934 scp->status |= VR_CURSOR_BLINK;
936 scp->status &= ~VR_CURSOR_BLINK;
940 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
942 if (scp->cursor_height <= 0) /* the text cursor is disabled */
947 scp->status |= VR_CURSOR_ON;
948 draw_pxlcursor_packed(scp, at, on, flip);
949 } else if (++pxlblinkrate & 4) {
951 scp->status ^= VR_CURSOR_ON;
952 draw_pxlcursor_packed(scp, at,
953 scp->status & VR_CURSOR_ON,
957 if (scp->status & VR_CURSOR_ON)
958 draw_pxlcursor_packed(scp, at, on, flip);
959 scp->status &= ~VR_CURSOR_ON;
962 scp->status |= VR_CURSOR_BLINK;
964 scp->status &= ~VR_CURSOR_BLINK;
968 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
970 if (scp->cursor_height <= 0) /* the text cursor is disabled */
975 scp->status |= VR_CURSOR_ON;
976 draw_pxlcursor_planar(scp, at, on, flip);
977 } else if (++pxlblinkrate & 4) {
979 scp->status ^= VR_CURSOR_ON;
980 draw_pxlcursor_planar(scp, at,
981 scp->status & VR_CURSOR_ON,
985 if (scp->status & VR_CURSOR_ON)
986 draw_pxlcursor_planar(scp, at, on, flip);
987 scp->status &= ~VR_CURSOR_ON;
990 scp->status |= VR_CURSOR_BLINK;
992 scp->status &= ~VR_CURSOR_BLINK;
996 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
998 if (!(scp->status & VR_CURSOR_BLINK))
1000 if (!(++pxlblinkrate & 4))
1003 scp->status ^= VR_CURSOR_ON;
1004 draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1008 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1010 if (!(scp->status & VR_CURSOR_BLINK))
1012 if (!(++pxlblinkrate & 4))
1015 scp->status ^= VR_CURSOR_ON;
1016 draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1020 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1022 if (!(scp->status & VR_CURSOR_BLINK))
1024 if (!(++pxlblinkrate & 4))
1027 scp->status ^= VR_CURSOR_ON;
1028 draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1031 #ifndef SC_NO_CUTPASTE
1034 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1036 int line_width, pixel_size;
1039 vm_offset_t draw_pos;
1041 line_width = scp->sc->adp->va_line_width;
1042 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1044 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1045 yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1047 draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1049 for (i = 0; i < (yend - y); i++) {
1050 for (j = (xend - x - 1); j >= 0; j--) {
1051 switch (scp->sc->adp->va_info.vi_depth) {
1053 if (mouse_or_mask[i] & 1 << (15 - j))
1054 writel(draw_pos + 4 * j,
1055 scp->ega_palette[15]);
1056 else if (mouse_and_mask[i] & 1 << (15 - j))
1057 writel(draw_pos + 4 * j,
1058 scp->ega_palette[0]);
1063 if (mouse_or_mask[i] & 1 << (15 - j))
1064 writew(draw_pos + 2 * j,
1065 scp->ega_palette[15]);
1066 else if (mouse_and_mask[i] & 1 << (15 - j))
1067 writew(draw_pos + 2 * j,
1068 scp->ega_palette[0]);
1073 draw_pos += line_width;
1078 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1083 vm_offset_t draw_pos;
1085 line_width = scp->sc->adp->va_line_width;
1087 xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel));
1088 yend = imin(scp->font_size * (scp->yoff + scp->ysize),
1089 imin(y + 16, scp->ypixel));
1091 draw_pos = scp->sc->adp->va_window + y * line_width + x;
1093 for (i = 0; i < (yend - y); i++) {
1094 for (j = (xend - x - 1); j >= 0; j--) {
1095 if (mouse_or_mask[i] & 1 << (15 - j))
1096 writeb(draw_pos + j, 15);
1097 else if (mouse_and_mask[i] & 1 << (15 - j))
1098 writeb(draw_pos + j, 0);
1101 draw_pos += line_width;
1106 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1115 line_width = scp->sc->adp->va_line_width;
1116 xoff = (x - scp->xoff*8)%8;
1117 ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1119 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
1120 outw(GDCIDX, 0x0001); /* set/reset enable */
1121 outw(GDCIDX, 0x0002); /* color compare */
1122 outw(GDCIDX, 0x0007); /* color don't care */
1123 outw(GDCIDX, 0xff08); /* bit mask */
1124 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
1125 p = scp->sc->adp->va_window + line_width*y + x/8;
1126 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1127 for (i = y, j = 0; i < ymax; ++i, ++j) {
1128 m = ~(mouse_and_mask[j] >> xoff);
1129 *(u_char *)p &= m >> 8;
1130 *(u_char *)(p + 1) &= m;
1135 for (i = y, j = 0; i < ymax; ++i, ++j) {
1136 m = ~(mouse_and_mask[j] >> xoff);
1141 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
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_or_mask[j] >> xoff;
1146 *(u_char *)p &= m >> 8;
1147 *(u_char *)(p + 1) &= m;
1151 for (i = y, j = 0; i < ymax; ++i, ++j) {
1152 m = mouse_or_mask[j] >> xoff;
1157 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
1158 outw(GDCIDX, 0x0003); /* data rotate/function select */
1162 remove_pxlmouse(scr_stat *scp, int x, int y)
1168 /* erase the mouse cursor image */
1169 col = x/8 - scp->xoff;
1170 row = y/scp->font_size - scp->yoff;
1171 pos = row*scp->xsize + col;
1172 i = (col < scp->xsize - 1) ? 2 : 1;
1173 (*scp->rndr->draw)(scp, pos, i, FALSE);
1174 if (row < scp->ysize - 1)
1175 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1179 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1182 draw_pxlmouse_direct(scp, x, y);
1184 remove_pxlmouse(scp, x, y);
1188 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1191 draw_pxlmouse_packed(scp, x, y);
1193 remove_pxlmouse(scp, x, y);
1197 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1200 draw_pxlmouse_planar(scp, x, y);
1202 remove_pxlmouse(scp, x, y);
1205 #endif /* SC_NO_CUTPASTE */
1206 #endif /* SC_PIXEL_MODE */
1208 #ifndef SC_NO_MODE_CHANGE
1210 /* graphics mode renderer */
1213 vga_grborder(scr_stat *scp, int color)
1215 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);