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