5203e5665ca41c281dd57f4712d73c86dec09328
[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.5 2005/02/01 16:30:02 joerg 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 #elsif defined(__alpha__)
463         error = alpha_btop(adp->va_info.vi_window + offset);
464 #else
465         error = ENXIO;
466 #endif
467         return(error);
468 }
469
470 int
471 gfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
472 {
473         struct gfb_softc *sc;
474         int error;
475
476         error = 0;
477         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
478
479         switch (cmd) {
480         case FBIOPUTCMAP:
481                 /* FALLTHROUGH */
482         case FBIO_GETWINORG:
483                 /* FALLTHROUGH */
484         case FBIO_SETWINORG:
485                 /* FALLTHROUGH */
486         case FBIO_SETDISPSTART:
487                 /* FALLTHROUGH */
488         case FBIO_SETLINEWIDTH:
489                 /* FALLTHROUGH */
490         case FBIO_GETPALETTE:
491                 /* FALLTHROUGH */
492         case FBIOGTYPE:
493                 /* FALLTHROUGH */
494         case FBIOGETCMAP:
495                 /* FALLTHROUGH */
496         default:
497                 error = fb_commonioctl(adp, cmd, arg); 
498         }
499         return(error);
500 }
501
502 int
503 gfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
504 {
505         int off;
506
507         /*
508            Just traverse the buffer, one pixel span at a time, setting
509            each pixel to the block-color...
510         */
511         for(off = (x * y); off < ((x + cx) * (y + cy)); off++)
512                 (*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff,
513                     sizeof(u_int32_t), 1, 0, 0);
514
515         return(0);
516 }
517
518 int
519 gfb_bitblt(video_adapter_t *adp, ...)
520 {
521         __va_list args;
522         vm_offset_t src, dst;
523         int count, i;
524         u_int32_t val;
525
526         __va_start(args, adp);
527
528         src = (__va_arg(args, vm_offset_t) + adp->va_window_orig) &
529             0x0000000000fffff8;
530         dst = (__va_arg(args, vm_offset_t) + adp->va_window_orig) &
531             0x0000000000fffff8;
532         count = __va_arg(args, int);
533         for(i = 0; i < count; i++, src++, dst++) {
534                 val = READ_GFB_BUFFER(adp, src);
535                 WRITE_GFB_BUFFER(adp, dst, val);
536         }
537         __va_end(args);
538         return(0);
539 }
540
541 int
542 /*gfb_clear(video_adapter_t *adp, int n)*/
543 gfb_clear(video_adapter_t *adp)
544         video_adapter_t *adp;
545 {
546         int off;
547
548 #if 0
549         if(n == 0)
550                 return(0);
551 #endif
552
553         /*
554            Just traverse the buffer, one 2K-pixel span at a time, clearing
555            each pixel...
556         */
557         /* for(off = 0; off < (n * adp->va_line_width); off += (2 KB)) */
558         for(off = 0; off < adp->va_window_size; off++)
559                 (*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff,
560                     sizeof(u_int32_t), 1, 0, 0);
561
562         return(0);
563 }
564
565 int
566 gfb_diag(video_adapter_t *adp, int level)
567 {
568         video_info_t info;
569         struct gfb_softc *sc;
570         int error;
571
572         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
573
574         /* Just dump everything we know about the adapter to the screen... */
575         fb_dump_adp_info(sc->driver_name, adp, level);
576
577         /* Try to get the info on this adapter... */
578         if(!(error = (*vidsw[adp->va_index]->get_info)(adp,
579             adp->va_initial_mode, &info)))
580                 /*
581                    Just dump everything we know about the adapter's mode
582                    to the screen...
583                 */
584                 fb_dump_mode_info(sc->driver_name, adp, &info, level);
585
586         return(error);
587 }
588
589 int
590 gfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
591 {
592         struct gfb_softc *sc;
593         int error, i;
594
595         error = 0;
596         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
597
598 #if 0
599         /* If we have a RAMDAC-specific counterpart, use it... */
600         if(sc->gfbc->ramdac_save_cursor_palette)
601                 error = sc->gfbc->ramdac_save_cursor_palette(adp,
602                     &sc->gfbc->cursor_palette);
603
604         else
605                 /* Otherwise, use the built-in functionality... */
606                 error = sc->gfbc->builtin_save_cursor_palette(adp,
607                     &sc->gfbc->cursor_palette);
608 #endif
609
610         for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
611                 palette[(3 * i)] = sc->gfbc->cursor_palette.red[i];
612                 palette[(3 * i) + 1] = sc->gfbc->cursor_palette.green[i];
613                 palette[(3 * i) + 2] = sc->gfbc->cursor_palette.blue[i];
614         }
615         return(error);
616 }
617
618 int
619 gfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
620 {
621         struct gfb_softc *sc;
622         int error, i;
623
624         error = 0;
625         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
626
627         for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
628                 sc->gfbc->cursor_palette.red[i] = palette[(3 * i)];
629                 sc->gfbc->cursor_palette.green[i] = palette[(3 * i) + 1];
630                 sc->gfbc->cursor_palette.blue[i] = palette[(3 * i) + 2];
631         }
632
633         /* If we have a RAMDAC-specific counterpart, use it... */
634         if(sc->gfbc->ramdac_load_cursor_palette)
635                 error = sc->gfbc->ramdac_load_cursor_palette(adp,
636                     &sc->gfbc->cursor_palette);
637         else
638                 /* Otherwise, use the built-in functionality... */
639                 error = sc->gfbc->builtin_load_cursor_palette(adp,
640                     &sc->gfbc->cursor_palette);
641
642         return(error);
643 }
644
645 int
646 gfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
647 {
648         int error, num_pixels;
649
650         if(n == 0)
651                 return(0);
652         num_pixels = adp->va_info.vi_cheight * adp->va_line_width;
653         error = (*vidsw[adp->va_index]->bitblt)(adp, src * num_pixels,
654             dst * num_pixels, n * num_pixels);
655         return(error);
656 }
657
658 int
659 gfb_putp(video_adapter_t *adp, vm_offset_t off, u_int32_t p, u_int32_t a,
660     int size, int bpp, int bit_ltor, int byte_ltor)
661 {
662         int i, j, k, num_shifts;
663         u_int32_t _p, val[32];
664
665         if(bpp < 1)
666                 return(-1);
667
668         /*
669             If we don't display bits right-to-left (little-bitian?),
670             then perform a bit-swap on p...
671         */
672         if(bit_ltor) {
673                 num_shifts = 8 * size;
674                 for(i = 0, _p = 0; i < num_shifts; i++, p >>= 1) {
675                         _p <<= 1;
676                         _p |= (p & 0x00000001);
677                 }
678         } else
679                 _p = p;
680
681         switch(bpp) {
682         /* Accelerate the simplest cases... */
683         case 1:
684                 if((a & 0x00000001) == 0)
685                         val[0] = 0;
686                 else if(size <= 0)
687                         val[0] = 0;
688                 else if(size == 1)
689                         val[0] = _p & 0x000000ff;
690                 else if(size == 2)
691                         val[0] = _p & 0x0000ffff;
692                 else if(size == 3)
693                         val[0] = _p & 0x00ffffff;
694                 else if(size == 4)
695                         val[0] = _p & 0xffffffff;
696                 break;
697
698         /* Only do the following if we are not a simple case... */
699         case 8:
700                 if(size > 0) {
701                         a &= 0x000000ff;
702                         val[0] = 0;
703                         if(_p & 0x00000001) val[0] |= (a);
704                         if(_p & 0x00000002) val[0] |= (a << 8);
705                         if(_p & 0x00000004) val[0] |= (a << 16);
706                         if(_p & 0x00000008) val[0] |= (a << 24);
707                         val[1] = 0;
708                         if(_p & 0x00000010) val[1] |= (a);
709                         if(_p & 0x00000020) val[1] |= (a << 8);
710                         if(_p & 0x00000040) val[1] |= (a << 16);
711                         if(_p & 0x00000080) val[1] |= (a << 24);
712                 }
713                 if(size > 1) {
714                         val[2] = 0;
715                         if(_p & 0x00000100) val[2] |= (a);
716                         if(_p & 0x00000200) val[2] |= (a << 8);
717                         if(_p & 0x00000400) val[2] |= (a << 16);
718                         if(_p & 0x00000800) val[2] |= (a << 24);
719                         val[3] = 0;
720                         if(_p & 0x00001000) val[3] |= (a);
721                         if(_p & 0x00002000) val[3] |= (a << 8);
722                         if(_p & 0x00004000) val[3] |= (a << 16);
723                         if(_p & 0x00008000) val[3] |= (a << 24);
724                 }       
725                 if(size > 2) {
726                         val[4] = 0;
727                         if(_p & 0x00010000) val[4] |= (a);
728                         if(_p & 0x00020000) val[4] |= (a << 8);
729                         if(_p & 0x00040000) val[4] |= (a << 16);
730                         if(_p & 0x00080000) val[4] |= (a << 24);
731                         val[5] = 0;
732                         if(_p & 0x00100000) val[5] |= (a);
733                         if(_p & 0x00200000) val[5] |= (a << 8);
734                         if(_p & 0x00400000) val[5] |= (a << 16);
735                         if(_p & 0x00800080) val[5] |= (a << 24);
736                 }
737                 if(size > 3) {
738                         val[6] = 0;
739                         if(_p & 0x01000000) val[6] |= (a);
740                         if(_p & 0x02000000) val[6] |= (a << 8);
741                         if(_p & 0x04000000) val[6] |= (a << 16);
742                         if(_p & 0x08000000) val[6] |= (a << 24);
743                         val[7] = 0;
744                         if(_p & 0x10000000) val[7] |= (a);
745                         if(_p & 0x20000000) val[7] |= (a << 8);
746                         if(_p & 0x40000000) val[7] |= (a << 16);
747                         if(_p & 0x80000000) val[7] |= (a << 24);
748                 }
749                 break;
750         case 16:
751                 if(size > 0) {
752                         a &= 0x0000ffff;
753                         if(_p & 0x00000001) val[0] |= (a);
754                         if(_p & 0x00000002) val[0] |= (a << 16);
755                         if(_p & 0x00000004) val[1] |= (a);
756                         if(_p & 0x00000008) val[1] |= (a << 16);
757                         if(_p & 0x00000010) val[2] |= (a);
758                         if(_p & 0x00000020) val[2] |= (a << 16);
759                         if(_p & 0x00000040) val[3] |= (a);
760                         if(_p & 0x00000080) val[3] |= (a << 16);
761                 }
762                 if(size > 1) {
763                         if(_p & 0x00000100) val[4] |= (a);
764                         if(_p & 0x00000200) val[4] |= (a << 16);
765                         if(_p & 0x00000400) val[5] |= (a);
766                         if(_p & 0x00000800) val[5] |= (a << 16);
767                         if(_p & 0x00001000) val[6] |= (a);
768                         if(_p & 0x00002000) val[6] |= (a << 16);
769                         if(_p & 0x00004000) val[7] |= (a);
770                         if(_p & 0x00008000) val[7] |= (a << 16);
771                 }
772                 if(size > 2) {
773                         if(_p & 0x00010000) val[8] |= (a);
774                         if(_p & 0x00020000) val[8] |= (a << 16);
775                         if(_p & 0x00040000) val[9] |= (a);
776                         if(_p & 0x00080000) val[9] |= (a << 16);
777                         if(_p & 0x00100000) val[10] |= (a);
778                         if(_p & 0x00200000) val[10] |= (a << 16);
779                         if(_p & 0x00400000) val[11] |= (a);
780                         if(_p & 0x00800000) val[11] |= (a << 16);
781                 }
782                 if(size > 3) {
783                         if(_p & 0x01000000) val[12] |= (a);
784                         if(_p & 0x02000000) val[12] |= (a << 16);
785                         if(_p & 0x04000000) val[13] |= (a);
786                         if(_p & 0x08000000) val[13] |= (a << 16);
787                         if(_p & 0x10000000) val[14] |= (a);
788                         if(_p & 0x20000000) val[14] |= (a << 16);
789                         if(_p & 0x40000000) val[15] |= (a);
790                         if(_p & 0x80000000) val[15] |= (a << 16);
791                 }
792                 break;
793         case 32:
794                 if(size > 0) {
795                         a &= 0xffffffff;
796                         if(_p & 0x00000001) val[0] = (a);
797                         if(_p & 0x00000002) val[1] = (a);
798                         if(_p & 0x00000004) val[2] = (a);
799                         if(_p & 0x00000008) val[3] = (a);
800                         if(_p & 0x00000010) val[4] = (a);
801                         if(_p & 0x00000020) val[5] = (a);
802                         if(_p & 0x00000040) val[6] = (a);
803                         if(_p & 0x00000080) val[7] = (a);
804                 }
805                 if(size > 1) {
806                         if(_p & 0x00000100) val[8] = (a);
807                         if(_p & 0x00000200) val[9] = (a);
808                         if(_p & 0x00000400) val[10] = (a);
809                         if(_p & 0x00000800) val[11] = (a);
810                         if(_p & 0x00001000) val[12] = (a);
811                         if(_p & 0x00002000) val[13] = (a);
812                         if(_p & 0x00004000) val[14] = (a);
813                         if(_p & 0x00008000) val[15] = (a);
814                 }
815                 if(size > 2) {
816                         if(_p & 0x00010000) val[16] = (a);
817                         if(_p & 0x00020000) val[17] = (a);
818                         if(_p & 0x00040000) val[18] = (a);
819                         if(_p & 0x00080000) val[19] = (a);
820                         if(_p & 0x00100000) val[20] = (a);
821                         if(_p & 0x00200000) val[21] = (a);
822                         if(_p & 0x00400000) val[22] = (a);
823                         if(_p & 0x00800000) val[23] = (a);
824                 }
825                 if(size > 3) {
826                         if(_p & 0x01000000) val[24] = (a);
827                         if(_p & 0x02000000) val[25] = (a);
828                         if(_p & 0x04000000) val[26] = (a);
829                         if(_p & 0x08000000) val[27] = (a);
830                         if(_p & 0x10000000) val[28] = (a);
831                         if(_p & 0x20000000) val[29] = (a);
832                         if(_p & 0x40000000) val[30] = (a);
833                         if(_p & 0x80000000) val[31] = (a);
834                 }
835                 break;
836         default:
837                 break;
838         }
839         j = (bpp == 1) ? 1 : bpp * size / sizeof(u_int32_t);
840
841         /*
842             If we don't display bytes right-to-left (little-endian),
843             then perform a byte-swap on p (we don't have to swap if
844             bpp == 1 and val[0] == 0)...
845         */
846         if((byte_ltor) && (j > 1) && (val[j] != 0)) {
847                 for(i = 0; i < (j - i); i++) {
848                         _p = val[j - i];
849                         val[j - i] = val[i];
850                         val[i] = _p;
851                 }
852                 for(i = 0; i < j; i++) {
853                         _p = val[i];
854                         for(k = 0, val[i] = 0; k < sizeof(u_int32_t);
855                             k++, _p >>= 8) {
856                                 val[i] <<= 8;
857                                 val[i] |= (_p & 0xff);
858                         }
859                 }
860         }
861
862         for(i = 0; i < j; i++) {
863                 /* Write the pixel-row... */
864                 WRITE_GFB_BUFFER(adp, (off + i), val[i]);
865         }
866         return(0);
867 }
868
869 int
870 gfb_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
871 {
872         vm_offset_t poff;
873         struct gfb_softc *sc;
874         int i, pixel_size;
875         u_int row, col;
876         u_int8_t *pixel;
877
878         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
879         pixel_size = adp->va_info.vi_depth / 8;
880
881         /* Get the start of the array of pixels rows for this character... */
882         pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight);
883
884         /* Calculate the new cursor position... */
885         row = off / adp->va_info.vi_width;
886         col = off % adp->va_info.vi_width;
887
888         /* Iterate over all the pixel rows for this character... */
889         for(i = 0; i < adp->va_info.vi_cheight; i++) {
890                 /* Get the address of the character's pixel-row... */
891                 poff = ((col * adp->va_info.vi_cwidth * pixel_size) +
892                     (((row * adp->va_info.vi_cheight) + i) *
893                     adp->va_line_width)) / sizeof(u_int32_t);
894
895                 /* Now display the current pixel row... */
896                 (*vidsw[adp->va_index]->putp)(adp, poff, pixel[i], a,
897                     sizeof(u_int8_t), 1, 1, 0);
898         }
899         return(0);
900 }
901
902 int
903 gfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
904 {
905         struct gfb_softc *sc;
906         int i;
907
908         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
909
910         /* If the string in empty, just return now... */
911         if(len == 0)
912                 return(0);
913
914         for(i = 0; i < len; i++)
915                 (*vidsw[adp->va_index]->putc)(adp, off + i, s[i] & 0x00ff,
916                     (s[i] & 0xff00) >> 8);
917
918         return(0);
919 }
920
921 int
922 gfb_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
923     u_int32_t pixel_mask, int size)
924 {
925         vm_offset_t poff;
926         int i, pixel_size;
927
928         pixel_size = adp->va_info.vi_depth / 8;
929
930         /* Iterate over all the pixel rows for the mouse pointer... */
931         for(i = 0; i < size; i++) {
932                 /* Get the address of the mouse pointer's pixel-row... */
933                 poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) /
934                     sizeof(u_int32_t);
935                 /* Now display the current pixel-row... */
936                 (*vidsw[adp->va_index]->putp)(adp, poff, pixel_image[i],
937                     pixel_mask, sizeof(u_int8_t), 1, 1, 0);
938         }
939
940         return(0);
941 }
942
943 int
944 gfb_error(void)
945 {
946
947         return(0);
948 }