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/tc/stic.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: stic.c,v 1.27 2003/12/17 03:59:33 ad Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Andrew Doran.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *      This product includes software developed by the NetBSD
   21  *      Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * Copyright (c) 1998, 1999 Tohru Nishimura.  All rights reserved.
   41  *
   42  * Redistribution and use in source and binary forms, with or without
   43  * modification, are permitted provided that the following conditions
   44  * are met:
   45  * 1. Redistributions of source code must retain the above copyright
   46  *    notice, this list of conditions and the following disclaimer.
   47  * 2. Redistributions in binary form must reproduce the above copyright
   48  *    notice, this list of conditions and the following disclaimer in the
   49  *    documentation and/or other materials provided with the distribution.
   50  * 3. All advertising materials mentioning features or use of this software
   51  *    must display the following acknowledgement:
   52  *      This product includes software developed by Tohru Nishimura
   53  *      for the NetBSD Project.
   54  * 4. The name of the author may not be used to endorse or promote products
   55  *    derived from this software without specific prior written permission
   56  *
   57  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   58  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   59  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   60  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   61  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   62  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   63  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   64  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   65  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   66  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   67  */
   68 
   69 /*
   70  * Driver for the DEC PixelStamp interface chip (STIC).
   71  *
   72  * XXX The bt459 interface shouldn't be replicated here.
   73  */
   74 
   75 #include <sys/cdefs.h>
   76 __KERNEL_RCSID(0, "$NetBSD: stic.c,v 1.27 2003/12/17 03:59:33 ad Exp $");
   77 
   78 #include <sys/param.h>
   79 #include <sys/systm.h>
   80 #include <sys/kernel.h>
   81 #include <sys/device.h>
   82 #include <sys/malloc.h>
   83 #include <sys/buf.h>
   84 #include <sys/ioctl.h>
   85 #include <sys/callout.h>
   86 #include <sys/conf.h>
   87 
   88 #include <uvm/uvm_extern.h>
   89 
   90 #if defined(pmax)
   91 #include <mips/cpuregs.h>
   92 #elif defined(alpha)
   93 #include <alpha/alpha_cpu.h>
   94 #endif
   95 
   96 #include <machine/vmparam.h>
   97 #include <machine/bus.h>
   98 #include <machine/intr.h>
   99 
  100 #include <dev/wscons/wsconsio.h>
  101 #include <dev/wscons/wsdisplayvar.h>
  102 
  103 #include <dev/wsfont/wsfont.h>
  104 
  105 #include <dev/ic/bt459reg.h>    
  106 
  107 #include <dev/tc/tcvar.h>
  108 #include <dev/tc/sticreg.h>
  109 #include <dev/tc/sticio.h>
  110 #include <dev/tc/sticvar.h>
  111 
  112 #define DUPBYTE0(x) ((((x)&0xff)<<16) | (((x)&0xff)<<8) | ((x)&0xff))
  113 #define DUPBYTE1(x) ((((x)<<8)&0xff0000) | ((x)&0xff00) | (((x)>>8)&0xff))
  114 #define DUPBYTE2(x) (((x)&0xff0000) | (((x)>>8)&0xff00) | (((x)>>16)&0xff))
  115 
  116 #define PACK(p, o) ((p)[(o)] | ((p)[(o)+1] << 16))
  117 
  118 #if defined(pmax)
  119 #define machine_btop(x)         mips_btop(x)
  120 #elif defined(alpha)
  121 #define machine_btop(x)         alpha_btop(x)
  122 #endif
  123 
  124 /*
  125  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
  126  * obscure register layout such as 2nd and 3rd Bt459 registers are
  127  * adjacent each other in a word, i.e.,
  128  *      struct bt459triplet {
  129  *              struct {
  130  *                      u_int8_t u0;
  131  *                      u_int8_t u1;
  132  *                      u_int8_t u2;
  133  *                      unsigned :8; 
  134  *              } bt_lo;
  135  *              struct {
  136  *
  137  * Although HX has single Bt459, 32bit R/W can be done w/o any trouble.
  138  *      struct bt459reg {
  139  *                 u_int32_t       bt_lo;
  140  *                 u_int32_t       bt_hi;
  141  *                 u_int32_t       bt_reg;
  142  *                 u_int32_t       bt_cmap;
  143  *      };
  144  *
  145  */
  146 
  147 /* Bt459 hardware registers */
  148 #define bt_lo   0
  149 #define bt_hi   1
  150 #define bt_reg  2
  151 #define bt_cmap 3
  152 
  153 #define REG(base, index)        *((u_int32_t *)(base) + (index))
  154 #define SELECT(vdac, regno) do {                \
  155         REG(vdac, bt_lo) = DUPBYTE0(regno);     \
  156         REG(vdac, bt_hi) = DUPBYTE1(regno);     \
  157         tc_wmb();                               \
  158    } while (0)
  159 
  160 int     sticioctl(void *, u_long, caddr_t, int, struct proc *);
  161 int     stic_alloc_screen(void *, const struct wsscreen_descr *, void **,
  162                           int *, int *, long *);
  163 void    stic_free_screen(void *, void *);
  164 int     stic_show_screen(void *, void *, int, void (*)(void *, int, int),
  165                          void *);
  166 
  167 void    stic_do_switch(void *);
  168 void    stic_setup_backing(struct stic_info *, struct stic_screen *);
  169 void    stic_setup_vdac(struct stic_info *);
  170 void    stic_clear_screen(struct stic_info *);
  171 
  172 int     stic_get_cmap(struct stic_info *, struct wsdisplay_cmap *);
  173 int     stic_set_cmap(struct stic_info *, struct wsdisplay_cmap *);
  174 int     stic_set_cursor(struct stic_info *, struct wsdisplay_cursor *);
  175 int     stic_get_cursor(struct stic_info *, struct wsdisplay_cursor *);
  176 void    stic_set_curpos(struct stic_info *, struct wsdisplay_curpos *);
  177 void    stic_set_hwcurpos(struct stic_info *);
  178 
  179 void    stic_cursor(void *, int, int, int);
  180 void    stic_copycols(void *, int, int, int, int);
  181 void    stic_copyrows(void *, int, int, int);
  182 void    stic_erasecols(void *, int, int, int, long);
  183 void    stic_eraserows(void *, int, int, long);
  184 int     stic_mapchar(void *, int, u_int *);
  185 void    stic_putchar(void *, int, int, u_int, long);
  186 int     stic_allocattr(void *, int, int, int, long *);
  187 
  188 dev_type_open(sticopen);
  189 dev_type_close(sticclose);
  190 dev_type_mmap(sticmmap);
  191 
  192 const struct cdevsw stic_cdevsw = {
  193         sticopen, sticclose, noread, nowrite, noioctl,
  194         nostop, notty, nopoll, sticmmap, nokqfilter,
  195 };
  196 
  197 /* Colormap for wscons, matching WSCOL_*. Upper 8 are high-intensity. */
  198 static const u_int8_t stic_cmap[16*3] = {
  199         0x00, 0x00, 0x00, /* black */
  200         0x7f, 0x00, 0x00, /* red */
  201         0x00, 0x7f, 0x00, /* green */
  202         0x7f, 0x7f, 0x00, /* brown */
  203         0x00, 0x00, 0x7f, /* blue */
  204         0x7f, 0x00, 0x7f, /* magenta */
  205         0x00, 0x7f, 0x7f, /* cyan */
  206         0xc7, 0xc7, 0xc7, /* white */
  207 
  208         0x7f, 0x7f, 0x7f, /* black */
  209         0xff, 0x00, 0x00, /* red */
  210         0x00, 0xff, 0x00, /* green */
  211         0xff, 0xff, 0x00, /* brown */
  212         0x00, 0x00, 0xff, /* blue */
  213         0xff, 0x00, 0xff, /* magenta */
  214         0x00, 0xff, 0xff, /* cyan */
  215         0xff, 0xff, 0xff, /* white */
  216 };
  217 
  218 /*
  219  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
  220  *   M M M M I I I I            M I M I M I M I
  221  *      [ before ]                 [ after ]
  222  *   3 2 1 0 3 2 1 0            0 0 1 1 2 2 3 3
  223  *   7 6 5 4 7 6 5 4            4 4 5 5 6 6 7 7
  224  */
  225 static const u_int8_t shuffle[256] = {
  226         0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
  227         0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
  228         0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
  229         0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
  230         0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
  231         0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
  232         0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
  233         0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
  234         0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
  235         0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
  236         0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
  237         0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
  238         0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
  239         0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
  240         0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
  241         0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
  242         0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
  243         0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
  244         0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
  245         0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
  246         0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
  247         0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
  248         0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
  249         0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
  250         0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
  251         0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
  252         0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
  253         0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
  254         0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
  255         0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
  256         0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
  257         0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
  258 };
  259 
  260 static const struct wsdisplay_accessops stic_accessops = {
  261         sticioctl,
  262         NULL,                   /* mmap */
  263         stic_alloc_screen,
  264         stic_free_screen,
  265         stic_show_screen,
  266         NULL,                   /* load_font */
  267 };
  268 
  269 static const struct wsdisplay_emulops stic_emulops = {
  270         stic_cursor,
  271         stic_mapchar,
  272         stic_putchar,
  273         stic_copycols,
  274         stic_erasecols,
  275         stic_copyrows,
  276         stic_eraserows,
  277         stic_allocattr
  278 };
  279 
  280 static struct wsscreen_descr stic_stdscreen = {
  281         "std", 
  282         0, 0,
  283         &stic_emulops,
  284         0, 0,
  285         WSSCREEN_WSCOLORS | WSSCREEN_HILIT
  286 };
  287 
  288 static const struct wsscreen_descr *_stic_scrlist[] = {
  289         &stic_stdscreen,
  290 };
  291 
  292 static const struct wsscreen_list stic_screenlist = {
  293         sizeof(_stic_scrlist) / sizeof(struct wsscreen_descr *), _stic_scrlist
  294 };
  295 
  296 struct  stic_info stic_consinfo;
  297 static struct   stic_screen stic_consscr;
  298 static struct   stic_info *stic_info[STIC_MAXDV];
  299 static int      stic_unit;
  300 
  301 void
  302 stic_init(struct stic_info *si)
  303 {
  304         volatile u_int32_t *vdac;
  305         int i, cookie;
  306 
  307         /* Reset the STIC & stamp(s). */
  308         stic_reset(si);
  309         vdac = si->si_vdac;
  310 
  311         /* Hit it... */
  312         SELECT(vdac, BT459_IREG_COMMAND_0);
  313         REG(vdac, bt_reg) = 0x00c0c0c0; tc_wmb();
  314 
  315         /* Now reset the VDAC. */
  316         *si->si_vdac_reset = 0;
  317         tc_wmb();
  318         tc_syncbus();
  319         DELAY(1000);
  320 
  321         /* Finish the initialization. */
  322         SELECT(vdac, BT459_IREG_COMMAND_1);
  323         REG(vdac, bt_reg) = 0x00000000; tc_wmb();
  324         REG(vdac, bt_reg) = 0x00c2c2c2; tc_wmb();
  325         REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
  326 
  327         for (i = 0; i < 7; i++) {
  328                 REG(vdac, bt_reg) = 0x00000000;
  329                 tc_wmb();
  330         }
  331 
  332         /* Set cursor colormap. */
  333         SELECT(vdac, BT459_IREG_CCOLOR_1);
  334         REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
  335         REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
  336         REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
  337         REG(vdac, bt_reg) = 0x00000000; tc_wmb();
  338         REG(vdac, bt_reg) = 0x00000000; tc_wmb();
  339         REG(vdac, bt_reg) = 0x00000000; tc_wmb();
  340         REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
  341         REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
  342         REG(vdac, bt_reg) = 0x00ffffff; tc_wmb();
  343 
  344         /* Get a font and set up screen metrics. */
  345         wsfont_init();
  346 
  347         cookie = wsfont_find(NULL, 12, 0, 2, WSDISPLAY_FONTORDER_R2L,
  348             WSDISPLAY_FONTORDER_L2R);
  349         if (cookie <= 0)
  350                 cookie = wsfont_find(NULL, 0, 0, 2, WSDISPLAY_FONTORDER_R2L,
  351                     WSDISPLAY_FONTORDER_L2R);
  352         if (cookie <= 0)
  353                 panic("stic_init: font table is empty");
  354 
  355         if (wsfont_lock(cookie, &si->si_font))
  356                 panic("stic_init: couldn't lock font");
  357 
  358         si->si_fontw = si->si_font->fontwidth;
  359         si->si_fonth = si->si_font->fontheight;
  360         si->si_consw = (1280 / si->si_fontw) & ~1;
  361         si->si_consh = 1024 / si->si_fonth;
  362         stic_stdscreen.ncols = si->si_consw;
  363         stic_stdscreen.nrows = si->si_consh;
  364 
  365 #ifdef DIAGNOSTIC
  366         if ((u_int)si->si_fonth > 32 || (u_int)si->si_fontw > 16)
  367                 panic("stic_init: unusable font");
  368 #endif
  369 
  370         stic_setup_vdac(si);
  371         stic_clear_screen(si);
  372         si->si_dispmode = WSDISPLAYIO_MODE_EMUL;
  373 }
  374 
  375 void
  376 stic_reset(struct stic_info *si)
  377 {
  378         int modtype, xconfig, yconfig, config;
  379         volatile struct stic_regs *sr;
  380 
  381         sr = si->si_stic;
  382 
  383         /*
  384          * Initialize the interface chip registers.
  385          */
  386         sr->sr_sticsr = 0x00000030;     /* Get the STIC's attention. */
  387         tc_wmb();
  388         tc_syncbus();
  389         DELAY(2000);                    /* wait 2ms for STIC to respond. */
  390         sr->sr_sticsr = 0x00000000;     /* Hit the STIC's csr again... */
  391         tc_wmb();
  392         sr->sr_buscsr = 0xffffffff;     /* and bash its bus-acess csr. */
  393         tc_wmb();
  394         tc_syncbus();                   /* Blam! */
  395         DELAY(20000);                   /* wait until the stic recovers... */
  396 
  397         modtype = sr->sr_modcl;
  398         xconfig = (modtype & 0x800) >> 11;
  399         yconfig = (modtype & 0x600) >> 9;
  400         config = (yconfig << 1) | xconfig;
  401         si->si_stampw = (xconfig ? 5 : 4);
  402         si->si_stamph = (1 << yconfig);
  403         si->si_stamphm = si->si_stamph - 1;
  404 #ifdef notyet
  405         si->si_option = (char)((modtype >> 12) & 3);
  406 #endif
  407 
  408         /* First PixelStamp */
  409         si->si_stamp[0x000b0] = config;
  410         si->si_stamp[0x000b4] = 0x0;
  411 
  412         /* Second PixelStamp */
  413         if (yconfig > 0) {
  414                 si->si_stamp[0x100b0] = config | 8;
  415                 si->si_stamp[0x100b4] = 0;
  416         }
  417 
  418         /*
  419          * Initialize STIC video registers.  Enable error and vertical
  420          * retrace interrupts.  Set the packet done flag so the Xserver will
  421          * not time-out on the first packet submitted.
  422          */
  423         sr->sr_vblank = (1024 << 16) | 1063;
  424         sr->sr_vsync = (1027 << 16) | 1030;
  425         sr->sr_hblank = (255 << 16) | 340;
  426         sr->sr_hsync2 = 245;
  427         sr->sr_hsync = (261 << 16) | 293;
  428         sr->sr_ipdvint =
  429             STIC_INT_WE | STIC_INT_P | STIC_INT_E_EN | STIC_INT_V_EN;
  430         sr->sr_sticsr = 8;
  431         tc_wmb();
  432         tc_syncbus();
  433 }
  434 
  435 void
  436 stic_attach(struct device *self, struct stic_info *si, int console)
  437 {
  438         struct wsemuldisplaydev_attach_args waa;
  439 
  440         if (stic_unit < STIC_MAXDV) {
  441                 stic_info[stic_unit] = si;
  442                 si->si_unit = stic_unit++;
  443         } else
  444                 si->si_unit = -1;
  445 
  446         callout_init(&si->si_switch_callout);
  447 
  448         /*
  449          * Allocate backing for the console.  We could trawl back through
  450          * msgbuf and and fill the backing, but it's not worth the hassle. 
  451          * We could also grab backing using pmap_steal_memory() early on,
  452          * but that's a little ugly.
  453          */
  454         if (console)
  455                 stic_setup_backing(si, &stic_consscr);
  456 
  457         waa.console = console;
  458         waa.scrdata = &stic_screenlist;
  459         waa.accessops = &stic_accessops;
  460         waa.accesscookie = si;
  461 
  462         config_found(self, &waa, wsemuldisplaydevprint);
  463 }
  464 
  465 void
  466 stic_cnattach(struct stic_info *si)
  467 {
  468         struct stic_screen *ss;
  469         long defattr;
  470 
  471         ss = &stic_consscr;
  472         si->si_curscreen = ss;
  473         ss->ss_flags = SS_ALLOCED | SS_ACTIVE | SS_CURENB;
  474         ss->ss_si = si;
  475 
  476         si->si_flags |= SI_CURENB_CHANGED;
  477         stic_flush(si);
  478 
  479         stic_allocattr(ss, 0, 0, 0, &defattr);
  480         stic_eraserows(ss, 0, si->si_consh, 0);
  481         wsdisplay_cnattach(&stic_stdscreen, ss, 0, 0, defattr);
  482 }
  483 
  484 void
  485 stic_setup_vdac(struct stic_info *si)
  486 {
  487         u_int8_t *ip, *mp;
  488         int r, c, o, b, i, s;
  489 
  490         s = spltty();
  491 
  492         ip = (u_int8_t *)si->si_cursor.cc_image;
  493         mp = (u_int8_t *)si->si_cursor.cc_mask;
  494         memset(ip, 0, sizeof(si->si_cursor.cc_image));
  495         memset(mp, 0, sizeof(si->si_cursor.cc_mask));
  496 
  497         for (r = 0; r < si->si_fonth; r++) {
  498                 for (c = r & 1; c < si->si_fontw; c += 2) {
  499                         o = c >> 3;
  500                         b = 1 << (c & 7);
  501                         ip[o] |= b;
  502                         mp[o] |= b;
  503                 }
  504 
  505                 ip += 8;
  506                 mp += 8;
  507         }
  508 
  509         si->si_cursor.cc_size.x = 64;
  510         si->si_cursor.cc_size.y = si->si_fonth;
  511         si->si_cursor.cc_hot.x = 0;
  512         si->si_cursor.cc_hot.y = 0;
  513 
  514         si->si_cursor.cc_color[0] = 0xff;
  515         si->si_cursor.cc_color[2] = 0xff;
  516         si->si_cursor.cc_color[4] = 0xff;
  517         si->si_cursor.cc_color[1] = 0x00;
  518         si->si_cursor.cc_color[3] = 0x00;
  519         si->si_cursor.cc_color[5] = 0x00;
  520 
  521         memset(&si->si_cmap, 0, sizeof(si->si_cmap));
  522         for (i = 0; i < 16; i++) {
  523                 si->si_cmap.r[i] = stic_cmap[i*3 + 0];
  524                 si->si_cmap.g[i] = stic_cmap[i*3 + 1];
  525                 si->si_cmap.b[i] = stic_cmap[i*3 + 2];
  526         }
  527 
  528         si->si_flags |= SI_CMAP_CHANGED | SI_CURSHAPE_CHANGED |
  529             SI_CURCMAP_CHANGED;
  530 
  531         splx(s);
  532 }
  533 
  534 void
  535 stic_clear_screen(struct stic_info *si)
  536 {
  537         u_int32_t *pb;
  538         int i;
  539 
  540         /*
  541          * Do this twice, since the first packet after a reset may be
  542          * silently ignored.
  543          */
  544         for (i = 0; i < 2; i++) {
  545                 pb = (*si->si_pbuf_get)(si);
  546 
  547                 pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
  548                 pb[1] = 0x01ffffff;
  549                 pb[2] = 0;
  550                 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
  551                 pb[4] = (1024 << 2) - 1;
  552                 pb[5] = 0;
  553                 pb[6] = 0;
  554                 pb[7] = (1280 << 19) | ((1024 << 3) + pb[4]);
  555 
  556                 (*si->si_pbuf_post)(si, pb);
  557         }
  558 }
  559 
  560 int
  561 sticioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  562 {
  563         struct stic_info *si;
  564         int s;
  565 
  566         si = v;
  567 
  568         switch (cmd) {
  569         case WSDISPLAYIO_GTYPE:
  570                 *(u_int *)data = si->si_disptype;
  571                 return (0);
  572 
  573         case WSDISPLAYIO_GINFO:
  574 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
  575                 wsd_fbip->height = 1024;
  576                 wsd_fbip->width = 1280;
  577                 wsd_fbip->depth = si->si_depth == 8 ? 8 : 32;
  578                 wsd_fbip->cmsize = CMAP_SIZE;
  579 #undef fbt
  580                 return (0);
  581 
  582         case WSDISPLAYIO_GETCMAP:
  583                 return (stic_get_cmap(si, (struct wsdisplay_cmap *)data));
  584 
  585         case WSDISPLAYIO_PUTCMAP:
  586                 return (stic_set_cmap(si, (struct wsdisplay_cmap *)data));
  587 
  588         case WSDISPLAYIO_SVIDEO:
  589 #if 0 /* XXX later */
  590                 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
  591                 if ((si->si_blanked == 0) ^ turnoff)
  592                         si->si_blanked = turnoff;
  593 #endif
  594                 return (0);
  595 
  596         case WSDISPLAYIO_GVIDEO:
  597 #if 0 /* XXX later */
  598                 *(u_int *)data = si->si_blanked ?
  599                     WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
  600 #endif
  601                 return (0);
  602 
  603         case WSDISPLAYIO_GCURPOS:
  604                 *(struct wsdisplay_curpos *)data = si->si_cursor.cc_pos;
  605                 return (0);
  606 
  607         case WSDISPLAYIO_SCURPOS:
  608                 stic_set_curpos(si, (struct wsdisplay_curpos *)data);
  609                 return (0);
  610 
  611         case WSDISPLAYIO_GCURMAX:
  612                 ((struct wsdisplay_curpos *)data)->x =
  613                 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
  614                 return (0);
  615 
  616         case WSDISPLAYIO_GCURSOR:
  617                 return (stic_get_cursor(si, (struct wsdisplay_cursor *)data));
  618 
  619         case WSDISPLAYIO_SCURSOR:
  620                 return (stic_set_cursor(si, (struct wsdisplay_cursor *)data));
  621 
  622         case WSDISPLAYIO_SMODE:
  623                 si->si_dispmode = *(int *)data;
  624                 if (si->si_dispmode == WSDISPLAYIO_MODE_EMUL) {
  625                         (*si->si_ioctl)(si, STICIO_STOPQ, NULL, flag, p);
  626                         stic_setup_vdac(si);
  627                         s = spltty();
  628                         stic_flush(si);
  629                         splx(s);
  630                         stic_clear_screen(si);
  631                         stic_do_switch(si->si_curscreen);
  632                 }
  633                 return (0);
  634 
  635         case STICIO_RESET:
  636                 stic_reset(si);
  637                 return (0);
  638         }
  639 
  640         if (si->si_ioctl != NULL)
  641                 return ((*si->si_ioctl)(si, cmd, data, flag, p));
  642 
  643         return (EPASSTHROUGH);
  644 }
  645 
  646 void
  647 stic_setup_backing(struct stic_info *si, struct stic_screen *ss)
  648 {
  649         int size;
  650 
  651         size = si->si_consw * si->si_consh * sizeof(*ss->ss_backing);
  652         ss->ss_backing = malloc(size, M_DEVBUF, M_NOWAIT|M_ZERO);
  653 }
  654 
  655 int
  656 stic_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
  657                   int *curxp, int *curyp, long *attrp)
  658 {
  659         struct stic_info *si;
  660         struct stic_screen *ss;
  661 
  662         si = (struct stic_info *)v;
  663         
  664         if ((stic_consscr.ss_flags & SS_ALLOCED) == 0)
  665                 ss = &stic_consscr;
  666         else {
  667                 ss = malloc(sizeof(*ss), M_DEVBUF, M_WAITOK|M_ZERO);
  668         }
  669         stic_setup_backing(si, ss);
  670 
  671         ss->ss_si = si;
  672         ss->ss_flags = SS_ALLOCED | SS_CURENB;
  673 
  674         *cookiep = ss;
  675         *curxp = 0;
  676         *curyp = 0;
  677 
  678         stic_allocattr(ss, 0, 0, 0, attrp);
  679         return (0);
  680 }
  681 
  682 void
  683 stic_free_screen(void *v, void *cookie)
  684 {
  685         struct stic_screen *ss;
  686 
  687         ss = cookie;
  688 
  689 #ifdef DIAGNOSTIC
  690         if (ss == &stic_consscr)
  691                 panic("stic_free_screen: console");
  692         if (ss == ((struct stic_info *)v)->si_curscreen)
  693                 panic("stic_free_screen: freeing current screen");
  694 #endif
  695 
  696         free(ss->ss_backing, M_DEVBUF);
  697         free(ss, M_DEVBUF);
  698 }
  699 
  700 int
  701 stic_show_screen(void *v, void *cookie, int waitok,
  702                  void (*cb)(void *, int, int), void *cbarg)
  703 {
  704         struct stic_info *si;
  705 
  706         si = (struct stic_info *)v;
  707         if (si->si_switchcbarg != NULL)
  708                 return (EAGAIN);
  709         si->si_switchcb = cb;
  710         si->si_switchcbarg = cbarg;
  711 
  712         if (cb != NULL) {
  713                 callout_reset(&si->si_switch_callout, 0, stic_do_switch,
  714                     cookie);
  715                 return (EAGAIN);
  716         }
  717 
  718         stic_do_switch(cookie);
  719         return (0);
  720 }
  721 
  722 void
  723 stic_do_switch(void *cookie)
  724 {
  725         struct stic_screen *ss;
  726         struct stic_info *si;
  727         u_int r, c, nr, nc;
  728         u_int16_t *p, *sp;
  729 
  730         ss = cookie;
  731         si = ss->ss_si;
  732 
  733 #ifdef DIAGNOSTIC
  734         if (ss->ss_backing == NULL)
  735                 panic("stic_do_switch: screen not backed");
  736 #endif
  737 
  738         /* Swap in the new screen, and temporarily disable its backing. */
  739         if (si->si_curscreen != NULL)
  740                 si->si_curscreen->ss_flags ^= SS_ACTIVE;
  741         si->si_curscreen = ss;
  742         ss->ss_flags |= SS_ACTIVE;
  743         sp = ss->ss_backing;
  744         ss->ss_backing = NULL;
  745 
  746         /* 
  747          * We assume that most of the screen is blank and blast it with
  748          * eraserows(), because eraserows() is cheap.
  749          */
  750         nr = si->si_consh;
  751         stic_eraserows(ss, 0, nr, 0);
  752 
  753         nc = si->si_consw;
  754         p = sp;
  755         for (r = 0; r < nr; r++)
  756                 for (c = 0; c < nc; c += 2, p += 2) {
  757                         if ((p[0] & 0xfff0) != 0)
  758                                 stic_putchar(ss, r, c, p[0] >> 8,
  759                                     p[0] & 0x00ff);
  760                         if ((p[1] & 0xfff0) != 0)
  761                                 stic_putchar(ss, r, c + 1, p[1] >> 8,
  762                                     p[1] & 0x00ff);
  763                 }
  764 
  765         /*
  766          * Re-enable the screen's backing, and move the cursor to the
  767          * correct spot.
  768          */
  769         ss->ss_backing = sp;
  770         si->si_cursor.cc_pos.x = ss->ss_curx;
  771         si->si_cursor.cc_pos.y = ss->ss_cury;
  772         stic_set_hwcurpos(si);
  773         si->si_flags |= SI_CURENB_CHANGED;
  774 
  775         /*
  776          * XXX Since we don't yet receive vblank interrupts from the
  777          * PXG, we must flush immediatley.
  778          */
  779         if (si->si_disptype == WSDISPLAY_TYPE_PXG)
  780                 stic_flush(si);
  781 
  782         /* Tell wscons that we're done. */
  783         if (si->si_switchcbarg != NULL) {
  784                 cookie = si->si_switchcbarg;
  785                 si->si_switchcbarg = NULL;
  786                 (*si->si_switchcb)(cookie, 0, 0);
  787         }
  788 }
  789 
  790 int
  791 stic_allocattr(void *cookie, int fg, int bg, int flags, long *attr)
  792 {
  793         long tmp;
  794 
  795         if ((flags & (WSATTR_BLINK | WSATTR_UNDERLINE)) != 0)
  796                 return (EINVAL);
  797 
  798         if ((flags & WSATTR_WSCOLORS) == 0) {
  799                 fg = 7;
  800                 bg = 0;
  801         }
  802 
  803         if ((flags & WSATTR_HILIT) != 0)
  804                 fg += 8;
  805 
  806         tmp = fg | (bg << 4);
  807         *attr = tmp | (tmp << 16);
  808         return (0);
  809 }
  810 
  811 void
  812 stic_erasecols(void *cookie, int row, int col, int num, long attr)
  813 {
  814         struct stic_info *si;
  815         struct stic_screen *ss;
  816         u_int32_t *pb;
  817         u_int i, linewidth;
  818         u_int16_t *p;
  819 
  820         ss = cookie;
  821         si = ss->ss_si;
  822 
  823         if (ss->ss_backing != NULL) {
  824                 p = ss->ss_backing + row * si->si_consw + col;
  825                 for (i = num; i != 0; i--)
  826                         *p++ = (u_int16_t)attr;
  827         }
  828         if ((ss->ss_flags & SS_ACTIVE) == 0)
  829                 return;
  830 
  831         col = (col * si->si_fontw) << 19;
  832         num = (num * si->si_fontw) << 19;
  833         row = row * si->si_fonth;
  834         attr = (attr & 0xf0) >> 4;
  835         linewidth = (si->si_fonth << 2) - 1;
  836         row = (row << 3) + linewidth;
  837 
  838         pb = (*si->si_pbuf_get)(si);
  839 
  840         pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
  841         pb[1] = 0x01ffffff;
  842         pb[2] = 0;
  843         pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
  844         pb[4] = linewidth;
  845         pb[5] = DUPBYTE0(attr);
  846         pb[6] = col | row;
  847         pb[7] = (col + num) | row;
  848 
  849         (*si->si_pbuf_post)(si, pb);
  850 }
  851 
  852 void
  853 stic_eraserows(void *cookie, int row, int num, long attr)
  854 {
  855         struct stic_info *si;
  856         struct stic_screen *ss;
  857         u_int linewidth, i;
  858         u_int32_t *pb;
  859 
  860         ss = cookie;
  861         si = ss->ss_si;
  862 
  863         if (ss->ss_backing != NULL) {
  864                 pb = (u_int32_t *)(ss->ss_backing + row * si->si_consw);
  865                 for (i = si->si_consw * num; i > 0; i -= 2)
  866                         *pb++ = (u_int32_t)attr;
  867         }
  868         if ((ss->ss_flags & SS_ACTIVE) == 0)
  869                 return;
  870 
  871         row *= si->si_fonth;
  872         num *= si->si_fonth;
  873         attr = (attr & 0xf0) >> 4;
  874         linewidth = (num << 2) - 1;
  875         row = (row << 3) + linewidth;
  876 
  877         pb = (*si->si_pbuf_get)(si);
  878 
  879         pb[0] = STAMP_CMD_LINES | STAMP_RGB_CONST | STAMP_LW_PERPACKET;
  880         pb[1] = 0x01ffffff;
  881         pb[2] = 0;
  882         pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY;
  883         pb[4] = linewidth;
  884         pb[5] = DUPBYTE0(attr);
  885         pb[6] = row;
  886         pb[7] = (1280 << 19) | row;
  887 
  888         (*si->si_pbuf_post)(si, pb);
  889 }
  890 
  891 void
  892 stic_copyrows(void *cookie, int src, int dst, int height)
  893 {
  894         struct stic_info *si;
  895         struct stic_screen *ss;
  896         u_int32_t *pb, *pbs;
  897         u_int num, inc, adj;
  898 
  899         ss = cookie;
  900         si = ss->ss_si;
  901 
  902         if (ss->ss_backing != NULL)
  903                 bcopy(ss->ss_backing + src * si->si_consw,
  904                     ss->ss_backing + dst * si->si_consw,
  905                     si->si_consw * sizeof(*ss->ss_backing) * height);
  906         if ((ss->ss_flags & SS_ACTIVE) == 0)
  907                 return;
  908 
  909         /*
  910          * We need to do this in reverse if the destination row is below
  911          * the source.
  912          */
  913         if (dst > src) {
  914                 src += height;
  915                 dst += height;
  916                 inc = -8;
  917                 adj = -1;
  918         } else {
  919                 inc = 8;
  920                 adj = 0;
  921         }
  922 
  923         src = (src * si->si_fonth + adj) << 3;
  924         dst = (dst * si->si_fonth + adj) << 3;
  925         height *= si->si_fonth;
  926 
  927         while (height > 0) {
  928                 num = (height < 255 ? height : 255);
  929                 height -= num;
  930 
  931                 pbs = (*si->si_pbuf_get)(si);
  932                 pb = pbs;
  933 
  934                 pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
  935                 pb[1] = (num << 24) | 0xffffff;
  936                 pb[2] = 0x0;
  937                 pb[3] = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN | 
  938                     STAMP_COPYSPAN_ALIGNED;
  939                 pb[4] = 1; /* linewidth */
  940 
  941                 for (; num != 0; num--, src += inc, dst += inc, pb += 3) {
  942                         pb[5] = 1280 << 3;
  943                         pb[6] = src;
  944                         pb[7] = dst;
  945                 }
  946 
  947                 (*si->si_pbuf_post)(si, pbs);
  948         }
  949 }
  950 
  951 void
  952 stic_copycols(void *cookie, int row, int src, int dst, int num)
  953 {
  954         struct stic_info *si;
  955         struct stic_screen *ss;
  956         u_int height, updword;
  957         u_int32_t *pb, *pbs;
  958 
  959         ss = cookie;
  960         si = ss->ss_si;
  961 
  962         if (ss->ss_backing != NULL)
  963                 bcopy(ss->ss_backing + row * si->si_consw + src,
  964                     ss->ss_backing + row * si->si_consw + dst,
  965                     num * sizeof(*ss->ss_backing));
  966         if ((ss->ss_flags & SS_ACTIVE) == 0)
  967                 return;
  968 
  969         /*
  970          * The stamp reads and writes left -> right only, so we need to
  971          * buffer the span if the source and destination regions overlap
  972          * and the source is left of the destination.
  973          */
  974         updword = STAMP_UPDATE_ENABLE | STAMP_METHOD_COPY | STAMP_SPAN;
  975 
  976         if (src < dst && src + num > dst)
  977                 updword |= STAMP_HALF_BUFF;
  978 
  979         row = (row * si->si_fonth) << 3;
  980         num = (num * si->si_fontw) << 3;
  981         src = row | ((src * si->si_fontw) << 19);
  982         dst = row | ((dst * si->si_fontw) << 19);
  983         height = si->si_fonth;
  984 
  985         pbs = (*si->si_pbuf_get)(si);
  986         pb = pbs;
  987 
  988         pb[0] = STAMP_CMD_COPYSPANS | STAMP_LW_PERPACKET;
  989         pb[1] = (height << 24) | 0xffffff;
  990         pb[2] = 0x0;
  991         pb[3] = updword;
  992         pb[4] = 1; /* linewidth */
  993 
  994         for ( ; height != 0; height--, src += 8, dst += 8, pb += 3) {
  995                 pb[5] = num;
  996                 pb[6] = src;
  997                 pb[7] = dst;
  998         }
  999 
 1000         (*si->si_pbuf_post)(si, pbs);
 1001 }
 1002 
 1003 void
 1004 stic_putchar(void *cookie, int r, int c, u_int uc, long attr)
 1005 {
 1006         struct wsdisplay_font *font;
 1007         struct stic_screen *ss;
 1008         struct stic_info *si;
 1009         u_int i, bgcolor, fgcolor;
 1010         u_int *pb, v1, v2, xya;
 1011         u_short *fr;
 1012 
 1013         ss = cookie;
 1014         si = ss->ss_si;
 1015 
 1016         /* It's cheaper to use erasecols() to blit blanks. */
 1017         if (uc == 0) {
 1018                 stic_erasecols(cookie, r, c, 1, attr);
 1019                 return;
 1020         }
 1021 
 1022         if (ss->ss_backing != NULL)
 1023                 ss->ss_backing[r * si->si_consw + c] =
 1024                     (u_short)((attr & 0xff) | (uc << 8));
 1025         if ((ss->ss_flags & SS_ACTIVE) == 0)
 1026                 return;
 1027 
 1028         font = si->si_font;
 1029         pb = (*si->si_pbuf_get)(si);
 1030 
 1031         /*
 1032          * Create a mask from the glyph.  Squeeze the foreground color
 1033          * through the mask, and then squeeze the background color through
 1034          * the inverted mask.  We may well read outside the glyph when
 1035          * creating the mask, but it's bounded by the hardware so it
 1036          * shouldn't matter a great deal...
 1037          */
 1038         pb[0] = STAMP_CMD_LINES | STAMP_RGB_FLAT | STAMP_XY_PERPRIMATIVE |
 1039             STAMP_LW_PERPRIMATIVE;
 1040         pb[1] = font->fontheight > 16 ? 0x04ffffff : 0x02ffffff;
 1041         pb[2] = 0x0;
 1042         pb[3] = STAMP_UPDATE_ENABLE | STAMP_WE_XYMASK | STAMP_METHOD_COPY;
 1043 
 1044         r *= font->fontheight;
 1045         c *= font->fontwidth;
 1046         uc = (uc - font->firstchar) * font->stride * font->fontheight;
 1047         fr = (u_short *)((caddr_t)font->data + uc);
 1048         bgcolor = DUPBYTE0((attr & 0xf0) >> 4);
 1049         fgcolor = DUPBYTE0(attr & 0x0f);
 1050 
 1051         i = ((font->fontheight > 16 ? 16 : font->fontheight) << 2) - 1;
 1052         v1 = (c << 19) | ((r << 3) + i);
 1053         v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
 1054         xya = XYMASKADDR(si->si_stampw, si->si_stamphm, c, r, 0, 0);
 1055 
 1056         pb[4] = PACK(fr, 0);
 1057         pb[5] = PACK(fr, 2);
 1058         pb[6] = PACK(fr, 4);
 1059         pb[7] = PACK(fr, 6);
 1060         pb[8] = PACK(fr, 8);
 1061         pb[9] = PACK(fr, 10);
 1062         pb[10] = PACK(fr, 12);
 1063         pb[11] = PACK(fr, 14);
 1064         pb[12] = xya;
 1065         pb[13] = v1;
 1066         pb[14] = v2;
 1067         pb[15] = i;
 1068         pb[16] = fgcolor;
 1069 
 1070         pb[17] = ~pb[4];
 1071         pb[18] = ~pb[5];
 1072         pb[19] = ~pb[6];
 1073         pb[20] = ~pb[7];
 1074         pb[21] = ~pb[8];
 1075         pb[22] = ~pb[9];
 1076         pb[23] = ~pb[10];
 1077         pb[24] = ~pb[11];
 1078         pb[25] = xya;
 1079         pb[26] = v1;
 1080         pb[27] = v2;
 1081         pb[28] = i;
 1082         pb[29] = bgcolor;
 1083 
 1084         /* Two more squeezes for the lower part of the character. */
 1085         if (font->fontheight > 16) {
 1086                 i = ((font->fontheight - 16) << 2) - 1;
 1087                 r += 16;
 1088                 v1 = (c << 19) | ((r << 3) + i);
 1089                 v2 = ((c + font->fontwidth) << 19) | (v1 & 0xffff);
 1090 
 1091                 pb[30] = PACK(fr, 16);
 1092                 pb[31] = PACK(fr, 18);
 1093                 pb[32] = PACK(fr, 20);
 1094                 pb[33] = PACK(fr, 22);
 1095                 pb[34] = PACK(fr, 24);
 1096                 pb[35] = PACK(fr, 26);
 1097                 pb[36] = PACK(fr, 28);
 1098                 pb[37] = PACK(fr, 30);
 1099                 pb[38] = xya;
 1100                 pb[39] = v1;
 1101                 pb[40] = v2;
 1102                 pb[41] = i;
 1103                 pb[42] = fgcolor;
 1104 
 1105                 pb[43] = ~pb[30];
 1106                 pb[44] = ~pb[31];
 1107                 pb[45] = ~pb[32];
 1108                 pb[46] = ~pb[33];
 1109                 pb[47] = ~pb[34];
 1110                 pb[48] = ~pb[35];
 1111                 pb[49] = ~pb[36];
 1112                 pb[50] = ~pb[37];
 1113                 pb[51] = xya;
 1114                 pb[52] = v1;
 1115                 pb[53] = v2;
 1116                 pb[54] = i;
 1117                 pb[55] = bgcolor;
 1118         }
 1119 
 1120         (*si->si_pbuf_post)(si, pb);
 1121 }
 1122 
 1123 int
 1124 stic_mapchar(void *cookie, int c, u_int *cp)
 1125 {
 1126         struct stic_info *si;
 1127 
 1128         si = ((struct stic_screen *)cookie)->ss_si;
 1129 
 1130         if (c < si->si_font->firstchar || c == ' ') {
 1131                 *cp = 0;
 1132                 return (0);
 1133         }
 1134 
 1135         if (c - si->si_font->firstchar >= si->si_font->numchars) {
 1136                 *cp = 0;
 1137                 return (0);
 1138         }
 1139 
 1140         *cp = c;
 1141         return (5);
 1142 }
 1143 
 1144 void
 1145 stic_cursor(void *cookie, int on, int row, int col)
 1146 {
 1147         struct stic_screen *ss;
 1148         struct stic_info *si;
 1149         int s;
 1150 
 1151         ss = cookie;
 1152         si = ss->ss_si;
 1153 
 1154         ss->ss_curx = col * si->si_fontw;
 1155         ss->ss_cury = row * si->si_fonth;
 1156 
 1157         s = spltty();
 1158 
 1159         if (on)
 1160                 ss->ss_flags |= SS_CURENB;
 1161         else
 1162                 ss->ss_flags &= ~SS_CURENB;
 1163 
 1164         if ((ss->ss_flags & SS_ACTIVE) != 0) {
 1165                 si->si_cursor.cc_pos.x = ss->ss_curx;
 1166                 si->si_cursor.cc_pos.y = ss->ss_cury;
 1167                 si->si_flags |= SI_CURENB_CHANGED;
 1168                 stic_set_hwcurpos(si);
 1169 
 1170                 /*
 1171                  * XXX Since we don't yet receive vblank interrupts from the
 1172                  * PXG, we must flush immediatley.
 1173                  */
 1174                 if (si->si_disptype == WSDISPLAY_TYPE_PXG)
 1175                         stic_flush(si);
 1176         }
 1177 
 1178         splx(s);
 1179 }
 1180 
 1181 void
 1182 stic_flush(struct stic_info *si)
 1183 {
 1184         volatile u_int32_t *vdac;
 1185         int v;
 1186 
 1187         if ((si->si_flags & SI_ALL_CHANGED) == 0)
 1188                 return;
 1189 
 1190         vdac = si->si_vdac;
 1191         v = si->si_flags;
 1192         si->si_flags &= ~SI_ALL_CHANGED;
 1193 
 1194         if ((v & SI_CURENB_CHANGED) != 0) {
 1195                 SELECT(vdac, BT459_IREG_CCR);
 1196                 if ((si->si_curscreen->ss_flags & SS_CURENB) != 0)
 1197                         REG(vdac, bt_reg) = 0x00c0c0c0;
 1198                 else
 1199                         REG(vdac, bt_reg) = 0x00000000;
 1200                 tc_wmb();
 1201         }
 1202 
 1203         if ((v & SI_CURCMAP_CHANGED) != 0) {
 1204                 u_int8_t *cp;
 1205 
 1206                 cp = si->si_cursor.cc_color;
 1207 
 1208                 SELECT(vdac, BT459_IREG_CCOLOR_2);
 1209                 REG(vdac, bt_reg) = DUPBYTE0(cp[1]);    tc_wmb();
 1210                 REG(vdac, bt_reg) = DUPBYTE0(cp[3]);    tc_wmb();
 1211                 REG(vdac, bt_reg) = DUPBYTE0(cp[5]);    tc_wmb();
 1212                 REG(vdac, bt_reg) = DUPBYTE0(cp[0]);    tc_wmb();
 1213                 REG(vdac, bt_reg) = DUPBYTE0(cp[2]);    tc_wmb();
 1214                 REG(vdac, bt_reg) = DUPBYTE0(cp[4]);    tc_wmb();
 1215         }
 1216 
 1217         if ((v & SI_CURSHAPE_CHANGED) != 0) {
 1218                 u_int8_t *ip, *mp, img, msk;
 1219                 u_int8_t u;
 1220                 int bcnt;
 1221 
 1222                 ip = (u_int8_t *)si->si_cursor.cc_image;
 1223                 mp = (u_int8_t *)si->si_cursor.cc_mask;
 1224 
 1225                 bcnt = 0;
 1226                 SELECT(vdac, BT459_IREG_CRAM_BASE);
 1227                 /* 64 pixel scan line is consisted with 16 byte cursor ram */
 1228                 while (bcnt < CURSOR_MAX_SIZE * 16) {
 1229                         img = *ip++;
 1230                         msk = *mp++;
 1231                         img &= msk;     /* cookie off image */
 1232                         u = (msk & 0x0f) << 4 | (img & 0x0f);
 1233                         REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
 1234                         tc_wmb();
 1235                         u = (msk & 0xf0) | (img & 0xf0) >> 4;
 1236                         REG(vdac, bt_reg) = DUPBYTE0(shuffle[u]);
 1237                         tc_wmb();
 1238                         bcnt += 2;
 1239                 }
 1240         }
 1241 
 1242         if ((v & SI_CMAP_CHANGED) != 0) {
 1243                 struct stic_hwcmap256 *cm;
 1244                 int index;
 1245 
 1246                 cm = &si->si_cmap;
 1247 
 1248                 SELECT(vdac, 0);
 1249                 SELECT(vdac, 0);
 1250                 for (index = 0; index < CMAP_SIZE; index++) {
 1251                         REG(vdac, bt_cmap) = DUPBYTE0(cm->r[index]);
 1252                         tc_wmb();
 1253                         REG(vdac, bt_cmap) = DUPBYTE0(cm->g[index]);
 1254                         tc_wmb();
 1255                         REG(vdac, bt_cmap) = DUPBYTE0(cm->b[index]);
 1256                         tc_wmb();
 1257                 }
 1258         }
 1259 }
 1260 
 1261 int
 1262 stic_get_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
 1263 {
 1264         u_int index = p->index, count = p->count;
 1265         int error;
 1266 
 1267         if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
 1268                 return (EINVAL);
 1269 
 1270         error = copyout(&si->si_cmap.r[index], p->red, count);
 1271         if (error)
 1272                 return error;
 1273         error = copyout(&si->si_cmap.g[index], p->green, count);
 1274         if (error)
 1275                 return error;
 1276         error = copyout(&si->si_cmap.b[index], p->blue, count);
 1277         return error;
 1278 }
 1279 
 1280 int
 1281 stic_set_cmap(struct stic_info *si, struct wsdisplay_cmap *p)
 1282 {
 1283         struct stic_hwcmap256 cmap;
 1284         u_int index, count;
 1285         int s, error;
 1286 
 1287         index = p->index;
 1288         count = p->count;
 1289 
 1290         if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
 1291                 return (EINVAL);
 1292 
 1293         error = copyin(p->red, &cmap.r[index], count);
 1294         if (error)
 1295                 return error;
 1296         error = copyin(p->green, &cmap.g[index], count);
 1297         if (error)
 1298                 return error;
 1299         error = copyin(p->blue, &cmap.b[index], count);
 1300         if (error)
 1301                 return error;
 1302 
 1303         s = spltty();
 1304         memcpy(&si->si_cmap.r[index], &cmap.r[index], count);
 1305         memcpy(&si->si_cmap.g[index], &cmap.g[index], count);
 1306         memcpy(&si->si_cmap.b[index], &cmap.b[index], count);
 1307         si->si_flags |= SI_CMAP_CHANGED;
 1308         splx(s);
 1309 
 1310         /*
 1311          * XXX Since we don't yet receive vblank interrupts from the PXG, we
 1312          * must flush immediatley.
 1313          */
 1314         if (si->si_disptype == WSDISPLAY_TYPE_PXG)
 1315                 stic_flush(si);
 1316 
 1317         return (0);
 1318 }
 1319 
 1320 int
 1321 stic_set_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
 1322 {
 1323 #define cc (&si->si_cursor)
 1324         u_int v, index = 0, count = 0, icount = 0;
 1325         struct stic_screen *ss;
 1326         uint8_t r[2], g[2], b[2], image[512], mask[512];
 1327         int s, error;
 1328 
 1329         v = p->which;
 1330         ss = si->si_curscreen;
 1331         if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
 1332                 index = p->cmap.index;
 1333                 count = p->cmap.count;
 1334                 if (index >= 2 || (index + count) > 2)                  
 1335                         return (EINVAL);
 1336                 error = copyin(p->cmap.red, &r[index], count);
 1337                 if (error)
 1338                         return error;
 1339                 error = copyin(p->cmap.green, &g[index], count);
 1340                 if (error)
 1341                         return error;
 1342                 error = copyin(p->cmap.blue, &b[index], count);
 1343                 if (error)
 1344                         return error;
 1345         }
 1346         if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
 1347                 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
 1348                         return (EINVAL);
 1349                 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
 1350                 error = copyin(p->image, image, icount);
 1351                 if (error)
 1352                         return error;
 1353                 error = copyin(p->mask, mask, icount);
 1354                 if (error)
 1355                         return error;
 1356         }
 1357         if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOCUR)) != 0) {
 1358                 if (v & WSDISPLAY_CURSOR_DOCUR)
 1359                         cc->cc_hot = p->hot;
 1360                 if (v & WSDISPLAY_CURSOR_DOPOS)
 1361                         stic_set_curpos(si, &p->pos);
 1362         }
 1363 
 1364         s = spltty();
 1365         if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) {
 1366                 if (p->enable)
 1367                         ss->ss_flags |= SS_CURENB;
 1368                 else
 1369                         ss->ss_flags &= ~SS_CURENB;
 1370                 si->si_flags |= SI_CURENB_CHANGED;
 1371         }
 1372         if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) {
 1373                 memcpy(&cc->cc_color[index], &r[index], count);
 1374                 memcpy(&cc->cc_color[index + 2], &g[index], count);
 1375                 memcpy(&cc->cc_color[index + 4], &b[index], count);
 1376                 si->si_flags |= SI_CURCMAP_CHANGED;
 1377         }
 1378         if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) {
 1379                 memset(cc->cc_image, 0, sizeof cc->cc_image);
 1380                 memcpy(cc->cc_image, image, icount);
 1381                 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
 1382                 memcpy(cc->cc_mask, mask, icount);
 1383                 si->si_flags |= SI_CURSHAPE_CHANGED;
 1384         }
 1385         splx(s);
 1386 
 1387         /*
 1388          * XXX Since we don't yet receive vblank interrupts from the PXG, we
 1389          * must flush immediatley.
 1390          */
 1391         if (si->si_disptype == WSDISPLAY_TYPE_PXG)
 1392                 stic_flush(si);
 1393 
 1394         return (0);
 1395 #undef cc
 1396 }
 1397 
 1398 int
 1399 stic_get_cursor(struct stic_info *si, struct wsdisplay_cursor *p)
 1400 {
 1401 
 1402         /* XXX */
 1403         return (EPASSTHROUGH);
 1404 }
 1405 
 1406 void
 1407 stic_set_curpos(struct stic_info *si, struct wsdisplay_curpos *curpos)
 1408 {
 1409         int x, y;
 1410 
 1411         x = curpos->x;
 1412         y = curpos->y;
 1413 
 1414         if (y < 0)
 1415                 y = 0;
 1416         else if (y > 1023)
 1417                 y = 1023;
 1418         if (x < 0)
 1419                 x = 0;
 1420         else if (x > 1279)
 1421                 x = 1279;
 1422 
 1423         si->si_cursor.cc_pos.x = x;
 1424         si->si_cursor.cc_pos.y = y;
 1425         stic_set_hwcurpos(si);
 1426 }
 1427 
 1428 void
 1429 stic_set_hwcurpos(struct stic_info *si)
 1430 {
 1431         volatile u_int32_t *vdac;
 1432         int x, y, s;
 1433 
 1434         vdac = si->si_vdac;
 1435 
 1436         x = si->si_cursor.cc_pos.x - si->si_cursor.cc_hot.x;
 1437         y = si->si_cursor.cc_pos.y - si->si_cursor.cc_hot.y;
 1438         x += STIC_MAGIC_X;
 1439         y += STIC_MAGIC_Y;
 1440 
 1441         s = spltty();
 1442         SELECT(vdac, BT459_IREG_CURSOR_X_LOW);
 1443         REG(vdac, bt_reg) = DUPBYTE0(x); tc_wmb();
 1444         REG(vdac, bt_reg) = DUPBYTE1(x); tc_wmb();
 1445         REG(vdac, bt_reg) = DUPBYTE0(y); tc_wmb();
 1446         REG(vdac, bt_reg) = DUPBYTE1(y); tc_wmb();
 1447         splx(s);
 1448 }
 1449 
 1450 /*
 1451  * STIC control inteface.  We have a separate device for mapping the board,
 1452  * because access to the DMA engine means that it's possible to circumvent
 1453  * the securelevel mechanism.
 1454  */
 1455 int
 1456 sticopen(dev_t dev, int flag, int mode, struct proc *p)
 1457 {
 1458         struct stic_info *si;
 1459         int s;
 1460 
 1461         if (securelevel > 0)
 1462                 return (EPERM);
 1463         if (minor(dev) >= STIC_MAXDV)
 1464                 return (ENXIO);
 1465         if ((si = stic_info[minor(dev)]) == NULL)
 1466                 return (ENXIO);
 1467 
 1468         s = spltty();
 1469         if ((si->si_flags & SI_DVOPEN) != 0) {
 1470                 splx(s);
 1471                 return (EBUSY);
 1472         }
 1473         si->si_flags |= SI_DVOPEN;
 1474         splx(s);
 1475 
 1476         return (0);
 1477 }
 1478 
 1479 int
 1480 sticclose(dev_t dev, int flag, int mode, struct proc *p)
 1481 {
 1482         struct stic_info *si;
 1483         int s;
 1484 
 1485         si = stic_info[minor(dev)];
 1486         s = spltty();
 1487         si->si_flags &= ~SI_DVOPEN;
 1488         splx(s);
 1489 
 1490         return (0);
 1491 }
 1492 
 1493 paddr_t
 1494 sticmmap(dev_t dev, off_t offset, int prot)
 1495 {
 1496         struct stic_info *si;
 1497         struct stic_xmap *sxm;
 1498         paddr_t pa;
 1499 
 1500         si = stic_info[minor(dev)];
 1501         sxm = NULL;
 1502 
 1503         if (securelevel > 0)
 1504                 return (-1L);
 1505         if (si->si_dispmode != WSDISPLAYIO_MODE_MAPPED) 
 1506                 return (-1L);
 1507 
 1508         if (offset < 0)
 1509                 return ((paddr_t)-1L);
 1510 
 1511         if (offset < sizeof(sxm->sxm_stic)) {
 1512                 pa = STIC_KSEG_TO_PHYS(si->si_stic);
 1513                 return (machine_btop(pa + offset));
 1514         }
 1515         offset -= sizeof(sxm->sxm_stic);
 1516 
 1517         if (offset < sizeof(sxm->sxm_poll)) {
 1518                 pa = STIC_KSEG_TO_PHYS(si->si_slotbase);
 1519                 return (machine_btop(pa + offset));
 1520         }
 1521         offset -= sizeof(sxm->sxm_poll);
 1522 
 1523         if (offset < si->si_buf_size)
 1524                 return (machine_btop(si->si_buf_phys + offset));
 1525 
 1526         return ((paddr_t)-1L);
 1527 }

Cache object: 073a86f5fdd022f03c60f541342c7654


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