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