2 * Copyright (c) 2000, 2001 Andrew Miklic, Andrew Gallatin, Peter Jeremy,
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
29 * All rights reserved.
31 * Author: Chris G. Demetriou
33 * Permission to use, copy, modify and distribute this software and
34 * its documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
41 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie the
51 * rights to redistribute these changes.
54 #include <sys/cdefs.h>
55 __FBSDID("$FreeBSD$");
57 #include <machine/stdarg.h>
59 #include <sys/param.h>
60 #include <sys/systm.h>
61 #include <sys/kernel.h>
64 #include <sys/fcntl.h>
65 #include <sys/malloc.h>
67 #include <sys/consio.h>
69 #include <isa/isareg.h>
70 #include <dev/fb/vgareg.h>
73 #include <vm/vm_param.h>
76 #include <machine/md_var.h>
77 #include <machine/pc/bios.h>
78 #include <machine/clock.h>
79 #include <machine/bus_memio.h>
80 #include <machine/bus.h>
81 #include <machine/pc/vesa.h>
82 #include <machine/resource.h>
83 #include <machine/rpb.h>
88 #include <pci/pcireg.h>
89 #include <pci/pcivar.h>
91 #include <dev/fb/fbreg.h>
92 #include <dev/syscons/syscons.h>
93 #include <dev/fb/gfb.h>
94 #include <dev/gfb/gfb_pci.h>
95 #include <dev/fb/tga.h>
96 #include <dev/tga/tga_pci.h>
100 /* TGA-specific FB video driver function declarations */
101 static int tga_error(void);
102 static vi_init_t tga_init;
103 static void tga2_init(struct gfb_softc *, int);
105 /* TGA-specific functionality. */
106 static gfb_builtin_save_palette_t tga_builtin_save_palette;
107 static gfb_builtin_load_palette_t tga_builtin_load_palette;
109 static gfb_builtin_save_palette_t tga2_builtin_save_palette;
110 static gfb_builtin_load_palette_t tga2_builtin_load_palette;
111 static gfb_builtin_save_cursor_palette_t tga2_builtin_save_cursor_palette;
112 static gfb_builtin_load_cursor_palette_t tga2_builtin_load_cursor_palette;
114 static gfb_builtin_read_hw_cursor_t tga_builtin_read_hw_cursor;
115 static gfb_builtin_set_hw_cursor_t tga_builtin_set_hw_cursor;
116 static gfb_builtin_set_hw_cursor_shape_t tga_builtin_set_hw_cursor_shape;
117 static void bt463_load_palette_intr(struct gfb_softc *);
118 static void bt463_load_cursor_palette_intr(struct gfb_softc *);
119 static int tga_schedule_intr(struct gfb_softc *, void (*)(struct gfb_softc *));
121 /* RAMDAC interface functions */
122 static gfb_ramdac_wr_t tga_bt485_wr;
123 static gfb_ramdac_rd_t tga_bt485_rd;
124 static gfb_ramdac_wr_t tga_bt463_wr;
125 static gfb_ramdac_rd_t tga_bt463_rd;
126 static gfb_ramdac_wr_t tga2_ibm561_wr;
127 static gfb_ramdac_rd_t tga2_ibm561_rd;
128 static void tga2_ics9110_wr(struct gfb_softc *, int);
130 /* RAMDAC-specific functions */
131 static gfb_ramdac_init_t bt463_init;
132 static void bt463_update_window_type(struct gfb_softc *);
134 static gfb_ramdac_save_palette_t bt463_save_palette;
135 static gfb_ramdac_load_palette_t bt463_load_palette;
137 static gfb_ramdac_save_cursor_palette_t bt463_save_cursor_palette;
138 static gfb_ramdac_load_cursor_palette_t bt463_load_cursor_palette;
139 static gfb_ramdac_init_t bt485_init;
140 static gfb_ramdac_save_palette_t bt485_save_palette;
141 static gfb_ramdac_load_palette_t bt485_load_palette;
142 static gfb_ramdac_save_cursor_palette_t bt485_save_cursor_palette;
143 static gfb_ramdac_load_cursor_palette_t bt485_load_cursor_palette;
144 static gfb_ramdac_read_hw_cursor_t bt485_read_hw_cursor;
145 static gfb_ramdac_set_hw_cursor_t bt485_set_hw_cursor;
146 static gfb_ramdac_set_hw_cursor_shape_t bt485_set_hw_cursor_shape;
147 static gfb_ramdac_init_t ibm561_init;
148 static gfb_ramdac_save_palette_t ibm561_save_palette;
149 static gfb_ramdac_load_palette_t ibm561_load_palette;
150 static gfb_ramdac_save_cursor_palette_t ibm561_save_cursor_palette;
151 static gfb_ramdac_load_cursor_palette_t ibm561_load_cursor_palette;
153 /* Video Driver-generic functions */
154 static vi_query_mode_t tga_query_mode;
155 static vi_set_mode_t tga_set_mode;
156 static vi_blank_display_t tga_blank_display;
158 static vi_ioctl_t tga_ioctl;
160 static vi_set_border_t tga_set_border;
161 static vi_set_win_org_t tga_set_win_org;
162 static vi_fill_rect_t tga_fill_rect;
163 static vi_bitblt_t tga_bitblt;
164 static vi_clear_t tga_clear;
165 static vi_putc_t tga_putc;
166 static vi_puts_t tga_puts;
167 static vi_putm_t tga_putm;
169 static video_switch_t tgavidsw = {
186 gfb_set_hw_cursor_shape,
196 gfb_save_cursor_palette,
197 gfb_load_cursor_palette,
205 VIDEO_DRIVER(tga, tgavidsw, NULL);
207 extern sc_rndr_sw_t txtrndrsw;
208 RENDERER(tga, 0, txtrndrsw, gfb_set);
211 extern sc_rndr_sw_t gfbrndrsw;
212 RENDERER(tga, PIXEL_MODE, gfbrndrsw, gfb_set);
213 #endif /* SC_PIXEL_MODE */
215 #ifndef SC_NO_MODE_CHANGE
216 extern sc_rndr_sw_t grrndrsw;
217 RENDERER(tga, GRAPHICS_MODE, grrndrsw, gfb_set);
218 #endif /* SC_NO_MODE_CHANGE */
220 RENDERER_MODULE(tga, gfb_set);
222 #define MHz * 1000000
225 extern struct gfb_softc *gfb_device_softcs[2][MAX_NUM_GFB_CARDS];
228 The following 3 variables exist only because we need statically
229 allocated structures very early in boot to support tga_configure()...
231 extern struct gfb_softc console;
232 extern video_adapter_t console_adp;
233 extern struct gfb_conf console_gfbc;
234 extern u_char console_palette_red[256];
235 extern u_char console_palette_green[256];
236 extern u_char console_palette_blue[256];
237 extern u_char console_cursor_palette_red[3];
238 extern u_char console_cursor_palette_green[3];
239 extern u_char console_cursor_palette_blue[3];
241 static struct monitor decmonitors[] = {
242 /* 0x0: 1280 x 1024 @ 72Hz */
243 { 1280, 32, 160, 232,
247 /* 0x1: 1280 x 1024 @ 66Hz */
248 { 1280, 32, 160, 232,
252 /* 0x2: 1280 x 1024 @ 60Hz */
253 { 1280, 44, 184, 200,
257 /* 0x3: 1152 x 900 @ 72Hz */
258 { 1152, 64, 112, 176,
262 /* 0x4: 1600 x 1200 @ 65Hz */
263 { 1600, 32, 192, 336,
267 /* 0x5: 1024 x 768 @ 70Hz */
268 { 1024, 24, 136, 144,
272 /* 0x6: 1024 x 768 @ 72Hz */
273 { 1024, 16, 128, 128,
277 /* 0x7: 1024 x 864 @ 60Hz */
278 { 1024, 12, 128, 116,
282 /* 0x8: 1024 x 768 @ 60Hz */
287 /* 0x9: 800 x 600 @ 72Hz */
292 /* 0xa: 800 x 600 @ 60Hz */
297 /* 0xb: 640 x 480 @ 72Hz */
302 /* 0xc: 640 x 480 @ 60Hz */
307 /* 0xd: 1280 x 1024 @ 75Hz */
308 { 1280, 16, 144, 248,
312 /* 0xe: 1280 x 1024 @ 60Hz */
313 { 1280, 19, 163, 234,
317 /* 0xf: 1600 x 1200 @ 75Hz */
318 /* XXX -- this one's weird. rcd */
319 { 1600, 32, 192, 336,
330 #define MB * 1024 * 1024
333 * These are the 16 default VGA colors--these are replicated 16 times as the
334 * initial (default) color-map. The text rendering functions use entries
335 * 0..15 for normal foreground/background colors. The entries 128..255 are
336 * used for blinking entries--when "on," they contain the foreground color
337 * entries; when "off," they contain the background color entries...
339 static const struct cmap {
343 } default_cmap[16] = {
344 {0x00, 0x00, 0x00}, /* Black */
345 {0x00, 0x00, 0xff}, /* Blue */
346 {0x00, 0xff, 0x00}, /* Green */
347 {0x00, 0xc0, 0xc0}, /* Cyan */
348 {0xff, 0x00, 0x00}, /* Red */
349 {0xc0, 0x00, 0xc0}, /* Magenta */
350 {0xc0, 0xc0, 0x00}, /* Brown */
351 {0xc0, 0xc0, 0xc0}, /* Light Grey */
352 {0x80, 0x80, 0x80}, /* Dark Grey */
353 {0x80, 0x80, 0xff}, /* Light Blue */
354 {0x80, 0xff, 0x80}, /* Light Green */
355 {0x80, 0xff, 0xff}, /* Light Cyan */
356 {0xff, 0x80, 0x80}, /* Light Red */
357 {0xff, 0x80, 0xff}, /* Light Magenta */
358 {0xff, 0xff, 0x80}, /* Yellow */
359 {0xff, 0xff, 0xff} /* White */
362 extern struct gfb_font bold8x16;
364 /*****************************************************************************
366 * FB-generic functions
368 ****************************************************************************/
371 tga_init(int unit, video_adapter_t *adp, int flags)
373 struct gfb_softc *sc;
374 struct gfb_conf *gfbc;
375 unsigned int monitor;
384 /* Assume the best... */
387 sc = gfb_device_softcs[adp->va_model][unit];
390 /* Initialize palette counts... */
391 gfbc->palette.count = 256;
392 gfbc->cursor_palette.count = 3;
394 /* Initialize the adapter... */
395 gder = BASIC_READ_TGA_REGISTER(adp, TGA_REG_GDER);
396 addrmask = (gder & GDER_ADDR_MASK) >> GDER_ADDR_SHIFT;
397 deep = (gder & GDER_DEEP) != 0;
398 cs = (gder & GDER_CS) == 0;
399 card_type = TGA_TYPE_UNKNOWN;
400 adp->va_little_bitian = 1;
401 adp->va_little_endian = 0;
402 adp->va_initial_mode = 0;
403 adp->va_initial_bios_mode = 0;
405 adp->va_info.vi_mem_model = V_INFO_MM_TEXT;
406 adp->va_info.vi_mode = M_VGA_M80x30;
407 adp->va_info.vi_flags = V_INFO_COLOR;
408 adp->va_buffer = adp->va_mem_base;
409 adp->va_buffer_size = 4 MB * (1 + addrmask);
410 adp->va_registers = adp->va_buffer + TGA_REG_SPACE_OFFSET;
411 adp->va_registers_size = 2 KB;
412 adp->va_window = adp->va_buffer + (adp->va_buffer_size / 2);
413 adp->va_info.vi_window = vtophys(adp->va_window);
414 adp->va_window_size = (deep ? 4 MB : 2 MB);
415 adp->va_info.vi_window_size = adp->va_window_size;
416 adp->va_window_gran = adp->va_window_size;
417 adp->va_info.vi_window_gran = adp->va_window_gran;
418 adp->va_info.vi_buffer = vtophys(adp->va_buffer);
419 adp->va_info.vi_buffer_size = adp->va_buffer_size;
420 adp->va_disp_start.x = 0;
421 adp->va_disp_start.y = 0;
422 adp->va_info.vi_depth = (deep ? 32 : 8);
423 adp->va_info.vi_planes = adp->va_info.vi_depth / 8;
424 adp->va_info.vi_width = (READ_GFB_REGISTER(adp, TGA_REG_VHCR) &
426 adp->va_info.vi_width |= (READ_GFB_REGISTER(adp, TGA_REG_VHCR) &
428 switch(adp->va_info.vi_width) {
430 adp->va_info.vi_width = 8192;
433 adp->va_info.vi_width = 8196;
436 adp->va_info.vi_width *= 4;
439 adp->va_info.vi_height = (READ_GFB_REGISTER(adp, TGA_REG_VVCR) &
441 adp->va_line_width = adp->va_info.vi_width * adp->va_info.vi_depth / 8;
442 if(READ_GFB_REGISTER(adp, TGA_REG_VHCR) & VHCR_ODD)
443 adp->va_info.vi_width -= 4;
446 Set the video base address and the cursor base address to
447 something known such that the video base address is at
448 least 1 KB past the cursor base address (the cursor is 1 KB
449 in size, so leave room for it)...we pick 4 KB and 0 KB,
450 respectively, since they begin at the top of the framebuffer
451 for minimal fragmentation of the address space, and this will
452 always leave enough room for the cursor for all implementations...
455 /* Set the video base address... */
456 tga_set_win_org(sc->adp, 4 KB);
458 /* Set the cursor base address... */
459 ccbr = READ_GFB_REGISTER(sc->adp, TGA_REG_CCBR);
460 ccbr = (ccbr & 0xfffffc0f) | (0 << 4);
461 WRITE_GFB_REGISTER(sc->adp, TGA_REG_CCBR, ccbr);
463 /* Type the card... */
464 if(adp->va_type == KD_TGA) {
467 /* 8bpp frame buffer */
468 gfbc->ramdac_name = "BT485";
469 gfbc->ramdac_init = bt485_init;
470 gfbc->ramdac_rd = tga_bt485_rd;
471 gfbc->ramdac_wr = tga_bt485_wr;
472 gfbc->ramdac_save_palette = bt485_save_palette;
473 gfbc->ramdac_load_palette = bt485_load_palette;
474 gfbc->ramdac_save_cursor_palette =
475 bt485_save_cursor_palette;
476 gfbc->ramdac_load_cursor_palette =
477 bt485_load_cursor_palette;
478 gfbc->ramdac_read_hw_cursor = bt485_read_hw_cursor;
479 gfbc->ramdac_set_hw_cursor = bt485_set_hw_cursor;
480 gfbc->ramdac_set_hw_cursor_shape =
481 bt485_set_hw_cursor_shape;
483 if(addrmask == GDER_ADDR_4MB) {
485 /* 4MB core map; T8-01 or T8-02 */
487 card_type = TGA_TYPE_T8_01;
488 gfbc->name = "T8-01";
490 card_type = TGA_TYPE_T8_02;
491 gfbc->name = "T8-02";
493 } else if(addrmask == GDER_ADDR_8MB) {
495 /* 8MB core map; T8-22 */
497 card_type = TGA_TYPE_T8_22;
498 gfbc->name = "T8-22";
500 } else if(addrmask == GDER_ADDR_16MB) {
502 /* 16MB core map; T8-44 */
504 card_type = TGA_TYPE_T8_44;
505 gfbc->name = "T8-44";
507 } else if(addrmask == GDER_ADDR_32MB) {
509 /* 32MB core map; ??? */
510 card_type = TGA_TYPE_UNKNOWN;
514 /* 32bpp frame buffer */
515 gfbc->ramdac_name = "BT463";
516 gfbc->ramdac_init = bt463_init;
517 gfbc->ramdac_rd = tga_bt463_rd;
518 gfbc->ramdac_wr = tga_bt463_wr;
519 gfbc->builtin_save_palette = tga_builtin_save_palette;
520 gfbc->builtin_load_palette = tga_builtin_load_palette;
521 gfbc->ramdac_save_cursor_palette =
522 bt463_save_cursor_palette;
523 gfbc->ramdac_load_cursor_palette =
524 bt463_load_cursor_palette;
525 gfbc->builtin_read_hw_cursor =
526 tga_builtin_read_hw_cursor;
527 gfbc->builtin_set_hw_cursor = tga_builtin_set_hw_cursor;
528 gfbc->builtin_set_hw_cursor_shape =
529 tga_builtin_set_hw_cursor_shape;
531 /* 32bpp frame buffer */
532 if(addrmask == GDER_ADDR_4MB) {
534 /* 4MB core map; ??? */
535 card_type = TGA_TYPE_UNKNOWN;
536 } else if(addrmask == GDER_ADDR_8MB) {
538 /* 8MB core map; ??? */
539 card_type = TGA_TYPE_UNKNOWN;
540 } else if(addrmask == GDER_ADDR_16MB) {
542 /* 16MB core map; T32-04 or T32-08 */
544 card_type = TGA_TYPE_T32_04;
545 gfbc->name = "T32-04";
547 card_type = TGA_TYPE_T32_08;
548 gfbc->name = "T32-08";
550 } else if(addrmask == GDER_ADDR_32MB) {
552 /* 32MB core map; T32-88 */
554 card_type = TGA_TYPE_T32_88;
555 gfbc->name = "T32-88";
560 else if(adp->va_type == KD_TGA2) {
561 gfbc->ramdac_name = "IBM561";
562 gfbc->ramdac_init = ibm561_init;
563 gfbc->ramdac_rd = tga2_ibm561_rd;
564 gfbc->ramdac_wr = tga2_ibm561_wr;
565 gfbc->ramdac_save_palette = ibm561_save_palette;
566 gfbc->ramdac_load_palette = ibm561_load_palette;
567 gfbc->ramdac_save_cursor_palette = ibm561_save_cursor_palette;
568 gfbc->ramdac_load_cursor_palette = ibm561_load_cursor_palette;
569 gfbc->builtin_read_hw_cursor = tga_builtin_read_hw_cursor;
570 gfbc->builtin_set_hw_cursor = tga_builtin_set_hw_cursor;
571 gfbc->builtin_set_hw_cursor_shape =
572 tga_builtin_set_hw_cursor_shape;
575 if(addrmask == GDER_ADDR_4MB)
576 card_type = TGA_TYPE_UNKNOWN;
579 else if(addrmask == GDER_ADDR_8MB) {
580 card_type = TGA2_TYPE_3D30;
585 else if(addrmask == GDER_ADDR_16MB) {
586 card_type = TGA2_TYPE_4D20;
589 else if(addrmask == GDER_ADDR_32MB)
590 card_type = TGA_TYPE_UNKNOWN;
594 For now, just return for TGA2 cards (i.e.,
595 allow syscons to treat this device as a normal
596 VGA device, and don't do anything TGA2-specific,
597 e.g., only use the TGA2 card in VGA mode for now
598 as opposed to 2DA mode...
600 if(adp->va_type == KD_TGA2)
603 /* If we couldn't identify the card, err-out... */
604 if(card_type == TGA_TYPE_UNKNOWN) {
605 printf("tga%d: Unknown TGA type\n", unit);
610 /* Clear and disable interrupts... */
611 WRITE_GFB_REGISTER(adp, TGA_REG_SISR, 0x00000001);
613 /* Perform TGA2-specific initialization, if necessary... */
614 if(adp->va_type == KD_TGA2) {
615 monitor = (~READ_GFB_REGISTER(adp, TGA_REG_GREV) >> 16 ) & 0x0f;
616 tga2_init(sc, monitor);
623 tga2_init(sc, monitor)
624 struct gfb_softc *sc;
628 tga2_ics9110_wr(sc, decmonitors[monitor].dotclock);
629 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VHCR,
630 ((decmonitors[monitor].hbp / 4) << VHCR_BPORCH_SHIFT) |
631 ((decmonitors[monitor].hsync / 4) << VHCR_HSYNC_SHIFT) |
632 (((decmonitors[monitor].hfp) / 4) << VHCR_FPORCH_SHIFT) |
633 ((decmonitors[monitor].cols) / 4));
634 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VVCR,
635 (decmonitors[monitor].vbp << VVCR_BPORCH_SHIFT) |
636 (decmonitors[monitor].vsync << VVCR_VSYNC_SHIFT) |
637 (decmonitors[monitor].vfp << VVCR_FPORCH_SHIFT) |
638 (decmonitors[monitor].rows));
639 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VVBR, 1);
640 GFB_REGISTER_READWRITE_BARRIER(sc, TGA_REG_VHCR, 3);
641 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VVVR,
642 READ_GFB_REGISTER(sc->adp, TGA_REG_VVVR) | 1);
643 GFB_REGISTER_READWRITE_BARRIER(sc, TGA_REG_VVVR, 1);
644 WRITE_GFB_REGISTER(sc->adp, TGA_REG_GPMR, 0xffffffff);
645 GFB_REGISTER_READWRITE_BARRIER(sc, TGA_REG_GPMR, 1);
649 tga_query_mode(video_adapter_t *adp, video_info_t *info)
653 /* Assume the best... */
656 /* Verify that this mode is supported on this adapter... */
657 if(adp->va_type == KD_TGA2) {
658 if((info->vi_mode != TGA2_2DA_MODE) &&
659 (info->vi_mode != TGA2_VGA_MODE))
663 if(info->vi_mode != 0)
670 tga_set_mode(video_adapter_t *adp, int mode)
676 /* Assume the best... */
679 gder = READ_GFB_REGISTER(adp, TGA_REG_GDER);
682 Determine the adapter type first
683 so we know which modes are valid for it...
685 switch(adp->va_type) {
689 Verify that this mode is supported
694 vgae_mask = ~0x00400000;
695 WRITE_GFB_REGISTER(adp, TGA_REG_GDER,
700 vgae_mask = 0x00400000;
701 WRITE_GFB_REGISTER(adp, TGA_REG_GDER,
712 Verify that this mode is supported
729 tga_blank_display(video_adapter_t *adp, int mode)
734 /* Assume the best... */
737 blanked = READ_GFB_REGISTER(adp, TGA_REG_VVVR) &
738 (VVR_BLANK | VVR_VIDEOVALID | VVR_CURSOR);
740 /* If we're not already blanked, then blank...*/
742 case V_DISPLAY_BLANK:
743 if(blanked != (VVR_VIDEOVALID | VVR_BLANK)) {
744 blanked = VVR_VIDEOVALID | VVR_BLANK;
745 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
748 case V_DISPLAY_STAND_BY:
749 if(blanked != VVR_BLANK) {
751 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
755 if(blanked != (VVR_VIDEOVALID | VVR_CURSOR)) {
756 blanked = VVR_VIDEOVALID | VVR_CURSOR;
757 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
769 tga_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
771 struct gfb_softc *sc;
775 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
779 tga_schedule_intr(sc, bt463_load_palette_intr);
784 case FBIO_SETDISPSTART:
785 case FBIO_SETLINEWIDTH:
786 case FBIO_GETPALETTE:
790 error = fb_commonioctl(adp, cmd, arg);
798 tga_set_border(video_adapter_t *adp, int color) {
803 tga_set_win_org(video_adapter_t *adp, off_t offset) {
805 u_int16_t window_orig;
810 /* Get the adapter's parameters... */
811 gder = BASIC_READ_TGA_REGISTER(adp, TGA_REG_GDER);
812 deep = (gder & 0x1) != 0;
813 cs = (gder & 0x200) == 0;
816 Set the window (framebuffer) origin according to the video
819 window_orig = offset / ((1 + cs) * (1 + deep) * (1 + deep) * 2 KB);
820 adp->va_window_orig = window_orig * ((1 + cs) * (1 + deep) *
823 /* Set the video base address... */
824 vvbr = READ_GFB_REGISTER(adp, TGA_REG_VVBR);
825 vvbr = (vvbr & 0xfffffe00) | window_orig;
826 WRITE_GFB_REGISTER(adp, TGA_REG_VVBR, vvbr);
831 tga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) {
839 /* Save the pixel mode... */
840 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
842 /* Save the pixel mask... */
843 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
845 /* Save the block-color... */
846 gbcr0 = READ_GFB_REGISTER(adp, TGA_REG_GBCR0);
847 gbcr1 = READ_GFB_REGISTER(adp, TGA_REG_GBCR1);
849 /* Set the pixel mode (block-fill)... */
850 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
851 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_BLK_FILL);
853 /* Set the pixel mask (enable writes to all pixels)... */
854 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, 0xffffffff);
856 color = ((val & 0xff00) << 24) || ((val & 0xff00) << 16) ||
857 ((val & 0xff00) << 8) || ((val & 0xff00) << 0);
859 /* Set the color for the block-fill... */
860 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR0, color);
861 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR1, color);
864 Just traverse the buffer, one 2K-pixel span at a time, setting
865 each pixel to the bolck-color...
867 for(off = (x * y); off < ((x + cx) * (y + cy)); off += (2 KB))
868 WRITE_GFB_BUFFER(adp, off >> 2L, 0x000007ff);
870 /* Restore the pixel mode... */
871 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
873 /* Restore the pixel mask... */
874 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
876 /* Restore the block-color... */
877 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR0, gbcr0);
878 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR1, gbcr1);
884 tga_bitblt(video_adapter_t *adp, ...) {
889 vm_offset_t src, dst;
893 /* Save the pixel mode... */
894 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
896 /* Save the raster op... */
897 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
899 /* Set the pixel mode (copy)... */
900 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
901 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_COPY);
903 /* Set the raster op (src)... */
904 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
906 src = (va_arg(args, vm_offset_t) + adp->va_window_orig) &
908 dst = (va_arg(args, vm_offset_t) + adp->va_window_orig) &
910 count = va_arg(args, int);
911 for(i = 0; i < count; i+= 64, src += 64, dst += 64) {
912 WRITE_GFB_REGISTER(adp, TGA_REG_GCSR, src);
913 WRITE_GFB_REGISTER(adp, TGA_REG_GCDR, dst);
916 /* Restore the raster op... */
917 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
919 /* Restore the pixel mode... */
920 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
928 tga_clear(video_adapter_t *adp, int n)
930 tga_clear(video_adapter_t *adp)
939 if(n == 0) return(0);
942 /* Save the pixel mode... */
943 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
945 /* Save the pixel mask... */
946 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
948 /* Save the raster op... */
949 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
951 /* Set the pixel mode (opaque-fill)... */
952 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
953 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_OPQ_FILL);
955 /* Set the pixel mask (enable writes to all pixels)... */
956 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, 0xffffffff);
958 /* Set the raster op (clear)... */
959 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x00);
962 Just traverse the buffer, one 2K-pixel span at a time, clearing
966 for(off = 0; off < (n * adp->va_line_width); off += (2 KB))
968 for(off = 0; off < adp->va_window_size; off += (2 KB))
969 WRITE_GFB_BUFFER(adp, off >> 2L, 0x000007ff);
971 /* Restore the pixel mask... */
972 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
974 /* Restore the raster op... */
975 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
977 /* Restore the pixel mode... */
978 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
984 tga_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
996 struct gfb_softc *sc;
999 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1000 pixel_size = adp->va_info.vi_depth / 8;
1002 /* Save the pixel mode... */
1003 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
1005 /* Save the pixel mask... */
1006 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
1008 /* Save the raster op... */
1009 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
1011 /* Save the background color... */
1012 gbgr = READ_GFB_REGISTER(adp, TGA_REG_GBGR);
1014 /* Save the foreground color... */
1015 gfgr = READ_GFB_REGISTER(adp, TGA_REG_GFGR);
1017 /* Set the pixel mode (opaque-stipple)... */
1018 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
1019 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_OPQ_STPL);
1021 /* Set the pixel mask (enable writes to the first cwidth pixels)... */
1022 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P,
1023 (1 << adp->va_info.vi_cwidth) - 1);
1025 /* Set the raster op (src)... */
1026 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
1028 /* Set the foreground color mask from the attribute byte... */
1029 mask = (a & 0x80) ? a : (a & 0x0f);
1031 /* Propagate the 8-bit mask across the full 32 bits... */
1032 mask |= (mask << 24) | (mask << 16) | (mask << 8);
1034 /* Set the foreground color... */
1035 WRITE_GFB_REGISTER(adp, TGA_REG_GFGR, mask);
1037 /* Set the background color mask from the attribute byte... */
1038 mask = (a >> 4) & 0x07;
1040 /* Propagate the 8-bit mask across the full 32 bits... */
1041 mask |= (mask << 24) | (mask << 16) | (mask << 8);
1043 /* Set the background color... */
1044 WRITE_GFB_REGISTER(adp, TGA_REG_GBGR, mask);
1046 /* Get the start of the array of pixels rows for this character... */
1047 pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight);
1049 /* Calculate the new cursor position... */
1050 row = off / adp->va_info.vi_width;
1051 col = off % adp->va_info.vi_width;
1053 /* Iterate over all the pixel rows for this character... */
1054 for(i = 0; i < adp->va_info.vi_cheight; i++) {
1056 /* Get the address of the character's pixel-row... */
1057 poff = ((col * adp->va_info.vi_cwidth * pixel_size) +
1058 (((row * adp->va_info.vi_cheight) + i) *
1059 adp->va_line_width)) / sizeof(gfb_reg_t);
1061 /* Now display the current pixel row... */
1062 WRITE_GFB_BUFFER(adp, poff, pixel[i]);
1065 /* Restore the foreground color... */
1066 WRITE_GFB_REGISTER(adp, TGA_REG_GFGR, gfgr);
1068 /* Restore the background color... */
1069 WRITE_GFB_REGISTER(adp, TGA_REG_GBGR, gbgr);
1071 /* Restore the pixel mode... */
1072 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
1074 /* Restore the pixel mask... */
1075 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
1077 /* Restore the raster op... */
1078 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
1084 tga_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
1096 struct gfb_softc *sc;
1099 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1100 pixel_size = adp->va_info.vi_depth / 8;
1102 /* If the string in empty, just return now... */
1103 if(len == 0) return(0);
1105 for(i = 0; i < len; i++)
1106 tga_putc(adp, off + i, s[i] & 0x00ff, (s[i] & 0xff00) >> 8);
1109 /* Save the pixel mode... */
1110 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
1112 /* Save the pixel mask... */
1113 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
1115 /* Save the raster op... */
1116 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
1118 /* Set the pixel mode (simple)... */
1119 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, (gmor & 0xffffffc0) | 0x00);
1121 /* Set the pixel mask (enable writes to all 32 pixels)... */
1122 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, (gpxr & 0xfffffff0) | 0xf);
1124 /* Set the raster op (src)... */
1125 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x03);
1128 First, do as many characters-rows at a time as possible (as exist)...
1130 for(i = 0; (len - i) > adp->va_info.vi_width;
1131 i += adp->va_info.vi_width) {
1134 Iterate over all the pixels for each character in the
1135 character-row, doing a scan-line at-a-time, rather than
1136 a character at-a-time (like tga_putc())...
1138 for(j = 0; j < adp->va_info.vi_cheight; j++) {
1140 for(k = 0; k < adp->va_info.vi_width; k++) {
1143 Get this character...
1145 c = s[i + k] & 0x00ff;
1148 Get the attribute for this character...
1150 a = (s[i + k] & 0xff00) >> 8;
1153 Get the start of the array of pixels rows for
1156 pixel = sc->gfbc->font +
1157 (c * adp->va_info.vi_cheight);
1159 /* Shift the other pre-existing pixel rows... */
1163 Get the first pixel row for
1168 if (((k + 1) % sizeof(gfb_reg_t)) == 0) {
1171 Calculate the new cursor
1174 row = (off + i + (k -
1175 (sizeof(gfb_reg_t) - 1))) /
1176 adp->va_info.vi_width;
1177 col = (off + i + (k -
1178 (sizeof(gfb_reg_t) - 1))) %
1179 adp->va_info.vi_width;
1182 Get the address of the current
1183 character's pixel-row...
1185 poff = ((col * adp->va_info.vi_cwidth *
1186 pixel_size) + (((row *
1187 adp->va_info.vi_cheight) + j) *
1188 adp->va_line_width)) /
1192 Now display the current
1195 (*vidsw[adp->va_index]->putp)(adp, poff,
1196 p, a, sizeof(gfb_reg_t),
1197 adp->va_info.vi_depth, 1, 0);
1199 /* Reset (clear) p... */
1207 Next, do as many character-sets at a time as possible (as exist)...
1209 for(; (len - i) > sizeof(gfb_reg_t); i += sizeof(gfb_reg_t)) {
1212 Iterate over all the pixels for each character in the
1213 character-row, doing a scan-line at-a-time, rather than
1214 a character at-a-time (like tga_putc())...
1216 for(j = 0; j < adp->va_info.vi_cheight; j++) {
1218 for(k = 0; k < sizeof(gfb_reg_t); k++) {
1221 Get this character...
1223 c = s[i + k] & 0x00ff;
1226 Get the attribute for this character...
1228 a = (s[i + k] & 0xff00) >> 8;
1231 Get the start of the array of pixels rows for
1234 pixel = sc->gfbc->font +
1235 (c * adp->va_info.vi_cheight);
1237 /* Shift the other pre-existing pixel rows... */
1241 Get the first pixel row for
1246 if (((k + 1) % sizeof(gfb_reg_t)) == 0) {
1249 Calculate the new cursor
1252 row = (off + i) / adp->va_info.vi_width;
1253 col = (off + i) % adp->va_info.vi_width;
1256 Get the address of the current
1257 character's pixel-row...
1259 poff = ((col * adp->va_info.vi_cwidth *
1260 pixel_size) + (((row *
1261 adp->va_info.vi_cheight) + j) *
1262 adp->va_line_width)) /
1266 Now display the current
1269 (*vidsw[adp->va_index]->putp)(adp, poff,
1270 p, a, sizeof(gfb_reg_t),
1271 adp->va_info.vi_depth, 1, 0);
1273 /* Reset (clear) p... */
1280 /* Restore the pixel mode... */
1281 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
1283 /* Restore the pixel mask... */
1284 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
1286 /* Restore the raster op... */
1287 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
1289 /* Finally, do the remaining characters a character at-a-time... */
1290 for(; i < len; i++) {
1292 Get this character...
1297 Get the attribute for this character...
1299 a = (s[i] & 0xff00) >> 8;
1302 Display this character...
1304 tga_putc(adp, off + i, c, a);
1310 tga_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
1311 gfb_reg_t pixel_mask, int size)
1319 pixel_size = adp->va_info.vi_depth / 8;
1321 /* Save the pixel mode... */
1322 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
1324 /* Save the pixel mask... */
1325 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
1327 /* Save the raster op... */
1328 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
1330 /* Set the pixel mode (simple)... */
1331 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
1332 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_SIMPLE);
1334 /* Set the pixel mask (enable writes to the first 8 pixels)... */
1335 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, (gpxr & 0xfffffff0) | 0xf);
1337 /* Set the raster op (src)... */
1338 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
1340 /* Iterate over all the pixel rows for the mouse pointer... */
1341 for(i = 0; i < size; i++) {
1343 /* Get the address of the mouse pointer's pixel-row... */
1344 poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) /
1347 /* Now display the current pixel-row... */
1348 (*vidsw[adp->va_index]->putp)(adp, poff, pixel_image[i],
1349 pixel_mask, sizeof(u_int8_t), adp->va_info.vi_depth, 1, 0);
1352 /* Restore the pixel mode... */
1353 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
1355 /* Restore the pixel mask... */
1356 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
1358 /* Restore the raster op... */
1359 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
1370 /*****************************************************************************
1372 * TGA-specific functions
1374 ****************************************************************************/
1377 tga_builtin_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
1381 struct gfb_softc *sc;
1384 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1387 * We store 8 bit values in the palette buffer, while the standard
1388 * VGA has 6 bit DAC .
1390 outb(PALRADR, 0x00);
1391 for(i = 0; i < palette->count; ++i) {
1392 palette->red[i] = inb(PALDATA) << 2;
1393 palette->green[i] = inb(PALDATA) << 2;
1394 palette->blue[i] = inb(PALDATA) << 2;
1400 tga_builtin_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
1404 struct gfb_softc *sc;
1407 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1410 * We store 8 bit values in the palette buffer, while the standard
1411 * VGA has 6 bit DAC .
1413 outb(PIXMASK, 0xff);
1414 outb(PALWADR, 0x00);
1415 for(i = 0; i < palette->count; ++i) {
1416 outb(PALDATA, palette->red[i] >> 2);
1417 outb(PALDATA, palette->green[i] >> 2);
1418 outb(PALDATA, palette->blue[i] >> 2);
1425 tga2_builtin_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
1429 struct gfb_softc *sc;
1432 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1434 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1435 BT463_IREG_CPALETTE_RAM & 0xff);
1436 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1437 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
1439 /* spit out the colormap data */
1440 for(i = 0; i < palette->count; i++) {
1441 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1443 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1445 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1452 tga2_builtin_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
1456 struct gfb_softc *sc;
1459 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1461 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1462 BT463_IREG_CPALETTE_RAM & 0xff);
1463 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1464 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
1466 /* spit out the colormap data */
1467 for(i = 0; i < palette->count; i++) {
1468 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1470 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1472 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1479 tga2_builtin_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
1483 struct gfb_softc *sc;
1486 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1488 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1489 BT463_IREG_CURSOR_COLOR_0 & 0xff);
1490 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1491 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
1493 /* spit out the cursor data */
1494 for(i = 0; i < palette->count; i++) {
1495 BTWNREG(sc, palette->red[i]);
1496 BTWNREG(sc, palette->green[i]);
1497 BTWNREG(sc, palette->blue[i]);
1503 tga2_builtin_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
1507 struct gfb_softc *sc;
1510 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1512 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1513 BT463_IREG_CURSOR_COLOR_0 & 0xff);
1514 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1515 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
1517 /* spit out the cursor data */
1518 for(i = 0; i < palette->count; i++) {
1519 BTWNREG(sc, palette->red[i]);
1520 BTWNREG(sc, palette->green[i]);
1521 BTWNREG(sc, palette->blue[i]);
1529 tga_builtin_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
1534 /* Assume the best... */
1537 cxyr = READ_GFB_REGISTER(adp, TGA_REG_CXYR) | 0x00ffffff;
1538 *col = (cxyr & 0x00000fff) / adp->va_info.vi_cwidth;
1539 *row = ((cxyr & 0x00fff000) >> 12) / adp->va_info.vi_cheight;
1544 tga_builtin_set_hw_cursor(video_adapter_t *adp, int col, int row)
1550 /* Assume the best... */
1553 vvvr = READ_GFB_REGISTER(adp, TGA_REG_VVVR);
1556 Make sure the parameters are in range for the screen
1559 if((row > adp->va_info.vi_height) ||
1560 (col > adp->va_info.vi_width))
1562 else if(((row * adp->va_info.vi_cheight) > 0x0fff) ||
1563 ((col * adp->va_info.vi_cwidth) > 0x0fff))
1566 If either of the parameters is less than 0,
1567 then hide the cursor...
1569 else if((row < 0) || (col < 0)) {
1570 if((vvvr & 0x00000004) != 0) {
1572 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1576 /* Otherwise, just move the cursor as requested... */
1578 cxyr = READ_GFB_REGISTER(adp, TGA_REG_CXYR) & 0xff000000;
1579 cxyr |= ((row * adp->va_info.vi_cheight) << 12);
1580 cxyr |= (col * adp->va_info.vi_cwidth);
1581 WRITE_GFB_REGISTER(adp, TGA_REG_CXYR, cxyr);
1582 if((vvvr & 0x00000004) == 0) {
1584 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1591 tga_builtin_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
1592 int cellsize, int blink)
1596 gfb_reg_t window_orig;
1601 /* Assume the best... */
1604 vvvr = READ_GFB_REGISTER(adp, TGA_REG_VVVR);
1607 Make sure the parameters are in range for the cursor
1608 (it's a 64x64 cursor)...
1613 /* If height is less than or equal to 0, then hide the cursor... */
1614 else if(height <= 0) {
1615 if((vvvr & 0x00000004) != 0) {
1617 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1621 /* Otherwise, just resize the cursor as requested... */
1623 ccbr = READ_GFB_REGISTER(adp, TGA_REG_CCBR);
1625 ccbr |= ((height - 1) << 10);
1626 WRITE_GFB_REGISTER(adp, TGA_REG_CCBR, ccbr);
1627 if((vvvr & 0x00000004) == 0) {
1629 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1632 /* Save the window origin... */
1633 window_orig = adp->va_window_orig;
1636 Fill in the cursor image (64 rows of 64 pixels per cursor
1637 row at 2 bits-per-pixel, so 64 rows of 16 bytes each)--we
1638 set va_window_orig to the cursor base address temporarily
1639 so that we can write to the cursor image...
1641 cba = (READ_GFB_REGISTER(adp, TGA_REG_CCBR) & 0xfffffc0f) >> 4;
1642 adp->va_window_orig = cba;
1643 for(i = 0; i < (64 - height); i++) {
1644 WRITE_GFB_BUFFER(adp, cba++, 0x00000000);
1645 WRITE_GFB_BUFFER(adp, cba++, 0x00000000);
1647 for(; i < 64; i++) {
1648 for(j = 0; j < (((64 - cellsize) / 8) /
1649 sizeof(gfb_reg_t)); j++)
1650 WRITE_GFB_BUFFER(adp, cba++, 0x00000000);
1651 for(; j < ((64 / 8) / sizeof(gfb_reg_t)); j++)
1652 WRITE_GFB_BUFFER(adp, cba++, 0xffffffff);
1655 /* Restore the window origin... */
1656 adp->va_window_orig = window_orig;
1663 bt463_load_palette_intr(struct gfb_softc *sc)
1665 sc->gfbc->ramdac_save_palette(sc->adp, &sc->gfbc->palette);
1669 bt463_load_cursor_palette_intr(struct gfb_softc *sc)
1671 sc->gfbc->ramdac_load_cursor_palette(sc->adp, &sc->gfbc->cursor_palette);
1675 tga_schedule_intr(struct gfb_softc *sc, void (*f)(struct gfb_softc *))
1677 /* Busy-wait for the previous interrupt to complete... */
1678 while((READ_GFB_REGISTER(sc->adp, TGA_REG_SISR) & 0x00000001) != 0);
1680 /* Arrange for f to be called at the next end-of-frame interrupt... */
1681 sc->gfbc->ramdac_intr = f;
1683 /* Enable the interrupt... */
1684 WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, 0x00010000);
1689 tga_bt485_rd(struct gfb_softc *sc, u_int btreg)
1693 if(btreg > BT485_REG_MAX)
1694 panic("tga_ramdac_rd: reg %d out of range\n", btreg);
1695 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 1) | 0x1);
1696 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1697 rdval = READ_GFB_REGISTER(sc->adp, TGA_REG_EPDR);
1698 return((rdval >> 16) & 0xff);
1702 tga_bt485_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
1704 if(btreg > BT485_REG_MAX)
1705 panic("tga_ramdac_wr: reg %d out of range\n", btreg);
1706 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR,
1707 (btreg << 9) | (0 << 8 ) | val);
1708 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1712 tga2_ibm561_rd(struct gfb_softc *sc, u_int btreg)
1714 bus_space_handle_t ramdac;
1717 if(btreg > BT485_REG_MAX)
1718 panic("tga_ramdac_rd: reg %d out of range\n", btreg);
1719 ramdac = sc->bhandle + TGA2_MEM_RAMDAC + (0xe << 12) + (btreg << 8);
1720 retval = bus_space_read_4(sc->btag, ramdac, 0) & 0xff;
1721 bus_space_barrier(sc->btag, ramdac, 0, 4, BUS_SPACE_BARRIER_READ);
1726 tga2_ibm561_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
1728 bus_space_handle_t ramdac;
1730 if(btreg > BT485_REG_MAX)
1731 panic("tga_ramdac_wr: reg %d out of range\n", btreg);
1732 ramdac = sc->bhandle + TGA2_MEM_RAMDAC + (0xe << 12) + (btreg << 8);
1733 bus_space_write_4(sc->btag, ramdac, 0, val & 0xff);
1734 bus_space_barrier(sc->btag, ramdac, 0, 4, BUS_SPACE_BARRIER_WRITE);
1738 tga_bt463_rd(struct gfb_softc *sc, u_int btreg)
1743 * Strobe CE# (high->low->high) since status and data are latched on
1744 * the falling and rising edges (repsectively) of this active-low
1748 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1749 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
1750 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1751 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 2) | 2 | 0);
1752 GFB_REGISTER_READ_BARRIER(sc, TGA_REG_EPSR, 1);
1753 rdval = READ_GFB_REGISTER(sc->adp, TGA_REG_EPDR);
1754 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1755 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
1756 return((rdval >> 16) & 0xff);
1760 tga_bt463_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
1763 * In spite of the 21030 documentation, to set the MPU bus bits for
1764 * a write, you set them in the upper bits of EPDR, not EPSR.
1768 * Strobe CE# (high->low->high) since status and data are latched on
1769 * the falling and rising edges of this active-low signal.
1772 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1773 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
1774 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1775 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR, (btreg << 10) | 0x000 | val);
1776 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1777 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
1781 tga2_ics9110_wr(struct gfb_softc *sc, int dotclock)
1783 bus_space_handle_t clock;
1790 N = 0x40; M = 0x7; V = 0x0; X = 0x1; R = 0x1; break;
1792 N = 0x2d; M = 0x2b; V = 0x1; X = 0x1; R = 0x1; break;
1794 N = 0x11; M = 0x9; V = 0x1; X = 0x1; R = 0x2; break;
1796 N = 0x6d; M = 0xf; V = 0x0; X = 0x1; R = 0x1; break;
1798 N = 0x5F; M = 0x3E; V = 0x1; X = 0x1; R = 0x1; break;
1800 N = 0x6e; M = 0x15; V = 0x0; X = 0x1; R = 0x1; break;
1802 N = 0x2a; M = 0x41; V = 0x1; X = 0x1; R = 0x1; break;
1804 N = 0x35; M = 0xb; V = 0x0; X = 0x1; R = 0x1; break;
1806 N = 0x6d; M = 0x0c; V = 0x0; X = 0x1; R = 0x2; break;
1808 N = 0x37; M = 0x3f; V = 0x1; X = 0x1; R = 0x2; break;
1810 N = 0x5f; M = 0x11; V = 0x0; X = 0x1; R = 0x2; break;
1812 N = 0x16; M = 0x05; V = 0x0; X = 0x1; R = 0x2; break;
1814 N = 0x66; M = 0x1d; V = 0x0; X = 0x1; R = 0x2; break;
1816 N = 0x42; M = 0x07; V = 0x0; X = 0x1; R = 0x1; break;
1818 N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
1820 N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
1822 panic("unrecognized clock rate %d\n", dotclock);
1825 /* XXX -- hard coded, bad */
1826 valU = N | ( M << 7 ) | (V << 14);
1827 valU |= (X << 15) | (R << 17);
1829 clock = sc->bhandle + TGA2_MEM_EXTDEV + TGA2_MEM_CLOCK + (0xe << 12);
1830 for(i = 24; i > 0; i--) {
1833 writeval = valU & 0x1;
1837 bus_space_write_4(sc->btag, clock, 0, writeval);
1838 bus_space_barrier(sc->btag, clock, 0, 4,
1839 BUS_SPACE_BARRIER_WRITE);
1841 clock = sc->bhandle + TGA2_MEM_EXTDEV + TGA2_MEM_CLOCK + (0xe << 12) +
1842 (0x1 << 11) + (0x1 << 11);
1843 bus_space_write_4(sc->btag, clock, 0, 0x0);
1844 bus_space_barrier(sc->btag, clock, 0, 0, BUS_SPACE_BARRIER_WRITE);
1847 /*****************************************************************************
1849 * BrookTree RAMDAC-specific functions
1851 ****************************************************************************/
1854 bt463_init(struct gfb_softc *sc)
1861 * Init the BT463 for normal operation.
1866 * reg 0: 4:1 multiplexing, 25/75 blink.
1867 * reg 1: Overlay mapping: mapped to common palette,
1868 * 14 window type entries, 24-plane configuration mode,
1869 * 4 overlay planes, underlays disabled, no cursor.
1870 * reg 2: sync-on-green enabled, pedestal enabled.
1873 BTWREG(sc, BT463_IREG_COMMAND_0, 0x40);
1874 BTWREG(sc, BT463_IREG_COMMAND_1, 0x48);
1875 BTWREG(sc, BT463_IREG_COMMAND_2, 0xC0);
1878 * Initialize the read mask.
1880 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1881 BT463_IREG_READ_MASK_P0_P7 & 0xff);
1882 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1883 (BT463_IREG_READ_MASK_P0_P7 >> 8) & 0xff);
1884 for(i = 0; i < 4; i++)
1888 * Initialize the blink mask.
1890 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1891 BT463_IREG_READ_MASK_P0_P7 & 0xff);
1892 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1893 (BT463_IREG_READ_MASK_P0_P7 >> 8) & 0xff);
1894 for(i = 0; i < 4; i++)
1898 * Clear test register
1900 BTWREG(sc, BT463_IREG_TEST, 0);
1903 * Initalize the RAMDAC info struct to hold all of our
1904 * data, and fill it in.
1907 /* Initialize the window type table:
1909 * Entry 0: 24-plane truecolor, overlays enabled, bypassed.
1911 * Lookup table bypass: yes ( 1 << 23 & 0x800000) 800000
1912 * Colormap address: 0x000 (0x000 << 17 & 0x7e0000) 0
1913 * Overlay mask: 0xf ( 0xf << 13 & 0x01e000) 1e000
1914 * Overlay location: P<27:24> ( 0 << 12 & 0x001000) 0
1915 * Display mode: Truecolor ( 0 << 9 & 0x000e00) 000
1916 * Number of planes: 8 ( 8 << 5 & 0x0001e0) 100
1917 * Plane shift: 0 ( 0 << 0 & 0x00001f) 0
1922 data->window_type[0] = 0x81e100;
1925 /* Entry 1: 8-plane pseudocolor in the bottom 8 bits,
1926 * overlays enabled, colormap starting at 0.
1928 * Lookup table bypass: no ( 0 << 23 & 0x800000) 0
1929 * Colormap address: 0x000 (0x000 << 17 & 0x7e0000) 0
1930 * Overlay mask: 0xf ( 0xf << 13 & 0x01e000) 0x1e000
1931 * Overlay location: P<27:24> ( 0 << 12 & 0x001000) 0
1932 * Display mode: Pseudocolor ( 1 << 9 & 0x000e00) 0x200
1933 * Number of planes: 8 ( 8 << 5 & 0x0001e0) 0x100
1934 * Plane shift: 16 ( 0x10 << 0 & 0x00001f) 10
1939 data->window_type[1] = 0x01e310;
1941 /* The colormap interface to the world only supports one colormap,
1942 * so having an entry for the 'alternate' colormap in the bt463
1943 * probably isn't useful.
1946 /* Fill the remaining table entries with clones of entry 0 until we
1947 * figure out a better use for them.
1950 for(i = 2; i < BT463_NWTYPE_ENTRIES; i++) {
1951 data->window_type[i] = 0x81e100;
1955 tga_schedule_intr(sc, bt463_update_window_type);
1956 tga_schedule_intr(sc, bt463_load_cursor_palette_intr);
1957 tga_schedule_intr(sc, bt463_load_palette_intr);
1961 bt463_update_window_type(struct gfb_softc *sc)
1965 /* The Bt463 won't accept window type data except during a blanking
1966 * interval, so we do this early in the interrupt.
1967 * Blanking the screen might also be a good idea, but it can cause
1968 * unpleasant flashing and is hard to do from this side of the
1971 /* spit out the window type data */
1972 for(i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
1974 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1975 (BT463_IREG_WINDOW_TYPE_TABLE + i) & 0xff);
1976 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1977 ((BT463_IREG_WINDOW_TYPE_TABLE + i) >> 8) & 0xff);
1978 BTWNREG(sc, (data->window_type[i]) & 0xff);
1979 BTWNREG(sc, (data->window_type[i] >> 8) & 0xff);
1980 BTWNREG(sc, (data->window_type[i] >> 16) & 0xff);
1987 bt463_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
1989 struct gfb_softc *sc;
1993 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1995 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1996 BT463_IREG_CPALETTE_RAM & 0xff);
1997 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1998 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
2000 /* get the colormap data */
2001 for(i = 0; i < palette->count; i++) {
2002 palette->red[i] = sc->gfbc->ramdac_rd(sc, BT463_REG_CMAP_DATA);
2003 palette->green[i] = sc->gfbc->ramdac_rd(sc,
2004 BT463_REG_CMAP_DATA);
2005 palette->blue[i] = sc->gfbc->ramdac_rd(sc, BT463_REG_CMAP_DATA);
2011 bt463_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
2013 struct gfb_softc *sc;
2017 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2019 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
2020 BT463_IREG_CPALETTE_RAM & 0xff);
2021 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
2022 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
2024 /* spit out the colormap data */
2025 for(i = 0; i < palette->count; i++) {
2026 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, palette->red[i]);
2027 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, palette->green[i]);
2028 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, palette->blue[i]);
2036 bt463_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2038 struct gfb_softc *sc;
2042 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2044 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
2045 BT463_IREG_CURSOR_COLOR_0 & 0xff);
2046 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
2047 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
2049 /* spit out the cursor data */
2050 for(i = 0; i < palette->count; i++) {
2051 palette->red[i] = BTRNREG(sc);
2052 palette->green[i] = BTRNREG(sc);
2053 palette->blue[i] = BTRNREG(sc);
2059 bt463_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2061 struct gfb_softc *sc;
2065 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2067 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
2068 BT463_IREG_CURSOR_COLOR_0 & 0xff);
2069 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
2070 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
2072 /* spit out the cursor data */
2073 for(i = 0; i < palette->count; i++) {
2074 BTWNREG(sc, palette->red[i]);
2075 BTWNREG(sc, palette->green[i]);
2076 BTWNREG(sc, palette->blue[i]);
2082 bt485_init(struct gfb_softc *sc)
2084 int i, j, num_cmap_entries;
2087 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_0);
2090 * Set the RAMDAC to 8 bit resolution, rather than 6 bit
2096 * Set the RAMDAC to sync-on-green.
2099 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_0, regval);
2102 /* Set the RAMDAC to 8BPP (no interesting options). */
2103 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_1, 0x40);
2105 /* Disable the cursor (for now) */
2106 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_2);
2109 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
2111 /* Use a 64x64x2 cursor */
2112 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, BT485_IREG_COMMAND_3);
2113 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2116 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, BT485_IREG_COMMAND_3);
2117 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2119 /* Set the Pixel Mask to something useful */
2120 sc->gfbc->ramdac_wr(sc, BT485_REG_PIXMASK, 0xff);
2123 /* Generate the cursor color map (Light-Grey)... */
2124 for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
2125 sc->gfbc->cursor_palette.red[i] = default_cmap[7].red;
2126 sc->gfbc->cursor_palette.green[i] = default_cmap[7].green;
2127 sc->gfbc->cursor_palette.blue[i] = default_cmap[7].blue;
2131 /* Enable cursor... */
2132 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_2);
2133 if(!(regval & 0x01)) {
2135 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
2137 else if(regval & 0x03) {
2139 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
2143 /* Generate the screen color map... */
2144 num_cmap_entries = sizeof(default_cmap) / sizeof(struct cmap);
2145 for(i = 0; i < sc->gfbc->palette.count / num_cmap_entries; i++)
2146 for(j = 0; j < num_cmap_entries; j++) {
2147 sc->gfbc->palette.red[(num_cmap_entries * i) + j] =
2148 default_cmap[j].red;
2149 sc->gfbc->palette.green[(num_cmap_entries * i) + j] =
2150 default_cmap[j].green;
2151 sc->gfbc->palette.blue[(num_cmap_entries * i) + j] =
2152 default_cmap[j].blue;
2157 bt485_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
2159 struct gfb_softc *sc;
2163 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2165 /* addr[9:0] assumed to be 0 */
2166 /* set addr[7:0] to 0 */
2167 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0x00);
2169 /* spit out the color data */
2170 for(i = 0; i < palette->count; i++) {
2171 palette->red[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_PALETTE);
2172 palette->green[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_PALETTE);
2173 palette->blue[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_PALETTE);
2179 bt485_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
2181 struct gfb_softc *sc;
2185 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2187 /* addr[9:0] assumed to be 0 */
2188 /* set addr[7:0] to 0 */
2189 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0x00);
2191 /* spit out the color data */
2192 for(i = 0; i < palette->count; i++) {
2193 sc->gfbc->ramdac_wr(sc, BT485_REG_PALETTE, palette->red[i]);
2194 sc->gfbc->ramdac_wr(sc, BT485_REG_PALETTE, palette->green[i]);
2195 sc->gfbc->ramdac_wr(sc, BT485_REG_PALETTE, palette->blue[i]);
2201 bt485_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2203 struct gfb_softc *sc;
2207 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2209 /* addr[9:0] assumed to be 0 */
2210 /* set addr[7:0] to 1 */
2211 sc->gfbc->ramdac_wr(sc, BT485_REG_COC_WRADDR, 0x01);
2213 /* spit out the cursor color data */
2214 for(i = 0; i < palette->count; i++) {
2215 palette->red[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_COCDATA);
2216 palette->green[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_COCDATA);
2217 palette->blue[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_COCDATA);
2223 bt485_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2225 struct gfb_softc *sc;
2229 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2231 /* addr[9:0] assumed to be 0 */
2232 /* set addr[7:0] to 1 */
2233 sc->gfbc->ramdac_wr(sc, BT485_REG_COC_WRADDR, 0x01);
2235 /* spit out the cursor color data */
2236 for(i = 0; i < palette->count; i++) {
2237 sc->gfbc->ramdac_wr(sc, BT485_REG_COCDATA, palette->red[i]);
2238 sc->gfbc->ramdac_wr(sc, BT485_REG_COCDATA, palette->green[i]);
2239 sc->gfbc->ramdac_wr(sc, BT485_REG_COCDATA, palette->blue[i]);
2245 bt485_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
2247 struct gfb_softc *sc;
2251 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2253 *col = (sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_X_HIGH) & 0x0f) << 8;
2254 *col |= sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_X_LOW) & 0xff;
2255 *col /= adp->va_info.vi_cwidth;
2257 *row = (sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_Y_HIGH) & 0x0f) << 8;
2258 *row |= sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_Y_LOW) & 0xff;
2259 *row /= adp->va_info.vi_cheight;
2266 bt485_set_hw_cursor(video_adapter_t *adp, int col, int row)
2268 struct gfb_softc *sc;
2273 /* Make sure the parameters are in range for the screen
2275 if((row > adp->va_info.vi_height) || (col > adp->va_info.vi_width))
2277 else if(((row * adp->va_info.vi_cheight) > 0x0fff) ||
2278 ((col * adp->va_info.vi_cwidth) > 0x0fff))
2280 else if((row < 0) || (col < 0)) {
2281 /* If either of the parameters is less than 0, then hide the
2286 /* Otherwise, just move the cursor as requested... */
2287 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2289 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_X_LOW,
2290 ((col + 8) * adp->va_info.vi_cwidth) & 0xff);
2291 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_X_HIGH,
2292 (((col + 8) * adp->va_info.vi_cwidth) >> 8) & 0x0f);
2293 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_Y_LOW,
2294 ((row + 4) * adp->va_info.vi_cheight) & 0xff);
2295 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_Y_HIGH,
2296 (((row + 4) * adp->va_info.vi_cheight) >> 8) & 0x0f);
2303 bt485_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
2304 int cellsize, int blink)
2306 struct gfb_softc *sc;
2307 int error, cell_count, count, i, j;
2312 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2315 Make sure the parameters are in range for the cursor
2316 (it's a 64x64 cursor)...
2320 else if(height <= 0) {
2321 /* If height is less than or equal to 0, then hide the
2324 /* Otherwise, just resize the cursor as requested... */
2326 /* 64 pixels per cursor-row, 2 bits-per-pixel, so counts in
2328 cell_count = cellsize / 8;
2332 * Write the cursor image data:
2333 * set addr[9:8] to 0,
2334 * set addr[7:0] to 0,
2337 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2338 BT485_IREG_COMMAND_3);
2339 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2341 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2342 BT485_IREG_COMMAND_3);
2343 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2344 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0);
2346 /* Fill-in the desired pixels in the specified pixel-rows... */
2347 for(i = 0; i < height; i++) {
2348 for(j = 0; j < cell_count; j++)
2349 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2351 for(j = 0; j < count - cell_count; j++)
2352 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2356 /* Clear the remaining pixel rows... */
2358 for(j = 0; j < count; j++)
2359 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2363 * Write the cursor mask data:
2364 * set addr[9:8] to 2,
2365 * set addr[7:0] to 0,
2368 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2369 BT485_IREG_COMMAND_3);
2370 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2371 regval &= ~0x03; regval |= 0x02;
2372 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2373 BT485_IREG_COMMAND_3);
2374 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2375 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0);
2377 /* Fill-in the desired pixels in the specified pixel-rows... */
2378 for(i = 0; i < height; i++) {
2379 for(j = 0; j < cell_count; j++)
2380 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2382 for(j = 0; j < count - cell_count; j++)
2383 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2387 /* Clear the remaining pixel rows... */
2389 for(j = 0; j < count; j++)
2390 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2393 /* set addr[9:0] back to 0 */
2394 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2395 BT485_IREG_COMMAND_3);
2396 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2398 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2399 BT485_IREG_COMMAND_3);
2400 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2406 ibm561_init(struct gfb_softc *sc)
2411 ibm561_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
2420 ibm561_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
2429 ibm561_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2438 ibm561_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)