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
27 * $FreeBSD: src/sys/dev/fb/tga.c,v 1.1.2.1 2001/11/01 08:33:14 obrien Exp $
28 * $DragonFly: src/sys/dev/video/fb/Attic/tga.c,v 1.4 2003/11/09 02:22:35 dillon Exp $
31 * Copyright (c) 1995, 1996 Carnegie-Mellon University.
32 * All rights reserved.
34 * Author: Chris G. Demetriou
36 * Permission to use, copy, modify and distribute this software and
37 * its documentation is hereby granted, provided that both the copyright
38 * notice and this permission notice appear in all copies of the
39 * software, derivative works or modified versions, and any portions
40 * thereof, and that both notices appear in supporting documentation.
42 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
44 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
46 * Carnegie Mellon requests users of this software to return to
48 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
49 * School of Computer Science
50 * Carnegie Mellon University
51 * Pittsburgh PA 15213-3890
53 * any improvements or extensions that they make and grant Carnegie the
54 * rights to redistribute these changes.
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 <bus/isa/isareg.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 <bus/pci/pcireg.h>
89 #include <bus/pci/pcivar.h>
92 #include <dev/syscons/syscons.h>
94 #include <dev/gfb/gfb_pci.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;
108 static gfb_builtin_save_palette_t tga2_builtin_save_palette;
109 static gfb_builtin_load_palette_t tga2_builtin_load_palette;
110 static gfb_builtin_save_cursor_palette_t tga2_builtin_save_cursor_palette;
111 static gfb_builtin_load_cursor_palette_t tga2_builtin_load_cursor_palette;
112 static gfb_builtin_read_hw_cursor_t tga_builtin_read_hw_cursor;
113 static gfb_builtin_set_hw_cursor_t tga_builtin_set_hw_cursor;
114 static gfb_builtin_set_hw_cursor_shape_t tga_builtin_set_hw_cursor_shape;
115 static void bt463_load_palette_intr(struct gfb_softc *);
116 static void bt463_load_cursor_palette_intr(struct gfb_softc *);
117 static int tga_schedule_intr(struct gfb_softc *, void (*)(struct gfb_softc *));
119 /* RAMDAC interface functions */
120 static gfb_ramdac_wr_t tga_bt485_wr;
121 static gfb_ramdac_rd_t tga_bt485_rd;
122 static gfb_ramdac_wr_t tga_bt463_wr;
123 static gfb_ramdac_rd_t tga_bt463_rd;
124 static gfb_ramdac_wr_t tga2_ibm561_wr;
125 static gfb_ramdac_rd_t tga2_ibm561_rd;
126 static void tga2_ics9110_wr(struct gfb_softc *, int);
128 /* RAMDAC-specific functions */
129 static gfb_ramdac_init_t bt463_init;
130 static void bt463_update_window_type(struct gfb_softc *);
131 static gfb_ramdac_save_palette_t bt463_save_palette;
132 static gfb_ramdac_load_palette_t bt463_load_palette;
133 static gfb_ramdac_save_cursor_palette_t bt463_save_cursor_palette;
134 static gfb_ramdac_load_cursor_palette_t bt463_load_cursor_palette;
135 static gfb_ramdac_init_t bt485_init;
136 static gfb_ramdac_save_palette_t bt485_save_palette;
137 static gfb_ramdac_load_palette_t bt485_load_palette;
138 static gfb_ramdac_save_cursor_palette_t bt485_save_cursor_palette;
139 static gfb_ramdac_load_cursor_palette_t bt485_load_cursor_palette;
140 static gfb_ramdac_read_hw_cursor_t bt485_read_hw_cursor;
141 static gfb_ramdac_set_hw_cursor_t bt485_set_hw_cursor;
142 static gfb_ramdac_set_hw_cursor_shape_t bt485_set_hw_cursor_shape;
143 static gfb_ramdac_init_t ibm561_init;
144 static gfb_ramdac_save_palette_t ibm561_save_palette;
145 static gfb_ramdac_load_palette_t ibm561_load_palette;
146 static gfb_ramdac_save_cursor_palette_t ibm561_save_cursor_palette;
147 static gfb_ramdac_load_cursor_palette_t ibm561_load_cursor_palette;
149 /* Video Driver-generic functions */
150 static vi_query_mode_t tga_query_mode;
151 static vi_set_mode_t tga_set_mode;
152 static vi_blank_display_t tga_blank_display;
153 static vi_ioctl_t tga_ioctl;
154 static vi_set_border_t tga_set_border;
155 static vi_set_win_org_t tga_set_win_org;
156 static vi_fill_rect_t tga_fill_rect;
157 static vi_bitblt_t tga_bitblt;
158 static vi_clear_t tga_clear;
159 static vi_putc_t tga_putc;
160 static vi_puts_t tga_puts;
161 static vi_putm_t tga_putm;
163 static video_switch_t tgavidsw = {
180 gfb_set_hw_cursor_shape,
190 gfb_save_cursor_palette,
191 gfb_load_cursor_palette,
199 VIDEO_DRIVER(tga, tgavidsw, NULL);
201 extern sc_rndr_sw_t txtrndrsw;
202 RENDERER(tga, 0, txtrndrsw, gfb_set);
205 extern sc_rndr_sw_t gfbrndrsw;
206 RENDERER(tga, PIXEL_MODE, gfbrndrsw, gfb_set);
207 #endif /* SC_PIXEL_MODE */
209 #ifndef SC_NO_MODE_CHANGE
210 extern sc_rndr_sw_t grrndrsw;
211 RENDERER(tga, GRAPHICS_MODE, grrndrsw, gfb_set);
212 #endif /* SC_NO_MODE_CHANGE */
214 RENDERER_MODULE(tga, gfb_set);
216 #define MHz * 1000000
219 extern struct gfb_softc *gfb_device_softcs[2][MAX_NUM_GFB_CARDS];
222 The following 3 variables exist only because we need statically
223 allocated structures very early in boot to support tga_configure()...
225 extern struct gfb_softc console;
226 extern video_adapter_t console_adp;
227 extern struct gfb_conf console_gfbc;
228 extern u_char console_palette_red[256];
229 extern u_char console_palette_green[256];
230 extern u_char console_palette_blue[256];
231 extern u_char console_cursor_palette_red[3];
232 extern u_char console_cursor_palette_green[3];
233 extern u_char console_cursor_palette_blue[3];
235 static struct monitor decmonitors[] = {
236 /* 0x0: 1280 x 1024 @ 72Hz */
237 { 1280, 32, 160, 232,
241 /* 0x1: 1280 x 1024 @ 66Hz */
242 { 1280, 32, 160, 232,
246 /* 0x2: 1280 x 1024 @ 60Hz */
247 { 1280, 44, 184, 200,
251 /* 0x3: 1152 x 900 @ 72Hz */
252 { 1152, 64, 112, 176,
256 /* 0x4: 1600 x 1200 @ 65Hz */
257 { 1600, 32, 192, 336,
261 /* 0x5: 1024 x 768 @ 70Hz */
262 { 1024, 24, 136, 144,
266 /* 0x6: 1024 x 768 @ 72Hz */
267 { 1024, 16, 128, 128,
271 /* 0x7: 1024 x 864 @ 60Hz */
272 { 1024, 12, 128, 116,
276 /* 0x8: 1024 x 768 @ 60Hz */
281 /* 0x9: 800 x 600 @ 72Hz */
286 /* 0xa: 800 x 600 @ 60Hz */
291 /* 0xb: 640 x 480 @ 72Hz */
296 /* 0xc: 640 x 480 @ 60Hz */
301 /* 0xd: 1280 x 1024 @ 75Hz */
302 { 1280, 16, 144, 248,
306 /* 0xe: 1280 x 1024 @ 60Hz */
307 { 1280, 19, 163, 234,
311 /* 0xf: 1600 x 1200 @ 75Hz */
312 /* XXX -- this one's weird. rcd */
313 { 1600, 32, 192, 336,
324 #define MB * 1024 * 1024
327 * These are the 16 default VGA colors--these are replicated 16 times as the
328 * initial (default) color-map. The text rendering functions use entries
329 * 0..15 for normal foreground/background colors. The entries 128..255 are
330 * used for blinking entries--when "on," they contain the foreground color
331 * entries; when "off," they contain the background color entries...
333 static const struct cmap {
337 } default_cmap[16] = {
338 {0x00, 0x00, 0x00}, /* Black */
339 {0x00, 0x00, 0xff}, /* Blue */
340 {0x00, 0xff, 0x00}, /* Green */
341 {0x00, 0xc0, 0xc0}, /* Cyan */
342 {0xff, 0x00, 0x00}, /* Red */
343 {0xc0, 0x00, 0xc0}, /* Magenta */
344 {0xc0, 0xc0, 0x00}, /* Brown */
345 {0xc0, 0xc0, 0xc0}, /* Light Grey */
346 {0x80, 0x80, 0x80}, /* Dark Grey */
347 {0x80, 0x80, 0xff}, /* Light Blue */
348 {0x80, 0xff, 0x80}, /* Light Green */
349 {0x80, 0xff, 0xff}, /* Light Cyan */
350 {0xff, 0x80, 0x80}, /* Light Red */
351 {0xff, 0x80, 0xff}, /* Light Magenta */
352 {0xff, 0xff, 0x80}, /* Yellow */
353 {0xff, 0xff, 0xff} /* White */
356 extern struct gfb_font bold8x16;
358 /*****************************************************************************
360 * FB-generic functions
362 ****************************************************************************/
365 tga_init(int unit, video_adapter_t *adp, int flags)
367 struct gfb_softc *sc;
368 struct gfb_conf *gfbc;
369 unsigned int monitor;
378 /* Assume the best... */
381 sc = gfb_device_softcs[adp->va_model][unit];
384 /* Initialize palette counts... */
385 gfbc->palette.count = 256;
386 gfbc->cursor_palette.count = 3;
388 /* Initialize the adapter... */
389 gder = BASIC_READ_TGA_REGISTER(adp, TGA_REG_GDER);
390 addrmask = (gder & GDER_ADDR_MASK) >> GDER_ADDR_SHIFT;
391 deep = (gder & GDER_DEEP) != 0;
392 cs = (gder & GDER_CS) == 0;
393 card_type = TGA_TYPE_UNKNOWN;
394 adp->va_little_bitian = 1;
395 adp->va_little_endian = 0;
396 adp->va_initial_mode = 0;
397 adp->va_initial_bios_mode = 0;
399 adp->va_info.vi_mem_model = V_INFO_MM_TEXT;
400 adp->va_info.vi_mode = M_VGA_M80x30;
401 adp->va_info.vi_flags = V_INFO_COLOR;
402 adp->va_buffer = adp->va_mem_base;
403 adp->va_buffer_size = 4 MB * (1 + addrmask);
404 adp->va_registers = adp->va_buffer + TGA_REG_SPACE_OFFSET;
405 adp->va_registers_size = 2 KB;
406 adp->va_window = adp->va_buffer + (adp->va_buffer_size / 2);
407 adp->va_info.vi_window = vtophys(adp->va_window);
408 adp->va_window_size = (deep ? 4 MB : 2 MB);
409 adp->va_info.vi_window_size = adp->va_window_size;
410 adp->va_window_gran = adp->va_window_size;
411 adp->va_info.vi_window_gran = adp->va_window_gran;
412 adp->va_info.vi_buffer = vtophys(adp->va_buffer);
413 adp->va_info.vi_buffer_size = adp->va_buffer_size;
414 adp->va_disp_start.x = 0;
415 adp->va_disp_start.y = 0;
416 adp->va_info.vi_depth = (deep ? 32 : 8);
417 adp->va_info.vi_planes = adp->va_info.vi_depth / 8;
418 adp->va_info.vi_width = (READ_GFB_REGISTER(adp, TGA_REG_VHCR) &
420 adp->va_info.vi_width |= (READ_GFB_REGISTER(adp, TGA_REG_VHCR) &
422 switch(adp->va_info.vi_width) {
424 adp->va_info.vi_width = 8192;
427 adp->va_info.vi_width = 8196;
430 adp->va_info.vi_width *= 4;
433 adp->va_info.vi_height = (READ_GFB_REGISTER(adp, TGA_REG_VVCR) &
435 adp->va_line_width = adp->va_info.vi_width * adp->va_info.vi_depth / 8;
436 if(READ_GFB_REGISTER(adp, TGA_REG_VHCR) & VHCR_ODD)
437 adp->va_info.vi_width -= 4;
440 Set the video base address and the cursor base address to
441 something known such that the video base address is at
442 least 1 KB past the cursor base address (the cursor is 1 KB
443 in size, so leave room for it)...we pick 4 KB and 0 KB,
444 respectively, since they begin at the top of the framebuffer
445 for minimal fragmentation of the address space, and this will
446 always leave enough room for the cursor for all implementations...
449 /* Set the video base address... */
450 tga_set_win_org(sc->adp, 4 KB);
452 /* Set the cursor base address... */
453 ccbr = READ_GFB_REGISTER(sc->adp, TGA_REG_CCBR);
454 ccbr = (ccbr & 0xfffffc0f) | (0 << 4);
455 WRITE_GFB_REGISTER(sc->adp, TGA_REG_CCBR, ccbr);
457 /* Type the card... */
458 if(adp->va_type == KD_TGA) {
461 /* 8bpp frame buffer */
462 gfbc->ramdac_name = "BT485";
463 gfbc->ramdac_init = bt485_init;
464 gfbc->ramdac_rd = tga_bt485_rd;
465 gfbc->ramdac_wr = tga_bt485_wr;
466 gfbc->ramdac_save_palette = bt485_save_palette;
467 gfbc->ramdac_load_palette = bt485_load_palette;
468 gfbc->ramdac_save_cursor_palette =
469 bt485_save_cursor_palette;
470 gfbc->ramdac_load_cursor_palette =
471 bt485_load_cursor_palette;
472 gfbc->ramdac_read_hw_cursor = bt485_read_hw_cursor;
473 gfbc->ramdac_set_hw_cursor = bt485_set_hw_cursor;
474 gfbc->ramdac_set_hw_cursor_shape =
475 bt485_set_hw_cursor_shape;
477 if(addrmask == GDER_ADDR_4MB) {
479 /* 4MB core map; T8-01 or T8-02 */
481 card_type = TGA_TYPE_T8_01;
482 gfbc->name = "T8-01";
484 card_type = TGA_TYPE_T8_02;
485 gfbc->name = "T8-02";
487 } else if(addrmask == GDER_ADDR_8MB) {
489 /* 8MB core map; T8-22 */
491 card_type = TGA_TYPE_T8_22;
492 gfbc->name = "T8-22";
494 } else if(addrmask == GDER_ADDR_16MB) {
496 /* 16MB core map; T8-44 */
498 card_type = TGA_TYPE_T8_44;
499 gfbc->name = "T8-44";
501 } else if(addrmask == GDER_ADDR_32MB) {
503 /* 32MB core map; ??? */
504 card_type = TGA_TYPE_UNKNOWN;
508 /* 32bpp frame buffer */
509 gfbc->ramdac_name = "BT463";
510 gfbc->ramdac_init = bt463_init;
511 gfbc->ramdac_rd = tga_bt463_rd;
512 gfbc->ramdac_wr = tga_bt463_wr;
513 gfbc->builtin_save_palette = tga_builtin_save_palette;
514 gfbc->builtin_load_palette = tga_builtin_load_palette;
515 gfbc->ramdac_save_cursor_palette =
516 bt463_save_cursor_palette;
517 gfbc->ramdac_load_cursor_palette =
518 bt463_load_cursor_palette;
519 gfbc->builtin_read_hw_cursor =
520 tga_builtin_read_hw_cursor;
521 gfbc->builtin_set_hw_cursor = tga_builtin_set_hw_cursor;
522 gfbc->builtin_set_hw_cursor_shape =
523 tga_builtin_set_hw_cursor_shape;
525 /* 32bpp frame buffer */
526 if(addrmask == GDER_ADDR_4MB) {
528 /* 4MB core map; ??? */
529 card_type = TGA_TYPE_UNKNOWN;
530 } else if(addrmask == GDER_ADDR_8MB) {
532 /* 8MB core map; ??? */
533 card_type = TGA_TYPE_UNKNOWN;
534 } else if(addrmask == GDER_ADDR_16MB) {
536 /* 16MB core map; T32-04 or T32-08 */
538 card_type = TGA_TYPE_T32_04;
539 gfbc->name = "T32-04";
541 card_type = TGA_TYPE_T32_08;
542 gfbc->name = "T32-08";
544 } else if(addrmask == GDER_ADDR_32MB) {
546 /* 32MB core map; T32-88 */
548 card_type = TGA_TYPE_T32_88;
549 gfbc->name = "T32-88";
554 else if(adp->va_type == KD_TGA2) {
555 gfbc->ramdac_name = "IBM561";
556 gfbc->ramdac_init = ibm561_init;
557 gfbc->ramdac_rd = tga2_ibm561_rd;
558 gfbc->ramdac_wr = tga2_ibm561_wr;
559 gfbc->ramdac_save_palette = ibm561_save_palette;
560 gfbc->ramdac_load_palette = ibm561_load_palette;
561 gfbc->ramdac_save_cursor_palette = ibm561_save_cursor_palette;
562 gfbc->ramdac_load_cursor_palette = ibm561_load_cursor_palette;
563 gfbc->builtin_read_hw_cursor = tga_builtin_read_hw_cursor;
564 gfbc->builtin_set_hw_cursor = tga_builtin_set_hw_cursor;
565 gfbc->builtin_set_hw_cursor_shape =
566 tga_builtin_set_hw_cursor_shape;
569 if(addrmask == GDER_ADDR_4MB)
570 card_type = TGA_TYPE_UNKNOWN;
573 else if(addrmask == GDER_ADDR_8MB) {
574 card_type = TGA2_TYPE_3D30;
579 else if(addrmask == GDER_ADDR_16MB) {
580 card_type = TGA2_TYPE_4D20;
583 else if(addrmask == GDER_ADDR_32MB)
584 card_type = TGA_TYPE_UNKNOWN;
588 For now, just return for TGA2 cards (i.e.,
589 allow syscons to treat this device as a normal
590 VGA device, and don't do anything TGA2-specific,
591 e.g., only use the TGA2 card in VGA mode for now
592 as opposed to 2DA mode...
594 if(adp->va_type == KD_TGA2)
597 /* If we couldn't identify the card, err-out... */
598 if(card_type == TGA_TYPE_UNKNOWN) {
599 printf("tga%d: Unknown TGA type\n", unit);
604 /* Clear and disable interrupts... */
605 WRITE_GFB_REGISTER(adp, TGA_REG_SISR, 0x00000001);
607 /* Perform TGA2-specific initialization, if necessary... */
608 if(adp->va_type == KD_TGA2) {
609 monitor = (~READ_GFB_REGISTER(adp, TGA_REG_GREV) >> 16 ) & 0x0f;
610 tga2_init(sc, monitor);
617 tga2_init(sc, monitor)
618 struct gfb_softc *sc;
622 tga2_ics9110_wr(sc, decmonitors[monitor].dotclock);
623 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VHCR,
624 ((decmonitors[monitor].hbp / 4) << VHCR_BPORCH_SHIFT) |
625 ((decmonitors[monitor].hsync / 4) << VHCR_HSYNC_SHIFT) |
626 (((decmonitors[monitor].hfp) / 4) << VHCR_FPORCH_SHIFT) |
627 ((decmonitors[monitor].cols) / 4));
628 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VVCR,
629 (decmonitors[monitor].vbp << VVCR_BPORCH_SHIFT) |
630 (decmonitors[monitor].vsync << VVCR_VSYNC_SHIFT) |
631 (decmonitors[monitor].vfp << VVCR_FPORCH_SHIFT) |
632 (decmonitors[monitor].rows));
633 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VVBR, 1);
634 GFB_REGISTER_READWRITE_BARRIER(sc, TGA_REG_VHCR, 3);
635 WRITE_GFB_REGISTER(sc->adp, TGA_REG_VVVR,
636 READ_GFB_REGISTER(sc->adp, TGA_REG_VVVR) | 1);
637 GFB_REGISTER_READWRITE_BARRIER(sc, TGA_REG_VVVR, 1);
638 WRITE_GFB_REGISTER(sc->adp, TGA_REG_GPMR, 0xffffffff);
639 GFB_REGISTER_READWRITE_BARRIER(sc, TGA_REG_GPMR, 1);
643 tga_query_mode(video_adapter_t *adp, video_info_t *info)
647 /* Assume the best... */
650 /* Verify that this mode is supported on this adapter... */
651 if(adp->va_type == KD_TGA2) {
652 if((info->vi_mode != TGA2_2DA_MODE) &&
653 (info->vi_mode != TGA2_VGA_MODE))
657 if(info->vi_mode != 0)
664 tga_set_mode(video_adapter_t *adp, int mode)
670 /* Assume the best... */
673 gder = READ_GFB_REGISTER(video_adapter_t *adp, TGA_REG_GDER);
676 Determine the adapter type first
677 so we know which modes are valid for it...
679 switch(adp->va_type) {
683 Verify that this mode is supported
688 vgae_mask = ~0x00400000;
689 WRITE_GFB_REGISTER(video_adapter_t *adp, TGA_REG_GDER,
694 vgae_mask = 0x00400000;
695 WRITE_GFB_REGISTER(video_adapter_t *adp, TGA_REG_GDER,
706 Verify that this mode is supported
723 tga_blank_display(video_adapter_t *adp, int mode)
728 /* Assume the best... */
731 blanked = READ_GFB_REGISTER(adp, TGA_REG_VVVR) &
732 (VVR_BLANK | VVR_VIDEOVALID | VVR_CURSOR);
734 /* If we're not already blanked, then blank...*/
736 case V_DISPLAY_BLANK:
737 if(blanked != (VVR_VIDEOVALID | VVR_BLANK)) {
738 blanked = VVR_VIDEOVALID | VVR_BLANK;
739 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
742 case V_DISPLAY_STAND_BY:
743 if(blanked != VVR_BLANK) {
745 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
749 if(blanked != (VVR_VIDEOVALID | VVR_CURSOR)) {
750 blanked = VVR_VIDEOVALID | VVR_CURSOR;
751 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
761 tga_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
763 struct gfb_softc *sc;
767 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
771 tga_schedule_intr(sc, bt463_load_palette_intr);
776 case FBIO_SETDISPSTART:
777 case FBIO_SETLINEWIDTH:
778 case FBIO_GETPALETTE:
782 error = fb_commonioctl(adp, cmd, arg);
788 tga_set_border(video_adapter_t *adp, int color) {
793 tga_set_win_org(video_adapter_t *adp, off_t offset) {
795 u_int16_t window_orig;
800 /* Get the adapter's parameters... */
801 gder = BASIC_READ_TGA_REGISTER(adp, TGA_REG_GDER);
802 deep = (gder & 0x1) != 0;
803 cs = (gder & 0x200) == 0;
806 Set the window (framebuffer) origin according to the video
809 window_orig = offset / ((1 + cs) * (1 + deep) * (1 + deep) * 2 KB);
810 adp->va_window_orig = window_orig * ((1 + cs) * (1 + deep) *
813 /* Set the video base address... */
814 vvbr = READ_GFB_REGISTER(adp, TGA_REG_VVBR);
815 vvbr = (vvbr & 0xfffffe00) | window_orig;
816 WRITE_GFB_REGISTER(adp, TGA_REG_VVBR, vvbr);
821 tga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) {
829 /* Save the pixel mode... */
830 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
832 /* Save the pixel mask... */
833 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
835 /* Save the block-color... */
836 gbcr0 = READ_GFB_REGISTER(adp, TGA_REG_GBCR0);
837 gbcr1 = READ_GFB_REGISTER(adp, TGA_REG_GBCR1);
839 /* Set the pixel mode (block-fill)... */
840 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
841 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_BLK_FILL);
843 /* Set the pixel mask (enable writes to all pixels)... */
844 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, 0xffffffff);
846 color = ((val & 0xff00) << 24) || ((val & 0xff00) << 16) ||
847 ((val & 0xff00) << 8) || ((val & 0xff00) << 0);
849 /* Set the color for the block-fill... */
850 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR0, color);
851 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR1, color);
854 Just traverse the buffer, one 2K-pixel span at a time, setting
855 each pixel to the bolck-color...
857 for(off = (x * y); off < ((x + cx) * (y + cy)); off += (2 KB))
858 WRITE_GFB_BUFFER(adp, off >> 2L, 0x000007ff);
860 /* Restore the pixel mode... */
861 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
863 /* Restore the pixel mask... */
864 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
866 /* Restore the block-color... */
867 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR0, gbcr0);
868 WRITE_GFB_REGISTER(adp, TGA_REG_GBCR1, gbcr1);
874 tga_bitblt(video_adapter_t *adp, ...) {
879 vm_offset_t src, dst;
881 __va_start(args, adp);
883 /* Save the pixel mode... */
884 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
886 /* Save the raster op... */
887 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
889 /* Set the pixel mode (copy)... */
890 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
891 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_COPY);
893 /* Set the raster op (src)... */
894 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
896 src = (__va_arg(args, vm_offset_t) + adp->va_window_orig) &
898 dst = (__va_arg(args, vm_offset_t) + adp->va_window_orig) &
900 count = __va_arg(args, int);
901 for(i = 0; i < count; i+= 64, src += 64, dst += 64) {
902 WRITE_GFB_REGISTER(adp, TGA_REG_GCSR, src);
903 WRITE_GFB_REGISTER(adp, TGA_REG_GCDR, dst);
906 /* Restore the raster op... */
907 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
909 /* Restore the pixel mode... */
910 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
918 tga_clear(video_adapter_t *adp, int n)
920 tga_clear(video_adapter_t *adp)
929 if(n == 0) return(0);
932 /* Save the pixel mode... */
933 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
935 /* Save the pixel mask... */
936 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
938 /* Save the raster op... */
939 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
941 /* Set the pixel mode (opaque-fill)... */
942 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
943 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_OPQ_FILL);
945 /* Set the pixel mask (enable writes to all pixels)... */
946 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, 0xffffffff);
948 /* Set the raster op (clear)... */
949 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x00);
952 Just traverse the buffer, one 2K-pixel span at a time, clearing
956 for(off = 0; off < (n * adp->va_line_width); off += (2 KB))
958 for(off = 0; off < adp->va_window_size; off += (2 KB))
959 WRITE_GFB_BUFFER(adp, off >> 2L, 0x000007ff);
961 /* Restore the pixel mask... */
962 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
964 /* Restore the raster op... */
965 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
967 /* Restore the pixel mode... */
968 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
974 tga_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
986 struct gfb_softc *sc;
989 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
990 pixel_size = adp->va_info.vi_depth / 8;
992 /* Save the pixel mode... */
993 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
995 /* Save the pixel mask... */
996 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
998 /* Save the raster op... */
999 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
1001 /* Save the background color... */
1002 gbgr = READ_GFB_REGISTER(adp, TGA_REG_GBGR);
1004 /* Save the foreground color... */
1005 gfgr = READ_GFB_REGISTER(adp, TGA_REG_GFGR);
1007 /* Set the pixel mode (opaque-stipple)... */
1008 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
1009 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_OPQ_STPL);
1011 /* Set the pixel mask (enable writes to the first cwidth pixels)... */
1012 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P,
1013 (1 << adp->va_info.vi_cwidth) - 1);
1015 /* Set the raster op (src)... */
1016 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
1018 /* Set the foreground color mask from the attribute byte... */
1019 mask = (a & 0x80) ? a : (a & 0x0f);
1021 /* Propagate the 8-bit mask across the full 32 bits... */
1022 mask |= (mask << 24) | (mask << 16) | (mask << 8);
1024 /* Set the foreground color... */
1025 WRITE_GFB_REGISTER(adp, TGA_REG_GFGR, mask);
1027 /* Set the background color mask from the attribute byte... */
1028 mask = (a >> 4) & 0x07;
1030 /* Propagate the 8-bit mask across the full 32 bits... */
1031 mask |= (mask << 24) | (mask << 16) | (mask << 8);
1033 /* Set the background color... */
1034 WRITE_GFB_REGISTER(adp, TGA_REG_GBGR, mask);
1036 /* Get the start of the array of pixels rows for this character... */
1037 pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight);
1039 /* Calculate the new cursor position... */
1040 row = off / adp->va_info.vi_width;
1041 col = off % adp->va_info.vi_width;
1043 /* Iterate over all the pixel rows for this character... */
1044 for(i = 0; i < adp->va_info.vi_cheight; i++) {
1046 /* Get the address of the character's pixel-row... */
1047 poff = ((col * adp->va_info.vi_cwidth * pixel_size) +
1048 (((row * adp->va_info.vi_cheight) + i) *
1049 adp->va_line_width)) / sizeof(gfb_reg_t);
1051 /* Now display the current pixel row... */
1052 WRITE_GFB_BUFFER(adp, poff, pixel[i]);
1055 /* Restore the foreground color... */
1056 WRITE_GFB_REGISTER(adp, TGA_REG_GFGR, gfgr);
1058 /* Restore the background color... */
1059 WRITE_GFB_REGISTER(adp, TGA_REG_GBGR, gbgr);
1061 /* Restore the pixel mode... */
1062 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
1064 /* Restore the pixel mask... */
1065 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
1067 /* Restore the raster op... */
1068 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
1074 tga_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
1086 struct gfb_softc *sc;
1089 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1090 pixel_size = adp->va_info.vi_depth / 8;
1092 /* If the string in empty, just return now... */
1093 if(len == 0) return(0);
1095 for(i = 0; i < len; i++)
1096 tga_putc(adp, off + i, s[i] & 0x00ff, (s[i] & 0xff00) >> 8);
1099 /* Save the pixel mode... */
1100 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
1102 /* Save the pixel mask... */
1103 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
1105 /* Save the raster op... */
1106 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
1108 /* Set the pixel mode (simple)... */
1109 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, (gmor & 0xffffffc0) | 0x00);
1111 /* Set the pixel mask (enable writes to all 32 pixels)... */
1112 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, (gpxr & 0xfffffff0) | 0xf);
1114 /* Set the raster op (src)... */
1115 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x03);
1118 First, do as many characters-rows at a time as possible (as exist)...
1120 for(i = 0; (len - i) > adp->va_info.vi_width;
1121 i += adp->va_info.vi_width) {
1124 Iterate over all the pixels for each character in the
1125 character-row, doing a scan-line at-a-time, rather than
1126 a character at-a-time (like tga_putc())...
1128 for(j = 0; j < adp->va_info.vi_cheight; j++) {
1130 for(k = 0; k < adp->va_info.vi_width; k++) {
1133 Get this character...
1135 c = s[i + k] & 0x00ff;
1138 Get the attribute for this character...
1140 a = (s[i + k] & 0xff00) >> 8;
1143 Get the start of the array of pixels rows for
1146 pixel = sc->gfbc->font +
1147 (c * adp->va_info.vi_cheight);
1149 /* Shift the other pre-existing pixel rows... */
1153 Get the first pixel row for
1158 if (((k + 1) % sizeof(gfb_reg_t)) == 0) {
1161 Calculate the new cursor
1164 row = (off + i + (k -
1165 (sizeof(gfb_reg_t) - 1))) /
1166 adp->va_info.vi_width;
1167 col = (off + i + (k -
1168 (sizeof(gfb_reg_t) - 1))) %
1169 adp->va_info.vi_width;
1172 Get the address of the current
1173 character's pixel-row...
1175 poff = ((col * adp->va_info.vi_cwidth *
1176 pixel_size) + (((row *
1177 adp->va_info.vi_cheight) + j) *
1178 adp->va_line_width)) /
1182 Now display the current
1185 (*vidsw[adp->va_index]->putp)(adp, poff,
1186 p, a, sizeof(gfb_reg_t),
1187 adp->va_info.vi_depth, 1, 0);
1189 /* Reset (clear) p... */
1197 Next, do as many character-sets at a time as possible (as exist)...
1199 for(; (len - i) > sizeof(gfb_reg_t); i += sizeof(gfb_reg_t)) {
1202 Iterate over all the pixels for each character in the
1203 character-row, doing a scan-line at-a-time, rather than
1204 a character at-a-time (like tga_putc())...
1206 for(j = 0; j < adp->va_info.vi_cheight; j++) {
1208 for(k = 0; k < sizeof(gfb_reg_t); k++) {
1211 Get this character...
1213 c = s[i + k] & 0x00ff;
1216 Get the attribute for this character...
1218 a = (s[i + k] & 0xff00) >> 8;
1221 Get the start of the array of pixels rows for
1224 pixel = sc->gfbc->font +
1225 (c * adp->va_info.vi_cheight);
1227 /* Shift the other pre-existing pixel rows... */
1231 Get the first pixel row for
1236 if (((k + 1) % sizeof(gfb_reg_t)) == 0) {
1239 Calculate the new cursor
1242 row = (off + i) / adp->va_info.vi_width;
1243 col = (off + i) % adp->va_info.vi_width;
1246 Get the address of the current
1247 character's pixel-row...
1249 poff = ((col * adp->va_info.vi_cwidth *
1250 pixel_size) + (((row *
1251 adp->va_info.vi_cheight) + j) *
1252 adp->va_line_width)) /
1256 Now display the current
1259 (*vidsw[adp->va_index]->putp)(adp, poff,
1260 p, a, sizeof(gfb_reg_t),
1261 adp->va_info.vi_depth, 1, 0);
1263 /* Reset (clear) p... */
1270 /* Restore the pixel mode... */
1271 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
1273 /* Restore the pixel mask... */
1274 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
1276 /* Restore the raster op... */
1277 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
1279 /* Finally, do the remaining characters a character at-a-time... */
1280 for(; i < len; i++) {
1282 Get this character...
1287 Get the attribute for this character...
1289 a = (s[i] & 0xff00) >> 8;
1292 Display this character...
1294 tga_putc(adp, off + i, c, a);
1300 tga_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
1301 gfb_reg_t pixel_mask, int size)
1309 pixel_size = adp->va_info.vi_depth / 8;
1311 /* Save the pixel mode... */
1312 gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
1314 /* Save the pixel mask... */
1315 gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
1317 /* Save the raster op... */
1318 gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
1320 /* Set the pixel mode (simple)... */
1321 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
1322 (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_SIMPLE);
1324 /* Set the pixel mask (enable writes to the first 8 pixels)... */
1325 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, (gpxr & 0xfffffff0) | 0xf);
1327 /* Set the raster op (src)... */
1328 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
1330 /* Iterate over all the pixel rows for the mouse pointer... */
1331 for(i = 0; i < size; i++) {
1333 /* Get the address of the mouse pointer's pixel-row... */
1334 poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) /
1337 /* Now display the current pixel-row... */
1338 (*vidsw[adp->va_index]->putp)(adp, poff, pixel_image[i],
1339 pixel_mask, sizeof(u_int8_t), adp->va_info.vi_depth, 1, 0);
1342 /* Restore the pixel mode... */
1343 WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
1345 /* Restore the pixel mask... */
1346 WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
1348 /* Restore the raster op... */
1349 WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
1360 /*****************************************************************************
1362 * TGA-specific functions
1364 ****************************************************************************/
1367 tga_builtin_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
1371 struct gfb_softc *sc;
1374 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1377 * We store 8 bit values in the palette buffer, while the standard
1378 * VGA has 6 bit DAC .
1380 outb(PALRADR, 0x00);
1381 for(i = 0; i < palette->count; ++i) {
1382 palette->red[i] = inb(PALDATA) << 2;
1383 palette->green[i] = inb(PALDATA) << 2;
1384 palette->blue[i] = inb(PALDATA) << 2;
1390 tga_builtin_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
1394 struct gfb_softc *sc;
1397 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1400 * We store 8 bit values in the palette buffer, while the standard
1401 * VGA has 6 bit DAC .
1403 outb(PIXMASK, 0xff);
1404 outb(PALWADR, 0x00);
1405 for(i = 0; i < palette->count; ++i) {
1406 outb(PALDATA, palette->red[i] >> 2);
1407 outb(PALDATA, palette->green[i] >> 2);
1408 outb(PALDATA, palette->blue[i] >> 2);
1414 tga2_builtin_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
1418 struct gfb_softc *sc;
1421 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1423 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1424 BT463_IREG_CPALETTE_RAM & 0xff);
1425 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1426 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
1428 /* spit out the colormap data */
1429 for(i = 0; i < palette->count; i++) {
1430 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1432 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1434 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1441 tga2_builtin_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
1445 struct gfb_softc *sc;
1448 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1450 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1451 BT463_IREG_CPALETTE_RAM & 0xff);
1452 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1453 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
1455 /* spit out the colormap data */
1456 for(i = 0; i < palette->count; i++) {
1457 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1459 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1461 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
1468 tga2_builtin_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
1472 struct gfb_softc *sc;
1475 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1477 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1478 BT463_IREG_CURSOR_COLOR_0 & 0xff);
1479 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1480 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
1482 /* spit out the cursor data */
1483 for(i = 0; i < palette->count; i++) {
1484 BTWNREG(sc, palette->red[i]);
1485 BTWNREG(sc, palette->green[i]);
1486 BTWNREG(sc, palette->blue[i]);
1492 tga2_builtin_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
1496 struct gfb_softc *sc;
1499 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1501 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1502 BT463_IREG_CURSOR_COLOR_0 & 0xff);
1503 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1504 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
1506 /* spit out the cursor data */
1507 for(i = 0; i < palette->count; i++) {
1508 BTWNREG(sc, palette->red[i]);
1509 BTWNREG(sc, palette->green[i]);
1510 BTWNREG(sc, palette->blue[i]);
1516 tga_builtin_read_hw_cursor(video_adapter_t *adp, int col, int row)
1521 /* Assume the best... */
1524 cxyr = READ_GFB_REGISTER(adp, TGA_REG_CXYR) | 0x00ffffff;
1525 *col = (cxyr & 0x00000fff) / adp->va_info.vi_cwidth;
1526 *row = ((cxyr & 0x00fff000) >> 12) / adp->va_info.vi_cheight;
1531 tga_builtin_set_hw_cursor(video_adapter_t *adp, int col, int row)
1537 /* Assume the best... */
1540 vvvr = READ_GFB_REGISTER(adp, TGA_REG_VVVR);
1543 Make sure the parameters are in range for the screen
1546 if((row > adp->va_info.vi_height) ||
1547 (col > adp->va_info.vi_width))
1549 else if(((row * adp->va_info.vi_cheight) > 0x0fff) ||
1550 ((col * adp->va_info.vi_cwidth) > 0x0fff))
1553 If either of the parameters is less than 0,
1554 then hide the cursor...
1556 else if((row < 0) || (col < 0)) {
1557 if((vvvr & 0x00000004) != 0) {
1559 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1563 /* Otherwise, just move the cursor as requested... */
1565 cxyr = READ_GFB_REGISTER(adp, TGA_REG_CXYR) & 0xff000000;
1566 cxyr |= ((row * adp->va_info.vi_cheight) << 12);
1567 cxyr |= (col * adp->va_info.vi_cwidth);
1568 WRITE_GFB_REGISTER(adp, TGA_REG_CXYR, cxyr);
1569 if((vvvr & 0x00000004) == 0) {
1571 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1578 tga_builtin_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
1579 int cellsize, int blink)
1583 gfb_reg_t window_orig;
1588 /* Assume the best... */
1591 vvvr = READ_GFB_REGISTER(adp, TGA_REG_VVVR);
1594 Make sure the parameters are in range for the cursor
1595 (it's a 64x64 cursor)...
1600 /* If height is less than or equal to 0, then hide the cursor... */
1601 else if(height <= 0) {
1602 if((vvvr & 0x00000004) != 0) {
1604 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1608 /* Otherwise, just resize the cursor as requested... */
1610 ccbr = READ_GFB_REGISTER(adp, TGA_REG_CCBR);
1612 ccbr |= ((height - 1) << 10);
1613 WRITE_GFB_REGISTER(adp, TGA_REG_CCBR, ccbr);
1614 if((vvvr & 0x00000004) == 0) {
1616 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
1619 /* Save the window origin... */
1620 window_orig = adp->va_window_orig;
1623 Fill in the cursor image (64 rows of 64 pixels per cursor
1624 row at 2 bits-per-pixel, so 64 rows of 16 bytes each)--we
1625 set va_window_orig to the cursor base address temporarily
1626 so that we can write to the cursor image...
1628 cba = (READ_GFB_REGISTER(adp, TGA_REG_CCBR) & 0xfffffc0f) >> 4;
1629 adp->va_window_orig = cba;
1630 for(i = 0; i < (64 - height); i++) {
1631 WRITE_GFB_BUFFER(adp, cba++, 0x00000000);
1632 WRITE_GFB_BUFFER(adp, cba++, 0x00000000);
1634 for(; i < 64; i++) {
1635 for(j = 0; j < (((64 - cellsize) / 8) /
1636 sizeof(gfb_reg_t)); j++)
1637 WRITE_GFB_BUFFER(adp, cba++, 0x00000000);
1638 for(; j < ((64 / 8) / sizeof(gfb_reg_t)); j++)
1639 WRITE_GFB_BUFFER(adp, cba++, 0xffffffff);
1642 /* Restore the window origin... */
1643 adp->va_window_orig = window_orig;
1650 bt463_load_palette_intr(struct gfb_softc *sc)
1652 sc->gfbc->ramdac_save_palette(sc->adp, &sc->gfbc->palette);
1656 bt463_load_cursor_palette_intr(struct gfb_softc *sc)
1658 sc->gfbc->ramdac_load_cursor_palette(sc->adp, &sc->gfbc->cursor_palette);
1662 tga_schedule_intr(struct gfb_softc *sc, void (*f)(struct gfb_softc *))
1664 /* Busy-wait for the previous interrupt to complete... */
1665 while((READ_GFB_REGISTER(sc->adp, TGA_REG_SISR) & 0x00000001) != 0);
1667 /* Arrange for f to be called at the next end-of-frame interrupt... */
1668 sc->gfbc->ramdac_intr = f;
1670 /* Enable the interrupt... */
1671 WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, 0x00010000);
1676 tga_bt485_rd(struct gfb_softc *sc, u_int btreg)
1680 if(btreg > BT485_REG_MAX)
1681 panic("tga_ramdac_rd: reg %d out of range\n", btreg);
1682 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 1) | 0x1);
1683 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1684 rdval = READ_GFB_REGISTER(sc->adp, TGA_REG_EPDR);
1685 return((rdval >> 16) & 0xff);
1689 tga_bt485_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
1691 if(btreg > BT485_REG_MAX)
1692 panic("tga_ramdac_wr: reg %d out of range\n", btreg);
1693 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR,
1694 (btreg << 9) | (0 << 8 ) | val);
1695 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1699 tga2_ibm561_rd(struct gfb_softc *sc, u_int btreg)
1701 bus_space_handle_t ramdac;
1704 if(btreg > BT485_REG_MAX)
1705 panic("tga_ramdac_rd: reg %d out of range\n", btreg);
1706 ramdac = sc->bhandle + TGA2_MEM_RAMDAC + (0xe << 12) + (btreg << 8);
1707 retval = bus_space_read_4(sc->btag, ramdac, 0) & 0xff;
1708 bus_space_barrier(sc->btag, ramdac, 0, 4, BUS_SPACE_BARRIER_READ);
1713 tga2_ibm561_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
1715 bus_space_handle_t ramdac;
1717 if(btreg > BT485_REG_MAX)
1718 panic("tga_ramdac_wr: reg %d out of range\n", btreg);
1719 ramdac = sc->bhandle + TGA2_MEM_RAMDAC + (0xe << 12) + (btreg << 8);
1720 bus_space_write_4(sc->btag, ramdac, 0, val & 0xff);
1721 bus_space_barrier(sc->btag, ramdac, 0, 4, BUS_SPACE_BARRIER_WRITE);
1725 tga_bt463_rd(struct gfb_softc *sc, u_int btreg)
1730 * Strobe CE# (high->low->high) since status and data are latched on
1731 * the falling and rising edges (repsectively) of this active-low
1735 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1736 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
1737 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1738 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 2) | 2 | 0);
1739 GFB_REGISTER_READ_BARRIER(sc, TGA_REG_EPSR, 1);
1740 rdval = READ_GFB_REGISTER(sc->adp, TGA_REG_EPDR);
1741 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPSR, 1);
1742 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPSR, (btreg << 2) | 2 | 1);
1743 return((rdval >> 16) & 0xff);
1747 tga_bt463_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
1750 * In spite of the 21030 documentation, to set the MPU bus bits for
1751 * a write, you set them in the upper bits of EPDR, not EPSR.
1755 * Strobe CE# (high->low->high) since status and data are latched on
1756 * the falling and rising edges of this active-low signal.
1759 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1760 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
1761 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1762 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR, (btreg << 10) | 0x000 | val);
1763 GFB_REGISTER_WRITE_BARRIER(sc, TGA_REG_EPDR, 1);
1764 WRITE_GFB_REGISTER(sc->adp, TGA_REG_EPDR, (btreg << 10) | 0x100 | val);
1768 tga2_ics9110_wr(struct gfb_softc *sc, int dotclock)
1770 bus_space_handle_t clock;
1777 N = 0x40; M = 0x7; V = 0x0; X = 0x1; R = 0x1; break;
1779 N = 0x2d; M = 0x2b; V = 0x1; X = 0x1; R = 0x1; break;
1781 N = 0x11; M = 0x9; V = 0x1; X = 0x1; R = 0x2; break;
1783 N = 0x6d; M = 0xf; V = 0x0; X = 0x1; R = 0x1; break;
1785 N = 0x5F; M = 0x3E; V = 0x1; X = 0x1; R = 0x1; break;
1787 N = 0x6e; M = 0x15; V = 0x0; X = 0x1; R = 0x1; break;
1789 N = 0x2a; M = 0x41; V = 0x1; X = 0x1; R = 0x1; break;
1791 N = 0x35; M = 0xb; V = 0x0; X = 0x1; R = 0x1; break;
1793 N = 0x6d; M = 0x0c; V = 0x0; X = 0x1; R = 0x2; break;
1795 N = 0x37; M = 0x3f; V = 0x1; X = 0x1; R = 0x2; break;
1797 N = 0x5f; M = 0x11; V = 0x0; X = 0x1; R = 0x2; break;
1799 N = 0x16; M = 0x05; V = 0x0; X = 0x1; R = 0x2; break;
1801 N = 0x66; M = 0x1d; V = 0x0; X = 0x1; R = 0x2; break;
1803 N = 0x42; M = 0x07; V = 0x0; X = 0x1; R = 0x1; break;
1805 N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
1807 N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
1809 panic("unrecognized clock rate %d\n", dotclock);
1812 /* XXX -- hard coded, bad */
1813 valU = N | ( M << 7 ) | (V << 14);
1814 valU |= (X << 15) | (R << 17);
1816 clock = sc->bhandle + TGA2_MEM_EXTDEV + TGA2_MEM_CLOCK + (0xe << 12);
1817 for(i = 24; i > 0; i--) {
1820 writeval = valU & 0x1;
1824 bus_space_write_4(sc->btag, clock, 0, writeval);
1825 bus_space_barrier(sc->btag, clock, 0, 4,
1826 BUS_SPACE_BARRIER_WRITE);
1828 clock = sc->bhandle + TGA2_MEM_EXTDEV + TGA2_MEM_CLOCK + (0xe << 12) +
1829 (0x1 << 11) + (0x1 << 11);
1830 bus_space_write_4(sc->btag, clock, 0, 0x0);
1831 bus_space_barrier(sc->btag, clock, 0, 0, BUS_SPACE_BARRIER_WRITE);
1834 /*****************************************************************************
1836 * BrookTree RAMDAC-specific functions
1838 ****************************************************************************/
1841 bt463_init(struct gfb_softc *sc)
1848 * Init the BT463 for normal operation.
1853 * reg 0: 4:1 multiplexing, 25/75 blink.
1854 * reg 1: Overlay mapping: mapped to common palette,
1855 * 14 window type entries, 24-plane configuration mode,
1856 * 4 overlay planes, underlays disabled, no cursor.
1857 * reg 2: sync-on-green enabled, pedestal enabled.
1860 BTWREG(sc, BT463_IREG_COMMAND_0, 0x40);
1861 BTWREG(sc, BT463_IREG_COMMAND_1, 0x48);
1862 BTWREG(sc, BT463_IREG_COMMAND_2, 0xC0);
1865 * Initialize the read mask.
1867 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1868 BT463_IREG_READ_MASK_P0_P7 & 0xff);
1869 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1870 (BT463_IREG_READ_MASK_P0_P7 >> 8) & 0xff);
1871 for(i = 0; i < 4; i++)
1875 * Initialize the blink mask.
1877 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1878 BT463_IREG_READ_MASK_P0_P7 & 0xff);
1879 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1880 (BT463_IREG_READ_MASK_P0_P7 >> 8) & 0xff);
1881 for(i = 0; i < 4; i++)
1885 * Clear test register
1887 BTWREG(sc, BT463_IREG_TEST, 0);
1890 * Initalize the RAMDAC info struct to hold all of our
1891 * data, and fill it in.
1894 /* Initialize the window type table:
1896 * Entry 0: 24-plane truecolor, overlays enabled, bypassed.
1898 * Lookup table bypass: yes ( 1 << 23 & 0x800000) 800000
1899 * Colormap address: 0x000 (0x000 << 17 & 0x7e0000) 0
1900 * Overlay mask: 0xf ( 0xf << 13 & 0x01e000) 1e000
1901 * Overlay location: P<27:24> ( 0 << 12 & 0x001000) 0
1902 * Display mode: Truecolor ( 0 << 9 & 0x000e00) 000
1903 * Number of planes: 8 ( 8 << 5 & 0x0001e0) 100
1904 * Plane shift: 0 ( 0 << 0 & 0x00001f) 0
1909 data->window_type[0] = 0x81e100;
1912 /* Entry 1: 8-plane pseudocolor in the bottom 8 bits,
1913 * overlays enabled, colormap starting at 0.
1915 * Lookup table bypass: no ( 0 << 23 & 0x800000) 0
1916 * Colormap address: 0x000 (0x000 << 17 & 0x7e0000) 0
1917 * Overlay mask: 0xf ( 0xf << 13 & 0x01e000) 0x1e000
1918 * Overlay location: P<27:24> ( 0 << 12 & 0x001000) 0
1919 * Display mode: Pseudocolor ( 1 << 9 & 0x000e00) 0x200
1920 * Number of planes: 8 ( 8 << 5 & 0x0001e0) 0x100
1921 * Plane shift: 16 ( 0x10 << 0 & 0x00001f) 10
1926 data->window_type[1] = 0x01e310;
1928 /* The colormap interface to the world only supports one colormap,
1929 * so having an entry for the 'alternate' colormap in the bt463
1930 * probably isn't useful.
1933 /* Fill the remaining table entries with clones of entry 0 until we
1934 * figure out a better use for them.
1937 for(i = 2; i < BT463_NWTYPE_ENTRIES; i++) {
1938 data->window_type[i] = 0x81e100;
1942 tga_schedule_intr(sc, bt463_update_window_type);
1943 tga_schedule_intr(sc, bt463_load_cursor_palette_intr);
1944 tga_schedule_intr(sc, bt463_load_palette_intr);
1948 bt463_update_window_type(struct gfb_softc *sc)
1952 /* The Bt463 won't accept window type data except during a blanking
1953 * interval, so we do this early in the interrupt.
1954 * Blanking the screen might also be a good idea, but it can cause
1955 * unpleasant flashing and is hard to do from this side of the
1958 /* spit out the window type data */
1959 for(i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
1961 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1962 (BT463_IREG_WINDOW_TYPE_TABLE + i) & 0xff);
1963 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1964 ((BT463_IREG_WINDOW_TYPE_TABLE + i) >> 8) & 0xff);
1965 BTWNREG(sc, (data->window_type[i]) & 0xff);
1966 BTWNREG(sc, (data->window_type[i] >> 8) & 0xff);
1967 BTWNREG(sc, (data->window_type[i] >> 16) & 0xff);
1973 bt463_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
1975 struct gfb_softc *sc;
1979 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
1981 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
1982 BT463_IREG_CPALETTE_RAM & 0xff);
1983 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
1984 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
1986 /* get the colormap data */
1987 for(i = 0; i < palette->count; i++) {
1988 palette->red[i] = sc->gfbc->ramdac_rd(sc, BT463_REG_CMAP_DATA);
1989 palette->green[i] = sc->gfbc->ramdac_rd(sc,
1990 BT463_REG_CMAP_DATA);
1991 palette->blue[i] = sc->gfbc->ramdac_rd(sc, BT463_REG_CMAP_DATA);
1997 bt463_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
1999 struct gfb_softc *sc;
2003 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2005 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
2006 BT463_IREG_CPALETTE_RAM & 0xff);
2007 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
2008 (BT463_IREG_CPALETTE_RAM >> 8) & 0xff);
2010 /* spit out the colormap data */
2011 for(i = 0; i < palette->count; i++) {
2012 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, palette->red[i]);
2013 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, palette->green[i]);
2014 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, palette->blue[i]);
2020 bt463_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2022 struct gfb_softc *sc;
2026 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2028 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
2029 BT463_IREG_CURSOR_COLOR_0 & 0xff);
2030 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
2031 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
2033 /* spit out the cursor data */
2034 for(i = 0; i < palette->count; i++) {
2035 palette->red[i] = BTRNREG(sc);
2036 palette->green[i] = BTRNREG(sc);
2037 palette->blue[i] = BTRNREG(sc);
2043 bt463_load_cursor_palette(video_adapter_t *adp, struct bfcmap *palette)
2045 struct gfb_softc *sc;
2049 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2051 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_LOW,
2052 BT463_IREG_CURSOR_COLOR_0 & 0xff);
2053 sc->gfbc->ramdac_wr(sc, BT463_REG_ADDR_HIGH,
2054 (BT463_IREG_CURSOR_COLOR_0 >> 8) & 0xff);
2056 /* spit out the cursor data */
2057 for(i = 0; i < palette->count; i++) {
2058 BTWNREG(sc, palette->red[i]);
2059 BTWNREG(sc, palette->green[i]);
2060 BTWNREG(sc, palette->blue[i]);
2066 bt485_init(struct gfb_softc *sc)
2068 int i, j, num_cmap_entries;
2071 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_0);
2074 * Set the RAMDAC to 8 bit resolution, rather than 6 bit
2080 * Set the RAMDAC to sync-on-green.
2083 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_0, regval);
2086 /* Set the RAMDAC to 8BPP (no interesting options). */
2087 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_1, 0x40);
2089 /* Disable the cursor (for now) */
2090 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_2);
2093 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
2095 /* Use a 64x64x2 cursor */
2096 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, BT485_IREG_COMMAND_3);
2097 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2100 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, BT485_IREG_COMMAND_3);
2101 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2103 /* Set the Pixel Mask to something useful */
2104 sc->gfbc->ramdac_wr(sc, BT485_REG_PIXMASK, 0xff);
2107 /* Generate the cursor color map (Light-Grey)... */
2108 for(i = 0; i < sc->gfbc->cursor_palette.count; i++) {
2109 sc->gfbc->cursor_palette.red[i] = default_cmap[7].red;
2110 sc->gfbc->cursor_palette.green[i] = default_cmap[7].green;
2111 sc->gfbc->cursor_palette.blue[i] = default_cmap[7].blue;
2115 /* Enable cursor... */
2116 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_2);
2117 if(!(regval & 0x01)) {
2119 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
2121 else if(regval & 0x03) {
2123 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
2127 /* Generate the screen color map... */
2128 num_cmap_entries = sizeof(default_cmap) / sizeof(struct cmap);
2129 for(i = 0; i < sc->gfbc->palette.count / num_cmap_entries; i++)
2130 for(j = 0; j < num_cmap_entries; j++) {
2131 sc->gfbc->palette.red[(num_cmap_entries * i) + j] =
2132 default_cmap[j].red;
2133 sc->gfbc->palette.green[(num_cmap_entries * i) + j] =
2134 default_cmap[j].green;
2135 sc->gfbc->palette.blue[(num_cmap_entries * i) + j] =
2136 default_cmap[j].blue;
2141 bt485_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
2143 struct gfb_softc *sc;
2147 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2149 /* addr[9:0] assumed to be 0 */
2150 /* set addr[7:0] to 0 */
2151 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0x00);
2153 /* spit out the color data */
2154 for(i = 0; i < palette->count; i++) {
2155 palette->red[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_PALETTE);
2156 palette->green[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_PALETTE);
2157 palette->blue[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_PALETTE);
2163 bt485_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
2165 struct gfb_softc *sc;
2169 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2171 /* addr[9:0] assumed to be 0 */
2172 /* set addr[7:0] to 0 */
2173 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0x00);
2175 /* spit out the color data */
2176 for(i = 0; i < palette->count; i++) {
2177 sc->gfbc->ramdac_wr(sc, BT485_REG_PALETTE, palette->red[i]);
2178 sc->gfbc->ramdac_wr(sc, BT485_REG_PALETTE, palette->green[i]);
2179 sc->gfbc->ramdac_wr(sc, BT485_REG_PALETTE, palette->blue[i]);
2185 bt485_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2187 struct gfb_softc *sc;
2191 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2193 /* addr[9:0] assumed to be 0 */
2194 /* set addr[7:0] to 1 */
2195 sc->gfbc->ramdac_wr(sc, BT485_REG_COC_WRADDR, 0x01);
2197 /* spit out the cursor color data */
2198 for(i = 0; i < palette->count; i++) {
2199 palette->red[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_COCDATA);
2200 palette->green[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_COCDATA);
2201 palette->blue[i] = sc->gfbc->ramdac_rd(sc, BT485_REG_COCDATA);
2207 bt485_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2209 struct gfb_softc *sc;
2213 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2215 /* addr[9:0] assumed to be 0 */
2216 /* set addr[7:0] to 1 */
2217 sc->gfbc->ramdac_wr(sc, BT485_REG_COC_WRADDR, 0x01);
2219 /* spit out the cursor color data */
2220 for(i = 0; i < palette->count; i++) {
2221 sc->gfbc->ramdac_wr(sc, BT485_REG_COCDATA, palette->red[i]);
2222 sc->gfbc->ramdac_wr(sc, BT485_REG_COCDATA, palette->green[i]);
2223 sc->gfbc->ramdac_wr(sc, BT485_REG_COCDATA, palette->blue[i]);
2229 bt485_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
2231 struct gfb_softc *sc;
2235 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2237 *col = (sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_X_HIGH) & 0x0f) << 8;
2238 *col |= sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_X_LOW) & 0xff;
2239 *col /= adp->va_info.vi_cwidth;
2241 *row = (sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_Y_HIGH) & 0x0f) << 8;
2242 *row |= sc->gfbc->ramdac_rd(sc, BT485_REG_CURSOR_Y_LOW) & 0xff;
2243 *row /= adp->va_info.vi_cheight;
2250 bt485_set_hw_cursor(video_adapter_t *adp, int col, int row)
2252 struct gfb_softc *sc;
2257 /* Make sure the parameters are in range for the screen
2259 if((row > adp->va_info.vi_height) || (col > adp->va_info.vi_width))
2261 else if(((row * adp->va_info.vi_cheight) > 0x0fff) ||
2262 ((col * adp->va_info.vi_cwidth) > 0x0fff))
2264 else if((row < 0) || (col < 0)) {
2265 /* If either of the parameters is less than 0, then hide the
2270 /* Otherwise, just move the cursor as requested... */
2271 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2273 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_X_LOW,
2274 ((col + 8) * adp->va_info.vi_cwidth) & 0xff);
2275 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_X_HIGH,
2276 (((col + 8) * adp->va_info.vi_cwidth) >> 8) & 0x0f);
2277 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_Y_LOW,
2278 ((row + 4) * adp->va_info.vi_cheight) & 0xff);
2279 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_Y_HIGH,
2280 (((row + 4) * adp->va_info.vi_cheight) >> 8) & 0x0f);
2287 bt485_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
2288 int cellsize, int blink)
2290 struct gfb_softc *sc;
2291 int error, cell_count, count, i, j;
2296 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
2299 Make sure the parameters are in range for the cursor
2300 (it's a 64x64 cursor)...
2304 else if(height <= 0) {
2305 /* If height is less than or equal to 0, then hide the
2308 /* Otherwise, just resize the cursor as requested... */
2310 /* 64 pixels per cursor-row, 2 bits-per-pixel, so counts in
2312 cell_count = cellsize / 8;
2316 * Write the cursor image data:
2317 * set addr[9:8] to 0,
2318 * set addr[7:0] to 0,
2321 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2322 BT485_IREG_COMMAND_3);
2323 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2325 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2326 BT485_IREG_COMMAND_3);
2327 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2328 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0);
2330 /* Fill-in the desired pixels in the specified pixel-rows... */
2331 for(i = 0; i < height; i++) {
2332 for(j = 0; j < cell_count; j++)
2333 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2335 for(j = 0; j < count - cell_count; j++)
2336 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2340 /* Clear the remaining pixel rows... */
2342 for(j = 0; j < count; j++)
2343 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2347 * Write the cursor mask data:
2348 * set addr[9:8] to 2,
2349 * set addr[7:0] to 0,
2352 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2353 BT485_IREG_COMMAND_3);
2354 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2355 regval &= ~0x03; regval |= 0x02;
2356 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2357 BT485_IREG_COMMAND_3);
2358 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2359 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, 0);
2361 /* Fill-in the desired pixels in the specified pixel-rows... */
2362 for(i = 0; i < height; i++) {
2363 for(j = 0; j < cell_count; j++)
2364 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2366 for(j = 0; j < count - cell_count; j++)
2367 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2371 /* Clear the remaining pixel rows... */
2373 for(j = 0; j < count; j++)
2374 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
2377 /* set addr[9:0] back to 0 */
2378 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2379 BT485_IREG_COMMAND_3);
2380 regval = sc->gfbc->ramdac_rd(sc, BT485_REG_EXTENDED);
2382 sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR,
2383 BT485_IREG_COMMAND_3);
2384 sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
2390 ibm561_init(struct gfb_softc *sc)
2395 ibm561_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
2404 ibm561_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
2413 ibm561_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
2422 ibm561_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)