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 $
34 #include "opt_syscons.h"
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/thread.h>
41 #include <sys/thread2.h>
43 #include <machine/console.h>
45 #include <dev/video/fb/fbreg.h>
46 #include <dev/video/fb/vgareg.h>
49 #include <bus/isa/isareg.h>
51 static vr_draw_border_t vga_txtborder;
52 static vr_draw_t vga_txtdraw;
53 static vr_set_cursor_t vga_txtcursor_shape;
54 static vr_draw_cursor_t vga_txtcursor;
55 static vr_blink_cursor_t vga_txtblink;
56 #ifndef SC_NO_CUTPASTE
57 static vr_draw_mouse_t vga_txtmouse;
59 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop
63 static vr_draw_border_t vga_pxlborder_direct;
64 static vr_draw_border_t vga_pxlborder_packed;
65 static vr_draw_border_t vga_pxlborder_planar;
66 static vr_draw_t vga_vgadraw_direct;
67 static vr_draw_t vga_vgadraw_packed;
68 static vr_draw_t vga_vgadraw_planar;
69 static vr_set_cursor_t vga_pxlcursor_shape;
70 static vr_draw_cursor_t vga_pxlcursor_direct;
71 static vr_draw_cursor_t vga_pxlcursor_packed;
72 static vr_draw_cursor_t vga_pxlcursor_planar;
73 static vr_blink_cursor_t vga_pxlblink_direct;
74 static vr_blink_cursor_t vga_pxlblink_packed;
75 static vr_blink_cursor_t vga_pxlblink_planar;
76 #ifndef SC_NO_CUTPASTE
77 static vr_draw_mouse_t vga_pxlmouse_direct;
78 static vr_draw_mouse_t vga_pxlmouse_packed;
79 static vr_draw_mouse_t vga_pxlmouse_planar;
81 #define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop
82 #define vga_pxlmouse_packed (vr_draw_mouse_t *)vga_nop
83 #define vga_pxlmouse_planar (vr_draw_mouse_t *)vga_nop
85 #endif /* SC_PIXEL_MODE */
87 #ifndef SC_NO_MODE_CHANGE
88 static vr_draw_border_t vga_grborder;
91 static void vga_nop(scr_stat *scp, ...);
93 static sc_rndr_sw_t txtrndrsw = {
101 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set);
104 static sc_rndr_sw_t directrndrsw = {
105 vga_pxlborder_direct,
108 vga_pxlcursor_direct,
112 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set);
114 static sc_rndr_sw_t packedrndrsw = {
115 vga_pxlborder_packed,
118 vga_pxlcursor_packed,
122 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set);
124 static sc_rndr_sw_t planarrndrsw = {
125 vga_pxlborder_planar,
128 vga_pxlcursor_planar,
132 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set);
133 #endif /* SC_PIXEL_MODE */
135 #ifndef SC_NO_MODE_CHANGE
136 static sc_rndr_sw_t grrndrsw = {
138 (vr_draw_t *)vga_nop,
139 (vr_set_cursor_t *)vga_nop,
140 (vr_draw_cursor_t *)vga_nop,
141 (vr_blink_cursor_t *)vga_nop,
142 (vr_draw_mouse_t *)vga_nop,
144 RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set);
145 #endif /* SC_NO_MODE_CHANGE */
147 RENDERER_MODULE(vga, vga_set);
149 #ifndef SC_NO_CUTPASTE
150 static u_short mouse_and_mask[16] = {
151 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
152 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
154 static u_short mouse_or_mask[16] = {
155 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
156 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
161 vga_nop(scr_stat *scp, ...)
165 /* text mode renderer */
168 vga_txtborder(scr_stat *scp, int color)
170 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
174 vga_txtdraw(scr_stat *scp, int from, int count, int flip)
180 if (from + count > scp->xsize*scp->ysize)
181 count = scp->xsize*scp->ysize - from;
184 for (p = scp->scr.vtb_buffer + from; count-- > 0; ++from) {
185 c = sc_vtb_getc(&scp->vtb, from);
186 a = sc_vtb_geta(&scp->vtb, from);
187 a = (a & 0x8800) | ((a & 0x7000) >> 4)
188 | ((a & 0x0700) << 4);
189 p = sc_vtb_putchar(&scp->scr, p, c, a);
192 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
197 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
199 if (base < 0 || base >= scp->font_height)
202 /* the caller may set height <= 0 in order to disable the cursor */
204 scp->cursor_base = base;
205 scp->cursor_height = height;
207 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
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_height < 14) {
232 } else if (scp->font_height >= 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 int sc_txtmouse_no_retrace_wait;
328 #ifndef SC_NO_CUTPASTE
331 draw_txtmouse(scr_stat *scp, int x, int y)
333 #ifndef SC_ALT_MOUSE_IMAGE
334 if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
335 u_char font_buf[128];
339 int xoffset, yoffset;
342 /* prepare mousepointer char's bitmaps */
343 pos = (y / scp->font_height - scp->yoff) * scp->xsize +
344 x / scp->font_width - scp->xoff;
345 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos) * scp->font_height,
346 &font_buf[0], scp->font_height);
347 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1) * scp->font_height,
348 &font_buf[32], scp->font_height);
350 + sc_vtb_getc(&scp->scr, pos + scp->xsize) * scp->font_height,
351 &font_buf[64], scp->font_height);
353 sc_vtb_getc(&scp->scr, pos + scp->xsize + 1) * scp->font_height,
354 &font_buf[96], scp->font_height);
355 for (i = 0; i < scp->font_height; ++i) {
356 cursor[i] = (font_buf[i]<<8) | font_buf[i+32];
357 cursor[i + scp->font_height] = (font_buf[i+64]<<8) |
361 /* now and-or in the mousepointer image */
362 xoffset = x % scp->font_width;
363 yoffset = y % scp->font_height;
364 for (i = 0; i < 16; ++i) {
365 cursor[i + yoffset] =
366 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
367 | (mouse_or_mask[i] >> xoffset);
369 for (i = 0; i < scp->font_height; ++i) {
370 font_buf[i] = (cursor[i] & 0xff00) >> 8;
371 font_buf[i + 32] = cursor[i] & 0xff;
372 font_buf[i + 64] = (cursor[i + scp->font_height] & 0xff00) >> 8;
373 font_buf[i + 96] = cursor[i + scp->font_height] & 0xff;
377 /* wait for vertical retrace to avoid jitter on some videocards */
378 while (!sc_txtmouse_no_retrace_wait &&
379 !(inb(CRTC + 6) & 0x08))
382 c = scp->sc->mouse_char;
383 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
386 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
387 /* FIXME: may be out of range! */
388 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
389 sc_vtb_geta(&scp->scr, pos + scp->xsize));
390 if (x < (scp->xsize - 1)*8) {
391 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
392 sc_vtb_geta(&scp->scr, pos + 1));
393 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
394 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
397 #endif /* SC_ALT_MOUSE_IMAGE */
399 /* Red, magenta and brown are mapped to green to to keep it readable */
400 static const int col_conv[16] = {
401 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
407 pos = (y / scp->font_height - scp->yoff)*
408 scp->xsize + x / scp->font_width - scp->xoff;
409 a = sc_vtb_geta(&scp->scr, pos);
410 if (scp->sc->adp->va_flags & V_ADP_COLOR)
411 color = (col_conv[(a & 0xf000) >> 12] << 12)
412 | ((a & 0x0f00) | 0x0800);
414 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
415 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
421 remove_txtmouse(scr_stat *scp, int x, int y)
426 vga_txtmouse(scr_stat *scp, int x, int y, int on)
429 draw_txtmouse(scp, x, y);
431 remove_txtmouse(scp, x, y);
434 #endif /* SC_NO_CUTPASTE */
438 /* pixel (raster text) mode renderer */
441 vga_pxlborder_direct(scr_stat *scp, int color)
444 int line_width, pixel_size;
446 vm_offset_t draw_pos, draw_end, p;
448 line_width = scp->sc->adp->va_line_width;
449 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
451 for (i = 0; i < 4 / pixel_size; ++i)
452 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
455 draw_pos = scp->sc->adp->va_window;
456 draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
458 for (p = draw_pos; p < draw_end; p += 4)
462 y = (scp->yoff + scp->ysize) * scp->font_height;
464 if (scp->ypixel > y) {
465 draw_pos = scp->sc->adp->va_window + line_width * y;
466 draw_end = draw_pos + line_width * (scp->ypixel - y);
468 for (p = draw_pos; p < draw_end; p += 4)
472 y = scp->yoff * scp->font_height;
473 x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
475 for (i = 0; i < scp->ysize * scp->font_height; ++i) {
477 draw_pos = scp->sc->adp->va_window +
478 line_width * (y + i);
479 draw_end = draw_pos +
480 scp->xoff * scp->font_width * pixel_size;
482 for (p = draw_pos; p < draw_end; p += 4)
487 draw_pos = scp->sc->adp->va_window +
488 line_width * (y + i) +
489 scp->xoff * 8 * pixel_size +
490 scp->xsize * 8 * pixel_size;
491 draw_end = draw_pos + x * 8 * pixel_size;
493 for (p = draw_pos; p < draw_end; p += 4)
500 vga_pxlborder_packed(scr_stat *scp, int color)
505 vm_offset_t draw_pos, draw_end, p;
507 line_width = scp->sc->adp->va_line_width;
508 u32 = (color << 24) + (color << 16) + (color << 8) + color;
511 draw_pos = scp->sc->adp->va_window;
512 draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
514 for (p = draw_pos; p < draw_end; p += 4)
518 y = (scp->yoff + scp->ysize) * scp->font_height;
520 if (scp->ypixel > y) {
521 draw_pos = scp->sc->adp->va_window + line_width * y;
522 draw_end = draw_pos + line_width * (scp->ypixel - y);
524 for (p = draw_pos; p < draw_end; p += 4)
528 y = scp->yoff * scp->font_height;
529 x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
531 for (i = 0; i < scp->ysize * scp->font_height; ++i) {
533 draw_pos = scp->sc->adp->va_window +
534 line_width * (y + i);
535 draw_end = draw_pos + scp->xoff * scp->font_width;
537 for (p = draw_pos; p < draw_end; p += 4)
542 draw_pos = scp->sc->adp->va_window +
543 line_width * (y + i) + scp->xoff * 8 +
545 draw_end = draw_pos + x * 8;
547 for (p = draw_pos; p < draw_end; p += 4)
554 vga_pxlborder_planar(scr_stat *scp, int color)
562 lwkt_gettoken(&tty_token);
564 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
566 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
567 outw(GDCIDX, 0x0003); /* data rotate/function select */
568 outw(GDCIDX, 0x0f01); /* set/reset enable */
569 outw(GDCIDX, 0xff08); /* bit mask */
570 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
571 line_width = scp->sc->adp->va_line_width;
572 p = scp->sc->adp->va_window;
574 bzero_io((void *)p, line_width*scp->yoff*scp->font_height);
575 y = (scp->yoff + scp->ysize)*scp->font_height;
577 bzero_io((void *)(p + line_width*y),
578 line_width*(scp->ypixel - y));
579 y = scp->yoff*scp->font_height;
580 x = scp->xpixel/scp->font_width - scp->xoff - scp->xsize;
581 for (i = 0; i < scp->ysize*scp->font_height; ++i) {
583 bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
585 bzero_io((void *)(p + line_width*(y + i)
586 + scp->xoff + scp->xsize), x);
588 outw(GDCIDX, 0x0000); /* set/reset */
589 outw(GDCIDX, 0x0001); /* set/reset enable */
590 lwkt_reltoken(&tty_token);
594 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
596 int line_width, pixel_size;
597 int a, i, j, k, l, pos;
598 uint32_t fg, bg, u32;
599 unsigned char *char_data;
600 vm_offset_t draw_pos, p;
602 line_width = scp->sc->adp->va_line_width;
603 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
605 draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
607 if (from + count > scp->xsize * scp->ysize)
608 count = scp->xsize * scp->ysize - from;
610 for (i = from; count-- > 0; ++i) {
611 a = sc_vtb_geta(&scp->vtb, i);
614 fg = scp->ega_palette[(((a & 0x7000) >> 4) |
616 bg = scp->ega_palette[(((a & 0x8000) >> 4) |
619 fg = scp->ega_palette[(a & 0x0f00) >> 8];
620 bg = scp->ega_palette[(a & 0xf000) >> 12];
624 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
627 for (j = 0; j < scp->font_height; ++j, ++char_data) {
630 for (k = 0; k < 2 * pixel_size; ++k) {
633 for (l = 0; l < 4 / pixel_size; ++l) {
634 u32 += (*char_data & (1 << pos--) ?
635 fg : bg) << (l * 8 * pixel_size);
642 p += line_width - 8 * pixel_size;
645 draw_pos += 8 * pixel_size;
647 if ((i % scp->xsize) == scp->xsize - 1)
648 draw_pos += scp->xoff * 16 * pixel_size +
649 (scp->font_height - 1) * line_width;
654 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
658 uint32_t fg, bg, u32;
659 unsigned char *char_data;
660 vm_offset_t draw_pos, p;
662 line_width = scp->sc->adp->va_line_width;
664 draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
666 if (from + count > scp->xsize * scp->ysize)
667 count = scp->xsize * scp->ysize - from;
669 for (i = from; count-- > 0; ++i) {
670 a = sc_vtb_geta(&scp->vtb, i);
673 fg = ((a & 0xf000) >> 4) >> 8;
674 bg = (a & 0x0f00) >> 8;
676 fg = (a & 0x0f00) >> 8;
677 bg = ((a & 0xf000) >> 4) >> 8;
681 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
684 for (j = 0; j < scp->font_height; ++j, ++char_data) {
685 u32 = ((*char_data & 1 ? fg : bg) << 24) +
686 ((*char_data & 2 ? fg : bg) << 16) +
687 ((*char_data & 4 ? fg : bg) << 8) +
688 (*char_data & 8 ? fg : bg);
691 u32 = ((*char_data & 16 ? fg : bg) << 24) +
692 ((*char_data & 32 ? fg : bg) << 16) +
693 ((*char_data & 64 ? fg : bg) << 8) +
694 (*char_data & 128 ? fg : bg);
700 draw_pos += scp->font_width;
702 if ((i % scp->xsize) == scp->xsize - 1)
703 draw_pos += scp->xoff * 16 +
704 (scp->font_height - 1) * line_width;
709 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
721 d = VIDEO_MEMORY_POS(scp, from, 1);
723 line_width = scp->sc->adp->va_line_width;
725 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
726 outw(GDCIDX, 0x0003); /* data rotate/function select */
727 outw(GDCIDX, 0x0f01); /* set/reset enable */
728 outw(GDCIDX, 0xff08); /* bit mask */
730 if (from + count > scp->xsize*scp->ysize)
731 count = scp->xsize*scp->ysize - from;
732 for (i = from; count-- > 0; ++i) {
733 a = sc_vtb_geta(&scp->vtb, i);
735 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
736 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
739 col2 = (a & 0xf000) >> 4;
741 /* set background color in EGA/VGA latch */
744 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
745 outw(GDCIDX, bg | 0x00); /* set/reset */
747 c = readb(d); /* set bg color in the latch */
748 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
750 /* foreground color */
751 outw(GDCIDX, col1 | 0x00); /* set/reset */
753 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_height]);
754 for (j = 0; j < scp->font_height; ++j, ++f) {
759 if ((i % scp->xsize) == scp->xsize - 1)
761 + (scp->font_height - 1)*line_width;
763 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
764 outw(GDCIDX, 0x0000); /* set/reset */
765 outw(GDCIDX, 0x0001); /* set/reset enable */
769 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
771 if (base < 0 || base >= scp->font_height)
773 /* the caller may set height <= 0 in order to disable the cursor */
775 scp->cursor_base = base;
776 scp->cursor_height = height;
781 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
783 int line_width, pixel_size, height;
785 uint32_t fg, bg, u32;
786 unsigned char *char_data;
787 vm_offset_t draw_pos;
789 line_width = scp->sc->adp->va_line_width;
790 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
792 draw_pos = VIDEO_MEMORY_POS(scp, at, scp->font_width * pixel_size) +
793 (scp->font_height - scp->cursor_base - 1) * line_width;
795 a = sc_vtb_geta(&scp->vtb, at);
798 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
799 ((a & 0xf000) >> 4)) >> 8];
800 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
803 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
805 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
806 ((a & 0xf000) >> 4)) >> 8];
809 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
810 scp->font_height - scp->cursor_base - 1]);
812 height = imin(scp->cursor_height, scp->font_height);
814 for (i = 0; i < height; ++i, --char_data) {
817 for (j = 0; j < 2 * pixel_size; ++j) {
820 for (k = 0; k < 4 / pixel_size; ++k) {
821 u32 += (*char_data & (1 << pos--) ?
822 fg : bg) << (k * 8 * pixel_size);
825 writel(draw_pos, u32);
829 draw_pos -= line_width + 8 * pixel_size;
834 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
836 int line_width, height;
838 uint32_t fg, bg, u32;
839 unsigned char *char_data;
840 vm_offset_t draw_pos;
842 line_width = scp->sc->adp->va_line_width;
844 draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
845 (scp->font_height - scp->cursor_base - 1) * line_width;
847 a = sc_vtb_geta(&scp->vtb, at);
850 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
851 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
853 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
854 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
857 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
858 scp->font_height - scp->cursor_base - 1]);
860 height = imin(scp->cursor_height, scp->font_height);
862 for (i = 0; i < height; ++i, --char_data) {
863 u32 = ((*char_data & 1 ? fg : bg) << 24) +
864 ((*char_data & 2 ? fg : bg) << 16) +
865 ((*char_data & 4 ? fg : bg) << 8) +
866 (*char_data & 8 ? fg : bg);
867 writel(draw_pos + 4, u32);
869 u32 = ((*char_data & 16 ? fg : bg) << 24) +
870 ((*char_data & 32 ? fg : bg) << 16) +
871 ((*char_data & 64 ? fg : bg) << 8) +
872 (*char_data & 128 ? fg : bg);
873 writel(draw_pos, u32);
875 draw_pos -= line_width;
880 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
891 line_width = scp->sc->adp->va_line_width;
893 d = VIDEO_MEMORY_POS(scp, at, 1) +
894 (scp->font_height - scp->cursor_base - 1) * line_width;
896 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
897 outw(GDCIDX, 0x0003); /* data rotate/function select */
898 outw(GDCIDX, 0x0f01); /* set/reset enable */
899 /* set background color in EGA/VGA latch */
900 a = sc_vtb_geta(&scp->vtb, at);
902 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
904 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
905 outw(GDCIDX, col | 0x00); /* set/reset */
906 outw(GDCIDX, 0xff08); /* bit mask */
908 c = readb(d); /* set bg color in the latch */
909 /* foreground color */
911 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
913 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
914 outw(GDCIDX, col | 0x00); /* set/reset */
915 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_height
916 + scp->font_height - scp->cursor_base - 1]);
917 height = imin(scp->cursor_height, scp->font_height);
918 for (i = 0; i < height; ++i, --f) {
919 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
923 outw(GDCIDX, 0x0000); /* set/reset */
924 outw(GDCIDX, 0x0001); /* set/reset enable */
925 outw(GDCIDX, 0xff08); /* bit mask */
928 static int pxlblinkrate = 0;
931 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
933 if (scp->cursor_height <= 0) /* the text cursor is disabled */
938 scp->status |= VR_CURSOR_ON;
939 draw_pxlcursor_direct(scp, at, on, flip);
940 } else if (++pxlblinkrate & 4) {
942 scp->status ^= VR_CURSOR_ON;
943 draw_pxlcursor_direct(scp, at,
944 scp->status & VR_CURSOR_ON,
948 if (scp->status & VR_CURSOR_ON)
949 draw_pxlcursor_direct(scp, at, on, flip);
950 scp->status &= ~VR_CURSOR_ON;
953 scp->status |= VR_CURSOR_BLINK;
955 scp->status &= ~VR_CURSOR_BLINK;
959 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
961 if (scp->cursor_height <= 0) /* the text cursor is disabled */
966 scp->status |= VR_CURSOR_ON;
967 draw_pxlcursor_packed(scp, at, on, flip);
968 } else if (++pxlblinkrate & 4) {
970 scp->status ^= VR_CURSOR_ON;
971 draw_pxlcursor_packed(scp, at,
972 scp->status & VR_CURSOR_ON,
976 if (scp->status & VR_CURSOR_ON)
977 draw_pxlcursor_packed(scp, at, on, flip);
978 scp->status &= ~VR_CURSOR_ON;
981 scp->status |= VR_CURSOR_BLINK;
983 scp->status &= ~VR_CURSOR_BLINK;
987 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
989 if (scp->cursor_height <= 0) /* the text cursor is disabled */
994 scp->status |= VR_CURSOR_ON;
995 draw_pxlcursor_planar(scp, at, on, flip);
996 } else if (++pxlblinkrate & 4) {
998 scp->status ^= VR_CURSOR_ON;
999 draw_pxlcursor_planar(scp, at,
1000 scp->status & VR_CURSOR_ON,
1004 if (scp->status & VR_CURSOR_ON)
1005 draw_pxlcursor_planar(scp, at, on, flip);
1006 scp->status &= ~VR_CURSOR_ON;
1009 scp->status |= VR_CURSOR_BLINK;
1011 scp->status &= ~VR_CURSOR_BLINK;
1015 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1017 if (!(scp->status & VR_CURSOR_BLINK))
1019 if (!(++pxlblinkrate & 4))
1022 scp->status ^= VR_CURSOR_ON;
1023 draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1027 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1029 if (!(scp->status & VR_CURSOR_BLINK))
1031 if (!(++pxlblinkrate & 4))
1034 scp->status ^= VR_CURSOR_ON;
1035 draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1039 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1041 if (!(scp->status & VR_CURSOR_BLINK))
1043 if (!(++pxlblinkrate & 4))
1046 scp->status ^= VR_CURSOR_ON;
1047 draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1050 #ifndef SC_NO_CUTPASTE
1053 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1055 int line_width, pixel_size;
1058 vm_offset_t draw_pos;
1060 line_width = scp->sc->adp->va_line_width;
1061 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1063 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1064 yend = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
1066 draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1068 for (i = 0; i < (yend - y); i++) {
1069 for (j = (xend - x - 1); j >= 0; j--) {
1070 switch (scp->sc->adp->va_info.vi_depth) {
1072 if (mouse_or_mask[i] & 1 << (15 - j))
1073 writel(draw_pos + 4 * j,
1074 scp->ega_palette[15]);
1075 else if (mouse_and_mask[i] & 1 << (15 - j))
1076 writel(draw_pos + 4 * j,
1077 scp->ega_palette[0]);
1082 if (mouse_or_mask[i] & 1 << (15 - j))
1083 writew(draw_pos + 2 * j,
1084 scp->ega_palette[15]);
1085 else if (mouse_and_mask[i] & 1 << (15 - j))
1086 writew(draw_pos + 2 * j,
1087 scp->ega_palette[0]);
1092 draw_pos += line_width;
1097 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1102 vm_offset_t draw_pos;
1104 line_width = scp->sc->adp->va_line_width;
1106 xend = imin(scp->font_width * (scp->xoff + scp->xsize),
1107 imin(x + 16, scp->xpixel));
1108 yend = imin(scp->font_height * (scp->yoff + scp->ysize),
1109 imin(y + 16, scp->ypixel));
1111 draw_pos = scp->sc->adp->va_window + y * line_width + x;
1113 for (i = 0; i < (yend - y); i++) {
1114 for (j = (xend - x - 1); j >= 0; j--) {
1115 if (mouse_or_mask[i] & 1 << (15 - j))
1116 writeb(draw_pos + j, 15);
1117 else if (mouse_and_mask[i] & 1 << (15 - j))
1118 writeb(draw_pos + j, 0);
1121 draw_pos += line_width;
1126 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1135 line_width = scp->sc->adp->va_line_width;
1136 xoff = (x - scp->xoff*8)%8;
1137 ymax = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
1139 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
1140 outw(GDCIDX, 0x0001); /* set/reset enable */
1141 outw(GDCIDX, 0x0002); /* color compare */
1142 outw(GDCIDX, 0x0007); /* color don't care */
1143 outw(GDCIDX, 0xff08); /* bit mask */
1144 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
1145 p = scp->sc->adp->va_window + line_width*y + x/8;
1146 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1147 for (i = y, j = 0; i < ymax; ++i, ++j) {
1148 m = ~(mouse_and_mask[j] >> xoff);
1149 *(u_char *)p &= m >> 8;
1150 *(u_char *)(p + 1) &= m;
1155 for (i = y, j = 0; i < ymax; ++i, ++j) {
1156 m = ~(mouse_and_mask[j] >> xoff);
1161 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
1162 p = scp->sc->adp->va_window + line_width*y + x/8;
1163 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1164 for (i = y, j = 0; i < ymax; ++i, ++j) {
1165 m = mouse_or_mask[j] >> xoff;
1166 *(u_char *)p &= m >> 8;
1167 *(u_char *)(p + 1) &= m;
1171 for (i = y, j = 0; i < ymax; ++i, ++j) {
1172 m = mouse_or_mask[j] >> xoff;
1177 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
1178 outw(GDCIDX, 0x0003); /* data rotate/function select */
1182 remove_pxlmouse(scr_stat *scp, int x, int y)
1188 /* erase the mouse cursor image */
1189 col = x / scp->font_width - scp->xoff;
1190 row = y / scp->font_height - scp->yoff;
1191 pos = row * scp->xsize + col;
1192 i = (col < scp->xsize - 1) ? 2 : 1;
1193 (*scp->rndr->draw)(scp, pos, i, FALSE);
1194 if (row < scp->ysize - 1)
1195 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1199 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1202 draw_pxlmouse_direct(scp, x, y);
1204 remove_pxlmouse(scp, x, y);
1208 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1211 draw_pxlmouse_packed(scp, x, y);
1213 remove_pxlmouse(scp, x, y);
1217 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1220 draw_pxlmouse_planar(scp, x, y);
1222 remove_pxlmouse(scp, x, y);
1225 #endif /* SC_NO_CUTPASTE */
1226 #endif /* SC_PIXEL_MODE */
1228 #ifndef SC_NO_MODE_CHANGE
1230 /* graphics mode renderer */
1233 vga_grborder(scr_stat *scp, int color)
1235 lwkt_gettoken(&tty_token);
1236 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1237 lwkt_reltoken(&tty_token);