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

Cache object: 65b477e91d4af84545b323e11705f7cb


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