The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/fb/tga.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000, 2001 Andrew Miklic, Andrew Gallatin, Peter Jeremy,
    3  * and Thomas V. Crimi
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    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.
   14  *
   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
   25  * SUCH DAMAGE.
   26  */
   27 /*-
   28  * Copyright (c) 1995, 1996 Carnegie-Mellon University.
   29  * All rights reserved.
   30  *
   31  * Author: Chris G. Demetriou
   32  * 
   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.
   38  * 
   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.
   42  * 
   43  * Carnegie Mellon requests users of this software to return to
   44  *
   45  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   46  *  School of Computer Science
   47  *  Carnegie Mellon University
   48  *  Pittsburgh PA 15213-3890
   49  *
   50  * any improvements or extensions that they make and grant Carnegie the
   51  * rights to redistribute these changes.
   52  */
   53 
   54 #include <sys/cdefs.h>
   55 __FBSDID("$FreeBSD: releng/6.0/sys/dev/fb/tga.c 150981 2005-10-05 21:48:03Z marius $");
   56 
   57 #include <machine/stdarg.h>
   58 
   59 #include <sys/param.h>
   60 #include <sys/systm.h>
   61 #include <sys/kernel.h>
   62 #include <sys/module.h>
   63 #include <sys/conf.h>
   64 #include <sys/proc.h>
   65 #include <sys/fcntl.h>
   66 #include <sys/malloc.h>
   67 #include <sys/fbio.h>
   68 #include <sys/consio.h>
   69 
   70 #include <isa/isareg.h>
   71 #include <dev/fb/vgareg.h>
   72 
   73 #include <vm/vm.h>
   74 #include <vm/vm_param.h>
   75 #include <vm/pmap.h>
   76 
   77 #include <machine/md_var.h>
   78 #include <machine/pc/bios.h>
   79 #include <machine/clock.h>
   80 #include <machine/bus.h>
   81 #include <machine/pc/vesa.h>
   82 #include <machine/resource.h>
   83 #include <machine/rpb.h>
   84 
   85 #include <sys/bus.h>
   86 #include <sys/rman.h>
   87 
   88 #include <dev/pci/pcireg.h>
   89 #include <dev/pci/pcivar.h>
   90 
   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>
   97 
   98 #include "opt_fb.h"
   99 
  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);
  104 
  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 #ifdef TGA2
  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;
  113 #endif 
  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 *));
  120 
  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);
  129 
  130 /* RAMDAC-specific functions */
  131 static gfb_ramdac_init_t bt463_init;
  132 static void bt463_update_window_type(struct gfb_softc *);
  133 #if 0
  134 static gfb_ramdac_save_palette_t bt463_save_palette;
  135 static gfb_ramdac_load_palette_t bt463_load_palette;
  136 #endif 
  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;
  152 
  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;
  157 #if 0
  158 static vi_ioctl_t tga_ioctl;
  159 #endif
  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;
  168 
  169 static video_switch_t tgavidsw = {
  170         gfb_probe,
  171         tga_init,
  172         gfb_get_info,
  173         tga_query_mode,
  174         tga_set_mode,
  175         gfb_save_font,
  176         gfb_load_font,
  177         gfb_show_font,
  178         gfb_save_palette,
  179         gfb_load_palette,
  180         tga_set_border,
  181         gfb_save_state,
  182         gfb_load_state,
  183         tga_set_win_org,
  184         gfb_read_hw_cursor,
  185         gfb_set_hw_cursor,
  186         gfb_set_hw_cursor_shape,
  187         tga_blank_display,
  188         gfb_mmap,
  189         gfb_ioctl,
  190         tga_clear,
  191         tga_fill_rect,
  192         tga_bitblt,
  193         tga_error,
  194         tga_error,
  195         gfb_diag,
  196         gfb_save_cursor_palette,
  197         gfb_load_cursor_palette,
  198         gfb_copy,
  199         gfb_putp,
  200         tga_putc,
  201         tga_puts,
  202         tga_putm,
  203 };
  204 
  205 VIDEO_DRIVER(tga, tgavidsw, NULL);
  206 
  207 extern sc_rndr_sw_t txtrndrsw;
  208 RENDERER(tga, 0, txtrndrsw, gfb_set);
  209 
  210 #ifdef SC_PIXEL_MODE
  211 extern sc_rndr_sw_t gfbrndrsw;
  212 RENDERER(tga, PIXEL_MODE, gfbrndrsw, gfb_set);
  213 #endif /* SC_PIXEL_MODE */
  214 
  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 */
  219 
  220 RENDERER_MODULE(tga, gfb_set);
  221 
  222 #define MHz     * 1000000
  223 #define KHz     * 1000
  224 
  225 extern struct gfb_softc *gfb_device_softcs[2][MAX_NUM_GFB_CARDS];
  226 
  227 /*
  228    The following 3 variables exist only because we need statically
  229    allocated structures very early in boot to support tga_configure()...
  230 */
  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];
  240 
  241 static struct monitor decmonitors[] = {
  242         /* 0x0: 1280 x 1024 @ 72Hz */
  243         { 1280, 32,     160,    232,
  244           1024, 3,      3,      33,
  245           130808 KHz },
  246 
  247         /* 0x1: 1280 x 1024 @ 66Hz */
  248         { 1280, 32,     160,    232,
  249           1024, 3,      3,      33,
  250           119840 KHz },
  251 
  252         /* 0x2: 1280 x 1024 @ 60Hz */
  253         { 1280, 44,     184,    200,
  254           1024, 3,      3,      26,
  255           108180 KHz },
  256 
  257         /* 0x3: 1152 x  900 @ 72Hz */
  258         { 1152, 64,     112,    176,
  259           900,  6,      10,     44,
  260           103994 KHz },
  261 
  262         /* 0x4: 1600 x 1200 @ 65Hz */
  263         { 1600, 32,     192,    336,
  264           1200, 1,      3,      46,
  265           175 MHz },
  266 
  267         /* 0x5: 1024 x  768 @ 70Hz */
  268         { 1024, 24,     136,    144,
  269           768,  3,      6,      29,
  270           75 MHz },
  271 
  272         /* 0x6: 1024 x  768 @ 72Hz */
  273         { 1024, 16,     128,    128,
  274           768,  1,      6,      22,
  275           74 MHz },
  276 
  277         /* 0x7: 1024 x  864 @ 60Hz */
  278         { 1024, 12,     128,    116,
  279           864,  0,      3,      34,
  280           69 MHz },
  281 
  282         /* 0x8: 1024 x  768 @ 60Hz */
  283         { 1024, 56,     64,     200,
  284           768,  7,      9,      26,
  285           65 MHz },
  286 
  287         /* 0x9:  800 x  600 @ 72Hz */
  288         { 800,  56,     120,    64,
  289           600,  37,     6,      23,
  290           50 MHz },
  291 
  292         /* 0xa:  800 x  600 @ 60Hz */
  293         { 800,  40,     128,    88,
  294           600,  1,      4,      23,
  295           40 MHz },
  296 
  297         /* 0xb:  640 x  480 @ 72Hz */
  298         { 640,  24,     40,     128,
  299           480,  9,      3,      28,
  300           31500 KHz },
  301 
  302         /* 0xc:  640 x  480 @ 60Hz */
  303         { 640,  16,     96,     48,
  304           480,  10,     2,      33,
  305           25175 KHz },
  306 
  307         /* 0xd: 1280 x 1024 @ 75Hz */
  308         { 1280, 16,     144,    248,
  309           1024, 1,      3,      38,
  310           135 MHz  },
  311 
  312         /* 0xe: 1280 x 1024 @ 60Hz */
  313         { 1280, 19,     163,    234,
  314           1024, 6,      7,      44,
  315           110 MHz },
  316 
  317         /* 0xf: 1600 x 1200 @ 75Hz */
  318         /* XXX -- this one's weird.  rcd */
  319         { 1600, 32,     192,    336,
  320           1200, 1,      3,      46,
  321           202500 KHz }
  322 };
  323 
  324 #undef MHz
  325 #undef KHz
  326 
  327 #undef KB
  328 #define KB      * 1024
  329 #undef MB
  330 #define MB      * 1024 * 1024
  331 
  332 /*
  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...
  338  */
  339 static const struct cmap {
  340         u_char red;
  341         u_char green;
  342         u_char blue;
  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 */
  360 };
  361 
  362 extern struct gfb_font bold8x16;
  363 
  364 /*****************************************************************************
  365  *
  366  * FB-generic functions
  367  *
  368  ****************************************************************************/
  369 
  370 static int
  371 tga_init(int unit, video_adapter_t *adp, int flags)
  372 {
  373         struct gfb_softc *sc;
  374         struct gfb_conf *gfbc;
  375         unsigned int monitor;
  376         int card_type;
  377         int gder;
  378         int deep;
  379         int addrmask;
  380         int cs;
  381         int error;
  382         gfb_reg_t ccbr;
  383 
  384         /* Assume the best... */
  385         error = 0;
  386 
  387         sc = gfb_device_softcs[adp->va_model][unit];
  388         gfbc = sc->gfbc;
  389 
  390         /* Initialize palette counts... */
  391         gfbc->palette.count = 256;
  392         gfbc->cursor_palette.count = 3;
  393 
  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;
  404         adp->va_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) &
  425                                    VHCR_ACTIVE_MASK);
  426         adp->va_info.vi_width |= (READ_GFB_REGISTER(adp, TGA_REG_VHCR) &
  427                                    0x30000000) >> 19;
  428         switch(adp->va_info.vi_width) {
  429         case 0:
  430                 adp->va_info.vi_width = 8192;
  431                 break;
  432         case 1:
  433                 adp->va_info.vi_width = 8196;
  434                 break;
  435         default:
  436                 adp->va_info.vi_width *= 4;
  437                 break;
  438         }
  439         adp->va_info.vi_height = (READ_GFB_REGISTER(adp, TGA_REG_VVCR) &
  440                                    VVCR_ACTIVE_MASK);
  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;
  444 
  445         /*
  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...
  453         */
  454 
  455         /* Set the video base address... */     
  456         tga_set_win_org(sc->adp, 4 KB);
  457 
  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);
  462 
  463         /* Type the card... */
  464         if(adp->va_type == KD_TGA) {
  465                 if(!deep) {
  466 
  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;
  482 
  483                         if(addrmask == GDER_ADDR_4MB) {
  484 
  485                                 /* 4MB core map; T8-01 or T8-02 */
  486                                 if(!cs) {
  487                                         card_type = TGA_TYPE_T8_01;
  488                                         gfbc->name = "T8-01";
  489                                 } else {
  490                                         card_type = TGA_TYPE_T8_02;
  491                                         gfbc->name = "T8-02";
  492                                 }
  493                         } else if(addrmask == GDER_ADDR_8MB) {
  494 
  495                                 /* 8MB core map; T8-22 */
  496                                 if(cs) {/* sanity */
  497                                         card_type = TGA_TYPE_T8_22;
  498                                         gfbc->name = "T8-22";
  499                                 }
  500                         } else if(addrmask == GDER_ADDR_16MB) {
  501 
  502                                 /* 16MB core map; T8-44 */
  503                                 if(cs) {/* sanity */
  504                                         card_type = TGA_TYPE_T8_44;
  505                                         gfbc->name = "T8-44";
  506                                 }
  507                         } else if(addrmask == GDER_ADDR_32MB) {
  508 
  509                                 /* 32MB core map; ??? */
  510                                 card_type = TGA_TYPE_UNKNOWN;
  511                         }
  512                 } else {
  513 
  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;
  530 
  531                         /* 32bpp frame buffer */
  532                         if(addrmask == GDER_ADDR_4MB) {
  533 
  534                                 /* 4MB core map; ??? */
  535                                 card_type = TGA_TYPE_UNKNOWN;
  536                         } else if(addrmask == GDER_ADDR_8MB) {
  537 
  538                                 /* 8MB core map; ??? */
  539                                 card_type = TGA_TYPE_UNKNOWN;
  540                         } else if(addrmask == GDER_ADDR_16MB) {
  541 
  542                                 /* 16MB core map; T32-04 or T32-08 */
  543                                 if(!cs) {
  544                                         card_type = TGA_TYPE_T32_04;
  545                                         gfbc->name = "T32-04";
  546                                 } else {
  547                                         card_type = TGA_TYPE_T32_08;
  548                                         gfbc->name = "T32-08";
  549                                 }
  550                         } else if(addrmask == GDER_ADDR_32MB) {
  551 
  552                                 /* 32MB core map; T32-88 */
  553                                 if(cs) {/* sanity */
  554                                         card_type = TGA_TYPE_T32_88;
  555                                         gfbc->name = "T32-88";
  556                                 }
  557                         }
  558                 }
  559         }
  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;
  573 
  574                 /* 4MB core map */
  575                 if(addrmask == GDER_ADDR_4MB)
  576                         card_type = TGA_TYPE_UNKNOWN;
  577 
  578                 /* 8MB core map */
  579                 else if(addrmask == GDER_ADDR_8MB) {
  580                         card_type = TGA2_TYPE_3D30;
  581                         gfbc->name = "3D30";
  582                 }
  583 
  584                 /* 16MB core map */
  585                 else if(addrmask == GDER_ADDR_16MB) {
  586                         card_type = TGA2_TYPE_4D20;
  587                         gfbc->name = "4D20";
  588                 }
  589                 else if(addrmask == GDER_ADDR_32MB)
  590                         card_type = TGA_TYPE_UNKNOWN;
  591         }
  592 
  593         /*
  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...
  599         */
  600         if(adp->va_type == KD_TGA2)
  601                 return(error);
  602 
  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);
  606                 error = ENODEV;
  607                 goto done;
  608         } 
  609 
  610         /* Clear and disable interrupts... */
  611         WRITE_GFB_REGISTER(adp, TGA_REG_SISR, 0x00000001);
  612 
  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);
  617         }
  618 done:
  619         return(error);
  620 }
  621 
  622 static void
  623 tga2_init(sc, monitor)
  624         struct gfb_softc *sc;
  625         int monitor;
  626 {
  627         return;
  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);
  646 }
  647 
  648 static int
  649 tga_query_mode(video_adapter_t *adp, video_info_t *info)
  650 {
  651         int error;
  652 
  653         /* Assume the best... */
  654         error = 0;
  655 
  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))
  660                         error = ENODEV;
  661         }
  662         else {
  663                 if(info->vi_mode != 0)
  664                         error = ENODEV;
  665         }
  666         return(error);
  667 }
  668 
  669 static int
  670 tga_set_mode(video_adapter_t *adp, int mode)
  671 {
  672         int error;
  673         gfb_reg_t gder;
  674         gfb_reg_t vgae_mask;
  675 
  676         /* Assume the best... */
  677         error = 0;
  678         
  679         gder = READ_GFB_REGISTER(adp, TGA_REG_GDER);
  680 
  681         /*
  682            Determine the adapter type first
  683            so we know which modes are valid for it...
  684         */
  685         switch(adp->va_type) {
  686         case KD_TGA2:
  687 
  688                 /*
  689                    Verify that this mode is supported
  690                    on this adapter...
  691                 */
  692                 switch(mode) {
  693                 case TGA2_2DA_MODE:
  694                         vgae_mask = ~0x00400000;
  695                         WRITE_GFB_REGISTER(adp, TGA_REG_GDER,
  696                             gder & vgae_mask);
  697                         adp->va_mode = mode;
  698                         break;
  699                 case TGA2_VGA_MODE:
  700                         vgae_mask = 0x00400000;
  701                         WRITE_GFB_REGISTER(adp, TGA_REG_GDER,
  702                             gder | vgae_mask);
  703                         adp->va_mode = mode;
  704                         break;
  705                 default:
  706                         error = ENODEV;
  707                 }
  708                 break;
  709         case KD_TGA:
  710 
  711                 /*
  712                    Verify that this mode is supported
  713                    on this adapter...
  714                 */
  715                 switch(mode) {
  716                 case 0:
  717                         break;
  718                 default:
  719                         error = ENXIO;
  720                 }
  721                 break;
  722         default:
  723                 error = ENODEV;
  724         }
  725         return(error);
  726 }
  727 
  728 static int
  729 tga_blank_display(video_adapter_t *adp, int mode)
  730 {
  731         gfb_reg_t blanked;
  732         int error;
  733 
  734         /* Assume the best... */
  735         error = 0;
  736 
  737         blanked = READ_GFB_REGISTER(adp, TGA_REG_VVVR) &
  738             (VVR_BLANK | VVR_VIDEOVALID | VVR_CURSOR);
  739 
  740         /* If we're not already blanked, then blank...*/
  741         switch(mode) {
  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);
  746                 }
  747                 break;
  748         case V_DISPLAY_STAND_BY:
  749                 if(blanked != VVR_BLANK) {
  750                         blanked = VVR_BLANK;
  751                         WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
  752                 }
  753                 break;
  754         case V_DISPLAY_ON:
  755                 if(blanked != (VVR_VIDEOVALID | VVR_CURSOR)) {
  756                         blanked = VVR_VIDEOVALID | VVR_CURSOR;
  757                         WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, blanked);
  758                 }
  759                 break;
  760         default:
  761                 break;
  762         }
  763         return(0);
  764 }
  765 
  766 #if 0
  767 
  768 static int
  769 tga_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
  770 {
  771         struct gfb_softc *sc;
  772         int error;
  773 
  774         error = 0;
  775         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
  776         switch (cmd) {
  777         case FBIOPUTCMAP:
  778 #if 0
  779                 tga_schedule_intr(sc, bt463_load_palette_intr);
  780                 break;
  781 #endif
  782         case FBIO_GETWINORG:
  783         case FBIO_SETWINORG:
  784         case FBIO_SETDISPSTART:
  785         case FBIO_SETLINEWIDTH:
  786         case FBIO_GETPALETTE:
  787         case FBIOGTYPE:
  788         case FBIOGETCMAP:
  789         default:
  790                 error = fb_commonioctl(adp, cmd, arg); 
  791         }
  792         return(error);
  793 }
  794 
  795 #endif /* 0 */
  796 
  797 static int
  798 tga_set_border(video_adapter_t *adp, int color) {
  799         return(ENODEV);
  800 }
  801 
  802 static int
  803 tga_set_win_org(video_adapter_t *adp, off_t offset) {
  804         gfb_reg_t vvbr;
  805         u_int16_t window_orig;
  806         int gder;
  807         int deep;
  808         int cs;
  809 
  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;
  814 
  815         /*
  816            Set the window (framebuffer) origin according to the video
  817            base address...
  818         */
  819         window_orig = offset / ((1 + cs) * (1 + deep) * (1 + deep) * 2 KB);
  820         adp->va_window_orig = window_orig * ((1 + cs) * (1 + deep) *
  821             (1 + deep) * 2 KB);
  822 
  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);
  827         return(0);
  828 }
  829 
  830 static int
  831 tga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) {
  832         int off;
  833         gfb_reg_t gpxr;
  834         gfb_reg_t gmor;
  835         gfb_reg_t gbcr0;
  836         gfb_reg_t gbcr1;
  837         gfb_reg_t color;
  838 
  839         /* Save the pixel mode... */
  840         gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
  841 
  842         /* Save the pixel mask... */
  843         gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
  844 
  845         /* Save the block-color... */
  846         gbcr0 = READ_GFB_REGISTER(adp, TGA_REG_GBCR0);
  847         gbcr1 = READ_GFB_REGISTER(adp, TGA_REG_GBCR1);
  848 
  849         /* Set the pixel mode (block-fill)... */
  850         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
  851                            (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_BLK_FILL);
  852 
  853         /* Set the pixel mask (enable writes to all pixels)... */
  854         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, 0xffffffff);
  855 
  856         color = ((val & 0xff00) << 24) || ((val & 0xff00) << 16) ||
  857             ((val & 0xff00) << 8) || ((val & 0xff00) << 0);
  858 
  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);
  862 
  863         /*
  864            Just traverse the buffer, one 2K-pixel span at a time, setting
  865            each pixel to the bolck-color...
  866         */
  867         for(off = (x * y); off < ((x + cx) * (y + cy)); off += (2 KB))
  868                 WRITE_GFB_BUFFER(adp, off >> 2L, 0x000007ff);
  869 
  870         /* Restore the pixel mode... */
  871         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
  872 
  873         /* Restore the pixel mask... */
  874         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
  875 
  876         /* Restore the block-color... */
  877         WRITE_GFB_REGISTER(adp, TGA_REG_GBCR0, gbcr0);
  878         WRITE_GFB_REGISTER(adp, TGA_REG_GBCR1, gbcr1);
  879 
  880         return(0);
  881 }
  882 
  883 static int
  884 tga_bitblt(video_adapter_t *adp, ...) {
  885         va_list args;
  886         int i, count;
  887         gfb_reg_t gmor;
  888         gfb_reg_t gopr;
  889         vm_offset_t src, dst;
  890 
  891         va_start(args, adp);
  892 
  893         /* Save the pixel mode... */
  894         gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
  895 
  896         /* Save the raster op... */
  897         gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
  898 
  899         /* Set the pixel mode (copy)... */
  900         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
  901             (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_COPY);
  902 
  903         /* Set the raster op (src)... */
  904         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
  905 
  906         src = (va_arg(args, vm_offset_t) + adp->va_window_orig) &
  907             0x0000000000fffff8;
  908         dst = (va_arg(args, vm_offset_t) + adp->va_window_orig) &
  909             0x0000000000fffff8;
  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);
  914         }
  915 
  916         /* Restore the raster op... */
  917         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
  918 
  919         /* Restore the pixel mode... */
  920         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
  921 
  922         va_end(args);
  923         return(0);
  924 }
  925 
  926 static int
  927 #if 0
  928 tga_clear(video_adapter_t *adp, int n)
  929 #else
  930 tga_clear(video_adapter_t *adp)
  931 #endif
  932 {
  933         int off;
  934         gfb_reg_t gpxr;
  935         gfb_reg_t gmor;
  936         gfb_reg_t gopr;
  937 
  938 #if 0
  939         if(n == 0) return(0);
  940 #endif
  941 
  942         /* Save the pixel mode... */
  943         gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
  944 
  945         /* Save the pixel mask... */
  946         gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
  947 
  948         /* Save the raster op... */
  949         gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
  950 
  951         /* Set the pixel mode (opaque-fill)... */
  952         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
  953                            (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_OPQ_FILL);
  954 
  955         /* Set the pixel mask (enable writes to all pixels)... */
  956         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, 0xffffffff);
  957 
  958         /* Set the raster op (clear)... */
  959         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x00);
  960 
  961         /*
  962            Just traverse the buffer, one 2K-pixel span at a time, clearing
  963            each pixel...
  964         */
  965 #if 0
  966         for(off = 0; off < (n * adp->va_line_width); off += (2 KB))
  967 #endif
  968         for(off = 0; off < adp->va_window_size; off += (2 KB))
  969                 WRITE_GFB_BUFFER(adp, off >> 2L, 0x000007ff);
  970 
  971         /* Restore the pixel mask... */
  972         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
  973 
  974         /* Restore the raster op... */
  975         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
  976 
  977         /* Restore the pixel mode... */
  978         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
  979 
  980         return(0);
  981 }
  982 
  983 int
  984 tga_putc(video_adapter_t *adp, vm_offset_t off, u_int8_t c, u_int8_t a)
  985 {
  986         int i;
  987         gfb_reg_t gpxr;
  988         gfb_reg_t gmor;
  989         gfb_reg_t gopr;
  990         gfb_reg_t gbgr;
  991         gfb_reg_t gfgr;
  992         gfb_reg_t mask;
  993         int row, col;
  994         u_int8_t *pixel;
  995         vm_offset_t poff;
  996         struct gfb_softc *sc;
  997         int pixel_size;
  998 
  999         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1000         pixel_size = adp->va_info.vi_depth / 8;
 1001 
 1002         /* Save the pixel mode... */
 1003         gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
 1004 
 1005         /* Save the pixel mask... */
 1006         gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
 1007 
 1008         /* Save the raster op... */
 1009         gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
 1010 
 1011         /* Save the background color... */
 1012         gbgr = READ_GFB_REGISTER(adp, TGA_REG_GBGR);
 1013 
 1014         /* Save the foreground color... */
 1015         gfgr = READ_GFB_REGISTER(adp, TGA_REG_GFGR);
 1016 
 1017         /* Set the pixel mode (opaque-stipple)... */
 1018         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
 1019             (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_OPQ_STPL);
 1020 
 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);
 1024 
 1025         /* Set the raster op (src)... */
 1026         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
 1027 
 1028         /* Set the foreground color mask from the attribute byte... */
 1029         mask = (a & 0x80) ? a : (a & 0x0f);
 1030 
 1031         /* Propagate the 8-bit mask across the full 32 bits... */
 1032         mask |= (mask << 24) | (mask << 16) | (mask << 8);
 1033 
 1034         /* Set the foreground color... */
 1035         WRITE_GFB_REGISTER(adp, TGA_REG_GFGR, mask);
 1036 
 1037         /* Set the background color mask from the attribute byte... */
 1038         mask = (a >> 4) & 0x07;
 1039 
 1040         /* Propagate the 8-bit mask across the full 32 bits... */
 1041         mask |= (mask << 24) | (mask << 16) | (mask << 8);
 1042 
 1043         /* Set the background color... */
 1044         WRITE_GFB_REGISTER(adp, TGA_REG_GBGR, mask);
 1045 
 1046         /* Get the start of the array of pixels rows for this character... */
 1047         pixel = sc->gfbc->font + (c * adp->va_info.vi_cheight);
 1048 
 1049         /* Calculate the new cursor position... */
 1050         row = off / adp->va_info.vi_width;
 1051         col = off % adp->va_info.vi_width;
 1052 
 1053         /* Iterate over all the pixel rows for this character... */
 1054         for(i = 0; i < adp->va_info.vi_cheight; i++) {
 1055 
 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);
 1060 
 1061                 /* Now display the current pixel row... */
 1062                 WRITE_GFB_BUFFER(adp, poff, pixel[i]);
 1063         }
 1064 
 1065         /* Restore the foreground color... */
 1066         WRITE_GFB_REGISTER(adp, TGA_REG_GFGR, gfgr);
 1067 
 1068         /* Restore the background color... */
 1069         WRITE_GFB_REGISTER(adp, TGA_REG_GBGR, gbgr);
 1070 
 1071         /* Restore the pixel mode... */
 1072         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
 1073 
 1074         /* Restore the pixel mask... */
 1075         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
 1076 
 1077         /* Restore the raster op... */
 1078         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
 1079 
 1080         return(0);
 1081 }
 1082 
 1083 int
 1084 tga_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
 1085 {
 1086         int i, j, k;
 1087         gfb_reg_t gpxr;
 1088         gfb_reg_t gmor;
 1089         gfb_reg_t gopr;
 1090         gfb_reg_t row, col;
 1091         u_int8_t *pixel;
 1092         u_int8_t c;
 1093         u_int8_t a;
 1094         gfb_reg_t p;
 1095         vm_offset_t poff;
 1096         struct gfb_softc *sc;
 1097         int pixel_size;
 1098 
 1099         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1100         pixel_size = adp->va_info.vi_depth / 8;
 1101 
 1102         /* If the string in empty, just return now... */
 1103         if(len == 0) return(0);
 1104 
 1105         for(i = 0; i < len; i++)
 1106                 tga_putc(adp, off + i, s[i] & 0x00ff, (s[i] & 0xff00) >> 8);
 1107         return(0);
 1108 
 1109         /* Save the pixel mode... */
 1110         gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
 1111 
 1112         /* Save the pixel mask... */
 1113         gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
 1114 
 1115         /* Save the raster op... */
 1116         gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
 1117 
 1118         /* Set the pixel mode (simple)... */
 1119         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, (gmor & 0xffffffc0) | 0x00);
 1120 
 1121         /* Set the pixel mask (enable writes to all 32 pixels)... */
 1122         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, (gpxr & 0xfffffff0) | 0xf);
 1123 
 1124         /* Set the raster op (src)... */
 1125         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x03);
 1126 
 1127         /*
 1128            First, do as many characters-rows at a time as possible (as exist)...
 1129         */
 1130         for(i = 0; (len - i) > adp->va_info.vi_width;
 1131             i += adp->va_info.vi_width) {
 1132 
 1133                 /*
 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())...
 1137                 */
 1138                 for(j = 0; j < adp->va_info.vi_cheight; j++) {
 1139                         p = 0;
 1140                         for(k = 0; k < adp->va_info.vi_width; k++) {
 1141 
 1142                                 /*
 1143                                    Get this character...
 1144                                 */
 1145                                 c = s[i + k] & 0x00ff;
 1146 
 1147                                 /*
 1148                                    Get the attribute for this character...
 1149                                 */
 1150                                 a = (s[i + k] & 0xff00) >> 8;
 1151 
 1152                                 /*
 1153                                    Get the start of the array of pixels rows for
 1154                                    this character...
 1155                                 */
 1156                                 pixel = sc->gfbc->font +
 1157                                         (c * adp->va_info.vi_cheight);
 1158 
 1159                                 /* Shift the other pre-existing pixel rows... */
 1160                                 p <<= 8;
 1161 
 1162                                 /*
 1163                                    Get the first pixel row for
 1164                                    this character...
 1165                                 */
 1166                                 p |= pixel[j];
 1167 
 1168                                 if (((k + 1) % sizeof(gfb_reg_t)) == 0) {
 1169 
 1170                                         /*
 1171                                            Calculate the new cursor
 1172                                            position...
 1173                                         */
 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;
 1180 
 1181                                         /*
 1182                                            Get the address of the current
 1183                                            character's pixel-row...
 1184                                         */
 1185                                         poff = ((col * adp->va_info.vi_cwidth * 
 1186                                             pixel_size) + (((row *
 1187                                             adp->va_info.vi_cheight) + j) *
 1188                                             adp->va_line_width)) /
 1189                                             sizeof(gfb_reg_t);
 1190 
 1191                                         /*
 1192                                            Now display the current
 1193                                            pixel row...
 1194                                         */
 1195                                         (*vidsw[adp->va_index]->putp)(adp, poff,
 1196                                             p, a, sizeof(gfb_reg_t),
 1197                                             adp->va_info.vi_depth, 1, 0);
 1198 
 1199                                         /* Reset (clear) p... */
 1200                                         p = 0;
 1201                                 }
 1202                         }
 1203                 }
 1204         }
 1205 
 1206         /*
 1207            Next, do as many character-sets at a time as possible (as exist)...
 1208         */
 1209         for(; (len - i) > sizeof(gfb_reg_t); i += sizeof(gfb_reg_t)) {
 1210 
 1211                 /*
 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())...
 1215                 */
 1216                 for(j = 0; j < adp->va_info.vi_cheight; j++) {
 1217                         p = 0;
 1218                         for(k = 0; k < sizeof(gfb_reg_t); k++) {
 1219 
 1220                                 /*
 1221                                    Get this character...
 1222                                 */
 1223                                 c = s[i + k] & 0x00ff;
 1224 
 1225                                 /*
 1226                                    Get the attribute for this character...
 1227                                 */
 1228                                 a = (s[i + k] & 0xff00) >> 8;
 1229 
 1230                                 /*
 1231                                    Get the start of the array of pixels rows for
 1232                                    this character...
 1233                                 */
 1234                                 pixel = sc->gfbc->font +
 1235                                     (c * adp->va_info.vi_cheight);
 1236 
 1237                                 /* Shift the other pre-existing pixel rows... */
 1238                                 p <<= 8;
 1239 
 1240                                 /*
 1241                                    Get the first pixel row for
 1242                                    this character...
 1243                                 */
 1244                                 p |= pixel[j];
 1245 
 1246                                 if (((k + 1) % sizeof(gfb_reg_t)) == 0) {
 1247 
 1248                                         /*
 1249                                            Calculate the new cursor
 1250                                            position...
 1251                                         */
 1252                                         row = (off + i) / adp->va_info.vi_width;
 1253                                         col = (off + i) % adp->va_info.vi_width;
 1254 
 1255                                         /*
 1256                                            Get the address of the current
 1257                                            character's pixel-row...
 1258                                         */
 1259                                         poff = ((col * adp->va_info.vi_cwidth * 
 1260                                             pixel_size) + (((row *
 1261                                             adp->va_info.vi_cheight) + j) *
 1262                                             adp->va_line_width)) /
 1263                                             sizeof(gfb_reg_t);
 1264 
 1265                                         /*
 1266                                            Now display the current
 1267                                            pixel row...
 1268                                         */
 1269                                         (*vidsw[adp->va_index]->putp)(adp, poff,
 1270                                             p, a, sizeof(gfb_reg_t),
 1271                                             adp->va_info.vi_depth, 1, 0);
 1272 
 1273                                         /* Reset (clear) p... */
 1274                                         p = 0;
 1275                                 }
 1276                         }
 1277                 }
 1278         }
 1279 
 1280         /* Restore the pixel mode... */
 1281         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
 1282 
 1283         /* Restore the pixel mask... */
 1284         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
 1285 
 1286         /* Restore the raster op... */
 1287         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
 1288 
 1289         /* Finally, do the remaining characters a character at-a-time... */
 1290         for(; i < len; i++) {
 1291                 /*
 1292                    Get this character...
 1293                 */
 1294                 c = s[i] & 0x00ff;
 1295 
 1296                 /*
 1297                    Get the attribute for this character...
 1298                 */
 1299                 a = (s[i] & 0xff00) >> 8;
 1300 
 1301                 /*
 1302                    Display this character...
 1303                 */
 1304                 tga_putc(adp, off + i, c, a);
 1305         }
 1306         return(0);
 1307 }
 1308 
 1309 int
 1310 tga_putm(video_adapter_t *adp, int x, int y, u_int8_t *pixel_image,
 1311             gfb_reg_t pixel_mask, int size, int width)
 1312 {
 1313         gfb_reg_t gpxr;
 1314         gfb_reg_t gmor;
 1315         gfb_reg_t gopr;
 1316         int i, pixel_size;
 1317         vm_offset_t poff;
 1318 
 1319         pixel_size = adp->va_info.vi_depth / 8;
 1320 
 1321         /* Save the pixel mode... */
 1322         gmor = READ_GFB_REGISTER(adp, TGA_REG_GMOR);
 1323 
 1324         /* Save the pixel mask... */
 1325         gpxr = READ_GFB_REGISTER(adp, TGA_REG_GPXR_P);
 1326 
 1327         /* Save the raster op... */
 1328         gopr = READ_GFB_REGISTER(adp, TGA_REG_GOPR);
 1329 
 1330         /* Set the pixel mode (simple)... */
 1331         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR,
 1332             (gmor & ~GMOR_MODE_MASK) | GMOR_MODE_SIMPLE);
 1333 
 1334         /* Set the pixel mask (enable writes to the first 8 pixels)... */
 1335         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, (gpxr & 0xfffffff0) | 0xf);
 1336 
 1337         /* Set the raster op (src)... */
 1338         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, (gopr & 0xfffffff0) | 0x3);
 1339 
 1340         /* Iterate over all the pixel rows for the mouse pointer... */
 1341         for(i = 0; i < size; i++) {
 1342 
 1343                 /* Get the address of the mouse pointer's pixel-row... */
 1344                 poff = ((x * pixel_size) + ((y + i) * adp->va_line_width)) /
 1345                     sizeof(gfb_reg_t);
 1346 
 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);
 1350         }
 1351 
 1352         /* Restore the pixel mode... */
 1353         WRITE_GFB_REGISTER(adp, TGA_REG_GPXR_P, gpxr);
 1354 
 1355         /* Restore the pixel mask... */
 1356         WRITE_GFB_REGISTER(adp, TGA_REG_GMOR, gmor);
 1357 
 1358         /* Restore the raster op... */
 1359         WRITE_GFB_REGISTER(adp, TGA_REG_GOPR, gopr);
 1360 
 1361         return(0);
 1362 }
 1363 
 1364 static int
 1365 tga_error(void)
 1366 {
 1367         return(0);
 1368 }
 1369 
 1370 /*****************************************************************************
 1371  *
 1372  * TGA-specific functions
 1373  *
 1374  ****************************************************************************/
 1375 
 1376 static int
 1377 tga_builtin_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
 1378 {
 1379         int i;
 1380         int error;
 1381         struct gfb_softc *sc;
 1382 
 1383         error = 0;
 1384         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1385 
 1386         /*
 1387          * We store 8 bit values in the palette buffer, while the standard
 1388          * VGA has 6 bit DAC .
 1389          */
 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;
 1395         }
 1396         return(error);
 1397 }
 1398 
 1399 static int
 1400 tga_builtin_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
 1401 {
 1402         int i;
 1403         int error;
 1404         struct gfb_softc *sc;
 1405 
 1406         error = 0;
 1407         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1408 
 1409         /*
 1410          * We store 8 bit values in the palette buffer, while the standard
 1411          * VGA has 6 bit DAC .
 1412         */
 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);
 1419         }
 1420         return(error);
 1421 }
 1422 
 1423 #ifdef TGA2
 1424 static int
 1425 tga2_builtin_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
 1426 {
 1427         int i;
 1428         int error;
 1429         struct gfb_softc *sc;
 1430 
 1431         error = 0;
 1432         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1433 
 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);
 1438 
 1439         /* spit out the colormap data */
 1440         for(i = 0; i < palette->count; i++) {
 1441                 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
 1442                     palette->red[i]);
 1443                 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, 
 1444                     palette->green[i]);
 1445                 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, 
 1446                     palette->blue[i]);
 1447         }
 1448         return(error);
 1449 }
 1450 
 1451 static int
 1452 tga2_builtin_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
 1453 {
 1454         int i;
 1455         int error;
 1456         struct gfb_softc *sc;
 1457 
 1458         error = 0;
 1459         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1460 
 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);
 1465 
 1466         /* spit out the colormap data */
 1467         for(i = 0; i < palette->count; i++) {
 1468                 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA,
 1469                     palette->red[i]);
 1470                 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, 
 1471                     palette->green[i]);
 1472                 sc->gfbc->ramdac_wr(sc, BT463_REG_CMAP_DATA, 
 1473                     palette->blue[i]);
 1474         }
 1475         return(error);
 1476 }
 1477 
 1478 static int
 1479 tga2_builtin_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 1480 {
 1481         int i;
 1482         int error;
 1483         struct gfb_softc *sc;
 1484 
 1485         error = 0;
 1486         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1487 
 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);
 1492 
 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]);
 1498         }
 1499         return(error);
 1500 }
 1501 
 1502 static int
 1503 tga2_builtin_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 1504 {
 1505         int i;
 1506         int error;
 1507         struct gfb_softc *sc;
 1508 
 1509         error = 0;
 1510         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1511 
 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);
 1516 
 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]);
 1522         }
 1523         return(error);
 1524 }
 1525 
 1526 #endif /* TGA2 */
 1527 
 1528 static int
 1529 tga_builtin_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
 1530 {
 1531         gfb_reg_t cxyr;
 1532         int error;
 1533 
 1534         /* Assume the best... */
 1535         error = 0;
 1536 
 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;
 1540         return(error);
 1541 }
 1542 
 1543 static int
 1544 tga_builtin_set_hw_cursor(video_adapter_t *adp, int col, int row)
 1545 {
 1546         int error;
 1547         gfb_reg_t cxyr;
 1548         gfb_reg_t vvvr;
 1549 
 1550         /* Assume the best... */
 1551         error = 0;
 1552 
 1553         vvvr = READ_GFB_REGISTER(adp, TGA_REG_VVVR);
 1554 
 1555         /*
 1556            Make sure the parameters are in range for the screen
 1557            size...
 1558         */
 1559         if((row > adp->va_info.vi_height) ||
 1560             (col > adp->va_info.vi_width))
 1561                 error = EINVAL;
 1562         else if(((row * adp->va_info.vi_cheight) > 0x0fff) ||
 1563             ((col * adp->va_info.vi_cwidth) > 0x0fff))
 1564                 error = EINVAL;
 1565         /*
 1566            If either of the parameters is less than 0,
 1567            then hide the cursor...
 1568         */
 1569         else if((row < 0) || (col < 0)) {
 1570                 if((vvvr & 0x00000004) != 0) {
 1571                         vvvr &= 0xfffffffb;
 1572                         WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
 1573                 }
 1574         }
 1575                 
 1576         /* Otherwise, just move the cursor as requested... */
 1577         else {
 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) {
 1583                         vvvr |= 0x00000004;
 1584                 WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
 1585                 }
 1586         }
 1587         return(error);
 1588 }
 1589 
 1590 static int
 1591 tga_builtin_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
 1592             int cellsize, int blink)
 1593 {
 1594         int i, j;
 1595         vm_offset_t cba;
 1596         gfb_reg_t window_orig;
 1597         gfb_reg_t ccbr;
 1598         gfb_reg_t vvvr;
 1599         int error;
 1600 
 1601         /* Assume the best... */
 1602         error = 0;
 1603 
 1604         vvvr = READ_GFB_REGISTER(adp, TGA_REG_VVVR);
 1605 
 1606         /*
 1607            Make sure the parameters are in range for the cursor
 1608            (it's a 64x64 cursor)...
 1609         */
 1610         if(height > 64)
 1611                 error = EINVAL;
 1612 
 1613         /* If height is less than or equal to 0, then hide the cursor... */
 1614         else if(height <= 0) {
 1615                 if((vvvr & 0x00000004) != 0) {
 1616                         vvvr &= 0xfffffffb;
 1617                         WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
 1618                 }
 1619         }
 1620 
 1621         /* Otherwise, just resize the cursor as requested... */
 1622         else {
 1623                 ccbr = READ_GFB_REGISTER(adp, TGA_REG_CCBR);
 1624                 ccbr &= 0xffff03ff;
 1625                 ccbr |= ((height - 1) << 10);
 1626                 WRITE_GFB_REGISTER(adp, TGA_REG_CCBR, ccbr);
 1627                 if((vvvr & 0x00000004) == 0) {
 1628                         vvvr |= 0x00000004;
 1629                         WRITE_GFB_REGISTER(adp, TGA_REG_VVVR, vvvr);
 1630                 }
 1631 
 1632                 /* Save the window origin... */
 1633                 window_orig = adp->va_window_orig;
 1634 
 1635                 /*
 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...
 1640                 */
 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);
 1646                 }
 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);
 1653                 }
 1654 
 1655                 /* Restore the window origin... */
 1656                 adp->va_window_orig = window_orig;
 1657 
 1658         }
 1659         return(error);
 1660 }
 1661 
 1662 static void
 1663 bt463_load_palette_intr(struct gfb_softc *sc)
 1664 {
 1665         sc->gfbc->ramdac_save_palette(sc->adp, &sc->gfbc->palette);
 1666 }
 1667 
 1668 static void
 1669 bt463_load_cursor_palette_intr(struct gfb_softc *sc)
 1670 {
 1671         sc->gfbc->ramdac_load_cursor_palette(sc->adp, &sc->gfbc->cursor_palette);
 1672 }
 1673 
 1674 static int
 1675 tga_schedule_intr(struct gfb_softc *sc, void (*f)(struct gfb_softc *))
 1676 {
 1677         /* Busy-wait for the previous interrupt to complete... */
 1678         while((READ_GFB_REGISTER(sc->adp, TGA_REG_SISR) & 0x00000001) != 0);
 1679 
 1680         /* Arrange for f to be called at the next end-of-frame interrupt... */
 1681         sc->gfbc->ramdac_intr = f;
 1682 
 1683         /* Enable the interrupt... */
 1684         WRITE_GFB_REGISTER(sc->adp, TGA_REG_SISR, 0x00010000);
 1685         return(0);
 1686 }
 1687 
 1688 static u_int8_t
 1689 tga_bt485_rd(struct gfb_softc *sc, u_int btreg)
 1690 {
 1691         gfb_reg_t rdval;
 1692 
 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);
 1699 }
 1700 
 1701 static void
 1702 tga_bt485_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
 1703 {
 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);
 1709 }
 1710 
 1711 static u_int8_t
 1712 tga2_ibm561_rd(struct gfb_softc *sc, u_int btreg)
 1713 {
 1714         bus_space_handle_t ramdac;
 1715         u_int8_t retval;
 1716 
 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);
 1722         return(retval);
 1723 }
 1724 
 1725 static void
 1726 tga2_ibm561_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
 1727 {
 1728         bus_space_handle_t ramdac;
 1729 
 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);
 1735 }
 1736 
 1737 static u_int8_t
 1738 tga_bt463_rd(struct gfb_softc *sc, u_int btreg)
 1739 {
 1740         gfb_reg_t rdval;
 1741 
 1742         /* 
 1743          * Strobe CE# (high->low->high) since status and data are latched on 
 1744          * the falling and rising edges (repsectively) of this active-low
 1745          * signal.
 1746          */
 1747         
 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);
 1757 }
 1758 
 1759 static void
 1760 tga_bt463_wr(struct gfb_softc *sc, u_int btreg, u_int8_t val)
 1761 {
 1762         /* 
 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.
 1765          */
 1766         
 1767         /* 
 1768          * Strobe CE# (high->low->high) since status and data are latched on
 1769          * the falling and rising edges of this active-low signal.
 1770          */
 1771 
 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);
 1778 }
 1779 
 1780 static void
 1781 tga2_ics9110_wr(struct gfb_softc *sc, int dotclock)
 1782 {
 1783         bus_space_handle_t clock;
 1784         gfb_reg_t valU;
 1785         int N, M, R, V, X;
 1786         int i;
 1787 
 1788         switch(dotclock) {
 1789         case 130808000:
 1790                 N = 0x40; M = 0x7; V = 0x0; X = 0x1; R = 0x1; break;
 1791         case 119840000:
 1792                 N = 0x2d; M = 0x2b; V = 0x1; X = 0x1; R = 0x1; break;
 1793         case 108180000:
 1794                 N = 0x11; M = 0x9; V = 0x1; X = 0x1; R = 0x2; break;
 1795         case 103994000:
 1796                 N = 0x6d; M = 0xf; V = 0x0; X = 0x1; R = 0x1; break;
 1797         case 175000000:
 1798                 N = 0x5F; M = 0x3E; V = 0x1; X = 0x1; R = 0x1; break;
 1799         case  75000000:
 1800                 N = 0x6e; M = 0x15; V = 0x0; X = 0x1; R = 0x1; break;
 1801         case  74000000:
 1802                 N = 0x2a; M = 0x41; V = 0x1; X = 0x1; R = 0x1; break;
 1803         case  69000000:
 1804                 N = 0x35; M = 0xb; V = 0x0; X = 0x1; R = 0x1; break;
 1805         case  65000000:
 1806                 N = 0x6d; M = 0x0c; V = 0x0; X = 0x1; R = 0x2; break;
 1807         case  50000000:
 1808                 N = 0x37; M = 0x3f; V = 0x1; X = 0x1; R = 0x2; break;
 1809         case  40000000:
 1810                 N = 0x5f; M = 0x11; V = 0x0; X = 0x1; R = 0x2; break;
 1811         case  31500000:
 1812                 N = 0x16; M = 0x05; V = 0x0; X = 0x1; R = 0x2; break;
 1813         case  25175000:
 1814                 N = 0x66; M = 0x1d; V = 0x0; X = 0x1; R = 0x2; break;
 1815         case 135000000:
 1816                 N = 0x42; M = 0x07; V = 0x0; X = 0x1; R = 0x1; break;
 1817         case 110000000:
 1818                 N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
 1819         case 202500000:
 1820                 N = 0x60; M = 0x32; V = 0x1; X = 0x1; R = 0x2; break;
 1821         default:
 1822                 panic("unrecognized clock rate %d\n", dotclock);
 1823         }
 1824 
 1825         /* XXX -- hard coded, bad */
 1826         valU  = N | ( M << 7 ) | (V << 14);
 1827         valU |= (X << 15) | (R << 17);
 1828         valU |= 0x17 << 19;
 1829         clock = sc->bhandle + TGA2_MEM_EXTDEV + TGA2_MEM_CLOCK + (0xe << 12);
 1830         for(i = 24; i > 0; i--) {
 1831                 gfb_reg_t       writeval;
 1832                 
 1833                 writeval = valU & 0x1;
 1834                 if (i == 1)  
 1835                         writeval |= 0x2; 
 1836                 valU >>= 1;
 1837                 bus_space_write_4(sc->btag, clock, 0, writeval);
 1838                 bus_space_barrier(sc->btag, clock, 0, 4,
 1839                     BUS_SPACE_BARRIER_WRITE);
 1840         }       
 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);
 1845 }
 1846 
 1847 /*****************************************************************************
 1848  *
 1849  * BrookTree RAMDAC-specific functions
 1850  *
 1851  ****************************************************************************/
 1852 
 1853 static void
 1854 bt463_init(struct gfb_softc *sc)
 1855 {
 1856         int i;
 1857 
 1858         return;
 1859 
 1860         /*
 1861          * Init the BT463 for normal operation.
 1862          */
 1863 
 1864         /*
 1865          * Setup:
 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.
 1871          */
 1872 
 1873         BTWREG(sc, BT463_IREG_COMMAND_0, 0x40);
 1874         BTWREG(sc, BT463_IREG_COMMAND_1, 0x48);
 1875         BTWREG(sc, BT463_IREG_COMMAND_2, 0xC0);
 1876 
 1877         /*
 1878          * Initialize the read mask.
 1879          */
 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++)
 1885                 BTWNREG(sc, 0xff);
 1886 
 1887         /*
 1888          * Initialize the blink mask.
 1889          */
 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++)
 1895                 BTWNREG(sc, 0);
 1896 
 1897         /*
 1898          * Clear test register
 1899          */
 1900         BTWREG(sc, BT463_IREG_TEST, 0);
 1901 
 1902         /*
 1903          * Initalize the RAMDAC info struct to hold all of our
 1904          * data, and fill it in.
 1905          */
 1906 
 1907         /* Initialize the window type table:
 1908          *
 1909          * Entry 0: 24-plane truecolor, overlays enabled, bypassed.
 1910          *
 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
 1918          *                                                        --------
 1919          *                                                        0x81e100
 1920          */       
 1921 #if 0
 1922         data->window_type[0] = 0x81e100;
 1923 #endif
 1924 
 1925         /* Entry 1: 8-plane pseudocolor in the bottom 8 bits, 
 1926          *          overlays enabled, colormap starting at 0. 
 1927          *
 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
 1935          *                                                        --------
 1936          *                                                        0x01e310
 1937          */       
 1938 #if 0
 1939         data->window_type[1] = 0x01e310;
 1940 #endif
 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.
 1944          */
 1945 
 1946         /* Fill the remaining table entries with clones of entry 0 until we 
 1947          * figure out a better use for them.
 1948          */
 1949 #if 0
 1950         for(i = 2; i < BT463_NWTYPE_ENTRIES; i++) {
 1951                 data->window_type[i] = 0x81e100;
 1952         }
 1953 #endif
 1954 
 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);
 1958 }
 1959 
 1960 static void
 1961 bt463_update_window_type(struct gfb_softc *sc)
 1962 {
 1963         int i;
 1964 
 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
 1969          * ramdac interface.
 1970          */
 1971         /* spit out the window type data */
 1972         for(i = 0; i < BT463_NWTYPE_ENTRIES; i++) {
 1973 #if 0
 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);
 1981 #endif
 1982         }
 1983 }
 1984 
 1985 #if 0
 1986 static int
 1987 bt463_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
 1988 {
 1989         struct gfb_softc *sc;
 1990         int error, i;
 1991 
 1992         error = 0;
 1993         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 1994 
 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);
 1999 
 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);
 2006         }
 2007         return(error);
 2008 }
 2009 
 2010 static int
 2011 bt463_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
 2012 {
 2013         struct gfb_softc *sc;
 2014         int error, i;
 2015 
 2016         error = 0;
 2017         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2018 
 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);
 2023 
 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]);
 2029         }
 2030         return(error);
 2031 }
 2032 
 2033 #endif /* 0 */
 2034 
 2035 static int
 2036 bt463_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 2037 {
 2038         struct gfb_softc *sc;
 2039         int error, i;
 2040 
 2041         error = 0;
 2042         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2043 
 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);
 2048 
 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);
 2054         }
 2055         return(error);
 2056 }
 2057 
 2058 static int
 2059 bt463_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 2060 {
 2061         struct gfb_softc *sc;
 2062         int error, i;
 2063 
 2064         error = 0;
 2065         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2066 
 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);
 2071 
 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]);
 2077         }
 2078         return(error);
 2079 }
 2080 
 2081 static void
 2082 bt485_init(struct gfb_softc *sc)
 2083 {
 2084         int i, j, num_cmap_entries;
 2085         u_int8_t regval;
 2086 
 2087         regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_0);
 2088 
 2089         /*
 2090          * Set the RAMDAC to 8 bit resolution, rather than 6 bit
 2091          * resolution.
 2092          */
 2093         regval |= 0x02;
 2094 
 2095         /*
 2096          * Set the RAMDAC to sync-on-green.
 2097          */
 2098         regval |= 0x08;
 2099         sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_0, regval);
 2100 
 2101 #if 0
 2102         /* Set the RAMDAC to 8BPP (no interesting options). */
 2103         sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_1, 0x40);
 2104 
 2105         /* Disable the cursor (for now) */
 2106         regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_2);
 2107         regval &= ~0x03;
 2108         regval |= 0x24;
 2109         sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
 2110 
 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);
 2114         regval |= 0x04;
 2115         regval |= 0x08;
 2116         sc->gfbc->ramdac_wr(sc, BT485_REG_PCRAM_WRADDR, BT485_IREG_COMMAND_3);
 2117         sc->gfbc->ramdac_wr(sc, BT485_REG_EXTENDED, regval);
 2118 
 2119         /* Set the Pixel Mask to something useful */
 2120         sc->gfbc->ramdac_wr(sc, BT485_REG_PIXMASK, 0xff);
 2121 #endif
 2122 
 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;
 2128         }
 2129 
 2130 #if 0
 2131         /* Enable cursor... */
 2132         regval = sc->gfbc->ramdac_rd(sc, BT485_REG_COMMAND_2);
 2133         if(!(regval & 0x01)) {
 2134                 regval |= 0x01;
 2135                 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
 2136         }
 2137         else if(regval & 0x03) {
 2138                 regval &= ~0x03;
 2139                 sc->gfbc->ramdac_wr(sc, BT485_REG_COMMAND_2, regval);
 2140         }
 2141 #endif
 2142 
 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;
 2153                 }
 2154 }
 2155 
 2156 static int
 2157 bt485_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
 2158 {
 2159         struct gfb_softc *sc;
 2160         int error, i;
 2161 
 2162         error = 0;
 2163         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2164 
 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);
 2168 
 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);
 2174         }
 2175         return(error);
 2176 }
 2177 
 2178 static int
 2179 bt485_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
 2180 {
 2181         struct gfb_softc *sc;
 2182         int error, i;
 2183 
 2184         error = 0;
 2185         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2186 
 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);
 2190 
 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]);
 2196         }
 2197         return(error);
 2198 }
 2199 
 2200 static int
 2201 bt485_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 2202 {
 2203         struct gfb_softc *sc;
 2204         int error, i;
 2205 
 2206         error = 0;
 2207         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2208 
 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);
 2212 
 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);
 2218         }
 2219         return(error);
 2220 }
 2221 
 2222 static int
 2223 bt485_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 2224 {
 2225         struct gfb_softc *sc;
 2226         int error, i;
 2227 
 2228         error = 0;
 2229         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2230 
 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);
 2234 
 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]);
 2240         }
 2241         return(error);
 2242 }
 2243 
 2244 static int
 2245 bt485_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
 2246 {
 2247         struct gfb_softc *sc;
 2248         int error, s;
 2249 
 2250         error = 0;
 2251         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2252         s = spltty();
 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;
 2256         *col -= 8;
 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;
 2260         *row -= 4;
 2261         splx(s);
 2262         return(error);
 2263 }
 2264 
 2265 static int
 2266 bt485_set_hw_cursor(video_adapter_t *adp, int col, int row)
 2267 {
 2268         struct gfb_softc *sc;
 2269         int error, s;
 2270 
 2271         error = 0;
 2272 
 2273         /* Make sure the parameters are in range for the screen
 2274            size... */
 2275         if((row > adp->va_info.vi_height) || (col > adp->va_info.vi_width))
 2276                 error = EINVAL;
 2277         else if(((row * adp->va_info.vi_cheight) > 0x0fff) ||
 2278             ((col * adp->va_info.vi_cwidth) > 0x0fff))
 2279                 error = EINVAL;
 2280         else if((row < 0) || (col < 0)) {
 2281                 /* If either of the parameters is less than 0, then hide the
 2282                    cursor... */
 2283                 col = -8;
 2284                 row = -4;
 2285         } else {
 2286                 /* Otherwise, just move the cursor as requested... */
 2287                 sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2288                 s = spltty();
 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);
 2297                 splx(s);
 2298         }
 2299         return(error);
 2300 }
 2301 
 2302 static int
 2303 bt485_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
 2304     int cellsize, int blink)
 2305 {
 2306         struct gfb_softc *sc;
 2307         int error, cell_count, count, i, j;
 2308         u_int8_t regval;
 2309 
 2310         error = 0;
 2311         cellsize /= 2;
 2312         sc = gfb_device_softcs[adp->va_model][adp->va_unit];
 2313 
 2314         /*
 2315            Make sure the parameters are in range for the cursor
 2316            (it's a 64x64 cursor)...
 2317         */
 2318         if(height > 64)
 2319                 error = EINVAL;
 2320         else if(height <= 0) {
 2321                 /* If height is less than or equal to 0, then hide the
 2322                    cursor... */
 2323         } else {
 2324                 /* Otherwise, just resize the cursor as requested... */
 2325 
 2326                 /* 64 pixels per cursor-row, 2 bits-per-pixel, so counts in
 2327                    bytes... */
 2328                 cell_count = cellsize / 8;
 2329                 count = 64 / 8;
 2330         
 2331                  /* 
 2332                   * Write the cursor image data:
 2333                   *     set addr[9:8] to 0,
 2334                   *     set addr[7:0] to 0,
 2335                   *     spit it all out.
 2336                   */
 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);
 2340                 regval &= ~0x03;
 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);
 2345 
 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,
 2350                                     0xff);
 2351                         for(j = 0; j < count - cell_count; j++)
 2352                                 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
 2353                                     0x00);
 2354                 }
 2355 
 2356                 /* Clear the remaining pixel rows... */
 2357                 for(; i < 64; i++)
 2358                         for(j = 0; j < count; j++)
 2359                                 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
 2360                                     0x00);
 2361 
 2362                 /*
 2363                  * Write the cursor mask data:
 2364                  *      set addr[9:8] to 2,
 2365                  *      set addr[7:0] to 0,
 2366                  *      spit it all out.
 2367                  */
 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);
 2376 
 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,
 2381                                     0xff);
 2382                         for(j = 0; j < count - cell_count; j++)
 2383                                 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
 2384                                     0x00);
 2385                 }
 2386 
 2387                 /* Clear the remaining pixel rows... */
 2388                 for(; i < 64; i++)
 2389                         for(j = 0; j < count; j++)
 2390                                 sc->gfbc->ramdac_wr(sc, BT485_REG_CURSOR_RAM,
 2391                                     0x00);
 2392 
 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);
 2397                 regval &= ~0x03;
 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);
 2401         }
 2402         return(error);
 2403 }
 2404 
 2405 static void
 2406 ibm561_init(struct gfb_softc *sc)
 2407 {
 2408 }
 2409 
 2410 static int
 2411 ibm561_save_palette(video_adapter_t *adp, video_color_palette_t *palette)
 2412 {
 2413         int error;
 2414 
 2415         error = 0;
 2416         return(error);
 2417 }
 2418 
 2419 static int
 2420 ibm561_load_palette(video_adapter_t *adp, video_color_palette_t *palette)
 2421 {
 2422         int error;
 2423 
 2424         error = 0;
 2425         return(error);
 2426 }
 2427 
 2428 static int
 2429 ibm561_save_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 2430 {
 2431         int error;
 2432 
 2433         error = 0;
 2434         return(error);
 2435 }
 2436 
 2437 static int
 2438 ibm561_load_cursor_palette(video_adapter_t *adp, struct fbcmap *palette)
 2439 {
 2440         int error;
 2441 
 2442         error = 0;
 2443         return(error);
 2444 }
 2445 
 2446 #undef MB
 2447 #undef KB

Cache object: 853adde09618c1369b0b3f3fed8452a0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.