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 $
30 * $DragonFly: src/sys/dev/misc/syscons/scvgarndr.c,v 1.15 2006/02/19 10:16:26 swildner Exp $
33 #include "opt_syscons.h"
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/kernel.h>
40 #include <machine/console.h>
42 #include <dev/video/fb/fbreg.h>
43 #include <dev/video/fb/vgareg.h>
46 #include <bus/isa/isareg.h>
48 static vr_draw_border_t vga_txtborder
;
49 static vr_draw_t vga_txtdraw
;
50 static vr_set_cursor_t vga_txtcursor_shape
;
51 static vr_draw_cursor_t vga_txtcursor
;
52 static vr_blink_cursor_t vga_txtblink
;
53 #ifndef SC_NO_CUTPASTE
54 static vr_draw_mouse_t vga_txtmouse
;
56 #define vga_txtmouse (vr_draw_mouse_t *)vga_nop
60 static vr_init_t vga_rndrinit
;
61 static vr_draw_border_t vga_pxlborder_direct
;
62 static vr_draw_border_t vga_pxlborder_planar
;
63 static vr_draw_t vga_vgadraw_direct
;
64 static vr_draw_t vga_vgadraw_planar
;
65 static vr_set_cursor_t vga_pxlcursor_shape
;
66 static vr_draw_cursor_t vga_pxlcursor_direct
;
67 static vr_draw_cursor_t vga_pxlcursor_planar
;
68 static vr_blink_cursor_t vga_pxlblink_direct
;
69 static vr_blink_cursor_t vga_pxlblink_planar
;
70 #ifndef SC_NO_CUTPASTE
71 static vr_draw_mouse_t vga_pxlmouse_direct
;
72 static vr_draw_mouse_t vga_pxlmouse_planar
;
74 #define vga_pxlmouse_direct (vr_draw_mouse_t *)vga_nop
75 #define vga_pxlmouse_planar (vr_draw_mouse_t *)vga_nop
77 #endif /* SC_PIXEL_MODE */
79 #ifndef SC_NO_MODE_CHANGE
80 static vr_draw_border_t vga_grborder
;
83 static void vga_nop(scr_stat
*scp
, ...);
85 static sc_rndr_sw_t txtrndrsw
= {
92 (vr_set_mouse_t
*)vga_nop
,
95 RENDERER(vga
, 0, txtrndrsw
, vga_set
);
98 static sc_rndr_sw_t vgarndrsw
= {
100 (vr_draw_border_t
*)vga_nop
,
101 (vr_draw_t
*)vga_nop
,
103 (vr_draw_cursor_t
*)vga_nop
,
104 (vr_blink_cursor_t
*)vga_nop
,
105 (vr_set_mouse_t
*)vga_nop
,
106 (vr_draw_mouse_t
*)vga_nop
,
108 RENDERER(vga
, PIXEL_MODE
, vgarndrsw
, vga_set
);
109 #endif /* SC_PIXEL_MODE */
111 #ifndef SC_NO_MODE_CHANGE
112 static sc_rndr_sw_t grrndrsw
= {
113 (vr_init_t
*)vga_nop
,
115 (vr_draw_t
*)vga_nop
,
116 (vr_set_cursor_t
*)vga_nop
,
117 (vr_draw_cursor_t
*)vga_nop
,
118 (vr_blink_cursor_t
*)vga_nop
,
119 (vr_set_mouse_t
*)vga_nop
,
120 (vr_draw_mouse_t
*)vga_nop
,
122 RENDERER(vga
, GRAPHICS_MODE
, grrndrsw
, vga_set
);
123 #endif /* SC_NO_MODE_CHANGE */
125 RENDERER_MODULE(vga
, vga_set
);
127 #ifndef SC_NO_CUTPASTE
128 static u_short mouse_and_mask
[16] = {
129 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
130 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
132 static u_short mouse_or_mask
[16] = {
133 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
134 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
139 vga_nop(scr_stat
*scp
, ...)
143 /* text mode renderer */
146 vga_txtborder(scr_stat
*scp
, int color
)
148 (*vidsw
[scp
->sc
->adapter
]->set_border
)(scp
->sc
->adp
, color
);
152 vga_txtdraw(scr_stat
*scp
, int from
, int count
, int flip
)
158 if (from
+ count
> scp
->xsize
*scp
->ysize
)
159 count
= scp
->xsize
*scp
->ysize
- from
;
162 for (p
= scp
->scr
.vtb_buffer
+ from
; count
-- > 0; ++from
) {
163 c
= sc_vtb_getc(&scp
->vtb
, from
);
164 a
= sc_vtb_geta(&scp
->vtb
, from
);
165 a
= (a
& 0x8800) | ((a
& 0x7000) >> 4)
166 | ((a
& 0x0700) << 4);
167 p
= sc_vtb_putchar(&scp
->scr
, p
, c
, a
);
170 sc_vtb_copy(&scp
->vtb
, from
, &scp
->scr
, from
, count
);
175 vga_txtcursor_shape(scr_stat
*scp
, int base
, int height
, int blink
)
177 if (base
< 0 || base
>= scp
->font_size
)
179 /* the caller may set height <= 0 in order to disable the cursor */
181 scp
->cursor_base
= base
;
182 scp
->cursor_height
= height
;
184 (*vidsw
[scp
->sc
->adapter
]->set_hw_cursor_shape
)(scp
->sc
->adp
,
186 scp
->font_size
, blink
);
190 draw_txtcharcursor(scr_stat
*scp
, int at
, u_short c
, u_short a
, int flip
)
195 scp
->cursor_saveunder_char
= c
;
196 scp
->cursor_saveunder_attr
= a
;
198 #ifndef SC_NO_FONT_LOADING
199 if (sc
->flags
& SC_CHAR_CURSOR
) {
204 if (scp
->font_size
< 14) {
207 } else if (scp
->font_size
>= 16) {
214 if (scp
->cursor_base
>= h
)
218 | ((a
& 0x7000) >> 4) | ((a
& 0x0700) << 4);
219 bcopy(font
+ c
*h
, font
+ sc
->cursor_char
*h
, h
);
220 font
= font
+ sc
->cursor_char
*h
;
221 for (i
= imax(h
- scp
->cursor_base
- scp
->cursor_height
, 0);
222 i
< h
- scp
->cursor_base
; ++i
) {
225 sc
->font_loading_in_progress
= TRUE
;
227 (*vidsw
[sc
->adapter
]->load_font
)(sc
->adp
, 0, h
, font
,
229 sc
->font_loading_in_progress
= FALSE
;
230 sc_vtb_putc(&scp
->scr
, at
, sc
->cursor_char
, a
);
232 #endif /* SC_NO_FONT_LOADING */
234 if ((a
& 0x7000) == 0x7000) {
236 if ((a
& 0x0700) == 0)
240 if ((a
& 0x0700) == 0x0700)
245 | ((a
& 0x7000) >> 4) | ((a
& 0x0700) << 4);
246 sc_vtb_putc(&scp
->scr
, at
, c
, a
);
251 vga_txtcursor(scr_stat
*scp
, int at
, int blink
, int on
, int flip
)
253 video_adapter_t
*adp
;
256 if (scp
->cursor_height
<= 0) /* the text cursor is disabled */
261 scp
->status
|= VR_CURSOR_BLINK
;
263 scp
->status
|= VR_CURSOR_ON
;
264 (*vidsw
[adp
->va_index
]->set_hw_cursor
)(adp
,
268 if (scp
->status
& VR_CURSOR_ON
)
269 (*vidsw
[adp
->va_index
]->set_hw_cursor
)(adp
,
271 scp
->status
&= ~VR_CURSOR_ON
;
274 scp
->status
&= ~VR_CURSOR_BLINK
;
276 scp
->status
|= VR_CURSOR_ON
;
277 draw_txtcharcursor(scp
, at
,
278 sc_vtb_getc(&scp
->scr
, at
),
279 sc_vtb_geta(&scp
->scr
, at
),
282 cursor_attr
= scp
->cursor_saveunder_attr
;
284 cursor_attr
= (cursor_attr
& 0x8800)
285 | ((cursor_attr
& 0x7000) >> 4)
286 | ((cursor_attr
& 0x0700) << 4);
287 if (scp
->status
& VR_CURSOR_ON
)
288 sc_vtb_putc(&scp
->scr
, at
,
289 scp
->cursor_saveunder_char
,
291 scp
->status
&= ~VR_CURSOR_ON
;
297 vga_txtblink(scr_stat
*scp
, int at
, int flip
)
301 #ifndef SC_NO_CUTPASTE
304 draw_txtmouse(scr_stat
*scp
, int x
, int y
)
306 #ifndef SC_ALT_MOUSE_IMAGE
307 if (ISMOUSEAVAIL(scp
->sc
->adp
->va_flags
)) {
308 u_char font_buf
[128];
312 int xoffset
, yoffset
;
316 /* prepare mousepointer char's bitmaps */
317 pos
= (y
/scp
->font_size
- scp
->yoff
)*scp
->xsize
+ x
/8 - scp
->xoff
;
318 bcopy(scp
->font
+ sc_vtb_getc(&scp
->scr
, pos
)*scp
->font_size
,
319 &font_buf
[0], scp
->font_size
);
320 bcopy(scp
->font
+ sc_vtb_getc(&scp
->scr
, pos
+ 1)*scp
->font_size
,
321 &font_buf
[32], scp
->font_size
);
323 + sc_vtb_getc(&scp
->scr
, pos
+ scp
->xsize
)*scp
->font_size
,
324 &font_buf
[64], scp
->font_size
);
326 + sc_vtb_getc(&scp
->scr
, pos
+ scp
->xsize
+ 1)*scp
->font_size
,
327 &font_buf
[96], scp
->font_size
);
328 for (i
= 0; i
< scp
->font_size
; ++i
) {
329 cursor
[i
] = font_buf
[i
]<<8 | font_buf
[i
+32];
330 cursor
[i
+ scp
->font_size
] = font_buf
[i
+64]<<8 | font_buf
[i
+96];
333 /* now and-or in the mousepointer image */
335 yoffset
= y
%scp
->font_size
;
336 for (i
= 0; i
< 16; ++i
) {
337 cursor
[i
+ yoffset
] =
338 (cursor
[i
+ yoffset
] & ~(mouse_and_mask
[i
] >> xoffset
))
339 | (mouse_or_mask
[i
] >> xoffset
);
341 for (i
= 0; i
< scp
->font_size
; ++i
) {
342 font_buf
[i
] = (cursor
[i
] & 0xff00) >> 8;
343 font_buf
[i
+ 32] = cursor
[i
] & 0xff;
344 font_buf
[i
+ 64] = (cursor
[i
+ scp
->font_size
] & 0xff00) >> 8;
345 font_buf
[i
+ 96] = cursor
[i
+ scp
->font_size
] & 0xff;
349 /* wait for vertical retrace to avoid jitter on some videocards */
350 crtc_addr
= scp
->sc
->adp
->va_crtc_addr
;
351 while (!(inb(crtc_addr
+ 6) & 0x08)) /* idle */ ;
353 c
= scp
->sc
->mouse_char
;
354 (*vidsw
[scp
->sc
->adapter
]->load_font
)(scp
->sc
->adp
, 0, 32, font_buf
,
357 sc_vtb_putc(&scp
->scr
, pos
, c
, sc_vtb_geta(&scp
->scr
, pos
));
358 /* FIXME: may be out of range! */
359 sc_vtb_putc(&scp
->scr
, pos
+ scp
->xsize
, c
+ 2,
360 sc_vtb_geta(&scp
->scr
, pos
+ scp
->xsize
));
361 if (x
< (scp
->xsize
- 1)*8) {
362 sc_vtb_putc(&scp
->scr
, pos
+ 1, c
+ 1,
363 sc_vtb_geta(&scp
->scr
, pos
+ 1));
364 sc_vtb_putc(&scp
->scr
, pos
+ scp
->xsize
+ 1, c
+ 3,
365 sc_vtb_geta(&scp
->scr
, pos
+ scp
->xsize
+ 1));
368 #endif /* SC_ALT_MOUSE_IMAGE */
370 /* Red, magenta and brown are mapped to green to to keep it readable */
371 static const int col_conv
[16] = {
372 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
378 pos
= (y
/scp
->font_size
- scp
->yoff
)*scp
->xsize
+ x
/8 - scp
->xoff
;
379 a
= sc_vtb_geta(&scp
->scr
, pos
);
380 if (scp
->sc
->adp
->va_flags
& V_ADP_COLOR
)
381 color
= (col_conv
[(a
& 0xf000) >> 12] << 12)
382 | ((a
& 0x0f00) | 0x0800);
384 color
= ((a
& 0xf000) >> 4) | ((a
& 0x0f00) << 4);
385 sc_vtb_putc(&scp
->scr
, pos
, sc_vtb_getc(&scp
->scr
, pos
), color
);
390 remove_txtmouse(scr_stat
*scp
, int x
, int y
)
395 vga_txtmouse(scr_stat
*scp
, int x
, int y
, int on
)
398 draw_txtmouse(scp
, x
, y
);
400 remove_txtmouse(scp
, x
, y
);
403 #endif /* SC_NO_CUTPASTE */
407 /* pixel (raster text) mode renderer */
410 vga_rndrinit(scr_stat
*scp
)
412 if (scp
->sc
->adp
->va_info
.vi_mem_model
== V_INFO_MM_PLANAR
) {
413 scp
->rndr
->draw_border
= vga_pxlborder_planar
;
414 scp
->rndr
->draw
= vga_vgadraw_planar
;
415 scp
->rndr
->draw_cursor
= vga_pxlcursor_planar
;
416 scp
->rndr
->blink_cursor
= vga_pxlblink_planar
;
417 scp
->rndr
->draw_mouse
= vga_pxlmouse_planar
;
418 } else if (scp
->sc
->adp
->va_info
.vi_mem_model
== V_INFO_MM_DIRECT
) {
419 scp
->rndr
->draw_border
= vga_pxlborder_direct
;
420 scp
->rndr
->draw
= vga_vgadraw_direct
;
421 scp
->rndr
->draw_cursor
= vga_pxlcursor_direct
;
422 scp
->rndr
->blink_cursor
= vga_pxlblink_direct
;
423 scp
->rndr
->draw_mouse
= vga_pxlmouse_direct
;
428 vga_pxlborder_direct(scr_stat
*scp
, int color
)
431 int line_width
, pixel_size
;
433 vm_offset_t draw_pos
, draw_end
, p
;
435 line_width
= scp
->sc
->adp
->va_line_width
;
436 pixel_size
= scp
->sc
->adp
->va_info
.vi_pixel_size
;
438 for (i
= 0; i
< 4 / pixel_size
; ++i
)
439 u32
+= scp
->ega_palette
[color
] << (i
* 8 * pixel_size
);
442 draw_pos
= scp
->sc
->adp
->va_window
;
443 draw_end
= draw_pos
+
444 line_width
* scp
->yoff
* scp
->font_size
;
446 for (p
= draw_pos
; p
< draw_end
; p
+= 4)
450 y
= (scp
->yoff
+ scp
->ysize
) * scp
->font_size
;
452 if (scp
->ypixel
> y
) {
453 draw_pos
= scp
->sc
->adp
->va_window
+ line_width
* y
;
454 draw_end
= draw_pos
+ line_width
* (scp
->ypixel
- y
);
456 for (p
= draw_pos
; p
< draw_end
; p
+= 4)
460 y
= scp
->yoff
* scp
->font_size
;
461 x
= scp
->xpixel
/ 8 - scp
->xoff
- scp
->xsize
;
463 for (i
= 0; i
< scp
->ysize
* scp
->font_size
; ++i
) {
465 draw_pos
= scp
->sc
->adp
->va_window
+
466 line_width
* (y
+ i
);
467 draw_end
= draw_pos
+ scp
->xoff
* 8 * pixel_size
;
469 for (p
= draw_pos
; p
< draw_end
; p
+= 4)
474 draw_pos
= scp
->sc
->adp
->va_window
+
475 line_width
* (y
+ i
) +
476 scp
->xoff
* 8 * pixel_size
+
477 scp
->xsize
* 8 * pixel_size
;
478 draw_end
= draw_pos
+ x
* 8 * pixel_size
;
480 for (p
= draw_pos
; p
< draw_end
; p
+= 4)
487 vga_pxlborder_planar(scr_stat
*scp
, int color
)
495 (*vidsw
[scp
->sc
->adapter
]->set_border
)(scp
->sc
->adp
, color
);
497 outw(GDCIDX
, 0x0005); /* read mode 0, write mode 0 */
498 outw(GDCIDX
, 0x0003); /* data rotate/function select */
499 outw(GDCIDX
, 0x0f01); /* set/reset enable */
500 outw(GDCIDX
, 0xff08); /* bit mask */
501 outw(GDCIDX
, (color
<< 8) | 0x00); /* set/reset */
502 line_width
= scp
->sc
->adp
->va_line_width
;
503 p
= scp
->sc
->adp
->va_window
;
505 bzero_io((void *)p
, line_width
*scp
->yoff
*scp
->font_size
);
506 y
= (scp
->yoff
+ scp
->ysize
)*scp
->font_size
;
508 bzero_io((void *)(p
+ line_width
*y
), line_width
*(scp
->ypixel
- y
));
509 y
= scp
->yoff
*scp
->font_size
;
510 x
= scp
->xpixel
/8 - scp
->xoff
- scp
->xsize
;
511 for (i
= 0; i
< scp
->ysize
*scp
->font_size
; ++i
) {
513 bzero_io((void *)(p
+ line_width
*(y
+ i
)), scp
->xoff
);
515 bzero_io((void *)(p
+ line_width
*(y
+ i
)
516 + scp
->xoff
+ scp
->xsize
), x
);
518 outw(GDCIDX
, 0x0000); /* set/reset */
519 outw(GDCIDX
, 0x0001); /* set/reset enable */
523 vga_vgadraw_direct(scr_stat
*scp
, int from
, int count
, int flip
)
525 int line_width
, pixel_size
;
526 int a
, i
, j
, k
, l
, pos
;
527 uint32_t fg
, bg
, u32
;
528 unsigned char *char_data
;
529 vm_offset_t draw_pos
, p
;
531 line_width
= scp
->sc
->adp
->va_line_width
;
532 pixel_size
= scp
->sc
->adp
->va_info
.vi_pixel_size
;
534 draw_pos
= VIDEO_MEMORY_POS(scp
, from
, 8 * pixel_size
);
536 if (from
+ count
> scp
->xsize
* scp
->ysize
)
537 count
= scp
->xsize
* scp
->ysize
- from
;
539 for (i
= from
; count
-- > 0; ++i
) {
540 a
= sc_vtb_geta(&scp
->vtb
, i
);
543 fg
= scp
->ega_palette
[(((a
& 0x7000) >> 4) |
545 bg
= scp
->ega_palette
[(((a
& 0x8000) >> 4) |
548 fg
= scp
->ega_palette
[(a
& 0x0f00) >> 8];
549 bg
= scp
->ega_palette
[(a
& 0xf000) >> 12];
553 char_data
= &(scp
->font
[sc_vtb_getc(&scp
->vtb
, i
) *
556 for (j
= 0; j
< scp
->font_size
; ++j
, ++char_data
) {
559 for (k
= 0; k
< 2 * pixel_size
; ++k
) {
562 for (l
= 0; l
< 4 / pixel_size
; ++l
) {
563 u32
+= (*char_data
& (1 << pos
--) ?
564 fg
: bg
) << (l
* 8 * pixel_size
);
571 p
+= line_width
- 8 * pixel_size
;
574 draw_pos
+= 8 * pixel_size
;
576 if ((i
% scp
->xsize
) == scp
->xsize
- 1)
577 draw_pos
+= scp
->xoff
* 16 * pixel_size
+
578 (scp
->font_size
- 1) * line_width
;
583 vga_vgadraw_planar(scr_stat
*scp
, int from
, int count
, int flip
)
595 d
= VIDEO_MEMORY_POS(scp
, from
, 1);
597 line_width
= scp
->sc
->adp
->va_line_width
;
599 outw(GDCIDX
, 0x0305); /* read mode 0, write mode 3 */
600 outw(GDCIDX
, 0x0003); /* data rotate/function select */
601 outw(GDCIDX
, 0x0f01); /* set/reset enable */
602 outw(GDCIDX
, 0xff08); /* bit mask */
604 if (from
+ count
> scp
->xsize
*scp
->ysize
)
605 count
= scp
->xsize
*scp
->ysize
- from
;
606 for (i
= from
; count
-- > 0; ++i
) {
607 a
= sc_vtb_geta(&scp
->vtb
, i
);
609 col1
= ((a
& 0x7000) >> 4) | (a
& 0x0800);
610 col2
= ((a
& 0x8000) >> 4) | (a
& 0x0700);
613 col2
= (a
& 0xf000) >> 4;
615 /* set background color in EGA/VGA latch */
618 outw(GDCIDX
, 0x0005); /* read mode 0, write mode 0 */
619 outw(GDCIDX
, bg
| 0x00); /* set/reset */
621 c
= readb(d
); /* set bg color in the latch */
622 outw(GDCIDX
, 0x0305); /* read mode 0, write mode 3 */
624 /* foreground color */
625 outw(GDCIDX
, col1
| 0x00); /* set/reset */
627 f
= &(scp
->font
[sc_vtb_getc(&scp
->vtb
, i
)*scp
->font_size
]);
628 for (j
= 0; j
< scp
->font_size
; ++j
, ++f
) {
633 if ((i
% scp
->xsize
) == scp
->xsize
- 1)
635 + (scp
->font_size
- 1)*line_width
;
637 outw(GDCIDX
, 0x0005); /* read mode 0, write mode 0 */
638 outw(GDCIDX
, 0x0000); /* set/reset */
639 outw(GDCIDX
, 0x0001); /* set/reset enable */
643 vga_pxlcursor_shape(scr_stat
*scp
, int base
, int height
, int blink
)
645 if (base
< 0 || base
>= scp
->font_size
)
647 /* the caller may set height <= 0 in order to disable the cursor */
649 scp
->cursor_base
= base
;
650 scp
->cursor_height
= height
;
655 draw_pxlcursor_direct(scr_stat
*scp
, int at
, int on
, int flip
)
657 int line_width
, pixel_size
, height
;
659 uint32_t fg
, bg
, u32
;
660 unsigned char *char_data
;
661 vm_offset_t draw_pos
;
663 line_width
= scp
->sc
->adp
->va_line_width
;
664 pixel_size
= scp
->sc
->adp
->va_info
.vi_pixel_size
;
666 draw_pos
= VIDEO_MEMORY_POS(scp
, at
, 8 * pixel_size
) +
667 (scp
->font_size
- scp
->cursor_base
- 1) * line_width
;
669 a
= sc_vtb_geta(&scp
->vtb
, at
);
672 fg
= scp
->ega_palette
[((on
) ? (a
& 0x0f00) :
673 ((a
& 0xf000) >> 4)) >> 8];
674 bg
= scp
->ega_palette
[((on
) ? ((a
& 0xf000) >> 4) :
677 fg
= scp
->ega_palette
[((on
) ? ((a
& 0xf000) >> 4) :
679 bg
= scp
->ega_palette
[((on
) ? (a
& 0x0f00) :
680 ((a
& 0xf000) >> 4)) >> 8];
683 char_data
= &(scp
->font
[sc_vtb_getc(&scp
->vtb
, at
) * scp
->font_size
+
684 scp
->font_size
- scp
->cursor_base
- 1]);
686 height
= imin(scp
->cursor_height
, scp
->font_size
);
688 for (i
= 0; i
< height
; ++i
, --char_data
) {
691 for (j
= 0; j
< 2 * pixel_size
; ++j
) {
694 for (k
= 0; k
< 4 / pixel_size
; ++k
) {
695 u32
+= (*char_data
& (1 << pos
--) ?
696 fg
: bg
) << (k
* 8 * pixel_size
);
699 writel(draw_pos
, u32
);
703 draw_pos
-= line_width
+ 8 * pixel_size
;
708 draw_pxlcursor_planar(scr_stat
*scp
, int at
, int on
, int flip
)
719 line_width
= scp
->sc
->adp
->va_line_width
;
721 d
= VIDEO_MEMORY_POS(scp
, at
, 1) +
722 (scp
->font_size
- scp
->cursor_base
- 1) * line_width
;
724 outw(GDCIDX
, 0x0005); /* read mode 0, write mode 0 */
725 outw(GDCIDX
, 0x0003); /* data rotate/function select */
726 outw(GDCIDX
, 0x0f01); /* set/reset enable */
727 /* set background color in EGA/VGA latch */
728 a
= sc_vtb_geta(&scp
->vtb
, at
);
730 col
= (on
) ? ((a
& 0xf000) >> 4) : (a
& 0x0f00);
732 col
= (on
) ? (a
& 0x0f00) : ((a
& 0xf000) >> 4);
733 outw(GDCIDX
, col
| 0x00); /* set/reset */
734 outw(GDCIDX
, 0xff08); /* bit mask */
736 c
= readb(d
); /* set bg color in the latch */
737 /* foreground color */
739 col
= (on
) ? (a
& 0x0f00) : ((a
& 0xf000) >> 4);
741 col
= (on
) ? ((a
& 0xf000) >> 4) : (a
& 0x0f00);
742 outw(GDCIDX
, col
| 0x00); /* set/reset */
743 f
= &(scp
->font
[sc_vtb_getc(&scp
->vtb
, at
)*scp
->font_size
744 + scp
->font_size
- scp
->cursor_base
- 1]);
745 height
= imin(scp
->cursor_height
, scp
->font_size
);
746 for (i
= 0; i
< height
; ++i
, --f
) {
747 outw(GDCIDX
, (*f
<< 8) | 0x08); /* bit mask */
751 outw(GDCIDX
, 0x0000); /* set/reset */
752 outw(GDCIDX
, 0x0001); /* set/reset enable */
753 outw(GDCIDX
, 0xff08); /* bit mask */
756 static int pxlblinkrate
= 0;
759 vga_pxlcursor_direct(scr_stat
*scp
, int at
, int blink
, int on
, int flip
)
761 if (scp
->cursor_height
<= 0) /* the text cursor is disabled */
766 scp
->status
|= VR_CURSOR_ON
;
767 draw_pxlcursor_direct(scp
, at
, on
, flip
);
768 } else if (++pxlblinkrate
& 4) {
770 scp
->status
^= VR_CURSOR_ON
;
771 draw_pxlcursor_direct(scp
, at
,
772 scp
->status
& VR_CURSOR_ON
,
776 if (scp
->status
& VR_CURSOR_ON
)
777 draw_pxlcursor_direct(scp
, at
, on
, flip
);
778 scp
->status
&= ~VR_CURSOR_ON
;
781 scp
->status
|= VR_CURSOR_BLINK
;
783 scp
->status
&= ~VR_CURSOR_BLINK
;
787 vga_pxlcursor_planar(scr_stat
*scp
, int at
, int blink
, int on
, int flip
)
789 if (scp
->cursor_height
<= 0) /* the text cursor is disabled */
794 scp
->status
|= VR_CURSOR_ON
;
795 draw_pxlcursor_planar(scp
, at
, on
, flip
);
796 } else if (++pxlblinkrate
& 4) {
798 scp
->status
^= VR_CURSOR_ON
;
799 draw_pxlcursor_planar(scp
, at
,
800 scp
->status
& VR_CURSOR_ON
,
804 if (scp
->status
& VR_CURSOR_ON
)
805 draw_pxlcursor_planar(scp
, at
, on
, flip
);
806 scp
->status
&= ~VR_CURSOR_ON
;
809 scp
->status
|= VR_CURSOR_BLINK
;
811 scp
->status
&= ~VR_CURSOR_BLINK
;
815 vga_pxlblink_direct(scr_stat
*scp
, int at
, int flip
)
817 if (!(scp
->status
& VR_CURSOR_BLINK
))
819 if (!(++pxlblinkrate
& 4))
822 scp
->status
^= VR_CURSOR_ON
;
823 draw_pxlcursor_direct(scp
, at
, scp
->status
& VR_CURSOR_ON
, flip
);
827 vga_pxlblink_planar(scr_stat
*scp
, int at
, int flip
)
829 if (!(scp
->status
& VR_CURSOR_BLINK
))
831 if (!(++pxlblinkrate
& 4))
834 scp
->status
^= VR_CURSOR_ON
;
835 draw_pxlcursor_planar(scp
, at
, scp
->status
& VR_CURSOR_ON
, flip
);
838 #ifndef SC_NO_CUTPASTE
841 draw_pxlmouse_direct(scr_stat
*scp
, int x
, int y
)
843 int line_width
, pixel_size
;
846 vm_offset_t draw_pos
;
848 line_width
= scp
->sc
->adp
->va_line_width
;
849 pixel_size
= scp
->sc
->adp
->va_info
.vi_pixel_size
;
851 xend
= imin(x
+ 8, 8 * (scp
->xoff
+ scp
->xsize
));
852 yend
= imin(y
+ 16, scp
->font_size
* (scp
->yoff
+ scp
->ysize
));
854 draw_pos
= scp
->sc
->adp
->va_window
+ y
* line_width
+ x
* pixel_size
;
856 for (i
= 0; i
< (yend
- y
); i
++) {
857 for (j
= (xend
- x
- 1); j
>= 0; j
--) {
858 switch (scp
->sc
->adp
->va_info
.vi_depth
) {
860 if (mouse_or_mask
[i
] & 1 << (15 - j
))
861 writel(draw_pos
+ 4 * j
,
862 scp
->ega_palette
[15]);
863 else if (mouse_and_mask
[i
] & 1 << (15 - j
))
864 writel(draw_pos
+ 4 * j
,
865 scp
->ega_palette
[0]);
870 if (mouse_or_mask
[i
] & 1 << (15 - j
))
871 writew(draw_pos
+ 2 * j
,
872 scp
->ega_palette
[15]);
873 else if (mouse_and_mask
[i
] & 1 << (15 - j
))
874 writew(draw_pos
+ 2 * j
,
875 scp
->ega_palette
[0]);
880 draw_pos
+= line_width
;
885 draw_pxlmouse_planar(scr_stat
*scp
, int x
, int y
)
894 line_width
= scp
->sc
->adp
->va_line_width
;
895 xoff
= (x
- scp
->xoff
*8)%8;
896 yoff
= y
- (y
/line_width
)*line_width
;
897 ymax
= imin(y
+ 16, scp
->font_size
* (scp
->yoff
+ scp
->ysize
));
899 outw(GDCIDX
, 0x0805); /* read mode 1, write mode 0 */
900 outw(GDCIDX
, 0x0001); /* set/reset enable */
901 outw(GDCIDX
, 0x0002); /* color compare */
902 outw(GDCIDX
, 0x0007); /* color don't care */
903 outw(GDCIDX
, 0xff08); /* bit mask */
904 outw(GDCIDX
, 0x0803); /* data rotate/function select (and) */
905 p
= scp
->sc
->adp
->va_window
+ line_width
*y
+ x
/8;
906 if (x
< 8 * (scp
->xoff
+ scp
->xsize
) - 8) {
907 for (i
= y
, j
= 0; i
< ymax
; ++i
, ++j
) {
908 m
= ~(mouse_and_mask
[j
] >> xoff
);
909 *(u_char
*)p
&= m
>> 8;
910 *(u_char
*)(p
+ 1) &= m
;
915 for (i
= y
, j
= 0; i
< ymax
; ++i
, ++j
) {
916 m
= ~(mouse_and_mask
[j
] >> xoff
);
921 outw(GDCIDX
, 0x1003); /* data rotate/function select (or) */
922 p
= scp
->sc
->adp
->va_window
+ line_width
*y
+ x
/8;
923 if (x
< 8 * (scp
->xoff
+ scp
->xsize
) - 8) {
924 for (i
= y
, j
= 0; i
< ymax
; ++i
, ++j
) {
925 m
= mouse_or_mask
[j
] >> xoff
;
926 *(u_char
*)p
&= m
>> 8;
927 *(u_char
*)(p
+ 1) &= m
;
931 for (i
= y
, j
= 0; i
< ymax
; ++i
, ++j
) {
932 m
= mouse_or_mask
[j
] >> xoff
;
937 outw(GDCIDX
, 0x0005); /* read mode 0, write mode 0 */
938 outw(GDCIDX
, 0x0003); /* data rotate/function select */
942 remove_pxlmouse(scr_stat
*scp
, int x
, int y
)
948 /* erase the mouse cursor image */
949 col
= x
/8 - scp
->xoff
;
950 row
= y
/scp
->font_size
- scp
->yoff
;
951 pos
= row
*scp
->xsize
+ col
;
952 i
= (col
< scp
->xsize
- 1) ? 2 : 1;
953 (*scp
->rndr
->draw
)(scp
, pos
, i
, FALSE
);
954 if (row
< scp
->ysize
- 1)
955 (*scp
->rndr
->draw
)(scp
, pos
+ scp
->xsize
, i
, FALSE
);
959 vga_pxlmouse_direct(scr_stat
*scp
, int x
, int y
, int on
)
962 draw_pxlmouse_direct(scp
, x
, y
);
964 remove_pxlmouse(scp
, x
, y
);
968 vga_pxlmouse_planar(scr_stat
*scp
, int x
, int y
, int on
)
971 draw_pxlmouse_planar(scp
, x
, y
);
973 remove_pxlmouse(scp
, x
, y
);
976 #endif /* SC_NO_CUTPASTE */
977 #endif /* SC_PIXEL_MODE */
979 #ifndef SC_NO_MODE_CHANGE
981 /* graphics mode renderer */
984 vga_grborder(scr_stat
*scp
, int color
)
986 (*vidsw
[scp
->sc
->adapter
]->set_border
)(scp
->sc
->adp
, color
);