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/hpc/hpcfb.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: hpcfb.c,v 1.30 2003/06/29 22:30:07 fvdl Exp $  */
    2 
    3 /*-
    4  * Copyright (c) 1999
    5  *         Shin Takemura and PocketBSD Project. All rights reserved.
    6  * Copyright (c) 2000,2001
    7  *         SATO Kazumi. All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. All advertising materials mentioning features or use of this software
   18  *    must display the following acknowledgement:
   19  *      This product includes software developed by the PocketBSD project
   20  *      and its contributors.
   21  * 4. Neither the name of the project nor the names of its contributors
   22  *    may be used to endorse or promote products derived from this software
   23  *    without specific prior written permission.
   24  *
   25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   35  * SUCH DAMAGE.
   36  *
   37  */
   38 
   39 /*
   40  * jump scroll, scroll thread, multiscreen, virtual text vram 
   41  * and hpcfb_emulops functions
   42  * written by SATO Kazumi.
   43  */
   44 
   45 #include <sys/cdefs.h>
   46 __KERNEL_RCSID(0, "$NetBSD: hpcfb.c,v 1.30 2003/06/29 22:30:07 fvdl Exp $");
   47 
   48 #define FBDEBUG
   49 static const char _copyright[] __attribute__ ((unused)) =
   50     "Copyright (c) 1999 Shin Takemura.  All rights reserved.";
   51 static const char _rcsid[] __attribute__ ((unused)) =
   52     "$NetBSD: hpcfb.c,v 1.30 2003/06/29 22:30:07 fvdl Exp $";
   53 
   54 #include <sys/param.h>
   55 #include <sys/systm.h>
   56 #include <sys/kernel.h>
   57 #include <sys/signalvar.h>
   58 #include <sys/proc.h>
   59 #include <sys/kthread.h>
   60 #include <sys/lock.h>
   61 #include <sys/user.h>
   62 #include <sys/device.h>
   63 #include <sys/conf.h>
   64 #include <sys/malloc.h>
   65 #include <sys/buf.h>
   66 #include <sys/ioctl.h>
   67 
   68 #include <uvm/uvm_extern.h>
   69 
   70 #include <machine/bus.h>
   71 
   72 #include <dev/wscons/wsconsio.h>
   73 #include <dev/wscons/wsdisplayvar.h>
   74 #include <dev/wscons/wscons_callbacks.h>
   75 
   76 #include <dev/wsfont/wsfont.h>
   77 #include <dev/rasops/rasops.h>
   78 
   79 #include <dev/hpc/hpcfbvar.h>
   80 #include <dev/hpc/hpcfbio.h>
   81 
   82 #include "bivideo.h"
   83 #if NBIVIDEO > 0
   84 #include <dev/hpc/bivideovar.h>
   85 #endif
   86 
   87 #ifdef FBDEBUG
   88 int     hpcfb_debug = 0;
   89 #define DPRINTF(arg) if (hpcfb_debug) printf arg;
   90 #else
   91 #define DPRINTF(arg)
   92 #endif
   93 
   94 #ifndef HPCFB_MAX_COLUMN
   95 #define HPCFB_MAX_COLUMN 130
   96 #endif /* HPCFB_MAX_COLUMN */
   97 #ifndef HPCFB_MAX_ROW
   98 #define HPCFB_MAX_ROW 80
   99 #endif /* HPCFB_MAX_ROW */
  100 
  101 /*
  102  * currently experimental
  103 #define HPCFB_JUMP
  104 */
  105 
  106 struct hpcfb_vchar {
  107         u_int c;
  108         long attr;
  109 };
  110 
  111 struct hpcfb_tvrow {
  112         int maxcol;
  113         int spacecol;
  114         struct hpcfb_vchar col[HPCFB_MAX_COLUMN];
  115 };
  116 
  117 struct hpcfb_devconfig {
  118         struct rasops_info      dc_rinfo;       /* rasops information */
  119 
  120         int             dc_blanked;     /* currently had video disabled */
  121         struct hpcfb_softc *dc_sc;
  122         int dc_rows;
  123         int dc_cols;
  124         struct hpcfb_tvrow *dc_tvram;
  125         int dc_curx;
  126         int dc_cury;
  127 #ifdef HPCFB_JUMP
  128         int dc_min_row;
  129         int dc_max_row;
  130         int dc_scroll;
  131         struct callout dc_scroll_ch;
  132         int dc_scroll_src;
  133         int dc_scroll_dst;
  134         int dc_scroll_num;
  135 #endif /* HPCFB_JUMP */
  136         volatile int dc_state;
  137 #define HPCFB_DC_CURRENT                0x80000000
  138 #define HPCFB_DC_DRAWING                0x01    /* drawing raster ops */
  139 #define HPCFB_DC_TDRAWING               0x02    /* drawing tvram */
  140 #define HPCFB_DC_SCROLLPENDING          0x04    /* scroll is pending */
  141 #define HPCFB_DC_UPDATE                 0x08    /* tvram update */
  142 #define HPCFB_DC_SCRDELAY               0x10    /* scroll time but delay it */
  143 #define HPCFB_DC_SCRTHREAD              0x20    /* in scroll thread or callout */
  144 #define HPCFB_DC_UPDATEALL              0x40    /* need to redraw all */
  145 #define HPCFB_DC_ABORT                  0x80    /* abort redrawing */
  146 #define HPCFB_DC_SWITCHREQ              0x100   /* switch request exist */
  147         int     dc_memsize;
  148         u_char *dc_fbaddr;
  149 };
  150 
  151 #define IS_DRAWABLE(dc) \
  152         (((dc)->dc_state&HPCFB_DC_CURRENT)&& \
  153          (((dc)->dc_state&(HPCFB_DC_DRAWING|HPCFB_DC_SWITCHREQ)) == 0))
  154 
  155 #define HPCFB_MAX_SCREEN 5
  156 #define HPCFB_MAX_JUMP 5
  157 
  158 struct hpcfb_softc {
  159         struct  device sc_dev;
  160         struct  hpcfb_devconfig *sc_dc; /* device configuration */
  161         const struct hpcfb_accessops    *sc_accessops;
  162         void *sc_accessctx;
  163         void *sc_powerhook;     /* power management hook */
  164         struct device *sc_wsdisplay;
  165         int sc_screen_resumed;
  166         int sc_polling;
  167         int sc_mapping;
  168         struct proc *sc_thread;
  169         struct lock sc_lock;
  170         void *sc_wantedscreen;
  171         void (*sc_switchcb)(void *, int, int);
  172         void *sc_switchcbarg;
  173         struct callout sc_switch_callout;
  174         int sc_nfbconf;
  175         struct hpcfb_fbconf *sc_fbconflist;
  176 };
  177 
  178 /*
  179  *  function prototypes
  180  */
  181 int     hpcfbmatch(struct device *, struct cfdata *, void *);
  182 void    hpcfbattach(struct device *, struct device *, void *);
  183 int     hpcfbprint(void *, const char *);
  184 
  185 int     hpcfb_ioctl(void *, u_long, caddr_t, int, struct proc *);
  186 paddr_t hpcfb_mmap(void *, off_t, int);
  187 
  188 void    hpcfb_refresh_screen(struct hpcfb_softc *);
  189 void    hpcfb_doswitch(struct hpcfb_softc *);
  190 
  191 #ifdef HPCFB_JUMP
  192 static void     hpcfb_create_thread(void *);
  193 static void     hpcfb_thread(void *);
  194 #endif /* HPCFB_JUMP */
  195 
  196 static int      hpcfb_init(struct hpcfb_fbconf *, struct hpcfb_devconfig *);
  197 static int      hpcfb_alloc_screen(void *, const struct wsscreen_descr *,
  198                     void **, int *, int *, long *);
  199 static void     hpcfb_free_screen(void *, void *);
  200 static int      hpcfb_show_screen(void *, void *, int,
  201                     void (*) (void *, int, int), void *);
  202 static void     hpcfb_pollc(void *, int);
  203 static void     hpcfb_power(int, void *);
  204 static void     hpcfb_cmap_reorder(struct hpcfb_fbconf *,
  205                     struct hpcfb_devconfig *);
  206 
  207 void    hpcfb_cursor(void *, int, int, int);
  208 int     hpcfb_mapchar(void *, int, unsigned int *);
  209 void    hpcfb_putchar(void *, int, int, u_int, long);
  210 void    hpcfb_copycols(void *, int, int, int, int);
  211 void    hpcfb_erasecols(void *, int, int, int, long);
  212 void    hpcfb_redraw(void *, int, int, int);
  213 void    hpcfb_copyrows(void *, int, int, int);
  214 void    hpcfb_eraserows(void *, int, int, long);
  215 int     hpcfb_allocattr(void *, int, int, int, long *);
  216 void    hpcfb_cursor_raw(void *, int, int, int);
  217 
  218 #ifdef HPCFB_JUMP
  219 void    hpcfb_update(void *);
  220 void    hpcfb_do_scroll(void *);
  221 void    hpcfb_check_update(void *);
  222 #endif /* HPCFB_JUMP */
  223 
  224 struct wsdisplay_emulops hpcfb_emulops = {
  225         hpcfb_cursor,
  226         hpcfb_mapchar,
  227         hpcfb_putchar,
  228         hpcfb_copycols,
  229         hpcfb_erasecols,
  230         hpcfb_copyrows,
  231         hpcfb_eraserows,
  232         hpcfb_allocattr
  233 };
  234 
  235 /*
  236  *  static variables
  237  */
  238 CFATTACH_DECL(hpcfb, sizeof(struct hpcfb_softc),
  239     hpcfbmatch, hpcfbattach, NULL, NULL);
  240 
  241 struct wsscreen_descr hpcfb_stdscreen = {
  242         "std",
  243         0, 0,   /* will be filled in -- XXX shouldn't, it's global */
  244         &hpcfb_emulops, /* XXX */
  245         0, 0,
  246         WSSCREEN_REVERSE
  247 };
  248 
  249 const struct wsscreen_descr *_hpcfb_scrlist[] = {
  250         &hpcfb_stdscreen,
  251         /* XXX other formats, graphics screen? */
  252 };
  253 
  254 struct wsscreen_list hpcfb_screenlist = {
  255         sizeof(_hpcfb_scrlist) / sizeof(struct wsscreen_descr *),
  256         _hpcfb_scrlist
  257 };
  258 
  259 struct wsdisplay_accessops hpcfb_accessops = {
  260         hpcfb_ioctl,
  261         hpcfb_mmap,
  262         hpcfb_alloc_screen,
  263         hpcfb_free_screen,
  264         hpcfb_show_screen,
  265         0 /* load_font */,
  266         hpcfb_pollc
  267 };
  268 
  269 void    hpcfb_tv_putchar(struct hpcfb_devconfig *, int, int, u_int, long);
  270 void    hpcfb_tv_copycols(struct hpcfb_devconfig *, int, int, int, int);
  271 void    hpcfb_tv_erasecols(struct hpcfb_devconfig *, int, int, int, long);
  272 void    hpcfb_tv_copyrows(struct hpcfb_devconfig *, int, int, int);
  273 void    hpcfb_tv_eraserows(struct hpcfb_devconfig *, int, int, long);
  274 
  275 struct wsdisplay_emulops rasops_emul;
  276 
  277 static int hpcfbconsole;
  278 struct hpcfb_devconfig hpcfb_console_dc;
  279 struct wsscreen_descr hpcfb_console_wsscreen;
  280 struct hpcfb_tvrow hpcfb_console_tvram[HPCFB_MAX_ROW];
  281 
  282 /*
  283  *  function bodies
  284  */
  285 
  286 int
  287 hpcfbmatch(struct device *parent, struct cfdata *match, void *aux)
  288 {
  289         return (1);
  290 }
  291 
  292 void
  293 hpcfbattach(struct device *parent, struct device *self, void *aux)
  294 {
  295         struct hpcfb_softc *sc = (struct hpcfb_softc *)self;
  296         struct hpcfb_attach_args *ha = aux;
  297         struct wsemuldisplaydev_attach_args wa;
  298 
  299         sc->sc_accessops = ha->ha_accessops;
  300         sc->sc_accessctx = ha->ha_accessctx;
  301         sc->sc_nfbconf = ha->ha_nfbconf;
  302         sc->sc_fbconflist = ha->ha_fbconflist;
  303 
  304         if (hpcfbconsole) {
  305                 sc->sc_dc = &hpcfb_console_dc;
  306                 hpcfb_console_dc.dc_sc = sc;
  307                 printf(": %dx%d pixels, %d colors, %dx%d chars",
  308                     sc->sc_dc->dc_rinfo.ri_width,sc->sc_dc->dc_rinfo.ri_height,
  309                     (1 << sc->sc_dc->dc_rinfo.ri_depth),
  310                     sc->sc_dc->dc_rinfo.ri_cols,sc->sc_dc->dc_rinfo.ri_rows);
  311                 /* Set video chip dependent CLUT if any. */
  312                 if (sc->sc_accessops->setclut)
  313                         sc->sc_accessops->setclut(sc->sc_accessctx, 
  314                             &hpcfb_console_dc.dc_rinfo);
  315         }
  316         printf("\n");
  317 
  318         sc->sc_polling = 0; /* XXX */
  319         sc->sc_mapping = 0; /* XXX */
  320         callout_init(&sc->sc_switch_callout);
  321 
  322         /* Add a power hook to power management */
  323         sc->sc_powerhook = powerhook_establish(hpcfb_power, sc);
  324         if (sc->sc_powerhook == NULL)
  325                 printf("%s: WARNING: unable to establish power hook\n",
  326                     sc->sc_dev.dv_xname);
  327 
  328         wa.console = hpcfbconsole;
  329         wa.scrdata = &hpcfb_screenlist;
  330         wa.accessops = &hpcfb_accessops;
  331         wa.accesscookie = sc;
  332 
  333         sc->sc_wsdisplay = config_found(self, &wa, wsemuldisplaydevprint);
  334 
  335 #ifdef HPCFB_JUMP
  336         /*
  337          * Create a kernel thread to scroll,
  338          */
  339         kthread_create(hpcfb_create_thread, sc);
  340 #endif /* HPCFB_JUMP */
  341 }
  342 
  343 #ifdef HPCFB_JUMP
  344 void
  345 hpcfb_create_thread(void *arg)
  346 {
  347         struct hpcfb_softc *sc = arg;
  348 
  349         if (kthread_create1(hpcfb_thread, sc, &sc->sc_thread,
  350             "%s", sc->sc_dev.dv_xname) == 0)
  351                 return;
  352 
  353         /*
  354          * We were unable to create the HPCFB thread; bail out.
  355          */
  356         sc->sc_thread = 0;
  357         printf("%s: unable to create thread, kernel hpcfb scroll support disabled\n",
  358             sc->sc_dev.dv_xname);
  359 }
  360 
  361 void
  362 hpcfb_thread(void *arg)
  363 {
  364         struct hpcfb_softc *sc = arg;
  365 
  366         /*
  367          * Loop forever, doing a periodic check for update events.
  368          */
  369         for (;;) {
  370                 /* HPCFB_LOCK(sc); */
  371                 sc->sc_dc->dc_state |= HPCFB_DC_SCRTHREAD;      
  372                 if (!sc->sc_mapping) /* draw only EMUL mode */
  373                         hpcfb_update(sc->sc_dc);
  374                 sc->sc_dc->dc_state &= ~HPCFB_DC_SCRTHREAD;     
  375                 /* APM_UNLOCK(sc); */
  376                 (void) tsleep(sc, PWAIT, "hpcfb",  (8 * hz) / 7 / 10);
  377         }
  378 }
  379 #endif /* HPCFB_JUMP */
  380 
  381 /* Print function (for parent devices). */
  382 int
  383 hpcfbprint(void *aux, const char *pnp)
  384 {
  385         if (pnp)
  386                 aprint_normal("hpcfb at %s", pnp);
  387 
  388         return (UNCONF);
  389 }
  390 
  391 int
  392 hpcfb_cnattach(struct hpcfb_fbconf *fbconf)
  393 {
  394         struct hpcfb_fbconf __fbconf __attribute__((__unused__));
  395         long defattr;
  396 
  397         DPRINTF(("%s(%d): hpcfb_cnattach()\n", __FILE__, __LINE__));
  398 #if NBIVIDEO > 0
  399         if (fbconf == 0) {
  400                 memset(&__fbconf, 0, sizeof(struct hpcfb_fbconf));
  401                 if (bivideo_getcnfb(&__fbconf) != 0)
  402                         return (ENXIO);
  403                 fbconf = &__fbconf;
  404         }
  405 #endif /* NBIVIDEO > 0 */
  406         memset(&hpcfb_console_dc, 0, sizeof(struct hpcfb_devconfig));
  407         if (hpcfb_init(fbconf, &hpcfb_console_dc) != 0)
  408                 return (ENXIO);
  409         hpcfb_console_dc.dc_state |= HPCFB_DC_CURRENT;
  410 
  411         hpcfb_console_dc.dc_tvram = hpcfb_console_tvram;
  412         /* clear screen */
  413         memset(hpcfb_console_tvram, 0, sizeof(hpcfb_console_tvram));
  414         hpcfb_redraw(&hpcfb_console_dc, 0, hpcfb_console_dc.dc_rows, 1);
  415 
  416         hpcfb_console_wsscreen = hpcfb_stdscreen;
  417         hpcfb_console_wsscreen.nrows = hpcfb_console_dc.dc_rows;
  418         hpcfb_console_wsscreen.ncols = hpcfb_console_dc.dc_cols;
  419         hpcfb_console_wsscreen.capabilities = hpcfb_console_dc.dc_rinfo.ri_caps;
  420         hpcfb_allocattr(&hpcfb_console_dc,
  421                         WSCOL_WHITE, WSCOL_BLACK, 0, &defattr);
  422         wsdisplay_cnattach(&hpcfb_console_wsscreen, &hpcfb_console_dc,
  423             0, 0, defattr);
  424         hpcfbconsole = 1;
  425 
  426         return (0);
  427 }
  428 
  429 int
  430 hpcfb_init(struct hpcfb_fbconf *fbconf, struct hpcfb_devconfig *dc)
  431 {
  432         struct rasops_info *ri;
  433         vaddr_t fbaddr;
  434 
  435         fbaddr = (vaddr_t)fbconf->hf_baseaddr;
  436         dc->dc_fbaddr = (u_char *)fbaddr;
  437 
  438         /* init rasops */
  439         ri = &dc->dc_rinfo;
  440         memset(ri, 0, sizeof(struct rasops_info));
  441         ri->ri_depth = fbconf->hf_pixel_width;
  442         ri->ri_bits = (caddr_t)fbaddr;
  443         ri->ri_width = fbconf->hf_width;
  444         ri->ri_height = fbconf->hf_height;
  445         ri->ri_stride = fbconf->hf_bytes_per_line;
  446 #if 0
  447         ri->ri_flg = RI_FORCEMONO | RI_CURSOR;
  448 #else
  449         ri->ri_flg = RI_CURSOR;
  450 #endif
  451         switch (ri->ri_depth) {
  452         case 8:
  453                 if (32 <= fbconf->hf_pack_width &&
  454                     (fbconf->hf_order_flags & HPCFB_REVORDER_BYTE) &&
  455                     (fbconf->hf_order_flags & HPCFB_REVORDER_WORD)) {
  456                         ri->ri_flg |= RI_BSWAP;
  457                 }
  458                 break;
  459         default:
  460                 if (fbconf->hf_order_flags & HPCFB_REVORDER_BYTE) {
  461 #if BYTE_ORDER == BIG_ENDIAN
  462                         ri->ri_flg |= RI_BSWAP;
  463 #endif
  464                 } else {
  465 #if BYTE_ORDER == LITTLE_ENDIAN
  466                         ri->ri_flg |= RI_BSWAP;
  467 #endif
  468                 }
  469                 break;
  470         }
  471 
  472         if (rasops_init(ri, HPCFB_MAX_ROW, HPCFB_MAX_COLUMN)) {
  473                 panic("%s(%d): rasops_init() failed!", __FILE__, __LINE__);
  474         }
  475 
  476         /* over write color map of rasops */
  477         hpcfb_cmap_reorder (fbconf, dc);
  478 
  479         dc->dc_curx = -1;
  480         dc->dc_cury = -1;
  481         dc->dc_rows = dc->dc_rinfo.ri_rows;
  482         dc->dc_cols = dc->dc_rinfo.ri_cols;
  483 #ifdef HPCFB_JUMP
  484         dc->dc_max_row = 0;
  485         dc->dc_min_row = dc->dc_rows;
  486         dc->dc_scroll = 0;
  487         callout_init(&dc->dc_scroll_ch);
  488 #endif /* HPCFB_JUMP */
  489         dc->dc_memsize = ri->ri_stride * ri->ri_height;
  490         /* hook rasops in hpcfb_ops */
  491         rasops_emul = ri->ri_ops; /* struct copy */
  492         ri->ri_ops = hpcfb_emulops; /* struct copy */
  493 
  494         return (0);
  495 }
  496 
  497 static void
  498 hpcfb_cmap_reorder(struct hpcfb_fbconf *fbconf, struct hpcfb_devconfig *dc)
  499 {
  500         struct rasops_info *ri = &dc->dc_rinfo;
  501         int reverse = fbconf->hf_access_flags & HPCFB_ACCESS_REVERSE;
  502         int *cmap = ri->ri_devcmap;
  503         int i, j, bg, fg, tmp;
  504 
  505         /*
  506          * Set forground and background so that the screen 
  507          * looks black on white.
  508          * Normally, black = 00 and white = ff.
  509          * HPCFB_ACCESS_REVERSE means black = ff and white = 00.
  510          */
  511         switch (fbconf->hf_pixel_width) {
  512         case 1:
  513                 /* FALLTHROUGH */
  514         case 2:
  515                 /* FALLTHROUGH */
  516         case 4:
  517                 if (reverse) {
  518                         bg = 0;
  519                         fg = ~0;
  520                 } else {
  521                         bg = ~0;
  522                         fg = 0;
  523                 }
  524                 /* for gray-scale LCD, hi-contrast color map */
  525                 cmap[0] = bg;
  526                 for (i = 1; i < 16; i++)
  527                         cmap[i] = fg;
  528                 break;
  529         case 8:
  530                 /* FALLTHROUGH */
  531         case 16:
  532                 if (reverse) {
  533                         for (i = 0, j = 15; i < 8; i++, j--) {
  534                                 tmp = cmap[i];
  535                                 cmap[i] = cmap[j];
  536                                 cmap[j] = tmp;
  537                         }
  538                 }
  539                 break;
  540         }
  541 }
  542 
  543 int
  544 hpcfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  545 {
  546         struct hpcfb_softc *sc = v;
  547         struct hpcfb_devconfig *dc = sc->sc_dc;
  548         struct wsdisplay_fbinfo *wdf;
  549 
  550         DPRINTF(("hpcfb_ioctl(cmd=0x%lx)\n", cmd));
  551         switch (cmd) {
  552         case WSKBDIO_BELL:
  553                 return (0);
  554                 break;
  555 
  556         case WSDISPLAYIO_GTYPE:
  557                 *(u_int *)data = WSDISPLAY_TYPE_HPCFB;
  558                 return (0);
  559 
  560         case WSDISPLAYIO_GINFO:
  561                 wdf = (void *)data;
  562                 wdf->height = dc->dc_rinfo.ri_height;
  563                 wdf->width = dc->dc_rinfo.ri_width;
  564                 wdf->depth = dc->dc_rinfo.ri_depth;
  565                 wdf->cmsize = 256;      /* XXXX */
  566                 return (0);
  567         
  568         case WSDISPLAYIO_SMODE:
  569                 if (*(int *)data == WSDISPLAYIO_MODE_EMUL){ 
  570                         if (sc->sc_mapping){
  571                                 sc->sc_mapping = 0;
  572                                 if (dc->dc_state&HPCFB_DC_DRAWING)
  573                                         dc->dc_state &= ~HPCFB_DC_ABORT;
  574 #ifdef HPCFB_FORCE_REDRAW
  575                                 hpcfb_refresh_screen(sc);
  576 #else
  577                                 dc->dc_state |= HPCFB_DC_UPDATEALL;
  578 #endif
  579                         }
  580                 } else {
  581                         if (!sc->sc_mapping) {
  582                                 sc->sc_mapping = 1;
  583                                 dc->dc_state |= HPCFB_DC_ABORT;
  584                         }
  585                         sc->sc_mapping = 1;
  586                 }
  587                 if (sc && sc->sc_accessops->iodone)
  588                         (*sc->sc_accessops->iodone)(sc->sc_accessctx);
  589                 return (0);     
  590 
  591         case WSDISPLAYIO_GETCMAP:
  592         case WSDISPLAYIO_PUTCMAP:
  593         case WSDISPLAYIO_SVIDEO:
  594         case WSDISPLAYIO_GVIDEO:
  595         case WSDISPLAYIO_GETPARAM:
  596         case WSDISPLAYIO_SETPARAM:
  597         case HPCFBIO_GCONF:
  598         case HPCFBIO_SCONF:
  599         case HPCFBIO_GDSPCONF:
  600         case HPCFBIO_SDSPCONF:
  601         case HPCFBIO_GOP:
  602         case HPCFBIO_SOP:
  603                 return ((*sc->sc_accessops->ioctl)(sc->sc_accessctx,
  604                     cmd, data, flag, p));
  605 
  606         default:
  607                 if (IOCGROUP(cmd) != 't')
  608                         DPRINTF(("%s(%d): hpcfb_ioctl(%lx, %lx) grp=%c num=%ld\n",
  609                             __FILE__, __LINE__,
  610                             cmd, (u_long)data, (char)IOCGROUP(cmd), cmd&0xff));
  611                 break;
  612         }
  613 
  614         return (EPASSTHROUGH); /* Inappropriate ioctl for device */
  615 }
  616 
  617 paddr_t
  618 hpcfb_mmap(void *v, off_t offset, int prot)
  619 {
  620         struct hpcfb_softc *sc = v;
  621 
  622         return ((*sc->sc_accessops->mmap)(sc->sc_accessctx, offset, prot));
  623 }
  624 
  625 static void 
  626 hpcfb_power(int why, void *arg)
  627 {
  628         struct hpcfb_softc *sc = arg;
  629 
  630         if (sc->sc_dc == NULL)
  631                 return; /* You have no screen yet. */
  632 
  633         switch (why) {
  634         case PWR_STANDBY:
  635                 break;
  636         case PWR_SOFTSUSPEND:
  637                 /* XXX, casting to 'struct wsdisplay_softc *' means
  638                    that you should not call the method here... */
  639                 sc->sc_screen_resumed = wsdisplay_getactivescreen(
  640                         (struct wsdisplay_softc *)sc->sc_wsdisplay);
  641                 if (wsdisplay_switch(sc->sc_wsdisplay,
  642                     WSDISPLAY_NULLSCREEN,
  643                     1 /* waitok */) == 0) {
  644                         wsscreen_switchwait(
  645                                 (struct wsdisplay_softc *)sc->sc_wsdisplay,
  646                                 WSDISPLAY_NULLSCREEN);
  647                 } else {
  648                         sc->sc_screen_resumed = WSDISPLAY_NULLSCREEN;
  649                 }
  650 
  651                 sc->sc_dc->dc_state &= ~HPCFB_DC_CURRENT;
  652                 break;
  653         case PWR_SOFTRESUME:
  654                 sc->sc_dc->dc_state |= HPCFB_DC_CURRENT;
  655                 if (sc->sc_screen_resumed != WSDISPLAY_NULLSCREEN)
  656                         wsdisplay_switch(sc->sc_wsdisplay,
  657                             sc->sc_screen_resumed,
  658                             1 /* waitok */);
  659                 break;
  660         }
  661 }
  662 
  663 void
  664 hpcfb_refresh_screen(struct hpcfb_softc *sc)
  665 {
  666         struct hpcfb_devconfig *dc = sc->sc_dc;
  667         int x, y;
  668 
  669         DPRINTF(("hpcfb_refres_screen()\n"));
  670         if (dc == NULL)
  671                 return;
  672 
  673 #ifdef HPCFB_JUMP
  674         if (dc->dc_state&HPCFB_DC_SCROLLPENDING) {
  675                 dc->dc_state &= ~HPCFB_DC_SCROLLPENDING;
  676                 dc->dc_state &= ~HPCFB_DC_UPDATE;
  677                 callout_stop(&dc->dc_scroll_ch);
  678         }
  679 #endif /* HPCFB_JUMP */
  680         /*
  681          * refresh screen
  682          */
  683         dc->dc_state &= ~HPCFB_DC_UPDATEALL;
  684         x = dc->dc_curx;
  685         y = dc->dc_cury;
  686         if (0 <= x && 0 <= y)
  687                 hpcfb_cursor_raw(dc, 0,  y, x); /* disable cursor */
  688         /* redraw all text */
  689         hpcfb_redraw(dc, 0, dc->dc_rows, 1);
  690         if (0 <= x && 0 <= y)
  691                 hpcfb_cursor_raw(dc, 1,  y, x); /* enable cursor */
  692 }
  693 
  694 static int
  695 hpcfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
  696     int *curxp, int *curyp, long *attrp)
  697 {
  698         struct hpcfb_softc *sc = v;
  699         struct hpcfb_devconfig *dc;
  700 
  701         DPRINTF(("%s(%d): hpcfb_alloc_screen()\n", __FILE__, __LINE__));
  702 
  703         dc = malloc(sizeof(struct hpcfb_devconfig), M_DEVBUF, M_WAITOK|M_ZERO);
  704         if (dc == NULL)
  705                 return (ENOMEM);
  706 
  707         dc->dc_sc = sc;
  708         if (hpcfb_init(&sc->sc_fbconflist[0], dc) != 0)
  709                 return (EINVAL);
  710         if (sc->sc_accessops->font) {
  711                 sc->sc_accessops->font(sc->sc_accessctx, 
  712                     dc->dc_rinfo.ri_font);
  713         }
  714         /* Set video chip dependent CLUT if any. */
  715         if (sc->sc_accessops->setclut)
  716                 sc->sc_accessops->setclut(sc->sc_accessctx, &dc->dc_rinfo);
  717         printf("hpcfb: %dx%d pixels, %d colors, %dx%d chars\n",
  718             dc->dc_rinfo.ri_width, dc->dc_rinfo.ri_height,
  719             (1 << dc->dc_rinfo.ri_depth),
  720             dc->dc_rinfo.ri_cols, dc->dc_rinfo.ri_rows);
  721 
  722         /*
  723          * XXX, wsdisplay won't reffer the information in wsscreen_descr
  724          * structure until alloc_screen will be called, at least, under
  725          * current implementation...
  726          */
  727         hpcfb_stdscreen.nrows = dc->dc_rows;
  728         hpcfb_stdscreen.ncols = dc->dc_cols;
  729         hpcfb_stdscreen.capabilities = dc->dc_rinfo.ri_caps;
  730 
  731         dc->dc_fbaddr = dc->dc_rinfo.ri_bits;
  732         dc->dc_rows = dc->dc_rinfo.ri_rows;
  733         dc->dc_cols = dc->dc_rinfo.ri_cols;
  734         dc->dc_memsize = dc->dc_rinfo.ri_stride * dc->dc_rinfo.ri_height;
  735 
  736         dc->dc_curx = -1;
  737         dc->dc_cury = -1;
  738         dc->dc_tvram = malloc(sizeof(struct hpcfb_tvrow)*dc->dc_rows,
  739             M_DEVBUF, M_WAITOK|M_ZERO);
  740         if (dc->dc_tvram == NULL){
  741                 free(dc, M_DEVBUF);
  742                 return (ENOMEM);
  743         }
  744                                 
  745         *curxp = 0;
  746         *curyp = 0;
  747         *cookiep = dc; 
  748         hpcfb_allocattr(*cookiep, WSCOL_WHITE, WSCOL_BLACK, 0, attrp);
  749         DPRINTF(("%s(%d): hpcfb_alloc_screen(): 0x%p\n",
  750             __FILE__, __LINE__, dc));
  751 
  752         return (0);
  753 }
  754 
  755 static void
  756 hpcfb_free_screen(void *v, void *cookie)
  757 {
  758         struct hpcfb_devconfig *dc = cookie;
  759 
  760         DPRINTF(("%s(%d): hpcfb_free_screen(0x%p)\n",
  761             __FILE__, __LINE__, cookie));
  762 #ifdef DIAGNOSTIC
  763         if (dc == &hpcfb_console_dc)
  764                 panic("hpcfb_free_screen: console");
  765 #endif
  766         free(dc->dc_tvram, M_DEVBUF);
  767         free(dc, M_DEVBUF);
  768 }
  769 
  770 static int
  771 hpcfb_show_screen(void *v, void *cookie, int waitok,
  772     void (*cb)(void *, int, int), void *cbarg)
  773 {
  774         struct hpcfb_softc *sc = v;
  775         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
  776         struct hpcfb_devconfig *odc;
  777 
  778         DPRINTF(("%s(%d): hpcfb_show_screen(0x%p)\n",
  779             __FILE__, __LINE__, dc));
  780 
  781         odc = sc->sc_dc;
  782 
  783         if (dc == NULL || odc == dc) {
  784                 hpcfb_refresh_screen(sc);
  785                 return (0);
  786         }
  787 
  788         if (odc != NULL) {
  789                 odc->dc_state |= HPCFB_DC_SWITCHREQ;
  790 
  791                 if ((odc->dc_state&HPCFB_DC_DRAWING) != 0) {
  792                         odc->dc_state |= HPCFB_DC_ABORT;
  793                 }
  794         }
  795 
  796         sc->sc_wantedscreen = cookie;
  797         sc->sc_switchcb = cb;
  798         sc->sc_switchcbarg = cbarg;
  799         if (cb) {
  800                 callout_reset(&sc->sc_switch_callout, 0,
  801                     (void(*)(void *))hpcfb_doswitch, sc);
  802                 return (EAGAIN);
  803         }
  804 
  805         hpcfb_doswitch(sc);
  806         return (0);
  807 }
  808 
  809 void
  810 hpcfb_doswitch(struct hpcfb_softc *sc)
  811 {
  812         struct hpcfb_devconfig *dc;
  813         struct hpcfb_devconfig *odc;
  814 
  815         DPRINTF(("hpcfb_doswitch()\n"));
  816         odc = sc->sc_dc;
  817         dc = sc->sc_wantedscreen;
  818 
  819         if (!dc) {
  820                 (*sc->sc_switchcb)(sc->sc_switchcbarg, EIO, 0);
  821                 odc->dc_state &= ~HPCFB_DC_SWITCHREQ;
  822                 return;
  823         }
  824 
  825         if (odc == dc) {
  826                 odc->dc_state &= ~HPCFB_DC_SWITCHREQ;
  827                 return;
  828         }
  829 
  830         if (odc) {
  831 #ifdef HPCFB_JUMP
  832                 odc->dc_state |= HPCFB_DC_ABORT;
  833 #endif /* HPCFB_JUMP */
  834 
  835                 if (odc->dc_curx >= 0 && odc->dc_cury >= 0)
  836                         hpcfb_cursor_raw(odc, 0,  odc->dc_cury, odc->dc_curx);
  837                 /* disable cursor */
  838                 /* disable old screen */
  839                 odc->dc_state &= ~HPCFB_DC_CURRENT;
  840                 /* XXX, This is too dangerous.
  841                 odc->dc_rinfo.ri_bits = NULL;
  842                 */
  843         }
  844         /* switch screen to new one */
  845         dc->dc_state |= HPCFB_DC_CURRENT;
  846         dc->dc_state &= ~HPCFB_DC_ABORT;
  847         dc->dc_rinfo.ri_bits = dc->dc_fbaddr;
  848         sc->sc_dc = dc;
  849 
  850         /* redraw screen image */
  851         hpcfb_refresh_screen(sc);
  852 
  853         sc->sc_wantedscreen = NULL;
  854         if (sc->sc_switchcb)
  855                 (*sc->sc_switchcb)(sc->sc_switchcbarg, 0, 0);
  856 
  857         if (odc != NULL)
  858                 odc->dc_state &= ~HPCFB_DC_SWITCHREQ;
  859         dc->dc_state &= ~HPCFB_DC_SWITCHREQ;
  860         return;
  861 }
  862 
  863 static void
  864 hpcfb_pollc(void *v, int on)
  865 {
  866         struct hpcfb_softc *sc = v;
  867 
  868         if (sc == NULL)
  869                 return;
  870         sc->sc_polling = on;
  871         if (sc->sc_accessops->iodone)
  872                 (*sc->sc_accessops->iodone)(sc->sc_accessctx);
  873         if (on) {
  874                 hpcfb_refresh_screen(sc);
  875                 if (sc->sc_accessops->iodone)
  876                         (*sc->sc_accessops->iodone)(sc->sc_accessctx);
  877         }
  878 
  879         return;
  880 }
  881 
  882 /*
  883  * cursor
  884  */
  885 void
  886 hpcfb_cursor(void *cookie, int on, int row, int col)
  887 {
  888         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
  889 
  890         if (on) {
  891                 dc->dc_curx = col;
  892                 dc->dc_cury = row;
  893         } else {
  894                 dc->dc_curx = -1;
  895                 dc->dc_cury = -1;
  896         }
  897 
  898         hpcfb_cursor_raw(cookie, on, row, col);
  899 }
  900 
  901 void
  902 hpcfb_cursor_raw(cookie, on, row, col)
  903         void *cookie;
  904         int on, row, col;
  905 {
  906         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
  907         struct hpcfb_softc *sc = dc->dc_sc;
  908         struct rasops_info *ri = &dc->dc_rinfo;
  909         int curwidth, curheight;
  910         int xoff, yoff;
  911 
  912 #ifdef HPCFB_JUMP
  913         if (dc->dc_state&HPCFB_DC_SCROLLPENDING) {
  914                 dc->dc_state |= HPCFB_DC_UPDATE;
  915                 return;
  916         }
  917 #endif /* HPCFB_JUMP */
  918         if (!IS_DRAWABLE(dc)) {
  919                 return;
  920         }
  921 
  922         if (ri->ri_bits == NULL)
  923                 return;
  924 
  925         dc->dc_state |= HPCFB_DC_DRAWING;
  926         if (sc && sc->sc_accessops->cursor) {
  927                 xoff = col * ri->ri_font->fontwidth;
  928                 yoff = row * ri->ri_font->fontheight;
  929                 curheight = ri->ri_font->fontheight;
  930                 curwidth = ri->ri_font->fontwidth;
  931                 (*sc->sc_accessops->cursor)(sc->sc_accessctx,
  932                     on, xoff, yoff, curwidth, curheight);
  933         } else 
  934                 rasops_emul.cursor(ri, on, row, col);
  935         dc->dc_state &= ~HPCFB_DC_DRAWING;
  936 }
  937 
  938 /*
  939  * mapchar
  940  */
  941 int
  942 hpcfb_mapchar(void *cookie, int c, unsigned int *cp)
  943 {
  944         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
  945         struct rasops_info *ri = &dc->dc_rinfo;
  946 
  947         return (rasops_emul.mapchar(ri, c, cp));
  948 }
  949 
  950 /*
  951  * putchar
  952  */
  953 void
  954 hpcfb_tv_putchar(struct hpcfb_devconfig *dc, int row, int col, u_int uc,
  955     long attr)
  956 {
  957         struct hpcfb_tvrow *vscn = dc->dc_tvram;
  958         struct hpcfb_vchar *vc = &vscn[row].col[col];
  959         struct hpcfb_vchar *vcb;
  960 
  961         if (vscn == 0)
  962                 return;
  963 
  964         dc->dc_state |= HPCFB_DC_TDRAWING;
  965 #ifdef HPCFB_JUMP
  966         if (row < dc->dc_min_row)
  967                 dc->dc_min_row = row;
  968         if (row > dc->dc_max_row)
  969                 dc->dc_max_row = row;
  970 
  971 #endif /* HPCFB_JUMP */
  972         if (vscn[row].maxcol +1 == col)
  973                 vscn[row].maxcol = col;
  974         else if (vscn[row].maxcol < col) {
  975                 vcb =  &vscn[row].col[vscn[row].maxcol+1];
  976                 memset(vcb, 0,
  977                     sizeof(struct hpcfb_vchar)*(col-vscn[row].maxcol-1));
  978                 vscn[row].maxcol = col;
  979         }
  980         vc->c = uc;
  981         vc->attr = attr;
  982         dc->dc_state &= ~HPCFB_DC_TDRAWING;
  983 #ifdef HPCFB_JUMP
  984         hpcfb_check_update(dc);
  985 #endif /* HPCFB_JUMP */
  986 }
  987 
  988 void
  989 hpcfb_putchar(void *cookie, int row, int col, u_int uc, long attr)
  990 {
  991         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
  992         struct hpcfb_softc *sc = dc->dc_sc;
  993         struct rasops_info *ri = &dc->dc_rinfo;
  994         int xoff;
  995         int yoff;
  996         int fclr, uclr;
  997         struct wsdisplay_font *font;
  998 
  999         hpcfb_tv_putchar(dc, row, col, uc, attr);
 1000 #ifdef HPCFB_JUMP
 1001         if (dc->dc_state&HPCFB_DC_SCROLLPENDING) {
 1002                 dc->dc_state |= HPCFB_DC_UPDATE;
 1003                 return;
 1004         }
 1005 #endif /* HPCFB_JUMP */
 1006 
 1007         if (!IS_DRAWABLE(dc)) {
 1008                 return;
 1009         }
 1010 
 1011         if (ri->ri_bits == NULL)
 1012                 return;
 1013 
 1014         dc->dc_state |= HPCFB_DC_DRAWING;
 1015         if (sc && sc->sc_accessops->putchar 
 1016             && (dc->dc_state&HPCFB_DC_CURRENT)) {
 1017                 font = ri->ri_font;
 1018                 yoff = row * ri->ri_font->fontheight;
 1019                 xoff =  col * ri->ri_font->fontwidth;
 1020                 fclr = ri->ri_devcmap[((u_int)attr >> 24) & 15];
 1021                 uclr = ri->ri_devcmap[((u_int)attr >> 16) & 15];
 1022 
 1023                 (*sc->sc_accessops->putchar)(sc->sc_accessctx,
 1024                     xoff, yoff, font, fclr, uclr, uc, attr);
 1025         } else
 1026                 rasops_emul.putchar(ri, row, col, uc, attr);
 1027         dc->dc_state &= ~HPCFB_DC_DRAWING;
 1028 #ifdef HPCFB_JUMP
 1029         hpcfb_check_update(dc);
 1030 #endif /* HPCFB_JUMP */
 1031 }
 1032 
 1033 /*
 1034  * copycols
 1035  */
 1036 void
 1037 hpcfb_tv_copycols(struct hpcfb_devconfig *dc, int row, int srccol, int dstcol,
 1038     int ncols)
 1039 {
 1040         struct hpcfb_tvrow *vscn = dc->dc_tvram;
 1041         struct hpcfb_vchar *svc = &vscn[row].col[srccol];
 1042         struct hpcfb_vchar *dvc = &vscn[row].col[dstcol];
 1043 
 1044         if (vscn == 0)
 1045                 return;
 1046 
 1047         dc->dc_state |= HPCFB_DC_TDRAWING;
 1048 #ifdef HPCFB_JUMP
 1049         if (row < dc->dc_min_row)
 1050                 dc->dc_min_row = row;
 1051         if (row > dc->dc_max_row)
 1052                 dc->dc_max_row = row;
 1053 #endif /* HPCFB_JUMP */
 1054 
 1055         memcpy(dvc, svc, ncols*sizeof(struct hpcfb_vchar));
 1056         if (vscn[row].maxcol < srccol+ncols-1)
 1057                 vscn[row].maxcol = srccol+ncols-1;
 1058         if (vscn[row].maxcol < dstcol+ncols-1)
 1059                 vscn[row].maxcol = dstcol+ncols-1;
 1060         dc->dc_state &= ~HPCFB_DC_TDRAWING;
 1061 #ifdef HPCFB_JUMP
 1062         hpcfb_check_update(dc);
 1063 #endif /* HPCFB_JUMP */
 1064 }
 1065 
 1066 void
 1067 hpcfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols)
 1068 {
 1069         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
 1070         struct hpcfb_softc *sc = dc->dc_sc;
 1071         struct rasops_info *ri = &dc->dc_rinfo;
 1072         int srcxoff,dstxoff;
 1073         int srcyoff,dstyoff;
 1074         int height, width;
 1075 
 1076         hpcfb_tv_copycols(dc, row, srccol, dstcol, ncols);
 1077 #ifdef HPCFB_JUMP
 1078         if (dc->dc_state&HPCFB_DC_SCROLLPENDING) {
 1079                 dc->dc_state |= HPCFB_DC_UPDATE;
 1080                 return;
 1081         }
 1082 #endif /* HPCFB_JUMP */
 1083         if (!IS_DRAWABLE(dc)) {
 1084                 return;
 1085         }
 1086 
 1087         if (ri->ri_bits == NULL)
 1088                 return;
 1089 
 1090         dc->dc_state |= HPCFB_DC_DRAWING;
 1091         if (sc && sc->sc_accessops->bitblit
 1092             && (dc->dc_state&HPCFB_DC_CURRENT)) {
 1093                 srcxoff = srccol * ri->ri_font->fontwidth;
 1094                 srcyoff = row * ri->ri_font->fontheight;
 1095                 dstxoff = dstcol * ri->ri_font->fontwidth;
 1096                 dstyoff = row * ri->ri_font->fontheight;
 1097                 width = ncols * ri->ri_font->fontwidth;
 1098                 height = ri->ri_font->fontheight;
 1099                 (*sc->sc_accessops->bitblit)(sc->sc_accessctx,
 1100                     srcxoff, srcyoff, dstxoff, dstyoff, height, width);
 1101         } else
 1102                 rasops_emul.copycols(ri, row, srccol, dstcol, ncols);
 1103         dc->dc_state &= ~HPCFB_DC_DRAWING;
 1104 #ifdef HPCFB_JUMP
 1105         hpcfb_check_update(dc);
 1106 #endif /* HPCFB_JUMP */
 1107 }
 1108 
 1109 
 1110 /*
 1111  * erasecols
 1112  */
 1113 void
 1114 hpcfb_tv_erasecols(struct hpcfb_devconfig *dc, int row, int startcol,
 1115     int ncols, long attr)
 1116 {
 1117         struct hpcfb_tvrow *vscn = dc->dc_tvram;
 1118 
 1119         if (vscn == 0)
 1120                 return;
 1121 
 1122         dc->dc_state |= HPCFB_DC_TDRAWING;
 1123 #ifdef HPCFB_JUMP
 1124         if (row < dc->dc_min_row)
 1125                 dc->dc_min_row = row;
 1126         if (row > dc->dc_max_row)
 1127                 dc->dc_max_row = row;
 1128 #endif /* HPCFB_JUMP */
 1129 
 1130         vscn[row].maxcol = startcol-1;
 1131         if (vscn[row].spacecol < startcol+ncols-1)
 1132                 vscn[row].spacecol = startcol+ncols-1;
 1133         dc->dc_state &= ~HPCFB_DC_TDRAWING;
 1134 #ifdef HPCFB_JUMP
 1135         hpcfb_check_update(dc);
 1136 #endif /* HPCFB_JUMP */
 1137 }
 1138 
 1139 void
 1140 hpcfb_erasecols(void *cookie, int row, int startcol, int ncols, long attr)
 1141 {
 1142         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
 1143         struct hpcfb_softc *sc = dc->dc_sc;
 1144         struct rasops_info *ri = &dc->dc_rinfo;
 1145         int xoff, yoff;
 1146         int width, height;
 1147 
 1148         hpcfb_tv_erasecols(dc, row, startcol, ncols, attr);
 1149 #ifdef HPCFB_JUMP
 1150         if (dc->dc_state&HPCFB_DC_SCROLLPENDING) {
 1151                 dc->dc_state |= HPCFB_DC_UPDATE;
 1152                 return;
 1153         }
 1154 #endif /* HPCFB_JUMP */
 1155         if (!IS_DRAWABLE(dc)) {
 1156                 return;
 1157         }
 1158 
 1159         if (ri->ri_bits == NULL)
 1160                 return;
 1161 
 1162         dc->dc_state |= HPCFB_DC_DRAWING;
 1163         if (sc && sc->sc_accessops->erase
 1164             && (dc->dc_state&HPCFB_DC_CURRENT)) {
 1165                 xoff = startcol * ri->ri_font->fontwidth;
 1166                 yoff = row * ri->ri_font->fontheight;
 1167                 width = ncols * ri->ri_font->fontwidth;
 1168                 height = ri->ri_font->fontheight;
 1169                 (*sc->sc_accessops->erase)(sc->sc_accessctx,
 1170                     xoff, yoff, height, width, attr);
 1171         } else 
 1172                 rasops_emul.erasecols(ri, row, startcol, ncols, attr);
 1173         dc->dc_state &= ~HPCFB_DC_DRAWING;
 1174 #ifdef HPCFB_JUMP
 1175         hpcfb_check_update(dc);
 1176 #endif /* HPCFB_JUMP */
 1177 }
 1178 
 1179 /*
 1180  * Copy rows.
 1181  */
 1182 void
 1183 hpcfb_tv_copyrows(struct hpcfb_devconfig *dc, int src, int dst, int num)
 1184 {
 1185         struct hpcfb_tvrow *vscn = dc->dc_tvram;
 1186         struct hpcfb_tvrow *svc = &vscn[src];
 1187         struct hpcfb_tvrow *dvc = &vscn[dst];
 1188         int i;
 1189         int d;
 1190 
 1191         if (vscn == 0)
 1192                 return;
 1193 
 1194         dc->dc_state |= HPCFB_DC_TDRAWING;
 1195 #ifdef HPCFB_JUMP
 1196         if (dst < dc->dc_min_row)
 1197                 dc->dc_min_row = dst;
 1198         if (dst + num > dc->dc_max_row)
 1199                 dc->dc_max_row = dst + num -1;
 1200 #endif /* HPCFB_JUMP */
 1201 
 1202         if (svc > dvc)
 1203                 d = 1;
 1204         else if (svc < dvc) {
 1205                 svc += num-1;
 1206                 dvc += num-1;
 1207                 d = -1;
 1208         } else  {
 1209                 dc->dc_state &= ~HPCFB_DC_TDRAWING;
 1210 #ifdef HPCFB_JUMP
 1211                 hpcfb_check_update(dc);
 1212 #endif /* HPCFB_JUMP */
 1213                 return; 
 1214         }
 1215 
 1216         for (i = 0; i < num; i++) {
 1217                 memcpy(&dvc->col[0], &svc->col[0], sizeof(struct hpcfb_vchar)*(svc->maxcol+1));
 1218                 if (svc->maxcol < dvc->maxcol && dvc->spacecol < dvc->maxcol)
 1219                         dvc->spacecol = dvc->maxcol;
 1220                 dvc->maxcol = svc->maxcol;
 1221                 svc+=d;
 1222                 dvc+=d;
 1223         }
 1224         dc->dc_state &= ~HPCFB_DC_TDRAWING;
 1225 #ifdef HPCFB_JUMP
 1226         hpcfb_check_update(dc);
 1227 #endif /* HPCFB_JUMP */
 1228 }
 1229 
 1230 void
 1231 hpcfb_redraw(cookie, row, num, all)
 1232         void *cookie;
 1233         int row, num;
 1234         int all;
 1235 {
 1236         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
 1237         struct rasops_info *ri = &dc->dc_rinfo;
 1238         int cols;
 1239         struct hpcfb_tvrow *vscn = dc->dc_tvram;
 1240         struct hpcfb_vchar *svc;
 1241         int i, j;
 1242 
 1243 #ifdef HPCFB_JUMP
 1244         if (dc->dc_state&HPCFB_DC_SCROLLPENDING) {
 1245                 dc->dc_state |= HPCFB_DC_UPDATE;
 1246                 return;
 1247         }
 1248 #endif /* HPCFB_JUMP */
 1249         if (dc->dc_sc != NULL
 1250             && !dc->dc_sc->sc_polling
 1251             && dc->dc_sc->sc_mapping)
 1252                 return;
 1253 
 1254         dc->dc_state &= ~HPCFB_DC_ABORT;
 1255 
 1256         if (vscn == 0)
 1257                 return;
 1258 
 1259         if (!IS_DRAWABLE(dc)) {
 1260                 return;
 1261         }
 1262 
 1263         if (ri->ri_bits == NULL)
 1264                 return;
 1265 
 1266         dc->dc_state |= HPCFB_DC_DRAWING;
 1267         dc->dc_state |= HPCFB_DC_TDRAWING;
 1268         for (i = 0; i < num; i++) {
 1269                 if (dc->dc_state&HPCFB_DC_ABORT)
 1270                         break;
 1271                 if ((dc->dc_state&HPCFB_DC_CURRENT) == 0)
 1272                         break;
 1273                 cols = vscn[row+i].maxcol;
 1274                 for (j = 0; j <= cols; j++) {
 1275                         if (dc->dc_state&HPCFB_DC_ABORT)
 1276                                 continue;
 1277                         if ((dc->dc_state&HPCFB_DC_CURRENT) == 0)
 1278                                 continue;
 1279                         svc = &vscn[row+i].col[j];
 1280                         rasops_emul.putchar(ri, row + i, j, svc->c, svc->attr);
 1281                 }
 1282                 if (all)
 1283                         cols = dc->dc_cols-1;
 1284                 else
 1285                         cols = vscn[row+i].spacecol;
 1286                 for (; j <= cols; j++) {
 1287                         if (dc->dc_state&HPCFB_DC_ABORT)
 1288                                 continue;
 1289                         if ((dc->dc_state&HPCFB_DC_CURRENT) == 0)
 1290                                 continue;
 1291                         rasops_emul.putchar(ri, row + i, j, ' ', 0);
 1292                 }
 1293                 vscn[row+i].spacecol = 0;
 1294         }
 1295         if (dc->dc_state&HPCFB_DC_ABORT)
 1296                 dc->dc_state &= ~HPCFB_DC_ABORT;
 1297         dc->dc_state &= ~HPCFB_DC_DRAWING;
 1298         dc->dc_state &= ~HPCFB_DC_TDRAWING;
 1299 #ifdef HPCFB_JUMP
 1300         hpcfb_check_update(dc);
 1301 #endif /* HPCFB_JUMP */
 1302 }
 1303 
 1304 #ifdef HPCFB_JUMP
 1305 void
 1306 hpcfb_update(void *v)
 1307 {
 1308         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v;
 1309 
 1310         /* callout_stop(&dc->dc_scroll_ch); */
 1311         dc->dc_state &= ~HPCFB_DC_SCROLLPENDING;
 1312         if (dc->dc_curx > 0 && dc->dc_cury > 0)
 1313                 hpcfb_cursor_raw(dc, 0,  dc->dc_cury, dc->dc_curx); 
 1314         if ((dc->dc_state&HPCFB_DC_UPDATEALL)) {
 1315                 hpcfb_redraw(dc, 0, dc->dc_rows, 1);
 1316                 dc->dc_state &= ~(HPCFB_DC_UPDATE|HPCFB_DC_UPDATEALL);
 1317         } else if ((dc->dc_state&HPCFB_DC_UPDATE)) {
 1318                 hpcfb_redraw(dc, dc->dc_min_row, 
 1319                     dc->dc_max_row - dc->dc_min_row, 0);
 1320                 dc->dc_state &= ~HPCFB_DC_UPDATE;
 1321         } else {
 1322                 hpcfb_redraw(dc, dc->dc_scroll_dst, dc->dc_scroll_num, 0);
 1323         }
 1324         if (dc->dc_curx > 0 && dc->dc_cury > 0)
 1325                 hpcfb_cursor_raw(dc, 1,  dc->dc_cury, dc->dc_curx); 
 1326 }
 1327 
 1328 void
 1329 hpcfb_do_scroll(void *v)
 1330 {
 1331         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v;
 1332 
 1333         dc->dc_state |= HPCFB_DC_SCRTHREAD;     
 1334         if (dc->dc_state&(HPCFB_DC_DRAWING|HPCFB_DC_TDRAWING))
 1335                 dc->dc_state |= HPCFB_DC_SCRDELAY;
 1336         else if (dc->dc_sc != NULL && dc->dc_sc->sc_thread)
 1337                 wakeup(dc->dc_sc);
 1338         else if (dc->dc_sc != NULL && !dc->dc_sc->sc_mapping) {
 1339                 /* draw only EMUL mode */
 1340                 hpcfb_update(v);
 1341         }
 1342         dc->dc_state &= ~HPCFB_DC_SCRTHREAD;    
 1343 }
 1344 
 1345 void
 1346 hpcfb_check_update(void *v)
 1347 {
 1348         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v;
 1349 
 1350         if (dc->dc_sc != NULL 
 1351             && dc->dc_sc->sc_polling 
 1352             && (dc->dc_state&HPCFB_DC_SCROLLPENDING)){
 1353                 callout_stop(&dc->dc_scroll_ch);
 1354                 dc->dc_state &= ~HPCFB_DC_SCRDELAY;
 1355                 hpcfb_update(v);
 1356         }
 1357         else if (dc->dc_state&HPCFB_DC_SCRDELAY){
 1358                 dc->dc_state &= ~HPCFB_DC_SCRDELAY;
 1359                 hpcfb_update(v);
 1360         } else if (dc->dc_state&HPCFB_DC_UPDATEALL){
 1361                 dc->dc_state &= ~HPCFB_DC_UPDATEALL;
 1362                 hpcfb_update(v);
 1363         }
 1364 }
 1365 #endif /* HPCFB_JUMP */
 1366 
 1367 void
 1368 hpcfb_copyrows(void *cookie, int src, int dst, int num)
 1369 {
 1370         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
 1371         struct rasops_info *ri = &dc->dc_rinfo;
 1372         struct hpcfb_softc *sc = dc->dc_sc;
 1373         int srcyoff, dstyoff;
 1374         int width, height;
 1375 
 1376         hpcfb_tv_copyrows(cookie, src, dst, num);
 1377 
 1378         if (!IS_DRAWABLE(dc)) {
 1379                 return;
 1380         }
 1381 
 1382         if (ri->ri_bits == NULL)
 1383                 return;
 1384 
 1385         if (sc && sc->sc_accessops->bitblit
 1386             && (dc->dc_state&HPCFB_DC_CURRENT)) {
 1387                 dc->dc_state |= HPCFB_DC_DRAWING;
 1388                 srcyoff = src * ri->ri_font->fontheight;
 1389                 dstyoff = dst * ri->ri_font->fontheight;
 1390                 width = dc->dc_cols * ri->ri_font->fontwidth;
 1391                 height = num * ri->ri_font->fontheight;
 1392                 (*sc->sc_accessops->bitblit)(sc->sc_accessctx,
 1393                     0, srcyoff, 0, dstyoff, height, width);
 1394                 dc->dc_state &= ~HPCFB_DC_DRAWING;
 1395         }
 1396         else {
 1397 #ifdef HPCFB_JUMP
 1398                 if (sc && sc->sc_polling) {
 1399                         hpcfb_check_update(dc);
 1400                 } else if ((dc->dc_state&HPCFB_DC_SCROLLPENDING) == 0) {
 1401                         dc->dc_state |= HPCFB_DC_SCROLLPENDING;
 1402                         dc->dc_scroll = 1;
 1403                         dc->dc_scroll_src = src;
 1404                         dc->dc_scroll_dst = dst;
 1405                         dc->dc_scroll_num = num;
 1406                         callout_reset(&dc->dc_scroll_ch, hz/100, &hpcfb_do_scroll, dc);
 1407                         return;
 1408                 } else if (dc->dc_scroll++ < dc->dc_rows/HPCFB_MAX_JUMP) {
 1409                         dc->dc_state |= HPCFB_DC_UPDATE;
 1410                         return;
 1411                 } else {
 1412                         dc->dc_state &= ~HPCFB_DC_SCROLLPENDING;
 1413                         callout_stop(&dc->dc_scroll_ch);
 1414                 }
 1415                 if (dc->dc_state&HPCFB_DC_UPDATE) {
 1416                         dc->dc_state &= ~HPCFB_DC_UPDATE;
 1417                         hpcfb_redraw(cookie, dc->dc_min_row, 
 1418                             dc->dc_max_row - dc->dc_min_row, 0);
 1419                         dc->dc_max_row = 0;
 1420                         dc->dc_min_row = dc->dc_rows;
 1421                         if (dc->dc_curx > 0 && dc->dc_cury > 0)
 1422                                 hpcfb_cursor(dc, 1,  dc->dc_cury, dc->dc_curx); 
 1423                         return;
 1424                 }
 1425 #endif /* HPCFB_JUMP */
 1426                 hpcfb_redraw(cookie, dst, num, 0);
 1427         }
 1428 #ifdef HPCFB_JUMP
 1429         hpcfb_check_update(dc);
 1430 #endif /* HPCFB_JUMP */
 1431 }
 1432 
 1433 /*
 1434  * eraserows
 1435  */
 1436 void
 1437 hpcfb_tv_eraserows(struct hpcfb_devconfig *dc, int row, int nrow, long attr)
 1438 {
 1439         struct hpcfb_tvrow *vscn = dc->dc_tvram;
 1440         int cols;
 1441         int i;
 1442 
 1443         if (vscn == 0)
 1444                 return;
 1445 
 1446         dc->dc_state |= HPCFB_DC_TDRAWING;
 1447         dc->dc_state &= ~HPCFB_DC_TDRAWING;
 1448 #ifdef HPCFB_JUMP
 1449         if (row < dc->dc_min_row)
 1450                 dc->dc_min_row = row;
 1451         if (row + nrow > dc->dc_max_row)
 1452                 dc->dc_max_row = row + nrow;
 1453 #endif /* HPCFB_JUMP */
 1454 
 1455         for (i = 0; i < nrow; i++) {
 1456                 cols = vscn[row+i].maxcol;
 1457                 if (vscn[row+i].spacecol < cols)
 1458                         vscn[row+i].spacecol = cols;
 1459                 vscn[row+i].maxcol = -1;
 1460         }
 1461 #ifdef HPCFB_JUMP
 1462         hpcfb_check_update(dc);
 1463 #endif /* HPCFB_JUMP */
 1464 }
 1465 
 1466 void
 1467 hpcfb_eraserows(void *cookie, int row, int nrow, long attr)
 1468 {
 1469         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
 1470         struct hpcfb_softc *sc = dc->dc_sc;
 1471         struct rasops_info *ri = &dc->dc_rinfo;
 1472         int yoff;
 1473         int width;
 1474         int height;
 1475 
 1476         hpcfb_tv_eraserows(dc, row, nrow, attr);
 1477 #ifdef HPCFB_JUMP
 1478         if (dc->dc_state&HPCFB_DC_SCROLLPENDING) {
 1479                 dc->dc_state |= HPCFB_DC_UPDATE;
 1480                 return;
 1481         }
 1482 #endif /* HPCFB_JUMP */
 1483         if (!IS_DRAWABLE(dc)) {
 1484                 return;
 1485         }
 1486 
 1487         if (ri->ri_bits == NULL)
 1488                 return;
 1489 
 1490         dc->dc_state |= HPCFB_DC_DRAWING;
 1491         if (sc && sc->sc_accessops->erase
 1492             && (dc->dc_state&HPCFB_DC_CURRENT)) {
 1493                 yoff = row * ri->ri_font->fontheight;
 1494                 width = dc->dc_cols * ri->ri_font->fontwidth;
 1495                 height = nrow * ri->ri_font->fontheight;
 1496                 (*sc->sc_accessops->erase)(sc->sc_accessctx,
 1497                     0, yoff, height, width, attr);
 1498         } else 
 1499                 rasops_emul.eraserows(ri, row, nrow, attr);
 1500         dc->dc_state &= ~HPCFB_DC_DRAWING;
 1501 #ifdef HPCFB_JUMP
 1502         hpcfb_check_update(dc);
 1503 #endif /* HPCFB_JUMP */
 1504 }
 1505 
 1506 /*
 1507  * allocattr
 1508  */
 1509 int
 1510 hpcfb_allocattr(void *cookie, int fg, int bg, int flags, long *attrp)
 1511 {
 1512         struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie;
 1513         struct rasops_info *ri = &dc->dc_rinfo;
 1514 
 1515         return (rasops_emul.allocattr(ri, fg, bg, flags, attrp));
 1516 }

Cache object: 483bbfbd32d16cc5d62c37e985036f8e


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