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_size)
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,
209 scp->font_size, blink);
214 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
219 scp->cursor_saveunder_char = c;
220 scp->cursor_saveunder_attr = a;
222 #ifndef SC_NO_FONT_LOADING
223 if (sc->flags & SC_CHAR_CURSOR) {
228 if (scp->font_size < 14) {
231 } else if (scp->font_size >= 16) {
238 if (scp->cursor_base >= h)
242 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
243 bcopy(font + c*h, font + sc->cursor_char*h, h);
244 font = font + sc->cursor_char*h;
245 for (i = imax(h - scp->cursor_base - scp->cursor_height, 0);
246 i < h - scp->cursor_base; ++i) {
249 sc->font_loading_in_progress = TRUE;
251 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font,
253 sc->font_loading_in_progress = FALSE;
254 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a);
256 #endif /* SC_NO_FONT_LOADING */
258 if ((a & 0x7000) == 0x7000) {
260 if ((a & 0x0700) == 0)
264 if ((a & 0x0700) == 0x0700)
269 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
270 sc_vtb_putc(&scp->scr, at, c, a);
275 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
277 video_adapter_t *adp;
280 if (scp->cursor_height <= 0) /* the text cursor is disabled */
285 scp->status |= VR_CURSOR_BLINK;
287 scp->status |= VR_CURSOR_ON;
288 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
292 if (scp->status & VR_CURSOR_ON)
293 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
295 scp->status &= ~VR_CURSOR_ON;
298 scp->status &= ~VR_CURSOR_BLINK;
300 scp->status |= VR_CURSOR_ON;
301 draw_txtcharcursor(scp, at,
302 sc_vtb_getc(&scp->scr, at),
303 sc_vtb_geta(&scp->scr, at),
306 cursor_attr = scp->cursor_saveunder_attr;
308 cursor_attr = (cursor_attr & 0x8800)
309 | ((cursor_attr & 0x7000) >> 4)
310 | ((cursor_attr & 0x0700) << 4);
311 if (scp->status & VR_CURSOR_ON)
312 sc_vtb_putc(&scp->scr, at,
313 scp->cursor_saveunder_char,
315 scp->status &= ~VR_CURSOR_ON;
321 vga_txtblink(scr_stat *scp, int at, int flip)
325 int sc_txtmouse_no_retrace_wait;
327 #ifndef SC_NO_CUTPASTE
330 draw_txtmouse(scr_stat *scp, int x, int y)
332 #ifndef SC_ALT_MOUSE_IMAGE
333 if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
334 u_char font_buf[128];
338 int xoffset, yoffset;
341 /* prepare mousepointer char's bitmaps */
342 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
343 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
344 &font_buf[0], scp->font_size);
345 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size,
346 &font_buf[32], scp->font_size);
348 + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size,
349 &font_buf[64], scp->font_size);
351 + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size,
352 &font_buf[96], scp->font_size);
353 for (i = 0; i < scp->font_size; ++i) {
354 cursor[i] = font_buf[i]<<8 | font_buf[i+32];
355 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
358 /* now and-or in the mousepointer image */
360 yoffset = y%scp->font_size;
361 for (i = 0; i < 16; ++i) {
362 cursor[i + yoffset] =
363 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
364 | (mouse_or_mask[i] >> xoffset);
366 for (i = 0; i < scp->font_size; ++i) {
367 font_buf[i] = (cursor[i] & 0xff00) >> 8;
368 font_buf[i + 32] = cursor[i] & 0xff;
369 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
370 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
374 /* wait for vertical retrace to avoid jitter on some videocards */
375 while (!sc_txtmouse_no_retrace_wait &&
376 !(inb(CRTC + 6) & 0x08))
379 c = scp->sc->mouse_char;
380 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
383 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
384 /* FIXME: may be out of range! */
385 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
386 sc_vtb_geta(&scp->scr, pos + scp->xsize));
387 if (x < (scp->xsize - 1)*8) {
388 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
389 sc_vtb_geta(&scp->scr, pos + 1));
390 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
391 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
394 #endif /* SC_ALT_MOUSE_IMAGE */
396 /* Red, magenta and brown are mapped to green to to keep it readable */
397 static const int col_conv[16] = {
398 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
404 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
405 a = sc_vtb_geta(&scp->scr, pos);
406 if (scp->sc->adp->va_flags & V_ADP_COLOR)
407 color = (col_conv[(a & 0xf000) >> 12] << 12)
408 | ((a & 0x0f00) | 0x0800);
410 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
411 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
417 remove_txtmouse(scr_stat *scp, int x, int y)
422 vga_txtmouse(scr_stat *scp, int x, int y, int on)
425 draw_txtmouse(scp, x, y);
427 remove_txtmouse(scp, x, y);
430 #endif /* SC_NO_CUTPASTE */
434 /* pixel (raster text) mode renderer */
437 vga_pxlborder_direct(scr_stat *scp, int color)
440 int line_width, pixel_size;
442 vm_offset_t draw_pos, draw_end, p;
444 line_width = scp->sc->adp->va_line_width;
445 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
447 for (i = 0; i < 4 / pixel_size; ++i)
448 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
451 draw_pos = scp->sc->adp->va_window;
452 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
454 for (p = draw_pos; p < draw_end; p += 4)
458 y = (scp->yoff + scp->ysize) * scp->font_size;
460 if (scp->ypixel > y) {
461 draw_pos = scp->sc->adp->va_window + line_width * y;
462 draw_end = draw_pos + line_width * (scp->ypixel - y);
464 for (p = draw_pos; p < draw_end; p += 4)
468 y = scp->yoff * scp->font_size;
469 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
471 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
473 draw_pos = scp->sc->adp->va_window +
474 line_width * (y + i);
475 draw_end = draw_pos + scp->xoff * 8 * pixel_size;
477 for (p = draw_pos; p < draw_end; p += 4)
482 draw_pos = scp->sc->adp->va_window +
483 line_width * (y + i) +
484 scp->xoff * 8 * pixel_size +
485 scp->xsize * 8 * pixel_size;
486 draw_end = draw_pos + x * 8 * pixel_size;
488 for (p = draw_pos; p < draw_end; p += 4)
495 vga_pxlborder_packed(scr_stat *scp, int color)
500 vm_offset_t draw_pos, draw_end, p;
502 line_width = scp->sc->adp->va_line_width;
503 u32 = (color << 24) + (color << 16) + (color << 8) + color;
506 draw_pos = scp->sc->adp->va_window;
507 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
509 for (p = draw_pos; p < draw_end; p += 4)
513 y = (scp->yoff + scp->ysize) * scp->font_size;
515 if (scp->ypixel > y) {
516 draw_pos = scp->sc->adp->va_window + line_width * y;
517 draw_end = draw_pos + line_width * (scp->ypixel - y);
519 for (p = draw_pos; p < draw_end; p += 4)
523 y = scp->yoff * scp->font_size;
524 x = scp->xpixel / 8 - scp->xoff - scp->xsize;
526 for (i = 0; i < scp->ysize * scp->font_size; ++i) {
528 draw_pos = scp->sc->adp->va_window +
529 line_width * (y + i);
530 draw_end = draw_pos + scp->xoff * 8;
532 for (p = draw_pos; p < draw_end; p += 4)
537 draw_pos = scp->sc->adp->va_window +
538 line_width * (y + i) + scp->xoff * 8 +
540 draw_end = draw_pos + x * 8;
542 for (p = draw_pos; p < draw_end; p += 4)
549 vga_pxlborder_planar(scr_stat *scp, int color)
557 lwkt_gettoken(&tty_token);
559 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
561 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
562 outw(GDCIDX, 0x0003); /* data rotate/function select */
563 outw(GDCIDX, 0x0f01); /* set/reset enable */
564 outw(GDCIDX, 0xff08); /* bit mask */
565 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
566 line_width = scp->sc->adp->va_line_width;
567 p = scp->sc->adp->va_window;
569 bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
570 y = (scp->yoff + scp->ysize)*scp->font_size;
572 bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y));
573 y = scp->yoff*scp->font_size;
574 x = scp->xpixel/8 - scp->xoff - scp->xsize;
575 for (i = 0; i < scp->ysize*scp->font_size; ++i) {
577 bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
579 bzero_io((void *)(p + line_width*(y + i)
580 + scp->xoff + scp->xsize), x);
582 outw(GDCIDX, 0x0000); /* set/reset */
583 outw(GDCIDX, 0x0001); /* set/reset enable */
584 lwkt_reltoken(&tty_token);
588 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
590 int line_width, pixel_size;
591 int a, i, j, k, l, pos;
592 uint32_t fg, bg, u32;
593 unsigned char *char_data;
594 vm_offset_t draw_pos, p;
596 line_width = scp->sc->adp->va_line_width;
597 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
599 draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
601 if (from + count > scp->xsize * scp->ysize)
602 count = scp->xsize * scp->ysize - from;
604 for (i = from; count-- > 0; ++i) {
605 a = sc_vtb_geta(&scp->vtb, i);
608 fg = scp->ega_palette[(((a & 0x7000) >> 4) |
610 bg = scp->ega_palette[(((a & 0x8000) >> 4) |
613 fg = scp->ega_palette[(a & 0x0f00) >> 8];
614 bg = scp->ega_palette[(a & 0xf000) >> 12];
618 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
621 for (j = 0; j < scp->font_size; ++j, ++char_data) {
624 for (k = 0; k < 2 * pixel_size; ++k) {
627 for (l = 0; l < 4 / pixel_size; ++l) {
628 u32 += (*char_data & (1 << pos--) ?
629 fg : bg) << (l * 8 * pixel_size);
636 p += line_width - 8 * pixel_size;
639 draw_pos += 8 * pixel_size;
641 if ((i % scp->xsize) == scp->xsize - 1)
642 draw_pos += scp->xoff * 16 * pixel_size +
643 (scp->font_size - 1) * line_width;
648 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
652 uint32_t fg, bg, u32;
653 unsigned char *char_data;
654 vm_offset_t draw_pos, p;
656 line_width = scp->sc->adp->va_line_width;
658 draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
660 if (from + count > scp->xsize * scp->ysize)
661 count = scp->xsize * scp->ysize - from;
663 for (i = from; count-- > 0; ++i) {
664 a = sc_vtb_geta(&scp->vtb, i);
667 fg = ((a & 0xf000) >> 4) >> 8;
668 bg = (a & 0x0f00) >> 8;
670 fg = (a & 0x0f00) >> 8;
671 bg = ((a & 0xf000) >> 4) >> 8;
675 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
678 for (j = 0; j < scp->font_size; ++j, ++char_data) {
679 u32 = ((*char_data & 1 ? fg : bg) << 24) +
680 ((*char_data & 2 ? fg : bg) << 16) +
681 ((*char_data & 4 ? fg : bg) << 8) +
682 (*char_data & 8 ? fg : bg);
685 u32 = ((*char_data & 16 ? fg : bg) << 24) +
686 ((*char_data & 32 ? fg : bg) << 16) +
687 ((*char_data & 64 ? fg : bg) << 8) +
688 (*char_data & 128 ? fg : bg);
696 if ((i % scp->xsize) == scp->xsize - 1)
697 draw_pos += scp->xoff * 16 +
698 (scp->font_size - 1) * line_width;
703 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
715 d = VIDEO_MEMORY_POS(scp, from, 1);
717 line_width = scp->sc->adp->va_line_width;
719 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
720 outw(GDCIDX, 0x0003); /* data rotate/function select */
721 outw(GDCIDX, 0x0f01); /* set/reset enable */
722 outw(GDCIDX, 0xff08); /* bit mask */
724 if (from + count > scp->xsize*scp->ysize)
725 count = scp->xsize*scp->ysize - from;
726 for (i = from; count-- > 0; ++i) {
727 a = sc_vtb_geta(&scp->vtb, i);
729 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
730 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
733 col2 = (a & 0xf000) >> 4;
735 /* set background color in EGA/VGA latch */
738 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
739 outw(GDCIDX, bg | 0x00); /* set/reset */
741 c = readb(d); /* set bg color in the latch */
742 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
744 /* foreground color */
745 outw(GDCIDX, col1 | 0x00); /* set/reset */
747 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
748 for (j = 0; j < scp->font_size; ++j, ++f) {
753 if ((i % scp->xsize) == scp->xsize - 1)
755 + (scp->font_size - 1)*line_width;
757 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
758 outw(GDCIDX, 0x0000); /* set/reset */
759 outw(GDCIDX, 0x0001); /* set/reset enable */
763 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
765 if (base < 0 || base >= scp->font_size)
767 /* the caller may set height <= 0 in order to disable the cursor */
769 scp->cursor_base = base;
770 scp->cursor_height = height;
775 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
777 int line_width, pixel_size, height;
779 uint32_t fg, bg, u32;
780 unsigned char *char_data;
781 vm_offset_t draw_pos;
783 line_width = scp->sc->adp->va_line_width;
784 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
786 draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
787 (scp->font_size - scp->cursor_base - 1) * line_width;
789 a = sc_vtb_geta(&scp->vtb, at);
792 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
793 ((a & 0xf000) >> 4)) >> 8];
794 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
797 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
799 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
800 ((a & 0xf000) >> 4)) >> 8];
803 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
804 scp->font_size - scp->cursor_base - 1]);
806 height = imin(scp->cursor_height, scp->font_size);
808 for (i = 0; i < height; ++i, --char_data) {
811 for (j = 0; j < 2 * pixel_size; ++j) {
814 for (k = 0; k < 4 / pixel_size; ++k) {
815 u32 += (*char_data & (1 << pos--) ?
816 fg : bg) << (k * 8 * pixel_size);
819 writel(draw_pos, u32);
823 draw_pos -= line_width + 8 * pixel_size;
828 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
830 int line_width, height;
832 uint32_t fg, bg, u32;
833 unsigned char *char_data;
834 vm_offset_t draw_pos;
836 line_width = scp->sc->adp->va_line_width;
838 draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
839 (scp->font_size - scp->cursor_base - 1) * line_width;
841 a = sc_vtb_geta(&scp->vtb, at);
844 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
845 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
847 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
848 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
851 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
852 scp->font_size - scp->cursor_base - 1]);
854 height = imin(scp->cursor_height, scp->font_size);
856 for (i = 0; i < height; ++i, --char_data) {
857 u32 = ((*char_data & 1 ? fg : bg) << 24) +
858 ((*char_data & 2 ? fg : bg) << 16) +
859 ((*char_data & 4 ? fg : bg) << 8) +
860 (*char_data & 8 ? fg : bg);
861 writel(draw_pos + 4, u32);
863 u32 = ((*char_data & 16 ? fg : bg) << 24) +
864 ((*char_data & 32 ? fg : bg) << 16) +
865 ((*char_data & 64 ? fg : bg) << 8) +
866 (*char_data & 128 ? fg : bg);
867 writel(draw_pos, u32);
869 draw_pos -= line_width;
874 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
885 line_width = scp->sc->adp->va_line_width;
887 d = VIDEO_MEMORY_POS(scp, at, 1) +
888 (scp->font_size - scp->cursor_base - 1) * line_width;
890 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
891 outw(GDCIDX, 0x0003); /* data rotate/function select */
892 outw(GDCIDX, 0x0f01); /* set/reset enable */
893 /* set background color in EGA/VGA latch */
894 a = sc_vtb_geta(&scp->vtb, at);
896 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
898 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
899 outw(GDCIDX, col | 0x00); /* set/reset */
900 outw(GDCIDX, 0xff08); /* bit mask */
902 c = readb(d); /* set bg color in the latch */
903 /* foreground color */
905 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
907 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
908 outw(GDCIDX, col | 0x00); /* set/reset */
909 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
910 + scp->font_size - scp->cursor_base - 1]);
911 height = imin(scp->cursor_height, scp->font_size);
912 for (i = 0; i < height; ++i, --f) {
913 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
917 outw(GDCIDX, 0x0000); /* set/reset */
918 outw(GDCIDX, 0x0001); /* set/reset enable */
919 outw(GDCIDX, 0xff08); /* bit mask */
922 static int pxlblinkrate = 0;
925 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
927 if (scp->cursor_height <= 0) /* the text cursor is disabled */
932 scp->status |= VR_CURSOR_ON;
933 draw_pxlcursor_direct(scp, at, on, flip);
934 } else if (++pxlblinkrate & 4) {
936 scp->status ^= VR_CURSOR_ON;
937 draw_pxlcursor_direct(scp, at,
938 scp->status & VR_CURSOR_ON,
942 if (scp->status & VR_CURSOR_ON)
943 draw_pxlcursor_direct(scp, at, on, flip);
944 scp->status &= ~VR_CURSOR_ON;
947 scp->status |= VR_CURSOR_BLINK;
949 scp->status &= ~VR_CURSOR_BLINK;
953 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
955 if (scp->cursor_height <= 0) /* the text cursor is disabled */
960 scp->status |= VR_CURSOR_ON;
961 draw_pxlcursor_packed(scp, at, on, flip);
962 } else if (++pxlblinkrate & 4) {
964 scp->status ^= VR_CURSOR_ON;
965 draw_pxlcursor_packed(scp, at,
966 scp->status & VR_CURSOR_ON,
970 if (scp->status & VR_CURSOR_ON)
971 draw_pxlcursor_packed(scp, at, on, flip);
972 scp->status &= ~VR_CURSOR_ON;
975 scp->status |= VR_CURSOR_BLINK;
977 scp->status &= ~VR_CURSOR_BLINK;
981 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
983 if (scp->cursor_height <= 0) /* the text cursor is disabled */
988 scp->status |= VR_CURSOR_ON;
989 draw_pxlcursor_planar(scp, at, on, flip);
990 } else if (++pxlblinkrate & 4) {
992 scp->status ^= VR_CURSOR_ON;
993 draw_pxlcursor_planar(scp, at,
994 scp->status & VR_CURSOR_ON,
998 if (scp->status & VR_CURSOR_ON)
999 draw_pxlcursor_planar(scp, at, on, flip);
1000 scp->status &= ~VR_CURSOR_ON;
1003 scp->status |= VR_CURSOR_BLINK;
1005 scp->status &= ~VR_CURSOR_BLINK;
1009 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1011 if (!(scp->status & VR_CURSOR_BLINK))
1013 if (!(++pxlblinkrate & 4))
1016 scp->status ^= VR_CURSOR_ON;
1017 draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1021 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1023 if (!(scp->status & VR_CURSOR_BLINK))
1025 if (!(++pxlblinkrate & 4))
1028 scp->status ^= VR_CURSOR_ON;
1029 draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1033 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1035 if (!(scp->status & VR_CURSOR_BLINK))
1037 if (!(++pxlblinkrate & 4))
1040 scp->status ^= VR_CURSOR_ON;
1041 draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1044 #ifndef SC_NO_CUTPASTE
1047 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1049 int line_width, pixel_size;
1052 vm_offset_t draw_pos;
1054 line_width = scp->sc->adp->va_line_width;
1055 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1057 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1058 yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1060 draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1062 for (i = 0; i < (yend - y); i++) {
1063 for (j = (xend - x - 1); j >= 0; j--) {
1064 switch (scp->sc->adp->va_info.vi_depth) {
1066 if (mouse_or_mask[i] & 1 << (15 - j))
1067 writel(draw_pos + 4 * j,
1068 scp->ega_palette[15]);
1069 else if (mouse_and_mask[i] & 1 << (15 - j))
1070 writel(draw_pos + 4 * j,
1071 scp->ega_palette[0]);
1076 if (mouse_or_mask[i] & 1 << (15 - j))
1077 writew(draw_pos + 2 * j,
1078 scp->ega_palette[15]);
1079 else if (mouse_and_mask[i] & 1 << (15 - j))
1080 writew(draw_pos + 2 * j,
1081 scp->ega_palette[0]);
1086 draw_pos += line_width;
1091 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1096 vm_offset_t draw_pos;
1098 line_width = scp->sc->adp->va_line_width;
1100 xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel));
1101 yend = imin(scp->font_size * (scp->yoff + scp->ysize),
1102 imin(y + 16, scp->ypixel));
1104 draw_pos = scp->sc->adp->va_window + y * line_width + x;
1106 for (i = 0; i < (yend - y); i++) {
1107 for (j = (xend - x - 1); j >= 0; j--) {
1108 if (mouse_or_mask[i] & 1 << (15 - j))
1109 writeb(draw_pos + j, 15);
1110 else if (mouse_and_mask[i] & 1 << (15 - j))
1111 writeb(draw_pos + j, 0);
1114 draw_pos += line_width;
1119 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1128 line_width = scp->sc->adp->va_line_width;
1129 xoff = (x - scp->xoff*8)%8;
1130 ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1132 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
1133 outw(GDCIDX, 0x0001); /* set/reset enable */
1134 outw(GDCIDX, 0x0002); /* color compare */
1135 outw(GDCIDX, 0x0007); /* color don't care */
1136 outw(GDCIDX, 0xff08); /* bit mask */
1137 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
1138 p = scp->sc->adp->va_window + line_width*y + x/8;
1139 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1140 for (i = y, j = 0; i < ymax; ++i, ++j) {
1141 m = ~(mouse_and_mask[j] >> xoff);
1142 *(u_char *)p &= m >> 8;
1143 *(u_char *)(p + 1) &= m;
1148 for (i = y, j = 0; i < ymax; ++i, ++j) {
1149 m = ~(mouse_and_mask[j] >> xoff);
1154 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
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_or_mask[j] >> xoff;
1159 *(u_char *)p &= m >> 8;
1160 *(u_char *)(p + 1) &= m;
1164 for (i = y, j = 0; i < ymax; ++i, ++j) {
1165 m = mouse_or_mask[j] >> xoff;
1170 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
1171 outw(GDCIDX, 0x0003); /* data rotate/function select */
1175 remove_pxlmouse(scr_stat *scp, int x, int y)
1181 /* erase the mouse cursor image */
1182 col = x/8 - scp->xoff;
1183 row = y/scp->font_size - scp->yoff;
1184 pos = row*scp->xsize + col;
1185 i = (col < scp->xsize - 1) ? 2 : 1;
1186 (*scp->rndr->draw)(scp, pos, i, FALSE);
1187 if (row < scp->ysize - 1)
1188 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1192 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1195 draw_pxlmouse_direct(scp, x, y);
1197 remove_pxlmouse(scp, x, y);
1201 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1204 draw_pxlmouse_packed(scp, x, y);
1206 remove_pxlmouse(scp, x, y);
1210 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1213 draw_pxlmouse_planar(scp, x, y);
1215 remove_pxlmouse(scp, x, y);
1218 #endif /* SC_NO_CUTPASTE */
1219 #endif /* SC_PIXEL_MODE */
1221 #ifndef SC_NO_MODE_CHANGE
1223 /* graphics mode renderer */
1226 vga_grborder(scr_stat *scp, int color)
1228 lwkt_gettoken(&tty_token);
1229 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1230 lwkt_reltoken(&tty_token);