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