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/ic/igsfb.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 /*      $NetBSD: igsfb.c,v 1.17 2003/11/13 03:09:29 chs Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2002, 2003 Valeriy E. Ushakov
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. The name of the author may not be used to endorse or promote products
   16  *    derived from this software without specific prior written permission
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   28  */
   29 
   30 /*
   31  * Integraphics Systems IGA 168x and CyberPro series.
   32  */
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: igsfb.c,v 1.17 2003/11/13 03:09:29 chs Exp $");
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #include <sys/kernel.h>
   39 #include <sys/device.h>
   40 #include <sys/malloc.h>
   41 #include <sys/ioctl.h>
   42 #include <sys/buf.h>
   43 #include <uvm/uvm_extern.h>
   44 
   45 #include <machine/bus.h>
   46 
   47 #include <dev/wscons/wsdisplayvar.h>
   48 #include <dev/wscons/wsconsio.h>
   49 #include <dev/wsfont/wsfont.h>
   50 #include <dev/rasops/rasops.h>
   51 
   52 #include <dev/ic/igsfbreg.h>
   53 #include <dev/ic/igsfbvar.h>
   54 
   55 
   56 struct igsfb_devconfig igsfb_console_dc;
   57 
   58 /*
   59  * wsscreen
   60  */
   61 
   62 /* filled from rasops_info in igsfb_common_init */
   63 static struct wsscreen_descr igsfb_stdscreen = {
   64         "std",                  /* name */
   65         0, 0,                   /* ncols, nrows */
   66         NULL,                   /* textops */
   67         0, 0,                   /* fontwidth, fontheight */
   68         0                       /* capabilities */
   69 };
   70 
   71 static const struct wsscreen_descr *_igsfb_scrlist[] = {
   72         &igsfb_stdscreen,
   73 };
   74 
   75 static const struct wsscreen_list igsfb_screenlist = {
   76         sizeof(_igsfb_scrlist) / sizeof(struct wsscreen_descr *),
   77         _igsfb_scrlist
   78 };
   79 
   80 
   81 /*
   82  * wsdisplay_accessops
   83  */
   84 
   85 static int      igsfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
   86 static paddr_t  igsfb_mmap(void *, off_t, int);
   87 
   88 static int      igsfb_alloc_screen(void *, const struct wsscreen_descr *,
   89                                    void **, int *, int *, long *);
   90 static void     igsfb_free_screen(void *, void *);
   91 static int      igsfb_show_screen(void *, void *, int,
   92                                   void (*) (void *, int, int), void *);
   93 
   94 static const struct wsdisplay_accessops igsfb_accessops = {
   95         igsfb_ioctl,
   96         igsfb_mmap,
   97         igsfb_alloc_screen,
   98         igsfb_free_screen,
   99         igsfb_show_screen,
  100         NULL,                   /* load_font */
  101         NULL,                   /* pollc */
  102         NULL,                   /* getwschar */
  103         NULL                    /* putwschar */
  104 };
  105 
  106 
  107 /*
  108  * acceleration
  109  */
  110 static int      igsfb_make_text_cursor(struct igsfb_devconfig *);
  111 static void     igsfb_accel_cursor(void *, int, int, int);
  112 
  113 static int      igsfb_accel_wait(struct igsfb_devconfig *);
  114 static void     igsfb_accel_fill(struct igsfb_devconfig *,
  115                                  u_int32_t, u_int32_t, u_int16_t, u_int16_t);
  116 static void     igsfb_accel_copy(struct igsfb_devconfig *,
  117                                  u_int32_t, u_int32_t, u_int16_t, u_int16_t);
  118 
  119 static void     igsfb_accel_copycols(void *, int, int, int, int);
  120 static void     igsfb_accel_erasecols(void *, int, int, int, long);
  121 static void     igsfb_accel_copyrows(void *, int, int, int);
  122 static void     igsfb_accel_eraserows(void *, int, int, long);
  123 static void     igsfb_accel_putchar(void *, int, int, u_int, long);
  124 
  125 
  126 /*
  127  * internal functions
  128  */
  129 static int      igsfb_init_video(struct igsfb_devconfig *);
  130 static void     igsfb_init_cmap(struct igsfb_devconfig *);
  131 static u_int16_t igsfb_spread_bits_8(u_int8_t);
  132 static void     igsfb_init_bit_table(struct igsfb_devconfig *);
  133 static void     igsfb_init_wsdisplay(struct igsfb_devconfig *);
  134 
  135 static void     igsfb_blank_screen(struct igsfb_devconfig *, int);
  136 static int      igsfb_get_cmap(struct igsfb_devconfig *,
  137                                struct wsdisplay_cmap *);
  138 static int      igsfb_set_cmap(struct igsfb_devconfig *,
  139                                const struct wsdisplay_cmap *);
  140 static void     igsfb_update_cmap(struct igsfb_devconfig *, u_int, u_int);
  141 static void     igsfb_set_curpos(struct igsfb_devconfig *,
  142                                  const struct wsdisplay_curpos *);
  143 static void     igsfb_update_curpos(struct igsfb_devconfig *);
  144 static int      igsfb_get_cursor(struct igsfb_devconfig *,
  145                                  struct wsdisplay_cursor *);
  146 static int      igsfb_set_cursor(struct igsfb_devconfig *,
  147                                  const struct wsdisplay_cursor *);
  148 static void     igsfb_update_cursor(struct igsfb_devconfig *, u_int);
  149 static void     igsfb_convert_cursor_data(struct igsfb_devconfig *,
  150                                           u_int, u_int);
  151 
  152 
  153 int
  154 igsfb_cnattach_subr(dc)
  155         struct igsfb_devconfig *dc;
  156 {
  157         struct rasops_info *ri;
  158         long defattr;
  159 
  160         KASSERT(dc == &igsfb_console_dc);
  161 
  162         igsfb_init_video(dc);
  163         igsfb_init_wsdisplay(dc);
  164 
  165         dc->dc_nscreens = 1;
  166 
  167         ri = &dc->dc_ri;
  168         (*ri->ri_ops.allocattr)(ri,
  169                                 WSCOL_BLACK, /* fg */
  170                                 WSCOL_BLACK, /* bg */
  171                                 0,           /* wsattrs */
  172                                 &defattr);
  173 
  174         wsdisplay_cnattach(&igsfb_stdscreen,
  175                            ri,   /* emulcookie */
  176                            0, 0, /* cursor position */
  177                            defattr);
  178         return (0);
  179 }
  180 
  181 
  182 /*
  183  * Finish off the attach.  Bus specific attach method should have
  184  * enabled io and memory accesses and mapped io (and cop?) registers.
  185  */
  186 void
  187 igsfb_attach_subr(sc, isconsole)
  188         struct igsfb_softc *sc;
  189         int isconsole;
  190 {
  191         struct igsfb_devconfig *dc = sc->sc_dc;
  192         struct wsemuldisplaydev_attach_args waa;
  193 
  194         KASSERT(dc != NULL);
  195 
  196         if (!isconsole) {
  197                 igsfb_init_video(dc);
  198                 igsfb_init_wsdisplay(dc);
  199         }
  200 
  201         printf("%s: %dMB, %s%dx%d, %dbpp\n",
  202                sc->sc_dev.dv_xname,
  203                (u_int32_t)(dc->dc_vmemsz >> 20),
  204                (dc->dc_hwflags & IGSFB_HW_BSWAP)
  205                    ? (dc->dc_hwflags & IGSFB_HW_BE_SELECT)
  206                        ? "hardware bswap, " : "software bswap, "
  207                    : "",
  208                dc->dc_width, dc->dc_height, dc->dc_depth);
  209 
  210         /* attach wsdisplay */
  211         waa.console = isconsole;
  212         waa.scrdata = &igsfb_screenlist;
  213         waa.accessops = &igsfb_accessops;
  214         waa.accesscookie = dc;
  215 
  216         config_found(&sc->sc_dev, &waa, wsemuldisplaydevprint);
  217 }
  218 
  219 
  220 static int
  221 igsfb_init_video(dc)
  222         struct igsfb_devconfig *dc;
  223 {
  224         bus_space_handle_t tmph;
  225         u_int8_t *p;
  226         int need_bswap;
  227         bus_addr_t fbaddr, craddr;
  228         off_t croffset;
  229         u_int8_t busctl, curctl;
  230 
  231         /* Total amount of video memory. */
  232         busctl = igs_ext_read(dc->dc_iot, dc->dc_ioh, IGS_EXT_BUS_CTL);
  233         if (busctl & 0x2)
  234                 dc->dc_vmemsz = 4;
  235         else if (busctl & 0x1)
  236                 dc->dc_vmemsz = 2;
  237         else
  238                 dc->dc_vmemsz = 1;
  239         dc->dc_vmemsz <<= 20;   /* megabytes -> bytes */
  240 
  241         /*
  242          * Check for endianness mismatch by writing a word at the end of
  243          * the video memory (off-screen) and reading it back byte-by-byte.
  244          */
  245         if (bus_space_map(dc->dc_memt,
  246                           dc->dc_memaddr + dc->dc_vmemsz - sizeof(u_int32_t),
  247                           sizeof(u_int32_t),
  248                           dc->dc_memflags | BUS_SPACE_MAP_LINEAR,
  249                           &tmph) != 0)
  250         {
  251                 printf("unable to map video memory for endianness test\n");
  252                 return (1);
  253         }
  254 
  255         p = bus_space_vaddr(dc->dc_memt, tmph);
  256 #if BYTE_ORDER == BIG_ENDIAN
  257         *((u_int32_t *)p) = 0x12345678;
  258 #else
  259         *((u_int32_t *)p) = 0x78563412;
  260 #endif
  261         if (p[0] == 0x12 && p[1] == 0x34 && p[2] == 0x56 && p[3] == 0x78)
  262                 need_bswap = 0;
  263         else
  264                 need_bswap = 1;
  265 
  266         bus_space_unmap(dc->dc_memt, tmph, sizeof(u_int32_t));
  267 
  268         /*
  269          * On CyberPro we can use magic bswap bit in linear address.
  270          */
  271         fbaddr = dc->dc_memaddr;
  272         if (need_bswap) {
  273                 dc->dc_hwflags |= IGSFB_HW_BSWAP;
  274                 if (dc->dc_id >= 0x2000) {
  275                         dc->dc_hwflags |= IGSFB_HW_BE_SELECT;
  276                         fbaddr |= IGS_MEM_BE_SELECT;
  277                 }
  278         }
  279 
  280         /*
  281          * XXX: TODO: make it possible to select the desired video mode.
  282          * For now - hardcode to 1024x768/8bpp.  This is what Krups OFW uses.
  283          */
  284         igsfb_hw_setup(dc);
  285         delay(10000);           /* XXX: uwe */
  286 
  287         dc->dc_width = 1024;
  288         dc->dc_height = 768;
  289         dc->dc_depth = 8;
  290 
  291         /*
  292          * Don't map in all N megs, just the amount we need for the wsscreen.
  293          */
  294         dc->dc_fbsz = dc->dc_width * dc->dc_height; /* XXX: 8bpp specific */
  295         if (bus_space_map(dc->dc_memt, fbaddr, dc->dc_fbsz,
  296                           dc->dc_memflags | BUS_SPACE_MAP_LINEAR,
  297                           &dc->dc_fbh) != 0)
  298         {
  299                 bus_space_unmap(dc->dc_iot, dc->dc_ioh, IGS_REG_SIZE);
  300                 printf("unable to map framebuffer\n");
  301                 return (1);
  302         }
  303 
  304         igsfb_init_cmap(dc);
  305 
  306         /*
  307          * 1KB for cursor sprite data at the very end of the video memory.
  308          */
  309         croffset = dc->dc_vmemsz - IGS_CURSOR_DATA_SIZE;
  310         craddr = fbaddr + croffset;
  311         if (bus_space_map(dc->dc_memt, craddr, IGS_CURSOR_DATA_SIZE,
  312                           dc->dc_memflags | BUS_SPACE_MAP_LINEAR,
  313                           &dc->dc_crh) != 0)
  314         {
  315                 bus_space_unmap(dc->dc_iot, dc->dc_ioh, IGS_REG_SIZE);
  316                 bus_space_unmap(dc->dc_memt, dc->dc_fbh, dc->dc_fbsz);
  317                 printf("unable to map cursor sprite region\n");
  318                 return (1);
  319         }
  320 
  321         /*
  322          * Tell the device where cursor sprite data are located in the
  323          * linear space (it takes data offset in 1KB units).
  324          */
  325         croffset >>= 10;        /* bytes -> kilobytes */
  326         igs_ext_write(dc->dc_iot, dc->dc_ioh,
  327                       IGS_EXT_SPRITE_DATA_LO, croffset & 0xff);
  328         igs_ext_write(dc->dc_iot, dc->dc_ioh,
  329                       IGS_EXT_SPRITE_DATA_HI, (croffset >> 8) & 0xf);
  330 
  331         /* init the bit expansion table for cursor sprite data conversion */
  332         igsfb_init_bit_table(dc);
  333 
  334         /* XXX: fill dc_cursor and use igsfb_update_cursor() instead? */
  335         memset(&dc->dc_cursor, 0, sizeof(struct igs_hwcursor));
  336         memset(bus_space_vaddr(dc->dc_memt, dc->dc_crh),
  337                /* transparent */ 0xaa, IGS_CURSOR_DATA_SIZE);
  338 
  339         curctl = igs_ext_read(dc->dc_iot, dc->dc_ioh, IGS_EXT_SPRITE_CTL);
  340         curctl |= IGS_EXT_SPRITE_64x64;
  341         curctl &= ~IGS_EXT_SPRITE_VISIBLE;
  342         igs_ext_write(dc->dc_iot, dc->dc_ioh, IGS_EXT_SPRITE_CTL, curctl);
  343         dc->dc_curenb = 0;
  344 
  345         /*
  346          * Map abd init graphic coprocessor for accelerated rasops.
  347          */
  348         if (dc->dc_id >= 0x2000) { /* XXX */
  349                 if (bus_space_map(dc->dc_iot,
  350                                   dc->dc_iobase + IGS_COP_BASE_B, IGS_COP_SIZE,
  351                                   dc->dc_ioflags,
  352                                   &dc->dc_coph) != 0)
  353                 {
  354                         printf("unable to map COP registers\n");
  355                         return (1);
  356                 }
  357 
  358                 /* XXX: hardcoded 8bpp */
  359                 bus_space_write_2(dc->dc_iot, dc->dc_coph,
  360                                   IGS_COP_SRC_MAP_WIDTH_REG,
  361                                   dc->dc_width - 1);
  362                 bus_space_write_2(dc->dc_iot, dc->dc_coph,
  363                                   IGS_COP_DST_MAP_WIDTH_REG,
  364                                   dc->dc_width - 1);
  365 
  366                 bus_space_write_1(dc->dc_iot, dc->dc_coph,
  367                                   IGS_COP_MAP_FMT_REG,
  368                                   IGS_COP_MAP_8BPP);
  369         }
  370 
  371         /* make sure screen is not blanked */
  372         dc->dc_blanked = 0;
  373         igsfb_blank_screen(dc, dc->dc_blanked);
  374 
  375         return (0);
  376 }
  377 
  378 
  379 static void
  380 igsfb_init_cmap(dc)
  381         struct igsfb_devconfig *dc;
  382 {
  383         bus_space_tag_t iot = dc->dc_iot;
  384         bus_space_handle_t ioh = dc->dc_ioh;
  385         const u_int8_t *p;
  386         int i;
  387 
  388         p = rasops_cmap;        /* "ANSI" color map */
  389 
  390         /* init software copy */
  391         for (i = 0; i < IGS_CMAP_SIZE; ++i, p += 3) {
  392                 dc->dc_cmap.r[i] = p[0];
  393                 dc->dc_cmap.g[i] = p[1];
  394                 dc->dc_cmap.b[i] = p[2];
  395         }
  396 
  397         /* propagate to the device */
  398         igsfb_update_cmap(dc, 0, IGS_CMAP_SIZE);
  399 
  400         /* set overscan color (XXX: use defattr's background?) */
  401         igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_RED,   0);
  402         igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_GREEN, 0);
  403         igs_ext_write(iot, ioh, IGS_EXT_OVERSCAN_BLUE,  0);
  404 }
  405 
  406 
  407 static void
  408 igsfb_init_wsdisplay(dc)
  409         struct igsfb_devconfig *dc;
  410 {
  411         struct rasops_info *ri;
  412         int wsfcookie;
  413 
  414         ri = &dc->dc_ri;
  415         ri->ri_hw = dc;
  416 
  417         ri->ri_flg = RI_CENTER | RI_CLEAR;
  418         if (IGSFB_HW_SOFT_BSWAP(dc))
  419             ri->ri_flg |= RI_BSWAP;
  420 
  421         ri->ri_depth = dc->dc_depth;
  422         ri->ri_width = dc->dc_width;
  423         ri->ri_height = dc->dc_height;
  424 
  425         ri->ri_stride = dc->dc_width; /* XXX: 8bpp specific */
  426         ri->ri_bits = (u_char *)dc->dc_fbh;
  427 
  428         /*
  429          * Initialize wsfont related stuff.
  430          */
  431         wsfont_init();
  432 
  433         /* prefer gallant that is identical to the one the prom uses */
  434         wsfcookie = wsfont_find("Gallant", 12, 22, 0,
  435                                 WSDISPLAY_FONTORDER_L2R,
  436                                 WSDISPLAY_FONTORDER_L2R);
  437         if (wsfcookie <= 0) {
  438 #ifdef DIAGNOSTIC
  439                 printf("unable to find font Gallant 12x22\n");
  440 #endif
  441                 wsfcookie = wsfont_find(NULL, 0, 0, 0, /* any font at all? */
  442                                         WSDISPLAY_FONTORDER_L2R,
  443                                         WSDISPLAY_FONTORDER_L2R);
  444         }
  445 
  446         if (wsfcookie <= 0) {
  447                 printf("unable to find any fonts\n");
  448                 return;
  449         }
  450 
  451         if (wsfont_lock(wsfcookie, &ri->ri_font) != 0) {
  452                 printf("unable to lock font\n");
  453                 return;
  454         }
  455         ri->ri_wsfcookie = wsfcookie;
  456 
  457 
  458         /* XXX: TODO: compute term size based on font dimensions? */
  459         rasops_init(ri, 34, 80);
  460 
  461 
  462         /* use the sprite for the text mode cursor */
  463         igsfb_make_text_cursor(dc);
  464 
  465         /* the cursor is "busy" while we are in the text mode */
  466         dc->dc_hwflags |= IGSFB_HW_TEXT_CURSOR;
  467 
  468         /* propagate sprite data to the device */
  469         igsfb_update_cursor(dc, WSDISPLAY_CURSOR_DOSHAPE);
  470 
  471         /* accelerated text cursor */
  472         ri->ri_ops.cursor = igsfb_accel_cursor;
  473 
  474         if (dc->dc_id >= 0x2000) { /* XXX */
  475             /* accelerated erase/copy */
  476             ri->ri_ops.copycols = igsfb_accel_copycols;
  477             ri->ri_ops.erasecols = igsfb_accel_erasecols;
  478             ri->ri_ops.copyrows = igsfb_accel_copyrows;
  479             ri->ri_ops.eraserows = igsfb_accel_eraserows;
  480 
  481             /* putchar hook to sync with the cop */
  482             dc->dc_ri_putchar = ri->ri_ops.putchar;
  483             ri->ri_ops.putchar = igsfb_accel_putchar;
  484         }
  485 
  486         igsfb_stdscreen.nrows = ri->ri_rows;
  487         igsfb_stdscreen.ncols = ri->ri_cols;
  488         igsfb_stdscreen.textops = &ri->ri_ops;
  489         igsfb_stdscreen.capabilities = ri->ri_caps;
  490 }
  491 
  492 
  493 /*
  494  * Init cursor data in dc_cursor for the accelerated text cursor.
  495  */
  496 static int
  497 igsfb_make_text_cursor(dc)
  498         struct igsfb_devconfig *dc;
  499 {
  500         struct wsdisplay_font *f = dc->dc_ri.ri_font;
  501         u_int16_t cc_scan[8];   /* one sprite scanline */
  502         u_int16_t s;
  503         int w, i;
  504 
  505         KASSERT(f->fontwidth <= IGS_CURSOR_MAX_SIZE);
  506         KASSERT(f->fontheight <= IGS_CURSOR_MAX_SIZE);
  507 
  508         w = f->fontwidth;
  509         for (i = 0; i < f->stride; ++i) {
  510                 if (w >= 8) {
  511                         s = 0xffff; /* all inverted */
  512                         w -= 8;
  513                 } else {
  514                         /* first w pixels inverted, the rest is transparent */
  515                         s = ~(0x5555 << (w * 2));
  516                         if (IGSFB_HW_SOFT_BSWAP(dc))
  517                                 s = bswap16(s);
  518                         w = 0;
  519                 }
  520                 cc_scan[i] = s;
  521         }
  522 
  523         dc->dc_cursor.cc_size.x = f->fontwidth;
  524         dc->dc_cursor.cc_size.y = f->fontheight;
  525 
  526         dc->dc_cursor.cc_hot.x = 0;
  527         dc->dc_cursor.cc_hot.y = 0;
  528 
  529         /* init sprite array to be all transparent */
  530         memset(dc->dc_cursor.cc_sprite, 0xaa, IGS_CURSOR_DATA_SIZE);
  531 
  532         for (i = 0; i < f->fontheight; ++i)
  533                 memcpy(&dc->dc_cursor.cc_sprite[i * 8],
  534                        cc_scan, f->stride * sizeof(u_int16_t));
  535 
  536         return (0);
  537 }
  538 
  539 
  540 /*
  541  * Spread a byte (abcd.efgh) into two (0a0b.0c0d 0e0f.0g0h).
  542  * Helper function for igsfb_init_bit_table().
  543  */
  544 static u_int16_t
  545 igsfb_spread_bits_8(b)
  546         u_int8_t b;
  547 {
  548         u_int16_t s = b;
  549 
  550         s = ((s & 0x00f0) << 4) | (s & 0x000f);
  551         s = ((s & 0x0c0c) << 2) | (s & 0x0303);
  552         s = ((s & 0x2222) << 1) | (s & 0x1111);
  553         return (s);
  554 }
  555 
  556 
  557 /*
  558  * Cursor sprite data are in 2bpp.  Incoming image/mask are in 1bpp.
  559  * Prebuild the table to expand 1bpp->2bpp, with bswapping if neccessary.
  560  */
  561 static void
  562 igsfb_init_bit_table(dc)
  563         struct igsfb_devconfig *dc;
  564 {
  565         u_int16_t *expand = dc->dc_bexpand;
  566         int need_bswap = IGSFB_HW_SOFT_BSWAP(dc);
  567         u_int16_t s;
  568         u_int i;
  569 
  570         for (i = 0; i < 256; ++i) {
  571                 s = igsfb_spread_bits_8(i);
  572                 expand[i] = need_bswap ? bswap16(s) : s;
  573         }
  574 }
  575 
  576 
  577 /*
  578  * wsdisplay_accessops: mmap()
  579  *   XXX: allow mmapping i/o mapped i/o regs if INSECURE???
  580  */
  581 static paddr_t
  582 igsfb_mmap(v, offset, prot)
  583         void *v;
  584         off_t offset;
  585         int prot;
  586 {
  587         struct igsfb_devconfig *dc = v;
  588 
  589         if (offset >= dc->dc_memsz || offset < 0)
  590                 return (-1);
  591 
  592         return (bus_space_mmap(dc->dc_memt, dc->dc_memaddr, offset, prot,
  593                                dc->dc_memflags | BUS_SPACE_MAP_LINEAR));
  594 }
  595 
  596 
  597 /*
  598  * wsdisplay_accessops: ioctl()
  599  */
  600 static int
  601 igsfb_ioctl(v, cmd, data, flag, p)
  602         void *v;
  603         u_long cmd;
  604         caddr_t data;
  605         int flag;
  606         struct proc *p;
  607 {
  608         struct igsfb_devconfig *dc = v;
  609         struct rasops_info *ri;
  610         int cursor_busy;
  611         int turnoff;
  612 
  613         /* don't permit cursor ioctls if we use sprite for text cursor */
  614         cursor_busy = !dc->dc_mapped
  615                 && (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR);
  616 
  617         switch (cmd) {
  618 
  619         case WSDISPLAYIO_GTYPE:
  620                 *(u_int *)data = WSDISPLAY_TYPE_PCIMISC;
  621                 return (0);
  622 
  623         case WSDISPLAYIO_GINFO:
  624                 ri = &dc->dc_ri;
  625 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
  626                 wsd_fbip->height = ri->ri_height;
  627                 wsd_fbip->width = ri->ri_width;
  628                 wsd_fbip->depth = ri->ri_depth;
  629                 wsd_fbip->cmsize = IGS_CMAP_SIZE;
  630 #undef wsd_fbip
  631                 return (0);
  632 
  633         case WSDISPLAYIO_SMODE:
  634 #define d (*(int *)data)
  635                 if (d == WSDISPLAYIO_MODE_MAPPED)
  636                         dc->dc_mapped = 1;
  637                 else {
  638                         dc->dc_mapped = 0;
  639                         /* reinit sprite for text cursor */
  640                         if (dc->dc_hwflags & IGSFB_HW_TEXT_CURSOR) {
  641                                 igsfb_make_text_cursor(dc);
  642                                 dc->dc_curenb = 0;
  643                                 igsfb_update_cursor(dc,
  644                                           WSDISPLAY_CURSOR_DOSHAPE
  645                                         | WSDISPLAY_CURSOR_DOCUR);
  646                         }
  647                 }
  648                 return (0);
  649 
  650         case WSDISPLAYIO_GVIDEO:
  651                 *(u_int *)data = dc->dc_blanked ?
  652                     WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
  653                 return (0);
  654 
  655         case WSDISPLAYIO_SVIDEO:
  656                 turnoff = (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF);
  657                 if (dc->dc_blanked != turnoff) {
  658                         dc->dc_blanked = turnoff;
  659                         igsfb_blank_screen(dc, dc->dc_blanked);
  660                 }
  661                 return (0);
  662 
  663         case WSDISPLAYIO_GETCMAP:
  664                 return (igsfb_get_cmap(dc, (struct wsdisplay_cmap *)data));
  665 
  666         case WSDISPLAYIO_PUTCMAP:
  667                 return (igsfb_set_cmap(dc, (struct wsdisplay_cmap *)data));
  668 
  669         case WSDISPLAYIO_GCURMAX:
  670                 ((struct wsdisplay_curpos *)data)->x = IGS_CURSOR_MAX_SIZE;
  671                 ((struct wsdisplay_curpos *)data)->y = IGS_CURSOR_MAX_SIZE;
  672                 return (0);
  673 
  674         case WSDISPLAYIO_GCURPOS:
  675                 if (cursor_busy)
  676                         return (EBUSY);
  677                 *(struct wsdisplay_curpos *)data = dc->dc_cursor.cc_pos;
  678                 return (0);
  679 
  680         case WSDISPLAYIO_SCURPOS:
  681                 if (cursor_busy)
  682                         return (EBUSY);
  683                 igsfb_set_curpos(dc, (struct wsdisplay_curpos *)data);
  684                 return (0);
  685 
  686         case WSDISPLAYIO_GCURSOR:
  687                 if (cursor_busy)
  688                         return (EBUSY);
  689                 return (igsfb_get_cursor(dc, (struct wsdisplay_cursor *)data));
  690 
  691         case WSDISPLAYIO_SCURSOR:
  692                 if (cursor_busy)
  693                         return (EBUSY);
  694                 return (igsfb_set_cursor(dc, (struct wsdisplay_cursor *)data));
  695         }
  696 
  697         return (EPASSTHROUGH);
  698 }
  699 
  700 
  701 /*
  702  * wsdisplay_accessops: ioctl(WSDISPLAYIO_SVIDEO)
  703  */
  704 static void
  705 igsfb_blank_screen(dc, blank)
  706         struct igsfb_devconfig *dc;
  707         int blank;
  708 {
  709 
  710         igs_ext_write(dc->dc_iot, dc->dc_ioh,
  711                       IGS_EXT_SYNC_CTL,
  712                       blank ? IGS_EXT_SYNC_H0 | IGS_EXT_SYNC_V0
  713                             : 0);
  714 }
  715 
  716 
  717 /*
  718  * wsdisplay_accessops: ioctl(WSDISPLAYIO_GETCMAP)
  719  *   Served from the software cmap copy.
  720  */
  721 static int
  722 igsfb_get_cmap(dc, p)
  723         struct igsfb_devconfig *dc;
  724         struct wsdisplay_cmap *p;
  725 {
  726         u_int index, count;
  727         int err;
  728 
  729         index = p->index;
  730         count = p->count;
  731 
  732         if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index)
  733                 return (EINVAL);
  734 
  735         err = copyout(&dc->dc_cmap.r[index], p->red, count);
  736         if (err)
  737                 return (err);
  738         err = copyout(&dc->dc_cmap.g[index], p->green, count);
  739         if (err)
  740                 return (err);
  741         err = copyout(&dc->dc_cmap.b[index], p->blue, count);
  742         if (err)
  743                 return (err);
  744 
  745         return (0);
  746 }
  747 
  748 
  749 /*
  750  * wsdisplay_accessops: ioctl(WSDISPLAYIO_PUTCMAP)
  751  *   Set the software cmap copy and propagate changed range to the device.
  752  */
  753 static int
  754 igsfb_set_cmap(dc, p)
  755         struct igsfb_devconfig *dc;
  756         const struct wsdisplay_cmap *p;
  757 {
  758         u_int index, count;
  759         uint8_t r[IGS_CMAP_SIZE];
  760         uint8_t g[IGS_CMAP_SIZE];
  761         uint8_t b[IGS_CMAP_SIZE];
  762         int error;
  763 
  764         index = p->index;
  765         count = p->count;
  766         if (index >= IGS_CMAP_SIZE || count > IGS_CMAP_SIZE - index)
  767                 return (EINVAL);
  768         error = copyin(p->red, &r[index], count);
  769         if (error)
  770                 return error;
  771         error = copyin(p->green, &g[index], count);
  772         if (error)
  773                 return error;
  774         error = copyin(p->blue, &b[index], count);
  775         if (error)
  776                 return error;
  777 
  778         memcpy(&dc->dc_cmap.r[index], &r[index], count);
  779         memcpy(&dc->dc_cmap.g[index], &g[index], count);
  780         memcpy(&dc->dc_cmap.b[index], &b[index], count);
  781 
  782         /* propagate changes to the device */
  783         igsfb_update_cmap(dc, index, count);
  784         return (0);
  785 }
  786 
  787 
  788 /*
  789  * Propagate specified part of the software cmap copy to the device.
  790  */
  791 static void
  792 igsfb_update_cmap(dc, index, count)
  793         struct igsfb_devconfig *dc;
  794         u_int index, count;
  795 {
  796         bus_space_tag_t t;
  797         bus_space_handle_t h;
  798         u_int last, i;
  799 
  800         if (index >= IGS_CMAP_SIZE)
  801                 return;
  802 
  803         last = index + count;
  804         if (last > IGS_CMAP_SIZE)
  805                 last = IGS_CMAP_SIZE;
  806 
  807         t = dc->dc_iot;
  808         h = dc->dc_ioh;
  809 
  810         /* start palette writing, index is autoincremented by hardware */
  811         bus_space_write_1(t, h, IGS_DAC_PEL_WRITE_IDX, index);
  812 
  813         for (i = index; i < last; ++i) {
  814                 bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.r[i]);
  815                 bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.g[i]);
  816                 bus_space_write_1(t, h, IGS_DAC_PEL_DATA, dc->dc_cmap.b[i]);
  817         }
  818 }
  819 
  820 
  821 /*
  822  * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURPOS)
  823  */
  824 static void
  825 igsfb_set_curpos(dc, curpos)
  826         struct igsfb_devconfig *dc;
  827         const struct wsdisplay_curpos *curpos;
  828 {
  829         struct rasops_info *ri = &dc->dc_ri;
  830         u_int x = curpos->x, y = curpos->y;
  831 
  832         if (x >= ri->ri_width)
  833                 x = ri->ri_width - 1;
  834         if (y >= ri->ri_height)
  835                 y = ri->ri_height - 1;
  836 
  837         dc->dc_cursor.cc_pos.x = x;
  838         dc->dc_cursor.cc_pos.y = y;
  839 
  840         /* propagate changes to the device */
  841         igsfb_update_curpos(dc);
  842 }
  843 
  844 
  845 static void
  846 igsfb_update_curpos(dc)
  847         struct igsfb_devconfig *dc;
  848 {
  849         bus_space_tag_t t;
  850         bus_space_handle_t h;
  851         int x, xoff, y, yoff;
  852 
  853         xoff = 0;
  854         x = dc->dc_cursor.cc_pos.x - dc->dc_cursor.cc_hot.x;
  855         if (x < 0) {
  856                 xoff = -x;
  857                 x = 0;
  858         }
  859 
  860         yoff = 0;
  861         y = dc->dc_cursor.cc_pos.y - dc->dc_cursor.cc_hot.y;
  862         if (y < 0) {
  863                 yoff = -y;
  864                 y = 0;
  865         }
  866 
  867         t = dc->dc_iot;
  868         h = dc->dc_ioh;
  869 
  870         igs_ext_write(t, h, IGS_EXT_SPRITE_HSTART_LO, x & 0xff);
  871         igs_ext_write(t, h, IGS_EXT_SPRITE_HSTART_HI, (x >> 8) & 0x07);
  872         igs_ext_write(t, h, IGS_EXT_SPRITE_HPRESET, xoff & 0x3f);
  873 
  874         igs_ext_write(t, h, IGS_EXT_SPRITE_VSTART_LO, y & 0xff);
  875         igs_ext_write(t, h, IGS_EXT_SPRITE_VSTART_HI, (y >> 8) & 0x07);
  876         igs_ext_write(t, h, IGS_EXT_SPRITE_VPRESET, yoff & 0x3f);
  877 }
  878 
  879 
  880 /*
  881  * wsdisplay_accessops: ioctl(WSDISPLAYIO_GCURSOR)
  882  */
  883 static int
  884 igsfb_get_cursor(dc, p)
  885         struct igsfb_devconfig *dc;
  886         struct wsdisplay_cursor *p;
  887 {
  888 
  889         /* XXX: TODO */
  890         return (0);
  891 }
  892 
  893 
  894 /*
  895  * wsdisplay_accessops: ioctl(WSDISPLAYIO_SCURSOR)
  896  */
  897 static int
  898 igsfb_set_cursor(dc, p)
  899         struct igsfb_devconfig *dc;
  900         const struct wsdisplay_cursor *p;
  901 {
  902         struct igs_hwcursor *cc;
  903         struct wsdisplay_curpos pos, hot;
  904         u_int v, index, count, icount, iwidth;
  905         uint8_t r[2], g[2], b[2], image[512], mask[512];
  906         int error;
  907 
  908         cc = &dc->dc_cursor;
  909         v = p->which;
  910         index = count = icount = iwidth = 0;    /* XXX: gcc */
  911 
  912         /* copy in the new cursor colormap */
  913         if (v & WSDISPLAY_CURSOR_DOCMAP) {
  914                 index = p->cmap.index;
  915                 count = p->cmap.count;
  916                 if (index >= 2 || (index + count) > 2)
  917                         return (EINVAL);
  918                 error = copyin(p->cmap.red, &r[index], count);
  919                 if (error)
  920                         return error;
  921                 error = copyin(p->cmap.green, &g[index], count);
  922                 if (error)
  923                         return error;
  924                 error = copyin(p->cmap.blue, &b[index], count);
  925                 if (error)
  926                         return error;
  927         }
  928 
  929         /* verify that the new cursor data are valid */
  930         if (v & WSDISPLAY_CURSOR_DOSHAPE) {
  931                 if (p->size.x > IGS_CURSOR_MAX_SIZE
  932                     || p->size.y > IGS_CURSOR_MAX_SIZE)
  933                         return (EINVAL);
  934 
  935                 iwidth = (p->size.x + 7) >> 3; /* bytes per scan line */
  936                 icount = iwidth * p->size.y;
  937                 error = copyin(p->image, image, icount);
  938                 if (error)
  939                         return error;
  940                 error = copyin(p->mask, mask, icount);
  941                 if (error)
  942                         return error;
  943         }
  944 
  945         /* enforce that the position is within screen bounds */
  946         if (v & WSDISPLAY_CURSOR_DOPOS) {
  947                 struct rasops_info *ri = &dc->dc_ri;
  948 
  949                 pos = p->pos;   /* local copy we can write to */
  950                 if (pos.x >= ri->ri_width)
  951                         pos.x = ri->ri_width - 1;
  952                 if (pos.y >= ri->ri_height)
  953                         pos.y = ri->ri_height - 1;
  954         }
  955 
  956         /* enforce that the hot spot is within sprite bounds */
  957         if (v & WSDISPLAY_CURSOR_DOHOT)
  958                 hot = p->hot;   /* local copy we can write to */
  959 
  960         if (v & (WSDISPLAY_CURSOR_DOHOT | WSDISPLAY_CURSOR_DOSHAPE)) {
  961                 const struct wsdisplay_curpos *nsize;
  962                 struct wsdisplay_curpos *nhot;
  963 
  964                 nsize = (v & WSDISPLAY_CURSOR_DOSHAPE) ?
  965                             &p->size : &cc->cc_size;
  966                 nhot = (v & WSDISPLAY_CURSOR_DOHOT) ? &hot : &cc->cc_hot;
  967 
  968                 if (nhot->x >= nsize->x)
  969                         nhot->x = nsize->x - 1;
  970                 if (nhot->y >= nsize->y)
  971                         nhot->y = nsize->y - 1;
  972         }
  973 
  974         /* copy data to the driver's cursor info */
  975         if (v & WSDISPLAY_CURSOR_DOCUR)
  976                 dc->dc_curenb = p->enable;
  977         if (v & WSDISPLAY_CURSOR_DOPOS)
  978                 cc->cc_pos = pos; /* local copy, possibly corrected */
  979         if (v & WSDISPLAY_CURSOR_DOHOT)
  980                 cc->cc_hot = hot; /* local copy, possibly corrected */
  981         if (v & WSDISPLAY_CURSOR_DOCMAP) {
  982                 memcpy(&cc->cc_color[index], &r[index], count);
  983                 memcpy(&cc->cc_color[index + 2], &g[index], count);
  984                 memcpy(&cc->cc_color[index + 4], &b[index], count);
  985         }
  986         if (v & WSDISPLAY_CURSOR_DOSHAPE) {
  987                 u_int trailing_bits;
  988 
  989                 memcpy(cc->cc_image, image, icount);
  990                 memcpy(cc->cc_mask, mask, icount);
  991                 cc->cc_size = p->size;
  992 
  993                 /* clear trailing bits in the "partial" mask bytes */
  994                 trailing_bits = p->size.x & 0x07;
  995                 if (trailing_bits != 0) {
  996                         const u_int cutmask = ~((~0) << trailing_bits);
  997                         u_char *mp;
  998                         u_int i;
  999 
 1000                         mp = cc->cc_mask + iwidth - 1;
 1001                         for (i = 0; i < p->size.y; ++i) {
 1002                                 *mp &= cutmask;
 1003                                 mp += iwidth;
 1004                         }
 1005                 }
 1006                 igsfb_convert_cursor_data(dc, iwidth, p->size.y);
 1007         }
 1008 
 1009         /* propagate changes to the device */
 1010         igsfb_update_cursor(dc, v);
 1011 
 1012         return (0);
 1013 }
 1014 
 1015 
 1016 /*
 1017  * Convert incoming 1bpp cursor image/mask into native 2bpp format.
 1018  */
 1019 static void
 1020 igsfb_convert_cursor_data(dc, width, height)
 1021         struct igsfb_devconfig *dc;
 1022         u_int width, height;
 1023 {
 1024         struct igs_hwcursor *cc = &dc->dc_cursor;
 1025         u_int16_t *expand = dc->dc_bexpand;
 1026         u_int8_t *ip, *mp;
 1027         u_int16_t is, ms, *dp;
 1028         u_int line, i;
 1029 
 1030         /* init sprite to be all transparent */
 1031         memset(cc->cc_sprite, 0xaa, IGS_CURSOR_DATA_SIZE);
 1032 
 1033         /* first scanline */
 1034         ip = cc->cc_image;
 1035         mp = cc->cc_mask;
 1036         dp = cc->cc_sprite;
 1037 
 1038         for (line = 0; line < height; ++line) {
 1039                 for (i = 0; i < width; ++i) {
 1040                         is = expand[ip[i]]; /* image: 0 -> 00, 1 -> 01 */
 1041                         ms = expand[mp[i]]; /*  mask: 0 -> 00, 1 -> 11 */
 1042                         ms |= (ms << 1);
 1043                         dp[i] = (0xaaaa & ~ms) | (is & ms);
 1044                 }
 1045 
 1046                 /* next scanline */
 1047                 ip += width;
 1048                 mp += width;
 1049                 dp += 8; /* 64 pixels, 2bpp, 8 pixels per short = 8 shorts */
 1050         }
 1051 }
 1052 
 1053 
 1054 /*
 1055  * Propagate cursor changes to the device.
 1056  * "which" is composed of WSDISPLAY_CURSOR_DO* bits.
 1057  */
 1058 static void
 1059 igsfb_update_cursor(dc, which)
 1060         struct igsfb_devconfig *dc;
 1061         u_int which;
 1062 {
 1063         bus_space_tag_t iot = dc->dc_iot;
 1064         bus_space_handle_t ioh = dc->dc_ioh;
 1065         u_int8_t curctl;
 1066 
 1067         curctl = 0;             /* XXX: gcc */
 1068 
 1069         /*
 1070          * We will need to tweak sprite control register for cursor
 1071          * visibility and cursor color map manipualtion.
 1072          */
 1073         if (which & (WSDISPLAY_CURSOR_DOCUR | WSDISPLAY_CURSOR_DOCMAP)) {
 1074                 curctl = igs_ext_read(iot, ioh, IGS_EXT_SPRITE_CTL);
 1075         }
 1076 
 1077         if (which & WSDISPLAY_CURSOR_DOSHAPE) {
 1078                 u_int8_t *dst = bus_space_vaddr(dc->dc_memt, dc->dc_crh);
 1079 
 1080                 /*
 1081                  * memcpy between spaces of different endianness would
 1082                  * be ... special.  We cannot be sure if memcpy gonna
 1083                  * push data in 4-byte chunks, we can't pre-bswap it,
 1084                  * so do it byte-by-byte to preserve byte ordering.
 1085                  */
 1086                 if (IGSFB_HW_SOFT_BSWAP(dc)) {
 1087                         u_int8_t *src = (u_int8_t *)dc->dc_cursor.cc_sprite;
 1088                         int i;
 1089 
 1090                         for (i = 0; i < IGS_CURSOR_DATA_SIZE; ++i)
 1091                                 *dst++ = *src++;
 1092                 } else {
 1093                         memcpy(dst, dc->dc_cursor.cc_sprite,
 1094                                IGS_CURSOR_DATA_SIZE);
 1095                 }
 1096         }
 1097 
 1098         if (which & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
 1099                 /* code shared with WSDISPLAYIO_SCURPOS */
 1100                 igsfb_update_curpos(dc);
 1101         }
 1102 
 1103         if (which & WSDISPLAY_CURSOR_DOCMAP) {
 1104                 u_int8_t *p;
 1105 
 1106                 /* tell DAC we want access to the cursor palette */
 1107                 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL,
 1108                               curctl | IGS_EXT_SPRITE_DAC_PEL);
 1109 
 1110                 p = dc->dc_cursor.cc_color;
 1111 
 1112                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_WRITE_IDX, 0);
 1113                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[0]);
 1114                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[2]);
 1115                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[4]);
 1116 
 1117                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_WRITE_IDX, 1);
 1118                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[1]);
 1119                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[3]);
 1120                 bus_space_write_1(iot, ioh, IGS_DAC_PEL_DATA, p[5]);
 1121 
 1122                 /* restore access to the normal palette */
 1123                 igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL, curctl);
 1124         }
 1125 
 1126         if (which & WSDISPLAY_CURSOR_DOCUR) {
 1127                 if ((curctl & IGS_EXT_SPRITE_VISIBLE) == 0
 1128                     && dc->dc_curenb)
 1129                         igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL,
 1130                                       curctl | IGS_EXT_SPRITE_VISIBLE);
 1131                 else if ((curctl & IGS_EXT_SPRITE_VISIBLE) != 0
 1132                          && !dc->dc_curenb)
 1133                         igs_ext_write(iot, ioh, IGS_EXT_SPRITE_CTL,
 1134                                       curctl & ~IGS_EXT_SPRITE_VISIBLE);
 1135         }
 1136 }
 1137 
 1138 
 1139 /*
 1140  * wsdisplay_accessops: alloc_screen()
 1141  */
 1142 static int
 1143 igsfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
 1144         void *v;
 1145         const struct wsscreen_descr *type;
 1146         void **cookiep;
 1147         int *curxp, *curyp;
 1148         long *attrp;
 1149 {
 1150         struct igsfb_devconfig *dc = v;
 1151         struct rasops_info *ri = &dc->dc_ri;
 1152 
 1153         if (dc->dc_nscreens > 0) /* only do single screen for now */
 1154                 return (ENOMEM);
 1155 
 1156         dc->dc_nscreens = 1;
 1157 
 1158         *cookiep = ri;          /* emulcookie for igsgfb_stdscreen.textops */
 1159         *curxp = *curyp = 0;    /* cursor position */
 1160         (*ri->ri_ops.allocattr)(ri,
 1161                                 WSCOL_BLACK, /* fg */
 1162                                 WSCOL_BLACK, /* bg */
 1163                                 0,           /* wsattr */
 1164                                 attrp);
 1165         return (0);
 1166 }
 1167 
 1168 
 1169 /*
 1170  * wsdisplay_accessops: free_screen()
 1171  */
 1172 static void
 1173 igsfb_free_screen(v, cookie)
 1174         void *v;
 1175         void *cookie;
 1176 {
 1177 
 1178         /* XXX */
 1179         return;
 1180 }
 1181 
 1182 
 1183 /*
 1184  * wsdisplay_accessops: show_screen()
 1185  */
 1186 static int
 1187 igsfb_show_screen(v, cookie, waitok, cb, cbarg)
 1188         void *v;
 1189         void *cookie;
 1190         int waitok;
 1191         void (*cb)(void *, int, int);
 1192         void *cbarg;
 1193 {
 1194 
 1195         /* XXX */
 1196         return (0);
 1197 }
 1198 
 1199 
 1200 
 1201 /*
 1202  * Accelerated text mode cursor that uses hardware sprite.
 1203  */
 1204 static void
 1205 igsfb_accel_cursor(cookie, on, row, col)
 1206         void *cookie;
 1207         int on, row, col;
 1208 {
 1209         struct rasops_info *ri = (struct rasops_info *)cookie;
 1210         struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw;
 1211         struct igs_hwcursor *cc = &dc->dc_cursor;
 1212         u_int which;
 1213 
 1214         ri->ri_crow = row;
 1215         ri->ri_ccol = col;
 1216 
 1217         which = 0;
 1218         if (on) {
 1219                 ri->ri_flg |= RI_CURSOR;
 1220 
 1221                 /* only bother to move the cursor if it's visibile */
 1222                 cc->cc_pos.x = ri->ri_xorigin
 1223                         + ri->ri_ccol * ri->ri_font->fontwidth;
 1224                 cc->cc_pos.y = ri->ri_yorigin
 1225                         + ri->ri_crow * ri->ri_font->fontheight;
 1226                 which |= WSDISPLAY_CURSOR_DOPOS;
 1227         } else
 1228                 ri->ri_flg &= ~RI_CURSOR;
 1229 
 1230         if (dc->dc_curenb != on) {
 1231                 dc->dc_curenb = on;
 1232                 which |= WSDISPLAY_CURSOR_DOCUR;
 1233         }
 1234 
 1235         /* propagate changes to the device */
 1236         igsfb_update_cursor(dc, which);
 1237 }
 1238 
 1239 
 1240 
 1241 /*
 1242  * Accelerated raster ops that use graphic coprocessor.
 1243  */
 1244 
 1245 static int
 1246 igsfb_accel_wait(dc)
 1247         struct igsfb_devconfig *dc;
 1248 {
 1249         bus_space_tag_t t = dc->dc_iot;
 1250         bus_space_handle_t h = dc->dc_coph;
 1251         int timo = 100000;
 1252         u_int8_t reg;
 1253 
 1254         while (timo--) {
 1255                 reg = bus_space_read_1(t, h, IGS_COP_CTL_REG);
 1256                 if ((reg & IGS_COP_CTL_BUSY) == 0)
 1257                         return (0);
 1258         }
 1259 
 1260         return (1);
 1261 }
 1262 
 1263 
 1264 static void
 1265 igsfb_accel_copy(dc, src, dst, width, height)
 1266         struct igsfb_devconfig *dc;
 1267         u_int32_t src, dst;
 1268         u_int16_t width, height;
 1269 {
 1270         bus_space_tag_t t = dc->dc_iot;
 1271         bus_space_handle_t h = dc->dc_coph;
 1272         u_int32_t toend;
 1273         u_int8_t drawcmd;
 1274 
 1275         drawcmd = IGS_COP_DRAW_ALL;
 1276         if (dst > src) {
 1277                 toend = dc->dc_ri.ri_width * (height - 1) + (width - 1);
 1278                 src += toend;
 1279                 dst += toend;
 1280                 drawcmd |= IGS_COP_OCTANT_X_NEG | IGS_COP_OCTANT_Y_NEG;
 1281         }
 1282 
 1283         igsfb_accel_wait(dc);
 1284         bus_space_write_1(t, h, IGS_COP_CTL_REG, 0);
 1285 
 1286         bus_space_write_1(t, h, IGS_COP_FG_MIX_REG, IGS_COP_MIX_S);
 1287 
 1288         bus_space_write_2(t, h, IGS_COP_WIDTH_REG, width - 1);
 1289         bus_space_write_2(t, h, IGS_COP_HEIGHT_REG, height - 1);
 1290 
 1291         bus_space_write_4(t, h, IGS_COP_SRC_START_REG, src);
 1292         bus_space_write_4(t, h, IGS_COP_DST_START_REG, dst);
 1293 
 1294         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_0_REG, drawcmd);
 1295         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_1_REG, IGS_COP_PPM_FIXED_FG);
 1296         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_2_REG, 0);
 1297         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_3_REG,
 1298                           IGS_COP_OP_PXBLT | IGS_COP_OP_FG_FROM_SRC);
 1299 }
 1300 
 1301 static void
 1302 igsfb_accel_fill(dc, color, dst, width, height)
 1303         struct igsfb_devconfig *dc;
 1304         u_int32_t color;
 1305         u_int32_t dst;
 1306         u_int16_t width, height;
 1307 {
 1308         bus_space_tag_t t = dc->dc_iot;
 1309         bus_space_handle_t h = dc->dc_coph;
 1310 
 1311         igsfb_accel_wait(dc);
 1312         bus_space_write_1(t, h, IGS_COP_CTL_REG, 0);
 1313 
 1314         bus_space_write_1(t, h, IGS_COP_FG_MIX_REG, IGS_COP_MIX_S);
 1315 
 1316         bus_space_write_2(t, h, IGS_COP_WIDTH_REG, width - 1);
 1317         bus_space_write_2(t, h, IGS_COP_HEIGHT_REG, height - 1);
 1318 
 1319         bus_space_write_4(t, h, IGS_COP_DST_START_REG, dst);
 1320         bus_space_write_4(t, h, IGS_COP_FG_REG, color);
 1321 
 1322         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_0_REG, IGS_COP_DRAW_ALL);
 1323         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_1_REG, IGS_COP_PPM_FIXED_FG);
 1324         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_2_REG, 0);
 1325         bus_space_write_1(t, h, IGS_COP_PIXEL_OP_3_REG, IGS_COP_OP_PXBLT);
 1326 }
 1327 
 1328 
 1329 static void
 1330 igsfb_accel_copyrows(cookie, src, dst, num)
 1331         void *cookie;
 1332         int src, dst, num;
 1333 {
 1334         struct rasops_info *ri = (struct rasops_info *)cookie;
 1335         struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw;
 1336         u_int32_t srp, dsp;
 1337         u_int16_t width, height;
 1338 
 1339         width = ri->ri_emuwidth;
 1340         height = num * ri->ri_font->fontheight;
 1341 
 1342         srp = ri->ri_xorigin
 1343                 + ri->ri_width * (ri->ri_yorigin
 1344                                   + src * ri->ri_font->fontheight);
 1345         dsp = ri->ri_xorigin
 1346                 + ri->ri_width * (ri->ri_yorigin
 1347                                   + dst * ri->ri_font->fontheight);
 1348 
 1349         igsfb_accel_copy(dc, srp, dsp, width, height);
 1350 }
 1351 
 1352 
 1353 void
 1354 igsfb_accel_copycols(cookie, row, src, dst, num)
 1355         void *cookie;
 1356         int row, src, dst, num;
 1357 {
 1358         struct rasops_info *ri = (struct rasops_info *)cookie;
 1359         struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw;
 1360         u_int32_t rowp, srp, dsp;
 1361         u_int16_t width, height;
 1362         
 1363         width = num * ri->ri_font->fontwidth;
 1364         height = ri->ri_font->fontheight;
 1365 
 1366         rowp = ri->ri_xorigin
 1367                 + ri->ri_width * (ri->ri_yorigin
 1368                                   + row * ri->ri_font->fontheight);
 1369 
 1370         srp = rowp + src * ri->ri_font->fontwidth;
 1371         dsp = rowp + dst * ri->ri_font->fontwidth;
 1372 
 1373         igsfb_accel_copy(dc, srp, dsp, width, height);  
 1374 }
 1375 
 1376 
 1377 static void
 1378 igsfb_accel_eraserows(cookie, row, num, attr)
 1379         void *cookie;
 1380         int row, num;
 1381         long attr;
 1382 {
 1383         struct rasops_info *ri = (struct rasops_info *)cookie;
 1384         struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw;
 1385         u_int32_t color;
 1386         u_int32_t dsp;
 1387         u_int16_t width, height;
 1388 
 1389         width = ri->ri_emuwidth;
 1390         height = num * ri->ri_font->fontheight;
 1391 
 1392         dsp = ri->ri_xorigin
 1393                 + ri->ri_width * (ri->ri_yorigin
 1394                                   + row * ri->ri_font->fontheight);
 1395 
 1396         /* XXX: we "know" the encoding that rasops' allocattr uses */
 1397         color = (attr >> 16) & 0xff;
 1398 
 1399         igsfb_accel_fill(dc, color, dsp, width, height);
 1400 }
 1401 
 1402 
 1403 void
 1404 igsfb_accel_erasecols(cookie, row, col, num, attr)
 1405         void *cookie;
 1406         int row, col, num;
 1407         long attr;
 1408 {
 1409         struct rasops_info *ri = (struct rasops_info *)cookie;
 1410         struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw;
 1411         u_int32_t color;
 1412         u_int32_t rowp, dsp;
 1413         u_int16_t width, height;
 1414 
 1415         width = num * ri->ri_font->fontwidth;
 1416         height = ri->ri_font->fontheight;
 1417 
 1418         rowp = ri->ri_xorigin
 1419                 + ri->ri_width * (ri->ri_yorigin
 1420                                   + row * ri->ri_font->fontheight);
 1421 
 1422         dsp = rowp + col * ri->ri_font->fontwidth;
 1423 
 1424         /* XXX: we "know" the encoding that rasops' allocattr uses */
 1425         color = (attr >> 16) & 0xff;
 1426 
 1427         igsfb_accel_fill(dc, color, dsp, width, height);
 1428 }
 1429 
 1430 
 1431 /*
 1432  * Not really implemented here, but we need to hook into the one
 1433  * supplied by rasops so that we can synchronize with the COP.
 1434  */
 1435 static void
 1436 igsfb_accel_putchar(cookie, row, col, uc, attr)
 1437         void *cookie;
 1438         int row, col;
 1439         u_int uc;
 1440         long attr;
 1441 {
 1442         struct rasops_info *ri = (struct rasops_info *)cookie;
 1443         struct igsfb_devconfig *dc = (struct igsfb_devconfig *)ri->ri_hw;
 1444 
 1445         igsfb_accel_wait(dc);
 1446         (*dc->dc_ri_putchar)(cookie, row, col, uc, attr);
 1447 }

Cache object: 1ef6ad75d7966eebe917fc3fc3513e86


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