Annotation of sys/dev/pcmcia/cfxga.c, Revision 1.1
1.1 ! nbrk 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: }
CVSweb