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/machfb.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) 2002 Bang Jun-Young
    3  * Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
    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  * 3. The name of the author may not be used to endorse or promote products
   15  *    derived from this software without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27  *
   28  *      from: NetBSD: machfb.c,v 1.23 2005/03/07 21:45:24 martin Exp
   29  */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD: releng/8.1/sys/dev/fb/machfb.c 191076 2009-04-14 20:23:47Z marius $");
   33 
   34 /*
   35  * Driver for ATI Mach64 graphics chips.  Some code is derived from the
   36  * ATI Rage Pro and Derivatives Programmer's Guide.
   37  */
   38 
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/bus.h>
   42 #include <sys/consio.h>
   43 #include <sys/endian.h>
   44 #include <sys/eventhandler.h>
   45 #include <sys/fbio.h>
   46 #include <sys/kernel.h>
   47 #include <sys/module.h>
   48 #include <sys/resource.h>
   49 
   50 #include <vm/vm.h>
   51 #include <vm/pmap.h>
   52 
   53 #include <dev/ofw/ofw_bus.h>
   54 #include <dev/ofw/openfirm.h>
   55 
   56 #include <machine/bus.h>
   57 #include <machine/bus_private.h>
   58 #include <machine/ofw_machdep.h>
   59 #include <machine/pmap.h>
   60 #include <machine/resource.h>
   61 #include <machine/sc_machdep.h>
   62 
   63 #include <sys/rman.h>
   64 
   65 #include <dev/fb/fbreg.h>
   66 #include <dev/fb/gfb.h>
   67 #include <dev/fb/machfbreg.h>
   68 #include <dev/pci/pcivar.h>
   69 #include <dev/pci/pcireg.h>
   70 #include <dev/syscons/syscons.h>
   71 
   72 /* #define MACHFB_DEBUG */
   73 
   74 #define MACHFB_DRIVER_NAME      "machfb"
   75 
   76 #define MACH64_REG_OFF          0x7ffc00
   77 #define MACH64_REG_SIZE         1024
   78 
   79 struct machfb_softc {
   80         video_adapter_t         sc_va;          /* must be first */
   81 
   82         phandle_t               sc_node;
   83         uint16_t                sc_chip_id;
   84         uint8_t                 sc_chip_rev;
   85 
   86         struct resource         *sc_memres;
   87         struct resource         *sc_vmemres;
   88         bus_space_tag_t         sc_memt;
   89         bus_space_tag_t         sc_regt;
   90         bus_space_handle_t      sc_memh;
   91         bus_space_handle_t      sc_regh;
   92         u_long                  sc_mem;
   93         u_long                  sc_vmem;
   94 
   95         u_int                   sc_height;
   96         u_int                   sc_width;
   97         u_int                   sc_depth;
   98         u_int                   sc_xmargin;
   99         u_int                   sc_ymargin;
  100 
  101         size_t                  sc_memsize;
  102         u_int                   sc_memtype;
  103         u_int                   sc_mem_freq;
  104         u_int                   sc_ramdac_freq;
  105         u_int                   sc_ref_freq;
  106 
  107         u_int                   sc_ref_div;
  108         u_int                   sc_mclk_post_div;
  109         u_int                   sc_mclk_fb_div;
  110 
  111         const u_char            *sc_font;
  112         u_int                   sc_cbwidth;
  113         vm_offset_t             sc_curoff;
  114 
  115         int                     sc_bg_cache;
  116         int                     sc_fg_cache;
  117         u_int                   sc_draw_cache;
  118 #define MACHFB_DRAW_CHAR        (1 << 0)
  119 #define MACHFB_DRAW_FILLRECT    (1 << 1)
  120 
  121         u_int                   sc_flags;
  122 #define MACHFB_CONSOLE          (1 << 0)
  123 #define MACHFB_CUREN            (1 << 1)
  124 #define MACHFB_DSP              (1 << 2)
  125 #define MACHFB_SWAP             (1 << 3)
  126 };
  127 
  128 static const struct {
  129         uint16_t        chip_id;
  130         const char      *name;
  131         uint32_t        ramdac_freq;
  132 } const machfb_info[] = {
  133         { ATI_MACH64_CT, "ATI Mach64 CT", 135000 },
  134         { ATI_RAGE_PRO_AGP, "ATI 3D Rage Pro (AGP)", 230000 },
  135         { ATI_RAGE_PRO_AGP1X, "ATI 3D Rage Pro (AGP 1x)", 230000 },
  136         { ATI_RAGE_PRO_PCI_B, "ATI 3D Rage Pro Turbo", 230000 },
  137         { ATI_RAGE_XC_PCI66, "ATI Rage XL (PCI66)", 230000 },
  138         { ATI_RAGE_XL_AGP, "ATI Rage XL (AGP)", 230000 },
  139         { ATI_RAGE_XC_AGP, "ATI Rage XC (AGP)", 230000 },
  140         { ATI_RAGE_XL_PCI66, "ATI Rage XL (PCI66)", 230000 },
  141         { ATI_RAGE_PRO_PCI_P, "ATI 3D Rage Pro", 230000 },
  142         { ATI_RAGE_PRO_PCI_L, "ATI 3D Rage Pro (limited 3D)", 230000 },
  143         { ATI_RAGE_XL_PCI, "ATI Rage XL", 230000 },
  144         { ATI_RAGE_XC_PCI, "ATI Rage XC", 230000 },
  145         { ATI_RAGE_II, "ATI 3D Rage I/II", 135000 },
  146         { ATI_RAGE_IIP, "ATI 3D Rage II+", 200000 },
  147         { ATI_RAGE_IIC_PCI, "ATI 3D Rage IIC", 230000 },
  148         { ATI_RAGE_IIC_AGP_B, "ATI 3D Rage IIC (AGP)", 230000 },
  149         { ATI_RAGE_IIC_AGP_P, "ATI 3D Rage IIC (AGP)", 230000 },
  150         { ATI_RAGE_LT_PRO_AGP, "ATI 3D Rage LT Pro (AGP 133MHz)", 230000 },
  151         { ATI_RAGE_MOB_M3_PCI, "ATI Rage Mobility M3", 230000 },
  152         { ATI_RAGE_MOB_M3_AGP, "ATI Rage Mobility M3 (AGP)", 230000 },
  153         { ATI_RAGE_LT, "ATI 3D Rage LT", 230000 },
  154         { ATI_RAGE_LT_PRO_PCI, "ATI 3D Rage LT Pro", 230000 },
  155         { ATI_RAGE_MOBILITY, "ATI Rage Mobility", 230000 },
  156         { ATI_RAGE_L_MOBILITY, "ATI Rage L Mobility", 230000 },
  157         { ATI_RAGE_LT_PRO, "ATI 3D Rage LT Pro", 230000 },
  158         { ATI_RAGE_LT_PRO2, "ATI 3D Rage LT Pro", 230000 },
  159         { ATI_RAGE_MOB_M1_PCI, "ATI Rage Mobility M1 (PCI)", 230000 },
  160         { ATI_RAGE_L_MOB_M1_PCI, "ATI Rage L Mobility (PCI)", 230000 },
  161         { ATI_MACH64_VT, "ATI Mach64 VT", 170000 },
  162         { ATI_MACH64_VTB, "ATI Mach64 VTB", 200000 },
  163         { ATI_MACH64_VT4, "ATI Mach64 VT4", 230000 }
  164 };
  165 
  166 static const struct machfb_cmap {
  167         uint8_t red;
  168         uint8_t green;
  169         uint8_t blue;
  170 } const machfb_default_cmap[16] = {
  171         {0x00, 0x00, 0x00},     /* black */
  172         {0x00, 0x00, 0xff},     /* blue */
  173         {0x00, 0xff, 0x00},     /* green */
  174         {0x00, 0xc0, 0xc0},     /* cyan */
  175         {0xff, 0x00, 0x00},     /* red */
  176         {0xc0, 0x00, 0xc0},     /* magenta */
  177         {0xc0, 0xc0, 0x00},     /* brown */
  178         {0xc0, 0xc0, 0xc0},     /* light grey */
  179         {0x80, 0x80, 0x80},     /* dark grey */
  180         {0x80, 0x80, 0xff},     /* light blue */
  181         {0x80, 0xff, 0x80},     /* light green */
  182         {0x80, 0xff, 0xff},     /* light cyan */
  183         {0xff, 0x80, 0x80},     /* light red */
  184         {0xff, 0x80, 0xff},     /* light magenta */
  185         {0xff, 0xff, 0x80},     /* yellow */
  186         {0xff, 0xff, 0xff}      /* white */
  187 };
  188 
  189 #define MACHFB_CMAP_OFF         16
  190 
  191 static const u_char const machfb_mouse_pointer_bits[64][8] = {
  192         { 0x00, 0x00, },        /* ............ */
  193         { 0x80, 0x00, },        /* *........... */
  194         { 0xc0, 0x00, },        /* **.......... */
  195         { 0xe0, 0x00, },        /* ***......... */
  196         { 0xf0, 0x00, },        /* ****........ */
  197         { 0xf8, 0x00, },        /* *****....... */
  198         { 0xfc, 0x00, },        /* ******...... */
  199         { 0xfe, 0x00, },        /* *******..... */
  200         { 0xff, 0x00, },        /* ********.... */
  201         { 0xff, 0x80, },        /* *********... */
  202         { 0xfc, 0xc0, },        /* ******..**.. */
  203         { 0xdc, 0x00, },        /* **.***...... */
  204         { 0x8e, 0x00, },        /* *...***..... */
  205         { 0x0e, 0x00, },        /* ....***..... */
  206         { 0x07, 0x00, },        /* .....***.... */
  207         { 0x04, 0x00, },        /* .....*...... */
  208         { 0x00, 0x00, },        /* ............ */
  209         { 0x00, 0x00, },        /* ............ */
  210         { 0x00, 0x00, },        /* ............ */
  211         { 0x00, 0x00, },        /* ............ */
  212         { 0x00, 0x00, },        /* ............ */
  213         { 0x00, 0x00, },        /* ............ */
  214 };
  215 
  216 /*
  217  * Lookup table to perform a bit-swap of the mouse pointer bits,
  218  * map set bits to CUR_CLR0 and unset bits to transparent.
  219  */
  220 static const u_char const machfb_mouse_pointer_lut[] = {
  221         0xaa, 0x2a, 0x8a, 0x0a, 0xa2, 0x22, 0x82, 0x02,
  222         0xa8, 0x28, 0x88, 0x08, 0xa0, 0x20, 0x80, 0x00
  223 };
  224 
  225 static const char *const machfb_memtype_names[] = {
  226         "(N/A)", "DRAM", "EDO DRAM", "EDO DRAM", "SDRAM", "SGRAM", "WRAM",
  227         "(unknown type)"
  228 };
  229 
  230 extern const struct gfb_font gallant12x22;
  231 
  232 static struct machfb_softc machfb_softc;
  233 static struct bus_space_tag machfb_bst_store[1];
  234 
  235 static device_probe_t machfb_pci_probe;
  236 static device_attach_t machfb_pci_attach;
  237 static device_detach_t machfb_pci_detach;
  238 
  239 static device_method_t machfb_methods[] = {
  240         /* Device interface */
  241         DEVMETHOD(device_probe,         machfb_pci_probe),
  242         DEVMETHOD(device_attach,        machfb_pci_attach),
  243         DEVMETHOD(device_detach,        machfb_pci_detach),
  244 
  245         { 0, 0 }
  246 };
  247 
  248 static driver_t machfb_pci_driver = {
  249         MACHFB_DRIVER_NAME,
  250         machfb_methods,
  251         sizeof(struct machfb_softc),
  252 };
  253 
  254 static devclass_t machfb_devclass;
  255 
  256 DRIVER_MODULE(machfb, pci, machfb_pci_driver, machfb_devclass, 0, 0);
  257 MODULE_DEPEND(machfb, pci, 1, 1, 1);
  258 
  259 static void machfb_cursor_enable(struct machfb_softc *, int);
  260 static int machfb_cursor_install(struct machfb_softc *);
  261 static int machfb_get_memsize(struct machfb_softc *);
  262 static void machfb_reset_engine(struct machfb_softc *);
  263 static void machfb_init_engine(struct machfb_softc *);
  264 #if 0
  265 static void machfb_adjust_frame(struct machfb_softc *, int, int);
  266 #endif
  267 static void machfb_shutdown_final(void *);
  268 static void machfb_shutdown_reset(void *);
  269 
  270 static int machfb_configure(int);
  271 
  272 static vi_probe_t machfb_probe;
  273 static vi_init_t machfb_init;
  274 static vi_get_info_t machfb_get_info;
  275 static vi_query_mode_t machfb_query_mode;
  276 static vi_set_mode_t machfb_set_mode;
  277 static vi_save_font_t machfb_save_font;
  278 static vi_load_font_t machfb_load_font;
  279 static vi_show_font_t machfb_show_font;
  280 static vi_save_palette_t machfb_save_palette;
  281 static vi_load_palette_t machfb_load_palette;
  282 static vi_set_border_t machfb_set_border;
  283 static vi_save_state_t machfb_save_state;
  284 static vi_load_state_t machfb_load_state;
  285 static vi_set_win_org_t machfb_set_win_org;
  286 static vi_read_hw_cursor_t machfb_read_hw_cursor;
  287 static vi_set_hw_cursor_t machfb_set_hw_cursor;
  288 static vi_set_hw_cursor_shape_t machfb_set_hw_cursor_shape;
  289 static vi_blank_display_t machfb_blank_display;
  290 static vi_mmap_t machfb_mmap;
  291 static vi_ioctl_t machfb_ioctl;
  292 static vi_clear_t machfb_clear;
  293 static vi_fill_rect_t machfb_fill_rect;
  294 static vi_bitblt_t machfb_bitblt;
  295 static vi_diag_t machfb_diag;
  296 static vi_save_cursor_palette_t machfb_save_cursor_palette;
  297 static vi_load_cursor_palette_t machfb_load_cursor_palette;
  298 static vi_copy_t machfb_copy;
  299 static vi_putp_t machfb_putp;
  300 static vi_putc_t machfb_putc;
  301 static vi_puts_t machfb_puts;
  302 static vi_putm_t machfb_putm;
  303 
  304 static video_switch_t machfbvidsw = {
  305         .probe                  = machfb_probe,
  306         .init                   = machfb_init,
  307         .get_info               = machfb_get_info,
  308         .query_mode             = machfb_query_mode,
  309         .set_mode               = machfb_set_mode,
  310         .save_font              = machfb_save_font,
  311         .load_font              = machfb_load_font,
  312         .show_font              = machfb_show_font,
  313         .save_palette           = machfb_save_palette,
  314         .load_palette           = machfb_load_palette,
  315         .set_border             = machfb_set_border,
  316         .save_state             = machfb_save_state,
  317         .load_state             = machfb_load_state,
  318         .set_win_org            = machfb_set_win_org,
  319         .read_hw_cursor         = machfb_read_hw_cursor,
  320         .set_hw_cursor          = machfb_set_hw_cursor,
  321         .set_hw_cursor_shape    = machfb_set_hw_cursor_shape,
  322         .blank_display          = machfb_blank_display,
  323         .mmap                   = machfb_mmap,
  324         .ioctl                  = machfb_ioctl,
  325         .clear                  = machfb_clear,
  326         .fill_rect              = machfb_fill_rect,
  327         .bitblt                 = machfb_bitblt,
  328         .diag                   = machfb_diag,
  329         .save_cursor_palette    = machfb_save_cursor_palette,
  330         .load_cursor_palette    = machfb_load_cursor_palette,
  331         .copy                   = machfb_copy,
  332         .putp                   = machfb_putp,
  333         .putc                   = machfb_putc,
  334         .puts                   = machfb_puts,
  335         .putm                   = machfb_putm
  336 };
  337 
  338 VIDEO_DRIVER(machfb, machfbvidsw, machfb_configure);
  339 
  340 extern sc_rndr_sw_t txtrndrsw;
  341 RENDERER(machfb, 0, txtrndrsw, gfb_set);
  342 
  343 RENDERER_MODULE(machfb, gfb_set);
  344 
  345 /*
  346  * Inline functions for getting access to register aperture.
  347  */
  348 static inline uint32_t regr(struct machfb_softc *, uint32_t);
  349 static inline uint8_t regrb(struct machfb_softc *, uint32_t);
  350 static inline void regw(struct machfb_softc *, uint32_t, uint32_t);
  351 static inline void regwb(struct machfb_softc *, uint32_t, uint8_t);
  352 static inline void regwb_pll(struct machfb_softc *, uint32_t, uint8_t);
  353 
  354 static inline uint32_t
  355 regr(struct machfb_softc *sc, uint32_t index)
  356 {
  357 
  358         return bus_space_read_4(sc->sc_regt, sc->sc_regh, index);
  359 }
  360 
  361 static inline uint8_t
  362 regrb(struct machfb_softc *sc, uint32_t index)
  363 {
  364 
  365         return bus_space_read_1(sc->sc_regt, sc->sc_regh, index);
  366 }
  367 
  368 static inline void
  369 regw(struct machfb_softc *sc, uint32_t index, uint32_t data)
  370 {
  371 
  372         bus_space_write_4(sc->sc_regt, sc->sc_regh, index, data);
  373         bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 4,
  374             BUS_SPACE_BARRIER_WRITE);
  375 }
  376 
  377 static inline void
  378 regwb(struct machfb_softc *sc, uint32_t index, uint8_t data)
  379 {
  380 
  381         bus_space_write_1(sc->sc_regt, sc->sc_regh, index, data);
  382         bus_space_barrier(sc->sc_regt, sc->sc_regh, index, 1,
  383             BUS_SPACE_BARRIER_WRITE);
  384 }
  385 
  386 static inline void
  387 regwb_pll(struct machfb_softc *sc, uint32_t index, uint8_t data)
  388 {
  389 
  390         regwb(sc, CLOCK_CNTL + 1, (index << 2) | PLL_WR_EN);
  391         regwb(sc, CLOCK_CNTL + 2, data);
  392         regwb(sc, CLOCK_CNTL + 1, (index << 2) & ~PLL_WR_EN);
  393 }
  394 
  395 static inline void
  396 wait_for_fifo(struct machfb_softc *sc, uint8_t v)
  397 {
  398 
  399         while ((regr(sc, FIFO_STAT) & 0xffff) > (0x8000 >> v))
  400                 ;
  401 }
  402 
  403 static inline void
  404 wait_for_idle(struct machfb_softc *sc)
  405 {
  406 
  407         wait_for_fifo(sc, 16);
  408         while ((regr(sc, GUI_STAT) & 1) != 0)
  409                 ;
  410 }
  411 
  412 /*
  413  * Inline functions for setting the background and foreground colors.
  414  */
  415 static inline void machfb_setbg(struct machfb_softc *sc, int bg);
  416 static inline void machfb_setfg(struct machfb_softc *sc, int fg);
  417 
  418 static inline void
  419 machfb_setbg(struct machfb_softc *sc, int bg)
  420 {
  421 
  422         if (bg == sc->sc_bg_cache)
  423                 return;
  424         sc->sc_bg_cache = bg;
  425         wait_for_fifo(sc, 1);
  426         regw(sc, DP_BKGD_CLR, bg + MACHFB_CMAP_OFF);
  427 }
  428 
  429 static inline void
  430 machfb_setfg(struct machfb_softc *sc, int fg)
  431 {
  432 
  433         if (fg == sc->sc_fg_cache)
  434                 return;
  435         sc->sc_fg_cache = fg;
  436         wait_for_fifo(sc, 1);
  437         regw(sc, DP_FRGD_CLR, fg + MACHFB_CMAP_OFF);
  438 }
  439 
  440 /*
  441  * video driver interface
  442  */
  443 static int
  444 machfb_configure(int flags)
  445 {
  446         struct machfb_softc *sc;
  447         phandle_t chosen, output;
  448         ihandle_t stdout;
  449         bus_addr_t addr;
  450         uint32_t id;
  451         int i, space;
  452 
  453         /*
  454          * For the high-level console probing return the number of
  455          * registered adapters.
  456          */
  457         if (!(flags & VIO_PROBE_ONLY)) {
  458                 for (i = 0; vid_find_adapter(MACHFB_DRIVER_NAME, i) >= 0; i++)
  459                         ;
  460                 return (i);
  461         }
  462 
  463         /* Low-level console probing and initialization. */
  464 
  465         sc = &machfb_softc;
  466         if (sc->sc_va.va_flags & V_ADP_REGISTERED)
  467                 goto found;
  468 
  469         if ((chosen = OF_finddevice("/chosen")) == -1)  /* Quis contra nos? */
  470                 return (0);
  471         if (OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)) == -1)
  472                 return (0);
  473         if ((output = OF_instance_to_package(stdout)) == -1)
  474                 return (0);
  475         if ((OF_getprop(output, "vendor-id", &id, sizeof(id)) == -1) ||
  476             id != ATI_VENDOR)
  477                 return (0);
  478         if (OF_getprop(output, "device-id", &id, sizeof(id)) == -1)
  479                 return (0);
  480         for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) {
  481                 if (id == machfb_info[i].chip_id) {
  482                         sc->sc_flags = MACHFB_CONSOLE;
  483                         sc->sc_node = output;
  484                         sc->sc_chip_id = id;
  485                         break;
  486                 }
  487         }
  488         if (!(sc->sc_flags & MACHFB_CONSOLE))
  489                 return (0);
  490 
  491         if (OF_getprop(output, "revision-id", &sc->sc_chip_rev,
  492             sizeof(sc->sc_chip_rev)) == -1)
  493                 return (0);
  494         if (OF_decode_addr(output, 0, &space, &addr) != 0)
  495                 return (0);
  496         sc->sc_memt = &machfb_bst_store[0];
  497         sc->sc_memh = sparc64_fake_bustag(space, addr, sc->sc_memt);
  498         sc->sc_regt = sc->sc_memt;
  499         bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF,
  500             MACH64_REG_SIZE, &sc->sc_regh);
  501 
  502         if (machfb_init(0, &sc->sc_va, 0) < 0)
  503                  return (0);
  504 
  505  found:
  506         /* Return number of found adapters. */
  507         return (1);
  508 }
  509 
  510 static int
  511 machfb_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
  512 {
  513 
  514         return (0);
  515 }
  516 
  517 static int
  518 machfb_init(int unit, video_adapter_t *adp, int flags)
  519 {
  520         struct machfb_softc *sc;
  521         phandle_t options;
  522         video_info_t *vi;
  523         char buf[32];
  524         int i;
  525         uint8_t dac_mask, dac_rindex, dac_windex;
  526 
  527         sc = (struct machfb_softc *)adp;
  528         vi = &adp->va_info;
  529 
  530         if ((regr(sc, CONFIG_CHIP_ID) & 0xffff) != sc->sc_chip_id)
  531                 return (ENXIO);
  532 
  533         sc->sc_ramdac_freq = 0;
  534         for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) {
  535                 if (sc->sc_chip_id == machfb_info[i].chip_id) {
  536                         sc->sc_ramdac_freq = machfb_info[i].ramdac_freq;
  537                         break;
  538                 }
  539         }
  540         if (sc->sc_ramdac_freq == 0)
  541                 return (ENXIO);
  542         if (sc->sc_chip_id == ATI_RAGE_II && sc->sc_chip_rev & 0x07)
  543                 sc->sc_ramdac_freq = 170000;
  544 
  545         vid_init_struct(adp, MACHFB_DRIVER_NAME, -1, unit);
  546 
  547         if (OF_getprop(sc->sc_node, "height", &sc->sc_height,
  548             sizeof(sc->sc_height)) == -1)
  549                 return (ENXIO);
  550         if (OF_getprop(sc->sc_node, "width", &sc->sc_width,
  551             sizeof(sc->sc_width)) == -1)
  552                 return (ENXIO);
  553         if (OF_getprop(sc->sc_node, "depth", &sc->sc_depth,
  554             sizeof(sc->sc_depth)) == -1)
  555                 return (ENXIO);
  556         if ((options = OF_finddevice("/options")) == -1)
  557                 return (ENXIO);
  558         if (OF_getprop(options, "screen-#rows", buf, sizeof(buf)) == -1)
  559                 return (ENXIO);
  560         vi->vi_height = strtol(buf, NULL, 10);
  561         if (OF_getprop(options, "screen-#columns", buf, sizeof(buf)) == -1)
  562                 return (ENXIO);
  563         vi->vi_width = strtol(buf, NULL, 10);
  564         vi->vi_cwidth = gallant12x22.width;
  565         vi->vi_cheight = gallant12x22.height;
  566         vi->vi_flags = V_INFO_COLOR;
  567         vi->vi_mem_model = V_INFO_MM_OTHER;
  568 
  569         sc->sc_font = gallant12x22.data;
  570         sc->sc_cbwidth = howmany(vi->vi_cwidth, NBBY);  /* width in bytes */
  571         sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
  572         sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight)) / 2;
  573 
  574         if (sc->sc_chip_id != ATI_MACH64_CT &&
  575             !((sc->sc_chip_id == ATI_MACH64_VT ||
  576             sc->sc_chip_id == ATI_RAGE_II) &&
  577             (sc->sc_chip_rev & 0x07) == 0))
  578                 sc->sc_flags |= MACHFB_DSP;
  579 
  580         sc->sc_memsize = machfb_get_memsize(sc);
  581         if (sc->sc_memsize == 8192)
  582                 /* The last page is used as register aperture. */
  583                 sc->sc_memsize -= 4;
  584         sc->sc_memtype = regr(sc, CONFIG_STAT0) & 0x07;
  585 
  586         if ((sc->sc_chip_id >= ATI_RAGE_XC_PCI66 &&
  587             sc->sc_chip_id <= ATI_RAGE_XL_PCI66) ||
  588             (sc->sc_chip_id >= ATI_RAGE_XL_PCI &&
  589             sc->sc_chip_id <= ATI_RAGE_XC_PCI))
  590                 sc->sc_ref_freq = 29498;
  591         else
  592                 sc->sc_ref_freq = 14318;
  593 
  594         regwb(sc, CLOCK_CNTL + 1, PLL_REF_DIV << 2);
  595         sc->sc_ref_div = regrb(sc, CLOCK_CNTL + 2);
  596         regwb(sc, CLOCK_CNTL + 1, MCLK_FB_DIV << 2);
  597         sc->sc_mclk_fb_div = regrb(sc, CLOCK_CNTL + 2);
  598         sc->sc_mem_freq = (2 * sc->sc_ref_freq * sc->sc_mclk_fb_div) /
  599             (sc->sc_ref_div * 2);
  600         sc->sc_mclk_post_div = (sc->sc_mclk_fb_div * 2 * sc->sc_ref_freq) /
  601             (sc->sc_mem_freq * sc->sc_ref_div);
  602 
  603         machfb_init_engine(sc);
  604 #if 0
  605         machfb_adjust_frame(0, 0);
  606 #endif
  607         machfb_set_mode(adp, 0);
  608 
  609         /*
  610          * Install our 16-color color map.  This is done only once and with
  611          * an offset of 16 on sparc64 as there the OBP driver expects white
  612          * to be at index 0 and black at 255 (some versions also use 1 - 8
  613          * for color text support or the full palette for the boot banner
  614          * logo but no versions seems to use the ISO 6429-1983 color map).
  615          * Otherwise the colors are inverted when back in the OFW.
  616          */
  617         dac_rindex = regrb(sc, DAC_RINDEX);
  618         dac_windex = regrb(sc, DAC_WINDEX);
  619         dac_mask = regrb(sc, DAC_MASK);
  620         regwb(sc, DAC_MASK, 0xff);
  621         regwb(sc, DAC_WINDEX, MACHFB_CMAP_OFF);
  622         for (i = 0; i < 16; i++) {
  623                 regwb(sc, DAC_DATA, machfb_default_cmap[i].red);
  624                 regwb(sc, DAC_DATA, machfb_default_cmap[i].green);
  625                 regwb(sc, DAC_DATA, machfb_default_cmap[i].blue);
  626         }
  627         regwb(sc, DAC_MASK, dac_mask);
  628         regwb(sc, DAC_RINDEX, dac_rindex);
  629         regwb(sc, DAC_WINDEX, dac_windex);
  630 
  631         machfb_blank_display(adp, V_DISPLAY_ON);
  632         machfb_clear(adp);
  633 
  634         /*
  635          * Setting V_ADP_MODECHANGE serves as hack so machfb_set_mode()
  636          * (which will invalidate our caches) is called as a precaution
  637          * when the X server shuts down.
  638          */
  639         adp->va_flags |= V_ADP_COLOR | V_ADP_MODECHANGE | V_ADP_PALETTE |
  640             V_ADP_BORDER | V_ADP_INITIALIZED;
  641         if (vid_register(adp) < 0)
  642                 return (ENXIO);
  643         adp->va_flags |= V_ADP_REGISTERED;
  644 
  645         return (0);
  646 }
  647 
  648 static int
  649 machfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
  650 {
  651 
  652         bcopy(&adp->va_info, info, sizeof(*info));
  653 
  654         return (0);
  655 }
  656 
  657 static int
  658 machfb_query_mode(video_adapter_t *adp, video_info_t *info)
  659 {
  660 
  661         return (ENODEV);
  662 }
  663 
  664 static int
  665 machfb_set_mode(video_adapter_t *adp, int mode)
  666 {
  667         struct machfb_softc *sc;
  668 
  669         sc = (struct machfb_softc *)adp;
  670 
  671         sc->sc_bg_cache = -1;
  672         sc->sc_fg_cache = -1;
  673         sc->sc_draw_cache = 0;
  674 
  675         return (0);
  676 }
  677 
  678 static int
  679 machfb_save_font(video_adapter_t *adp, int page, int size, int width,
  680     u_char *data, int c, int count)
  681 {
  682 
  683         return (ENODEV);
  684 }
  685 
  686 static int
  687 machfb_load_font(video_adapter_t *adp, int page, int size, int width,
  688     u_char *data, int c, int count)
  689 {
  690 
  691         return (ENODEV);
  692 }
  693 
  694 static int
  695 machfb_show_font(video_adapter_t *adp, int page)
  696 {
  697 
  698         return (ENODEV);
  699 }
  700 
  701 static int
  702 machfb_save_palette(video_adapter_t *adp, u_char *palette)
  703 {
  704         struct machfb_softc *sc;
  705         int i;
  706         uint8_t dac_mask, dac_rindex, dac_windex;
  707 
  708         sc = (struct machfb_softc *)adp;
  709 
  710         dac_rindex = regrb(sc, DAC_RINDEX);
  711         dac_windex = regrb(sc, DAC_WINDEX);
  712         dac_mask = regrb(sc, DAC_MASK);
  713         regwb(sc, DAC_MASK, 0xff);
  714         regwb(sc, DAC_RINDEX, 0x0);
  715         for (i = 0; i < 256 * 3; i++)
  716                 palette[i] = regrb(sc, DAC_DATA);
  717         regwb(sc, DAC_MASK, dac_mask);
  718         regwb(sc, DAC_RINDEX, dac_rindex);
  719         regwb(sc, DAC_WINDEX, dac_windex);
  720 
  721         return (0);
  722 }
  723 
  724 static int
  725 machfb_load_palette(video_adapter_t *adp, u_char *palette)
  726 {
  727         struct machfb_softc *sc;
  728         int i;
  729         uint8_t dac_mask, dac_rindex, dac_windex;
  730 
  731         sc = (struct machfb_softc *)adp;
  732 
  733         dac_rindex = regrb(sc, DAC_RINDEX);
  734         dac_windex = regrb(sc, DAC_WINDEX);
  735         dac_mask = regrb(sc, DAC_MASK);
  736         regwb(sc, DAC_MASK, 0xff);
  737         regwb(sc, DAC_WINDEX, 0x0);
  738         for (i = 0; i < 256 * 3; i++)
  739                 regwb(sc, DAC_DATA, palette[i]);
  740         regwb(sc, DAC_MASK, dac_mask);
  741         regwb(sc, DAC_RINDEX, dac_rindex);
  742         regwb(sc, DAC_WINDEX, dac_windex);
  743 
  744         return (0);
  745 }
  746 
  747 static int
  748 machfb_set_border(video_adapter_t *adp, int border)
  749 {
  750         struct machfb_softc *sc;
  751 
  752         sc = (struct machfb_softc *)adp;
  753 
  754         machfb_fill_rect(adp, border, 0, 0, sc->sc_width, sc->sc_ymargin);
  755         machfb_fill_rect(adp, border, 0, sc->sc_height - sc->sc_ymargin,
  756             sc->sc_width, sc->sc_ymargin);
  757         machfb_fill_rect(adp, border, 0, 0, sc->sc_xmargin, sc->sc_height);
  758         machfb_fill_rect(adp, border, sc->sc_width - sc->sc_xmargin, 0,
  759             sc->sc_xmargin, sc->sc_height);
  760 
  761         return (0);
  762 }
  763 
  764 static int
  765 machfb_save_state(video_adapter_t *adp, void *p, size_t size)
  766 {
  767 
  768         return (ENODEV);
  769 }
  770 
  771 static int
  772 machfb_load_state(video_adapter_t *adp, void *p)
  773 {
  774 
  775         return (ENODEV);
  776 }
  777 
  778 static int
  779 machfb_set_win_org(video_adapter_t *adp, off_t offset)
  780 {
  781 
  782         return (ENODEV);
  783 }
  784 
  785 static int
  786 machfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
  787 {
  788 
  789         *col = 0;
  790         *row = 0;
  791 
  792         return (0);
  793 }
  794 
  795 static int
  796 machfb_set_hw_cursor(video_adapter_t *adp, int col, int row)
  797 {
  798 
  799         return (ENODEV);
  800 }
  801 
  802 static int
  803 machfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
  804     int celsize, int blink)
  805 {
  806 
  807         return (ENODEV);
  808 }
  809 
  810 static int
  811 machfb_blank_display(video_adapter_t *adp, int mode)
  812 {
  813         struct machfb_softc *sc;
  814         uint32_t crtc_gen_cntl;
  815 
  816         sc = (struct machfb_softc *)adp;
  817 
  818         crtc_gen_cntl = (regr(sc, CRTC_GEN_CNTL) | CRTC_EXT_DISP_EN | CRTC_EN) &
  819             ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS);
  820         switch (mode) {
  821         case V_DISPLAY_ON:
  822                 break;
  823         case V_DISPLAY_BLANK:
  824                 crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_VSYNC_DIS |
  825                     CRTC_DISPLAY_DIS;
  826                 break;
  827         case V_DISPLAY_STAND_BY:
  828                 crtc_gen_cntl |= CRTC_HSYNC_DIS | CRTC_DISPLAY_DIS;
  829                 break;
  830         case V_DISPLAY_SUSPEND:
  831                 crtc_gen_cntl |= CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS;
  832                 break;
  833         }
  834         regw(sc, CRTC_GEN_CNTL, crtc_gen_cntl);
  835 
  836         return (0);
  837 }
  838 
  839 static int
  840 machfb_mmap(video_adapter_t *adp, vm_offset_t offset, vm_paddr_t *paddr,
  841     int prot)
  842 {
  843         struct machfb_softc *sc;
  844         video_info_t *vi;
  845 
  846         sc = (struct machfb_softc *)adp;
  847         vi = &adp->va_info;
  848 
  849         /* BAR 2 - VGA memory */
  850         if (sc->sc_vmem != 0 && offset >= sc->sc_vmem &&
  851             offset < sc->sc_vmem + vi->vi_registers_size) {
  852                 *paddr = vi->vi_registers + offset - sc->sc_vmem;
  853                 return (0);
  854         }
  855 
  856         /* BAR 0 - framebuffer */
  857         if (offset >= sc->sc_mem &&
  858             offset < sc->sc_mem + vi->vi_buffer_size) {
  859                 *paddr = vi->vi_buffer + offset - sc->sc_mem;
  860                 return (0);
  861         }
  862 
  863         /* 'regular' framebuffer mmap()ing */
  864         if (offset < adp->va_window_size) {
  865                 *paddr = vi->vi_window + offset;
  866                 return (0);
  867         }
  868 
  869         return (EINVAL);
  870 }
  871 
  872 static int
  873 machfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
  874 {
  875         struct machfb_softc *sc;
  876         struct fbcursor *fbc;
  877         struct fbtype *fb;
  878 
  879         sc = (struct machfb_softc *)adp;
  880 
  881         switch (cmd) {
  882         case FBIOGTYPE:
  883                 fb = (struct fbtype *)data;
  884                 fb->fb_type = FBTYPE_PCIMISC;
  885                 fb->fb_height = sc->sc_height;
  886                 fb->fb_width = sc->sc_width;
  887                 fb->fb_depth = sc->sc_depth;
  888                 if (sc->sc_depth <= 1 || sc->sc_depth > 8)
  889                         fb->fb_cmsize = 0;
  890                 else
  891                         fb->fb_cmsize = 1 << sc->sc_depth;
  892                 fb->fb_size = adp->va_buffer_size;
  893                 break;
  894         case FBIOSCURSOR:
  895                 fbc = (struct fbcursor *)data;
  896                 if (fbc->set & FB_CUR_SETCUR && fbc->enable == 0) {
  897                         machfb_cursor_enable(sc, 0);
  898                         sc->sc_flags &= ~MACHFB_CUREN;
  899                 } else
  900                         return (ENODEV);
  901                 break;
  902         default:
  903                 return (fb_commonioctl(adp, cmd, data));
  904         }
  905 
  906         return (0);
  907 }
  908 
  909 static int
  910 machfb_clear(video_adapter_t *adp)
  911 {
  912         struct machfb_softc *sc;
  913 
  914         sc = (struct machfb_softc *)adp;
  915 
  916         machfb_fill_rect(adp, (SC_NORM_ATTR >> 4) & 0xf, 0, 0, sc->sc_width,
  917             sc->sc_height);
  918 
  919         return (0);
  920 }
  921 
  922 static int
  923 machfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
  924 {
  925         struct machfb_softc *sc;
  926 
  927         sc = (struct machfb_softc *)adp;
  928 
  929         if (sc->sc_draw_cache != MACHFB_DRAW_FILLRECT) {
  930                 wait_for_fifo(sc, 7);
  931                 regw(sc, DP_WRITE_MASK, 0xff);
  932                 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_8BPP | HOST_8BPP);
  933                 regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR);
  934                 regw(sc, DP_MIX, MIX_SRC << 16);
  935                 regw(sc, CLR_CMP_CNTL, 0);      /* no transparency */
  936                 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
  937                 regw(sc, DST_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
  938                 sc->sc_draw_cache = MACHFB_DRAW_FILLRECT;
  939         }
  940         machfb_setfg(sc, val);
  941         wait_for_fifo(sc, 4);
  942         regw(sc, SRC_Y_X, (x << 16) | y);
  943         regw(sc, SRC_WIDTH1, cx);
  944         regw(sc, DST_Y_X, (x << 16) | y);
  945         regw(sc, DST_HEIGHT_WIDTH, (cx << 16) | cy);
  946 
  947         return (0);
  948 }
  949 
  950 static int
  951 machfb_bitblt(video_adapter_t *adp, ...)
  952 {
  953 
  954         return (ENODEV);
  955 }
  956 
  957 static int
  958 machfb_diag(video_adapter_t *adp, int level)
  959 {
  960         video_info_t info;
  961 
  962         fb_dump_adp_info(adp->va_name, adp, level);
  963         machfb_get_info(adp, 0, &info);
  964         fb_dump_mode_info(adp->va_name, adp, &info, level);
  965 
  966         return (0);
  967 }
  968 
  969 static int
  970 machfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
  971 {
  972 
  973         return (ENODEV);
  974 }
  975 
  976 static int
  977 machfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
  978 {
  979 
  980         return (ENODEV);
  981 }
  982 
  983 static int
  984 machfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
  985 {
  986 
  987         return (ENODEV);
  988 }
  989 
  990 static int
  991 machfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
  992     int size, int bpp, int bit_ltor, int byte_ltor)
  993 {
  994 
  995         return (ENODEV);
  996 }
  997 
  998 static int
  999 machfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
 1000 {
 1001         struct machfb_softc *sc;
 1002         const uint8_t *p;
 1003         int i;
 1004 
 1005         sc = (struct machfb_softc *)adp;
 1006 
 1007         if (sc->sc_draw_cache != MACHFB_DRAW_CHAR) {
 1008                 wait_for_fifo(sc, 8);
 1009                 regw(sc, DP_WRITE_MASK, 0xff);  /* XXX only good for 8 bit */
 1010                 regw(sc, DP_PIX_WIDTH, DST_8BPP | SRC_1BPP | HOST_1BPP);
 1011                 regw(sc, DP_SRC, MONO_SRC_HOST | BKGD_SRC_BKGD_CLR |
 1012                     FRGD_SRC_FRGD_CLR);
 1013                 regw(sc, DP_MIX ,((MIX_SRC & 0xffff) << 16) | MIX_SRC);
 1014                 regw(sc, CLR_CMP_CNTL, 0);      /* no transparency */
 1015                 regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
 1016                 regw(sc, DST_CNTL, DST_Y_TOP_TO_BOTTOM | DST_X_LEFT_TO_RIGHT);
 1017                 regw(sc, HOST_CNTL, HOST_BYTE_ALIGN);
 1018                 sc->sc_draw_cache = MACHFB_DRAW_CHAR;
 1019         }
 1020         machfb_setbg(sc, (a >> 4) & 0xf);
 1021         machfb_setfg(sc, a & 0xf);
 1022         wait_for_fifo(sc, 4 + (adp->va_info.vi_cheight / sc->sc_cbwidth));
 1023         regw(sc, SRC_Y_X, 0);
 1024         regw(sc, SRC_WIDTH1, adp->va_info.vi_cwidth);
 1025         regw(sc, DST_Y_X, ((((off % adp->va_info.vi_width) *
 1026             adp->va_info.vi_cwidth) + sc->sc_xmargin) << 16) |
 1027             (((off / adp->va_info.vi_width) * adp->va_info.vi_cheight) +
 1028             sc->sc_ymargin));
 1029         regw(sc, DST_HEIGHT_WIDTH, (adp->va_info.vi_cwidth << 16) |
 1030             adp->va_info.vi_cheight);
 1031         p = sc->sc_font + (c * adp->va_info.vi_cheight * sc->sc_cbwidth);
 1032         for (i = 0; i < adp->va_info.vi_cheight * sc->sc_cbwidth; i += 4)
 1033                 regw(sc, HOST_DATA0 + i, (p[i + 3] << 24 | p[i + 2] << 16 |
 1034                     p[i + 1] << 8 | p[i]));
 1035 
 1036         return (0);
 1037 }
 1038 
 1039 static int
 1040 machfb_puts(video_adapter_t *adp, vm_offset_t off, uint16_t *s, int len)
 1041 {
 1042         struct machfb_softc *sc;
 1043         int blanks, i, x1, x2, y1, y2;
 1044         uint8_t a, c, color1, color2;
 1045 
 1046         sc = (struct machfb_softc *)adp;
 1047 
 1048 #define MACHFB_BLANK    machfb_fill_rect(adp, color1, x1, y1,           \
 1049                             blanks * adp->va_info.vi_cwidth,            \
 1050                             adp->va_info.vi_cheight)
 1051 
 1052         blanks = color1 = x1 = y1 = 0;
 1053         for (i = 0; i < len; i++) {
 1054                 /*
 1055                  * Accelerate continuous blanks by drawing a respective
 1056                  * rectangle instead.  Drawing a rectangle of any size
 1057                  * takes about the same number of operations as drawing
 1058                  * a single character.
 1059                  */
 1060                 c = s[i] & 0xff;
 1061                 a = (s[i] & 0xff00) >> 8;
 1062                 if (c == 0x00 || c == 0x20 || c == 0xdb || c == 0xff) {
 1063                         color2 = (a >> (c == 0xdb ? 0 : 4) & 0xf);
 1064                         x2 = (((off + i) % adp->va_info.vi_width) *
 1065                             adp->va_info.vi_cwidth) + sc->sc_xmargin;
 1066                         y2 = (((off + i) / adp->va_info.vi_width) *
 1067                             adp->va_info.vi_cheight) + sc->sc_ymargin;
 1068                         if (blanks == 0) {
 1069                                 color1 = color2;
 1070                                 x1 = x2;
 1071                                 y1 = y2;
 1072                                 blanks++;
 1073                         } else if (color1 != color2 || y1 != y2) {
 1074                                 MACHFB_BLANK;
 1075                                 color1 = color2;
 1076                                 x1 = x2;
 1077                                 y1 = y2;
 1078                                 blanks = 1;
 1079                         } else
 1080                                 blanks++;
 1081                 } else {
 1082                         if (blanks != 0) {
 1083                                 MACHFB_BLANK;
 1084                                 blanks = 0;
 1085                         }
 1086                         vidd_putc(adp, off + i, c, a);
 1087                 }
 1088         }
 1089         if (blanks != 0)
 1090                 MACHFB_BLANK;
 1091 
 1092 #undef MACHFB_BLANK
 1093 
 1094         return (0);
 1095 }
 1096 
 1097 static int
 1098 machfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
 1099     uint32_t pixel_mask, int size, int width)
 1100 {
 1101         struct machfb_softc *sc;
 1102         int error;
 1103 
 1104         sc = (struct machfb_softc *)adp;
 1105 
 1106         if ((!(sc->sc_flags & MACHFB_CUREN)) &&
 1107             (error = machfb_cursor_install(sc)) < 0)
 1108                 return (error);
 1109         else {
 1110                 /*
 1111                  * The hardware cursor always must be disabled when
 1112                  * fiddling with its bits otherwise some artifacts
 1113                  * may appear on the screen.
 1114                  */
 1115                 machfb_cursor_enable(sc, 0);
 1116         }
 1117 
 1118         regw(sc, CUR_HORZ_VERT_OFF, 0);
 1119         if ((regr(sc, GEN_TEST_CNTL) & CRTC_DBL_SCAN_EN) != 0)
 1120                 y <<= 1;
 1121         regw(sc, CUR_HORZ_VERT_POSN, ((y + sc->sc_ymargin) << 16) |
 1122             (x + sc->sc_xmargin));
 1123         machfb_cursor_enable(sc, 1);
 1124         sc->sc_flags |= MACHFB_CUREN;
 1125 
 1126         return (0);
 1127 }
 1128 
 1129 /*
 1130  * PCI bus interface
 1131  */
 1132 static int
 1133 machfb_pci_probe(device_t dev)
 1134 {
 1135         int i;
 1136 
 1137         if (pci_get_class(dev) != PCIC_DISPLAY ||
 1138             pci_get_subclass(dev) != PCIS_DISPLAY_VGA)
 1139                 return (ENXIO);
 1140 
 1141         for (i = 0; i < sizeof(machfb_info) / sizeof(machfb_info[0]); i++) {
 1142                 if (pci_get_device(dev) == machfb_info[i].chip_id) {
 1143                         device_set_desc(dev, machfb_info[i].name);
 1144                         return (BUS_PROBE_DEFAULT);
 1145                 }
 1146         }
 1147 
 1148         return (ENXIO);
 1149 }
 1150 
 1151 static int
 1152 machfb_pci_attach(device_t dev)
 1153 {
 1154         struct machfb_softc *sc;
 1155         video_adapter_t *adp;
 1156         video_switch_t *sw;
 1157         video_info_t *vi;
 1158         phandle_t node;
 1159         int error, i, rid;
 1160         uint32_t *p32, u32;
 1161         uint8_t *p;
 1162 
 1163         node = ofw_bus_get_node(dev);
 1164         if ((sc = (struct machfb_softc *)vid_get_adapter(vid_find_adapter(
 1165             MACHFB_DRIVER_NAME, 0))) != NULL && sc->sc_node == node) {
 1166                 device_printf(dev, "console\n");
 1167                 device_set_softc(dev, sc);
 1168         } else {
 1169                 sc = device_get_softc(dev);
 1170 
 1171                 sc->sc_node = node;
 1172                 sc->sc_chip_id = pci_get_device(dev);
 1173                 sc->sc_chip_rev = pci_get_revid(dev);
 1174         }
 1175         adp = &sc->sc_va;
 1176         vi = &adp->va_info;
 1177 
 1178         /*
 1179          * Allocate resources regardless of whether we are the console
 1180          * and already obtained the bus tag and handle for the framebuffer
 1181          * in machfb_configure() or not so the resources are marked as
 1182          * taken in the respective RMAN.
 1183          */
 1184 
 1185         /* Enable memory and IO access. */
 1186         pci_write_config(dev, PCIR_COMMAND,
 1187             pci_read_config(dev, PCIR_COMMAND, 2) | PCIM_CMD_PORTEN |
 1188             PCIM_CMD_MEMEN, 2);
 1189 
 1190         /*
 1191          * NB: we need to take care that the framebuffer isn't mapped
 1192          * in twice as besides wasting resources this isn't possible with
 1193          * all MMUs.
 1194          */
 1195         rid = PCIR_BAR(0);
 1196         if ((sc->sc_memres = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
 1197             &rid, 0)) == NULL) {
 1198                 device_printf(dev, "cannot allocate memory resources\n");
 1199                 return (ENXIO);
 1200         }
 1201         if (OF_getprop(sc->sc_node, "address", &u32, sizeof(u32)) > 0 &&
 1202                 vtophys(u32) == rman_get_bushandle(sc->sc_memres))
 1203                 adp->va_mem_base = u32;
 1204         else {
 1205                 bus_release_resource(dev, SYS_RES_MEMORY,
 1206                     rman_get_rid(sc->sc_memres), sc->sc_memres);
 1207                 rid = PCIR_BAR(0);
 1208                 if ((sc->sc_memres = bus_alloc_resource_any(dev,
 1209                     SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) {
 1210                         device_printf(dev,
 1211                             "cannot allocate memory resources\n");
 1212                         return (ENXIO);
 1213                 }
 1214                 adp->va_mem_base =
 1215                     (vm_offset_t)rman_get_virtual(sc->sc_memres);
 1216         }
 1217         sc->sc_memt = rman_get_bustag(sc->sc_memres);
 1218         sc->sc_memh = rman_get_bushandle(sc->sc_memres);
 1219         sc->sc_regt = sc->sc_memt;
 1220         bus_space_subregion(sc->sc_regt, sc->sc_memh, MACH64_REG_OFF,
 1221             MACH64_REG_SIZE, &sc->sc_regh);
 1222         adp->va_mem_size = rman_get_size(sc->sc_memres);
 1223         adp->va_buffer = adp->va_mem_base;
 1224         adp->va_buffer_size = adp->va_mem_size;
 1225         sc->sc_mem = rman_get_start(sc->sc_memres);
 1226         vi->vi_buffer = sc->sc_memh;
 1227         vi->vi_buffer_size = adp->va_buffer_size;
 1228 
 1229         /*
 1230          * Depending on the firmware version the VGA I/O and/or memory
 1231          * resources of the Mach64 chips come up disabled.  We generally
 1232          * enable them above (pci(4) actually already did this unless
 1233          * pci_enable_io_modes is not set) but this doesn't necessarily
 1234          * mean that we get valid ones.  Invalid resources seem to have
 1235          * in common that they start at address 0.  We don't allocate
 1236          * them in this case in order to avoid warnings in apb(4) and
 1237          * crashes when using these invalid resources.  X.Org is aware
 1238          * of this and doesn't use the VGA resources in this case (but
 1239          * demands them if they are valid).
 1240          */
 1241         rid = PCIR_BAR(2);
 1242         if (bus_get_resource_start(dev, SYS_RES_MEMORY, rid) != 0) {
 1243                 if ((sc->sc_vmemres = bus_alloc_resource_any(dev,
 1244                     SYS_RES_MEMORY, &rid, RF_ACTIVE)) == NULL) {
 1245                         device_printf(dev,
 1246                             "cannot allocate VGA memory resources\n");
 1247                         error = ENXIO;
 1248                         goto fail_memres;
 1249                 }
 1250                 adp->va_registers =
 1251                     (vm_offset_t)rman_get_virtual(sc->sc_vmemres);
 1252                 adp->va_registers_size = rman_get_size(sc->sc_vmemres);
 1253                 sc->sc_vmem = rman_get_start(sc->sc_vmemres);
 1254                 vi->vi_registers = rman_get_bushandle(sc->sc_vmemres);
 1255                 vi->vi_registers_size = adp->va_registers_size;
 1256         }
 1257 
 1258         if (!(sc->sc_flags & MACHFB_CONSOLE)) {
 1259                 if ((sw = vid_get_switch(MACHFB_DRIVER_NAME)) == NULL) {
 1260                         device_printf(dev, "cannot get video switch\n");
 1261                         error = ENODEV;
 1262                         goto fail_vmemres;
 1263                 }
 1264                 /*
 1265                  * During device configuration we don't necessarily probe
 1266                  * the adapter which is the console first so we can't use
 1267                  * the device unit number for the video adapter unit.  The
 1268                  * worst case would be that we use the video adapter unit
 1269                  * 0 twice.  As it doesn't really matter which unit number
 1270                  * the corresponding video adapter has just use the next
 1271                  * unused one.
 1272                  */
 1273                 for (i = 0; i < devclass_get_maxunit(machfb_devclass); i++)
 1274                         if (vid_find_adapter(MACHFB_DRIVER_NAME, i) < 0)
 1275                                 break;
 1276                 if ((error = sw->init(i, adp, 0)) != 0) {
 1277                         device_printf(dev, "cannot initialize adapter\n");
 1278                         goto fail_vmemres;
 1279                 }
 1280         }
 1281 
 1282         /*
 1283          * Test whether the aperture is byte swapped or not, set
 1284          * va_window and va_window_size as appropriate.  Note that
 1285          * the aperture could be mapped either big or little endian
 1286          * on independently of the endianess of the host so this
 1287          * has to be a runtime test.
 1288          */
 1289         p32 = (uint32_t *)adp->va_buffer;
 1290         u32 = *p32;
 1291         p = (uint8_t *)adp->va_buffer;
 1292         *p32 = 0x12345678;
 1293         if (!(p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78)) {
 1294                 adp->va_window = adp->va_buffer + 0x800000;
 1295                 adp->va_window_size = adp->va_buffer_size - 0x800000;
 1296                 vi->vi_window = vi->vi_buffer + 0x800000;
 1297                 vi->vi_window_size = vi->vi_buffer_size - 0x800000;
 1298                 sc->sc_flags |= MACHFB_SWAP;
 1299         } else {
 1300                 adp->va_window = adp->va_buffer;
 1301                 adp->va_window_size = adp->va_buffer_size;
 1302                 vi->vi_window = vi->vi_buffer;
 1303                 vi->vi_window_size = vi->vi_buffer_size;
 1304         }
 1305         *p32 = u32;
 1306         adp->va_window_gran = adp->va_window_size;
 1307 
 1308         device_printf(dev,
 1309             "%d MB aperture at %p %sswapped\n",
 1310             (u_int)(adp->va_window_size / (1024 * 1024)),
 1311             (void *)adp->va_window, (sc->sc_flags & MACHFB_SWAP) ?
 1312             "" : "not ");
 1313         device_printf(dev,
 1314             "%ld KB %s %d.%d MHz, maximum RAMDAC clock %d MHz, %sDSP\n",
 1315             (u_long)sc->sc_memsize, machfb_memtype_names[sc->sc_memtype],
 1316             sc->sc_mem_freq / 1000, sc->sc_mem_freq % 1000,
 1317             sc->sc_ramdac_freq / 1000,
 1318             (sc->sc_flags & MACHFB_DSP) ? "" : "no ");
 1319         device_printf(dev, "resolution %dx%d at %d bpp\n",
 1320             sc->sc_width, sc->sc_height, sc->sc_depth);
 1321 
 1322         /*
 1323          * Allocate one page for the mouse pointer image at the end of
 1324          * the little endian aperture, right before the memory mapped
 1325          * registers that might also reside there.  Must be done after
 1326          * sc_memsize was set and possibly adjusted to account for the
 1327          * memory mapped registers.
 1328          */
 1329         sc->sc_curoff = (sc->sc_memsize * 1024) - PAGE_SIZE;
 1330         sc->sc_memsize -= PAGE_SIZE / 1024;
 1331         machfb_cursor_enable(sc, 0);
 1332         /* Initialize with an all transparent image. */
 1333         memset((void *)(adp->va_buffer + sc->sc_curoff), 0xaa, PAGE_SIZE);
 1334 
 1335         /*
 1336          * Register a handler that performs some cosmetic surgery like
 1337          * turning off the mouse pointer on halt in preparation for
 1338          * handing the screen over to the OFW.  Register another handler
 1339          * that turns off the CRTC when resetting, otherwise the OFW
 1340          * boot command issued by cpu_reset() just doesn't work.
 1341          */
 1342         EVENTHANDLER_REGISTER(shutdown_final, machfb_shutdown_final, sc,
 1343             SHUTDOWN_PRI_DEFAULT);
 1344         EVENTHANDLER_REGISTER(shutdown_reset, machfb_shutdown_reset, sc,
 1345             SHUTDOWN_PRI_DEFAULT);
 1346 
 1347         return (0);
 1348 
 1349  fail_vmemres:
 1350         if (sc->sc_vmemres != NULL)
 1351                 bus_release_resource(dev, SYS_RES_MEMORY,
 1352                     rman_get_rid(sc->sc_vmemres), sc->sc_vmemres);
 1353  fail_memres:
 1354         bus_release_resource(dev, SYS_RES_MEMORY,
 1355             rman_get_rid(sc->sc_memres), sc->sc_memres);
 1356 
 1357         return (error);
 1358 }
 1359 
 1360 static int
 1361 machfb_pci_detach(device_t dev)
 1362 {
 1363 
 1364         return (EINVAL);
 1365 }
 1366 
 1367 /*
 1368  * internal functions
 1369  */
 1370 static void
 1371 machfb_cursor_enable(struct machfb_softc *sc, int onoff)
 1372 {
 1373 
 1374         if (onoff)
 1375                 regw(sc, GEN_TEST_CNTL,
 1376                     regr(sc, GEN_TEST_CNTL) | HWCURSOR_ENABLE);
 1377         else
 1378                 regw(sc, GEN_TEST_CNTL,
 1379                     regr(sc, GEN_TEST_CNTL) &~ HWCURSOR_ENABLE);
 1380 }
 1381 
 1382 static int
 1383 machfb_cursor_install(struct machfb_softc *sc)
 1384 {
 1385         uint16_t *p, v;
 1386         uint8_t fg;
 1387         int i, j;
 1388 
 1389         if (sc->sc_curoff == 0)
 1390                 return (ENODEV);
 1391 
 1392         machfb_cursor_enable(sc, 0);
 1393         regw(sc, CUR_OFFSET, sc->sc_curoff >> 3);
 1394         fg = SC_NORM_ATTR & 0xf;
 1395         regw(sc, CUR_CLR0, machfb_default_cmap[fg].red << 24 |
 1396             machfb_default_cmap[fg].green << 16 |
 1397             machfb_default_cmap[fg].blue << 8);
 1398         p = (uint16_t *)(sc->sc_va.va_buffer + sc->sc_curoff);
 1399         for (i = 0; i < 64; i++) {
 1400                 for (j = 0; j < 8; j++) {
 1401                         v = machfb_mouse_pointer_lut[
 1402                             machfb_mouse_pointer_bits[i][j] >> 4] << 8 |
 1403                             machfb_mouse_pointer_lut[
 1404                             machfb_mouse_pointer_bits[i][j] & 0x0f];
 1405                         if (sc->sc_flags & MACHFB_SWAP)
 1406                                 *(p++) = bswap16(v);
 1407                         else
 1408                                 *(p++) = v;
 1409                 }
 1410         }
 1411 
 1412         return (0);
 1413 }
 1414 
 1415 static int
 1416 machfb_get_memsize(struct machfb_softc *sc)
 1417 {
 1418         int tmp, memsize;
 1419         const int const mem_tab[] = {
 1420                 512, 1024, 2048, 4096, 6144, 8192, 12288, 16384
 1421         };
 1422 
 1423         tmp = regr(sc, MEM_CNTL);
 1424 #ifdef MACHFB_DEBUG
 1425         printf("memcntl=0x%08x\n", tmp);
 1426 #endif
 1427         if (sc->sc_flags & MACHFB_DSP) {
 1428                 tmp &= 0x0000000f;
 1429                 if (tmp < 8)
 1430                         memsize = (tmp + 1) * 512;
 1431                 else if (tmp < 12)
 1432                         memsize = (tmp - 3) * 1024;
 1433                 else
 1434                         memsize = (tmp - 7) * 2048;
 1435         } else
 1436                 memsize = mem_tab[tmp & 0x07];
 1437 
 1438         return (memsize);
 1439 }
 1440 
 1441 static void
 1442 machfb_reset_engine(struct machfb_softc *sc)
 1443 {
 1444 
 1445         /* Reset engine.*/
 1446         regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) & ~GUI_ENGINE_ENABLE);
 1447 
 1448         /* Enable engine. */
 1449         regw(sc, GEN_TEST_CNTL, regr(sc, GEN_TEST_CNTL) | GUI_ENGINE_ENABLE);
 1450 
 1451         /*
 1452          * Ensure engine is not locked up by clearing any FIFO or
 1453          * host errors.
 1454          */
 1455         regw(sc, BUS_CNTL, regr(sc, BUS_CNTL) | BUS_HOST_ERR_ACK |
 1456             BUS_FIFO_ERR_ACK);
 1457 }
 1458 
 1459 static void
 1460 machfb_init_engine(struct machfb_softc *sc)
 1461 {
 1462         uint32_t pitch_value;
 1463 
 1464         pitch_value = sc->sc_width;
 1465 
 1466         if (sc->sc_depth == 24)
 1467                 pitch_value *= 3;
 1468 
 1469         machfb_reset_engine(sc);
 1470 
 1471         wait_for_fifo(sc, 14);
 1472 
 1473         regw(sc, CONTEXT_MASK, 0xffffffff);
 1474 
 1475         regw(sc, DST_OFF_PITCH, (pitch_value / 8) << 22);
 1476 
 1477         regw(sc, DST_Y_X, 0);
 1478         regw(sc, DST_HEIGHT, 0);
 1479         regw(sc, DST_BRES_ERR, 0);
 1480         regw(sc, DST_BRES_INC, 0);
 1481         regw(sc, DST_BRES_DEC, 0);
 1482 
 1483         regw(sc, DST_CNTL, DST_LAST_PEL | DST_X_LEFT_TO_RIGHT |
 1484             DST_Y_TOP_TO_BOTTOM);
 1485 
 1486         regw(sc, SRC_OFF_PITCH, (pitch_value / 8) << 22);
 1487 
 1488         regw(sc, SRC_Y_X, 0);
 1489         regw(sc, SRC_HEIGHT1_WIDTH1, 1);
 1490         regw(sc, SRC_Y_X_START, 0);
 1491         regw(sc, SRC_HEIGHT2_WIDTH2, 1);
 1492 
 1493         regw(sc, SRC_CNTL, SRC_LINE_X_LEFT_TO_RIGHT);
 1494 
 1495         wait_for_fifo(sc, 13);
 1496         regw(sc, HOST_CNTL, 0);
 1497 
 1498         regw(sc, PAT_REG0, 0);
 1499         regw(sc, PAT_REG1, 0);
 1500         regw(sc, PAT_CNTL, 0);
 1501 
 1502         regw(sc, SC_LEFT, 0);
 1503         regw(sc, SC_TOP, 0);
 1504         regw(sc, SC_BOTTOM, sc->sc_height - 1);
 1505         regw(sc, SC_RIGHT, pitch_value - 1);
 1506 
 1507         regw(sc, DP_BKGD_CLR, 0);
 1508         regw(sc, DP_FRGD_CLR, 0xffffffff);
 1509         regw(sc, DP_WRITE_MASK, 0xffffffff);
 1510         regw(sc, DP_MIX, (MIX_SRC << 16) | MIX_DST);
 1511 
 1512         regw(sc, DP_SRC, FRGD_SRC_FRGD_CLR);
 1513 
 1514         wait_for_fifo(sc, 3);
 1515         regw(sc, CLR_CMP_CLR, 0);
 1516         regw(sc, CLR_CMP_MASK, 0xffffffff);
 1517         regw(sc, CLR_CMP_CNTL, 0);
 1518 
 1519         wait_for_fifo(sc, 2);
 1520         switch (sc->sc_depth) {
 1521         case 8:
 1522                 regw(sc, DP_PIX_WIDTH, HOST_8BPP | SRC_8BPP | DST_8BPP);
 1523                 regw(sc, DP_CHAIN_MASK, DP_CHAIN_8BPP);
 1524                 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN);
 1525                 break;
 1526 #if 0
 1527         case 32:
 1528                 regw(sc, DP_PIX_WIDTH, HOST_32BPP | SRC_32BPP | DST_32BPP);
 1529                 regw(sc, DP_CHAIN_MASK, DP_CHAIN_32BPP);
 1530                 regw(sc, DAC_CNTL, regr(sc, DAC_CNTL) | DAC_8BIT_EN);
 1531                 break;
 1532 #endif
 1533         }
 1534 
 1535         wait_for_fifo(sc, 2);
 1536         regw(sc, CRTC_INT_CNTL, regr(sc, CRTC_INT_CNTL) & ~0x20);
 1537         regw(sc, GUI_TRAJ_CNTL, DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM);
 1538 
 1539         wait_for_idle(sc);
 1540 }
 1541 
 1542 #if 0
 1543 static void
 1544 machfb_adjust_frame(struct machfb_softc *sc, int x, int y)
 1545 {
 1546         int offset;
 1547 
 1548         offset = ((x + y * sc->sc_width) * (sc->sc_depth >> 3)) >> 3;
 1549 
 1550         regw(sc, CRTC_OFF_PITCH, (regr(sc, CRTC_OFF_PITCH) & 0xfff00000) |
 1551             offset);
 1552 }
 1553 #endif
 1554 
 1555 static void
 1556 machfb_shutdown_final(void *v)
 1557 {
 1558         struct machfb_softc *sc = v;
 1559 
 1560         machfb_cursor_enable(sc, 0);
 1561         /*
 1562          * In case this is the console set the cursor of the stdout
 1563          * instance to the start of the last line so OFW output ends
 1564          * up beneath what FreeBSD left on the screen.
 1565          */
 1566         if (sc->sc_flags & MACHFB_CONSOLE) {
 1567                 OF_interpret("stdout @ is my-self 0 to column#", 0);
 1568                 OF_interpret("stdout @ is my-self #lines 1 - to line#", 0);
 1569         }
 1570 }
 1571 
 1572 static void
 1573 machfb_shutdown_reset(void *v)
 1574 {
 1575         struct machfb_softc *sc = v;
 1576 
 1577         machfb_blank_display(&sc->sc_va, V_DISPLAY_STAND_BY);
 1578 }

Cache object: 09db6869c799e2f57691889723011654


[ 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.