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/cfb.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: cfb.c,v 1.44 2003/12/20 07:10:00 nisimura Exp $ */
    2 
    3 /*
    4  * Copyright (c) 1998, 1999 Tohru Nishimura.  All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by Tohru Nishimura
   17  *      for the NetBSD Project.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/cdefs.h>
   34 __KERNEL_RCSID(0, "$NetBSD: cfb.c,v 1.44 2003/12/20 07:10:00 nisimura 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/buf.h>
   42 #include <sys/ioctl.h>
   43 
   44 #include <machine/bus.h>
   45 #include <machine/intr.h>
   46 
   47 #include <dev/wscons/wsconsio.h>
   48 #include <dev/wscons/wsdisplayvar.h>
   49 
   50 #include <dev/rasops/rasops.h>
   51 #include <dev/wsfont/wsfont.h>
   52 
   53 #include <dev/tc/tcvar.h>
   54 #include <dev/ic/bt459reg.h>    
   55 
   56 #include <uvm/uvm_extern.h>
   57 
   58 #if defined(pmax)
   59 #define machine_btop(x) mips_btop(MIPS_KSEG1_TO_PHYS(x))
   60 #endif
   61 
   62 #if defined(alpha)
   63 #define machine_btop(x) alpha_btop(ALPHA_K0SEG_TO_PHYS(x))
   64 #endif
   65 
   66 /*
   67  * N.B., Bt459 registers are 8bit width.  Some of TC framebuffers have
   68  * obscure register layout such as 2nd and 3rd Bt459 registers are
   69  * adjacent each other in a word, i.e.,
   70  *      struct bt459triplet {
   71  *              struct {
   72  *                      u_int8_t u0;
   73  *                      u_int8_t u1;
   74  *                      u_int8_t u2;
   75  *                      unsigned :8;
   76  *              } bt_lo;
   77  *              ...
   78  * Although CX has single Bt459, 32bit R/W can be done w/o any trouble.
   79  *      struct bt459reg {
   80  *                 u_int32_t       bt_lo;
   81  *                 u_int32_t       bt_hi;
   82  *                 u_int32_t       bt_reg;
   83  *                 u_int32_t       bt_cmap;
   84  *      };
   85  */
   86 
   87 /* Bt459 hardware registers, memory-mapped in 32bit stride */
   88 #define bt_lo   0x0
   89 #define bt_hi   0x4
   90 #define bt_reg  0x8
   91 #define bt_cmap 0xc
   92 
   93 #define REGWRITE32(p,i,v) do {                                  \
   94         *(volatile u_int32_t *)((p) + (i)) = (v); tc_wmb();     \
   95     } while (0)
   96 #define VDACSELECT(p,r) do {                                    \
   97         REGWRITE32(p, bt_lo, 0xff & (r));                       \
   98         REGWRITE32(p, bt_hi, 0x0f & ((r)>>8));                  \
   99    } while (0)
  100 
  101 struct hwcmap256 {
  102 #define CMAP_SIZE       256     /* 256 R/G/B entries */
  103         u_int8_t r[CMAP_SIZE];
  104         u_int8_t g[CMAP_SIZE];
  105         u_int8_t b[CMAP_SIZE];
  106 };
  107 
  108 struct hwcursor64 {
  109         struct wsdisplay_curpos cc_pos;
  110         struct wsdisplay_curpos cc_hot;
  111         struct wsdisplay_curpos cc_size;
  112         struct wsdisplay_curpos cc_magic;
  113 #define CURSOR_MAX_SIZE 64
  114         u_int8_t cc_color[6];
  115         u_int64_t cc_image[CURSOR_MAX_SIZE];
  116         u_int64_t cc_mask[CURSOR_MAX_SIZE];
  117 };
  118 
  119 struct cfb_softc {
  120         struct device sc_dev;
  121         vaddr_t sc_vaddr;
  122         size_t sc_size;
  123         struct rasops_info *sc_ri;
  124         struct hwcmap256 sc_cmap;       /* software copy of colormap */
  125         struct hwcursor64 sc_cursor;    /* software copy of cursor */
  126         int sc_blanked;
  127         int sc_curenb;                  /* cursor sprite enabled */
  128         int sc_changed;                 /* need update of hardware */
  129 #define WSDISPLAY_CMAP_DOLUT    0x20
  130         int nscreens;
  131 };
  132 
  133 #define CX_MAGIC_X      220
  134 #define CX_MAGIC_Y      35
  135 
  136 #define CX_FB_OFFSET    0x000000
  137 #define CX_FB_SIZE      0x100000
  138 #define CX_BT459_OFFSET 0x200000
  139 #define CX_OFFSET_IREQ  0x300000        /* Interrupt req. control */
  140 
  141 static int  cfbmatch(struct device *, struct cfdata *, void *);
  142 static void cfbattach(struct device *, struct device *, void *);
  143 
  144 CFATTACH_DECL(cfb, sizeof(struct cfb_softc),
  145     cfbmatch, cfbattach, NULL, NULL);
  146 
  147 static void cfb_common_init(struct rasops_info *);
  148 static struct rasops_info cfb_console_ri;
  149 static tc_addr_t cfb_consaddr;
  150 
  151 static struct wsscreen_descr cfb_stdscreen = {
  152         "std", 0, 0,
  153         0, /* textops */
  154         0, 0,
  155         WSSCREEN_REVERSE
  156 };
  157 
  158 static const struct wsscreen_descr *_cfb_scrlist[] = {
  159         &cfb_stdscreen,
  160 };
  161 
  162 static const struct wsscreen_list cfb_screenlist = {
  163         sizeof(_cfb_scrlist) / sizeof(struct wsscreen_descr *), _cfb_scrlist
  164 };
  165 
  166 static int      cfbioctl(void *, u_long, caddr_t, int, struct proc *);
  167 static paddr_t  cfbmmap(void *, off_t, int);
  168 
  169 static int      cfb_alloc_screen(void *, const struct wsscreen_descr *,
  170                                       void **, int *, int *, long *);
  171 static void     cfb_free_screen(void *, void *);
  172 static int      cfb_show_screen(void *, void *, int,
  173                                      void (*) (void *, int, int), void *);
  174 
  175 static const struct wsdisplay_accessops cfb_accessops = {
  176         cfbioctl,
  177         cfbmmap,
  178         cfb_alloc_screen,
  179         cfb_free_screen,
  180         cfb_show_screen,
  181         0 /* load_font */
  182 };
  183 
  184 int  cfb_cnattach(tc_addr_t);
  185 static int  cfbintr(void *);
  186 static void cfbhwinit(caddr_t);
  187 static void cfb_cmap_init(struct cfb_softc *);
  188 
  189 static int  get_cmap(struct cfb_softc *, struct wsdisplay_cmap *);
  190 static int  set_cmap(struct cfb_softc *, struct wsdisplay_cmap *);
  191 static int  set_cursor(struct cfb_softc *, struct wsdisplay_cursor *);
  192 static int  get_cursor(struct cfb_softc *, struct wsdisplay_cursor *);
  193 static void set_curpos(struct cfb_softc *, struct wsdisplay_curpos *);
  194 
  195 /*
  196  * Compose 2 bit/pixel cursor image.  Bit order will be reversed.
  197  *   M M M M I I I I            M I M I M I M I
  198  *      [ before ]                 [ after ]
  199  *   3 2 1 0 3 2 1 0            0 0 1 1 2 2 3 3
  200  *   7 6 5 4 7 6 5 4            4 4 5 5 6 6 7 7
  201  */
  202 static const u_int8_t shuffle[256] = {
  203         0x00, 0x40, 0x10, 0x50, 0x04, 0x44, 0x14, 0x54,
  204         0x01, 0x41, 0x11, 0x51, 0x05, 0x45, 0x15, 0x55,
  205         0x80, 0xc0, 0x90, 0xd0, 0x84, 0xc4, 0x94, 0xd4,
  206         0x81, 0xc1, 0x91, 0xd1, 0x85, 0xc5, 0x95, 0xd5,
  207         0x20, 0x60, 0x30, 0x70, 0x24, 0x64, 0x34, 0x74,
  208         0x21, 0x61, 0x31, 0x71, 0x25, 0x65, 0x35, 0x75,
  209         0xa0, 0xe0, 0xb0, 0xf0, 0xa4, 0xe4, 0xb4, 0xf4,
  210         0xa1, 0xe1, 0xb1, 0xf1, 0xa5, 0xe5, 0xb5, 0xf5,
  211         0x08, 0x48, 0x18, 0x58, 0x0c, 0x4c, 0x1c, 0x5c,
  212         0x09, 0x49, 0x19, 0x59, 0x0d, 0x4d, 0x1d, 0x5d,
  213         0x88, 0xc8, 0x98, 0xd8, 0x8c, 0xcc, 0x9c, 0xdc,
  214         0x89, 0xc9, 0x99, 0xd9, 0x8d, 0xcd, 0x9d, 0xdd,
  215         0x28, 0x68, 0x38, 0x78, 0x2c, 0x6c, 0x3c, 0x7c,
  216         0x29, 0x69, 0x39, 0x79, 0x2d, 0x6d, 0x3d, 0x7d,
  217         0xa8, 0xe8, 0xb8, 0xf8, 0xac, 0xec, 0xbc, 0xfc,
  218         0xa9, 0xe9, 0xb9, 0xf9, 0xad, 0xed, 0xbd, 0xfd,
  219         0x02, 0x42, 0x12, 0x52, 0x06, 0x46, 0x16, 0x56,
  220         0x03, 0x43, 0x13, 0x53, 0x07, 0x47, 0x17, 0x57,
  221         0x82, 0xc2, 0x92, 0xd2, 0x86, 0xc6, 0x96, 0xd6,
  222         0x83, 0xc3, 0x93, 0xd3, 0x87, 0xc7, 0x97, 0xd7,
  223         0x22, 0x62, 0x32, 0x72, 0x26, 0x66, 0x36, 0x76,
  224         0x23, 0x63, 0x33, 0x73, 0x27, 0x67, 0x37, 0x77,
  225         0xa2, 0xe2, 0xb2, 0xf2, 0xa6, 0xe6, 0xb6, 0xf6,
  226         0xa3, 0xe3, 0xb3, 0xf3, 0xa7, 0xe7, 0xb7, 0xf7,
  227         0x0a, 0x4a, 0x1a, 0x5a, 0x0e, 0x4e, 0x1e, 0x5e,
  228         0x0b, 0x4b, 0x1b, 0x5b, 0x0f, 0x4f, 0x1f, 0x5f,
  229         0x8a, 0xca, 0x9a, 0xda, 0x8e, 0xce, 0x9e, 0xde,
  230         0x8b, 0xcb, 0x9b, 0xdb, 0x8f, 0xcf, 0x9f, 0xdf,
  231         0x2a, 0x6a, 0x3a, 0x7a, 0x2e, 0x6e, 0x3e, 0x7e,
  232         0x2b, 0x6b, 0x3b, 0x7b, 0x2f, 0x6f, 0x3f, 0x7f,
  233         0xaa, 0xea, 0xba, 0xfa, 0xae, 0xee, 0xbe, 0xfe,
  234         0xab, 0xeb, 0xbb, 0xfb, 0xaf, 0xef, 0xbf, 0xff,
  235 };
  236 
  237 static int
  238 cfbmatch(parent, match, aux)
  239         struct device *parent;
  240         struct cfdata *match;
  241         void *aux;
  242 {
  243         struct tc_attach_args *ta = aux;
  244 
  245         if (strncmp("PMAG-BA ", ta->ta_modname, TC_ROM_LLEN) != 0)
  246                 return (0);
  247 
  248         return (1);
  249 }
  250 
  251 static void
  252 cfbattach(parent, self, aux)
  253         struct device *parent, *self;
  254         void *aux;
  255 {
  256         struct cfb_softc *sc = (struct cfb_softc *)self;
  257         struct tc_attach_args *ta = aux;
  258         struct rasops_info *ri;
  259         struct wsemuldisplaydev_attach_args waa;
  260         int console;
  261 
  262         console = (ta->ta_addr == cfb_consaddr);
  263         if (console) {
  264                 sc->sc_ri = ri = &cfb_console_ri;
  265                 sc->nscreens = 1;
  266         }
  267         else {
  268                 MALLOC(ri, struct rasops_info *, sizeof(struct rasops_info),
  269                         M_DEVBUF, M_NOWAIT);
  270                 if (ri == NULL) {
  271                         printf(": can't alloc memory\n");
  272                         return;
  273                 }
  274                 memset(ri, 0, sizeof(struct rasops_info));
  275 
  276                 ri->ri_hw = (void *)ta->ta_addr;
  277                 cfb_common_init(ri);
  278                 sc->sc_ri = ri;
  279         }
  280         printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth);
  281 
  282         cfb_cmap_init(sc);
  283 
  284         sc->sc_vaddr = ta->ta_addr;
  285         sc->sc_cursor.cc_magic.x = CX_MAGIC_X;
  286         sc->sc_cursor.cc_magic.y = CX_MAGIC_Y;
  287         sc->sc_blanked = sc->sc_curenb = 0;
  288 
  289         tc_intr_establish(parent, ta->ta_cookie, IPL_TTY, cfbintr, sc);
  290 
  291         /* clear any pending interrupts */
  292         *(volatile u_int8_t *)((caddr_t)ri->ri_hw + CX_OFFSET_IREQ) = 0;
  293 
  294         waa.console = console;
  295         waa.scrdata = &cfb_screenlist;
  296         waa.accessops = &cfb_accessops;
  297         waa.accesscookie = sc;
  298 
  299         config_found(self, &waa, wsemuldisplaydevprint);
  300 }
  301 
  302 static void
  303 cfb_cmap_init(sc)
  304         struct cfb_softc *sc;
  305 {
  306         struct hwcmap256 *cm;
  307         const u_int8_t *p;
  308         int index;
  309 
  310         cm = &sc->sc_cmap;
  311         p = rasops_cmap;
  312         for (index = 0; index < CMAP_SIZE; index++, p += 3) {
  313                 cm->r[index] = p[0];
  314                 cm->g[index] = p[1];
  315                 cm->b[index] = p[2];
  316         }
  317 }
  318 
  319 static void
  320 cfb_common_init(ri)
  321         struct rasops_info *ri;
  322 {
  323         caddr_t base;
  324         int cookie;
  325 
  326         base = (caddr_t)ri->ri_hw;
  327 
  328         /* initialize colormap and cursor hardware */
  329         cfbhwinit(base);
  330 
  331         ri->ri_flg = RI_CENTER;
  332         ri->ri_depth = 8;
  333         ri->ri_width = 1024;
  334         ri->ri_height = 864;
  335         ri->ri_stride = 1024;
  336         ri->ri_bits = base + CX_FB_OFFSET;
  337 
  338         /* clear the screen */
  339         memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height);
  340 
  341         wsfont_init();
  342         /* prefer 12 pixel wide font */
  343         cookie = wsfont_find(NULL, 12, 0, 0, WSDISPLAY_FONTORDER_L2R,
  344             WSDISPLAY_FONTORDER_L2R);
  345         if (cookie <= 0)
  346                 cookie = wsfont_find(NULL, 0, 0, 0, WSDISPLAY_FONTORDER_L2R,
  347                     WSDISPLAY_FONTORDER_L2R);
  348         if (cookie <= 0) {
  349                 printf("cfb: font table is empty\n");
  350                 return;
  351         }
  352 
  353         if (wsfont_lock(cookie, &ri->ri_font)) {
  354                 printf("cfb: couldn't lock font\n");
  355                 return;
  356         }
  357         ri->ri_wsfcookie = cookie;
  358 
  359         rasops_init(ri, 34, 80);
  360 
  361         /* XXX shouldn't be global */
  362         cfb_stdscreen.nrows = ri->ri_rows;
  363         cfb_stdscreen.ncols = ri->ri_cols;
  364         cfb_stdscreen.textops = &ri->ri_ops;
  365         cfb_stdscreen.capabilities = ri->ri_caps;
  366 }
  367 
  368 static int
  369 cfbioctl(v, cmd, data, flag, p)
  370         void *v;
  371         u_long cmd;
  372         caddr_t data;
  373         int flag;
  374         struct proc *p;
  375 {
  376         struct cfb_softc *sc = v;
  377         struct rasops_info *ri = sc->sc_ri;
  378         int turnoff, s;
  379 
  380         switch (cmd) {
  381         case WSDISPLAYIO_GTYPE:
  382                 *(u_int *)data = WSDISPLAY_TYPE_CFB;
  383                 return (0);
  384 
  385         case WSDISPLAYIO_GINFO:
  386 #define wsd_fbip ((struct wsdisplay_fbinfo *)data)
  387                 wsd_fbip->height = ri->ri_height;
  388                 wsd_fbip->width = ri->ri_width;
  389                 wsd_fbip->depth = ri->ri_depth;
  390                 wsd_fbip->cmsize = CMAP_SIZE;
  391 #undef fbt
  392                 return (0);
  393 
  394         case WSDISPLAYIO_GETCMAP:
  395                 return get_cmap(sc, (struct wsdisplay_cmap *)data);
  396 
  397         case WSDISPLAYIO_PUTCMAP:
  398                 return set_cmap(sc, (struct wsdisplay_cmap *)data);
  399 
  400         case WSDISPLAYIO_SVIDEO:
  401                 turnoff = *(int *)data == WSDISPLAYIO_VIDEO_OFF;
  402                 if ((sc->sc_blanked == 0) ^ turnoff) {
  403                         sc->sc_blanked = turnoff;
  404                         /* XXX later XXX */
  405                 }
  406                 return (0);
  407 
  408         case WSDISPLAYIO_GVIDEO:
  409                 *(u_int *)data = sc->sc_blanked ?
  410                     WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON;
  411                 return (0);
  412 
  413         case WSDISPLAYIO_GCURPOS:
  414                 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos;
  415                 return (0);
  416 
  417         case WSDISPLAYIO_SCURPOS:
  418                 s = spltty();
  419                 set_curpos(sc, (struct wsdisplay_curpos *)data);
  420                 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS;
  421                 splx(s);
  422                 return (0);
  423 
  424         case WSDISPLAYIO_GCURMAX:
  425                 ((struct wsdisplay_curpos *)data)->x =
  426                 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE;
  427                 return (0);
  428 
  429         case WSDISPLAYIO_GCURSOR:
  430                 return get_cursor(sc, (struct wsdisplay_cursor *)data);
  431 
  432         case WSDISPLAYIO_SCURSOR:
  433                 return set_cursor(sc, (struct wsdisplay_cursor *)data);
  434 
  435         case WSDISPLAYIO_SMODE:
  436                 if (*(int *)data == WSDISPLAYIO_MODE_EMUL) {
  437                         s = spltty();
  438                         cfb_cmap_init(sc);
  439                         sc->sc_curenb = 0;
  440                         sc->sc_blanked = 0;
  441                         sc->sc_changed |= (WSDISPLAY_CURSOR_DOCUR |
  442                             WSDISPLAY_CMAP_DOLUT);
  443                         splx(s);
  444                 }
  445                 return (0);
  446         }
  447         return EPASSTHROUGH;
  448 }
  449 
  450 paddr_t
  451 cfbmmap(v, offset, prot)
  452         void *v;
  453         off_t offset;
  454         int prot;
  455 {
  456         struct cfb_softc *sc = v;
  457 
  458         if (offset >= CX_FB_SIZE || offset < 0)
  459                 return (-1);
  460         return machine_btop(sc->sc_vaddr + CX_FB_OFFSET + offset);
  461 }
  462 
  463 static int
  464 cfb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
  465         void *v;
  466         const struct wsscreen_descr *type;
  467         void **cookiep;
  468         int *curxp, *curyp;
  469         long *attrp;
  470 {
  471         struct cfb_softc *sc = v;
  472         struct rasops_info *ri = sc->sc_ri;
  473         long defattr;
  474 
  475         if (sc->nscreens > 0)
  476                 return (ENOMEM);
  477 
  478         *cookiep = ri;   /* one and only for now */
  479         *curxp = 0;
  480         *curyp = 0;
  481         (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
  482         *attrp = defattr;
  483         sc->nscreens++;
  484         return (0);
  485 }
  486 
  487 static void
  488 cfb_free_screen(v, cookie)
  489         void *v;
  490         void *cookie;
  491 {
  492         struct cfb_softc *sc = v;
  493 
  494         if (sc->sc_ri == &cfb_console_ri)
  495                 panic("cfb_free_screen: console");
  496 
  497         sc->nscreens--;
  498 }
  499 
  500 static int
  501 cfb_show_screen(v, cookie, waitok, cb, cbarg)
  502         void *v;
  503         void *cookie;
  504         int waitok;
  505         void (*cb)(void *, int, int);
  506         void *cbarg;
  507 {
  508 
  509         return (0);
  510 }
  511 
  512 /* EXPORT */ int
  513 cfb_cnattach(addr)
  514         tc_addr_t addr;
  515 {
  516         struct rasops_info *ri;
  517         long defattr;
  518 
  519         ri = &cfb_console_ri;
  520         ri->ri_hw = (void *)addr;
  521         cfb_common_init(ri);
  522         (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr);
  523         wsdisplay_cnattach(&cfb_stdscreen, ri, 0, 0, defattr);
  524         cfb_consaddr = addr;
  525         return(0);
  526 }
  527 
  528 static int
  529 cfbintr(arg)
  530         void *arg;
  531 {
  532         struct cfb_softc *sc = arg;
  533         caddr_t base, vdac;
  534         int v;
  535         
  536         base = (caddr_t)sc->sc_ri->ri_hw;
  537         *(u_int8_t *)(base + CX_OFFSET_IREQ) = 0;
  538         if (sc->sc_changed == 0)
  539                 return (1);
  540 
  541         vdac = base + CX_BT459_OFFSET;
  542         v = sc->sc_changed;
  543         if (v & WSDISPLAY_CURSOR_DOCUR) {
  544                 VDACSELECT(vdac, BT459_IREG_CCR);
  545                 REGWRITE32(vdac, bt_reg, (sc->sc_curenb) ? 0xc0 : 0x00);
  546         }
  547         if (v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) {
  548                 int x, y;
  549 
  550                 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x;
  551                 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y;
  552 
  553                 x += sc->sc_cursor.cc_magic.x;
  554                 y += sc->sc_cursor.cc_magic.y;
  555 
  556                 VDACSELECT(vdac, BT459_IREG_CURSOR_X_LOW);
  557                 REGWRITE32(vdac, bt_reg, x);    
  558                 REGWRITE32(vdac, bt_reg, x >> 8);
  559                 REGWRITE32(vdac, bt_reg, y);
  560                 REGWRITE32(vdac, bt_reg, y >> 8);
  561         }
  562         if (v & WSDISPLAY_CURSOR_DOCMAP) {
  563                 u_int8_t *cp = sc->sc_cursor.cc_color;
  564 
  565                 VDACSELECT(vdac, BT459_IREG_CCOLOR_2);
  566                 REGWRITE32(vdac, bt_reg, cp[1]);
  567                 REGWRITE32(vdac, bt_reg, cp[3]);
  568                 REGWRITE32(vdac, bt_reg, cp[5]);
  569 
  570                 REGWRITE32(vdac, bt_reg, cp[0]);
  571                 REGWRITE32(vdac, bt_reg, cp[2]);
  572                 REGWRITE32(vdac, bt_reg, cp[4]);
  573         }
  574         if (v & WSDISPLAY_CURSOR_DOSHAPE) {
  575                 u_int8_t *ip, *mp, img, msk;
  576                 u_int8_t u;
  577                 int bcnt;
  578 
  579                 ip = (u_int8_t *)sc->sc_cursor.cc_image;
  580                 mp = (u_int8_t *)sc->sc_cursor.cc_mask;
  581 
  582                 bcnt = 0;
  583                 VDACSELECT(vdac, BT459_IREG_CRAM_BASE+0);
  584                 /* 64 pixel scan line is consisted with 16 byte cursor ram */
  585                 while (bcnt < sc->sc_cursor.cc_size.y * 16) {
  586                         /* pad right half 32 pixel when smaller than 33 */
  587                         if ((bcnt & 0x8) && sc->sc_cursor.cc_size.x < 33) {
  588                                 REGWRITE32(vdac, bt_reg, 0);
  589                                 REGWRITE32(vdac, bt_reg, 0);
  590                         }
  591                         else {
  592                                 img = *ip++;
  593                                 msk = *mp++;
  594                                 img &= msk;     /* cookie off image */
  595                                 u = (msk & 0x0f) << 4 | (img & 0x0f);
  596                                 REGWRITE32(vdac, bt_reg, shuffle[u]);
  597                                 u = (msk & 0xf0) | (img & 0xf0) >> 4;
  598                                 REGWRITE32(vdac, bt_reg, shuffle[u]);
  599                         }
  600                         bcnt += 2;
  601                 }
  602                 /* pad unoccupied scan lines */
  603                 while (bcnt < CURSOR_MAX_SIZE * 16) {
  604                         REGWRITE32(vdac, bt_reg, 0);
  605                         REGWRITE32(vdac, bt_reg, 0);
  606                         bcnt += 2;
  607                 }
  608         }
  609         if (v & WSDISPLAY_CMAP_DOLUT) {
  610                 struct hwcmap256 *cm = &sc->sc_cmap;
  611                 int index;
  612 
  613                 VDACSELECT(vdac, 0);
  614                 for (index = 0; index < CMAP_SIZE; index++) {
  615                         REGWRITE32(vdac, bt_cmap, cm->r[index]);
  616                         REGWRITE32(vdac, bt_cmap, cm->g[index]);
  617                         REGWRITE32(vdac, bt_cmap, cm->b[index]);
  618                 }
  619         }
  620         sc->sc_changed = 0;
  621         return (1);
  622 }
  623 
  624 static void
  625 cfbhwinit(cfbbase)
  626         caddr_t cfbbase;
  627 {
  628         caddr_t vdac = cfbbase + CX_BT459_OFFSET;
  629         const u_int8_t *p;
  630         int i;
  631 
  632         VDACSELECT(vdac, BT459_IREG_COMMAND_0);
  633         REGWRITE32(vdac, bt_reg, 0x40); /* CMD0 */
  634         REGWRITE32(vdac, bt_reg, 0x0);  /* CMD1 */
  635         REGWRITE32(vdac, bt_reg, 0xc0); /* CMD2 */
  636         REGWRITE32(vdac, bt_reg, 0xff); /* PRM */
  637         REGWRITE32(vdac, bt_reg, 0);    /* 205 */
  638         REGWRITE32(vdac, bt_reg, 0x0);  /* PBM */
  639         REGWRITE32(vdac, bt_reg, 0);    /* 207 */
  640         REGWRITE32(vdac, bt_reg, 0x0);  /* ORM */
  641         REGWRITE32(vdac, bt_reg, 0x0);  /* OBM */
  642         REGWRITE32(vdac, bt_reg, 0x0);  /* ILV */
  643         REGWRITE32(vdac, bt_reg, 0x0);  /* TEST */
  644 
  645         VDACSELECT(vdac, BT459_IREG_CCR);
  646         REGWRITE32(vdac, bt_reg, 0x0);
  647         REGWRITE32(vdac, bt_reg, 0x0);
  648         REGWRITE32(vdac, bt_reg, 0x0);
  649         REGWRITE32(vdac, bt_reg, 0x0);
  650         REGWRITE32(vdac, bt_reg, 0x0);
  651         REGWRITE32(vdac, bt_reg, 0x0);
  652         REGWRITE32(vdac, bt_reg, 0x0);
  653         REGWRITE32(vdac, bt_reg, 0x0);
  654         REGWRITE32(vdac, bt_reg, 0x0);
  655         REGWRITE32(vdac, bt_reg, 0x0);
  656         REGWRITE32(vdac, bt_reg, 0x0);
  657         REGWRITE32(vdac, bt_reg, 0x0);
  658         REGWRITE32(vdac, bt_reg, 0x0);
  659 
  660         /* build sane colormap */
  661         VDACSELECT(vdac, 0);
  662         p = rasops_cmap;
  663         for (i = 0; i < CMAP_SIZE; i++, p += 3) {
  664                 REGWRITE32(vdac, bt_cmap, p[0]);
  665                 REGWRITE32(vdac, bt_cmap, p[1]);
  666                 REGWRITE32(vdac, bt_cmap, p[2]);
  667         }
  668 
  669         /* clear out cursor image */
  670         VDACSELECT(vdac, BT459_IREG_CRAM_BASE);
  671         for (i = 0; i < 1024; i++)
  672                 REGWRITE32(vdac, bt_reg, 0xff);
  673 
  674         /*
  675          * 2 bit/pixel cursor.  Assign MSB for cursor mask and LSB for
  676          * cursor image.  CCOLOR_2 for mask color, while CCOLOR_3 for
  677          * image color.  CCOLOR_1 will be never used.
  678          */
  679         VDACSELECT(vdac, BT459_IREG_CCOLOR_1);
  680         REGWRITE32(vdac, bt_reg, 0xff);
  681         REGWRITE32(vdac, bt_reg, 0xff);
  682         REGWRITE32(vdac, bt_reg, 0xff);
  683 
  684         REGWRITE32(vdac, bt_reg, 0);
  685         REGWRITE32(vdac, bt_reg, 0);
  686         REGWRITE32(vdac, bt_reg, 0);
  687 
  688         REGWRITE32(vdac, bt_reg, 0xff);
  689         REGWRITE32(vdac, bt_reg, 0xff);
  690         REGWRITE32(vdac, bt_reg, 0xff);
  691 }
  692 
  693 static int
  694 get_cmap(sc, p)
  695         struct cfb_softc *sc;
  696         struct wsdisplay_cmap *p;
  697 {
  698         u_int index = p->index, count = p->count;
  699         int error;
  700 
  701         if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
  702                 return (EINVAL);
  703 
  704         error = copyout(&sc->sc_cmap.r[index], p->red, count);
  705         if (error)
  706                 return error;
  707         error = copyout(&sc->sc_cmap.g[index], p->green, count);
  708         if (error)
  709                 return error;
  710         error = copyout(&sc->sc_cmap.b[index], p->blue, count);
  711         return error;
  712 }
  713 
  714 static int
  715 set_cmap(sc, p)
  716         struct cfb_softc *sc;
  717         struct wsdisplay_cmap *p;
  718 {
  719         struct hwcmap256 cmap;
  720         u_int index = p->index, count = p->count;
  721         int error, s;
  722 
  723         if (index >= CMAP_SIZE || count > CMAP_SIZE - index)
  724                 return (EINVAL);
  725 
  726         error = copyin(p->red, &cmap.r[index], count);
  727         if (error)
  728                 return error;
  729         error = copyin(p->green, &cmap.g[index], count);
  730         if (error)
  731                 return error;
  732         error = copyin(p->blue, &cmap.b[index], count);
  733         if (error)
  734                 return error;
  735         s = spltty();
  736         memcpy(&sc->sc_cmap.r[index], &cmap.r[index], count);
  737         memcpy(&sc->sc_cmap.g[index], &cmap.g[index], count);
  738         memcpy(&sc->sc_cmap.b[index], &cmap.b[index], count);
  739         sc->sc_changed |= WSDISPLAY_CMAP_DOLUT;
  740         splx(s);
  741         return (0);
  742 }
  743 
  744 static int
  745 set_cursor(sc, p)
  746         struct cfb_softc *sc;
  747         struct wsdisplay_cursor *p;
  748 {
  749 #define cc (&sc->sc_cursor)
  750         u_int v, index = 0, count = 0, icount = 0;
  751         uint8_t r[2], g[2], b[2], image[512], mask[512];
  752         int error, s;
  753 
  754         v = p->which;
  755         if (v & WSDISPLAY_CURSOR_DOCMAP) {
  756                 index = p->cmap.index;
  757                 count = p->cmap.count;
  758                 if (index >= 2 || (index + count) > 2)
  759                         return (EINVAL);
  760                 error = copyin(p->cmap.red, &r[index], count);
  761                 if (error)
  762                         return error;
  763                 error = copyin(p->cmap.green, &g[index], count);
  764                 if (error)
  765                         return error;
  766                 error = copyin(p->cmap.blue, &b[index], count);
  767                 if (error)
  768                         return error;
  769         }
  770         if (v & WSDISPLAY_CURSOR_DOSHAPE) {
  771                 if (p->size.x > CURSOR_MAX_SIZE || p->size.y > CURSOR_MAX_SIZE)
  772                         return (EINVAL);
  773                 icount = ((p->size.x < 33) ? 4 : 8) * p->size.y;
  774                 error = copyin(p->image, image, icount);
  775                 if (error)
  776                         return error;
  777                 error = copyin(p->mask, mask, icount);
  778                 if (error)
  779                         return error;
  780         }
  781 
  782         s = spltty();
  783         if (v & WSDISPLAY_CURSOR_DOCUR)
  784                 sc->sc_curenb = p->enable;
  785         if (v & WSDISPLAY_CURSOR_DOPOS)
  786                 set_curpos(sc, &p->pos);
  787         if (v & WSDISPLAY_CURSOR_DOHOT)
  788                 cc->cc_hot = p->hot;
  789         if (v & WSDISPLAY_CURSOR_DOCMAP) {
  790                 memcpy(&cc->cc_color[index], &r[index], count);
  791                 memcpy(&cc->cc_color[index + 2], &g[index], count);
  792                 memcpy(&cc->cc_color[index + 4], &b[index], count);
  793         }
  794         if (v & WSDISPLAY_CURSOR_DOSHAPE) {
  795                 cc->cc_size = p->size;
  796                 memset(cc->cc_image, 0, sizeof cc->cc_image);
  797                 memcpy(cc->cc_image, image, icount);
  798                 memset(cc->cc_mask, 0, sizeof cc->cc_mask);
  799                 memcpy(cc->cc_mask, mask, icount);
  800         }
  801         sc->sc_changed |= v;
  802         splx(s);
  803 
  804         return (0);
  805 #undef cc
  806 }
  807 
  808 static int
  809 get_cursor(sc, p)
  810         struct cfb_softc *sc;
  811         struct wsdisplay_cursor *p;
  812 {
  813         return (EPASSTHROUGH); /* XXX */
  814 }
  815 
  816 static void
  817 set_curpos(sc, curpos)
  818         struct cfb_softc *sc;
  819         struct wsdisplay_curpos *curpos;
  820 {
  821         struct rasops_info *ri = sc->sc_ri;
  822         int x = curpos->x, y = curpos->y;
  823 
  824         if (y < 0)
  825                 y = 0;
  826         else if (y > ri->ri_height)
  827                 y = ri->ri_height;
  828         if (x < 0)
  829                 x = 0;
  830         else if (x > ri->ri_width)
  831                 x = ri->ri_width;
  832         sc->sc_cursor.cc_pos.x = x;
  833         sc->sc_cursor.cc_pos.y = y;
  834 }

Cache object: 3ac05abd2543c4dc0eb07db0ee088fe7


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