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