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