]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/fb/gfb.c
This commit was generated by cvs2svn to compensate for changes in r106121,
[FreeBSD/FreeBSD.git] / sys / dev / 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 /*
27  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
28  * All rights reserved.
29  *
30  * Author: Chris G. Demetriou
31  * 
32  * Permission to use, copy, modify and distribute this software and
33  * its documentation is hereby granted, provided that both the copyright
34  * notice and this permission notice appear in all copies of the
35  * software, derivative works or modified versions, and any portions
36  * thereof, and that both notices appear in supporting documentation.
37  * 
38  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 
39  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 
40  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41  * 
42  * Carnegie Mellon requests users of this software to return to
43  *
44  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
45  *  School of Computer Science
46  *  Carnegie Mellon University
47  *  Pittsburgh PA 15213-3890
48  *
49  * any improvements or extensions that they make and grant Carnegie the
50  * rights to redistribute these changes.
51  */
52
53 #include <sys/cdefs.h>
54 __FBSDID("$FreeBSD$");
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 <pci/pcireg.h>
84 #include <pci/pcivar.h>
85
86 #include <dev/fb/fbreg.h>
87 #include <dev/fb/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, 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 {
545         int off;
546
547 #if 0
548         if(n == 0)
549                 return(0);
550 #endif
551
552         /*
553            Just traverse the buffer, one 2K-pixel span at a time, clearing
554            each pixel...
555         */
556         /* for(off = 0; off < (n * adp->va_line_width); off += (2 KB)) */
557         for(off = 0; off < adp->va_window_size; off++)
558                 (*vidsw[adp->va_index]->putp)(adp, off, 0x000007ff, 0xffffffff,
559                     sizeof(u_int32_t), 1, 0, 0);
560
561         return(0);
562 }
563
564 int
565 gfb_diag(video_adapter_t *adp, int level)
566 {
567         video_info_t info;
568         struct gfb_softc *sc;
569         int error;
570
571         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
572
573         /* Just dump everything we know about the adapter to the screen... */
574         fb_dump_adp_info(sc->driver_name, adp, level);
575
576         /* Try to get the info on this adapter... */
577         if(!(error = (*vidsw[adp->va_index]->get_info)(adp,
578             adp->va_initial_mode, &info)))
579                 /*
580                    Just dump everything we know about the adapter's mode
581                    to the screen...
582                 */
583                 fb_dump_mode_info(sc->driver_name, adp, &info, level);
584
585         return(error);
586 }
587
588 int
589 gfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
590 {
591         struct gfb_softc *sc;
592         int error, i;
593
594         error = 0;
595         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
596
597 #if 0
598         /* If we have a RAMDAC-specific counterpart, use it... */
599         if(sc->gfbc->ramdac_save_cursor_palette)
600                 error = sc->gfbc->ramdac_save_cursor_palette(adp,
601                     &sc->gfbc->cursor_palette);
602
603         else
604                 /* Otherwise, use the built-in functionality... */
605                 error = sc->gfbc->builtin_save_cursor_palette(adp,
606                     &sc->gfbc->cursor_palette);
607 #endif
608
609         for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
610                 palette[(3 * i)] = sc->gfbc->cursor_palette.red[i];
611                 palette[(3 * i) + 1] = sc->gfbc->cursor_palette.green[i];
612                 palette[(3 * i) + 2] = sc->gfbc->cursor_palette.blue[i];
613         }
614         return(error);
615 }
616
617 int
618 gfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
619 {
620         struct gfb_softc *sc;
621         int error, i;
622
623         error = 0;
624         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
625
626         for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
627                 sc->gfbc->cursor_palette.red[i] = palette[(3 * i)];
628                 sc->gfbc->cursor_palette.green[i] = palette[(3 * i) + 1];
629                 sc->gfbc->cursor_palette.blue[i] = palette[(3 * i) + 2];
630         }
631
632         /* If we have a RAMDAC-specific counterpart, use it... */
633         if(sc->gfbc->ramdac_load_cursor_palette)
634                 error = sc->gfbc->ramdac_load_cursor_palette(adp,
635                     &sc->gfbc->cursor_palette);
636         else
637                 /* Otherwise, use the built-in functionality... */
638                 error = sc->gfbc->builtin_load_cursor_palette(adp,
639                     &sc->gfbc->cursor_palette);
640
641         return(error);
642 }
643
644 int
645 gfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
646 {
647         int error, num_pixels;
648
649         if(n == 0)
650                 return(0);
651         num_pixels = adp->va_info.vi_cheight * adp->va_line_width;
652         error = (*vidsw[adp->va_index]->bitblt)(adp, src * num_pixels,
653             dst * num_pixels, n * num_pixels);
654         return(error);
655 }
656
657 int
658 gfb_putp(video_adapter_t *adp, vm_offset_t off, u_int32_t p, u_int32_t a,
659     int size, int bpp, int bit_ltor, int byte_ltor)
660 {
661         int i, j, k, num_shifts;
662         u_int32_t _p, val[32];
663
664         if(bpp < 1)
665                 return(-1);
666
667         /*
668             If we don't display bits right-to-left (little-bitian?),
669             then perform a bit-swap on p...
670         */
671         if(bit_ltor) {
672                 num_shifts = 8 * size;
673                 for(i = 0, _p = 0; i < num_shifts; i++, p >>= 1) {
674                         _p <<= 1;
675                         _p |= (p & 0x00000001);
676                 }
677         } else
678                 _p = p;
679
680         switch(bpp) {
681         /* Accelerate the simplest cases... */
682         case 1:
683                 if((a & 0x00000001) == 0)
684                         val[0] = 0;
685                 else if(size <= 0)
686                         val[0] = 0;
687                 else if(size == 1)
688                         val[0] = _p & 0x000000ff;
689                 else if(size == 2)
690                         val[0] = _p & 0x0000ffff;
691                 else if(size == 3)
692                         val[0] = _p & 0x00ffffff;
693                 else if(size == 4)
694                         val[0] = _p & 0xffffffff;
695                 break;
696
697         /* Only do the following if we are not a simple case... */
698         case 8:
699                 if(size > 0) {
700                         a &= 0x000000ff;
701                         val[0] = 0;
702                         if(_p & 0x00000001) val[0] |= (a);
703                         if(_p & 0x00000002) val[0] |= (a << 8);
704                         if(_p & 0x00000004) val[0] |= (a << 16);
705                         if(_p & 0x00000008) val[0] |= (a << 24);
706                         val[1] = 0;
707                         if(_p & 0x00000010) val[1] |= (a);
708                         if(_p & 0x00000020) val[1] |= (a << 8);
709                         if(_p & 0x00000040) val[1] |= (a << 16);
710                         if(_p & 0x00000080) val[1] |= (a << 24);
711                 }
712                 if(size > 1) {
713                         val[2] = 0;
714                         if(_p & 0x00000100) val[2] |= (a);
715                         if(_p & 0x00000200) val[2] |= (a << 8);
716                         if(_p & 0x00000400) val[2] |= (a << 16);
717                         if(_p & 0x00000800) val[2] |= (a << 24);
718                         val[3] = 0;
719                         if(_p & 0x00001000) val[3] |= (a);
720                         if(_p & 0x00002000) val[3] |= (a << 8);
721                         if(_p & 0x00004000) val[3] |= (a << 16);
722                         if(_p & 0x00008000) val[3] |= (a << 24);
723                 }       
724                 if(size > 2) {
725                         val[4] = 0;
726                         if(_p & 0x00010000) val[4] |= (a);
727                         if(_p & 0x00020000) val[4] |= (a << 8);
728                         if(_p & 0x00040000) val[4] |= (a << 16);
729                         if(_p & 0x00080000) val[4] |= (a << 24);
730                         val[5] = 0;
731                         if(_p & 0x00100000) val[5] |= (a);
732                         if(_p & 0x00200000) val[5] |= (a << 8);
733                         if(_p & 0x00400000) val[5] |= (a << 16);
734                         if(_p & 0x00800080) val[5] |= (a << 24);
735                 }
736                 if(size > 3) {
737                         val[6] = 0;
738                         if(_p & 0x01000000) val[6] |= (a);
739                         if(_p & 0x02000000) val[6] |= (a << 8);
740                         if(_p & 0x04000000) val[6] |= (a << 16);
741                         if(_p & 0x08000000) val[6] |= (a << 24);
742                         val[7] = 0;
743                         if(_p & 0x10000000) val[7] |= (a);
744                         if(_p & 0x20000000) val[7] |= (a << 8);
745                         if(_p & 0x40000000) val[7] |= (a << 16);
746                         if(_p & 0x80000000) val[7] |= (a << 24);
747                 }
748                 break;
749         case 16:
750                 if(size > 0) {
751                         a &= 0x0000ffff;
752                         if(_p & 0x00000001) val[0] |= (a);
753                         if(_p & 0x00000002) val[0] |= (a << 16);
754                         if(_p & 0x00000004) val[1] |= (a);
755                         if(_p & 0x00000008) val[1] |= (a << 16);
756                         if(_p & 0x00000010) val[2] |= (a);
757                         if(_p & 0x00000020) val[2] |= (a << 16);
758                         if(_p & 0x00000040) val[3] |= (a);
759                         if(_p & 0x00000080) val[3] |= (a << 16);
760                 }
761                 if(size > 1) {
762                         if(_p & 0x00000100) val[4] |= (a);
763                         if(_p & 0x00000200) val[4] |= (a << 16);
764                         if(_p & 0x00000400) val[5] |= (a);
765                         if(_p & 0x00000800) val[5] |= (a << 16);
766                         if(_p & 0x00001000) val[6] |= (a);
767                         if(_p & 0x00002000) val[6] |= (a << 16);
768                         if(_p & 0x00004000) val[7] |= (a);
769                         if(_p & 0x00008000) val[7] |= (a << 16);
770                 }
771                 if(size > 2) {
772                         if(_p & 0x00010000) val[8] |= (a);
773                         if(_p & 0x00020000) val[8] |= (a << 16);
774                         if(_p & 0x00040000) val[9] |= (a);
775                         if(_p & 0x00080000) val[9] |= (a << 16);
776                         if(_p & 0x00100000) val[10] |= (a);
777                         if(_p & 0x00200000) val[10] |= (a << 16);
778                         if(_p & 0x00400000) val[11] |= (a);
779                         if(_p & 0x00800000) val[11] |= (a << 16);
780                 }
781                 if(size > 3) {
782                         if(_p & 0x01000000) val[12] |= (a);
783                         if(_p & 0x02000000) val[12] |= (a << 16);
784                         if(_p & 0x04000000) val[13] |= (a);
785                         if(_p & 0x08000000) val[13] |= (a << 16);
786                         if(_p & 0x10000000) val[14] |= (a);
787                         if(_p & 0x20000000) val[14] |= (a << 16);
788                         if(_p & 0x40000000) val[15] |= (a);
789                         if(_p & 0x80000000) val[15] |= (a << 16);
790                 }
791                 break;
792         case 32:
793                 if(size > 0) {
794                         a &= 0xffffffff;
795                         if(_p & 0x00000001) val[0] = (a);
796                         if(_p & 0x00000002) val[1] = (a);
797                         if(_p & 0x00000004) val[2] = (a);
798                         if(_p & 0x00000008) val[3] = (a);
799                         if(_p & 0x00000010) val[4] = (a);
800                         if(_p & 0x00000020) val[5] = (a);
801                         if(_p & 0x00000040) val[6] = (a);
802                         if(_p & 0x00000080) val[7] = (a);
803                 }
804                 if(size > 1) {
805                         if(_p & 0x00000100) val[8] = (a);
806                         if(_p & 0x00000200) val[9] = (a);
807                         if(_p & 0x00000400) val[10] = (a);
808                         if(_p & 0x00000800) val[11] = (a);
809                         if(_p & 0x00001000) val[12] = (a);
810                         if(_p & 0x00002000) val[13] = (a);
811                         if(_p & 0x00004000) val[14] = (a);
812                         if(_p & 0x00008000) val[15] = (a);
813                 }
814                 if(size > 2) {
815                         if(_p & 0x00010000) val[16] = (a);
816                         if(_p & 0x00020000) val[17] = (a);
817                         if(_p & 0x00040000) val[18] = (a);
818                         if(_p & 0x00080000) val[19] = (a);
819                         if(_p & 0x00100000) val[20] = (a);
820                         if(_p & 0x00200000) val[21] = (a);
821                         if(_p & 0x00400000) val[22] = (a);
822                         if(_p & 0x00800000) val[23] = (a);
823                 }
824                 if(size > 3) {
825                         if(_p & 0x01000000) val[24] = (a);
826                         if(_p & 0x02000000) val[25] = (a);
827                         if(_p & 0x04000000) val[26] = (a);
828                         if(_p & 0x08000000) val[27] = (a);
829                         if(_p & 0x10000000) val[28] = (a);
830                         if(_p & 0x20000000) val[29] = (a);
831                         if(_p & 0x40000000) val[30] = (a);
832                         if(_p & 0x80000000) val[31] = (a);
833                 }
834                 break;
835         default:
836                 break;
837         }
838         j = (bpp == 1) ? 1 : bpp * size / sizeof(u_int32_t);
839
840         /*
841             If we don't display bytes right-to-left (little-endian),
842             then perform a byte-swap on p (we don't have to swap if
843             bpp == 1 and val[0] == 0)...
844         */
845         if((byte_ltor) && (j > 1) && (val[j] != 0)) {
846                 for(i = 0; i < (j - i); i++) {
847                         _p = val[j - i];
848                         val[j - i] = val[i];
849                         val[i] = _p;
850                 }
851                 for(i = 0; i < j; i++) {
852                         _p = val[i];
853                         for(k = 0, val[i] = 0; k < sizeof(u_int32_t);
854                             k++, _p >>= 8) {
855                                 val[i] <<= 8;
856                                 val[i] |= (_p & 0xff);
857                         }
858                 }
859         }
860
861         for(i = 0; i < j; i++) {
862                 /* Write the pixel-row... */
863                 WRITE_GFB_BUFFER(adp, (off + i), val[i]);
864         }
865         return(0);
866 }
867
868 int
869 gfb_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
870 {
871         vm_offset_t poff;
872         struct gfb_softc *sc;
873         int i, pixel_size;
874         u_int row, col;
875         u_int8_t *pixel;
876
877         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
878         pixel_size = adp->va_info.vi_depth / 8;
879
880         /* Get the start of the array of pixels rows for this character... */
881         pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight);
882
883         /* Calculate the new cursor position... */
884         row = off / adp->va_info.vi_width;
885         col = off % adp->va_info.vi_width;
886
887         /* Iterate over all the pixel rows for this character... */
888         for(i = 0; i < adp->va_info.vi_cheight; i++) {
889                 /* Get the address of the character's pixel-row... */
890                 poff = ((col * adp->va_info.vi_cwidth * pixel_size) +
891                     (((row * adp->va_info.vi_cheight) + i) *
892                     adp->va_line_width)) / sizeof(u_int32_t);
893
894                 /* Now display the current pixel row... */
895                 (*vidsw[adp->va_index]->putp)(adp, poff, pixel[i], a,
896                     sizeof(u_int8_t), 1, 1, 0);
897         }
898         return(0);
899 }
900
901 int
902 gfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
903 {
904         struct gfb_softc *sc;
905         int i;
906
907         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
908
909         /* If the string in empty, just return now... */
910         if(len == 0)
911                 return(0);
912
913         for(i = 0; i < len; i++)
914                 (*vidsw[adp->va_index]->putc)(adp, off + i, s[i] & 0x00ff,
915                     (s[i] & 0xff00) >> 8);
916
917         return(0);
918 }
919
920 int
921 gfb_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
922     u_int32_t pixel_mask, int size)
923 {
924         vm_offset_t poff;
925         int i, pixel_size;
926
927         pixel_size = adp->va_info.vi_depth / 8;
928
929         /* Iterate over all the pixel rows for the mouse pointer... */
930         for(i = 0; i < size; i++) {
931                 /* Get the address of the mouse pointer's pixel-row... */
932                 poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) /
933                     sizeof(u_int32_t);
934                 /* Now display the current pixel-row... */
935                 (*vidsw[adp->va_index]->putp)(adp, poff, pixel_image[i],
936                     pixel_mask, sizeof(u_int8_t), 1, 1, 0);
937         }
938
939         return(0);
940 }
941
942 int
943 gfb_error(void)
944 {
945
946         return(0);
947 }