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