]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - sys/dev/syscons/scvgarndr.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.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->font_size * line_width - scp->xsize;
717         }
718         outw(GDCIDX, 0x0000);           /* set/reset */
719         outw(GDCIDX, 0x0001);           /* set/reset enable */
720         outw(GDCIDX, 0xff08);           /* bit mask */
721 }
722
723 static void
724 vga_vgadraw_direct(scr_stat *scp, int from, int count, int flip)
725 {
726         vm_offset_t d = 0;
727         vm_offset_t e;
728         u_char *f;
729         u_short col1, col2, color;
730         int line_width, pixel_size;
731         int i, j, k;
732         int a;
733
734         line_width = scp->sc->adp->va_line_width;
735         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
736
737         d = VIDEO_MEMORY_POS(scp, from, 8 * pixel_size);
738
739         if (from + count > scp->xsize * scp->ysize)
740                 count = scp->xsize * scp->ysize - from;
741
742         for (i = from; count-- > 0; ++i) {
743                 a = sc_vtb_geta(&scp->vtb, i);
744
745                 if (flip) {
746                         col1 = (((a & 0x7000) >> 4) | (a & 0x0800)) >> 8;
747                         col2 = (((a & 0x8000) >> 4) | (a & 0x0700)) >> 8;
748                 } else {
749                         col1 = (a & 0x0f00) >> 8;
750                         col2 = (a & 0xf000) >> 12;
751                 }
752
753                 e = d;
754                 f = &(scp->font[sc_vtb_getc(&scp->vtb, i) * scp->font_size]);
755
756                 for (j = 0; j < scp->font_size; ++j, ++f) {
757                         for (k = 0; k < 8; ++k) {
758                                 color = *f & (1 << (7 - k)) ? col1 : col2;
759                                 vga_drawpxl(e + pixel_size * k, color);
760                         }
761
762                         e += line_width;
763                 }
764
765                 d += 8 * pixel_size;
766
767                 if ((i % scp->xsize) == scp->xsize - 1)
768                         d += scp->font_size * line_width -
769                             scp->xsize * 8 * pixel_size;
770         }
771 }
772
773 static void
774 vga_vgadraw_planar(scr_stat *scp, int from, int count, int flip)
775 {
776         vm_offset_t d;
777         vm_offset_t e;
778         u_char *f;
779         u_short bg;
780         u_short col1, col2;
781         int line_width;
782         int i, j;
783         int a;
784         u_char c;
785
786         d = VIDEO_MEMORY_POS(scp, from, 1);
787
788         line_width = scp->sc->adp->va_line_width;
789
790         outw(GDCIDX, 0x0305);           /* read mode 0, write mode 3 */
791         outw(GDCIDX, 0x0003);           /* data rotate/function select */
792         outw(GDCIDX, 0x0f01);           /* set/reset enable */
793         outw(GDCIDX, 0xff08);           /* bit mask */
794         bg = -1;
795         if (from + count > scp->xsize*scp->ysize)
796                 count = scp->xsize*scp->ysize - from;
797         for (i = from; count-- > 0; ++i) {
798                 a = sc_vtb_geta(&scp->vtb, i);
799                 if (flip) {
800                         col1 = ((a & 0x7000) >> 4) | (a & 0x0800);
801                         col2 = ((a & 0x8000) >> 4) | (a & 0x0700);
802                 } else {
803                         col1 = (a & 0x0f00);
804                         col2 = (a & 0xf000) >> 4;
805                 }
806                 /* set background color in EGA/VGA latch */
807                 if (bg != col2) {
808                         bg = col2;
809                         outw(GDCIDX, 0x0005);   /* read mode 0, write mode 0 */
810                         outw(GDCIDX, bg | 0x00); /* set/reset */
811                         writeb(d, 0);
812                         c = readb(d);           /* set bg color in the latch */
813                         outw(GDCIDX, 0x0305);   /* read mode 0, write mode 3 */
814                 }
815                 /* foreground color */
816                 outw(GDCIDX, col1 | 0x00);      /* set/reset */
817                 e = d;
818                 f = &(scp->font[sc_vtb_getc(&scp->vtb, i)*scp->font_size]);
819                 for (j = 0; j < scp->font_size; ++j, ++f) {
820                         writeb(e, *f);
821                         e += line_width;
822                 }
823                 ++d;
824                 if ((i % scp->xsize) == scp->xsize - 1)
825                         d += scp->font_size * line_width - scp->xsize;
826         }
827         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
828         outw(GDCIDX, 0x0000);           /* set/reset */
829         outw(GDCIDX, 0x0001);           /* set/reset enable */
830 }
831
832 static void 
833 vga_pxlcursor_shape(scr_stat *scp, int base, int height, int blink)
834 {
835         if (base < 0 || base >= scp->font_size)
836                 return;
837         /* the caller may set height <= 0 in order to disable the cursor */
838 #if 0
839         scp->curs_attr.base = base;
840         scp->curs_attr.height = height;
841 #endif
842 }
843
844 static void 
845 draw_pxlcursor_direct(scr_stat *scp, int at, int on, int flip)
846 {
847         vm_offset_t d = 0;
848         u_char *f;
849         int line_width, pixel_size;
850         int height;
851         int col1, col2, color;
852         int a;
853         int i, j;
854
855         line_width = scp->sc->adp->va_line_width;
856         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
857
858         d = VIDEO_MEMORY_POS(scp, at, 8 * pixel_size) +
859             (scp->font_size - scp->curs_attr.base - 1) * line_width;
860
861         a = sc_vtb_geta(&scp->vtb, at);
862
863         if (flip) {
864                 col1 = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
865                 col2 = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
866         } else {
867                 col1 = ((on) ? ((a & 0xf000) >> 4) : (a & 0x0f00)) >> 8;
868                 col2 = ((on) ? (a & 0x0f00) : ((a & 0xf000) >> 4)) >> 8;
869         }
870
871         f = &(scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_size +
872               scp->font_size - scp->curs_attr.base - 1]);
873
874         height = imin(scp->curs_attr.height, scp->font_size);
875
876         for (i = 0; i < height; ++i, --f) {
877                 for (j = 0; j < 8; ++j) {
878                         color = *f & (1 << (7 - j)) ? col1 : col2;
879                         vga_drawpxl(d + pixel_size * j, color);
880                 }
881
882                 d -= line_width;
883         }
884 }
885
886 static void 
887 draw_pxlcursor_planar(scr_stat *scp, int at, int on, int flip)
888 {
889         vm_offset_t d;
890         u_char *f;
891         int line_width;
892         int height;
893         int col;
894         int a;
895         int i;
896         u_char c;
897
898         line_width = scp->sc->adp->va_line_width;
899
900         d = VIDEO_MEMORY_POS(scp, at, 1) +
901             (scp->font_size - scp->curs_attr.base - 1) * line_width;
902
903         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
904         outw(GDCIDX, 0x0003);           /* data rotate/function select */
905         outw(GDCIDX, 0x0f01);           /* set/reset enable */
906         /* set background color in EGA/VGA latch */
907         a = sc_vtb_geta(&scp->vtb, at);
908         if (flip)
909                 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
910         else
911                 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
912         outw(GDCIDX, col | 0x00);       /* set/reset */
913         outw(GDCIDX, 0xff08);           /* bit mask */
914         writeb(d, 0);
915         c = readb(d);                   /* set bg color in the latch */
916         /* foreground color */
917         if (flip)
918                 col = (on) ? (a & 0x0f00) : ((a & 0xf000) >> 4);
919         else
920                 col = (on) ? ((a & 0xf000) >> 4) : (a & 0x0f00);
921         outw(GDCIDX, col | 0x00);       /* set/reset */
922         f = &(scp->font[sc_vtb_getc(&scp->vtb, at)*scp->font_size
923                 + scp->font_size - scp->curs_attr.base - 1]);
924         height = imin(scp->curs_attr.height, scp->font_size);
925         for (i = 0; i < height; ++i, --f) {
926                 outw(GDCIDX, (*f << 8) | 0x08); /* bit mask */
927                 writeb(d, 0);
928                 d -= line_width;
929         }
930         outw(GDCIDX, 0x0000);           /* set/reset */
931         outw(GDCIDX, 0x0001);           /* set/reset enable */
932         outw(GDCIDX, 0xff08);           /* bit mask */
933 }
934
935 static int pxlblinkrate = 0;
936
937 static void 
938 vga_pxlcursor_direct(scr_stat *scp, int at, int blink, int on, int flip)
939 {
940         if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
941                 return;
942
943         if (on) {
944                 if (!blink) {
945                         scp->status |= VR_CURSOR_ON;
946                         draw_pxlcursor_direct(scp, at, on, flip);
947                 } else if (++pxlblinkrate & 4) {
948                         pxlblinkrate = 0;
949                         scp->status ^= VR_CURSOR_ON;
950                         draw_pxlcursor_direct(scp, at,
951                                               scp->status & VR_CURSOR_ON,
952                                               flip);
953                 }
954         } else {
955                 if (scp->status & VR_CURSOR_ON)
956                         draw_pxlcursor_direct(scp, at, on, flip);
957                 scp->status &= ~VR_CURSOR_ON;
958         }
959         if (blink)
960                 scp->status |= VR_CURSOR_BLINK;
961         else
962                 scp->status &= ~VR_CURSOR_BLINK;
963 }
964
965 static void 
966 vga_pxlcursor_planar(scr_stat *scp, int at, int blink, int on, int flip)
967 {
968         if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
969                 return;
970
971         if (on) {
972                 if (!blink) {
973                         scp->status |= VR_CURSOR_ON;
974                         draw_pxlcursor_planar(scp, at, on, flip);
975                 } else if (++pxlblinkrate & 4) {
976                         pxlblinkrate = 0;
977                         scp->status ^= VR_CURSOR_ON;
978                         draw_pxlcursor_planar(scp, at,
979                                               scp->status & VR_CURSOR_ON,
980                                               flip);
981                 }
982         } else {
983                 if (scp->status & VR_CURSOR_ON)
984                         draw_pxlcursor_planar(scp, at, on, flip);
985                 scp->status &= ~VR_CURSOR_ON;
986         }
987         if (blink)
988                 scp->status |= VR_CURSOR_BLINK;
989         else
990                 scp->status &= ~VR_CURSOR_BLINK;
991 }
992
993 static void
994 vga_pxlblink_direct(scr_stat *scp, int at, int flip)
995 {
996         if (!(scp->status & VR_CURSOR_BLINK))
997                 return;
998         if (!(++pxlblinkrate & 4))
999                 return;
1000         pxlblinkrate = 0;
1001         scp->status ^= VR_CURSOR_ON;
1002         draw_pxlcursor_direct(scp, at, scp->status & VR_CURSOR_ON, flip);
1003 }
1004
1005 static void
1006 vga_pxlblink_planar(scr_stat *scp, int at, int flip)
1007 {
1008         if (!(scp->status & VR_CURSOR_BLINK))
1009                 return;
1010         if (!(++pxlblinkrate & 4))
1011                 return;
1012         pxlblinkrate = 0;
1013         scp->status ^= VR_CURSOR_ON;
1014         draw_pxlcursor_planar(scp, at, scp->status & VR_CURSOR_ON, flip);
1015 }
1016
1017 #ifndef SC_NO_CUTPASTE
1018
1019 static void
1020 draw_pxlmouse_planar(scr_stat *scp, int x, int y)
1021 {
1022         vm_offset_t p;
1023         int line_width;
1024         int xoff, yoff;
1025         int ymax;
1026         u_short m;
1027         int i, j;
1028
1029         line_width = scp->sc->adp->va_line_width;
1030         xoff = (x - scp->xoff*8)%8;
1031         yoff = y - (y/line_width)*line_width;
1032         ymax = imin(y + 16, scp->ypixel);
1033
1034         outw(GDCIDX, 0x0805);           /* read mode 1, write mode 0 */
1035         outw(GDCIDX, 0x0001);           /* set/reset enable */
1036         outw(GDCIDX, 0x0002);           /* color compare */
1037         outw(GDCIDX, 0x0007);           /* color don't care */
1038         outw(GDCIDX, 0xff08);           /* bit mask */
1039         outw(GDCIDX, 0x0803);           /* data rotate/function select (and) */
1040         p = scp->sc->adp->va_window + line_width*y + x/8;
1041         if (x < scp->xpixel - 8) {
1042                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1043                         m = ~(mouse_and_mask[j] >> xoff);
1044 #if defined(__i386__) || defined(__amd64__)
1045                         *(u_char *)p &= m >> 8;
1046                         *(u_char *)(p + 1) &= m;
1047 #else
1048                         writeb(p, readb(p) & (m >> 8));
1049                         writeb(p + 1, readb(p + 1) & (m >> 8));
1050 #endif
1051                         p += line_width;
1052                 }
1053         } else {
1054                 xoff += 8;
1055                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1056                         m = ~(mouse_and_mask[j] >> xoff);
1057 #if defined(__i386__) || defined(__amd64__)
1058                         *(u_char *)p &= m;
1059 #else
1060                         writeb(p, readb(p) & (m >> 8));
1061 #endif
1062                         p += line_width;
1063                 }
1064         }
1065         outw(GDCIDX, 0x1003);           /* data rotate/function select (or) */
1066         p = scp->sc->adp->va_window + line_width*y + x/8;
1067         if (x < scp->xpixel - 8) {
1068                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1069                         m = mouse_or_mask[j] >> xoff;
1070 #if defined(__i386__) || defined(__amd64__)
1071                         *(u_char *)p &= m >> 8;
1072                         *(u_char *)(p + 1) &= m;
1073 #else
1074                         writeb(p, readb(p) & (m >> 8));
1075                         writeb(p + 1, readb(p + 1) & (m >> 8));
1076 #endif
1077                         p += line_width;
1078                 }
1079         } else {
1080                 for (i = y, j = 0; i < ymax; ++i, ++j) {
1081                         m = mouse_or_mask[j] >> xoff;
1082 #if defined(__i386__) || defined(__amd64__)
1083                         *(u_char *)p &= m;
1084 #else
1085                         writeb(p, readb(p) & (m >> 8));
1086 #endif
1087                         p += line_width;
1088                 }
1089         }
1090         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
1091         outw(GDCIDX, 0x0003);           /* data rotate/function select */
1092 }
1093
1094 static void
1095 remove_pxlmouse_planar(scr_stat *scp, int x, int y)
1096 {
1097         vm_offset_t p;
1098         int col, row;
1099         int pos;
1100         int line_width;
1101         int ymax;
1102         int i;
1103
1104         /* erase the mouse cursor image */
1105         col = x/8 - scp->xoff;
1106         row = y/scp->font_size - scp->yoff;
1107         pos = row*scp->xsize + col;
1108         i = (col < scp->xsize - 1) ? 2 : 1;
1109         (*scp->rndr->draw)(scp, pos, i, FALSE);
1110         if (row < scp->ysize - 1)
1111                 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
1112
1113         /* paint border if necessary */
1114         line_width = scp->sc->adp->va_line_width;
1115         outw(GDCIDX, 0x0005);           /* read mode 0, write mode 0 */
1116         outw(GDCIDX, 0x0003);           /* data rotate/function select */
1117         outw(GDCIDX, 0x0f01);           /* set/reset enable */
1118         outw(GDCIDX, 0xff08);           /* bit mask */
1119         outw(GDCIDX, (scp->border << 8) | 0x00);        /* set/reset */
1120         if (row == scp->ysize - 1) {
1121                 i = (scp->ysize + scp->yoff)*scp->font_size;
1122                 ymax = imin(i + scp->font_size, scp->ypixel);
1123                 p = scp->sc->adp->va_window + i*line_width + scp->xoff + col;
1124                 if (col < scp->xsize - 1) {
1125                         for (; i < ymax; ++i) {
1126                                 writeb(p, 0);
1127                                 writeb(p + 1, 0);
1128                                 p += line_width;
1129                         }
1130                 } else {
1131                         for (; i < ymax; ++i) {
1132                                 writeb(p, 0);
1133                                 p += line_width;
1134                         }
1135                 }
1136         }
1137         if ((col == scp->xsize - 1) && (scp->xoff > 0)) {
1138                 i = (row + scp->yoff)*scp->font_size;
1139                 ymax = imin(i + scp->font_size*2, scp->ypixel);
1140                 p = scp->sc->adp->va_window + i*line_width
1141                         + scp->xoff + scp->xsize;
1142                 for (; i < ymax; ++i) {
1143                         writeb(p, 0);
1144                         p += line_width;
1145                 }
1146         }
1147         outw(GDCIDX, 0x0000);           /* set/reset */
1148         outw(GDCIDX, 0x0001);           /* set/reset enable */
1149 }
1150
1151 static void 
1152 vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on)
1153 {
1154         vm_offset_t p;
1155         int line_width, pixel_size;
1156         int xend, yend;
1157         static int x_old = 0, xend_old = 0;
1158         static int y_old = 0, yend_old = 0;
1159         int i, j;
1160         uint32_t *u32;
1161         uint16_t *u16;
1162         uint8_t  *u8;
1163         int bpp;
1164
1165         if (!on)
1166                 return;
1167
1168         bpp = scp->sc->adp->va_info.vi_depth;
1169
1170         if ((bpp == 16) && (scp->sc->adp->va_info.vi_pixel_fsizes[1] == 5))
1171                 bpp = 15;
1172
1173         line_width = scp->sc->adp->va_line_width;
1174         pixel_size = scp->sc->adp->va_info.vi_pixel_size;
1175
1176         xend = imin(x + 16, scp->xpixel);
1177         yend = imin(y + 16, scp->ypixel);
1178
1179         p = scp->sc->adp->va_window + y_old * line_width + x_old * pixel_size;
1180
1181         for (i = 0; i < (yend_old - y_old); i++) {
1182                 for (j = (xend_old - x_old - 1); j >= 0; j--) {
1183                         switch (bpp) {
1184                         case 32:
1185                                 u32 = (uint32_t*)(p + j * pixel_size);
1186                                 writel(u32, mouse_buf32[i * 16 + j]);
1187                                 break;
1188                         case 16:
1189                                 /* FALLTHROUGH */
1190                         case 15:
1191                                 u16 = (uint16_t*)(p + j * pixel_size);
1192                                 writew(u16, mouse_buf16[i * 16 + j]);
1193                                 break;
1194                         case 8:
1195                                 u8 = (uint8_t*)(p + j * pixel_size);
1196                                 writeb(u8, mouse_buf8[i * 16 + j]);
1197                                 break;
1198                         }
1199                 }
1200
1201                 p += line_width;
1202         }
1203
1204         p = scp->sc->adp->va_window + y * line_width + x * pixel_size;
1205
1206         for (i = 0; i < (yend - y); i++) {
1207                 for (j = (xend - x - 1); j >= 0; j--) {
1208                         switch (bpp) {
1209                         case 32:
1210                                 u32 = (uint32_t*)(p + j * pixel_size);
1211                                 mouse_buf32[i * 16 + j] = *u32;
1212                                 if (mouse_or_mask[i] & (1 << (15 - j)))
1213                                         writel(u32, vga_palette32[15]);
1214                                 else if (mouse_and_mask[i] & (1 << (15 - j)))
1215                                         writel(u32, 0);
1216                                 break;
1217                         case 16:
1218                                 u16 = (uint16_t*)(p + j * pixel_size);
1219                                 mouse_buf16[i * 16 + j] = *u16;
1220                                 if (mouse_or_mask[i] & (1 << (15 - j)))
1221                                         writew(u16, vga_palette16[15]);
1222                                 else if (mouse_and_mask[i] & (1 << (15 - j)))
1223                                         writew(u16, 0);
1224                                 break;
1225                         case 15:
1226                                 u16 = (uint16_t*)(p  + j * pixel_size);
1227                                 mouse_buf16[i * 16 + j] = *u16;
1228                                 if (mouse_or_mask[i] & (1 << (15 - j)))
1229                                         writew(u16, vga_palette15[15]);
1230                                 else if (mouse_and_mask[i] & (1 << (15 - j)))
1231                                         writew(u16, 0);
1232                                 break;
1233                         case 8:
1234                                 u8 = (uint8_t*)(p + j * pixel_size);
1235                                 mouse_buf8[i * 16 + j] = *u8;
1236                                 if (mouse_or_mask[i] & (1 << (15 - j)))
1237                                         writeb(u8, 15);
1238                                 else if (mouse_and_mask[i] & (1 << (15 - j)))
1239                                         writeb(u8, 0);
1240                                 break;
1241                         }
1242                 }
1243
1244                 p += line_width;
1245         }
1246
1247         x_old = x;
1248         y_old = y;
1249         xend_old = xend;
1250         yend_old = yend;
1251 }
1252
1253 static void 
1254 vga_pxlmouse_planar(scr_stat *scp, int x, int y, int on)
1255 {
1256         if (on)
1257                 draw_pxlmouse_planar(scp, x, y);
1258         else
1259                 remove_pxlmouse_planar(scp, x, y);
1260 }
1261
1262 #endif /* SC_NO_CUTPASTE */
1263 #endif /* SC_PIXEL_MODE */
1264
1265 #ifndef SC_NO_MODE_CHANGE
1266
1267 /* graphics mode renderer */
1268
1269 static void
1270 vga_grborder(scr_stat *scp, int color)
1271 {
1272         vidd_set_border(scp->sc->adp, color);
1273 }
1274
1275 #endif