kernel - Fix multiple tty_token issues related to vt switching and X
[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                         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 #ifndef SC_NO_CUTPASTE
327
328 static void
329 draw_txtmouse(scr_stat *scp, int x, int y)
330 {
331 #ifndef SC_ALT_MOUSE_IMAGE
332     if (ISMOUSEAVAIL(scp->sc->adp->va_flags)) {
333         u_char font_buf[128];
334         u_short cursor[32];
335         u_char c;
336         int pos;
337         int xoffset, yoffset;
338         int i;
339
340         /* prepare mousepointer char's bitmaps */
341         pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
342         bcopy(scp->font + sc_vtb_getc(&scp->scr, pos)*scp->font_size,
343               &font_buf[0], scp->font_size);
344         bcopy(scp->font + sc_vtb_getc(&scp->scr, pos + 1)*scp->font_size,
345               &font_buf[32], scp->font_size);
346         bcopy(scp->font 
347                  + sc_vtb_getc(&scp->scr, pos + scp->xsize)*scp->font_size,
348               &font_buf[64], scp->font_size);
349         bcopy(scp->font
350                  + sc_vtb_getc(&scp->scr, pos + scp->xsize + 1)*scp->font_size,
351               &font_buf[96], scp->font_size);
352         for (i = 0; i < scp->font_size; ++i) {
353                 cursor[i] = font_buf[i]<<8 | font_buf[i+32];
354                 cursor[i + scp->font_size] = font_buf[i+64]<<8 | font_buf[i+96];
355         }
356
357         /* now and-or in the mousepointer image */
358         xoffset = x%8;
359         yoffset = y%scp->font_size;
360         for (i = 0; i < 16; ++i) {
361                 cursor[i + yoffset] =
362                         (cursor[i + yoffset] & ~(mouse_and_mask[i] >> xoffset))
363                         | (mouse_or_mask[i] >> xoffset);
364         }
365         for (i = 0; i < scp->font_size; ++i) {
366                 font_buf[i] = (cursor[i] & 0xff00) >> 8;
367                 font_buf[i + 32] = cursor[i] & 0xff;
368                 font_buf[i + 64] = (cursor[i + scp->font_size] & 0xff00) >> 8;
369                 font_buf[i + 96] = cursor[i + scp->font_size] & 0xff;
370         }
371
372 #if 1
373         /* wait for vertical retrace to avoid jitter on some videocards */
374         while (!(inb(CRTC + 6) & 0x08)) /* idle */ ;
375 #endif
376         c = scp->sc->mouse_char;
377         (*vidsw[scp->sc->adapter]->load_font)(scp->sc->adp, 0, 32, font_buf,
378                                               c, 4); 
379
380         sc_vtb_putc(&scp->scr, pos, c, sc_vtb_geta(&scp->scr, pos));
381         /* FIXME: may be out of range! */
382         sc_vtb_putc(&scp->scr, pos + scp->xsize, c + 2,
383                     sc_vtb_geta(&scp->scr, pos + scp->xsize));
384         if (x < (scp->xsize - 1)*8) {
385                 sc_vtb_putc(&scp->scr, pos + 1, c + 1,
386                             sc_vtb_geta(&scp->scr, pos + 1));
387                 sc_vtb_putc(&scp->scr, pos + scp->xsize + 1, c + 3,
388                             sc_vtb_geta(&scp->scr, pos + scp->xsize + 1));
389         }
390     } else
391 #endif /* SC_ALT_MOUSE_IMAGE */
392     {
393         /* Red, magenta and brown are mapped to green to to keep it readable */
394         static const int col_conv[16] = {
395                 6, 6, 6, 6, 2, 2, 2, 6, 14, 14, 14, 14, 10, 10, 10, 14
396         };
397         int pos;
398         int color;
399         int a;
400
401         pos = (y/scp->font_size - scp->yoff)*scp->xsize + x/8 - scp->xoff;
402         a = sc_vtb_geta(&scp->scr, pos);
403         if (scp->sc->adp->va_flags & V_ADP_COLOR)
404                 color = (col_conv[(a & 0xf000) >> 12] << 12)
405                         | ((a & 0x0f00) | 0x0800);
406         else
407                 color = ((a & 0xf000) >> 4) | ((a & 0x0f00) << 4);
408         sc_vtb_putc(&scp->scr, pos, sc_vtb_getc(&scp->scr, pos), color);
409     }
410
411 }
412
413 static void
414 remove_txtmouse(scr_stat *scp, int x, int y)
415 {
416 }
417
418 static void 
419 vga_txtmouse(scr_stat *scp, int x, int y, int on)
420 {
421         if (on)
422                 draw_txtmouse(scp, x, y);
423         else
424                 remove_txtmouse(scp, x, y);
425 }
426
427 #endif /* SC_NO_CUTPASTE */
428
429 #ifdef SC_PIXEL_MODE
430
431 /* pixel (raster text) mode renderer */
432
433 static void
434 vga_pxlborder_direct(scr_stat *scp, int color)
435 {
436         int i, x, y;
437         int line_width, pixel_size;
438         uint32_t u32 = 0;
439         vm_offset_t draw_pos, draw_end, p;
440
441         line_width = scp->sc->adp->va_line_width;
442         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
443
444         for (i = 0; i < 4 / pixel_size; ++i)
445                 u32 += scp->ega_palette[color] << (i * 8 * pixel_size);
446
447         if (scp->yoff > 0) {
448                 draw_pos = scp->sc->adp->va_window;
449                 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
450
451                 for (p = draw_pos; p < draw_end; p += 4)
452                         writel(p, u32);
453         }
454
455         y = (scp->yoff + scp->ysize) * scp->font_size;
456
457         if (scp->ypixel > y) {
458                 draw_pos = scp->sc->adp->va_window + line_width * y;
459                 draw_end = draw_pos + line_width * (scp->ypixel - y);
460
461                 for (p = draw_pos; p < draw_end; p += 4)
462                         writel(p, u32); 
463         }
464
465         y = scp->yoff * scp->font_size;
466         x = scp->xpixel / 8 - scp->xoff - scp->xsize;
467
468         for (i = 0; i < scp->ysize * scp->font_size; ++i) {
469                 if (scp->xoff > 0) {
470                         draw_pos = scp->sc->adp->va_window +
471                             line_width * (y + i);
472                         draw_end = draw_pos + scp->xoff * 8 * pixel_size;
473
474                         for (p = draw_pos; p < draw_end; p += 4)
475                                 writel(p, u32);
476                 }
477
478                 if (x > 0) {
479                         draw_pos = scp->sc->adp->va_window +
480                             line_width * (y + i) +
481                             scp->xoff * 8 * pixel_size +
482                             scp->xsize * 8 * pixel_size;
483                         draw_end = draw_pos + x * 8 * pixel_size;
484
485                         for (p = draw_pos; p < draw_end; p += 4)
486                                 writel(p, u32);
487                 }
488         }
489 }
490
491 static void
492 vga_pxlborder_packed(scr_stat *scp, int color)
493 {
494         int i, x, y;
495         int line_width;
496         uint32_t u32;
497         vm_offset_t draw_pos, draw_end, p;
498
499         line_width = scp->sc->adp->va_line_width;
500         u32 = (color << 24) + (color << 16) + (color << 8) + color;
501
502         if (scp->yoff > 0) {
503                 draw_pos = scp->sc->adp->va_window;
504                 draw_end = draw_pos + line_width * scp->yoff * scp->font_size;
505
506                 for (p = draw_pos; p < draw_end; p += 4)
507                         writel(p, u32);
508         }
509
510         y = (scp->yoff + scp->ysize) * scp->font_size;
511
512         if (scp->ypixel > y) {
513                 draw_pos = scp->sc->adp->va_window + line_width * y;
514                 draw_end = draw_pos + line_width * (scp->ypixel - y);
515
516                 for (p = draw_pos; p < draw_end; p += 4)
517                         writel(p, u32);
518         }
519
520         y = scp->yoff * scp->font_size;
521         x = scp->xpixel / 8 - scp->xoff - scp->xsize;
522
523         for (i = 0; i < scp->ysize * scp->font_size; ++i) {
524                 if (scp->xoff > 0) {
525                         draw_pos = scp->sc->adp->va_window +
526                             line_width * (y + i);
527                         draw_end = draw_pos + scp->xoff * 8;
528
529                         for (p = draw_pos; p < draw_end; p += 4)
530                                 writel(p, u32);
531                 }
532
533                 if (x > 0) {
534                         draw_pos = scp->sc->adp->va_window +
535                             line_width * (y + i) + scp->xoff * 8 +
536                             scp->xsize * 8;
537                         draw_end = draw_pos + x * 8;
538
539                         for (p = draw_pos; p < draw_end; p += 4)
540                                 writel(p, u32);
541                 }
542         }
543 }
544
545 static void
546 vga_pxlborder_planar(scr_stat *scp, int color)
547 {
548         vm_offset_t p;
549         int line_width;
550         int x;
551         int y;
552         int i;
553
554         lwkt_gettoken(&tty_token);
555
556         (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
557
558         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
559         outw(GDCIDX, 0x0003);           /* data rotate/function select */
560         outw(GDCIDX, 0x0f01);           /* set/reset enable */
561         outw(GDCIDX, 0xff08);           /* bit mask */
562         outw(GDCIDX, (color << 8) | 0x00);      /* set/reset */
563         line_width = scp->sc->adp->va_line_width;
564         p = scp->sc->adp->va_window;
565         if (scp->yoff > 0)
566                 bzero_io((void *)p, line_width*scp->yoff*scp->font_size);
567         y = (scp->yoff + scp->ysize)*scp->font_size;
568         if (scp->ypixel > y)
569                 bzero_io((void *)(p + line_width*y), line_width*(scp->ypixel - y));
570         y = scp->yoff*scp->font_size;
571         x = scp->xpixel/8 - scp->xoff - scp->xsize;
572         for (i = 0; i < scp->ysize*scp->font_size; ++i) {
573                 if (scp->xoff > 0)
574                         bzero_io((void *)(p + line_width*(y + i)), scp->xoff);
575                 if (x > 0)
576                         bzero_io((void *)(p + line_width*(y + i)
577                                      + scp->xoff + scp->xsize), x);
578         }
579         outw(GDCIDX, 0x0000);           /* set/reset */
580         outw(GDCIDX, 0x0001);           /* set/reset enable */
581         lwkt_reltoken(&tty_token);
582 }
583
584 static void
585 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
586 {
587         int line_width, pixel_size;
588         int a, i, j, k, l, pos;
589         uint32_t fg, bg, u32;
590         unsigned char *char_data;
591         vm_offset_t draw_pos, p;
592
593         line_width = scp->sc->adp->va_line_width;
594         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
595
596         draw_pos = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
597
598         if (from + count > scp->xsize * scp->ysize)
599                 count = scp->xsize * scp->ysize - from;
600
601         for (i = from; count-- > 0; ++i) {
602                 a = sc_vtb_geta(&scp->vtb, i);
603
604                 if (flip) {
605                         fg = scp->ega_palette[(((a & 0x7000) >> 4) |
606                             (a & 0x0800)) >> 8];
607                         bg = scp->ega_palette[(((a & 0x8000) >> 4) |
608                             (a & 0x0700)) >> 8];
609                 } else {
610                         fg = scp->ega_palette[(a & 0x0f00) >> 8];
611                         bg = scp->ega_palette[(a & 0xf000) >> 12];
612                 }
613
614                 p = draw_pos;
615                 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
616                     scp->font_size]);
617
618                 for (j = 0; j < scp->font_size; ++j, ++char_data) {
619                         pos = 7;
620
621                         for (k = 0; k < 2 * pixel_size; ++k) {
622                                 u32 = 0;
623
624                                 for (l = 0; l < 4 / pixel_size; ++l) {
625                                         u32 += (*char_data & (1 << pos--) ?
626                                             fg : bg) << (l * 8 * pixel_size);
627                                 }
628
629                                 writel(p, u32);
630                                 p += 4;
631                         }
632
633                         p += line_width - 8 * pixel_size;
634                 }
635
636                 draw_pos += 8 * pixel_size;
637
638                 if ((i % scp->xsize) == scp->xsize - 1)
639                         draw_pos += scp->xoff * 16 * pixel_size +
640                              (scp->font_size - 1) * line_width;
641         }
642 }
643
644 static void
645 vga_vgadraw_packed(scr_stat *scp, int from, int count, int flip)
646 {
647         int line_width;
648         int a, i, j;
649         uint32_t fg, bg, u32;
650         unsigned char *char_data;
651         vm_offset_t draw_pos, p;
652
653         line_width = scp->sc->adp->va_line_width;
654
655         draw_pos = VIDEO_MEMORY_POS(scp, from, 8);
656
657         if (from + count > scp->xsize * scp->ysize)
658                 count = scp->xsize * scp->ysize - from;
659
660         for (i = from; count-- > 0; ++i) {
661                 a = sc_vtb_geta(&scp->vtb, i);
662
663                 if (flip) {
664                         fg = ((a & 0xf000) >> 4) >> 8;
665                         bg = (a & 0x0f00) >> 8;
666                 } else {
667                         fg = (a & 0x0f00) >> 8;
668                         bg = ((a & 0xf000) >> 4) >> 8;
669                 }
670
671                 p = draw_pos;
672                 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
673                     scp->font_size]);
674
675                 for (j = 0; j < scp->font_size; ++j, ++char_data) {
676                         u32 = ((*char_data & 1 ? fg : bg) << 24) +
677                               ((*char_data & 2 ? fg : bg) << 16) +
678                               ((*char_data & 4 ? fg : bg) << 8) +
679                               (*char_data & 8 ? fg : bg);
680                         writel(p + 4, u32);
681
682                         u32 = ((*char_data & 16 ? fg : bg) << 24) +
683                               ((*char_data & 32 ? fg : bg) << 16) +
684                               ((*char_data & 64 ? fg : bg) << 8) +
685                               (*char_data & 128 ? fg : bg);
686                         writel(p, u32);
687
688                         p += line_width;
689                 }
690
691                 draw_pos += 8;
692
693                 if ((i % scp->xsize) == scp->xsize - 1)
694                         draw_pos += scp->xoff * 16 +
695                              (scp->font_size - 1) * line_width;
696         }
697 }
698
699 static void
700 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
701 {
702         vm_offset_t d;
703         vm_offset_t e;
704         u_char *f;
705         u_short bg;
706         u_short col1, col2;
707         int line_width;
708         int i, j;
709         int a;
710         u_char c;
711
712         d = VIDEO_MEMORY_POS(scp, from, 1);
713
714         line_width = scp->sc->adp->va_line_width;
715
716         outw(GDCIDX, 0x0305);           /* read mode 0, write mode 3 */
717         outw(GDCIDX, 0x0003);           /* data rotate/function select */
718         outw(GDCIDX, 0x0f01);           /* set/reset enable */
719         outw(GDCIDX, 0xff08);           /* bit mask */
720         bg = -1;
721         if (from + count > scp->xsize*scp->ysize)
722                 count = scp->xsize*scp->ysize - from;
723         for (i = from; count-- > 0; ++i) {
724                 a = sc_vtb_geta(&scp->vtb, i);
725                 if (flip) {
726                         col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
727                         col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
728                 } else {
729                         col1 = (a & 0x0f00);
730                         col2 = (a & 0xf000) >> 4;
731                 }
732                 /* set background color in EGA/VGA latch */
733                 if (bg != col2) {
734                         bg = col2;
735                         outw(GDCIDX, 0x0005);   /* read mode 0, write mode 0 */
736                         outw(GDCIDX, bg | 0x00); /* set/reset */
737                         writeb(d, 0);
738                         c = readb(d);           /* set bg color in the latch */
739                         outw(GDCIDX, 0x0305);   /* read mode 0, write mode 3 */
740                 }
741                 /* foreground color */
742                 outw(GDCIDX, col1 | 0x00);      /* set/reset */
743                 e = d;
744                 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
745                 for (j = 0; j < scp->font_size; ++j, ++f) {
746                         writeb(e, *f);
747                         e += line_width;
748                 }
749                 ++d;
750                 if ((i % scp->xsize) == scp->xsize - 1)
751                         d += scp->xoff*2 
752                                  + (scp->font_size - 1)*line_width;
753         }
754         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
755         outw(GDCIDX, 0x0000);           /* set/reset */
756         outw(GDCIDX, 0x0001);           /* set/reset enable */
757 }
758
759 static void 
760 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
761 {
762         if (base < 0 || base >= scp->font_size)
763                 return;
764         /* the caller may set height <= 0 in order to disable the cursor */
765 #if 0
766         scp->cursor_base = base;
767         scp->cursor_height = height;
768 #endif
769 }
770
771 static void 
772 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
773 {
774         int line_width, pixel_size, height;
775         int a, i, j, k, pos;
776         uint32_t fg, bg, u32;
777         unsigned char *char_data;
778         vm_offset_t draw_pos;
779
780         line_width = scp->sc->adp->va_line_width;
781         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
782
783         draw_pos = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
784             (scp->font_size - scp->cursor_base - 1) * line_width;
785
786         a = sc_vtb_geta(&scp->vtb, at);
787
788         if (flip) {
789                 fg = scp->ega_palette[((on) ? (a & 0x0f00) :
790                     ((a & 0xf000) >> 4)) >> 8];
791                 bg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
792                     (a & 0x0f00)) >> 8];
793         } else {
794                 fg = scp->ega_palette[((on) ? ((a & 0xf000) >> 4) :
795                     (a & 0x0f00)) >> 8];
796                 bg = scp->ega_palette[((on) ? (a & 0x0f00) :
797                     ((a & 0xf000) >> 4)) >> 8];
798         }
799
800         char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
801             scp->font_size - scp->cursor_base - 1]);
802
803         height = imin(scp->cursor_height, scp->font_size);
804
805         for (i = 0; i < height; ++i, --char_data) {
806                 pos = 7;
807
808                 for (j = 0; j < 2 * pixel_size; ++j) {
809                         u32 = 0;
810
811                         for (k = 0; k < 4 / pixel_size; ++k) {
812                                 u32 += (*char_data & (1 << pos--) ?
813                                     fg : bg) << (k * 8 * pixel_size);
814                         }
815
816                         writel(draw_pos, u32);
817                         draw_pos += 4;
818                 }
819
820                 draw_pos -= line_width + 8 * pixel_size;
821         }
822 }
823
824 static void
825 draw_pxlcursor_packed(scr_stat *scp, int at, int on, int flip)
826 {
827         int line_width, height;
828         int a, i;
829         uint32_t fg, bg, u32;
830         unsigned char *char_data;
831         vm_offset_t draw_pos;
832
833         line_width = scp->sc->adp->va_line_width;
834
835         draw_pos = VIDEO_MEMORY_POS(scp, at, 8) +
836             (scp->font_size - scp->cursor_base - 1) * line_width;
837
838         a = sc_vtb_geta(&scp->vtb, at);
839
840         if (flip) {
841                 fg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
842                 bg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
843         } else {
844                 fg = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
845                 bg = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
846         }
847
848         char_data = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
849             scp->font_size - scp->cursor_base - 1]);
850
851         height = imin(scp->cursor_height, scp->font_size);
852
853         for (i = 0; i < height; ++i, --char_data) {
854                 u32 = ((*char_data & 1 ? fg : bg) << 24) +
855                       ((*char_data & 2 ? fg : bg) << 16) +
856                       ((*char_data & 4 ? fg : bg) << 8) +
857                       (*char_data & 8 ? fg : bg);
858                 writel(draw_pos + 4, u32);
859
860                 u32 = ((*char_data & 16 ? fg : bg) << 24) +
861                       ((*char_data & 32 ? fg : bg) << 16) +
862                       ((*char_data & 64 ? fg : bg) << 8) +
863                       (*char_data & 128 ? fg : bg);
864                 writel(draw_pos, u32);
865
866                 draw_pos -= line_width;
867         }
868 }
869
870 static void 
871 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
872 {
873         vm_offset_t d;
874         u_char *f;
875         int line_width;
876         int height;
877         int col;
878         int a;
879         int i;
880         u_char c;
881
882         line_width = scp->sc->adp->va_line_width;
883
884         d = VIDEO_MEMORY_POS(scp, at, 1) +
885             (scp->font_size - scp->cursor_base - 1) * line_width;
886
887         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
888         outw(GDCIDX, 0x0003);           /* data rotate/function select */
889         outw(GDCIDX, 0x0f01);           /* set/reset enable */
890         /* set background color in EGA/VGA latch */
891         a = sc_vtb_geta(&scp->vtb, at);
892         if (flip)
893                 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
894         else
895                 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
896         outw(GDCIDX, col | 0x00);       /* set/reset */
897         outw(GDCIDX, 0xff08);           /* bit mask */
898         writeb(d, 0);
899         c = readb(d);                   /* set bg color in the latch */
900         /* foreground color */
901         if (flip)
902                 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
903         else
904                 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
905         outw(GDCIDX, col | 0x00);       /* set/reset */
906         f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
907                 + scp->font_size - scp->cursor_base - 1]);
908         height = imin(scp->cursor_height, scp->font_size);
909         for (i = 0; i < height; ++i, --f) {
910                 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
911                 writeb(d, 0);
912                 d -= line_width;
913         }
914         outw(GDCIDX, 0x0000);           /* set/reset */
915         outw(GDCIDX, 0x0001);           /* set/reset enable */
916         outw(GDCIDX, 0xff08);           /* bit mask */
917 }
918
919 static int pxlblinkrate = 0;
920
921 static void 
922 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
923 {
924         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
925                 return;
926
927         if (on) {
928                 if (!blink) {
929                         scp->status |= VR_CURSOR_ON;
930                         draw_pxlcursor_direct(scp, at, on, flip);
931                 } else if (++pxlblinkrate & 4) {
932                         pxlblinkrate = 0;
933                         scp->status ^= VR_CURSOR_ON;
934                         draw_pxlcursor_direct(scp, at,
935                                               scp->status & VR_CURSOR_ON,
936                                               flip);
937                 }
938         } else {
939                 if (scp->status & VR_CURSOR_ON)
940                         draw_pxlcursor_direct(scp, at, on, flip);
941                 scp->status &= ~VR_CURSOR_ON;
942         }
943         if (blink)
944                 scp->status |= VR_CURSOR_BLINK;
945         else
946                 scp->status &= ~VR_CURSOR_BLINK;
947 }
948
949 static void 
950 vga_pxlcursor_packed(scr_stat *scp, int at, int blink, int on, int flip)
951 {
952         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
953                 return;
954
955         if (on) {
956                 if (!blink) {
957                         scp->status |= VR_CURSOR_ON;
958                         draw_pxlcursor_packed(scp, at, on, flip);
959                 } else if (++pxlblinkrate & 4) {
960                         pxlblinkrate = 0;
961                         scp->status ^= VR_CURSOR_ON;
962                         draw_pxlcursor_packed(scp, at,
963                                               scp->status & VR_CURSOR_ON,
964                                               flip);
965                 }
966         } else {
967                 if (scp->status & VR_CURSOR_ON)
968                         draw_pxlcursor_packed(scp, at, on, flip);
969                 scp->status &= ~VR_CURSOR_ON;
970         }
971         if (blink)
972                 scp->status |= VR_CURSOR_BLINK;
973         else
974                 scp->status &= ~VR_CURSOR_BLINK;
975 }
976
977 static void
978 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
979 {
980         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
981                 return;
982
983         if (on) {
984                 if (!blink) {
985                         scp->status |= VR_CURSOR_ON;
986                         draw_pxlcursor_planar(scp, at, on, flip);
987                 } else if (++pxlblinkrate & 4) {
988                         pxlblinkrate = 0;
989                         scp->status ^= VR_CURSOR_ON;
990                         draw_pxlcursor_planar(scp, at,
991                                               scp->status & VR_CURSOR_ON,
992                                               flip);
993                 }
994         } else {
995                 if (scp->status & VR_CURSOR_ON)
996                         draw_pxlcursor_planar(scp, at, on, flip);
997                 scp->status &= ~VR_CURSOR_ON;
998         }
999         if (blink)
1000                 scp->status |= VR_CURSOR_BLINK;
1001         else
1002                 scp->status &= ~VR_CURSOR_BLINK;
1003 }
1004
1005 static void
1006 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
1007 {
1008         if (!(scp->status & VR_CURSOR_BLINK))
1009                 return;
1010         if (!(++pxlblinkrate & 4))
1011                 return;
1012         pxlblinkrate = 0;
1013         scp->status ^= VR_CURSOR_ON;
1014         draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1015 }
1016
1017 static void
1018 vga_pxlblink_packed(scr_stat *scp, int at, int flip)
1019 {
1020         if (!(scp->status & VR_CURSOR_BLINK))
1021                 return;
1022         if (!(++pxlblinkrate & 4))
1023                 return;
1024         pxlblinkrate = 0;
1025         scp->status ^= VR_CURSOR_ON;
1026         draw_pxlcursor_packed(scp, at, scp->status & VR_CURSOR_ON, flip);
1027 }
1028
1029 static void
1030 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1031 {
1032         if (!(scp->status & VR_CURSOR_BLINK))
1033                 return;
1034         if (!(++pxlblinkrate & 4))
1035                 return;
1036         pxlblinkrate = 0;
1037         scp->status ^= VR_CURSOR_ON;
1038         draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1039 }
1040
1041 #ifndef SC_NO_CUTPASTE
1042
1043 static void 
1044 draw_pxlmouse_direct(scr_stat *scp, int x, int y)
1045 {
1046         int line_width, pixel_size;
1047         int xend, yend;
1048         int i, j;
1049         vm_offset_t draw_pos;
1050
1051         line_width = scp->sc->adp->va_line_width;
1052         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1053
1054         xend = imin(x + 8, 8 * (scp->xoff + scp->xsize));
1055         yend = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1056
1057         draw_pos = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1058
1059         for (i = 0; i < (yend - y); i++) {
1060                 for (j = (xend - x - 1); j >= 0; j--) {
1061                         switch (scp->sc->adp->va_info.vi_depth) {
1062                         case 32:
1063                                 if (mouse_or_mask[i] & 1 << (15 - j))
1064                                         writel(draw_pos + 4 * j,
1065                                             scp->ega_palette[15]);
1066                                 else if (mouse_and_mask[i] & 1 << (15 - j))
1067                                         writel(draw_pos + 4 * j,
1068                                             scp->ega_palette[0]);
1069                                 break;
1070                         case 16:
1071                                 /* FALLTHROUGH */
1072                         case 15:
1073                                 if (mouse_or_mask[i] & 1 << (15 - j))
1074                                         writew(draw_pos + 2 * j,
1075                                             scp->ega_palette[15]);
1076                                 else if (mouse_and_mask[i] & 1 << (15 - j))
1077                                         writew(draw_pos + 2 * j,
1078                                             scp->ega_palette[0]);
1079                                 break;
1080                         }
1081                 }
1082
1083                 draw_pos += line_width;
1084         }
1085 }
1086
1087 static void
1088 draw_pxlmouse_packed(scr_stat *scp, int x, int y)
1089 {
1090         int line_width;
1091         int xend, yend;
1092         int i, j;
1093         vm_offset_t draw_pos;
1094
1095         line_width = scp->sc->adp->va_line_width;
1096
1097         xend = imin(8 * (scp->xoff + scp->xsize), imin(x + 16, scp->xpixel));
1098         yend = imin(scp->font_size * (scp->yoff + scp->ysize),
1099             imin(y + 16, scp->ypixel));
1100
1101         draw_pos = scp->sc->adp->va_window + y * line_width + x;
1102
1103         for (i = 0; i < (yend - y); i++) {
1104                 for (j = (xend - x - 1); j >= 0; j--) {
1105                         if (mouse_or_mask[i] & 1 << (15 - j))
1106                                 writeb(draw_pos + j, 15);
1107                         else if (mouse_and_mask[i] & 1 << (15 - j))
1108                                 writeb(draw_pos + j, 0);
1109                 }
1110
1111                 draw_pos += line_width;
1112         }
1113 }
1114
1115 static void
1116 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1117 {
1118         vm_offset_t p;
1119         int line_width;
1120         int xoff;
1121         int ymax;
1122         u_short m;
1123         int i, j;
1124
1125         line_width = scp->sc->adp->va_line_width;
1126         xoff = (x - scp->xoff*8)%8;
1127         ymax = imin(y + 16, scp->font_size * (scp->yoff + scp->ysize));
1128
1129         outw(GDCIDX, 0x0805);           /* read mode 1, write mode 0 */
1130         outw(GDCIDX, 0x0001);           /* set/reset enable */
1131         outw(GDCIDX, 0x0002);           /* color compare */
1132         outw(GDCIDX, 0x0007);           /* color don't care */
1133         outw(GDCIDX, 0xff08);           /* bit mask */
1134         outw(GDCIDX, 0x0803);           /* data rotate/function select (and) */
1135         p = scp->sc->adp->va_window + line_width*y + x/8;
1136         if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1137                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1138                         m = ~(mouse_and_mask[j] >> xoff);
1139                         *(u_char *)p &= m >> 8;
1140                         *(u_char *)(p + 1) &= m;
1141                         p += line_width;
1142                 }
1143         } else {
1144                 xoff += 8;
1145                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1146                         m = ~(mouse_and_mask[j] >> xoff);
1147                         *(u_char *)p &= m;
1148                         p += line_width;
1149                 }
1150         }
1151         outw(GDCIDX, 0x1003);           /* data rotate/function select (or) */
1152         p = scp->sc->adp->va_window + line_width*y + x/8;
1153         if (x < 8 * (scp->xoff + scp->xsize) - 8) {
1154                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1155                         m = mouse_or_mask[j] >> xoff;
1156                         *(u_char *)p &= m >> 8;
1157                         *(u_char *)(p + 1) &= m;
1158                         p += line_width;
1159                 }
1160         } else {
1161                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1162                         m = mouse_or_mask[j] >> xoff;
1163                         *(u_char *)p &= m;
1164                         p += line_width;
1165                 }
1166         }
1167         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
1168         outw(GDCIDX, 0x0003);           /* data rotate/function select */
1169 }
1170
1171 static void
1172 remove_pxlmouse(scr_stat *scp, int x, int y)
1173 {
1174         int col, row;
1175         int pos;
1176         int i;
1177
1178         /* erase the mouse cursor image */
1179         col = x/8 - scp->xoff;
1180         row = y/scp->font_size - scp->yoff;
1181         pos = row*scp->xsize + col;
1182         i = (col < scp->xsize - 1) ? 2 : 1;
1183         (*scp->rndr->draw)(scp, pos, i, FALSE);
1184         if (row < scp->ysize - 1)
1185                 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1186 }
1187
1188 static void 
1189 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1190 {
1191         if (on)
1192                 draw_pxlmouse_direct(scp, x, y);
1193         else
1194                 remove_pxlmouse(scp, x, y);
1195 }
1196
1197 static void
1198 vga_pxlmouse_packed(scr_stat *scp, int x, int y, int on)
1199 {
1200         if (on)
1201                 draw_pxlmouse_packed(scp, x, y);
1202         else
1203                 remove_pxlmouse(scp, x, y);
1204 }
1205
1206 static void 
1207 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1208 {
1209         if (on)
1210                 draw_pxlmouse_planar(scp, x, y);
1211         else
1212                 remove_pxlmouse(scp, x, y);
1213 }
1214
1215 #endif /* SC_NO_CUTPASTE */
1216 #endif /* SC_PIXEL_MODE */
1217
1218 #ifndef SC_NO_MODE_CHANGE
1219
1220 /* graphics mode renderer */
1221
1222 static void
1223 vga_grborder(scr_stat *scp, int color)
1224 {
1225         lwkt_gettoken(&tty_token);
1226         (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
1227         lwkt_reltoken(&tty_token);
1228 }
1229
1230 #endif