Deleted Added
full compact
scgfbrndr.c (55849) scgfbrndr.c (56043)
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 *
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 $
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>
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
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
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};
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};
96RENDERER(mda, 0, txtrndrsw);
97RENDERER(cga, 0, txtrndrsw);
98RENDERER(ega, 0, txtrndrsw);
99RENDERER(vga, 0, txtrndrsw);
97RENDERER(mda, 0, txtrndrsw, vga_set);
98RENDERER(cga, 0, txtrndrsw, vga_set);
99RENDERER(ega, 0, txtrndrsw, vga_set);
100RENDERER(vga, 0, txtrndrsw, vga_set);
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};
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};
112RENDERER(ega, PIXEL_MODE, egarndrsw);
113RENDERER(ega, PIXEL_MODE, egarndrsw, vga_set);
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};
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};
124RENDERER(vga, PIXEL_MODE, vgarndrsw);
125RENDERER(vga, PIXEL_MODE, vgarndrsw, vga_set);
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};
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};
138RENDERER(cga, GRAPHICS_MODE, grrndrsw);
139RENDERER(ega, GRAPHICS_MODE, grrndrsw);
140RENDERER(vga, GRAPHICS_MODE, grrndrsw);
139RENDERER(cga, GRAPHICS_MODE, grrndrsw, vga_set);
140RENDERER(ega, GRAPHICS_MODE, grrndrsw, vga_set);
141RENDERER(vga, GRAPHICS_MODE, grrndrsw, vga_set);
141#endif /* SC_NO_MODE_CHANGE */
142
142#endif /* SC_NO_MODE_CHANGE */
143
144RENDERER_MODULE(vga, vga_set);
145
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 */
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 */