root/dev/pcmcia/cfxga.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cfxga_install_function
  2. cfxga_remove_function
  3. cfxga_match
  4. cfxga_activate
  5. cfxga_attach
  6. cfxga_detach
  7. cfxga_alloc_screen
  8. cfxga_burner
  9. cfxga_free_screen
  10. cfxga_ioctl
  11. cfxga_mmap
  12. cfxga_show_screen
  13. cfxga_reset_video
  14. cfxga_reset_and_repaint
  15. cfxga_wait
  16. cfxga_synchronize
  17. cfxga_expand_char
  18. cfxga_repaint_screen
  19. cfxga_solid_fill
  20. cfxga_standalone_rop
  21. cfxga_copycols
  22. cfxga_copyrows
  23. cfxga_do_cursor
  24. cfxga_erasecols
  25. cfxga_eraserows
  26. cfxga_putchar

    1 /*      $OpenBSD: cfxga.c,v 1.14 2006/11/29 19:11:17 miod Exp $ */
    2 
    3 /*
    4  * Copyright (c) 2005, 2006, Matthieu Herrb and Miodrag Vallat
    5  *
    6  * Permission to use, copy, modify, and distribute this software for any
    7  * purpose with or without fee is hereby granted, provided that the above
    8  * copyright notice and this permission notice appear in all copies.
    9  *
   10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
   11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
   13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   17  */
   18 
   19 /*
   20  * Display driver for the Colorgraphic CompactFlash ``VoyagerVGA'' card.
   21  * based upon the Epson S1D13806 graphics chip.
   22  *
   23  * Our goals are:
   24  * - to provide a somewhat usable emulation mode for extra text display.
   25  * - to let an application (such as an X server) map the controller registers
   26  *   in order to do its own display game.
   27  *
   28  * Driving this card is somewhat a challenge since:
   29  * - its video memory is not directly accessible.
   30  * - no operation can make use of DMA.
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/kernel.h>
   35 #include <sys/device.h>
   36 #include <sys/systm.h>
   37 #include <sys/malloc.h>
   38 #include <sys/conf.h>
   39 
   40 #include <dev/pcmcia/pcmciavar.h>
   41 #include <dev/pcmcia/pcmciareg.h>
   42 
   43 #include <dev/wscons/wsconsio.h>
   44 #include <dev/wscons/wsdisplayvar.h>
   45 #include <dev/rasops/rasops.h>
   46 
   47 #include <dev/pcmcia/cfxgareg.h>
   48 
   49 /*
   50 #define CFXGADEBUG
   51 #define ENABLE_8BIT_MODES
   52 */
   53 
   54 #ifdef CFXGADEBUG
   55 #define DPRINTF(arg) printf arg
   56 #else
   57 #define DPRINTF(arg)
   58 #endif
   59 
   60 struct cfxga_screen;
   61 
   62 #define CFXGA_MODE_640x480x16   0
   63 #define CFXGA_MODE_800x600x16   1
   64 #ifdef ENABLE_8BIT_MODES
   65 #define CFXGA_MODE_640x480x8    2
   66 #define CFXGA_MODE_800x600x8    3
   67 #define CFXGA_NMODES            4
   68 #else
   69 #define CFXGA_NMODES            2
   70 #endif
   71 
   72 struct cfxga_softc {
   73         struct device sc_dev;
   74         struct pcmcia_function *sc_pf;
   75         int     sc_state;
   76 #define CS_MAPPED       0x0001
   77 #define CS_RESET        0x0002
   78 
   79         struct pcmcia_mem_handle sc_pmemh;
   80         int sc_memwin;
   81         bus_addr_t sc_offset;
   82 
   83         int sc_mode;
   84 
   85         int sc_nscreens;
   86         LIST_HEAD(, cfxga_screen) sc_scr;
   87         struct cfxga_screen *sc_active;
   88 
   89         /* wsdisplay glue */
   90         struct wsscreen_descr sc_wsd[CFXGA_NMODES];
   91         struct wsscreen_list sc_wsl;
   92         struct wsscreen_descr *sc_scrlist[CFXGA_NMODES];
   93         struct wsdisplay_emulops sc_ops;
   94         struct device *sc_wsdisplay;
   95 };
   96 
   97 int     cfxga_match(struct device *, void *,  void *);
   98 void    cfxga_attach(struct device *, struct device *, void *);
   99 int     cfxga_detach(struct device *, int);
  100 int     cfxga_activate(struct device *, enum devact);
  101 
  102 struct cfattach cfxga_ca = {
  103         sizeof(struct cfxga_softc), cfxga_match, cfxga_attach,
  104         cfxga_detach, cfxga_activate
  105 };
  106 
  107 struct cfdriver cfxga_cd = {
  108         NULL, "cfxga", DV_DULL
  109 };
  110 
  111 int     cfxga_alloc_screen(void *, const struct wsscreen_descr *, void **,
  112             int *, int *, long *);
  113 void    cfxga_burner(void *, u_int, u_int);
  114 void    cfxga_free_screen(void *, void *);
  115 int     cfxga_ioctl(void *, u_long, caddr_t, int, struct proc *);
  116 paddr_t cfxga_mmap(void *, off_t, int);
  117 int     cfxga_show_screen(void *, void *, int, void (*)(void *, int, int),
  118             void *);
  119 
  120 struct wsdisplay_accessops cfxga_accessops = {
  121         cfxga_ioctl,
  122         cfxga_mmap,
  123         cfxga_alloc_screen,
  124         cfxga_free_screen,
  125         cfxga_show_screen,
  126         NULL,
  127         NULL,
  128         NULL,
  129         cfxga_burner
  130 };
  131 
  132 /*
  133  * Per-screen structure
  134  */
  135 
  136 struct cfxga_screen {
  137         LIST_ENTRY(cfxga_screen) scr_link;
  138         struct cfxga_softc *scr_sc;     /* parent reference */
  139         struct rasops_info scr_ri;      /* raster op glue */
  140         struct wsdisplay_charcell *scr_mem;     /* backing memory */
  141 };
  142         
  143 void    cfxga_copycols(void *, int, int, int, int);
  144 void    cfxga_copyrows(void *, int, int, int);
  145 void    cfxga_do_cursor(struct rasops_info *);
  146 void    cfxga_erasecols(void *, int, int, int, long);
  147 void    cfxga_eraserows(void *, int, int, long);
  148 void    cfxga_putchar(void *, int, int, u_int, long);
  149 
  150 int     cfxga_install_function(struct pcmcia_function *);
  151 void    cfxga_remove_function(struct pcmcia_function *);
  152 
  153 int     cfxga_expand_char(struct cfxga_screen *, u_int, int, int, long);
  154 int     cfxga_repaint_screen(struct cfxga_screen *);
  155 void    cfxga_reset_video(struct cfxga_softc *);
  156 void    cfxga_reset_and_repaint(struct cfxga_softc *);
  157 int     cfxga_solid_fill(struct cfxga_screen *, int, int, int, int, int32_t);
  158 int     cfxga_standalone_rop(struct cfxga_screen *, u_int,
  159             int, int, int, int, int, int);
  160 int     cfxga_synchronize(struct cfxga_softc *);
  161 u_int   cfxga_wait(struct cfxga_softc *, u_int, u_int);
  162 
  163 #define cfxga_clear_screen(scr) \
  164         cfxga_solid_fill(scr, 0, 0, scr->scr_ri.ri_width, \
  165             scr->scr_ri.ri_height, scr->scr_ri.ri_devcmap[WSCOL_BLACK])
  166 
  167 #define cfxga_read_1(sc, addr) \
  168         bus_space_read_1((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  169             (sc)->sc_offset + (addr))
  170 #define cfxga_read_2(sc, addr) \
  171         bus_space_read_2((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  172             (sc)->sc_offset + (addr))
  173 #define cfxga_write_1(sc, addr, val) \
  174         bus_space_write_1((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  175             (sc)->sc_offset + (addr), (val))
  176 #define cfxga_write_2(sc, addr, val) \
  177         bus_space_write_2((sc)->sc_pmemh.memt, (sc)->sc_pmemh.memh, \
  178             (sc)->sc_offset + (addr), (val))
  179 
  180 #define cfxga_stop_memory_blt(sc) \
  181         (void)cfxga_read_2(sc, CFREG_BITBLT_DATA)
  182 
  183 const char *cfxga_modenames[CFXGA_NMODES] = {
  184         "640x480x16",
  185         "800x600x16",
  186 #ifdef ENABLE_8BIT_MODES
  187         "640x480x8",
  188         "800x600x8"
  189 #endif
  190 };
  191 
  192 /*
  193  * This card is very poorly engineered, specificationwise. It does not
  194  * provide any CIS information, and has no vendor/product numbers as
  195  * well: as such, there is no easy way to differentiate it from any
  196  * other cheapo PCMCIA card.
  197  *
  198  * The best we can do is probe for a chip ID. This is not perfect but better
  199  * than matching blindly. Of course this requires us to play some nasty games
  200  * behind the PCMCIA framework to be able to do this probe, and correctly fail
  201  * if this is not the card we are looking for.
  202  *
  203  * In shorter words: some card designers ought to be shot, as a service
  204  * to the community.
  205  */
  206 
  207 /*
  208  * Create the necessary pcmcia function structures to alleviate the lack
  209  * of any CIS information on this device.
  210  * Actually, we hijack the fake function created by the pcmcia framework.
  211  */
  212 int
  213 cfxga_install_function(struct pcmcia_function *pf)
  214 {
  215         struct pcmcia_config_entry *cfe;
  216 
  217         /* Get real. */
  218         pf->pf_flags &= ~PFF_FAKE;
  219 
  220         /* Tell the pcmcia framework where the CCR is. */
  221         pf->ccr_base = 0x800;
  222         pf->ccr_mask = 0x67;
  223 
  224         /* Create a simple cfe. */
  225         cfe = (struct pcmcia_config_entry *)malloc(sizeof *cfe,
  226             M_DEVBUF, M_NOWAIT);
  227         if (cfe == NULL) {
  228                 DPRINTF(("%s: cfe allocation failed\n", __func__));
  229                 return (ENOMEM);
  230         }
  231 
  232         bzero(cfe, sizeof *cfe);
  233         cfe->number = 42;       /* have to put some value... */
  234         cfe->flags = PCMCIA_CFE_IO16;
  235         cfe->iftype = PCMCIA_IFTYPE_MEMORY;
  236 
  237         SIMPLEQ_INSERT_TAIL(&pf->cfe_head, cfe, cfe_list);
  238 
  239         pcmcia_function_init(pf, cfe);
  240         return (0);
  241 }
  242 
  243 /*
  244  * Undo the changes done above.
  245  * Such a function is necessary since we need a full-blown pcmcia world
  246  * set up in order to do the device probe, but if we don't match the card,
  247  * leaving this state will cause trouble during other probes.
  248  */
  249 void
  250 cfxga_remove_function(struct pcmcia_function *pf)
  251 {
  252         struct pcmcia_config_entry *cfe;
  253 
  254         /* we are the first and only entry... */
  255         cfe = SIMPLEQ_FIRST(&pf->cfe_head);
  256         SIMPLEQ_REMOVE_HEAD(&pf->cfe_head, cfe_list);
  257         free(cfe, M_DEVBUF);
  258 
  259         /* And we're a figment of the kernel's imagination again. */
  260         pf->pf_flags |= PFF_FAKE;
  261 }
  262 
  263 int 
  264 cfxga_match(struct device *parent, void *match, void *aux)
  265 {
  266         struct pcmcia_attach_args *pa = aux;
  267         struct pcmcia_function *pf = pa->pf;
  268         struct pcmcia_mem_handle h;
  269         int rc;
  270         int win;
  271         bus_addr_t ptr;
  272         u_int8_t id = 0;
  273 
  274         if (pa->product != PCMCIA_PRODUCT_INVALID ||
  275             pa->manufacturer != PCMCIA_VENDOR_INVALID)
  276                 return (0);
  277 
  278         /* Only a card with no CIS will have a fake function... */
  279         if ((pf->pf_flags & PFF_FAKE) == 0)
  280                 return (0);
  281 
  282         if (cfxga_install_function(pf) != 0)
  283                 return (0);
  284 
  285         if (pcmcia_function_enable(pf) != 0) {
  286                 DPRINTF(("%s: function enable failed\n"));
  287                 return (0);
  288         }
  289 
  290         rc = pcmcia_mem_alloc(pf, CFXGA_MEM_RANGE, &h);
  291         if (rc != 0)
  292                 goto out;
  293 
  294         rc = pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0, CFXGA_MEM_RANGE,
  295             &h, &ptr, &win);
  296         if (rc != 0)
  297                 goto out2;
  298 
  299         id = (bus_space_read_1(h.memt, h.memh, ptr + CFREG_REV) &
  300             CR_PRODUCT_MASK) >> CR_PRODUCT_SHIFT;
  301 
  302         pcmcia_mem_unmap(pa->pf, win);
  303 out2:
  304         pcmcia_mem_free(pa->pf, &h);
  305 out:
  306         pcmcia_function_disable(pf);
  307         cfxga_remove_function(pf);
  308 
  309         /*
  310          * Be sure to return a value greater than pccom's if we match,
  311          * otherwise it can win due to the way config(8) will order devices...
  312          */
  313         return (id == PRODUCT_S1D13806 ? 10 : 0);
  314 }
  315 
  316 int
  317 cfxga_activate(struct device *dev, enum devact act)
  318 {
  319         struct cfxga_softc *sc = (void *)dev;
  320 
  321         switch (act) {
  322         case DVACT_ACTIVATE:
  323                 if (pcmcia_function_enable(sc->sc_pf) != 0) {
  324                         printf("%s: function enable failed\n",
  325                             sc->sc_dev.dv_xname);
  326                 } else {
  327                         cfxga_reset_and_repaint(sc);
  328                 }
  329                 break;
  330         case DVACT_DEACTIVATE:
  331                 pcmcia_function_disable(sc->sc_pf);
  332                 break;
  333         }
  334         return (0);
  335 }
  336 
  337 void 
  338 cfxga_attach(struct device *parent, struct device *self, void *aux)
  339 {
  340         struct cfxga_softc *sc = (void *)self;
  341         struct pcmcia_attach_args *pa = aux;
  342         struct pcmcia_function *pf = pa->pf;
  343         struct wsemuldisplaydev_attach_args waa;
  344         struct wsscreen_descr *wsd;
  345         u_int i;
  346 
  347         LIST_INIT(&sc->sc_scr);
  348         sc->sc_nscreens = 0;
  349         sc->sc_pf = pf;
  350 
  351         if (cfxga_install_function(pf) != 0) {
  352                 printf(": pcmcia function setup failed\n");
  353                 return;
  354         }
  355 
  356         if (pcmcia_function_enable(pf)) {
  357                 printf(": function enable failed\n");
  358                 return;
  359         }
  360 
  361         if (pcmcia_mem_alloc(pf, CFXGA_MEM_RANGE, &sc->sc_pmemh) != 0) {
  362                 printf(": can't allocate memory space\n");
  363                 return;
  364         }
  365 
  366         if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, 0, CFXGA_MEM_RANGE,
  367             &sc->sc_pmemh, &sc->sc_offset, &sc->sc_memwin) != 0) {
  368                 printf(": can't map frame buffer registers\n");
  369                 pcmcia_mem_free(pf, &sc->sc_pmemh);
  370                 return;
  371         }
  372 
  373         SET(sc->sc_state, CS_MAPPED);
  374 
  375         printf("\n");
  376 
  377         sc->sc_mode = WSDISPLAYIO_MODE_EMUL;
  378 
  379         /*
  380          * We actually defer real initialization to the creation of the
  381          * first wsdisplay screen, since we do not know which mode to pick
  382          * yet.
  383          */
  384 
  385         for (wsd = sc->sc_wsd, i = 0; i < CFXGA_NMODES; wsd++, i++) {
  386                 strlcpy(wsd->name, cfxga_modenames[i], sizeof(wsd->name));
  387                 wsd->textops = &sc->sc_ops;
  388                 sc->sc_scrlist[i] = wsd;
  389         }
  390         sc->sc_wsl.nscreens = CFXGA_NMODES;
  391         sc->sc_wsl.screens = (const struct wsscreen_descr **)sc->sc_scrlist;
  392 
  393         waa.console = 0;
  394         waa.scrdata = &sc->sc_wsl;
  395         waa.accessops = &cfxga_accessops;
  396         waa.accesscookie = sc;
  397         waa.defaultscreens = 1;
  398 
  399         if ((sc->sc_wsdisplay =
  400             config_found(self, &waa, wsemuldisplaydevprint)) == NULL) {
  401                 /* otherwise wscons will do this */
  402                 if (sc->sc_active != NULL)
  403                         cfxga_clear_screen(sc->sc_active);
  404                 else
  405                         cfxga_burner(sc, 0, 0);
  406         }
  407 }
  408 
  409 int
  410 cfxga_detach(struct device *dev, int flags)
  411 {
  412         struct cfxga_softc *sc = (void *)dev;
  413 
  414         /*
  415          * Detach all children, and hope wsdisplay detach code is correct...
  416          */
  417         if (sc->sc_wsdisplay != NULL) {
  418                 config_detach(sc->sc_wsdisplay, DETACH_FORCE);
  419                 /* sc->sc_wsdisplay = NULL; */
  420         }
  421 
  422         if (ISSET(sc->sc_state, CS_MAPPED)) {
  423                 pcmcia_mem_unmap(sc->sc_pf, sc->sc_memwin);
  424                 pcmcia_mem_free(sc->sc_pf, &sc->sc_pmemh);
  425                 /* CLR(sc->sc_state, CS_MAPPED); */
  426         }
  427 
  428         return (0);
  429 }
  430 
  431 /*
  432  * Wscons operations
  433  */
  434 
  435 int
  436 cfxga_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
  437     int *curxp, int *curyp, long *attrp)
  438 {
  439         struct cfxga_softc *sc = v;
  440         struct cfxga_screen *scr;
  441         struct rasops_info *ri;
  442         u_int mode, width, height, depth, scrsize;
  443 
  444         scr = malloc(sizeof *scr, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
  445         if (scr == NULL)
  446                 return (ENOMEM);
  447         bzero(scr, sizeof *scr);
  448 
  449         mode = type - sc->sc_wsd;
  450 #ifdef DIAGNOSTIC
  451         if (mode >= CFXGA_NMODES)
  452                 mode = CFXGA_MODE_640x480x16;
  453 #endif
  454         switch (mode) {
  455         default:
  456         case CFXGA_MODE_640x480x16:
  457                 width = 640;
  458                 height = 480;
  459                 depth = 16;
  460                 break;
  461         case CFXGA_MODE_800x600x16:
  462                 width = 800;
  463                 height = 600;
  464                 depth = 16;
  465                 break;
  466 #ifdef ENABLE_8BIT_MODES
  467         case CFXGA_MODE_640x480x8:
  468                 width = 640;
  469                 height = 480;
  470                 depth = 8;
  471                 break;
  472         case CFXGA_MODE_800x600x8:
  473                 width = 800;
  474                 height = 600;
  475                 depth = 8;
  476                 break;
  477 #endif
  478         }
  479 
  480         ri = &scr->scr_ri;
  481         ri->ri_hw = (void *)scr;
  482         ri->ri_bits = NULL;
  483         ri->ri_depth = depth;
  484         ri->ri_width = width;
  485         ri->ri_height = height;
  486         ri->ri_stride = width * depth / 8;
  487         ri->ri_flg = 0;
  488 
  489         /* swap B and R at 16 bpp */
  490         if (depth == 16) {
  491                 ri->ri_rnum = 5;
  492                 ri->ri_rpos = 11;
  493                 ri->ri_gnum = 6;
  494                 ri->ri_gpos = 5;
  495                 ri->ri_bnum = 5;
  496                 ri->ri_bpos = 0;
  497         }
  498 
  499         if (type->nrows == 0)   /* first screen creation */
  500                 rasops_init(ri, 100, 100);
  501         else
  502                 rasops_init(ri, type->nrows, type->ncols);
  503 
  504         /*
  505          * Allocate backing store to remember non-visible screen contents in
  506          * emulation mode.
  507          */
  508         scrsize = ri->ri_rows * ri->ri_cols * sizeof(struct wsdisplay_charcell);
  509         scr->scr_mem = malloc(scrsize, M_DEVBUF, cold ? M_NOWAIT : M_WAITOK);
  510         if (scr->scr_mem == NULL) {
  511                 free(scr, M_DEVBUF);
  512                 return (ENOMEM);
  513         }
  514         bzero(scr->scr_mem, scrsize);
  515 
  516         ri->ri_ops.copycols = cfxga_copycols;
  517         ri->ri_ops.copyrows = cfxga_copyrows;
  518         ri->ri_ops.erasecols = cfxga_erasecols;
  519         ri->ri_ops.eraserows = cfxga_eraserows;
  520         ri->ri_ops.putchar = cfxga_putchar;
  521         ri->ri_do_cursor = cfxga_do_cursor;
  522 
  523         /*
  524          * Finish initializing our screen descriptions, now that we know
  525          * the actual console emulation parameters.
  526          */
  527         if (type->nrows == 0) {
  528                 struct wsscreen_descr *wsd = (struct wsscreen_descr *)type;
  529 
  530                 wsd->nrows = ri->ri_rows;
  531                 wsd->ncols = ri->ri_cols;
  532                 bcopy(&ri->ri_ops, &sc->sc_ops, sizeof(sc->sc_ops));
  533                 wsd->fontwidth = ri->ri_font->fontwidth;
  534                 wsd->fontheight = ri->ri_font->fontheight;
  535                 wsd->capabilities = ri->ri_caps;
  536         }
  537 
  538         scr->scr_sc = sc;
  539         LIST_INSERT_HEAD(&sc->sc_scr, scr, scr_link);
  540         sc->sc_nscreens++;
  541 
  542         ri->ri_ops.alloc_attr(ri, 0, 0, 0, attrp);
  543 
  544         *cookiep = ri;
  545         *curxp = *curyp = 0;
  546         
  547         return (0);
  548 }
  549 
  550 void
  551 cfxga_burner(void *v, u_int on, u_int flags)
  552 {
  553         struct cfxga_softc *sc = (void *)v;
  554         u_int8_t mode;
  555 
  556         mode = cfxga_read_1(sc, CFREG_MODE) & LCD_MODE_SWIVEL_BIT_0;
  557 
  558         if (on)
  559                 cfxga_write_1(sc, CFREG_MODE, mode | MODE_CRT);
  560         else
  561                 cfxga_write_1(sc, CFREG_MODE, mode | MODE_NO_DISPLAY);
  562 }
  563 
  564 void
  565 cfxga_free_screen(void *v, void *cookie)
  566 {
  567         struct cfxga_softc *sc = v;
  568         struct rasops_info *ri = cookie;
  569         struct cfxga_screen *scr = ri->ri_hw;
  570 
  571         LIST_REMOVE(scr, scr_link);
  572         sc->sc_nscreens--;
  573 
  574         if (scr == sc->sc_active) {
  575                 sc->sc_active = NULL;
  576                 cfxga_burner(sc, 0, 0);
  577         }
  578 
  579         free(scr->scr_mem, M_DEVBUF);
  580         free(scr, M_DEVBUF);
  581 }
  582 
  583 int
  584 cfxga_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  585 {
  586         struct cfxga_softc *sc = v;
  587         struct cfxga_screen *scr;
  588         struct wsdisplay_fbinfo *wdf;
  589         int mode;
  590 
  591         switch (cmd) {
  592         case WSDISPLAYIO_GTYPE:
  593                 *(u_int *)data = WSDISPLAY_TYPE_CFXGA;
  594                 break;
  595 
  596         case WSDISPLAYIO_GINFO:
  597                 wdf = (struct wsdisplay_fbinfo *)data;
  598                 scr = sc->sc_active;
  599                 if (scr == NULL) {
  600                         /* try later...after running wsconscfg to add screens */
  601                         wdf->height = wdf->width = wdf->depth = wdf->cmsize = 0;
  602                 } else {
  603                         wdf->height = scr->scr_ri.ri_height;
  604                         wdf->width = scr->scr_ri.ri_width;
  605                         wdf->depth = scr->scr_ri.ri_depth;
  606                         wdf->cmsize = scr->scr_ri.ri_depth <= 8 ?
  607                             (1 << scr->scr_ri.ri_depth) : 0;
  608                 }
  609                 break;
  610 
  611         case WSDISPLAYIO_SMODE:
  612                 mode = *(u_int *)data;
  613                 if (mode == sc->sc_mode)
  614                         break;
  615                 switch (mode) {
  616                 case WSDISPLAYIO_MODE_EMUL:
  617                         cfxga_reset_and_repaint(sc);
  618                         break;
  619                 case WSDISPLAYIO_MODE_MAPPED:
  620                         break;
  621                 default:
  622                         return (EINVAL);
  623                 }
  624                 sc->sc_mode = mode;
  625                 break;
  626 
  627         /* these operations are handled by the wscons code... */
  628         case WSDISPLAYIO_GVIDEO:
  629         case WSDISPLAYIO_SVIDEO:
  630                 break;
  631 
  632         /* these operations are not supported... */
  633         case WSDISPLAYIO_GETCMAP:
  634         case WSDISPLAYIO_PUTCMAP:
  635         case WSDISPLAYIO_LINEBYTES:
  636         case WSDISPLAYIO_GCURPOS:
  637         case WSDISPLAYIO_SCURPOS:
  638         case WSDISPLAYIO_GCURMAX:
  639         case WSDISPLAYIO_GCURSOR:
  640         case WSDISPLAYIO_SCURSOR:
  641         default:
  642                 return (-1);
  643         }
  644 
  645         return (0);
  646 }
  647 
  648 paddr_t
  649 cfxga_mmap(void *v, off_t off, int prot)
  650 {
  651         return (-1);
  652 }
  653 
  654 int
  655 cfxga_show_screen(void *v, void *cookie, int waitok,
  656     void (*cb)(void *, int, int), void *cbarg)
  657 {
  658         struct cfxga_softc *sc = v;
  659         struct rasops_info *ri = cookie;
  660         struct cfxga_screen *scr = ri->ri_hw, *old;
  661 
  662         old = sc->sc_active;
  663         if (old == scr)
  664                 return (0);
  665 
  666         sc->sc_active = scr;
  667         cfxga_reset_and_repaint(sc);    /* will turn video on if scr != NULL */
  668 
  669         return (0);
  670 }
  671 
  672 /*
  673  * Real frame buffer operations
  674  */
  675 
  676 void
  677 cfxga_reset_video(struct cfxga_softc *sc)
  678 {
  679         struct cfxga_screen *scr = sc->sc_active;
  680         struct rasops_info *ri;
  681 #ifdef ENABLE_8BIT_MODES
  682         const u_int8_t *cmap;
  683         u_int i;
  684 #endif
  685 
  686         /*
  687          * Reset controller
  688          */
  689 
  690         /* need to write to both REV and MISC at the same time */
  691         cfxga_write_2(sc, CFREG_REV, 0x80 | (CM_REGSEL << 8));
  692         delay(25000);   /* maintain reset for a short while */
  693         /* need to write to both REV and MISC at the same time */
  694         cfxga_write_2(sc, CFREG_REV, 0 | (CM_MEMSEL << 8));
  695         delay(25000);
  696         /* stop any pending blt operation */
  697         cfxga_write_2(sc, CFREG_BITBLT_CONTROL, 0);
  698         cfxga_stop_memory_blt(sc);
  699         cfxga_write_1(sc, CFREG_MODE, 0);       /* disable all displays */
  700 
  701         /*
  702          * Setup common video mode parameters.
  703          */
  704 
  705         cfxga_write_2(sc, CFREG_MEMCLK, MEMCLK_SRC_CLK3);
  706 #if 0
  707         cfxga_write_1(sc, CFREG_LCD_PCLK, LCD_PCLK_SRC_CLKI | LCD_PCLK_DIV_1);
  708         cfxga_write_1(sc, CFREG_MPLUG_CLK,
  709             MPLUG_PCLK_SRC_CLKI2 | MPLUG_PCLK_DIV_1);
  710 #endif
  711         cfxga_write_2(sc, CFREG_CRTTV_PCLK, CRT_PCLK_SRC_CLKI | CRT_PCLK_DIV_1);
  712         cfxga_write_2(sc, CFREG_WSTATE, WSTATE_MCLK);
  713 
  714         /* MEMCNF and DRAM_RFRSH need to be programmed at the same time */
  715         cfxga_write_2(sc, CFREG_MEMCNF,
  716             MEMCNF_SDRAM_INIT | (DRAM_RFRSH_50MHZ << 8));
  717         delay(250);
  718         cfxga_write_2(sc, CFREG_DRAM_TIMING, DRAM_TIMING_50MHZ);
  719 
  720         /*
  721          * Setup mode-dependent parameters.
  722          */
  723         if (scr == NULL)
  724                 return;
  725 
  726         ri = &scr->scr_ri;
  727         switch (scr->scr_ri.ri_width) {
  728         default:
  729         case 640:
  730                 cfxga_write_1(sc, CFREG_CRT_HWIDTH, (640 / 8) - 1);
  731                 /* HNDISP and HSTART need to be programmed at the same time */
  732                 cfxga_write_2(sc, CFREG_CRT_HNDISP, 23 | (2 << 8));
  733                 cfxga_write_1(sc, CFREG_CRT_HPULSE, 4);
  734                 cfxga_write_2(sc, CFREG_CRT_VHEIGHT, 480 - 1);
  735                 /* VNDISP and VSTART need to be programmed at the same time */
  736                 cfxga_write_2(sc, CFREG_CRT_VNDISP, 39 | (8 << 8));
  737                 cfxga_write_1(sc, CFREG_CRT_VPULSE, 2);
  738                 break;
  739         case 800:
  740                 cfxga_write_1(sc, CFREG_CRT_HWIDTH, (800 / 8) - 1);
  741                 /* HNDISP and HSTART need to be programmed at the same time */
  742                 cfxga_write_2(sc, CFREG_CRT_HNDISP, 27 | (2 << 8));
  743                 cfxga_write_1(sc, CFREG_CRT_HPULSE, 4);
  744                 cfxga_write_2(sc, CFREG_CRT_VHEIGHT, 600 - 1);
  745                 /* VNDISP and VSTART need to be programmed at the same time */
  746                 cfxga_write_2(sc, CFREG_CRT_VNDISP, 25 | (8 << 8));
  747                 cfxga_write_1(sc, CFREG_CRT_VPULSE, 2);
  748                 break;
  749         }
  750         cfxga_write_1(sc, CFREG_CRT_MODE,
  751             ri->ri_depth == 16 ? CRT_MODE_16BPP : CRT_MODE_8BPP);
  752         cfxga_write_2(sc, CFREG_CRT_START_LOW, 0);
  753         cfxga_write_1(sc, CFREG_CRT_START_HIGH, 0);
  754         cfxga_write_2(sc, CFREG_CRT_MEMORY, ri->ri_width * ri->ri_depth / 16);
  755         cfxga_write_1(sc, CFREG_CRT_PANNING, 0);
  756         cfxga_write_1(sc, CFREG_CRT_FIFO_THRESHOLD_HIGH, 0);
  757         cfxga_write_1(sc, CFREG_CRT_FIFO_THRESHOLD_LOW, 0);
  758         cfxga_write_1(sc, CFREG_CRT_CURSOR_CONTROL, CURSOR_INACTIVE);
  759 
  760 #ifdef ENABLE_8BIT_MODES
  761         /*
  762          * On 8bpp video modes, program the LUT
  763          */
  764         if (ri->ri_depth == 8) {
  765 #if 0
  766                 /* Wait for retrace */
  767                 while ((cfxga_read_1(sc, CFREG_CRT_VNDISP) &
  768                     CRT_VNDISP_STATUS) == 0)
  769                         delay(1);
  770 #endif
  771                 cfxga_write_1(sc, CFREG_LUT_MODE, LUT_CRT);
  772                 cfxga_write_1(sc, CFREG_LUT_ADDRESS, 0); /* autoincrements */
  773                 cmap = rasops_cmap;
  774                 for (i = 256 * 3; i != 0; i--)
  775                         cfxga_write_1(sc, CFREG_LUT_DATA, *cmap++ & 0xf0);
  776         }
  777 #endif
  778 
  779         cfxga_write_1(sc, CFREG_TV_CONTROL,
  780             TV_LUMINANCE_FILTER | TV_SVIDEO_OUTPUT | TV_NTSC_OUTPUT);
  781 
  782         cfxga_write_1(sc, CFREG_POWER_CONF, POWERSAVE_MBO);
  783         cfxga_write_1(sc, CFREG_WATCHDOG, 0);
  784 
  785         cfxga_write_1(sc, CFREG_MODE, MODE_CRT);
  786         delay(25000);
  787 }
  788 
  789 void
  790 cfxga_reset_and_repaint(struct cfxga_softc *sc)
  791 {
  792         cfxga_reset_video(sc);
  793 
  794         if (sc->sc_active != NULL)
  795                 cfxga_repaint_screen(sc->sc_active);
  796         else
  797                 cfxga_burner(sc, 0, 0);
  798 }
  799 
  800 /*
  801  * Wait for the blitter to be in a given state.
  802  */
  803 u_int
  804 cfxga_wait(struct cfxga_softc *sc, u_int mask, u_int result)
  805 {
  806         u_int tries;
  807 
  808         for (tries = 10000; tries != 0; tries--) {
  809                 if ((cfxga_read_1(sc, CFREG_BITBLT_CONTROL) & mask) == result)
  810                         break;
  811                 delay(10);
  812         }
  813 
  814         return (tries);
  815 }
  816 
  817 /*
  818  * Wait for all pending blitter operations to be complete.
  819  * Returns non-zero if the blitter got stuck.
  820  */
  821 int
  822 cfxga_synchronize(struct cfxga_softc *sc)
  823 {
  824         /* Wait for previous operations to complete */
  825         if (cfxga_wait(sc, BITBLT_ACTIVE, 0) == 0) {
  826                 DPRINTF(("%s: not ready\n", __func__));
  827                 if (ISSET(sc->sc_state, CS_RESET))
  828                         return (EAGAIN);
  829                 else {
  830                         DPRINTF(("%s: resetting...\n", sc->sc_dev.dv_xname));
  831                         SET(sc->sc_state, CS_RESET);
  832                         cfxga_reset_and_repaint(sc);
  833                         CLR(sc->sc_state, CS_RESET);
  834                 }
  835         }
  836         cfxga_stop_memory_blt(sc);
  837         return (0);
  838 }
  839 
  840 /*
  841  * Display a character.
  842  */
  843 int
  844 cfxga_expand_char(struct cfxga_screen *scr, u_int uc, int x, int y, long attr)
  845 {
  846         struct cfxga_softc *sc = scr->scr_sc;
  847         struct rasops_info *ri = &scr->scr_ri;
  848         struct wsdisplay_font *font = ri->ri_font;
  849         u_int pos, sts, fifo_avail, chunk;
  850         u_int8_t *fontbits;
  851         int bg, fg, ul;
  852         u_int i;
  853         int rc;
  854 
  855         pos = (y * ri->ri_width + x) * ri->ri_depth / 8;
  856         fontbits = (u_int8_t *)(font->data + (uc - font->firstchar) *
  857             ri->ri_fontscale);
  858         ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, &ul);
  859 
  860         /* Wait for previous operations to complete */
  861         if ((rc = cfxga_synchronize(sc)) != 0)
  862                 return (rc);
  863 
  864         cfxga_write_2(sc, CFREG_COLOR_EXPANSION,
  865             ((font->fontwidth - 1) & 7) | (OP_COLOR_EXPANSION << 8));
  866         cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, font->fontwidth <= 8 ? 0 : 1);
  867         cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, 0);
  868         cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, pos);
  869         cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, pos >> 16);
  870         cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
  871             ri->ri_width * ri->ri_depth / 16);
  872         cfxga_write_2(sc, CFREG_BITBLT_WIDTH, font->fontwidth - 1);
  873         cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, font->fontheight - 1);
  874         cfxga_write_2(sc, CFREG_BITBLT_FG, ri->ri_devcmap[fg]);
  875         cfxga_write_2(sc, CFREG_BITBLT_BG, ri->ri_devcmap[bg]);
  876         cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
  877             (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
  878 
  879         if (cfxga_wait(sc, BITBLT_ACTIVE, BITBLT_ACTIVE) == 0)
  880                 goto fail;      /* unlikely */
  881         fifo_avail = 0;
  882 
  883         for (i = font->fontheight; i != 0; i--) {
  884                 /*
  885                  * Find out how much words we can feed before
  886                  * a FIFO check is needed.
  887                  */
  888                 if (fifo_avail == 0) {
  889                         sts = cfxga_read_1(sc, CFREG_BITBLT_CONTROL);
  890                         if ((sts & BITBLT_FIFO_NOT_EMPTY) == 0)
  891                                 fifo_avail = font->fontwidth <= 8 ? 2 : 1;
  892                         else if ((sts & BITBLT_FIFO_HALF_FULL) == 0)
  893                                 fifo_avail = font->fontwidth <= 8 ? 1 : 0;
  894                         else {
  895                                 /*
  896                                  * Let the cheap breathe for a short while.
  897                                  * If this is not enough to free some FIFO
  898                                  * entries, abort the operation.
  899                                  */
  900                                 if (cfxga_wait(sc, BITBLT_FIFO_FULL, 0) == 0)
  901                                         goto fail;
  902                         }
  903                 }
  904 
  905                 if (font->fontwidth <= 8) {
  906                         chunk = *fontbits;
  907                         if (ul && i == 1)
  908                                 chunk = 0xff;
  909                 } else {
  910                         chunk = *(u_int16_t *)fontbits;
  911                         if (ul && i == 1)
  912                                 chunk = 0xffff;
  913                 }
  914                 cfxga_write_2(sc, CFREG_BITBLT_DATA, chunk);
  915                 fontbits += font->stride;
  916                 fifo_avail--;
  917         }
  918 
  919         return (0);
  920 
  921 fail:
  922         DPRINTF(("%s: abort\n", __func__));
  923         cfxga_write_2(sc, CFREG_BITBLT_CONTROL, 0);
  924         cfxga_stop_memory_blt(sc);
  925         return (EINTR);
  926 }
  927 
  928 /*
  929  * Copy a memory bitmap to the frame buffer.
  930  *
  931  * This is slow - we only use this to repaint the whole frame buffer on
  932  * screen switches.
  933  */
  934 int
  935 cfxga_repaint_screen(struct cfxga_screen *scr)
  936 {
  937         struct wsdisplay_charcell *cell = scr->scr_mem;
  938         struct rasops_info *ri = &scr->scr_ri;
  939         int x, y, cx, cy, lx, ly;
  940         int fg, bg;
  941         int rc;
  942 
  943         cfxga_clear_screen(scr);
  944 
  945         cx = ri->ri_font->fontwidth;
  946         cy = ri->ri_font->fontheight;
  947 
  948         for (ly = 0, y = ri->ri_yorigin; ly < ri->ri_rows; ly++, y += cy) {
  949                 for (lx = 0, x = ri->ri_xorigin; lx < ri->ri_cols;
  950                     lx++, x += cx) {
  951                         if (cell->uc == 0 || cell->uc == ' ') {
  952                                 ri->ri_ops.unpack_attr(ri, cell->attr,
  953                                     &fg, &bg, NULL);
  954                                 rc = cfxga_solid_fill(scr, x, y, cx, cy,
  955                                     ri->ri_devcmap[bg]);
  956                         } else {
  957                                 rc = cfxga_expand_char(scr, cell->uc,
  958                                     x, y, cell->attr);
  959                         }
  960                         cell++;
  961                         if (rc != 0)
  962                                 return (rc);
  963                 }
  964         }
  965 
  966         return (0);
  967 }
  968 
  969 /*
  970  * Perform a solid fill operation.
  971  */
  972 int
  973 cfxga_solid_fill(struct cfxga_screen *scr, int x, int y, int cx, int cy,
  974     int32_t srccolor)
  975 {
  976         struct cfxga_softc *sc = scr->scr_sc;
  977         struct rasops_info *ri = &scr->scr_ri;
  978         u_int pos;
  979         int rc;
  980 
  981         pos = (y * ri->ri_width + x) * ri->ri_depth / 8;
  982 
  983         /* Wait for previous operations to complete */
  984         if ((rc = cfxga_synchronize(sc)) != 0)
  985                 return (rc);
  986 
  987         cfxga_write_2(sc, CFREG_BITBLT_ROP, 0 | (OP_SOLID_FILL << 8));
  988         cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, pos);
  989         cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, pos >> 16);
  990         cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, pos);
  991         cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, pos >> 16);
  992         cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
  993             ri->ri_width * ri->ri_depth / 16);
  994         cfxga_write_2(sc, CFREG_BITBLT_WIDTH, cx - 1);
  995         cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, cy - 1);
  996         cfxga_write_2(sc, CFREG_BITBLT_FG, (u_int16_t)srccolor);
  997         cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
  998             (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
  999 
 1000         return (0);
 1001 }
 1002 
 1003 /*
 1004  * Perform an internal frame buffer operation.
 1005  */
 1006 int
 1007 cfxga_standalone_rop(struct cfxga_screen *scr, u_int rop, int sx, int sy,
 1008     int dx, int dy, int cx, int cy)
 1009 {
 1010         struct cfxga_softc *sc = scr->scr_sc;
 1011         struct rasops_info *ri = &scr->scr_ri;
 1012         u_int srcpos, dstpos;
 1013         u_int opcode;
 1014         int rc;
 1015 
 1016         srcpos = (sy * ri->ri_width + sx) * ri->ri_depth / 8;
 1017         dstpos = (dy * ri->ri_width + dx) * ri->ri_depth / 8;
 1018 
 1019         if (dstpos <= srcpos)
 1020                 opcode = (OP_MOVE_POSITIVE_ROP << 8) | rop;
 1021         else
 1022                 opcode = (OP_MOVE_NEGATIVE_ROP << 8) | rop;
 1023 
 1024         /* Wait for previous operations to complete */
 1025         if ((rc = cfxga_synchronize(sc)) != 0)
 1026                 return (rc);
 1027 
 1028         cfxga_write_2(sc, CFREG_BITBLT_ROP, opcode);
 1029         cfxga_write_2(sc, CFREG_BITBLT_SRC_LOW, srcpos);
 1030         cfxga_write_2(sc, CFREG_BITBLT_SRC_HIGH, srcpos >> 16);
 1031         cfxga_write_2(sc, CFREG_BITBLT_DST_LOW, dstpos);
 1032         cfxga_write_2(sc, CFREG_BITBLT_DST_HIGH, dstpos >> 16);
 1033         cfxga_write_2(sc, CFREG_BITBLT_OFFSET,
 1034             ri->ri_width * ri->ri_depth / 16);
 1035         cfxga_write_2(sc, CFREG_BITBLT_WIDTH, cx - 1);
 1036         cfxga_write_2(sc, CFREG_BITBLT_HEIGHT, cy - 1);
 1037         cfxga_write_2(sc, CFREG_BITBLT_CONTROL, BITBLT_ACTIVE |
 1038             (ri->ri_depth > 8 ? BITBLT_COLOR_16 : BITBLT_COLOR_8));
 1039 
 1040         return (0);
 1041 }
 1042 
 1043 /*
 1044  * Text console raster operations.
 1045  *
 1046  * We shadow all these operations on a memory copy of the frame buffer.
 1047  * Since we are running in emulation mode only, this could be optimized
 1048  * by only storing actual character cell values (a la mda).
 1049  */
 1050 
 1051 void
 1052 cfxga_copycols(void *cookie, int row, int src, int dst, int num)
 1053 {
 1054         struct rasops_info *ri = cookie;
 1055         struct cfxga_screen *scr = ri->ri_hw;
 1056         int sx, dx, y, cx, cy;
 1057 
 1058         /* Copy columns in backing store. */
 1059         ovbcopy(scr->scr_mem + row * ri->ri_cols + src,
 1060             scr->scr_mem + row * ri->ri_cols + dst,
 1061             num * sizeof(struct wsdisplay_charcell));
 1062 
 1063         if (scr != scr->scr_sc->sc_active)
 1064                 return;
 1065 
 1066         sx = src * ri->ri_font->fontwidth + ri->ri_xorigin;
 1067         dx = dst * ri->ri_font->fontwidth + ri->ri_xorigin;
 1068         y = row * ri->ri_font->fontheight + ri->ri_yorigin;
 1069         cx = num * ri->ri_font->fontwidth;
 1070         cy = ri->ri_font->fontheight;
 1071         cfxga_standalone_rop(scr, ROP_SRC, sx, y, dx, y, cx, cy);
 1072 }
 1073 
 1074 void
 1075 cfxga_copyrows(void *cookie, int src, int dst, int num)
 1076 {
 1077         struct rasops_info *ri = cookie;
 1078         struct cfxga_screen *scr = ri->ri_hw;
 1079         int x, sy, dy, cx, cy;
 1080 
 1081         /* Copy rows in backing store. */
 1082         ovbcopy(scr->scr_mem + src * ri->ri_cols,
 1083             scr->scr_mem + dst * ri->ri_cols,
 1084             num * ri->ri_cols * sizeof(struct wsdisplay_charcell));
 1085 
 1086         if (scr != scr->scr_sc->sc_active)
 1087                 return;
 1088 
 1089         x = ri->ri_xorigin;
 1090         sy = src * ri->ri_font->fontheight + ri->ri_yorigin;
 1091         dy = dst * ri->ri_font->fontheight + ri->ri_yorigin;
 1092         cx = ri->ri_emuwidth;
 1093         cy = num * ri->ri_font->fontheight;
 1094         cfxga_standalone_rop(scr, ROP_SRC, x, sy, x, dy, cx, cy);
 1095 }
 1096 
 1097 void
 1098 cfxga_do_cursor(struct rasops_info *ri)
 1099 {
 1100         struct cfxga_screen *scr = ri->ri_hw;
 1101         int x, y, cx, cy;
 1102 
 1103         if (scr != scr->scr_sc->sc_active)
 1104                 return;
 1105 
 1106         x = ri->ri_ccol * ri->ri_font->fontwidth + ri->ri_xorigin;
 1107         y = ri->ri_crow * ri->ri_font->fontheight + ri->ri_yorigin;
 1108         cx = ri->ri_font->fontwidth;
 1109         cy = ri->ri_font->fontheight;
 1110         cfxga_standalone_rop(scr, ROP_ONES ^ ROP_SRC /* i.e. not SRC */,
 1111             x, y, x, y, cx, cy);
 1112 }
 1113 
 1114 void
 1115 cfxga_erasecols(void *cookie, int row, int col, int num, long attr)
 1116 {
 1117         struct rasops_info *ri = cookie;
 1118         struct cfxga_screen *scr = ri->ri_hw;
 1119         int fg, bg;
 1120         int x, y, cx, cy;
 1121 
 1122         /* Erase columns in backing store. */
 1123         for (x = col; x < col + num; x++) {
 1124                 scr->scr_mem[row * ri->ri_cols + x].uc = 0;
 1125                 scr->scr_mem[row * ri->ri_cols + x].attr = attr;
 1126         }
 1127 
 1128         if (scr != scr->scr_sc->sc_active)
 1129                 return;
 1130 
 1131         ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
 1132         x = col * ri->ri_font->fontwidth + ri->ri_xorigin;
 1133         y = row * ri->ri_font->fontheight + ri->ri_yorigin;
 1134         cx = num * ri->ri_font->fontwidth;
 1135         cy = ri->ri_font->fontheight;
 1136         cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
 1137 }
 1138 
 1139 void
 1140 cfxga_eraserows(void *cookie, int row, int num, long attr)
 1141 {
 1142         struct rasops_info *ri = cookie;
 1143         struct cfxga_screen *scr = ri->ri_hw;
 1144         int fg, bg;
 1145         int x, y, cx, cy;
 1146 
 1147         /* Erase rows in backing store. */
 1148         for (x = 0; x < ri->ri_cols; x++) {
 1149                 scr->scr_mem[row * ri->ri_cols + x].uc = 0;
 1150                 scr->scr_mem[row * ri->ri_cols + x].attr = attr;
 1151         }
 1152         for (y = 1; y < num; y++)
 1153                 ovbcopy(scr->scr_mem + row * ri->ri_cols,
 1154                     scr->scr_mem + (row + y) * ri->ri_cols,
 1155                     ri->ri_cols * sizeof(struct wsdisplay_charcell));
 1156 
 1157         if (scr != scr->scr_sc->sc_active)
 1158                 return;
 1159 
 1160         ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
 1161         x = ri->ri_xorigin;
 1162         y = row * ri->ri_font->fontheight + ri->ri_yorigin;
 1163         cx = ri->ri_emuwidth;
 1164         cy = num * ri->ri_font->fontheight;
 1165         cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
 1166 }
 1167 
 1168 void
 1169 cfxga_putchar(void *cookie, int row, int col, u_int uc, long attr)
 1170 {
 1171         struct rasops_info *ri = cookie;
 1172         struct cfxga_screen *scr = ri->ri_hw;
 1173         int x, y;
 1174 
 1175         scr->scr_mem[row * ri->ri_cols + col].uc = uc;
 1176         scr->scr_mem[row * ri->ri_cols + col].attr = attr;
 1177 
 1178         if (scr != scr->scr_sc->sc_active)
 1179                 return;
 1180 
 1181         x = col * ri->ri_font->fontwidth + ri->ri_xorigin;
 1182         y = row * ri->ri_font->fontheight + ri->ri_yorigin;
 1183 
 1184         if (uc == ' ') {
 1185                 int cx, cy, fg, bg;
 1186 
 1187                 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL);
 1188                 cx = ri->ri_font->fontwidth;
 1189                 cy = ri->ri_font->fontheight;
 1190                 cfxga_solid_fill(scr, x, y, cx, cy, ri->ri_devcmap[bg]);
 1191         } else {
 1192                 cfxga_expand_char(scr, uc, x, y, attr);
 1193         }
 1194 }

/* [<][>][^][v][top][bottom][index][help] */