4 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
7 * This code is derived from software contributed to The DragonFly Project
8 * by Sascha Wildner <saw@online.de>
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer as
15 * the first lines of this file unmodified.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 * $FreeBSD: src/sys/dev/syscons/scvgarndr.c,v 1.5.2.3 2001/07/28 12:51:47 yokota Exp $
32 * $DragonFly: src/sys/dev/misc/syscons/scvgarndr.c,v 1.17 2008/08/10 19:45:01 swildner Exp $
35 #include "opt_syscons.h"
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/thread.h>
42 #include <sys/thread2.h>
44 #include <machine/console.h>
46 #include <dev/video/fb/fbreg.h>
47 #include <dev/video/fb/vgareg.h>
50 #include <bus/isa/isareg.h>
53 * XXX: this still doesn't quite work with tokens (mainly vga_txtcursor*),
54 * so temporarily disable tokens here.
57 #define lwkt_gettoken(x)
58 #define lwkt_reltoken(x)
61 static vr_draw_border_t vga_txtborder;
62 static vr_draw_t vga_txtdraw;
63 static vr_set_cursor_t vga_txtcursor_shape;
64 static vr_draw_cursor_t vga_txtcursor;
65 static vr_blink_cursor_t vga_txtblink;
66 #ifndef SC_NO_CUTPASTE
67 static vr_draw_mouse_t vga_txtmouse;
69 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop
73 static vr_draw_border_t vga_pxlborder_direct;
74 static vr_draw_border_t vga_pxlborder_packed;
75 static vr_draw_border_t vga_pxlborder_planar;
76 static vr_draw_t vga_vgadraw_direct;
77 static vr_draw_t vga_vgadraw_packed;
78 static vr_draw_t vga_vgadraw_planar;
79 static vr_set_cursor_t vga_pxlcursor_shape;
80 static vr_draw_cursor_t vga_pxlcursor_direct;
81 static vr_draw_cursor_t vga_pxlcursor_packed;
82 static vr_draw_cursor_t vga_pxlcursor_planar;
83 static vr_blink_cursor_t vga_pxlblink_direct;
84 static vr_blink_cursor_t vga_pxlblink_packed;
85 static vr_blink_cursor_t vga_pxlblink_planar;
86 #ifndef SC_NO_CUTPASTE
87 static vr_draw_mouse_t vga_pxlmouse_direct;
88 static vr_draw_mouse_t vga_pxlmouse_packed;
89 static vr_draw_mouse_t vga_pxlmouse_planar;
91 #define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop
92 #define vga_pxlmouse_packed (vr_draw_mouse_t *)vga_nop
93 #define vga_pxlmouse_planar (vr_draw_mouse_t *)vga_nop
95 #endif /* SC_PIXEL_MODE */
97 #ifndef SC_NO_MODE_CHANGE
98 static vr_draw_border_t vga_grborder;
101 static void vga_nop(scr_stat *scp, ...);
103 static sc_rndr_sw_t txtrndrsw = {
111 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set);
114 static sc_rndr_sw_t directrndrsw = {
115 vga_pxlborder_direct,
118 vga_pxlcursor_direct,
122 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set);
124 static sc_rndr_sw_t packedrndrsw = {
125 vga_pxlborder_packed,
128 vga_pxlcursor_packed,
132 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set);
134 static sc_rndr_sw_t planarrndrsw = {
135 vga_pxlborder_planar,
138 vga_pxlcursor_planar,
142 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set);
143 #endif /* SC_PIXEL_MODE */
145 #ifndef SC_NO_MODE_CHANGE
146 static sc_rndr_sw_t grrndrsw = {
148 (vr_draw_t *)vga_nop,
149 (vr_set_cursor_t *)vga_nop,
150 (vr_draw_cursor_t *)vga_nop,
151 (vr_blink_cursor_t *)vga_nop,
152 (vr_draw_mouse_t *)vga_nop,
154 RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set);
155 #endif /* SC_NO_MODE_CHANGE */
157 RENDERER_MODULE(vga, vga_set);
159 #ifndef SC_NO_CUTPASTE
160 static u_short mouse_and_mask[16] = {
161 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
162 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
164 static u_short mouse_or_mask[16] = {
165 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
166 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
171 vga_nop(scr_stat *scp, ...)
175 /* text mode renderer */
178 vga_txtborder(scr_stat *scp, int color)
180 lwkt_gettoken(&tty_token);
181 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
182 lwkt_reltoken(&tty_token);
186 vga_txtdraw(scr_stat *scp, int from, int count, int flip)
192 if (from + count > scp->xsize*scp->ysize)
193 count = scp->xsize*scp->ysize - from;
196 for (p = scp->scr.vtb_buffer + from; count-- > 0; ++from) {
197 c = sc_vtb_getc(&scp->vtb, from);
198 a = sc_vtb_geta(&scp->vtb, from);
199 a = (a & 0x8800) | ((a & 0x7000) >> 4)
200 | ((a & 0x0700) << 4);
201 p = sc_vtb_putchar(&scp->scr, p, c, a);
204 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
209 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
211 if (base < 0 || base >= scp->font_size)
213 lwkt_gettoken(&tty_token);
214 /* the caller may set height <= 0 in order to disable the cursor */
216 scp->cursor_base = base;
217 scp->cursor_height = height;
219 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
221 scp->font_size, blink);
222 lwkt_reltoken(&tty_token);
226 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
231 scp->cursor_saveunder_char = c;
232 scp->cursor_saveunder_attr = a;
234 //lwkt_gettoken(&tty_token);
235 #ifndef SC_NO_FONT_LOADING
236 if (sc->flags & SC_CHAR_CURSOR) {
241 if (scp->font_size < 14) {
244 } else if (scp->font_size >= 16) {
251 if (scp->cursor_base >= h) {
252 lwkt_reltoken(&tty_token);
257 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
258 bcopy(font + c*h, font + sc->cursor_char*h, h);
259 font = font + sc->cursor_char*h;
260 for (i = imax(h - scp->cursor_base - scp->cursor_height, 0);
261 i < h - scp->cursor_base; ++i) {
264 sc->font_loading_in_progress = TRUE;
266 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font,
268 sc->font_loading_in_progress = FALSE;
269 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a);
271 #endif /* SC_NO_FONT_LOADING */
273 if ((a & 0x7000) == 0x7000) {
275 if ((a & 0x0700) == 0)
279 if ((a & 0x0700) == 0x0700)
284 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
285 sc_vtb_putc(&scp->scr, at, c, a);
287 //lwkt_reltoken(&tty_token);
291 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
293 video_adapter_t *adp;
296 if (scp->cursor_height <= 0) /* the text cursor is disabled */
299 //lwkt_gettoken(&tty_token);
302 scp->status |= VR_CURSOR_BLINK;
304 scp->status |= VR_CURSOR_ON;
305 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
309 if (scp->status & VR_CURSOR_ON)
310 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
312 scp->status &= ~VR_CURSOR_ON;
315 scp->status &= ~VR_CURSOR_BLINK;
317 scp->status |= VR_CURSOR_ON;
318 draw_txtcharcursor(scp, at,
319 sc_vtb_getc(&scp->scr, at),
320 sc_vtb_geta(&scp->scr, at),
323 cursor_attr = scp->cursor_saveunder_attr;
325 cursor_attr = (cursor_attr & 0x8800)
326 | ((cursor_attr & 0x7000) >> 4)
327 | ((cursor_attr & 0x0700) << 4);
328 if (scp->status & VR_CURSOR_ON)
329 sc_vtb_putc(&scp->scr, at,
330 scp->cursor_saveunder_char,
332 scp->status &= ~VR_CURSOR_ON;
335 //lwkt_reltoken(&tty_token);
339 vga_txtblink(scr_stat *scp, int at, int flip)
343 #ifndef SC_NO_CUTPASTE
346 draw_txtmouse(scr_stat *scp, int x, int y)
348 #ifndef SC_ALT_MOUSE_IMAGE
349 if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
350 u_char font_buf[128];
354 int xoffset, yoffset;
357 lwkt_gettoken(&tty_token);
359 /* prepare mousepointer char's bitmaps */
360 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
361 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
362 &font_buf[0], scp->font_size);
363 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size,
364 &font_buf[32], scp->font_size);
366 + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size,
367 &font_buf[64], scp->font_size);
369 + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size,
370 &font_buf[96], scp->font_size);
371 for (i = 0; i < scp->font_size; ++i) {
372 cursor[i] = font_buf[i]<<8 | font_buf[i+32];
373 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
376 /* now and-or in the mousepointer image */
378 yoffset = y%scp->font_size;
379 for (i = 0; i < 16; ++i) {
380 cursor[i + yoffset] =
381 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
382 | (mouse_or_mask[i] >> xoffset);
384 for (i = 0; i < scp->font_size; ++i) {
385 font_buf[i] = (cursor[i] & 0xff00) >> 8;
386 font_buf[i + 32] = cursor[i] & 0xff;
387 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
388 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
392 /* wait for vertical retrace to avoid jitter on some videocards */
393 while (!(inb(CRTC + 6) & 0x08)) /* idle */ ;
395 c = scp->sc->mouse_char;
396 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
399 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
400 /* FIXME: may be out of range! */
401 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
402 sc_vtb_geta(&scp->scr, pos + scp->xsize));
403 if (x < (scp->xsize - 1)*8) {
404 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
405 sc_vtb_geta(&scp->scr, pos + 1));
406 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
407 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
410 #endif /* SC_ALT_MOUSE_IMAGE */
412 /* Red, magenta and brown are mapped to green to to keep it readable */
413 static const int col_conv[16] = {
414 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
420 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
421 a = sc_vtb_geta(&scp->scr, pos);
422 if (scp->sc->adp->va_flags & V_ADP_COLOR)
423 color = (col_conv[(a & 0xf000) >> 12] << 12)
424 | ((a & 0x0f00) | 0x0800);
426 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
427 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
430 lwkt_reltoken(&tty_token);
434 remove_txtmouse(scr_stat *scp, int x, int y)
439 vga_txtmouse(scr_stat *scp, int x, int y, int on)
442 draw_txtmouse(scp, x, y);
444 remove_txtmouse(scp, x, y);
447 #endif /* SC_NO_CUTPASTE */
451 /* pixel (raster text) mode renderer */
454 vga_pxlborder_direct(scr_stat *scp, int color)
457 int line_width, pixel_size;
459 vm_offset_t draw_pos, draw_end, p;
461 line_width = scp->sc->adp->va_line_width;
462 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
464 for (i = 0; i < 4 / pixel_size; ++i)
465 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
468 draw_pos = scp->sc->adp->va_window;
469 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
471 for (p = draw_pos; p < draw_end; p += 4)
475 y = (scp->yoff + scp->ysize) * scp->font_size;
477 if (scp->ypixel > y) {
478 draw_pos = scp->sc->adp->va_window + line_width * y;
479 draw_end = draw_pos + line_width * (scp->ypixel - y);
481 for (p = draw_pos; p < draw_end; p += 4)
485 y = scp->yoff * scp->font_size;
486 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
488 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
490 draw_pos = scp->sc->adp->va_window +
491 line_width * (y + i);
492 draw_end = draw_pos + scp->xoff * 8 * pixel_size;
494 for (p = draw_pos; p < draw_end; p += 4)
499 draw_pos = scp->sc->adp->va_window +
500 line_width * (y + i) +
501 scp->xoff * 8 * pixel_size +
502 scp->xsize * 8 * pixel_size;
503 draw_end = draw_pos + x * 8 * pixel_size;
505 for (p = draw_pos; p < draw_end; p += 4)
512 vga_pxlborder_packed(scr_stat *scp, int color)
517 vm_offset_t draw_pos, draw_end, p;
519 line_width = scp->sc->adp->va_line_width;
520 u32 = (color << 24) + (color << 16) + (color << 8) + color;
523 draw_pos = scp->sc->adp->va_window;
524 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
526 for (p = draw_pos; p < draw_end; p += 4)
530 y = (scp->yoff + scp->ysize) * scp->font_size;
532 if (scp->ypixel > y) {
533 draw_pos = scp->sc->adp->va_window + line_width * y;
534 draw_end = draw_pos + line_width * (scp->ypixel - y);
536 for (p = draw_pos; p < draw_end; p += 4)
540 y = scp->yoff * scp->font_size;
541 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
543 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
545 draw_pos = scp->sc->adp->va_window +
546 line_width * (y + i);
547 draw_end = draw_pos + scp->xoff * 8;
549 for (p = draw_pos; p < draw_end; p += 4)
554 draw_pos = scp->sc->adp->va_window +
555 line_width * (y + i) + scp->xoff * 8 +
557 draw_end = draw_pos + x * 8;
559 for (p = draw_pos; p < draw_end; p += 4)
566 vga_pxlborder_planar(scr_stat *scp, int color)
574 lwkt_gettoken(&tty_token);
576 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
578 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
579 outw(GDCIDX, 0x0003); /* data rotate/function select */
580 outw(GDCIDX, 0x0f01); /* set/reset enable */
581 outw(GDCIDX, 0xff08); /* bit mask */
582 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
583 line_width = scp->sc->adp->va_line_width;
584 p = scp->sc->adp->va_window;
586 bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
587 y = (scp->yoff + scp->ysize)*scp->font_size;
589 bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y));
590 y = scp->yoff*scp->font_size;
591 x = scp->xpixel/8 - scp->xoff - scp->xsize;
592 for (i = 0; i < scp->ysize*scp->font_size; ++i) {
594 bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
596 bzero_io((void *)(p + line_width*(y + i)
597 + scp->xoff + scp->xsize), x);
599 outw(GDCIDX, 0x0000); /* set/reset */
600 outw(GDCIDX, 0x0001); /* set/reset enable */
601 lwkt_reltoken(&tty_token);
605 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
607 int line_width, pixel_size;
608 int a, i, j, k, l, pos;
609 uint32_t fg, bg, u32;
610 unsigned char *char_data;
611 vm_offset_t draw_pos, p;
613 line_width = scp->sc->adp->va_line_width;
614 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
616 draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
618 if (from + count > scp->xsize * scp->ysize)
619 count = scp->xsize * scp->ysize - from;
621 for (i = from; count-- > 0; ++i) {
622 a = sc_vtb_geta(&scp->vtb, i);
625 fg = scp->ega_palette[(((a & 0x7000) >> 4) |
627 bg = scp->ega_palette[(((a & 0x8000) >> 4) |
630 fg = scp->ega_palette[(a & 0x0f00) >> 8];
631 bg = scp->ega_palette[(a & 0xf000) >> 12];
635 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
638 for (j = 0; j < scp->font_size; ++j, ++char_data) {
641 for (k = 0; k < 2 * pixel_size; ++k) {
644 for (l = 0; l < 4 / pixel_size; ++l) {
645 u32 += (*char_data & (1 << pos--) ?
646 fg : bg) << (l * 8 * pixel_size);
653 p += line_width - 8 * pixel_size;
656 draw_pos += 8 * pixel_size;
658 if ((i % scp->xsize) == scp->xsize - 1)
659 draw_pos += scp->xoff * 16 * pixel_size +
660 (scp->font_size - 1) * line_width;
665 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
669 uint32_t fg, bg, u32;
670 unsigned char *char_data;
671 vm_offset_t draw_pos, p;
673 line_width = scp->sc->adp->va_line_width;
675 draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
677 if (from + count > scp->xsize * scp->ysize)
678 count = scp->xsize * scp->ysize - from;
680 for (i = from; count-- > 0; ++i) {
681 a = sc_vtb_geta(&scp->vtb, i);
684 fg = ((a & 0xf000) >> 4) >> 8;
685 bg = (a & 0x0f00) >> 8;
687 fg = (a & 0x0f00) >> 8;
688 bg = ((a & 0xf000) >> 4) >> 8;
692 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
695 for (j = 0; j < scp->font_size; ++j, ++char_data) {
696 u32 = ((*char_data & 1 ? fg : bg) << 24) +
697 ((*char_data & 2 ? fg : bg) << 16) +
698 ((*char_data & 4 ? fg : bg) << 8) +
699 (*char_data & 8 ? fg : bg);
702 u32 = ((*char_data & 16 ? fg : bg) << 24) +
703 ((*char_data & 32 ? fg : bg) << 16) +
704 ((*char_data & 64 ? fg : bg) << 8) +
705 (*char_data & 128 ? fg : bg);
713 if ((i % scp->xsize) == scp->xsize - 1)
714 draw_pos += scp->xoff * 16 +
715 (scp->font_size - 1) * line_width;
720 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
732 d = VIDEO_MEMORY_POS(scp, from, 1);
734 line_width = scp->sc->adp->va_line_width;
736 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
737 outw(GDCIDX, 0x0003); /* data rotate/function select */
738 outw(GDCIDX, 0x0f01); /* set/reset enable */
739 outw(GDCIDX, 0xff08); /* bit mask */
741 if (from + count > scp->xsize*scp->ysize)
742 count = scp->xsize*scp->ysize - from;
743 for (i = from; count-- > 0; ++i) {
744 a = sc_vtb_geta(&scp->vtb, i);
746 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
747 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
750 col2 = (a & 0xf000) >> 4;
752 /* set background color in EGA/VGA latch */
755 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
756 outw(GDCIDX, bg | 0x00); /* set/reset */
758 c = readb(d); /* set bg color in the latch */
759 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
761 /* foreground color */
762 outw(GDCIDX, col1 | 0x00); /* set/reset */
764 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
765 for (j = 0; j < scp->font_size; ++j, ++f) {
770 if ((i % scp->xsize) == scp->xsize - 1)
772 + (scp->font_size - 1)*line_width;
774 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
775 outw(GDCIDX, 0x0000); /* set/reset */
776 outw(GDCIDX, 0x0001); /* set/reset enable */
780 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
782 if (base < 0 || base >= scp->font_size)
784 /* the caller may set height <= 0 in order to disable the cursor */
786 scp->cursor_base = base;
787 scp->cursor_height = height;
792 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
794 int line_width, pixel_size, height;
796 uint32_t fg, bg, u32;
797 unsigned char *char_data;
798 vm_offset_t draw_pos;
800 line_width = scp->sc->adp->va_line_width;
801 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
803 draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
804 (scp->font_size - scp->cursor_base - 1) * line_width;
806 a = sc_vtb_geta(&scp->vtb, at);
809 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
810 ((a & 0xf000) >> 4)) >> 8];
811 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
814 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
816 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
817 ((a & 0xf000) >> 4)) >> 8];
820 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
821 scp->font_size - scp->cursor_base - 1]);
823 height = imin(scp->cursor_height, scp->font_size);
825 for (i = 0; i < height; ++i, --char_data) {
828 for (j = 0; j < 2 * pixel_size; ++j) {
831 for (k = 0; k < 4 / pixel_size; ++k) {
832 u32 += (*char_data & (1 << pos--) ?
833 fg : bg) << (k * 8 * pixel_size);
836 writel(draw_pos, u32);
840 draw_pos -= line_width + 8 * pixel_size;
845 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
847 int line_width, height;
849 uint32_t fg, bg, u32;
850 unsigned char *char_data;
851 vm_offset_t draw_pos;
853 line_width = scp->sc->adp->va_line_width;
855 draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
856 (scp->font_size - scp->cursor_base - 1) * line_width;
858 a = sc_vtb_geta(&scp->vtb, at);
861 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
862 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
864 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
865 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
868 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
869 scp->font_size - scp->cursor_base - 1]);
871 height = imin(scp->cursor_height, scp->font_size);
873 for (i = 0; i < height; ++i, --char_data) {
874 u32 = ((*char_data & 1 ? fg : bg) << 24) +
875 ((*char_data & 2 ? fg : bg) << 16) +
876 ((*char_data & 4 ? fg : bg) << 8) +
877 (*char_data & 8 ? fg : bg);
878 writel(draw_pos + 4, u32);
880 u32 = ((*char_data & 16 ? fg : bg) << 24) +
881 ((*char_data & 32 ? fg : bg) << 16) +
882 ((*char_data & 64 ? fg : bg) << 8) +
883 (*char_data & 128 ? fg : bg);
884 writel(draw_pos, u32);
886 draw_pos -= line_width;
891 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
902 line_width = scp->sc->adp->va_line_width;
904 d = VIDEO_MEMORY_POS(scp, at, 1) +
905 (scp->font_size - scp->cursor_base - 1) * line_width;
907 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
908 outw(GDCIDX, 0x0003); /* data rotate/function select */
909 outw(GDCIDX, 0x0f01); /* set/reset enable */
910 /* set background color in EGA/VGA latch */
911 a = sc_vtb_geta(&scp->vtb, at);
913 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
915 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
916 outw(GDCIDX, col | 0x00); /* set/reset */
917 outw(GDCIDX, 0xff08); /* bit mask */
919 c = readb(d); /* set bg color in the latch */
920 /* foreground color */
922 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
924 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
925 outw(GDCIDX, col | 0x00); /* set/reset */
926 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
927 + scp->font_size - scp->cursor_base - 1]);
928 height = imin(scp->cursor_height, scp->font_size);
929 for (i = 0; i < height; ++i, --f) {
930 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
934 outw(GDCIDX, 0x0000); /* set/reset */
935 outw(GDCIDX, 0x0001); /* set/reset enable */
936 outw(GDCIDX, 0xff08); /* bit mask */
939 static int pxlblinkrate = 0;
942 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
944 if (scp->cursor_height <= 0) /* the text cursor is disabled */
949 scp->status |= VR_CURSOR_ON;
950 draw_pxlcursor_direct(scp, at, on, flip);
951 } else if (++pxlblinkrate & 4) {
953 scp->status ^= VR_CURSOR_ON;
954 draw_pxlcursor_direct(scp, at,
955 scp->status & VR_CURSOR_ON,
959 if (scp->status & VR_CURSOR_ON)
960 draw_pxlcursor_direct(scp, at, on, flip);
961 scp->status &= ~VR_CURSOR_ON;
964 scp->status |= VR_CURSOR_BLINK;
966 scp->status &= ~VR_CURSOR_BLINK;
970 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
972 if (scp->cursor_height <= 0) /* the text cursor is disabled */
977 scp->status |= VR_CURSOR_ON;
978 draw_pxlcursor_packed(scp, at, on, flip);
979 } else if (++pxlblinkrate & 4) {
981 scp->status ^= VR_CURSOR_ON;
982 draw_pxlcursor_packed(scp, at,
983 scp->status & VR_CURSOR_ON,
987 if (scp->status & VR_CURSOR_ON)
988 draw_pxlcursor_packed(scp, at, on, flip);
989 scp->status &= ~VR_CURSOR_ON;
992 scp->status |= VR_CURSOR_BLINK;
994 scp->status &= ~VR_CURSOR_BLINK;
998 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
1000 if (scp->cursor_height <= 0) /* the text cursor is disabled */
1005 scp->status |= VR_CURSOR_ON;
1006 draw_pxlcursor_planar(scp, at, on, flip);
1007 } else if (++pxlblinkrate & 4) {
1009 scp->status ^= VR_CURSOR_ON;
1010 draw_pxlcursor_planar(scp, at,
1011 scp->status & VR_CURSOR_ON,
1015 if (scp->status & VR_CURSOR_ON)
1016 draw_pxlcursor_planar(scp, at, on, flip);
1017 scp->status &= ~VR_CURSOR_ON;
1020 scp->status |= VR_CURSOR_BLINK;
1022 scp->status &= ~VR_CURSOR_BLINK;
1026 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1028 if (!(scp->status & VR_CURSOR_BLINK))
1030 if (!(++pxlblinkrate & 4))
1033 scp->status ^= VR_CURSOR_ON;
1034 draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1038 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1040 if (!(scp->status & VR_CURSOR_BLINK))
1042 if (!(++pxlblinkrate & 4))
1045 scp->status ^= VR_CURSOR_ON;
1046 draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1050 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1052 if (!(scp->status & VR_CURSOR_BLINK))
1054 if (!(++pxlblinkrate & 4))
1057 scp->status ^= VR_CURSOR_ON;
1058 draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1061 #ifndef SC_NO_CUTPASTE
1064 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1066 int line_width, pixel_size;
1069 vm_offset_t draw_pos;
1071 line_width = scp->sc->adp->va_line_width;
1072 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1074 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1075 yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1077 draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1079 for (i = 0; i < (yend - y); i++) {
1080 for (j = (xend - x - 1); j >= 0; j--) {
1081 switch (scp->sc->adp->va_info.vi_depth) {
1083 if (mouse_or_mask[i] & 1 << (15 - j))
1084 writel(draw_pos + 4 * j,
1085 scp->ega_palette[15]);
1086 else if (mouse_and_mask[i] & 1 << (15 - j))
1087 writel(draw_pos + 4 * j,
1088 scp->ega_palette[0]);
1093 if (mouse_or_mask[i] & 1 << (15 - j))
1094 writew(draw_pos + 2 * j,
1095 scp->ega_palette[15]);
1096 else if (mouse_and_mask[i] & 1 << (15 - j))
1097 writew(draw_pos + 2 * j,
1098 scp->ega_palette[0]);
1103 draw_pos += line_width;
1108 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1113 vm_offset_t draw_pos;
1115 line_width = scp->sc->adp->va_line_width;
1117 xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel));
1118 yend = imin(scp->font_size * (scp->yoff + scp->ysize),
1119 imin(y + 16, scp->ypixel));
1121 draw_pos = scp->sc->adp->va_window + y * line_width + x;
1123 for (i = 0; i < (yend - y); i++) {
1124 for (j = (xend - x - 1); j >= 0; j--) {
1125 if (mouse_or_mask[i] & 1 << (15 - j))
1126 writeb(draw_pos + j, 15);
1127 else if (mouse_and_mask[i] & 1 << (15 - j))
1128 writeb(draw_pos + j, 0);
1131 draw_pos += line_width;
1136 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1145 line_width = scp->sc->adp->va_line_width;
1146 xoff = (x - scp->xoff*8)%8;
1147 ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1149 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
1150 outw(GDCIDX, 0x0001); /* set/reset enable */
1151 outw(GDCIDX, 0x0002); /* color compare */
1152 outw(GDCIDX, 0x0007); /* color don't care */
1153 outw(GDCIDX, 0xff08); /* bit mask */
1154 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
1155 p = scp->sc->adp->va_window + line_width*y + x/8;
1156 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1157 for (i = y, j = 0; i < ymax; ++i, ++j) {
1158 m = ~(mouse_and_mask[j] >> xoff);
1159 *(u_char *)p &= m >> 8;
1160 *(u_char *)(p + 1) &= m;
1165 for (i = y, j = 0; i < ymax; ++i, ++j) {
1166 m = ~(mouse_and_mask[j] >> xoff);
1171 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
1172 p = scp->sc->adp->va_window + line_width*y + x/8;
1173 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1174 for (i = y, j = 0; i < ymax; ++i, ++j) {
1175 m = mouse_or_mask[j] >> xoff;
1176 *(u_char *)p &= m >> 8;
1177 *(u_char *)(p + 1) &= m;
1181 for (i = y, j = 0; i < ymax; ++i, ++j) {
1182 m = mouse_or_mask[j] >> xoff;
1187 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
1188 outw(GDCIDX, 0x0003); /* data rotate/function select */
1192 remove_pxlmouse(scr_stat *scp, int x, int y)
1198 /* erase the mouse cursor image */
1199 col = x/8 - scp->xoff;
1200 row = y/scp->font_size - scp->yoff;
1201 pos = row*scp->xsize + col;
1202 i = (col < scp->xsize - 1) ? 2 : 1;
1203 (*scp->rndr->draw)(scp, pos, i, FALSE);
1204 if (row < scp->ysize - 1)
1205 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1209 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1212 draw_pxlmouse_direct(scp, x, y);
1214 remove_pxlmouse(scp, x, y);
1218 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1221 draw_pxlmouse_packed(scp, x, y);
1223 remove_pxlmouse(scp, x, y);
1227 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1230 draw_pxlmouse_planar(scp, x, y);
1232 remove_pxlmouse(scp, x, y);
1235 #endif /* SC_NO_CUTPASTE */
1236 #endif /* SC_PIXEL_MODE */
1238 #ifndef SC_NO_MODE_CHANGE
1240 /* graphics mode renderer */
1243 vga_grborder(scr_stat *scp, int color)
1245 lwkt_gettoken(&tty_token);
1246 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1247 lwkt_reltoken(&tty_token);