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