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