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