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