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

Cache object: d24c1ca71cd3651b66824e33ac9c1d15


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