Deleted Added
sdiff udiff text old ( 55849 ) new ( 56043 )
full compact
1/*-
2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 * $FreeBSD: head/sys/dev/syscons/scgfbrndr.c 55849 2000-01-12 12:30:33Z yokota $
27 */
28
29#include "sc.h"
30#include "vga.h"
31#include "opt_syscons.h"
32#include "opt_vga.h"
33
34#if NSC > 0 && NVGA > 0
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39
40#include <machine/console.h>
41#include <machine/md_var.h>
42
43#include <dev/fb/fbreg.h>
44#include <dev/fb/vgareg.h>
45#include <dev/syscons/syscons.h>
46
47#include <isa/isareg.h>
48
49#ifndef SC_RENDER_DEBUG
50#define SC_RENDER_DEBUG 0
51#endif
52
53static vr_clear_t vga_txtclear;
54static vr_draw_border_t vga_txtborder;
55static vr_draw_t vga_txtdraw;
56static vr_set_cursor_t vga_txtcursor_shape;
57static vr_draw_cursor_t vga_txtcursor;
58static vr_blink_cursor_t vga_txtblink;
59#ifndef SC_NO_CUTPASTE
60static vr_draw_mouse_t vga_txtmouse;
61#else
62#define vga_txtmouse (vr_draw_mouse_t *)vga_nop
63#endif
64
65#ifdef SC_PIXEL_MODE
66static vr_clear_t vga_pxlclear;
67static vr_draw_border_t vga_pxlborder;
68static vr_draw_t vga_egadraw;
69static vr_draw_t vga_vgadraw;
70static vr_set_cursor_t vga_pxlcursor_shape;
71static vr_draw_cursor_t vga_pxlcursor;
72static vr_blink_cursor_t vga_pxlblink;
73#ifndef SC_NO_CUTPASTE
74static vr_draw_mouse_t vga_pxlmouse;
75#else
76#define vga_pxlmouse (vr_draw_mouse_t *)vga_nop
77#endif
78#endif /* SC_PIXEL_MODE */
79
80#ifndef SC_NO_MODE_CHANGE
81static vr_draw_border_t vga_grborder;
82#endif
83
84static void vga_nop(scr_stat *scp, ...);
85
86static sc_rndr_sw_t txtrndrsw = {
87 vga_txtclear,
88 vga_txtborder,
89 vga_txtdraw,
90 vga_txtcursor_shape,
91 vga_txtcursor,
92 vga_txtblink,
93 (vr_set_mouse_t *)vga_nop,
94 vga_txtmouse,
95};
96RENDERER(mda, 0, txtrndrsw);
97RENDERER(cga, 0, txtrndrsw);
98RENDERER(ega, 0, txtrndrsw);
99RENDERER(vga, 0, txtrndrsw);
100
101#ifdef SC_PIXEL_MODE
102static sc_rndr_sw_t egarndrsw = {
103 vga_pxlclear,
104 vga_pxlborder,
105 vga_egadraw,
106 vga_pxlcursor_shape,
107 vga_pxlcursor,
108 vga_pxlblink,
109 (vr_set_mouse_t *)vga_nop,
110 vga_pxlmouse,
111};
112RENDERER(ega, PIXEL_MODE, egarndrsw);
113
114static sc_rndr_sw_t vgarndrsw = {
115 vga_pxlclear,
116 vga_pxlborder,
117 vga_vgadraw,
118 vga_pxlcursor_shape,
119 vga_pxlcursor,
120 vga_pxlblink,
121 (vr_set_mouse_t *)vga_nop,
122 vga_pxlmouse,
123};
124RENDERER(vga, PIXEL_MODE, vgarndrsw);
125#endif /* SC_PIXEL_MODE */
126
127#ifndef SC_NO_MODE_CHANGE
128static sc_rndr_sw_t grrndrsw = {
129 (vr_clear_t *)vga_nop,
130 vga_grborder,
131 (vr_draw_t *)vga_nop,
132 (vr_set_cursor_t *)vga_nop,
133 (vr_draw_cursor_t *)vga_nop,
134 (vr_blink_cursor_t *)vga_nop,
135 (vr_set_mouse_t *)vga_nop,
136 (vr_draw_mouse_t *)vga_nop,
137};
138RENDERER(cga, GRAPHICS_MODE, grrndrsw);
139RENDERER(ega, GRAPHICS_MODE, grrndrsw);
140RENDERER(vga, GRAPHICS_MODE, grrndrsw);
141#endif /* SC_NO_MODE_CHANGE */
142
143#ifndef SC_NO_CUTPASTE
144static u_short mouse_and_mask[16] = {
145 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
146 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
147};
148static u_short mouse_or_mask[16] = {
149 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
150 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
151};
152#endif
153
154static void
155vga_nop(scr_stat *scp, ...)
156{
157}
158
159/* text mode renderer */
160
161static void
162vga_txtclear(scr_stat *scp, int c, int attr)
163{
164 sc_vtb_clear(&scp->scr, c, attr);
165}
166
167static void
168vga_txtborder(scr_stat *scp, int color)
169{
170 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
171}
172
173static void
174vga_txtdraw(scr_stat *scp, int from, int count, int flip)
175{
176 vm_offset_t p;
177 int c;
178 int a;
179
180 if (from + count > scp->xsize*scp->ysize)
181 count = scp->xsize*scp->ysize - from;
182
183 if (flip) {
184 for (p = sc_vtb_pointer(&scp->scr, 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);
190 }
191 } else {
192 sc_vtb_copy(&scp->vtb, from, &scp->scr, from, count);
193 }
194}
195
196static void
197vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
198{
199 if (base < 0 || base >= scp->font_size)
200 return;
201 /* the caller may set height <= 0 in order to disable the cursor */
202#if 0
203 scp->cursor_base = base;
204 scp->cursor_height = height;
205#endif
206 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
207 base, height,
208 scp->font_size, blink);
209}
210
211static void
212vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
213{
214 video_adapter_t *adp;
215 int cursor_attr;
216
217 if (scp->cursor_height <= 0) /* the text cursor is disabled */
218 return;
219
220 adp = scp->sc->adp;
221 if (blink) {
222 scp->status |= VR_CURSOR_BLINK;
223 if (on) {
224 scp->status |= VR_CURSOR_ON;
225 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
226 at%scp->xsize,
227 at/scp->xsize);
228 } else {
229 if (scp->status & VR_CURSOR_ON)
230 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
231 -1, -1);
232 scp->status &= ~VR_CURSOR_ON;
233 }
234 } else {
235 scp->status &= ~VR_CURSOR_BLINK;
236 if (on) {
237 scp->status |= VR_CURSOR_ON;
238 cursor_attr = sc_vtb_geta(&scp->vtb, at);
239 scp->cursor_saveunder_char = sc_vtb_getc(&scp->scr, at);
240 scp->cursor_saveunder_attr = cursor_attr;
241 if ((cursor_attr & 0x7000) == 0x7000) {
242 cursor_attr &= 0x8f00;
243 if ((cursor_attr & 0x0700) == 0)
244 cursor_attr |= 0x0700;
245 } else {
246 cursor_attr |= 0x7000;
247 if ((cursor_attr & 0x0700) == 0x0700)
248 cursor_attr &= 0xf000;
249 }
250 if (flip)
251 cursor_attr = (cursor_attr & 0x8800)
252 | ((cursor_attr & 0x7000) >> 4)
253 | ((cursor_attr & 0x0700) << 4);
254 sc_vtb_putc(&scp->scr, at,
255 sc_vtb_getc(&scp->scr, at),
256 cursor_attr);
257 } else {
258 cursor_attr = scp->cursor_saveunder_attr;
259 if (flip)
260 cursor_attr = (cursor_attr & 0x8800)
261 | ((cursor_attr & 0x7000) >> 4)
262 | ((cursor_attr & 0x0700) << 4);
263 if (scp->status & VR_CURSOR_ON)
264 sc_vtb_putc(&scp->scr, at,
265 scp->cursor_saveunder_char,
266 cursor_attr);
267 scp->status &= ~VR_CURSOR_ON;
268 }
269 }
270}
271
272static void
273vga_txtblink(scr_stat *scp, int at, int flip)
274{
275}
276
277#ifndef SC_NO_CUTPASTE
278
279static void
280draw_txtmouse(scr_stat *scp, int x, int y)
281{
282#ifndef SC_ALT_MOUSE_IMAGE
283 u_char font_buf[128];
284 u_short cursor[32];
285 u_char c;
286 int pos;
287 int xoffset, yoffset;
288 int crtc_addr;
289 int i;
290
291 /* prepare mousepointer char's bitmaps */
292 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
293 bcopy(scp->font + sc_vtb_getc(&scp->vtb, pos)*scp->font_size,
294 &font_buf[0], scp->font_size);
295 bcopy(scp->font + sc_vtb_getc(&scp->vtb, pos + 1)*scp->font_size,
296 &font_buf[32], scp->font_size);
297 bcopy(scp->font
298 + sc_vtb_getc(&scp->vtb, pos + scp->xsize)*scp->font_size,
299 &font_buf[64], scp->font_size);
300 bcopy(scp->font
301 + sc_vtb_getc(&scp->vtb, pos + scp->xsize + 1)*scp->font_size,
302 &font_buf[96], scp->font_size);
303 for (i = 0; i < scp->font_size; ++i) {
304 cursor[i] = font_buf[i]<<8 | font_buf[i+32];
305 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
306 }
307
308 /* now and-or in the mousepointer image */
309 xoffset = x%8;
310 yoffset = y%scp->font_size;
311 for (i = 0; i < 16; ++i) {
312 cursor[i + yoffset] =
313 (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
314 | (mouse_or_mask[i] >> xoffset);
315 }
316 for (i = 0; i < scp->font_size; ++i) {
317 font_buf[i] = (cursor[i] & 0xff00) >> 8;
318 font_buf[i + 32] = cursor[i] & 0xff;
319 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
320 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
321 }
322
323#if 1
324 /* wait for vertical retrace to avoid jitter on some videocards */
325 crtc_addr = scp->sc->adp->va_crtc_addr;
326 while (!(inb(crtc_addr + 6) & 0x08)) /* idle */ ;
327#endif
328 c = scp->sc->mouse_char;
329 (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
330 c, 4);
331
332 sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
333 /* FIXME: may be out of range! */
334 sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
335 sc_vtb_geta(&scp->scr, pos + scp->xsize));
336 if (x < (scp->xsize - 1)*8) {
337 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
338 sc_vtb_geta(&scp->scr, pos + 1));
339 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
340 sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
341 }
342#else /* SC_ALT_MOUSE_IMAGE */
343 /* Red, magenta and brown are mapped to green to to keep it readable */
344 static const int col_conv[16] = {
345 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
346 };
347 int pos;
348 int color;
349 int a;
350
351 pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
352 a = sc_vtb_geta(&scp->scr, pos);
353 if (scp->sc->adp->va_flags & V_ADP_COLOR)
354 color = (col_conv[(a & 0xf000) >> 12] << 12)
355 | ((a & 0x0f00) | 0x0800);
356 else
357 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
358 sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
359#endif /* SC_ALT_MOUSE_IMAGE */
360}
361
362static void
363remove_txtmouse(scr_stat *scp, int x, int y)
364{
365}
366
367static void
368vga_txtmouse(scr_stat *scp, int x, int y, int on)
369{
370 if (on)
371 draw_txtmouse(scp, x, y);
372 else
373 remove_txtmouse(scp, x, y);
374}
375
376#endif /* SC_NO_CUTPASTE */
377
378#ifdef SC_PIXEL_MODE
379
380/* pixel (raster text) mode renderer */
381
382static void
383vga_pxlclear(scr_stat *scp, int c, int attr)
384{
385 vm_offset_t p;
386 int line_width;
387 int lines;
388 int i;
389
390 /* XXX: we are just filling the screen with the background color... */
391 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
392 outw(GDCIDX, 0x0003); /* data rotate/function select */
393 outw(GDCIDX, 0x0f01); /* set/reset enable */
394 outw(GDCIDX, 0xff08); /* bit mask */
395 outw(GDCIDX, ((attr & 0xf000) >> 4) | 0x00); /* set/reset */
396 line_width = scp->sc->adp->va_line_width;
397 lines = scp->ysize*scp->font_size;
398 p = scp->sc->adp->va_window + line_width*scp->yoff*scp->font_size
399 + scp->xoff;
400 for (i = 0; i < lines; ++i) {
401 bzero_io((void *)p, scp->xsize);
402 p += line_width;
403 }
404 outw(GDCIDX, 0x0000); /* set/reset */
405 outw(GDCIDX, 0x0001); /* set/reset enable */
406}
407
408static void
409vga_pxlborder(scr_stat *scp, int color)
410{
411 vm_offset_t p;
412 int line_width;
413 int i;
414
415 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
416
417 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
418 outw(GDCIDX, 0x0003); /* data rotate/function select */
419 outw(GDCIDX, 0x0f01); /* set/reset enable */
420 outw(GDCIDX, 0xff08); /* bit mask */
421 outw(GDCIDX, (color << 8) | 0x00); /* set/reset */
422 line_width = scp->sc->adp->va_line_width;
423 p = scp->sc->adp->va_window;
424 if (scp->yoff > 0) {
425 bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
426 bzero_io((void *)(p + line_width*(scp->yoff + scp->ysize)
427 *scp->font_size),
428 line_width*(scp->ypixel
429 - (scp->yoff + scp->ysize)*scp->font_size));
430 }
431 if (scp->xoff > 0) {
432 for (i = 0; i < scp->ysize*scp->font_size; ++i) {
433 bzero_io((void *)(p + line_width
434 *(scp->yoff*scp->font_size + i)),
435 scp->xoff);
436 bzero_io((void *)(p + line_width
437 *(scp->yoff*scp->font_size + i)
438 + scp->xoff + scp->xsize),
439 scp->xpixel/8 - scp->xoff - scp->xsize);
440 }
441 }
442 outw(GDCIDX, 0x0000); /* set/reset */
443 outw(GDCIDX, 0x0001); /* set/reset enable */
444}
445
446static void
447vga_egadraw(scr_stat *scp, int from, int count, int flip)
448{
449 vm_offset_t d;
450 vm_offset_t e;
451 u_char *f;
452 u_short bg;
453 u_short col1, col2;
454 int line_width;
455 int i, j;
456 int a;
457 u_char c;
458
459 line_width = scp->sc->adp->va_line_width;
460 d = scp->sc->adp->va_window
461 + scp->xoff
462 + scp->yoff*scp->font_size*line_width
463 + (from%scp->xsize)
464 + scp->font_size*line_width*(from/scp->xsize);
465
466 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
467 outw(GDCIDX, 0x0003); /* data rotate/function select */
468 outw(GDCIDX, 0x0f01); /* set/reset enable */
469 bg = -1;
470 if (from + count > scp->xsize*scp->ysize)
471 count = scp->xsize*scp->ysize - from;
472 for (i = from; count-- > 0; ++i) {
473 a = sc_vtb_geta(&scp->vtb, i);
474 if (flip) {
475 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
476 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
477 } else {
478 col1 = (a & 0x0f00);
479 col2 = (a & 0xf000) >> 4;
480 }
481 /* set background color in EGA/VGA latch */
482 if (bg != col2) {
483 bg = col2;
484 outw(GDCIDX, bg | 0x00); /* set/reset */
485 outw(GDCIDX, 0xff08); /* bit mask */
486 writeb(d, 0);
487 c = readb(d); /* set bg color in the latch */
488 }
489 /* foreground color */
490 outw(GDCIDX, col1 | 0x00); /* set/reset */
491 e = d;
492 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
493 for (j = 0; j < scp->font_size; ++j, ++f) {
494 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
495 writeb(e, 0);
496 e += line_width;
497 }
498 ++d;
499 if ((i % scp->xsize) == scp->xsize - 1)
500 d += scp->xoff*2
501 + (scp->font_size - 1)*line_width;
502 }
503 outw(GDCIDX, 0x0000); /* set/reset */
504 outw(GDCIDX, 0x0001); /* set/reset enable */
505 outw(GDCIDX, 0xff08); /* bit mask */
506}
507
508static void
509vga_vgadraw(scr_stat *scp, int from, int count, int flip)
510{
511 vm_offset_t d;
512 vm_offset_t e;
513 u_char *f;
514 u_short bg;
515 u_short col1, col2;
516 int line_width;
517 int i, j;
518 int a;
519 u_char c;
520
521 line_width = scp->sc->adp->va_line_width;
522 d = scp->sc->adp->va_window
523 + scp->xoff
524 + scp->yoff*scp->font_size*line_width
525 + (from%scp->xsize)
526 + scp->font_size*line_width*(from/scp->xsize);
527
528 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
529 outw(GDCIDX, 0x0003); /* data rotate/function select */
530 outw(GDCIDX, 0x0f01); /* set/reset enable */
531 outw(GDCIDX, 0xff08); /* bit mask */
532 bg = -1;
533 if (from + count > scp->xsize*scp->ysize)
534 count = scp->xsize*scp->ysize - from;
535 for (i = from; count-- > 0; ++i) {
536 a = sc_vtb_geta(&scp->vtb, i);
537 if (flip) {
538 col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
539 col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
540 } else {
541 col1 = (a & 0x0f00);
542 col2 = (a & 0xf000) >> 4;
543 }
544 /* set background color in EGA/VGA latch */
545 if (bg != col2) {
546 bg = col2;
547 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
548 outw(GDCIDX, bg | 0x00); /* set/reset */
549 writeb(d, 0);
550 c = readb(d); /* set bg color in the latch */
551 outw(GDCIDX, 0x0305); /* read mode 0, write mode 3 */
552 }
553 /* foreground color */
554 outw(GDCIDX, col1 | 0x00); /* set/reset */
555 e = d;
556 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
557 for (j = 0; j < scp->font_size; ++j, ++f) {
558 writeb(e, *f);
559 e += line_width;
560 }
561 ++d;
562 if ((i % scp->xsize) == scp->xsize - 1)
563 d += scp->xoff*2
564 + (scp->font_size - 1)*line_width;
565 }
566 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
567 outw(GDCIDX, 0x0000); /* set/reset */
568 outw(GDCIDX, 0x0001); /* set/reset enable */
569}
570
571static void
572vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
573{
574 if (base < 0 || base >= scp->font_size)
575 return;
576 /* the caller may set height <= 0 in order to disable the cursor */
577#if 0
578 scp->cursor_base = base;
579 scp->cursor_height = height;
580#endif
581}
582
583static void
584draw_pxlcursor(scr_stat *scp, int at, int on, int flip)
585{
586 vm_offset_t d;
587 u_char *f;
588 int line_width;
589 int height;
590 int col;
591 int a;
592 int i;
593 u_char c;
594
595 line_width = scp->sc->adp->va_line_width;
596 d = scp->sc->adp->va_window
597 + scp->xoff
598 + scp->yoff*scp->font_size*line_width
599 + (at%scp->xsize)
600 + scp->font_size*line_width*(at/scp->xsize)
601 + (scp->font_size - scp->cursor_base - 1)*line_width;
602
603 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
604 outw(GDCIDX, 0x0003); /* data rotate/function select */
605 outw(GDCIDX, 0x0f01); /* set/reset enable */
606 /* set background color in EGA/VGA latch */
607 a = sc_vtb_geta(&scp->vtb, at);
608 if (flip)
609 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
610 else
611 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
612 outw(GDCIDX, col | 0x00); /* set/reset */
613 outw(GDCIDX, 0xff08); /* bit mask */
614 writeb(d, 0);
615 c = readb(d); /* set bg color in the latch */
616 /* foreground color */
617 if (flip)
618 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
619 else
620 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
621 outw(GDCIDX, col | 0x00); /* set/reset */
622 f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
623 + scp->font_size - scp->cursor_base - 1]);
624 height = imin(scp->cursor_height, scp->font_size);
625 for (i = 0; i < height; ++i, --f) {
626 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
627 writeb(d, 0);
628 d -= line_width;
629 }
630 outw(GDCIDX, 0x0000); /* set/reset */
631 outw(GDCIDX, 0x0001); /* set/reset enable */
632 outw(GDCIDX, 0xff08); /* bit mask */
633}
634
635static void
636vga_pxlcursor(scr_stat *scp, int at, int blink, int on, int flip)
637{
638 if (scp->cursor_height <= 0) /* the text cursor is disabled */
639 return;
640
641 if (on) {
642 scp->status |= VR_CURSOR_ON;
643 draw_pxlcursor(scp, at, on, flip);
644 } else {
645 if (scp->status & VR_CURSOR_ON)
646 draw_pxlcursor(scp, at, on, flip);
647 scp->status &= ~VR_CURSOR_ON;
648 }
649 if (blink)
650 scp->status |= VR_CURSOR_BLINK;
651 else
652 scp->status &= ~VR_CURSOR_BLINK;
653}
654
655static void
656vga_pxlblink(scr_stat *scp, int at, int flip)
657{
658 static int blinkrate = 0;
659
660 if (!(scp->status & VR_CURSOR_BLINK))
661 return;
662 if (!(++blinkrate & 4))
663 return;
664 blinkrate = 0;
665 scp->status ^= VR_CURSOR_ON;
666 draw_pxlcursor(scp, at, scp->status & VR_CURSOR_ON, flip);
667}
668
669#ifndef SC_NO_CUTPASTE
670
671static void
672draw_pxlmouse(scr_stat *scp, int x, int y)
673{
674 vm_offset_t p;
675 int line_width;
676 int xoff, yoff;
677 int ymax;
678 u_short m;
679 int i, j;
680
681 line_width = scp->sc->adp->va_line_width;
682 xoff = (x - scp->xoff*8)%8;
683 yoff = y - (y/line_width)*line_width;
684 ymax = imin(y + 16, scp->ypixel);
685
686 outw(GDCIDX, 0x0805); /* read mode 1, write mode 0 */
687 outw(GDCIDX, 0x0001); /* set/reset enable */
688 outw(GDCIDX, 0x0002); /* color compare */
689 outw(GDCIDX, 0x0007); /* color don't care */
690 outw(GDCIDX, 0xff08); /* bit mask */
691 outw(GDCIDX, 0x0803); /* data rotate/function select (and) */
692 p = scp->sc->adp->va_window + line_width*y + x/8;
693 if (x < scp->xpixel - 16) {
694 for (i = y, j = 0; i < ymax; ++i, ++j) {
695 m = ~(mouse_and_mask[j] >> xoff);
696#ifdef __i386__
697 *(u_char *)p &= m >> 8;
698 *(u_char *)(p + 1) &= m;
699#elif defined(__alpha__)
700 writeb(p, readb(p) & (m >> 8));
701 writeb(p + 1, readb(p + 1) & (m >> 8));
702#endif
703 p += line_width;
704 }
705 } else {
706 xoff += 8;
707 for (i = y, j = 0; i < ymax; ++i, ++j) {
708 m = ~(mouse_and_mask[j] >> xoff);
709#ifdef __i386__
710 *(u_char *)p &= m;
711#elif defined(__alpha__)
712 writeb(p, readb(p) & (m >> 8));
713#endif
714 p += line_width;
715 }
716 }
717 outw(GDCIDX, 0x1003); /* data rotate/function select (or) */
718 p = scp->sc->adp->va_window + line_width*y + x/8;
719 if (x < scp->xpixel - 16) {
720 for (i = y, j = 0; i < ymax; ++i, ++j) {
721 m = mouse_or_mask[j] >> xoff;
722#ifdef __i386__
723 *(u_char *)p &= m >> 8;
724 *(u_char *)(p + 1) &= m;
725#elif defined(__alpha__)
726 writeb(p, readb(p) & (m >> 8));
727 writeb(p + 1, readb(p + 1) & (m >> 8));
728#endif
729 p += line_width;
730 }
731 } else {
732 for (i = y, j = 0; i < ymax; ++i, ++j) {
733 m = mouse_or_mask[j] >> xoff;
734#ifdef __i386__
735 *(u_char *)p &= m;
736#elif defined(__alpha__)
737 writeb(p, readb(p) & (m >> 8));
738#endif
739 p += line_width;
740 }
741 }
742 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
743 outw(GDCIDX, 0x0003); /* data rotate/function select */
744}
745
746static void
747remove_pxlmouse(scr_stat *scp, int x, int y)
748{
749 vm_offset_t p;
750 int col, row;
751 int pos;
752 int line_width;
753 int ymax;
754 int i;
755
756 /* erase the mouse cursor image */
757 col = x/8 - scp->xoff;
758 row = y/scp->font_size - scp->yoff;
759 pos = row*scp->xsize + col;
760 i = (col < scp->xsize - 1) ? 2 : 1;
761 (*scp->rndr->draw)(scp, pos, i, FALSE);
762 if (row < scp->ysize - 1)
763 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
764
765 /* paint border if necessary */
766 line_width = scp->sc->adp->va_line_width;
767 outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */
768 outw(GDCIDX, 0x0003); /* data rotate/function select */
769 outw(GDCIDX, 0x0f01); /* set/reset enable */
770 outw(GDCIDX, 0xff08); /* bit mask */
771 outw(GDCIDX, (scp->border << 8) | 0x00); /* set/reset */
772 if (row == scp->ysize - 1) {
773 i = (scp->ysize + scp->yoff)*scp->font_size;
774 ymax = imin(i + scp->font_size, scp->ypixel);
775 p = scp->sc->adp->va_window + i*line_width + scp->xoff + col;
776 if (col < scp->xsize - 1) {
777 for (; i < ymax; ++i) {
778 writeb(p, 0);
779 writeb(p + 1, 0);
780 p += line_width;
781 }
782 } else {
783 for (; i < ymax; ++i) {
784 writeb(p, 0);
785 p += line_width;
786 }
787 }
788 }
789 if ((col == scp->xsize - 1) && (scp->xoff > 0)) {
790 i = (row + scp->yoff)*scp->font_size;
791 ymax = imin(i + scp->font_size*2, scp->ypixel);
792 p = scp->sc->adp->va_window + i*line_width
793 + scp->xoff + scp->xsize;
794 for (; i < ymax; ++i) {
795 writeb(p, 0);
796 p += line_width;
797 }
798 }
799 outw(GDCIDX, 0x0000); /* set/reset */
800 outw(GDCIDX, 0x0001); /* set/reset enable */
801}
802
803static void
804vga_pxlmouse(scr_stat *scp, int x, int y, int on)
805{
806 if (on)
807 draw_pxlmouse(scp, x, y);
808 else
809 remove_pxlmouse(scp, x, y);
810}
811
812#endif /* SC_NO_CUTPASTE */
813#endif /* SC_PIXEL_MODE */
814
815#ifndef SC_NO_MODE_CHANGE
816
817/* graphics mode renderer */
818
819static void
820vga_grborder(scr_stat *scp, int color)
821{
822 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
823}
824
825#endif
826
827#endif /* NSC > 0 && NVGA > 0 */