Remove DEC Alpha support.
[dragonfly.git] / sys / dev / video / fb / gfb.c
1 /*-
2  * Copyright (c) 2001 Andrew Miklic
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/dev/fb/gfb.c,v 1.1.2.1 2001/11/01 08:33:14 obrien Exp $
27  * $DragonFly: src/sys/dev/video/fb/Attic/gfb.c,v 1.6 2005/04/30 23:04:21 swildner Exp $
28  */
29 /*
30  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
31  * All rights reserved.
32  *
33  * Author: Chris G. Demetriou
34  * 
35  * Permission to use, copy, modify and distribute this software and
36  * its documentation is hereby granted, provided that both the copyright
37  * notice and this permission notice appear in all copies of the
38  * software, derivative works or modified versions, and any portions
39  * thereof, and that both notices appear in supporting documentation.
40  * 
41  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
42  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
43  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
44  * 
45  * Carnegie Mellon requests users of this software to return to
46  *
47  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
48  *  School of Computer Science
49  *  Carnegie Mellon University
50  *  Pittsburgh PA 15213-3890
51  *
52  * any improvements or extensions that they make and grant Carnegie the
53  * rights to redistribute these changes.
54  */
55
56 #include <machine/stdarg.h>
57
58 #include <sys/param.h>
59 #include <sys/systm.h>
60 #include <sys/kernel.h>
61 #include <sys/conf.h>
62 #include <sys/proc.h>
63 #include <sys/fcntl.h>
64 #include <sys/malloc.h>
65 #include <sys/fbio.h>
66
67 #include <vm/vm.h>
68 #include <vm/vm_param.h>
69 #include <vm/pmap.h>
70
71 #include <machine/md_var.h>
72 #include <machine/pc/bios.h>
73 #include <machine/clock.h>
74 #include <machine/bus_memio.h>
75 #include <machine/bus.h>
76 #include <machine/pc/vesa.h>
77 #include <machine/resource.h>
78 #include <machine/rpb.h>
79
80 #include <sys/bus.h>
81 #include <sys/rman.h>
82
83 #include <bus/pci/pcireg.h>
84 #include <bus/pci/pcivar.h>
85
86 #include "fbreg.h"
87 #include "gfb.h"
88 #include <dev/gfb/gfb_pci.h>
89
90 #include "opt_gfb.h"
91
92 struct gfb_softc *gfb_device_softcs[2][MAX_NUM_GFB_CARDS] = {
93         {
94                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
95                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
96         },
97         {
98                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
99                 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
100         },
101 };
102
103 /*
104    The following 9 variables exist only because we need statically
105    allocated structures very early in boot to support gfb_configure()...
106 */
107 struct gfb_softc console;
108 video_adapter_t console_adp;
109 struct gfb_conf console_gfbc;
110 u_char console_palette_red[256];
111 u_char console_palette_green[256];
112 u_char console_palette_blue[256];
113 u_char console_cursor_palette_red[3];
114 u_char console_cursor_palette_green[3];
115 u_char console_cursor_palette_blue[3];
116
117 extern struct gfb_font bold8x16;
118
119 /*****************************************************************************
120  *
121  * FB-generic functions
122  *
123  ****************************************************************************/
124
125 int
126 gfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
127 {
128         int error;
129
130         /* Assume the best... */
131         error = 0;
132
133         if((*adpp = vid_get_adapter(vid_find_adapter((char *)arg, unit))) == NULL)
134                 error = ENODEV;
135         else
136                 (*adpp)->va_flags |= V_ADP_PROBED;
137
138         return(error);
139 }
140
141 int
142 gfb_init(int unit, video_adapter_t *adp, int flags)
143 {
144         struct gfb_softc *sc;
145         struct gfb_conf *gfbc;
146         int error;
147
148         /* Assume the best... */
149         error = 0;
150
151         if(!init_done(adp)) {
152                 sc = gfb_device_softcs[adp->va_model][unit];
153                 gfbc = sc->gfbc;
154
155                 /* Initialize the RAMDAC... */
156                 (*gfbc->ramdac_init)(sc);
157
158                 /* Initialize the palettes... */
159                 (*gfbc->ramdac_load_palette)(sc->adp, &sc->gfbc->palette);
160                 (*gfbc->ramdac_load_cursor_palette)(sc->adp,
161                     &sc->gfbc->cursor_palette);
162
163                 /* Prepare the default font... */
164                 (*vidsw[adp->va_index]->load_font)(adp, 0, bold8x16.height,
165                     bold8x16.data, 0, 256);
166                 adp->va_info.vi_cwidth = gfbc->fonts[0].width;
167                 adp->va_info.vi_cheight = gfbc->fonts[0].height;
168
169                 /*
170                    Normalize vi_width and vi_height to be in terms of
171                    on-screen characters, rather than pixels (*_init()
172                    leaves them in terms of pixels...
173                 */
174                 adp->va_info.vi_width /= adp->va_info.vi_cwidth;
175                 adp->va_info.vi_height /= adp->va_info.vi_cheight;
176
177                 /* Enable the default font... */
178                 (*vidsw[adp->va_index]->show_font)(adp, 0);
179
180                 /* Enable future font-loading... */
181                 adp->va_flags |= V_ADP_FONT;
182
183                 /* Flag this initialization for this adapter... */      
184                 adp->va_flags |= V_ADP_INITIALIZED;
185         }
186         return(error);
187 }
188
189 int
190 gfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
191 {
192         int error;
193
194         /* Assume the best... */
195         error = 0;
196
197         /*
198            The info for GFB adapters does not depend on its mode,
199            so just copy it indiscriminantly (actually, we originally
200            checked the mode, but the current fb framework is somewhat
201            sloppily done in places, and assumes VGA in several places,
202            which makes such checks always fail for such GFBs as TGA)...
203         */
204         bcopy(&adp->va_info, info, sizeof(video_info_t));
205         return(error);
206 }
207
208 int
209 gfb_set_mode(video_adapter_t *adp, int mode)
210 {
211
212         adp->va_mode = mode;
213         return(0);
214 }
215
216 int
217 gfb_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
218     int ch, int count)
219 {
220         struct gfb_softc *sc;
221         int error;
222         int i;
223
224         error = 0;
225         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
226
227         /* Check the font information... */
228         if((sc->gfbc->fonts[page].height != fontsize) ||
229            (sc->gfbc->fonts[page].width != 8))
230                 error = EINVAL;
231         else
232
233                 /*
234                    Copy the character pixel array from our
235                    very own private cache...
236                 */
237                 for(i = ch; i < count * fontsize; i++)
238                         data[i] = adp->va_little_bitian ?
239                             BIT_REVERSE(sc->gfbc->fonts[page].data[i]) :
240                             sc->gfbc->fonts[page].data[i];
241
242         return(error);
243 }
244
245 int
246 gfb_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
247     int ch, int count)
248 {
249         struct gfb_softc *sc;
250         int error;
251         int i;
252
253         error = 0;
254         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
255
256         /* Copy the character pixel array into our very own private cache... */
257         for(i = ch; i < count * fontsize; i++)
258                 sc->gfbc->fonts[page].data[i] = adp->va_little_bitian ?
259                     BIT_REVERSE(data[i]) : data[i];
260
261         /* Save the font information... */
262         sc->gfbc->fonts[page].height = fontsize;
263         sc->gfbc->fonts[page].width = 8;
264
265         return(error);
266 }
267
268 int
269 gfb_show_font(video_adapter_t *adp, int page)
270 {
271         struct gfb_softc *sc;
272         int error;
273
274         error = 0;
275         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
276
277         /* Normalize adapter values... */
278         adp->va_info.vi_height *= adp->va_info.vi_cheight;
279         adp->va_info.vi_width *= adp->va_info.vi_cwidth;
280
281         /* Set the current font pixels... */
282         sc->gfbc->font = sc->gfbc->fonts[page].data;
283
284         /* Set the current font width... */
285         adp->va_info.vi_cwidth = sc->gfbc->fonts[page].width;
286
287         /* Set the current font height... */
288         adp->va_info.vi_cheight = sc->gfbc->fonts[page].height;
289
290         /* Recompute adapter values... */
291         adp->va_info.vi_height /= adp->va_info.vi_cheight;
292         adp->va_info.vi_width /= adp->va_info.vi_cwidth;
293
294         return(error);
295 }
296
297 int
298 gfb_save_palette(video_adapter_t *adp, u_char *palette)
299 {
300         struct gfb_softc *sc;
301         int error;
302         int i;
303
304         error = 0;
305         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
306
307 #if 0
308         /* If we have a RAMDAC-specific counterpart, use it... */
309         if(sc->gfbc->ramdac_save_palette)
310                 error = sc->gfbc->ramdac_save_palette(adp, &sc->gfbc->palette);
311
312         else
313                 /* Otherwise, use the built-in functionality... */
314                 error = sc->gfbc->builtin_save_palette(adp, &sc->gfbc->palette);
315 #endif
316
317         for(i = 0; i < sc->gfbc->palette.count; i++) {
318                 palette[(3 * i)] = sc->gfbc->palette.red[i];
319                 palette[(3 * i) + 1] = sc->gfbc->palette.green[i];
320                 palette[(3 * i) + 2] = sc->gfbc->palette.blue[i];
321         }
322         return(error);
323 }
324
325 int
326 gfb_load_palette(video_adapter_t *adp, const u_char *palette)
327 {
328         struct gfb_softc *sc;
329         int error;
330         int i;
331
332         error = 0;
333         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
334
335         for(i = 0; i < sc->gfbc->palette.count; i++) {
336                 sc->gfbc->palette.red[i] = palette[(3 * i)];
337                 sc->gfbc->palette.green[i] = palette[(3 * i) + 1];
338                 sc->gfbc->palette.blue[i] = palette[(3 * i) + 2];
339         }
340
341         /* If we have a RAMDAC-specific counterpart, use it... */
342         if(sc->gfbc->ramdac_load_palette)
343                 error = sc->gfbc->ramdac_load_palette(adp, &sc->gfbc->palette);
344         else
345                 /* Otherwise, use the built-in functionality... */
346                 error = sc->gfbc->builtin_load_palette(adp, &sc->gfbc->palette);
347
348         return(error);
349 }
350
351 int
352 gfb_set_border(video_adapter_t *adp, int color)
353 {
354
355         return(ENODEV);
356 }
357
358 int
359 gfb_save_state(video_adapter_t *adp, void *p, size_t size)
360 {
361         int i;
362         u_int32_t *regs;
363
364         regs = (u_int32_t *)p;
365         regs[0] = size;
366         for(i = 1; i <= size; i++)
367                 regs[i] = READ_GFB_REGISTER(adp, i);
368         return(0);
369 }
370
371 int
372 gfb_load_state(video_adapter_t *adp, void *p)
373 {
374         size_t size;
375         int i;
376         u_int32_t *regs;
377
378         regs = (u_int32_t *)p;
379         size = regs[0];
380         for(i = 1; i <= size; i++)
381                 WRITE_GFB_REGISTER(adp, i, regs[i]);
382         return(0);
383 }
384
385 int
386 gfb_set_win_org(video_adapter_t *adp, off_t offset)
387 {
388
389         adp->va_window_orig = offset;
390         return(0);
391 }
392
393 int
394 gfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
395 {
396         struct gfb_softc *sc;
397         int error;
398
399         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
400
401         /* If we have a RAMDAC-specific counterpart, use it... */
402         if(sc->gfbc->ramdac_read_hw_cursor)
403                 error = sc->gfbc->ramdac_read_hw_cursor(adp, col, row);
404         else
405                 /* Otherwise, use the built-in functionality... */
406                 error = sc->gfbc->builtin_read_hw_cursor(adp, col, row);
407
408         return(error);
409 }
410
411 int
412 gfb_set_hw_cursor(adp, col, row)
413         video_adapter_t *adp;
414         int col;
415         int row;
416 {
417         int error;
418         struct gfb_softc *sc;
419
420         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
421
422         /* If we have a RAMDAC-specific counterpart, use it... */
423         if(sc->gfbc->ramdac_set_hw_cursor)
424                 error = sc->gfbc->ramdac_set_hw_cursor(adp, col, row);
425
426         /* Otherwise, use the built-in functionality... */
427         else
428                 error = sc->gfbc->builtin_set_hw_cursor(adp, col, row);
429         return(error);
430 }
431
432 int
433 gfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
434     int cellsize, int blink)
435 {
436         struct gfb_softc *sc;
437         int error;
438
439         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
440
441         /* If we have a RAMDAC-specific counterpart, use it... */
442         if(sc->gfbc->ramdac_set_hw_cursor_shape)
443                 error = sc->gfbc->ramdac_set_hw_cursor_shape(adp, base, height,
444                     cellsize, blink);
445         else
446                 /* Otherwise, use the built-in functionality... */
447                 error = sc->gfbc->builtin_set_hw_cursor_shape(adp, base,
448                     height, cellsize, blink);
449
450         return(error);
451 }
452
453 int
454 gfb_mmap(video_adapter_t *adp, vm_offset_t offset, int prot)
455 {
456         int error;
457
458         if(offset > adp->va_window_size - PAGE_SIZE)
459                 error = ENXIO;
460 #ifdef __i386__
461         error = i386_btop(adp->va_info.vi_window + offset);
462 #else
463         error = ENXIO;
464 #endif
465         return(error);
466 }
467
468 int
469 gfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
470 {
471         struct gfb_softc *sc;
472         int error;
473
474         error = 0;
475         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
476
477         switch (cmd) {
478         case FBIOPUTCMAP:
479                 /* FALLTHROUGH */
480         case FBIO_GETWINORG:
481                 /* FALLTHROUGH */
482         case FBIO_SETWINORG:
483                 /* FALLTHROUGH */
484         case FBIO_SETDISPSTART:
485                 /* FALLTHROUGH */
486         case FBIO_SETLINEWIDTH:
487                 /* FALLTHROUGH */
488         case FBIO_GETPALETTE:
489                 /* FALLTHROUGH */
490         case FBIOGTYPE:
491                 /* FALLTHROUGH */
492         case FBIOGETCMAP:
493                 /* FALLTHROUGH */
494         default:
495                 error = fb_commonioctl(adp, cmd, arg); 
496         }
497         return(error);
498 }
499
500 int
501 gfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
502 {
503         int off;
504
505         /*
506            Just traverse the buffer, one pixel span at a time, setting
507            each pixel to the block-color...
508         */
509         for(off = (x * y); off < ((x + cx) * (y + cy)); off++)
510                 (*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff,
511                     sizeof(u_int32_t), 1, 0, 0);
512
513         return(0);
514 }
515
516 int
517 gfb_bitblt(video_adapter_t *adp, ...)
518 {
519         __va_list args;
520         vm_offset_t src, dst;
521         int count, i;
522         u_int32_t val;
523
524         __va_start(args, adp);
525
526         src = (__va_arg(args, vm_offset_t) + adp->va_window_orig) &
527             0x0000000000fffff8;
528         dst = (__va_arg(args, vm_offset_t) + adp->va_window_orig) &
529             0x0000000000fffff8;
530         count = __va_arg(args, int);
531         for(i = 0; i < count; i++, src++, dst++) {
532                 val = READ_GFB_BUFFER(adp, src);
533                 WRITE_GFB_BUFFER(adp, dst, val);
534         }
535         __va_end(args);
536         return(0);
537 }
538
539 int
540 /*gfb_clear(video_adapter_t *adp, int n)*/
541 gfb_clear(video_adapter_t *adp)
542         video_adapter_t *adp;
543 {
544         int off;
545
546 #if 0
547         if(n == 0)
548                 return(0);
549 #endif
550
551         /*
552            Just traverse the buffer, one 2K-pixel span at a time, clearing
553            each pixel...
554         */
555         /* for(off = 0; off < (n * adp->va_line_width); off += (2 KB)) */
556         for(off = 0; off < adp->va_window_size; off++)
557                 (*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff,
558                     sizeof(u_int32_t), 1, 0, 0);
559
560         return(0);
561 }
562
563 int
564 gfb_diag(video_adapter_t *adp, int level)
565 {
566         video_info_t info;
567         struct gfb_softc *sc;
568         int error;
569
570         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
571
572         /* Just dump everything we know about the adapter to the screen... */
573         fb_dump_adp_info(sc->driver_name, adp, level);
574
575         /* Try to get the info on this adapter... */
576         if(!(error = (*vidsw[adp->va_index]->get_info)(adp,
577             adp->va_initial_mode, &info)))
578                 /*
579                    Just dump everything we know about the adapter's mode
580                    to the screen...
581                 */
582                 fb_dump_mode_info(sc->driver_name, adp, &info, level);
583
584         return(error);
585 }
586
587 int
588 gfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
589 {
590         struct gfb_softc *sc;
591         int error, i;
592
593         error = 0;
594         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
595
596 #if 0
597         /* If we have a RAMDAC-specific counterpart, use it... */
598         if(sc->gfbc->ramdac_save_cursor_palette)
599                 error = sc->gfbc->ramdac_save_cursor_palette(adp,
600                     &sc->gfbc->cursor_palette);
601
602         else
603                 /* Otherwise, use the built-in functionality... */
604                 error = sc->gfbc->builtin_save_cursor_palette(adp,
605                     &sc->gfbc->cursor_palette);
606 #endif
607
608         for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
609                 palette[(3 * i)] = sc->gfbc->cursor_palette.red[i];
610                 palette[(3 * i) + 1] = sc->gfbc->cursor_palette.green[i];
611                 palette[(3 * i) + 2] = sc->gfbc->cursor_palette.blue[i];
612         }
613         return(error);
614 }
615
616 int
617 gfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
618 {
619         struct gfb_softc *sc;
620         int error, i;
621
622         error = 0;
623         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
624
625         for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
626                 sc->gfbc->cursor_palette.red[i] = palette[(3 * i)];
627                 sc->gfbc->cursor_palette.green[i] = palette[(3 * i) + 1];
628                 sc->gfbc->cursor_palette.blue[i] = palette[(3 * i) + 2];
629         }
630
631         /* If we have a RAMDAC-specific counterpart, use it... */
632         if(sc->gfbc->ramdac_load_cursor_palette)
633                 error = sc->gfbc->ramdac_load_cursor_palette(adp,
634                     &sc->gfbc->cursor_palette);
635         else
636                 /* Otherwise, use the built-in functionality... */
637                 error = sc->gfbc->builtin_load_cursor_palette(adp,
638                     &sc->gfbc->cursor_palette);
639
640         return(error);
641 }
642
643 int
644 gfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
645 {
646         int error, num_pixels;
647
648         if(n == 0)
649                 return(0);
650         num_pixels = adp->va_info.vi_cheight * adp->va_line_width;
651         error = (*vidsw[adp->va_index]->bitblt)(adp, src * num_pixels,
652             dst * num_pixels, n * num_pixels);
653         return(error);
654 }
655
656 int
657 gfb_putp(video_adapter_t *adp, vm_offset_t off, u_int32_t p, u_int32_t a,
658     int size, int bpp, int bit_ltor, int byte_ltor)
659 {
660         int i, j, k, num_shifts;
661         u_int32_t _p, val[32];
662
663         if(bpp < 1)
664                 return(-1);
665
666         /*
667             If we don't display bits right-to-left (little-bitian?),
668             then perform a bit-swap on p...
669         */
670         if(bit_ltor) {
671                 num_shifts = 8 * size;
672                 for(i = 0, _p = 0; i < num_shifts; i++, p >>= 1) {
673                         _p <<= 1;
674                         _p |= (p & 0x00000001);
675                 }
676         } else
677                 _p = p;
678
679         switch(bpp) {
680         /* Accelerate the simplest cases... */
681         case 1:
682                 if((a & 0x00000001) == 0)
683                         val[0] = 0;
684                 else if(size <= 0)
685                         val[0] = 0;
686                 else if(size == 1)
687                         val[0] = _p & 0x000000ff;
688                 else if(size == 2)
689                         val[0] = _p & 0x0000ffff;
690                 else if(size == 3)
691                         val[0] = _p & 0x00ffffff;
692                 else if(size == 4)
693                         val[0] = _p & 0xffffffff;
694                 break;
695
696         /* Only do the following if we are not a simple case... */
697         case 8:
698                 if(size > 0) {
699                         a &= 0x000000ff;
700                         val[0] = 0;
701                         if(_p & 0x00000001) val[0] |= (a);
702                         if(_p & 0x00000002) val[0] |= (a << 8);
703                         if(_p & 0x00000004) val[0] |= (a << 16);
704                         if(_p & 0x00000008) val[0] |= (a << 24);
705                         val[1] = 0;
706                         if(_p & 0x00000010) val[1] |= (a);
707                         if(_p & 0x00000020) val[1] |= (a << 8);
708                         if(_p & 0x00000040) val[1] |= (a << 16);
709                         if(_p & 0x00000080) val[1] |= (a << 24);
710                 }
711                 if(size > 1) {
712                         val[2] = 0;
713                         if(_p & 0x00000100) val[2] |= (a);
714                         if(_p & 0x00000200) val[2] |= (a << 8);
715                         if(_p & 0x00000400) val[2] |= (a << 16);
716                         if(_p & 0x00000800) val[2] |= (a << 24);
717                         val[3] = 0;
718                         if(_p & 0x00001000) val[3] |= (a);
719                         if(_p & 0x00002000) val[3] |= (a << 8);
720                         if(_p & 0x00004000) val[3] |= (a << 16);
721                         if(_p & 0x00008000) val[3] |= (a << 24);
722                 }       
723                 if(size > 2) {
724                         val[4] = 0;
725                         if(_p & 0x00010000) val[4] |= (a);
726                         if(_p & 0x00020000) val[4] |= (a << 8);
727                         if(_p & 0x00040000) val[4] |= (a << 16);
728                         if(_p & 0x00080000) val[4] |= (a << 24);
729                         val[5] = 0;
730                         if(_p & 0x00100000) val[5] |= (a);
731                         if(_p & 0x00200000) val[5] |= (a << 8);
732                         if(_p & 0x00400000) val[5] |= (a << 16);
733                         if(_p & 0x00800080) val[5] |= (a << 24);
734                 }
735                 if(size > 3) {
736                         val[6] = 0;
737                         if(_p & 0x01000000) val[6] |= (a);
738                         if(_p & 0x02000000) val[6] |= (a << 8);
739                         if(_p & 0x04000000) val[6] |= (a << 16);
740                         if(_p & 0x08000000) val[6] |= (a << 24);
741                         val[7] = 0;
742                         if(_p & 0x10000000) val[7] |= (a);
743                         if(_p & 0x20000000) val[7] |= (a << 8);
744                         if(_p & 0x40000000) val[7] |= (a << 16);
745                         if(_p & 0x80000000) val[7] |= (a << 24);
746                 }
747                 break;
748         case 16:
749                 if(size > 0) {
750                         a &= 0x0000ffff;
751                         if(_p & 0x00000001) val[0] |= (a);
752                         if(_p & 0x00000002) val[0] |= (a << 16);
753                         if(_p & 0x00000004) val[1] |= (a);
754                         if(_p & 0x00000008) val[1] |= (a << 16);
755                         if(_p & 0x00000010) val[2] |= (a);
756                         if(_p & 0x00000020) val[2] |= (a << 16);
757                         if(_p & 0x00000040) val[3] |= (a);
758                         if(_p & 0x00000080) val[3] |= (a << 16);
759                 }
760                 if(size > 1) {
761                         if(_p & 0x00000100) val[4] |= (a);
762                         if(_p & 0x00000200) val[4] |= (a << 16);
763                         if(_p & 0x00000400) val[5] |= (a);
764                         if(_p & 0x00000800) val[5] |= (a << 16);
765                         if(_p & 0x00001000) val[6] |= (a);
766                         if(_p & 0x00002000) val[6] |= (a << 16);
767                         if(_p & 0x00004000) val[7] |= (a);
768                         if(_p & 0x00008000) val[7] |= (a << 16);
769                 }
770                 if(size > 2) {
771                         if(_p & 0x00010000) val[8] |= (a);
772                         if(_p & 0x00020000) val[8] |= (a << 16);
773                         if(_p & 0x00040000) val[9] |= (a);
774                         if(_p & 0x00080000) val[9] |= (a << 16);
775                         if(_p & 0x00100000) val[10] |= (a);
776                         if(_p & 0x00200000) val[10] |= (a << 16);
777                         if(_p & 0x00400000) val[11] |= (a);
778                         if(_p & 0x00800000) val[11] |= (a << 16);
779                 }
780                 if(size > 3) {
781                         if(_p & 0x01000000) val[12] |= (a);
782                         if(_p & 0x02000000) val[12] |= (a << 16);
783                         if(_p & 0x04000000) val[13] |= (a);
784                         if(_p & 0x08000000) val[13] |= (a << 16);
785                         if(_p & 0x10000000) val[14] |= (a);
786                         if(_p & 0x20000000) val[14] |= (a << 16);
787                         if(_p & 0x40000000) val[15] |= (a);
788                         if(_p & 0x80000000) val[15] |= (a << 16);
789                 }
790                 break;
791         case 32:
792                 if(size > 0) {
793                         a &= 0xffffffff;
794                         if(_p & 0x00000001) val[0] = (a);
795                         if(_p & 0x00000002) val[1] = (a);
796                         if(_p & 0x00000004) val[2] = (a);
797                         if(_p & 0x00000008) val[3] = (a);
798                         if(_p & 0x00000010) val[4] = (a);
799                         if(_p & 0x00000020) val[5] = (a);
800                         if(_p & 0x00000040) val[6] = (a);
801                         if(_p & 0x00000080) val[7] = (a);
802                 }
803                 if(size > 1) {
804                         if(_p & 0x00000100) val[8] = (a);
805                         if(_p & 0x00000200) val[9] = (a);
806                         if(_p & 0x00000400) val[10] = (a);
807                         if(_p & 0x00000800) val[11] = (a);
808                         if(_p & 0x00001000) val[12] = (a);
809                         if(_p & 0x00002000) val[13] = (a);
810                         if(_p & 0x00004000) val[14] = (a);
811                         if(_p & 0x00008000) val[15] = (a);
812                 }
813                 if(size > 2) {
814                         if(_p & 0x00010000) val[16] = (a);
815                         if(_p & 0x00020000) val[17] = (a);
816                         if(_p & 0x00040000) val[18] = (a);
817                         if(_p & 0x00080000) val[19] = (a);
818                         if(_p & 0x00100000) val[20] = (a);
819                         if(_p & 0x00200000) val[21] = (a);
820                         if(_p & 0x00400000) val[22] = (a);
821                         if(_p & 0x00800000) val[23] = (a);
822                 }
823                 if(size > 3) {
824                         if(_p & 0x01000000) val[24] = (a);
825                         if(_p & 0x02000000) val[25] = (a);
826                         if(_p & 0x04000000) val[26] = (a);
827                         if(_p & 0x08000000) val[27] = (a);
828                         if(_p & 0x10000000) val[28] = (a);
829                         if(_p & 0x20000000) val[29] = (a);
830                         if(_p & 0x40000000) val[30] = (a);
831                         if(_p & 0x80000000) val[31] = (a);
832                 }
833                 break;
834         default:
835                 break;
836         }
837         j = (bpp == 1) ? 1 : bpp * size / sizeof(u_int32_t);
838
839         /*
840             If we don't display bytes right-to-left (little-endian),
841             then perform a byte-swap on p (we don't have to swap if
842             bpp == 1 and val[0] == 0)...
843         */
844         if((byte_ltor) && (j > 1) && (val[j] != 0)) {
845                 for(i = 0; i < (j - i); i++) {
846                         _p = val[j - i];
847                         val[j - i] = val[i];
848                         val[i] = _p;
849                 }
850                 for(i = 0; i < j; i++) {
851                         _p = val[i];
852                         for(k = 0, val[i] = 0; k < sizeof(u_int32_t);
853                             k++, _p >>= 8) {
854                                 val[i] <<= 8;
855                                 val[i] |= (_p & 0xff);
856                         }
857                 }
858         }
859
860         for(i = 0; i < j; i++) {
861                 /* Write the pixel-row... */
862                 WRITE_GFB_BUFFER(adp, (off + i), val[i]);
863         }
864         return(0);
865 }
866
867 int
868 gfb_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
869 {
870         vm_offset_t poff;
871         struct gfb_softc *sc;
872         int i, pixel_size;
873         u_int row, col;
874         u_int8_t *pixel;
875
876         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
877         pixel_size = adp->va_info.vi_depth / 8;
878
879         /* Get the start of the array of pixels rows for this character... */
880         pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight);
881
882         /* Calculate the new cursor position... */
883         row = off / adp->va_info.vi_width;
884         col = off % adp->va_info.vi_width;
885
886         /* Iterate over all the pixel rows for this character... */
887         for(i = 0; i < adp->va_info.vi_cheight; i++) {
888                 /* Get the address of the character's pixel-row... */
889                 poff = ((col * adp->va_info.vi_cwidth * pixel_size) +
890                     (((row * adp->va_info.vi_cheight) + i) *
891                     adp->va_line_width)) / sizeof(u_int32_t);
892
893                 /* Now display the current pixel row... */
894                 (*vidsw[adp->va_index]->putp)(adp, poff, pixel[i], a,
895                     sizeof(u_int8_t), 1, 1, 0);
896         }
897         return(0);
898 }
899
900 int
901 gfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
902 {
903         struct gfb_softc *sc;
904         int i;
905
906         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
907
908         /* If the string in empty, just return now... */
909         if(len == 0)
910                 return(0);
911
912         for(i = 0; i < len; i++)
913                 (*vidsw[adp->va_index]->putc)(adp, off + i, s[i] & 0x00ff,
914                     (s[i] & 0xff00) >> 8);
915
916         return(0);
917 }
918
919 int
920 gfb_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
921     u_int32_t pixel_mask, int size)
922 {
923         vm_offset_t poff;
924         int i, pixel_size;
925
926         pixel_size = adp->va_info.vi_depth / 8;
927
928         /* Iterate over all the pixel rows for the mouse pointer... */
929         for(i = 0; i < size; i++) {
930                 /* Get the address of the mouse pointer's pixel-row... */
931                 poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) /
932                     sizeof(u_int32_t);
933                 /* Now display the current pixel-row... */
934                 (*vidsw[adp->va_index]->putp)(adp, poff, pixel_image[i],
935                     pixel_mask, sizeof(u_int8_t), 1, 1, 0);
936         }
937
938         return(0);
939 }
940
941 int
942 gfb_error(void)
943 {
944
945         return(0);
946 }