kernel/syscons: Add simple font scaling when using KMS drivers.
[dragonfly.git] / sys / dev / misc / syscons / scvgarndr.c
1 /*-
2  * (MPSAFE)
3  *
4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The DragonFly Project
8  * by Sascha Wildner <saw@online.de>
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer as
15  *    the first lines of this file unmodified.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * $FreeBSD: src/sys/dev/syscons/scvgarndr.c,v 1.5.2.3 2001/07/28 12:51:47 yokota Exp $
32  */
33
34 #include "opt_syscons.h"
35 #include "opt_vga.h"
36
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/thread.h>
41 #include <sys/thread2.h>
42
43 #include <machine/console.h>
44
45 #include <dev/video/fb/fbreg.h>
46 #include <dev/video/fb/vgareg.h>
47 #include "syscons.h"
48
49 #include <bus/isa/isareg.h>
50
51 static vr_draw_border_t         vga_txtborder;
52 static vr_draw_t                vga_txtdraw;
53 static vr_set_cursor_t          vga_txtcursor_shape;
54 static vr_draw_cursor_t         vga_txtcursor;
55 static vr_blink_cursor_t        vga_txtblink;
56 #ifndef SC_NO_CUTPASTE
57 static vr_draw_mouse_t          vga_txtmouse;
58 #else
59 #define vga_txtmouse            (vr_draw_mouse_t *)vga_nop
60 #endif
61
62 #ifdef SC_PIXEL_MODE
63 static vr_draw_border_t         vga_pxlborder_direct;
64 static vr_draw_border_t         vga_pxlborder_packed;
65 static vr_draw_border_t         vga_pxlborder_planar;
66 static vr_draw_t                vga_vgadraw_direct;
67 static vr_draw_t                vga_vgadraw_packed;
68 static vr_draw_t                vga_vgadraw_planar;
69 static vr_set_cursor_t          vga_pxlcursor_shape;
70 static vr_draw_cursor_t         vga_pxlcursor_direct;
71 static vr_draw_cursor_t         vga_pxlcursor_packed;
72 static vr_draw_cursor_t         vga_pxlcursor_planar;
73 static vr_blink_cursor_t        vga_pxlblink_direct;
74 static vr_blink_cursor_t        vga_pxlblink_packed;
75 static vr_blink_cursor_t        vga_pxlblink_planar;
76 #ifndef SC_NO_CUTPASTE
77 static vr_draw_mouse_t          vga_pxlmouse_direct;
78 static vr_draw_mouse_t          vga_pxlmouse_packed;
79 static vr_draw_mouse_t          vga_pxlmouse_planar;
80 #else
81 #define vga_pxlmouse_direct     (vr_draw_mouse_t *)vga_nop
82 #define vga_pxlmouse_packed     (vr_draw_mouse_t *)vga_nop
83 #define vga_pxlmouse_planar     (vr_draw_mouse_t *)vga_nop
84 #endif
85 #endif /* SC_PIXEL_MODE */
86
87 #ifndef SC_NO_MODE_CHANGE
88 static vr_draw_border_t         vga_grborder;
89 #endif
90
91 static void                     vga_nop(scr_stat *scp, ...);
92
93 static sc_rndr_sw_t txtrndrsw = {
94         vga_txtborder,
95         vga_txtdraw,    
96         vga_txtcursor_shape,
97         vga_txtcursor,
98         vga_txtblink,
99         vga_txtmouse,
100 };
101 RENDERER(vga, V_INFO_MM_TEXT, txtrndrsw, vga_set);
102
103 #ifdef SC_PIXEL_MODE
104 static sc_rndr_sw_t directrndrsw = {
105         vga_pxlborder_direct,
106         vga_vgadraw_direct,
107         vga_pxlcursor_shape,
108         vga_pxlcursor_direct,
109         vga_pxlblink_direct,
110         vga_pxlmouse_direct,
111 };
112 RENDERER(vga, V_INFO_MM_DIRECT, directrndrsw, vga_set);
113
114 static sc_rndr_sw_t packedrndrsw = {
115         vga_pxlborder_packed,
116         vga_vgadraw_packed,
117         vga_pxlcursor_shape,
118         vga_pxlcursor_packed,
119         vga_pxlblink_packed,
120         vga_pxlmouse_packed,
121 };
122 RENDERER(vga, V_INFO_MM_PACKED, packedrndrsw, vga_set);
123
124 static sc_rndr_sw_t planarrndrsw = {
125         vga_pxlborder_planar,
126         vga_vgadraw_planar,
127         vga_pxlcursor_shape,
128         vga_pxlcursor_planar,
129         vga_pxlblink_planar,
130         vga_pxlmouse_planar,
131 };
132 RENDERER(vga, V_INFO_MM_PLANAR, planarrndrsw, vga_set);
133 #endif /* SC_PIXEL_MODE */
134
135 #ifndef SC_NO_MODE_CHANGE
136 static sc_rndr_sw_t grrndrsw = {
137         vga_grborder,
138         (vr_draw_t *)vga_nop,
139         (vr_set_cursor_t *)vga_nop,
140         (vr_draw_cursor_t *)vga_nop,
141         (vr_blink_cursor_t *)vga_nop,
142         (vr_draw_mouse_t *)vga_nop,
143 };
144 RENDERER(vga, V_INFO_MM_OTHER, grrndrsw, vga_set);
145 #endif /* SC_NO_MODE_CHANGE */
146
147 RENDERER_MODULE(vga, vga_set);
148
149 #ifndef SC_NO_CUTPASTE
150 static u_short mouse_and_mask[16] = {
151         0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
152         0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
153 };
154 static u_short mouse_or_mask[16] = {
155         0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
156         0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
157 };
158 #endif
159
160 static void
161 vga_nop(scr_stat *scp, ...)
162 {
163 }
164
165 /* text mode renderer */
166
167 static void
168 vga_txtborder(scr_stat *scp, int color)
169 {
170         (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
171 }
172
173 static void
174 vga_txtdraw(scr_stat *scp, int from, int count, int flip)
175 {
176         uint16_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 = scp->scr.vtb_buffer + 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
196 static void 
197 vga_txtcursor_shape(scr_stat *scp, int base, int height, int blink)
198 {
199         if (base < 0 || base >= scp->font_height)
200                 return;
201
202         /* the caller may set height <= 0 in order to disable the cursor */
203 #if 0
204         scp->cursor_base = base;
205         scp->cursor_height = height;
206 #endif
207         (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
208                                                         base, height,
209                                                         scp->font_height,
210                                                         blink);
211
212 }
213
214 static void
215 draw_txtcharcursor(scr_stat *scp, int at, u_short c, u_short a, int flip)
216 {
217         sc_softc_t *sc;
218
219         sc = scp->sc;
220         scp->cursor_saveunder_char = c;
221         scp->cursor_saveunder_attr = a;
222
223 #ifndef SC_NO_FONT_LOADING
224         if (sc->flags & SC_CHAR_CURSOR) {
225                 unsigned char *font;
226                 int h;
227                 int i;
228
229                 if (scp->font_height < 14) {
230                         font = sc->font_8;
231                         h = 8;
232                 } else if (scp->font_height >= 16) {
233                         font = sc->font_16;
234                         h = 16;
235                 } else {
236                         font = sc->font_14;
237                         h = 14;
238                 }
239                 if (scp->cursor_base >= h)
240                         return;
241                 if (flip)
242                         a = (a & 0x8800)
243                                 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
244                 bcopy(font + c*h, font + sc->cursor_char*h, h);
245                 font = font + sc->cursor_char*h;
246                 for (i = imax(h - scp->cursor_base - scp->cursor_height, 0);
247                         i < h - scp->cursor_base; ++i) {
248                         font[i] ^= 0xff;
249                 }
250                 sc->font_loading_in_progress = TRUE;
251                 /* XXX */
252                 (*vidsw[sc->adapter]->load_font)(sc->adp, 0, h, font,
253                                                  sc->cursor_char, 1);
254                 sc->font_loading_in_progress = FALSE;
255                 sc_vtb_putc(&scp->scr, at, sc->cursor_char, a);
256         } else
257 #endif /* SC_NO_FONT_LOADING */
258         {
259                 if ((a & 0x7000) == 0x7000) {
260                         a &= 0x8f00;
261                         if ((a & 0x0700) == 0)
262                                 a |= 0x0700;
263                 } else {
264                         a |= 0x7000;
265                         if ((a & 0x0700) == 0x0700)
266                                 a &= 0xf000;
267                 }
268                 if (flip)
269                         a = (a & 0x8800)
270                                 | ((a & 0x7000) >> 4) | ((a & 0x0700) << 4);
271                 sc_vtb_putc(&scp->scr, at, c, a);
272         }
273 }
274
275 static void
276 vga_txtcursor(scr_stat *scp, int at, int blink, int on, int flip)
277 {
278         video_adapter_t *adp;
279         int cursor_attr;
280
281         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
282                 return;
283
284         adp = scp->sc->adp;
285         if (blink) {
286                 scp->status |= VR_CURSOR_BLINK;
287                 if (on) {
288                         scp->status |= VR_CURSOR_ON;
289                         (*vidsw[adp->va_index]->set_hw_cursor)(adp,
290                                                                at%scp->xsize,
291                                                                at/scp->xsize); 
292                 } else {
293                         if (scp->status & VR_CURSOR_ON)
294                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
295                                                                        -1, -1);
296                         scp->status &= ~VR_CURSOR_ON;
297                 }
298         } else {
299                 scp->status &= ~VR_CURSOR_BLINK;
300                 if (on) {
301                         scp->status |= VR_CURSOR_ON;
302                         draw_txtcharcursor(scp, at,
303                                            sc_vtb_getc(&scp->scr, at),
304                                            sc_vtb_geta(&scp->scr, at),
305                                            flip);
306                 } else {
307                         cursor_attr = scp->cursor_saveunder_attr;
308                         if (flip)
309                                 cursor_attr = (cursor_attr & 0x8800)
310                                         | ((cursor_attr & 0x7000) >> 4)
311                                         | ((cursor_attr & 0x0700) << 4);
312                         if (scp->status & VR_CURSOR_ON)
313                                 sc_vtb_putc(&scp->scr, at,
314                                             scp->cursor_saveunder_char,
315                                             cursor_attr);
316                         scp->status &= ~VR_CURSOR_ON;
317                 }
318         }
319 }
320
321 static void
322 vga_txtblink(scr_stat *scp, int at, int flip)
323 {
324 }
325
326 int sc_txtmouse_no_retrace_wait;
327
328 #ifndef SC_NO_CUTPASTE
329
330 static void
331 draw_txtmouse(scr_stat *scp, int x, int y)
332 {
333 #ifndef SC_ALT_MOUSE_IMAGE
334     if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
335         u_char font_buf[128];
336         u_short cursor[32];
337         u_char c;
338         int pos;
339         int xoffset, yoffset;
340         int i;
341
342         /* prepare mousepointer char's bitmaps */
343         pos = (y / scp->font_height - scp->yoff) * scp->xsize +
344               x / scp->font_width - scp->xoff;
345         bcopy(scp->font + sc_vtb_getc(&scp->scr, pos) * scp->font_height,
346               &font_buf[0], scp->font_height);
347         bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1) * scp->font_height,
348               &font_buf[32], scp->font_height);
349         bcopy(scp->font 
350                  + sc_vtb_getc(&scp->scr, pos + scp->xsize) * scp->font_height,
351               &font_buf[64], scp->font_height);
352         bcopy(scp->font +
353               sc_vtb_getc(&scp->scr, pos + scp->xsize + 1) * scp->font_height,
354               &font_buf[96], scp->font_height);
355         for (i = 0; i < scp->font_height; ++i) {
356                 cursor[i] = (font_buf[i]<<8) | font_buf[i+32];
357                 cursor[i + scp->font_height] = (font_buf[i+64]<<8) |
358                                                font_buf[i+96];
359         }
360
361         /* now and-or in the mousepointer image */
362         xoffset = x % scp->font_width;
363         yoffset = y % scp->font_height;
364         for (i = 0; i < 16; ++i) {
365                 cursor[i + yoffset] =
366                         (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
367                         | (mouse_or_mask[i] >> xoffset);
368         }
369         for (i = 0; i < scp->font_height; ++i) {
370                 font_buf[i] = (cursor[i] & 0xff00) >> 8;
371                 font_buf[i + 32] = cursor[i] & 0xff;
372                 font_buf[i + 64] = (cursor[i + scp->font_height] & 0xff00) >> 8;
373                 font_buf[i + 96] = cursor[i + scp->font_height] & 0xff;
374         }
375
376 #if 1
377         /* wait for vertical retrace to avoid jitter on some videocards */
378         while (!sc_txtmouse_no_retrace_wait &&
379             !(inb(CRTC + 6) & 0x08))
380                 /* idle */ ;
381 #endif
382         c = scp->sc->mouse_char;
383         (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
384                                               c, 4); 
385
386         sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
387         /* FIXME: may be out of range! */
388         sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
389                     sc_vtb_geta(&scp->scr, pos + scp->xsize));
390         if (x < (scp->xsize - 1)*8) {
391                 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
392                             sc_vtb_geta(&scp->scr, pos + 1));
393                 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
394                             sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
395         }
396     } else
397 #endif /* SC_ALT_MOUSE_IMAGE */
398     {
399         /* Red, magenta and brown are mapped to green to to keep it readable */
400         static const int col_conv[16] = {
401                 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
402         };
403         int pos;
404         int color;
405         int a;
406
407         pos = (y / scp->font_height - scp->yoff)*
408               scp->xsize + x / scp->font_width - scp->xoff;
409         a = sc_vtb_geta(&scp->scr, pos);
410         if (scp->sc->adp->va_flags & V_ADP_COLOR)
411                 color = (col_conv[(a & 0xf000) >> 12] << 12)
412                         | ((a & 0x0f00) | 0x0800);
413         else
414                 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
415         sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
416     }
417
418 }
419
420 static void
421 remove_txtmouse(scr_stat *scp, int x, int y)
422 {
423 }
424
425 static void 
426 vga_txtmouse(scr_stat *scp, int x, int y, int on)
427 {
428         if (on)
429                 draw_txtmouse(scp, x, y);
430         else
431                 remove_txtmouse(scp, x, y);
432 }
433
434 #endif /* SC_NO_CUTPASTE */
435
436 #ifdef SC_PIXEL_MODE
437
438 /* pixel (raster text) mode renderer */
439
440 static void
441 vga_pxlborder_direct(scr_stat *scp, int color)
442 {
443         int i, x, y;
444         int line_width, pixel_size;
445         uint32_t u32 = 0;
446         vm_offset_t draw_pos, draw_end, p;
447
448         line_width = scp->sc->adp->va_line_width;
449         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
450
451         for (i = 0; i < 4 / pixel_size; ++i)
452                 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
453
454         if (scp->yoff > 0) {
455                 draw_pos = scp->sc->adp->va_window;
456                 draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
457
458                 for (p = draw_pos; p < draw_end; p += 4)
459                         writel(p, u32);
460         }
461
462         y = (scp->yoff + scp->ysize) * scp->font_height;
463
464         if (scp->ypixel > y) {
465                 draw_pos = scp->sc->adp->va_window + line_width * y;
466                 draw_end = draw_pos + line_width * (scp->ypixel - y);
467
468                 for (p = draw_pos; p < draw_end; p += 4)
469                         writel(p, u32); 
470         }
471
472         y = scp->yoff * scp->font_height;
473         x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
474
475         for (i = 0; i < scp->ysize * scp->font_height; ++i) {
476                 if (scp->xoff > 0) {
477                         draw_pos = scp->sc->adp->va_window +
478                             line_width * (y + i);
479                         draw_end = draw_pos +
480                                    scp->xoff * scp->font_width * pixel_size;
481
482                         for (p = draw_pos; p < draw_end; p += 4)
483                                 writel(p, u32);
484                 }
485
486                 if (x > 0) {
487                         draw_pos = scp->sc->adp->va_window +
488                             line_width * (y + i) +
489                             scp->xoff * 8 * pixel_size +
490                             scp->xsize * 8 * pixel_size;
491                         draw_end = draw_pos + x * 8 * pixel_size;
492
493                         for (p = draw_pos; p < draw_end; p += 4)
494                                 writel(p, u32);
495                 }
496         }
497 }
498
499 static void
500 vga_pxlborder_packed(scr_stat *scp, int color)
501 {
502         int i, x, y;
503         int line_width;
504         uint32_t u32;
505         vm_offset_t draw_pos, draw_end, p;
506
507         line_width = scp->sc->adp->va_line_width;
508         u32 = (color << 24) + (color << 16) + (color << 8) + color;
509
510         if (scp->yoff > 0) {
511                 draw_pos = scp->sc->adp->va_window;
512                 draw_end = draw_pos + line_width * scp->yoff * scp->font_height;
513
514                 for (p = draw_pos; p < draw_end; p += 4)
515                         writel(p, u32);
516         }
517
518         y = (scp->yoff + scp->ysize) * scp->font_height;
519
520         if (scp->ypixel > y) {
521                 draw_pos = scp->sc->adp->va_window + line_width * y;
522                 draw_end = draw_pos + line_width * (scp->ypixel - y);
523
524                 for (p = draw_pos; p < draw_end; p += 4)
525                         writel(p, u32);
526         }
527
528         y = scp->yoff * scp->font_height;
529         x = scp->xpixel / scp->font_width - scp->xoff - scp->xsize;
530
531         for (i = 0; i < scp->ysize * scp->font_height; ++i) {
532                 if (scp->xoff > 0) {
533                         draw_pos = scp->sc->adp->va_window +
534                             line_width * (y + i);
535                         draw_end = draw_pos + scp->xoff * scp->font_width;
536
537                         for (p = draw_pos; p < draw_end; p += 4)
538                                 writel(p, u32);
539                 }
540
541                 if (x > 0) {
542                         draw_pos = scp->sc->adp->va_window +
543                             line_width * (y + i) + scp->xoff * 8 +
544                             scp->xsize * 8;
545                         draw_end = draw_pos + x * 8;
546
547                         for (p = draw_pos; p < draw_end; p += 4)
548                                 writel(p, u32);
549                 }
550         }
551 }
552
553 static void
554 vga_pxlborder_planar(scr_stat *scp, int color)
555 {
556         vm_offset_t p;
557         int line_width;
558         int x;
559         int y;
560         int i;
561
562         lwkt_gettoken(&tty_token);
563
564         (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
565
566         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
567         outw(GDCIDX, 0x0003);           /* data rotate/function select */
568         outw(GDCIDX, 0x0f01);           /* set/reset enable */
569         outw(GDCIDX, 0xff08);           /* bit mask */
570         outw(GDCIDX, (color << 8) | 0x00);      /* set/reset */
571         line_width = scp->sc->adp->va_line_width;
572         p = scp->sc->adp->va_window;
573         if (scp->yoff > 0)
574                 bzero_io((void *)p, line_width*scp->yoff*scp->font_height);
575         y = (scp->yoff + scp->ysize)*scp->font_height;
576         if (scp->ypixel > y)
577                 bzero_io((void *)(p + line_width*y),
578                          line_width*(scp->ypixel - y));
579         y = scp->yoff*scp->font_height;
580         x = scp->xpixel/scp->font_width - scp->xoff - scp->xsize;
581         for (i = 0; i < scp->ysize*scp->font_height; ++i) {
582                 if (scp->xoff > 0)
583                         bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
584                 if (x > 0)
585                         bzero_io((void *)(p + line_width*(y + i)
586                                      + scp->xoff + scp->xsize), x);
587         }
588         outw(GDCIDX, 0x0000);           /* set/reset */
589         outw(GDCIDX, 0x0001);           /* set/reset enable */
590         lwkt_reltoken(&tty_token);
591 }
592
593 static void
594 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
595 {
596         int line_width, pixel_size;
597         int a, i, j, k, l, pos;
598         uint32_t fg, bg, u32;
599         unsigned char *char_data;
600         vm_offset_t draw_pos, p;
601
602         line_width = scp->sc->adp->va_line_width;
603         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
604
605         draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
606
607         if (from + count > scp->xsize * scp->ysize)
608                 count = scp->xsize * scp->ysize - from;
609
610         for (i = from; count-- > 0; ++i) {
611                 a = sc_vtb_geta(&scp->vtb, i);
612
613                 if (flip) {
614                         fg = scp->ega_palette[(((a & 0x7000) >> 4) |
615                             (a & 0x0800)) >> 8];
616                         bg = scp->ega_palette[(((a & 0x8000) >> 4) |
617                             (a & 0x0700)) >> 8];
618                 } else {
619                         fg = scp->ega_palette[(a & 0x0f00) >> 8];
620                         bg = scp->ega_palette[(a & 0xf000) >> 12];
621                 }
622
623                 p = draw_pos;
624                 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
625                     scp->font_height]);
626
627                 for (j = 0; j < scp->font_height; ++j, ++char_data) {
628                         pos = 7;
629
630                         for (k = 0; k < 2 * pixel_size; ++k) {
631                                 u32 = 0;
632
633                                 for (l = 0; l < 4 / pixel_size; ++l) {
634                                         u32 += (*char_data & (1 << pos--) ?
635                                             fg : bg) << (l * 8 * pixel_size);
636                                 }
637
638                                 writel(p, u32);
639                                 p += 4;
640                         }
641
642                         p += line_width - 8 * pixel_size;
643                 }
644
645                 draw_pos += 8 * pixel_size;
646
647                 if ((i % scp->xsize) == scp->xsize - 1)
648                         draw_pos += scp->xoff * 16 * pixel_size +
649                              (scp->font_height - 1) * line_width;
650         }
651 }
652
653 static void
654 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
655 {
656         int line_width;
657         int a, i, j;
658         uint32_t fg, bg, u32;
659         unsigned char *char_data;
660         vm_offset_t draw_pos, p;
661
662         line_width = scp->sc->adp->va_line_width;
663
664         draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
665
666         if (from + count > scp->xsize * scp->ysize)
667                 count = scp->xsize * scp->ysize - from;
668
669         for (i = from; count-- > 0; ++i) {
670                 a = sc_vtb_geta(&scp->vtb, i);
671
672                 if (flip) {
673                         fg = ((a & 0xf000) >> 4) >> 8;
674                         bg = (a & 0x0f00) >> 8;
675                 } else {
676                         fg = (a & 0x0f00) >> 8;
677                         bg = ((a & 0xf000) >> 4) >> 8;
678                 }
679
680                 p = draw_pos;
681                 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
682                     scp->font_height]);
683
684                 for (j = 0; j < scp->font_height; ++j, ++char_data) {
685                         u32 = ((*char_data & 1 ? fg : bg) << 24) +
686                               ((*char_data & 2 ? fg : bg) << 16) +
687                               ((*char_data & 4 ? fg : bg) << 8) +
688                               (*char_data & 8 ? fg : bg);
689                         writel(p + 4, u32);
690
691                         u32 = ((*char_data & 16 ? fg : bg) << 24) +
692                               ((*char_data & 32 ? fg : bg) << 16) +
693                               ((*char_data & 64 ? fg : bg) << 8) +
694                               (*char_data & 128 ? fg : bg);
695                         writel(p, u32);
696
697                         p += line_width;
698                 }
699
700                 draw_pos += scp->font_width;
701
702                 if ((i % scp->xsize) == scp->xsize - 1)
703                         draw_pos += scp->xoff * 16 +
704                              (scp->font_height - 1) * line_width;
705         }
706 }
707
708 static void
709 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
710 {
711         vm_offset_t d;
712         vm_offset_t e;
713         u_char *f;
714         u_short bg;
715         u_short col1, col2;
716         int line_width;
717         int i, j;
718         int a;
719         u_char c;
720
721         d = VIDEO_MEMORY_POS(scp, from, 1);
722
723         line_width = scp->sc->adp->va_line_width;
724
725         outw(GDCIDX, 0x0305);           /* read mode 0, write mode 3 */
726         outw(GDCIDX, 0x0003);           /* data rotate/function select */
727         outw(GDCIDX, 0x0f01);           /* set/reset enable */
728         outw(GDCIDX, 0xff08);           /* bit mask */
729         bg = -1;
730         if (from + count > scp->xsize*scp->ysize)
731                 count = scp->xsize*scp->ysize - from;
732         for (i = from; count-- > 0; ++i) {
733                 a = sc_vtb_geta(&scp->vtb, i);
734                 if (flip) {
735                         col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
736                         col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
737                 } else {
738                         col1 = (a & 0x0f00);
739                         col2 = (a & 0xf000) >> 4;
740                 }
741                 /* set background color in EGA/VGA latch */
742                 if (bg != col2) {
743                         bg = col2;
744                         outw(GDCIDX, 0x0005);   /* read mode 0, write mode 0 */
745                         outw(GDCIDX, bg | 0x00); /* set/reset */
746                         writeb(d, 0);
747                         c = readb(d);           /* set bg color in the latch */
748                         outw(GDCIDX, 0x0305);   /* read mode 0, write mode 3 */
749                 }
750                 /* foreground color */
751                 outw(GDCIDX, col1 | 0x00);      /* set/reset */
752                 e = d;
753                 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_height]);
754                 for (j = 0; j < scp->font_height; ++j, ++f) {
755                         writeb(e, *f);
756                         e += line_width;
757                 }
758                 ++d;
759                 if ((i % scp->xsize) == scp->xsize - 1)
760                         d += scp->xoff*2 
761                                  + (scp->font_height - 1)*line_width;
762         }
763         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
764         outw(GDCIDX, 0x0000);           /* set/reset */
765         outw(GDCIDX, 0x0001);           /* set/reset enable */
766 }
767
768 static void 
769 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
770 {
771         if (base < 0 || base >= scp->font_height)
772                 return;
773         /* the caller may set height <= 0 in order to disable the cursor */
774 #if 0
775         scp->cursor_base = base;
776         scp->cursor_height = height;
777 #endif
778 }
779
780 static void 
781 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
782 {
783         int line_width, pixel_size, height;
784         int a, i, j, k, pos;
785         uint32_t fg, bg, u32;
786         unsigned char *char_data;
787         vm_offset_t draw_pos;
788
789         line_width = scp->sc->adp->va_line_width;
790         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
791
792         draw_pos = VIDEO_MEMORY_POS(scp, at, scp->font_width * pixel_size) +
793             (scp->font_height - scp->cursor_base - 1) * line_width;
794
795         a = sc_vtb_geta(&scp->vtb, at);
796
797         if (flip) {
798                 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
799                     ((a & 0xf000) >> 4)) >> 8];
800                 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
801                     (a & 0x0f00)) >> 8];
802         } else {
803                 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
804                     (a & 0x0f00)) >> 8];
805                 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
806                     ((a & 0xf000) >> 4)) >> 8];
807         }
808
809         char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
810             scp->font_height - scp->cursor_base - 1]);
811
812         height = imin(scp->cursor_height, scp->font_height);
813
814         for (i = 0; i < height; ++i, --char_data) {
815                 pos = 7;
816
817                 for (j = 0; j < 2 * pixel_size; ++j) {
818                         u32 = 0;
819
820                         for (k = 0; k < 4 / pixel_size; ++k) {
821                                 u32 += (*char_data & (1 << pos--) ?
822                                     fg : bg) << (k * 8 * pixel_size);
823                         }
824
825                         writel(draw_pos, u32);
826                         draw_pos += 4;
827                 }
828
829                 draw_pos -= line_width + 8 * pixel_size;
830         }
831 }
832
833 static void
834 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
835 {
836         int line_width, height;
837         int a, i;
838         uint32_t fg, bg, u32;
839         unsigned char *char_data;
840         vm_offset_t draw_pos;
841
842         line_width = scp->sc->adp->va_line_width;
843
844         draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
845             (scp->font_height - scp->cursor_base - 1) * line_width;
846
847         a = sc_vtb_geta(&scp->vtb, at);
848
849         if (flip) {
850                 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
851                 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
852         } else {
853                 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
854                 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
855         }
856
857         char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height +
858             scp->font_height - scp->cursor_base - 1]);
859
860         height = imin(scp->cursor_height, scp->font_height);
861
862         for (i = 0; i < height; ++i, --char_data) {
863                 u32 = ((*char_data & 1 ? fg : bg) << 24) +
864                       ((*char_data & 2 ? fg : bg) << 16) +
865                       ((*char_data & 4 ? fg : bg) << 8) +
866                       (*char_data & 8 ? fg : bg);
867                 writel(draw_pos + 4, u32);
868
869                 u32 = ((*char_data & 16 ? fg : bg) << 24) +
870                       ((*char_data & 32 ? fg : bg) << 16) +
871                       ((*char_data & 64 ? fg : bg) << 8) +
872                       (*char_data & 128 ? fg : bg);
873                 writel(draw_pos, u32);
874
875                 draw_pos -= line_width;
876         }
877 }
878
879 static void 
880 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
881 {
882         vm_offset_t d;
883         u_char *f;
884         int line_width;
885         int height;
886         int col;
887         int a;
888         int i;
889         u_char c;
890
891         line_width = scp->sc->adp->va_line_width;
892
893         d = VIDEO_MEMORY_POS(scp, at, 1) +
894             (scp->font_height - scp->cursor_base - 1) * line_width;
895
896         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
897         outw(GDCIDX, 0x0003);           /* data rotate/function select */
898         outw(GDCIDX, 0x0f01);           /* set/reset enable */
899         /* set background color in EGA/VGA latch */
900         a = sc_vtb_geta(&scp->vtb, at);
901         if (flip)
902                 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
903         else
904                 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
905         outw(GDCIDX, col | 0x00);       /* set/reset */
906         outw(GDCIDX, 0xff08);           /* bit mask */
907         writeb(d, 0);
908         c = readb(d);                   /* set bg color in the latch */
909         /* foreground color */
910         if (flip)
911                 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
912         else
913                 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
914         outw(GDCIDX, col | 0x00);       /* set/reset */
915         f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_height
916                 + scp->font_height - scp->cursor_base - 1]);
917         height = imin(scp->cursor_height, scp->font_height);
918         for (i = 0; i < height; ++i, --f) {
919                 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
920                 writeb(d, 0);
921                 d -= line_width;
922         }
923         outw(GDCIDX, 0x0000);           /* set/reset */
924         outw(GDCIDX, 0x0001);           /* set/reset enable */
925         outw(GDCIDX, 0xff08);           /* bit mask */
926 }
927
928 static int pxlblinkrate = 0;
929
930 static void 
931 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
932 {
933         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
934                 return;
935
936         if (on) {
937                 if (!blink) {
938                         scp->status |= VR_CURSOR_ON;
939                         draw_pxlcursor_direct(scp, at, on, flip);
940                 } else if (++pxlblinkrate & 4) {
941                         pxlblinkrate = 0;
942                         scp->status ^= VR_CURSOR_ON;
943                         draw_pxlcursor_direct(scp, at,
944                                               scp->status & VR_CURSOR_ON,
945                                               flip);
946                 }
947         } else {
948                 if (scp->status & VR_CURSOR_ON)
949                         draw_pxlcursor_direct(scp, at, on, flip);
950                 scp->status &= ~VR_CURSOR_ON;
951         }
952         if (blink)
953                 scp->status |= VR_CURSOR_BLINK;
954         else
955                 scp->status &= ~VR_CURSOR_BLINK;
956 }
957
958 static void 
959 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
960 {
961         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
962                 return;
963
964         if (on) {
965                 if (!blink) {
966                         scp->status |= VR_CURSOR_ON;
967                         draw_pxlcursor_packed(scp, at, on, flip);
968                 } else if (++pxlblinkrate & 4) {
969                         pxlblinkrate = 0;
970                         scp->status ^= VR_CURSOR_ON;
971                         draw_pxlcursor_packed(scp, at,
972                                               scp->status & VR_CURSOR_ON,
973                                               flip);
974                 }
975         } else {
976                 if (scp->status & VR_CURSOR_ON)
977                         draw_pxlcursor_packed(scp, at, on, flip);
978                 scp->status &= ~VR_CURSOR_ON;
979         }
980         if (blink)
981                 scp->status |= VR_CURSOR_BLINK;
982         else
983                 scp->status &= ~VR_CURSOR_BLINK;
984 }
985
986 static void
987 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
988 {
989         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
990                 return;
991
992         if (on) {
993                 if (!blink) {
994                         scp->status |= VR_CURSOR_ON;
995                         draw_pxlcursor_planar(scp, at, on, flip);
996                 } else if (++pxlblinkrate & 4) {
997                         pxlblinkrate = 0;
998                         scp->status ^= VR_CURSOR_ON;
999                         draw_pxlcursor_planar(scp, at,
1000                                               scp->status & VR_CURSOR_ON,
1001                                               flip);
1002                 }
1003         } else {
1004                 if (scp->status & VR_CURSOR_ON)
1005                         draw_pxlcursor_planar(scp, at, on, flip);
1006                 scp->status &= ~VR_CURSOR_ON;
1007         }
1008         if (blink)
1009                 scp->status |= VR_CURSOR_BLINK;
1010         else
1011                 scp->status &= ~VR_CURSOR_BLINK;
1012 }
1013
1014 static void
1015 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1016 {
1017         if (!(scp->status & VR_CURSOR_BLINK))
1018                 return;
1019         if (!(++pxlblinkrate & 4))
1020                 return;
1021         pxlblinkrate = 0;
1022         scp->status ^= VR_CURSOR_ON;
1023         draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1024 }
1025
1026 static void
1027 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1028 {
1029         if (!(scp->status & VR_CURSOR_BLINK))
1030                 return;
1031         if (!(++pxlblinkrate & 4))
1032                 return;
1033         pxlblinkrate = 0;
1034         scp->status ^= VR_CURSOR_ON;
1035         draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1036 }
1037
1038 static void
1039 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1040 {
1041         if (!(scp->status & VR_CURSOR_BLINK))
1042                 return;
1043         if (!(++pxlblinkrate & 4))
1044                 return;
1045         pxlblinkrate = 0;
1046         scp->status ^= VR_CURSOR_ON;
1047         draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1048 }
1049
1050 #ifndef SC_NO_CUTPASTE
1051
1052 static void 
1053 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1054 {
1055         int line_width, pixel_size;
1056         int xend, yend;
1057         int i, j;
1058         vm_offset_t draw_pos;
1059
1060         line_width = scp->sc->adp->va_line_width;
1061         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1062
1063         xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1064         yend = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
1065
1066         draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1067
1068         for (i = 0; i < (yend - y); i++) {
1069                 for (j = (xend - x - 1); j >= 0; j--) {
1070                         switch (scp->sc->adp->va_info.vi_depth) {
1071                         case 32:
1072                                 if (mouse_or_mask[i] & 1 << (15 - j))
1073                                         writel(draw_pos + 4 * j,
1074                                             scp->ega_palette[15]);
1075                                 else if (mouse_and_mask[i] & 1 << (15 - j))
1076                                         writel(draw_pos + 4 * j,
1077                                             scp->ega_palette[0]);
1078                                 break;
1079                         case 16:
1080                                 /* FALLTHROUGH */
1081                         case 15:
1082                                 if (mouse_or_mask[i] & 1 << (15 - j))
1083                                         writew(draw_pos + 2 * j,
1084                                             scp->ega_palette[15]);
1085                                 else if (mouse_and_mask[i] & 1 << (15 - j))
1086                                         writew(draw_pos + 2 * j,
1087                                             scp->ega_palette[0]);
1088                                 break;
1089                         }
1090                 }
1091
1092                 draw_pos += line_width;
1093         }
1094 }
1095
1096 static void
1097 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1098 {
1099         int line_width;
1100         int xend, yend;
1101         int i, j;
1102         vm_offset_t draw_pos;
1103
1104         line_width = scp->sc->adp->va_line_width;
1105
1106         xend = imin(scp->font_width * (scp->xoff + scp->xsize),
1107                     imin(x + 16, scp->xpixel));
1108         yend = imin(scp->font_height * (scp->yoff + scp->ysize),
1109                     imin(y + 16, scp->ypixel));
1110
1111         draw_pos = scp->sc->adp->va_window + y * line_width + x;
1112
1113         for (i = 0; i < (yend - y); i++) {
1114                 for (j = (xend - x - 1); j >= 0; j--) {
1115                         if (mouse_or_mask[i] & 1 << (15 - j))
1116                                 writeb(draw_pos + j, 15);
1117                         else if (mouse_and_mask[i] & 1 << (15 - j))
1118                                 writeb(draw_pos + j, 0);
1119                 }
1120
1121                 draw_pos += line_width;
1122         }
1123 }
1124
1125 static void
1126 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1127 {
1128         vm_offset_t p;
1129         int line_width;
1130         int xoff;
1131         int ymax;
1132         u_short m;
1133         int i, j;
1134
1135         line_width = scp->sc->adp->va_line_width;
1136         xoff = (x - scp->xoff*8)%8;
1137         ymax = imin(y + 16, scp->font_height * (scp->yoff + scp->ysize));
1138
1139         outw(GDCIDX, 0x0805);           /* read mode 1, write mode 0 */
1140         outw(GDCIDX, 0x0001);           /* set/reset enable */
1141         outw(GDCIDX, 0x0002);           /* color compare */
1142         outw(GDCIDX, 0x0007);           /* color don't care */
1143         outw(GDCIDX, 0xff08);           /* bit mask */
1144         outw(GDCIDX, 0x0803);           /* data rotate/function select (and) */
1145         p = scp->sc->adp->va_window + line_width*y + x/8;
1146         if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1147                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1148                         m = ~(mouse_and_mask[j] >> xoff);
1149                         *(u_char *)p &= m >> 8;
1150                         *(u_char *)(p + 1) &= m;
1151                         p += line_width;
1152                 }
1153         } else {
1154                 xoff += 8;
1155                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1156                         m = ~(mouse_and_mask[j] >> xoff);
1157                         *(u_char *)p &= m;
1158                         p += line_width;
1159                 }
1160         }
1161         outw(GDCIDX, 0x1003);           /* data rotate/function select (or) */
1162         p = scp->sc->adp->va_window + line_width*y + x/8;
1163         if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1164                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1165                         m = mouse_or_mask[j] >> xoff;
1166                         *(u_char *)p &= m >> 8;
1167                         *(u_char *)(p + 1) &= m;
1168                         p += line_width;
1169                 }
1170         } else {
1171                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1172                         m = mouse_or_mask[j] >> xoff;
1173                         *(u_char *)p &= m;
1174                         p += line_width;
1175                 }
1176         }
1177         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
1178         outw(GDCIDX, 0x0003);           /* data rotate/function select */
1179 }
1180
1181 static void
1182 remove_pxlmouse(scr_stat *scp, int x, int y)
1183 {
1184         int col, row;
1185         int pos;
1186         int i;
1187
1188         /* erase the mouse cursor image */
1189         col = x / scp->font_width - scp->xoff;
1190         row = y / scp->font_height - scp->yoff;
1191         pos = row * scp->xsize + col;
1192         i = (col < scp->xsize - 1) ? 2 : 1;
1193         (*scp->rndr->draw)(scp, pos, i, FALSE);
1194         if (row < scp->ysize - 1)
1195                 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1196 }
1197
1198 static void 
1199 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1200 {
1201         if (on)
1202                 draw_pxlmouse_direct(scp, x, y);
1203         else
1204                 remove_pxlmouse(scp, x, y);
1205 }
1206
1207 static void
1208 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1209 {
1210         if (on)
1211                 draw_pxlmouse_packed(scp, x, y);
1212         else
1213                 remove_pxlmouse(scp, x, y);
1214 }
1215
1216 static void 
1217 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1218 {
1219         if (on)
1220                 draw_pxlmouse_planar(scp, x, y);
1221         else
1222                 remove_pxlmouse(scp, x, y);
1223 }
1224
1225 #endif /* SC_NO_CUTPASTE */
1226 #endif /* SC_PIXEL_MODE */
1227
1228 #ifndef SC_NO_MODE_CHANGE
1229
1230 /* graphics mode renderer */
1231
1232 static void
1233 vga_grborder(scr_stat *scp, int color)
1234 {
1235         lwkt_gettoken(&tty_token);
1236         (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1237         lwkt_reltoken(&tty_token);
1238 }
1239
1240 #endif