2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * This code is derived from software contributed to The DragonFly Project
6 * by Sascha Wildner <saw@online.de>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer as
13 * the first lines of this file unmodified.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * $FreeBSD: src/sys/dev/syscons/scvgarndr.c,v 1.5.2.3 2001/07/28 12:51:47 yokota Exp $
32 #include "opt_syscons.h"
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/thread.h>
39 #include <sys/thread2.h>
41 #include <machine/console.h>
43 #include <dev/video/fb/fbreg.h>
44 #include <dev/video/fb/vgareg.h>
47 #include <bus/isa/isareg.h>
49 static vr_draw_border_t vga_txtborder;
50 static vr_draw_t vga_txtdraw;
51 static vr_set_cursor_t vga_txtcursor_shape;
52 static vr_draw_cursor_t vga_txtcursor;
53 static vr_blink_cursor_t vga_txtblink;
54 #ifndef SC_NO_CUTPASTE
55 static vr_draw_mouse_t vga_txtmouse;
57 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop
61 static vr_draw_border_t vga_pxlborder_direct;
62 static vr_draw_border_t vga_pxlborder_packed;
63 static vr_draw_border_t vga_pxlborder_planar;
64 static vr_draw_t vga_vgadraw_direct;
65 static vr_draw_t vga_vgadraw_packed;
66 static vr_draw_t vga_vgadraw_planar;
67 static vr_set_cursor_t vga_pxlcursor_shape;
68 static vr_draw_cursor_t vga_pxlcursor_direct;
69 static vr_draw_cursor_t vga_pxlcursor_packed;
70 static vr_draw_cursor_t vga_pxlcursor_planar;
71 static vr_blink_cursor_t vga_pxlblink_direct;
72 static vr_blink_cursor_t vga_pxlblink_packed;
73 static vr_blink_cursor_t vga_pxlblink_planar;
74 #ifndef SC_NO_CUTPASTE
75 static vr_draw_mouse_t vga_pxlmouse_direct;
76 static vr_draw_mouse_t vga_pxlmouse_packed;
77 static vr_draw_mouse_t vga_pxlmouse_planar;
79 #define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop
80 #define vga_pxlmouse_packed (vr_draw_mouse_t *)vga_nop
81 #define vga_pxlmouse_planar (vr_draw_mouse_t *)vga_nop
83 #endif /* SC_PIXEL_MODE */
85 #ifndef SC_NO_MODE_CHANGE
86 static vr_draw_border_t vga_grborder;
89 static void vga_nop(scr_stat *scp, ...);
91 static sc_rndr_sw_t txtrndrsw = {
99 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set);
102 static sc_rndr_sw_t directrndrsw = {
103 vga_pxlborder_direct,
106 vga_pxlcursor_direct,
110 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set);
112 static sc_rndr_sw_t packedrndrsw = {
113 vga_pxlborder_packed,
116 vga_pxlcursor_packed,
120 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set);
122 static sc_rndr_sw_t planarrndrsw = {
123 vga_pxlborder_planar,
126 vga_pxlcursor_planar,
130 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set);
131 #endif /* SC_PIXEL_MODE */
133 #ifndef SC_NO_MODE_CHANGE
134 static sc_rndr_sw_t grrndrsw = {
136 (vr_draw_t *)vga_nop,
137 (vr_set_cursor_t *)vga_nop,
138 (vr_draw_cursor_t *)vga_nop,
139 (vr_blink_cursor_t *)vga_nop,
140 (vr_draw_mouse_t *)vga_nop,
142 RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set);
143 #endif /* SC_NO_MODE_CHANGE */
145 RENDERER_MODULE(vga, vga_set);
147 #ifndef SC_NO_CUTPASTE
148 static u_short mouse_and_mask[16] = {
149 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
150 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
152 static u_short mouse_or_mask[16] = {
153 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
154 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
159 vga_nop(scr_stat *scp, ...)
163 /* text mode renderer */
166 vga_txtborder(scr_stat *scp, int color)
168 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
172 vga_txtdraw(scr_stat *scp, int from, int count, int flip)
178 if (from + count > scp->xsize*scp->ysize)
179 count = scp->xsize*scp->ysize - from;
182 for (p = scp->scr.vtb_buffer + from; count-- > 0; ++from) {
183 c = sc_vtb_getc(&scp->vtb, from);
184 a = sc_vtb_geta(&scp->vtb, from);
185 a = (a & 0x8800) | ((a & 0x7000) >> 4)
186 | ((a & 0x0700) << 4);
187 p = sc_vtb_putchar(&scp->scr, p, c, a);
190 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
195 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
197 if (base < 0 || base >= scp->font_height)
200 /* the caller may set height <= 0 in order to disable the cursor */
202 scp->cursor_base = base;
203 scp->cursor_height = height;
205 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
213 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
218 scp->cursor_saveunder_char = c;
219 scp->cursor_saveunder_attr = a;
221 #ifndef SC_NO_FONT_LOADING
222 if (sc->flags & SC_CHAR_CURSOR) {
227 if (scp->font_height < 14) {
230 } else if (scp->font_height >= 16) {
237 if (scp->cursor_base >= h)
241 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
242 bcopy(font + c*h, font + sc->cursor_char*h, h);
243 font = font + sc->cursor_char*h;
244 for (i = imax(h - scp->cursor_base - scp->cursor_height, 0);
245 i < h - scp->cursor_base; ++i) {
248 sc->font_loading_in_progress = TRUE;
250 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font,
252 sc->font_loading_in_progress = FALSE;
253 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a);
255 #endif /* SC_NO_FONT_LOADING */
257 if ((a & 0x7000) == 0x7000) {
259 if ((a & 0x0700) == 0)
263 if ((a & 0x0700) == 0x0700)
268 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
269 sc_vtb_putc(&scp->scr, at, c, a);
274 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
276 video_adapter_t *adp;
279 if (scp->cursor_height <= 0) /* the text cursor is disabled */
284 scp->status |= VR_CURSOR_BLINK;
286 scp->status |= VR_CURSOR_ON;
287 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
291 if (scp->status & VR_CURSOR_ON)
292 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
294 scp->status &= ~VR_CURSOR_ON;
297 scp->status &= ~VR_CURSOR_BLINK;
299 scp->status |= VR_CURSOR_ON;
300 draw_txtcharcursor(scp, at,
301 sc_vtb_getc(&scp->scr, at),
302 sc_vtb_geta(&scp->scr, at),
305 cursor_attr = scp->cursor_saveunder_attr;
307 cursor_attr = (cursor_attr & 0x8800)
308 | ((cursor_attr & 0x7000) >> 4)
309 | ((cursor_attr & 0x0700) << 4);
310 if (scp->status & VR_CURSOR_ON)
311 sc_vtb_putc(&scp->scr, at,
312 scp->cursor_saveunder_char,
314 scp->status &= ~VR_CURSOR_ON;
320 vga_txtblink(scr_stat *scp, int at, int flip)
324 int sc_txtmouse_no_retrace_wait;
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_height - scp->yoff) * scp->xsize +
342 x / scp->font_width - scp->xoff;
343 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos) * scp->font_height,
344 &font_buf[0], scp->font_height);
345 bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1) * scp->font_height,
346 &font_buf[32], scp->font_height);
348 + sc_vtb_getc(&scp->scr, pos + scp->xsize) * scp->font_height,
349 &font_buf[64], scp->font_height);
351 sc_vtb_getc(&scp->scr, pos + scp->xsize + 1) * scp->font_height,
352 &font_buf[96], scp->font_height);
353 for (i = 0; i < scp->font_height; ++i) {
354 cursor[i] = (font_buf[i]<<8) | font_buf[i+32];
355 cursor[i + scp->font_height] = (font_buf[i+64]<<8) |
359 /* now and-or in the mousepointer image */
360 xoffset = x % scp->font_width;
361 yoffset = y % scp->font_height;
362 for (i = 0; i < 16; ++i) {
363 cursor[i + yoffset] =
364 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
365 | (mouse_or_mask[i] >> xoffset);
367 for (i = 0; i < scp->font_height; ++i) {
368 font_buf[i] = (cursor[i] & 0xff00) >> 8;
369 font_buf[i + 32] = cursor[i] & 0xff;
370 font_buf[i + 64] = (cursor[i + scp->font_height] & 0xff00) >> 8;
371 font_buf[i + 96] = cursor[i + scp->font_height] & 0xff;
375 /* wait for vertical retrace to avoid jitter on some videocards */
376 while (!sc_txtmouse_no_retrace_wait &&
377 !(inb(CRTC + 6) & 0x08))
380 c = scp->sc->mouse_char;
381 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
384 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
385 /* FIXME: may be out of range! */
386 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
387 sc_vtb_geta(&scp->scr, pos + scp->xsize));
388 if (x < (scp->xsize - 1)*8) {
389 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
390 sc_vtb_geta(&scp->scr, pos + 1));
391 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
392 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
395 #endif /* SC_ALT_MOUSE_IMAGE */
397 /* Red, magenta and brown are mapped to green to to keep it readable */
398 static const int col_conv[16] = {
399 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
405 pos = (y / scp->font_height - scp->yoff)*
406 scp->xsize + x / scp->font_width - scp->xoff;
407 a = sc_vtb_geta(&scp->scr, pos);
408 if (scp->sc->adp->va_flags & V_ADP_COLOR)
409 color = (col_conv[(a & 0xf000) >> 12] << 12)
410 | ((a & 0x0f00) | 0x0800);
412 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
413 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
419 remove_txtmouse(scr_stat *scp, int x, int y)
424 vga_txtmouse(scr_stat *scp, int x, int y, int on)
427 draw_txtmouse(scp, x, y);
429 remove_txtmouse(scp, x, y);
432 #endif /* SC_NO_CUTPASTE */
436 /* pixel (raster text) mode renderer */
439 vga_pxlborder_direct(scr_stat *scp, int color)
442 int line_width, pixel_size;
444 vm_offset_t draw_pos, draw_end, p;
446 line_width = scp->sc->adp->va_line_width;
447 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
449 for (i = 0; i < 4 / pixel_size; ++i)
450 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
453 draw_pos = scp->sc->adp->va_window;
454 draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
456 for (p = draw_pos; p < draw_end; p += 4)
460 y = (scp->yoff + scp->ysize) * scp->font_height;
462 if (scp->ypixel > y) {
463 draw_pos = scp->sc->adp->va_window + line_width * y;
464 draw_end = draw_pos + line_width * (scp->ypixel - y);
466 for (p = draw_pos; p < draw_end; p += 4)
470 y = scp->yoff * scp->font_height;
471 x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
473 for (i = 0; i < scp->ysize * scp->font_height; ++i) {
475 draw_pos = scp->sc->adp->va_window +
476 line_width * (y + i);
477 draw_end = draw_pos +
478 scp->xoff * scp->font_width * pixel_size;
480 for (p = draw_pos; p < draw_end; p += 4)
485 draw_pos = scp->sc->adp->va_window +
486 line_width * (y + i) +
487 scp->xoff * 8 * pixel_size +
488 scp->xsize * 8 * pixel_size;
489 draw_end = draw_pos + x * 8 * pixel_size;
491 for (p = draw_pos; p < draw_end; p += 4)
498 vga_pxlborder_packed(scr_stat *scp, int color)
503 vm_offset_t draw_pos, draw_end, p;
505 line_width = scp->sc->adp->va_line_width;
506 u32 = (color << 24) + (color << 16) + (color << 8) + color;
509 draw_pos = scp->sc->adp->va_window;
510 draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
512 for (p = draw_pos; p < draw_end; p += 4)
516 y = (scp->yoff + scp->ysize) * scp->font_height;
518 if (scp->ypixel > y) {
519 draw_pos = scp->sc->adp->va_window + line_width * y;
520 draw_end = draw_pos + line_width * (scp->ypixel - y);
522 for (p = draw_pos; p < draw_end; p += 4)
526 y = scp->yoff * scp->font_height;
527 x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
529 for (i = 0; i < scp->ysize * scp->font_height; ++i) {
531 draw_pos = scp->sc->adp->va_window +
532 line_width * (y + i);
533 draw_end = draw_pos + scp->xoff * scp->font_width;
535 for (p = draw_pos; p < draw_end; p += 4)
540 draw_pos = scp->sc->adp->va_window +
541 line_width * (y + i) + scp->xoff * 8 +
543 draw_end = draw_pos + x * 8;
545 for (p = draw_pos; p < draw_end; p += 4)
552 vga_pxlborder_planar(scr_stat *scp, int color)
560 lwkt_gettoken(&tty_token);
562 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
564 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
565 outw(GDCIDX, 0x0003); /* data rotate/function select */
566 outw(GDCIDX, 0x0f01); /* set/reset enable */
567 outw(GDCIDX, 0xff08); /* bit mask */
568 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
569 line_width = scp->sc->adp->va_line_width;
570 p = scp->sc->adp->va_window;
572 bzero_io((void *)p, line_width*scp->yoff*scp->font_height);
573 y = (scp->yoff + scp->ysize)*scp->font_height;
575 bzero_io((void *)(p + line_width*y),
576 line_width*(scp->ypixel - y));
577 y = scp->yoff*scp->font_height;
578 x = scp->xpixel/scp->font_width - scp->xoff - scp->xsize;
579 for (i = 0; i < scp->ysize*scp->font_height; ++i) {
581 bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
583 bzero_io((void *)(p + line_width*(y + i)
584 + scp->xoff + scp->xsize), x);
586 outw(GDCIDX, 0x0000); /* set/reset */
587 outw(GDCIDX, 0x0001); /* set/reset enable */
588 lwkt_reltoken(&tty_token);
592 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
594 int line_width, pixel_size;
595 int a, i, j, k, l, pos;
596 uint32_t fg, bg, u32;
597 unsigned char *char_data;
598 vm_offset_t draw_pos, p;
600 line_width = scp->sc->adp->va_line_width;
601 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
603 draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
605 if (from + count > scp->xsize * scp->ysize)
606 count = scp->xsize * scp->ysize - from;
608 for (i = from; count-- > 0; ++i) {
609 a = sc_vtb_geta(&scp->vtb, i);
612 fg = scp->ega_palette[(((a & 0x7000) >> 4) |
614 bg = scp->ega_palette[(((a & 0x8000) >> 4) |
617 fg = scp->ega_palette[(a & 0x0f00) >> 8];
618 bg = scp->ega_palette[(a & 0xf000) >> 12];
622 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
625 for (j = 0; j < scp->font_height; ++j, ++char_data) {
628 for (k = 0; k < 2 * pixel_size; ++k) {
631 for (l = 0; l < 4 / pixel_size; ++l) {
632 u32 += (*char_data & (1 << pos--) ?
633 fg : bg) << (l * 8 * pixel_size);
640 p += line_width - 8 * pixel_size;
643 draw_pos += 8 * pixel_size;
645 if ((i % scp->xsize) == scp->xsize - 1)
646 draw_pos += scp->xoff * 16 * pixel_size +
647 (scp->font_height - 1) * line_width;
652 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
656 uint32_t fg, bg, u32;
657 unsigned char *char_data;
658 vm_offset_t draw_pos, p;
660 line_width = scp->sc->adp->va_line_width;
662 draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
664 if (from + count > scp->xsize * scp->ysize)
665 count = scp->xsize * scp->ysize - from;
667 for (i = from; count-- > 0; ++i) {
668 a = sc_vtb_geta(&scp->vtb, i);
671 fg = ((a & 0xf000) >> 4) >> 8;
672 bg = (a & 0x0f00) >> 8;
674 fg = (a & 0x0f00) >> 8;
675 bg = ((a & 0xf000) >> 4) >> 8;
679 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
682 for (j = 0; j < scp->font_height; ++j, ++char_data) {
683 u32 = ((*char_data & 1 ? fg : bg) << 24) +
684 ((*char_data & 2 ? fg : bg) << 16) +
685 ((*char_data & 4 ? fg : bg) << 8) +
686 (*char_data & 8 ? fg : bg);
689 u32 = ((*char_data & 16 ? fg : bg) << 24) +
690 ((*char_data & 32 ? fg : bg) << 16) +
691 ((*char_data & 64 ? fg : bg) << 8) +
692 (*char_data & 128 ? fg : bg);
698 draw_pos += scp->font_width;
700 if ((i % scp->xsize) == scp->xsize - 1)
701 draw_pos += scp->xoff * 16 +
702 (scp->font_height - 1) * line_width;
707 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
719 d = VIDEO_MEMORY_POS(scp, from, 1);
721 line_width = scp->sc->adp->va_line_width;
723 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
724 outw(GDCIDX, 0x0003); /* data rotate/function select */
725 outw(GDCIDX, 0x0f01); /* set/reset enable */
726 outw(GDCIDX, 0xff08); /* bit mask */
728 if (from + count > scp->xsize*scp->ysize)
729 count = scp->xsize*scp->ysize - from;
730 for (i = from; count-- > 0; ++i) {
731 a = sc_vtb_geta(&scp->vtb, i);
733 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
734 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
737 col2 = (a & 0xf000) >> 4;
739 /* set background color in EGA/VGA latch */
742 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
743 outw(GDCIDX, bg | 0x00); /* set/reset */
745 c = readb(d); /* set bg color in the latch */
746 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
748 /* foreground color */
749 outw(GDCIDX, col1 | 0x00); /* set/reset */
751 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_height]);
752 for (j = 0; j < scp->font_height; ++j, ++f) {
757 if ((i % scp->xsize) == scp->xsize - 1)
759 + (scp->font_height - 1)*line_width;
761 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
762 outw(GDCIDX, 0x0000); /* set/reset */
763 outw(GDCIDX, 0x0001); /* set/reset enable */
767 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
769 if (base < 0 || base >= scp->font_height)
771 /* the caller may set height <= 0 in order to disable the cursor */
773 scp->cursor_base = base;
774 scp->cursor_height = height;
779 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
781 int line_width, pixel_size, height;
783 uint32_t fg, bg, u32;
784 unsigned char *char_data;
785 vm_offset_t draw_pos;
787 line_width = scp->sc->adp->va_line_width;
788 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
790 draw_pos = VIDEO_MEMORY_POS(scp, at, scp->font_width * pixel_size) +
791 (scp->font_height - scp->cursor_base - 1) * line_width;
793 a = sc_vtb_geta(&scp->vtb, at);
796 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
797 ((a & 0xf000) >> 4)) >> 8];
798 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
801 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
803 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
804 ((a & 0xf000) >> 4)) >> 8];
807 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
808 scp->font_height - scp->cursor_base - 1]);
810 height = imin(scp->cursor_height, scp->font_height);
812 for (i = 0; i < height; ++i, --char_data) {
815 for (j = 0; j < 2 * pixel_size; ++j) {
818 for (k = 0; k < 4 / pixel_size; ++k) {
819 u32 += (*char_data & (1 << pos--) ?
820 fg : bg) << (k * 8 * pixel_size);
823 writel(draw_pos, u32);
827 draw_pos -= line_width + 8 * pixel_size;
832 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
834 int line_width, height;
836 uint32_t fg, bg, u32;
837 unsigned char *char_data;
838 vm_offset_t draw_pos;
840 line_width = scp->sc->adp->va_line_width;
842 draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
843 (scp->font_height - scp->cursor_base - 1) * line_width;
845 a = sc_vtb_geta(&scp->vtb, at);
848 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
849 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
851 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
852 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
855 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
856 scp->font_height - scp->cursor_base - 1]);
858 height = imin(scp->cursor_height, scp->font_height);
860 for (i = 0; i < height; ++i, --char_data) {
861 u32 = ((*char_data & 1 ? fg : bg) << 24) +
862 ((*char_data & 2 ? fg : bg) << 16) +
863 ((*char_data & 4 ? fg : bg) << 8) +
864 (*char_data & 8 ? fg : bg);
865 writel(draw_pos + 4, u32);
867 u32 = ((*char_data & 16 ? fg : bg) << 24) +
868 ((*char_data & 32 ? fg : bg) << 16) +
869 ((*char_data & 64 ? fg : bg) << 8) +
870 (*char_data & 128 ? fg : bg);
871 writel(draw_pos, u32);
873 draw_pos -= line_width;
878 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
889 line_width = scp->sc->adp->va_line_width;
891 d = VIDEO_MEMORY_POS(scp, at, 1) +
892 (scp->font_height - scp->cursor_base - 1) * line_width;
894 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
895 outw(GDCIDX, 0x0003); /* data rotate/function select */
896 outw(GDCIDX, 0x0f01); /* set/reset enable */
897 /* set background color in EGA/VGA latch */
898 a = sc_vtb_geta(&scp->vtb, at);
900 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
902 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
903 outw(GDCIDX, col | 0x00); /* set/reset */
904 outw(GDCIDX, 0xff08); /* bit mask */
906 c = readb(d); /* set bg color in the latch */
907 /* foreground color */
909 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
911 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
912 outw(GDCIDX, col | 0x00); /* set/reset */
913 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_height
914 + scp->font_height - scp->cursor_base - 1]);
915 height = imin(scp->cursor_height, scp->font_height);
916 for (i = 0; i < height; ++i, --f) {
917 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
921 outw(GDCIDX, 0x0000); /* set/reset */
922 outw(GDCIDX, 0x0001); /* set/reset enable */
923 outw(GDCIDX, 0xff08); /* bit mask */
926 static int pxlblinkrate = 0;
929 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
931 if (scp->cursor_height <= 0) /* the text cursor is disabled */
936 scp->status |= VR_CURSOR_ON;
937 draw_pxlcursor_direct(scp, at, on, flip);
938 } else if (++pxlblinkrate & 4) {
940 scp->status ^= VR_CURSOR_ON;
941 draw_pxlcursor_direct(scp, at,
942 scp->status & VR_CURSOR_ON,
946 if (scp->status & VR_CURSOR_ON)
947 draw_pxlcursor_direct(scp, at, on, flip);
948 scp->status &= ~VR_CURSOR_ON;
951 scp->status |= VR_CURSOR_BLINK;
953 scp->status &= ~VR_CURSOR_BLINK;
957 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
959 if (scp->cursor_height <= 0) /* the text cursor is disabled */
964 scp->status |= VR_CURSOR_ON;
965 draw_pxlcursor_packed(scp, at, on, flip);
966 } else if (++pxlblinkrate & 4) {
968 scp->status ^= VR_CURSOR_ON;
969 draw_pxlcursor_packed(scp, at,
970 scp->status & VR_CURSOR_ON,
974 if (scp->status & VR_CURSOR_ON)
975 draw_pxlcursor_packed(scp, at, on, flip);
976 scp->status &= ~VR_CURSOR_ON;
979 scp->status |= VR_CURSOR_BLINK;
981 scp->status &= ~VR_CURSOR_BLINK;
985 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
987 if (scp->cursor_height <= 0) /* the text cursor is disabled */
992 scp->status |= VR_CURSOR_ON;
993 draw_pxlcursor_planar(scp, at, on, flip);
994 } else if (++pxlblinkrate & 4) {
996 scp->status ^= VR_CURSOR_ON;
997 draw_pxlcursor_planar(scp, at,
998 scp->status & VR_CURSOR_ON,
1002 if (scp->status & VR_CURSOR_ON)
1003 draw_pxlcursor_planar(scp, at, on, flip);
1004 scp->status &= ~VR_CURSOR_ON;
1007 scp->status |= VR_CURSOR_BLINK;
1009 scp->status &= ~VR_CURSOR_BLINK;
1013 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1015 if (!(scp->status & VR_CURSOR_BLINK))
1017 if (!(++pxlblinkrate & 4))
1020 scp->status ^= VR_CURSOR_ON;
1021 draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1025 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1027 if (!(scp->status & VR_CURSOR_BLINK))
1029 if (!(++pxlblinkrate & 4))
1032 scp->status ^= VR_CURSOR_ON;
1033 draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1037 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1039 if (!(scp->status & VR_CURSOR_BLINK))
1041 if (!(++pxlblinkrate & 4))
1044 scp->status ^= VR_CURSOR_ON;
1045 draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1048 #ifndef SC_NO_CUTPASTE
1051 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1053 int line_width, pixel_size;
1056 vm_offset_t draw_pos;
1058 line_width = scp->sc->adp->va_line_width;
1059 pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1061 xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1062 yend = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
1064 draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1066 for (i = 0; i < (yend - y); i++) {
1067 for (j = (xend - x - 1); j >= 0; j--) {
1068 switch (scp->sc->adp->va_info.vi_depth) {
1070 if (mouse_or_mask[i] & 1 << (15 - j))
1071 writel(draw_pos + 4 * j,
1072 scp->ega_palette[15]);
1073 else if (mouse_and_mask[i] & 1 << (15 - j))
1074 writel(draw_pos + 4 * j,
1075 scp->ega_palette[0]);
1080 if (mouse_or_mask[i] & 1 << (15 - j))
1081 writew(draw_pos + 2 * j,
1082 scp->ega_palette[15]);
1083 else if (mouse_and_mask[i] & 1 << (15 - j))
1084 writew(draw_pos + 2 * j,
1085 scp->ega_palette[0]);
1090 draw_pos += line_width;
1095 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1100 vm_offset_t draw_pos;
1102 line_width = scp->sc->adp->va_line_width;
1104 xend = imin(scp->font_width * (scp->xoff + scp->xsize),
1105 imin(x + 16, scp->xpixel));
1106 yend = imin(scp->font_height * (scp->yoff + scp->ysize),
1107 imin(y + 16, scp->ypixel));
1109 draw_pos = scp->sc->adp->va_window + y * line_width + x;
1111 for (i = 0; i < (yend - y); i++) {
1112 for (j = (xend - x - 1); j >= 0; j--) {
1113 if (mouse_or_mask[i] & 1 << (15 - j))
1114 writeb(draw_pos + j, 15);
1115 else if (mouse_and_mask[i] & 1 << (15 - j))
1116 writeb(draw_pos + j, 0);
1119 draw_pos += line_width;
1124 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1133 line_width = scp->sc->adp->va_line_width;
1134 xoff = (x - scp->xoff*8)%8;
1135 ymax = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
1137 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
1138 outw(GDCIDX, 0x0001); /* set/reset enable */
1139 outw(GDCIDX, 0x0002); /* color compare */
1140 outw(GDCIDX, 0x0007); /* color don't care */
1141 outw(GDCIDX, 0xff08); /* bit mask */
1142 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
1143 p = scp->sc->adp->va_window + line_width*y + x/8;
1144 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1145 for (i = y, j = 0; i < ymax; ++i, ++j) {
1146 m = ~(mouse_and_mask[j] >> xoff);
1147 *(u_char *)p &= m >> 8;
1148 *(u_char *)(p + 1) &= m;
1153 for (i = y, j = 0; i < ymax; ++i, ++j) {
1154 m = ~(mouse_and_mask[j] >> xoff);
1159 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
1160 p = scp->sc->adp->va_window + line_width*y + x/8;
1161 if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1162 for (i = y, j = 0; i < ymax; ++i, ++j) {
1163 m = mouse_or_mask[j] >> xoff;
1164 *(u_char *)p &= m >> 8;
1165 *(u_char *)(p + 1) &= m;
1169 for (i = y, j = 0; i < ymax; ++i, ++j) {
1170 m = mouse_or_mask[j] >> xoff;
1175 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
1176 outw(GDCIDX, 0x0003); /* data rotate/function select */
1180 remove_pxlmouse(scr_stat *scp, int x, int y)
1186 /* erase the mouse cursor image */
1187 col = x / scp->font_width - scp->xoff;
1188 row = y / scp->font_height - scp->yoff;
1189 pos = row * scp->xsize + col;
1190 i = (col < scp->xsize - 1) ? 2 : 1;
1191 (*scp->rndr->draw)(scp, pos, i, FALSE);
1192 if (row < scp->ysize - 1)
1193 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1197 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1200 draw_pxlmouse_direct(scp, x, y);
1202 remove_pxlmouse(scp, x, y);
1206 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1209 draw_pxlmouse_packed(scp, x, y);
1211 remove_pxlmouse(scp, x, y);
1215 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1218 draw_pxlmouse_planar(scp, x, y);
1220 remove_pxlmouse(scp, x, y);
1223 #endif /* SC_NO_CUTPASTE */
1224 #endif /* SC_PIXEL_MODE */
1226 #ifndef SC_NO_MODE_CHANGE
1228 /* graphics mode renderer */
1231 vga_grborder(scr_stat *scp, int color)
1233 lwkt_gettoken(&tty_token);
1234 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1235 lwkt_reltoken(&tty_token);