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>
52 static vr_draw_border_t vga_txtborder;
53 static vr_draw_t vga_txtdraw;
54 static vr_set_cursor_t vga_txtcursor_shape;
55 static vr_draw_cursor_t vga_txtcursor;
56 static vr_blink_cursor_t vga_txtblink;
57 #ifndef SC_NO_CUTPASTE
58 static vr_draw_mouse_t vga_txtmouse;
60 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop
64 static vr_draw_border_t vga_pxlborder_direct;
65 static vr_draw_border_t vga_pxlborder_packed;
66 static vr_draw_border_t vga_pxlborder_planar;
67 static vr_draw_t vga_vgadraw_direct;
68 static vr_draw_t vga_vgadraw_packed;
69 static vr_draw_t vga_vgadraw_planar;
70 static vr_set_cursor_t vga_pxlcursor_shape;
71 static vr_draw_cursor_t vga_pxlcursor_direct;
72 static vr_draw_cursor_t vga_pxlcursor_packed;
73 static vr_draw_cursor_t vga_pxlcursor_planar;
74 static vr_blink_cursor_t vga_pxlblink_direct;
75 static vr_blink_cursor_t vga_pxlblink_packed;
76 static vr_blink_cursor_t vga_pxlblink_planar;
77 #ifndef SC_NO_CUTPASTE
78 static vr_draw_mouse_t vga_pxlmouse_direct;
79 static vr_draw_mouse_t vga_pxlmouse_packed;
80 static vr_draw_mouse_t vga_pxlmouse_planar;
82 #define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop
83 #define vga_pxlmouse_packed (vr_draw_mouse_t *)vga_nop
84 #define vga_pxlmouse_planar (vr_draw_mouse_t *)vga_nop
86 #endif /* SC_PIXEL_MODE */
88 #ifndef SC_NO_MODE_CHANGE
89 static vr_draw_border_t vga_grborder;
92 static void vga_nop(scr_stat *scp, ...);
94 static sc_rndr_sw_t txtrndrsw = {
102 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set);
105 static sc_rndr_sw_t directrndrsw = {
106 vga_pxlborder_direct,
109 vga_pxlcursor_direct,
113 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set);
115 static sc_rndr_sw_t packedrndrsw = {
116 vga_pxlborder_packed,
119 vga_pxlcursor_packed,
123 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set);
125 static sc_rndr_sw_t planarrndrsw = {
126 vga_pxlborder_planar,
129 vga_pxlcursor_planar,
133 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set);
134 #endif /* SC_PIXEL_MODE */
136 #ifndef SC_NO_MODE_CHANGE
137 static sc_rndr_sw_t grrndrsw = {
139 (vr_draw_t *)vga_nop,
140 (vr_set_cursor_t *)vga_nop,
141 (vr_draw_cursor_t *)vga_nop,
142 (vr_blink_cursor_t *)vga_nop,
143 (vr_draw_mouse_t *)vga_nop,
145 RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set);
146 #endif /* SC_NO_MODE_CHANGE */
148 RENDERER_MODULE(vga, vga_set);
150 #ifndef SC_NO_CUTPASTE
151 static u_short mouse_and_mask[16] = {
152 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
153 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
155 static u_short mouse_or_mask[16] = {
156 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
157 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
162 vga_nop(scr_stat *scp, ...)
166 /* text mode renderer */
169 vga_txtborder(scr_stat *scp, int color)
171 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
175 vga_txtdraw(scr_stat *scp, int from, int count, int flip)
181 if (from + count > scp->xsize*scp->ysize)
182 count = scp->xsize*scp->ysize - from;
185 for (p = scp->scr.vtb_buffer + from; count-- > 0; ++from) {
186 c = sc_vtb_getc(&scp->vtb, from);
187 a = sc_vtb_geta(&scp->vtb, from);
188 a = (a & 0x8800) | ((a & 0x7000) >> 4)
189 | ((a & 0x0700) << 4);
190 p = sc_vtb_putchar(&scp->scr, p, c, a);
193 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
198 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
200 if (base < 0 || base >= scp->font_size)
203 /* the caller may set height <= 0 in order to disable the cursor */
205 scp->cursor_base = base;
206 scp->cursor_height = height;
208 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
210 scp->font_size, blink);
215 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
220 scp->cursor_saveunder_char = c;
221 scp->cursor_saveunder_attr = a;
223 #ifndef SC_NO_FONT_LOADING
224 if (sc->flags & SC_CHAR_CURSOR) {
229 if (scp->font_size < 14) {
232 } else if (scp->font_size >= 16) {
239 if (scp->cursor_base >= h)
243 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
244 bcopy(font + c*h, font + sc->cursor_char*h, h);
245 font = font + sc->cursor_char*h;
246 for (i = imax(h - scp->cursor_base - scp->cursor_height, 0);
247 i < h - scp->cursor_base; ++i) {
250 sc->font_loading_in_progress = TRUE;
252 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font,
254 sc->font_loading_in_progress = FALSE;
255 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a);
257 #endif /* SC_NO_FONT_LOADING */
259 if ((a & 0x7000) == 0x7000) {
261 if ((a & 0x0700) == 0)
265 if ((a & 0x0700) == 0x0700)
270 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
271 sc_vtb_putc(&scp->scr, at, c, a);
276 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
278 video_adapter_t *adp;
281 if (scp->cursor_height <= 0) /* the text cursor is disabled */
286 scp->status |= VR_CURSOR_BLINK;
288 scp->status |= VR_CURSOR_ON;
289 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
293 if (scp->status & VR_CURSOR_ON)
294 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
296 scp->status &= ~VR_CURSOR_ON;
299 scp->status &= ~VR_CURSOR_BLINK;
301 scp->status |= VR_CURSOR_ON;
302 draw_txtcharcursor(scp, at,
303 sc_vtb_getc(&scp->scr, at),
304 sc_vtb_geta(&scp->scr, at),
307 cursor_attr = scp->cursor_saveunder_attr;
309 cursor_attr = (cursor_attr & 0x8800)
310 | ((cursor_attr & 0x7000) >> 4)
311 | ((cursor_attr & 0x0700) << 4);
312 if (scp->status & VR_CURSOR_ON)
313 sc_vtb_putc(&scp->scr, at,
314 scp->cursor_saveunder_char,
316 scp->status &= ~VR_CURSOR_ON;
322 vga_txtblink(scr_stat *scp, int at, int flip)
326 #ifndef SC_NO_CUTPASTE
329 draw_txtmouse(scr_stat *scp, int x, int y)
331 #ifndef SC_ALT_MOUSE_IMAGE
332 if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
333 u_char font_buf[128];
337 int xoffset, yoffset;
340 /* prepare mousepointer char's bitmaps */
341 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
342 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
343 &font_buf[0], scp->font_size);
344 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size,
345 &font_buf[32], scp->font_size);
347 + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size,
348 &font_buf[64], scp->font_size);
350 + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size,
351 &font_buf[96], scp->font_size);
352 for (i = 0; i < scp->font_size; ++i) {
353 cursor[i] = font_buf[i]<<8 | font_buf[i+32];
354 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
357 /* now and-or in the mousepointer image */
359 yoffset = y%scp->font_size;
360 for (i = 0; i < 16; ++i) {
361 cursor[i + yoffset] =
362 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
363 | (mouse_or_mask[i] >> xoffset);
365 for (i = 0; i < scp->font_size; ++i) {
366 font_buf[i] = (cursor[i] & 0xff00) >> 8;
367 font_buf[i + 32] = cursor[i] & 0xff;
368 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
369 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
373 /* wait for vertical retrace to avoid jitter on some videocards */
374 while (!(inb(CRTC + 6) & 0x08)) /* idle */ ;
376 c = scp->sc->mouse_char;
377 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
380 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
381 /* FIXME: may be out of range! */
382 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
383 sc_vtb_geta(&scp->scr, pos + scp->xsize));
384 if (x < (scp->xsize - 1)*8) {
385 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
386 sc_vtb_geta(&scp->scr, pos + 1));
387 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
388 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
391 #endif /* SC_ALT_MOUSE_IMAGE */
393 /* Red, magenta and brown are mapped to green to to keep it readable */
394 static const int col_conv[16] = {
395 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
401 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
402 a = sc_vtb_geta(&scp->scr, pos);
403 if (scp->sc->adp->va_flags & V_ADP_COLOR)
404 color = (col_conv[(a & 0xf000) >> 12] << 12)
405 | ((a & 0x0f00) | 0x0800);
407 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
408 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
414 remove_txtmouse(scr_stat *scp, int x, int y)
419 vga_txtmouse(scr_stat *scp, int x, int y, int on)
422 draw_txtmouse(scp, x, y);
424 remove_txtmouse(scp, x, y);
427 #endif /* SC_NO_CUTPASTE */
431 /* pixel (raster text) mode renderer */
434 vga_pxlborder_direct(scr_stat *scp, int color)
437 int line_width, pixel_size;
439 vm_offset_t draw_pos, draw_end, p;
441 line_width = scp->sc->adp->va_line_width;
442 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
444 for (i = 0; i < 4 / pixel_size; ++i)
445 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
448 draw_pos = scp->sc->adp->va_window;
449 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
451 for (p = draw_pos; p < draw_end; p += 4)
455 y = (scp->yoff + scp->ysize) * scp->font_size;
457 if (scp->ypixel > y) {
458 draw_pos = scp->sc->adp->va_window + line_width * y;
459 draw_end = draw_pos + line_width * (scp->ypixel - y);
461 for (p = draw_pos; p < draw_end; p += 4)
465 y = scp->yoff * scp->font_size;
466 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
468 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
470 draw_pos = scp->sc->adp->va_window +
471 line_width * (y + i);
472 draw_end = draw_pos + scp->xoff * 8 * pixel_size;
474 for (p = draw_pos; p < draw_end; p += 4)
479 draw_pos = scp->sc->adp->va_window +
480 line_width * (y + i) +
481 scp->xoff * 8 * pixel_size +
482 scp->xsize * 8 * pixel_size;
483 draw_end = draw_pos + x * 8 * pixel_size;
485 for (p = draw_pos; p < draw_end; p += 4)
492 vga_pxlborder_packed(scr_stat *scp, int color)
497 vm_offset_t draw_pos, draw_end, p;
499 line_width = scp->sc->adp->va_line_width;
500 u32 = (color << 24) + (color << 16) + (color << 8) + color;
503 draw_pos = scp->sc->adp->va_window;
504 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
506 for (p = draw_pos; p < draw_end; p += 4)
510 y = (scp->yoff + scp->ysize) * scp->font_size;
512 if (scp->ypixel > y) {
513 draw_pos = scp->sc->adp->va_window + line_width * y;
514 draw_end = draw_pos + line_width * (scp->ypixel - y);
516 for (p = draw_pos; p < draw_end; p += 4)
520 y = scp->yoff * scp->font_size;
521 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
523 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
525 draw_pos = scp->sc->adp->va_window +
526 line_width * (y + i);
527 draw_end = draw_pos + scp->xoff * 8;
529 for (p = draw_pos; p < draw_end; p += 4)
534 draw_pos = scp->sc->adp->va_window +
535 line_width * (y + i) + scp->xoff * 8 +
537 draw_end = draw_pos + x * 8;
539 for (p = draw_pos; p < draw_end; p += 4)
546 vga_pxlborder_planar(scr_stat *scp, int color)
554 lwkt_gettoken(&tty_token);
556 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
558 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
559 outw(GDCIDX, 0x0003); /* data rotate/function select */
560 outw(GDCIDX, 0x0f01); /* set/reset enable */
561 outw(GDCIDX, 0xff08); /* bit mask */
562 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
563 line_width = scp->sc->adp->va_line_width;
564 p = scp->sc->adp->va_window;
566 bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
567 y = (scp->yoff + scp->ysize)*scp->font_size;
569 bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y));
570 y = scp->yoff*scp->font_size;
571 x = scp->xpixel/8 - scp->xoff - scp->xsize;
572 for (i = 0; i < scp->ysize*scp->font_size; ++i) {
574 bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
576 bzero_io((void *)(p + line_width*(y + i)
577 + scp->xoff + scp->xsize), x);
579 outw(GDCIDX, 0x0000); /* set/reset */
580 outw(GDCIDX, 0x0001); /* set/reset enable */
581 lwkt_reltoken(&tty_token);
585 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
587 int line_width, pixel_size;
588 int a, i, j, k, l, pos;
589 uint32_t fg, bg, u32;
590 unsigned char *char_data;
591 vm_offset_t draw_pos, p;
593 line_width = scp->sc->adp->va_line_width;
594 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
596 draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
598 if (from + count > scp->xsize * scp->ysize)
599 count = scp->xsize * scp->ysize - from;
601 for (i = from; count-- > 0; ++i) {
602 a = sc_vtb_geta(&scp->vtb, i);
605 fg = scp->ega_palette[(((a & 0x7000) >> 4) |
607 bg = scp->ega_palette[(((a & 0x8000) >> 4) |
610 fg = scp->ega_palette[(a & 0x0f00) >> 8];
611 bg = scp->ega_palette[(a & 0xf000) >> 12];
615 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
618 for (j = 0; j < scp->font_size; ++j, ++char_data) {
621 for (k = 0; k < 2 * pixel_size; ++k) {
624 for (l = 0; l < 4 / pixel_size; ++l) {
625 u32 += (*char_data & (1 << pos--) ?
626 fg : bg) << (l * 8 * pixel_size);
633 p += line_width - 8 * pixel_size;
636 draw_pos += 8 * pixel_size;
638 if ((i % scp->xsize) == scp->xsize - 1)
639 draw_pos += scp->xoff * 16 * pixel_size +
640 (scp->font_size - 1) * line_width;
645 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
649 uint32_t fg, bg, u32;
650 unsigned char *char_data;
651 vm_offset_t draw_pos, p;
653 line_width = scp->sc->adp->va_line_width;
655 draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
657 if (from + count > scp->xsize * scp->ysize)
658 count = scp->xsize * scp->ysize - from;
660 for (i = from; count-- > 0; ++i) {
661 a = sc_vtb_geta(&scp->vtb, i);
664 fg = ((a & 0xf000) >> 4) >> 8;
665 bg = (a & 0x0f00) >> 8;
667 fg = (a & 0x0f00) >> 8;
668 bg = ((a & 0xf000) >> 4) >> 8;
672 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
675 for (j = 0; j < scp->font_size; ++j, ++char_data) {
676 u32 = ((*char_data & 1 ? fg : bg) << 24) +
677 ((*char_data & 2 ? fg : bg) << 16) +
678 ((*char_data & 4 ? fg : bg) << 8) +
679 (*char_data & 8 ? fg : bg);
682 u32 = ((*char_data & 16 ? fg : bg) << 24) +
683 ((*char_data & 32 ? fg : bg) << 16) +
684 ((*char_data & 64 ? fg : bg) << 8) +
685 (*char_data & 128 ? fg : bg);
693 if ((i % scp->xsize) == scp->xsize - 1)
694 draw_pos += scp->xoff * 16 +
695 (scp->font_size - 1) * line_width;
700 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
712 d = VIDEO_MEMORY_POS(scp, from, 1);
714 line_width = scp->sc->adp->va_line_width;
716 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
717 outw(GDCIDX, 0x0003); /* data rotate/function select */
718 outw(GDCIDX, 0x0f01); /* set/reset enable */
719 outw(GDCIDX, 0xff08); /* bit mask */
721 if (from + count > scp->xsize*scp->ysize)
722 count = scp->xsize*scp->ysize - from;
723 for (i = from; count-- > 0; ++i) {
724 a = sc_vtb_geta(&scp->vtb, i);
726 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
727 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
730 col2 = (a & 0xf000) >> 4;
732 /* set background color in EGA/VGA latch */
735 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
736 outw(GDCIDX, bg | 0x00); /* set/reset */
738 c = readb(d); /* set bg color in the latch */
739 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
741 /* foreground color */
742 outw(GDCIDX, col1 | 0x00); /* set/reset */
744 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
745 for (j = 0; j < scp->font_size; ++j, ++f) {
750 if ((i % scp->xsize) == scp->xsize - 1)
752 + (scp->font_size - 1)*line_width;
754 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
755 outw(GDCIDX, 0x0000); /* set/reset */
756 outw(GDCIDX, 0x0001); /* set/reset enable */
760 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
762 if (base < 0 || base >= scp->font_size)
764 /* the caller may set height <= 0 in order to disable the cursor */
766 scp->cursor_base = base;
767 scp->cursor_height = height;
772 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
774 int line_width, pixel_size, height;
776 uint32_t fg, bg, u32;
777 unsigned char *char_data;
778 vm_offset_t draw_pos;
780 line_width = scp->sc->adp->va_line_width;
781 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
783 draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
784 (scp->font_size - scp->cursor_base - 1) * line_width;
786 a = sc_vtb_geta(&scp->vtb, at);
789 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
790 ((a & 0xf000) >> 4)) >> 8];
791 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
794 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
796 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
797 ((a & 0xf000) >> 4)) >> 8];
800 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
801 scp->font_size - scp->cursor_base - 1]);
803 height = imin(scp->cursor_height, scp->font_size);
805 for (i = 0; i < height; ++i, --char_data) {
808 for (j = 0; j < 2 * pixel_size; ++j) {
811 for (k = 0; k < 4 / pixel_size; ++k) {
812 u32 += (*char_data & (1 << pos--) ?
813 fg : bg) << (k * 8 * pixel_size);
816 writel(draw_pos, u32);
820 draw_pos -= line_width + 8 * pixel_size;
825 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
827 int line_width, height;
829 uint32_t fg, bg, u32;
830 unsigned char *char_data;
831 vm_offset_t draw_pos;
833 line_width = scp->sc->adp->va_line_width;
835 draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
836 (scp->font_size - scp->cursor_base - 1) * line_width;
838 a = sc_vtb_geta(&scp->vtb, at);
841 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
842 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
844 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
845 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
848 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
849 scp->font_size - scp->cursor_base - 1]);
851 height = imin(scp->cursor_height, scp->font_size);
853 for (i = 0; i < height; ++i, --char_data) {
854 u32 = ((*char_data & 1 ? fg : bg) << 24) +
855 ((*char_data & 2 ? fg : bg) << 16) +
856 ((*char_data & 4 ? fg : bg) << 8) +
857 (*char_data & 8 ? fg : bg);
858 writel(draw_pos + 4, u32);
860 u32 = ((*char_data & 16 ? fg : bg) << 24) +
861 ((*char_data & 32 ? fg : bg) << 16) +
862 ((*char_data & 64 ? fg : bg) << 8) +
863 (*char_data & 128 ? fg : bg);
864 writel(draw_pos, u32);
866 draw_pos -= line_width;
871 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
882 line_width = scp->sc->adp->va_line_width;
884 d = VIDEO_MEMORY_POS(scp, at, 1) +
885 (scp->font_size - scp->cursor_base - 1) * line_width;
887 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
888 outw(GDCIDX, 0x0003); /* data rotate/function select */
889 outw(GDCIDX, 0x0f01); /* set/reset enable */
890 /* set background color in EGA/VGA latch */
891 a = sc_vtb_geta(&scp->vtb, at);
893 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
895 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
896 outw(GDCIDX, col | 0x00); /* set/reset */
897 outw(GDCIDX, 0xff08); /* bit mask */
899 c = readb(d); /* set bg color in the latch */
900 /* foreground color */
902 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
904 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
905 outw(GDCIDX, col | 0x00); /* set/reset */
906 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
907 + scp->font_size - scp->cursor_base - 1]);
908 height = imin(scp->cursor_height, scp->font_size);
909 for (i = 0; i < height; ++i, --f) {
910 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
914 outw(GDCIDX, 0x0000); /* set/reset */
915 outw(GDCIDX, 0x0001); /* set/reset enable */
916 outw(GDCIDX, 0xff08); /* bit mask */
919 static int pxlblinkrate = 0;
922 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
924 if (scp->cursor_height <= 0) /* the text cursor is disabled */
929 scp->status |= VR_CURSOR_ON;
930 draw_pxlcursor_direct(scp, at, on, flip);
931 } else if (++pxlblinkrate & 4) {
933 scp->status ^= VR_CURSOR_ON;
934 draw_pxlcursor_direct(scp, at,
935 scp->status & VR_CURSOR_ON,
939 if (scp->status & VR_CURSOR_ON)
940 draw_pxlcursor_direct(scp, at, on, flip);
941 scp->status &= ~VR_CURSOR_ON;
944 scp->status |= VR_CURSOR_BLINK;
946 scp->status &= ~VR_CURSOR_BLINK;
950 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
952 if (scp->cursor_height <= 0) /* the text cursor is disabled */
957 scp->status |= VR_CURSOR_ON;
958 draw_pxlcursor_packed(scp, at, on, flip);
959 } else if (++pxlblinkrate & 4) {
961 scp->status ^= VR_CURSOR_ON;
962 draw_pxlcursor_packed(scp, at,
963 scp->status & VR_CURSOR_ON,
967 if (scp->status & VR_CURSOR_ON)
968 draw_pxlcursor_packed(scp, at, on, flip);
969 scp->status &= ~VR_CURSOR_ON;
972 scp->status |= VR_CURSOR_BLINK;
974 scp->status &= ~VR_CURSOR_BLINK;
978 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
980 if (scp->cursor_height <= 0) /* the text cursor is disabled */
985 scp->status |= VR_CURSOR_ON;
986 draw_pxlcursor_planar(scp, at, on, flip);
987 } else if (++pxlblinkrate & 4) {
989 scp->status ^= VR_CURSOR_ON;
990 draw_pxlcursor_planar(scp, at,
991 scp->status & VR_CURSOR_ON,
995 if (scp->status & VR_CURSOR_ON)
996 draw_pxlcursor_planar(scp, at, on, flip);
997 scp->status &= ~VR_CURSOR_ON;
1000 scp->status |= VR_CURSOR_BLINK;
1002 scp->status &= ~VR_CURSOR_BLINK;
1006 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1008 if (!(scp->status & VR_CURSOR_BLINK))
1010 if (!(++pxlblinkrate & 4))
1013 scp->status ^= VR_CURSOR_ON;
1014 draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1018 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1020 if (!(scp->status & VR_CURSOR_BLINK))
1022 if (!(++pxlblinkrate & 4))
1025 scp->status ^= VR_CURSOR_ON;
1026 draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1030 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1032 if (!(scp->status & VR_CURSOR_BLINK))
1034 if (!(++pxlblinkrate & 4))
1037 scp->status ^= VR_CURSOR_ON;
1038 draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1041 #ifndef SC_NO_CUTPASTE
1044 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1046 int line_width, pixel_size;
1049 vm_offset_t draw_pos;
1051 line_width = scp->sc->adp->va_line_width;
1052 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1054 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1055 yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1057 draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1059 for (i = 0; i < (yend - y); i++) {
1060 for (j = (xend - x - 1); j >= 0; j--) {
1061 switch (scp->sc->adp->va_info.vi_depth) {
1063 if (mouse_or_mask[i] & 1 << (15 - j))
1064 writel(draw_pos + 4 * j,
1065 scp->ega_palette[15]);
1066 else if (mouse_and_mask[i] & 1 << (15 - j))
1067 writel(draw_pos + 4 * j,
1068 scp->ega_palette[0]);
1073 if (mouse_or_mask[i] & 1 << (15 - j))
1074 writew(draw_pos + 2 * j,
1075 scp->ega_palette[15]);
1076 else if (mouse_and_mask[i] & 1 << (15 - j))
1077 writew(draw_pos + 2 * j,
1078 scp->ega_palette[0]);
1083 draw_pos += line_width;
1088 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1093 vm_offset_t draw_pos;
1095 line_width = scp->sc->adp->va_line_width;
1097 xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel));
1098 yend = imin(scp->font_size * (scp->yoff + scp->ysize),
1099 imin(y + 16, scp->ypixel));
1101 draw_pos = scp->sc->adp->va_window + y * line_width + x;
1103 for (i = 0; i < (yend - y); i++) {
1104 for (j = (xend - x - 1); j >= 0; j--) {
1105 if (mouse_or_mask[i] & 1 << (15 - j))
1106 writeb(draw_pos + j, 15);
1107 else if (mouse_and_mask[i] & 1 << (15 - j))
1108 writeb(draw_pos + j, 0);
1111 draw_pos += line_width;
1116 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1125 line_width = scp->sc->adp->va_line_width;
1126 xoff = (x - scp->xoff*8)%8;
1127 ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1129 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
1130 outw(GDCIDX, 0x0001); /* set/reset enable */
1131 outw(GDCIDX, 0x0002); /* color compare */
1132 outw(GDCIDX, 0x0007); /* color don't care */
1133 outw(GDCIDX, 0xff08); /* bit mask */
1134 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
1135 p = scp->sc->adp->va_window + line_width*y + x/8;
1136 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1137 for (i = y, j = 0; i < ymax; ++i, ++j) {
1138 m = ~(mouse_and_mask[j] >> xoff);
1139 *(u_char *)p &= m >> 8;
1140 *(u_char *)(p + 1) &= m;
1145 for (i = y, j = 0; i < ymax; ++i, ++j) {
1146 m = ~(mouse_and_mask[j] >> xoff);
1151 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
1152 p = scp->sc->adp->va_window + line_width*y + x/8;
1153 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1154 for (i = y, j = 0; i < ymax; ++i, ++j) {
1155 m = mouse_or_mask[j] >> xoff;
1156 *(u_char *)p &= m >> 8;
1157 *(u_char *)(p + 1) &= m;
1161 for (i = y, j = 0; i < ymax; ++i, ++j) {
1162 m = mouse_or_mask[j] >> xoff;
1167 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
1168 outw(GDCIDX, 0x0003); /* data rotate/function select */
1172 remove_pxlmouse(scr_stat *scp, int x, int y)
1178 /* erase the mouse cursor image */
1179 col = x/8 - scp->xoff;
1180 row = y/scp->font_size - scp->yoff;
1181 pos = row*scp->xsize + col;
1182 i = (col < scp->xsize - 1) ? 2 : 1;
1183 (*scp->rndr->draw)(scp, pos, i, FALSE);
1184 if (row < scp->ysize - 1)
1185 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1189 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1192 draw_pxlmouse_direct(scp, x, y);
1194 remove_pxlmouse(scp, x, y);
1198 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1201 draw_pxlmouse_packed(scp, x, y);
1203 remove_pxlmouse(scp, x, y);
1207 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1210 draw_pxlmouse_planar(scp, x, y);
1212 remove_pxlmouse(scp, x, y);
1215 #endif /* SC_NO_CUTPASTE */
1216 #endif /* SC_PIXEL_MODE */
1218 #ifndef SC_NO_MODE_CHANGE
1220 /* graphics mode renderer */
1223 vga_grborder(scr_stat *scp, int color)
1225 lwkt_gettoken(&tty_token);
1226 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1227 lwkt_reltoken(&tty_token);