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

Cache object: 07bc19f2d557e16cd97e73afb362f66e


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