1 /* $NetBSD: cgfourteen.c,v 1.102 2026/10/13 08:19:48 macallan Exp $ */ 2 3 /* 4 * Copyright (c) 1996 5 * The President and Fellows of Harvard College. All rights reserved. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This software was developed by the Computer Systems Engineering group 10 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 11 * contributed to Berkeley. 12 * 13 * All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by Harvard University. 16 * This product includes software developed by the University of 17 * California, Lawrence Berkeley Laboratory. 18 * 19 * Redistribution and use in source and binary forms, with or without 20 * modification, are permitted provided that the following conditions 21 * are met: 22 * 1. Redistributions of source code must retain the above copyright 23 * notice, this list of conditions and the following disclaimer. 24 * 2. Redistributions in binary form must reproduce the above copyright 25 * notice, this list of conditions and the following disclaimer in the 26 * documentation and/or other materials provided with the distribution. 27 * 3. All advertising materials mentioning features or use of this software 28 * must display the following acknowledgement: 29 * This product includes software developed by the University of 30 * California, Berkeley and its contributors. 31 * This product includes software developed by Harvard University and 32 * its contributors. 33 * 4. Neither the name of the University nor the names of its contributors 34 * may be used to endorse or promote products derived from this software 35 * without specific prior written permission. 36 * 37 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 40 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 47 * SUCH DAMAGE. 48 * 49 * Based on: 50 * NetBSD: cgthree.c,v 1.28 1996/05/31 09:59:22 pk Exp 51 * NetBSD: cgsix.c,v 1.25 1996/04/01 17:30:00 christos Exp 52 */ 53 54 /* 55 * Driver for Campus-II on-board mbus-based video (cgfourteen). 56 * 57 * Does not handle interrupts, even though they can occur. 58 * 59 * XXX should defer colormap updates to vertical retrace interrupts 60 */ 61 62 #include "opt_wsemul.h" 63 #include "sx.h" 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/buf.h> 68 #include <sys/device.h> 69 #include <sys/ioctl.h> 70 #include <sys/kmem.h> 71 #include <sys/mman.h> 72 #include <sys/tty.h> 73 #include <sys/conf.h> 74 #include <dev/pci/pciio.h> 75 76 #include <uvm/uvm_extern.h> 77 78 #include <dev/sun/fbio.h> 79 #include <machine/autoconf.h> 80 #include <machine/pmap.h> 81 #include <dev/sun/fbvar.h> 82 #include <machine/cpu.h> 83 #include <dev/sbus/sbusvar.h> 84 85 #include "wsdisplay.h" 86 #include <dev/wscons/wsconsio.h> 87 #include <dev/wsfont/wsfont.h> 88 #include <dev/rasops/rasops.h> 89 90 #include <dev/wscons/wsdisplay_vconsvar.h> 91 #include <dev/wscons/wsdisplay_glyphcachevar.h> 92 93 #include <sparc/sparc/asm.h> 94 #include <sparc/dev/cgfourteenreg.h> 95 #include <sparc/dev/cgfourteenvar.h> 96 #include <sparc/dev/sxreg.h> 97 #include <sparc/dev/sxvar.h> 98 99 /* autoconfiguration driver */ 100 static int cgfourteenmatch(device_t, struct cfdata *, void *); 101 static void cgfourteenattach(device_t, device_t, void *); 102 static void cgfourteenunblank(device_t); 103 104 CFATTACH_DECL_NEW(cgfourteen, sizeof(struct cgfourteen_softc), 105 cgfourteenmatch, cgfourteenattach, NULL, NULL); 106 107 extern struct cfdriver cgfourteen_cd; 108 109 dev_type_open(cgfourteenopen); 110 dev_type_close(cgfourteenclose); 111 dev_type_ioctl(cgfourteenioctl); 112 dev_type_mmap(cgfourteenmmap); 113 dev_type_poll(cgfourteenpoll); 114 115 const struct cdevsw cgfourteen_cdevsw = { 116 .d_open = cgfourteenopen, 117 .d_close = cgfourteenclose, 118 .d_read = noread, 119 .d_write = nowrite, 120 .d_ioctl = cgfourteenioctl, 121 .d_stop = nostop, 122 .d_tty = notty, 123 .d_poll = cgfourteenpoll, 124 .d_mmap = cgfourteenmmap, 125 .d_kqfilter = nokqfilter, 126 .d_discard = nodiscard, 127 .d_flag = 0 128 }; 129 130 /* frame buffer generic driver */ 131 static struct fbdriver cgfourteenfbdriver = { 132 cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl, 133 cgfourteenpoll, cgfourteenmmap, nokqfilter 134 }; 135 136 static void cg14_set_video(struct cgfourteen_softc *, int); 137 static int cg14_get_video(struct cgfourteen_softc *); 138 static int cg14_get_cmap(struct fbcmap *, union cg14cmap *, int); 139 static int cg14_put_cmap(struct fbcmap *, union cg14cmap *, int); 140 static void cg14_load_hwcmap(struct cgfourteen_softc *, int, int); 141 static void cg14_init(struct cgfourteen_softc *); 142 static void cg14_reset(struct cgfourteen_softc *); 143 144 #if NWSDISPLAY > 0 145 static void cg14_setup_wsdisplay(struct cgfourteen_softc *, int); 146 static void cg14_init_cmap(struct cgfourteen_softc *); 147 static int cg14_putcmap(struct cgfourteen_softc *, struct wsdisplay_cmap *); 148 static int cg14_getcmap(struct cgfourteen_softc *, struct wsdisplay_cmap *); 149 static void cg14_set_depth(struct cgfourteen_softc *, int); 150 static void cg14_move_cursor(struct cgfourteen_softc *, int, int); 151 static int cg14_do_cursor(struct cgfourteen_softc *, 152 struct wsdisplay_cursor *); 153 154 #if NSX > 0 155 static void cg14_wait_idle(struct cgfourteen_softc *); 156 static void cg14_rectfill(struct cgfourteen_softc *, int, int, int, int, 157 uint32_t); 158 static void cg14_rectfill_a(void *, int, int, int, int, long); 159 static void cg14_invert(struct cgfourteen_softc *, int, int, int, int); 160 static void cg14_bitblt(void *, int, int, int, int, int, int, int); 161 static void cg14_bitblt_gc(void *, int, int, int, int, int, int, int); 162 163 static void cg14_putchar_aa(void *, int, int, u_int, long); 164 static void cg14_cursor(void *, int, int, int); 165 static void cg14_putchar(void *, int, int, u_int, long); 166 static void cg14_copycols(void *, int, int, int, int); 167 static void cg14_erasecols(void *, int, int, int, long); 168 static void cg14_copyrows(void *, int, int, int); 169 static void cg14_eraserows(void *, int, int, long); 170 static int cg14_allocattr(void *, int, int, int, long *); 171 172 /* 173 * issue ALU instruction: 174 * sxi(OPCODE, srcA, srcB, dest, count) 175 */ 176 #define sxi(inst, a, b, d, cnt) \ 177 sx_wait(sc->sc_sx); \ 178 sx_write(sc->sc_sx, SX_INSTRUCTIONS, inst((a), (b), (d), (cnt))) 179 180 /* 181 * issue memory referencing instruction: 182 * sxm(OPCODE, address, start register, count) 183 */ 184 #define sxm(inst, addr, reg, count) sta((addr) & ~7, ASI_SX, inst((reg), (count), (addr) & 7)) 185 186 #endif /* NSX > 0 */ 187 188 #endif 189 190 /* 191 * Match a cgfourteen. 192 */ 193 int 194 cgfourteenmatch(device_t parent, struct cfdata *cf, void *aux) 195 { 196 union obio_attach_args *uoba = aux; 197 struct sbus_attach_args *sa = &uoba->uoba_sbus; 198 199 /* 200 * The cgfourteen is a local-bus video adaptor, accessed directly 201 * via the processor, and not through device space or an external 202 * bus. Thus we look _only_ at the obio bus. 203 * Additionally, these things exist only on the Sun4m. 204 */ 205 206 if (uoba->uoba_isobio4 != 0 || !CPU_ISSUN4M) 207 return (0); 208 209 /* Check driver name */ 210 return (strcmp(cf->cf_name, sa->sa_name) == 0); 211 } 212 213 #if NWSDISPLAY > 0 214 static int cg14_ioctl(void *, void *, u_long, void *, int, struct lwp *); 215 static paddr_t cg14_mmap(void *, void *, off_t, int); 216 static void cg14_init_screen(void *, struct vcons_screen *, int, long *); 217 218 219 struct wsdisplay_accessops cg14_accessops = { 220 cg14_ioctl, 221 cg14_mmap, 222 NULL, /* alloc_screen */ 223 NULL, /* free_screen */ 224 NULL, /* show_screen */ 225 NULL, /* load_font */ 226 NULL, /* pollc */ 227 NULL /* scroll */ 228 }; 229 #endif 230 231 /* 232 * Attach a display. We need to notice if it is the console, too. 233 */ 234 void 235 cgfourteenattach(device_t parent, device_t self, void *aux) 236 { 237 union obio_attach_args *uoba = aux; 238 struct sbus_attach_args *sa = &uoba->uoba_sbus; 239 struct cgfourteen_softc *sc = device_private(self); 240 struct fbdevice *fb = &sc->sc_fb; 241 bus_space_handle_t bh; 242 int node; 243 volatile uint32_t *lut; 244 int i, isconsole, items; 245 uint32_t fbva[2] = {0, 0}; 246 uint32_t *ptr = fbva; 247 int ver, impl; 248 #if NSX > 0 249 device_t dv; 250 deviter_t di; 251 #endif 252 253 sc->sc_dev = self; 254 sc->sc_opens = 0; 255 node = sa->sa_node; 256 257 /* Remember cookies for cgfourteenmmap() */ 258 sc->sc_bustag = sa->sa_bustag; 259 260 fb->fb_driver = &cgfourteenfbdriver; 261 fb->fb_device = sc->sc_dev; 262 /* Mask out invalid flags from the user. */ 263 fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK; 264 265 fb->fb_type.fb_type = FBTYPE_MDICOLOR; 266 fb->fb_type.fb_depth = 32; 267 268 fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node); 269 270 fb->fb_type.fb_cmsize = CG14_CLUT_SIZE; 271 272 if (sa->sa_nreg < 2) { 273 printf("%s: only %d register sets\n", 274 device_xname(self), sa->sa_nreg); 275 return; 276 } 277 memcpy(sc->sc_physadr, sa->sa_reg, 278 sa->sa_nreg * sizeof(struct sbus_reg)); 279 280 sc->sc_vramsize = sc->sc_physadr[CG14_PXL_IDX].sbr_size; 281 fb->fb_type.fb_size = sc->sc_vramsize; 282 283 printf(": %d MB VRAM", (uint32_t)(sc->sc_vramsize >> 20)); 284 /* 285 * Now map in the 8 useful pages of registers 286 */ 287 if (sa->sa_size < 0x10000) { 288 #ifdef DIAGNOSTIC 289 printf("warning: can't find all cgfourteen registers...\n"); 290 #endif 291 sa->sa_size = 0x10000; 292 } 293 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 294 sa->sa_offset, 295 sa->sa_size, 296 BUS_SPACE_MAP_LINEAR, 297 &bh) != 0) { 298 printf("%s: cannot map control registers\n", 299 device_xname(self)); 300 return; 301 } 302 sc->sc_regh = bh; 303 sc->sc_regaddr = BUS_ADDR(sa->sa_slot, sa->sa_offset); 304 sc->sc_fbaddr = BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 305 sc->sc_physadr[CG14_PXL_IDX].sbr_offset); 306 307 sc->sc_ctl = (struct cg14ctl *) (bh); 308 sc->sc_hwc = (struct cg14curs *) (bh + CG14_OFFSET_CURS); 309 sc->sc_dac = (struct cg14dac *) (bh + CG14_OFFSET_DAC); 310 sc->sc_xlut = (struct cg14xlut *) (bh + CG14_OFFSET_XLUT); 311 sc->sc_clut1 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT1); 312 sc->sc_clut2 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT2); 313 sc->sc_clut3 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT3); 314 sc->sc_clutincr = (u_int *) (bh + CG14_OFFSET_CLUTINCR); 315 316 /* 317 * Let the user know that we're here 318 */ 319 printf(": %dx%d", 320 fb->fb_type.fb_width, fb->fb_type.fb_height); 321 322 /* 323 * Enable the video. 324 */ 325 cg14_set_video(sc, 1); 326 327 /* 328 * Grab the initial colormap 329 */ 330 lut = sc->sc_clut1->clut_lut; 331 for (i = 0; i < CG14_CLUT_SIZE; i++) 332 sc->sc_cmap.cm_chip[i] = lut[i]; 333 334 /* See if we're the console */ 335 isconsole = fb_is_console(node); 336 337 #if NWSDISPLAY > 0 338 prom_getprop(sa->sa_node, "address", 4, &items, &ptr); 339 if (fbva[1] == 0) { 340 if (sbus_bus_map( sc->sc_bustag, 341 sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 342 sc->sc_physadr[CG14_PXL_IDX].sbr_offset, 343 sc->sc_vramsize, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, 344 &bh) != 0) { 345 printf("%s: cannot map pixels\n", 346 device_xname(sc->sc_dev)); 347 return; 348 } 349 sc->sc_fb.fb_pixels = bus_space_vaddr(sc->sc_bustag, bh); 350 } else { 351 sc->sc_fb.fb_pixels = (void *)fbva[1]; 352 } 353 354 if (isconsole) 355 printf(" (console)\n"); 356 else 357 printf("\n"); 358 359 sc->sc_fbdepth = 32; 360 ver = sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK; 361 impl = sc->sc_ctl->ctl_rsr & CG14_RSR_IMPLMASK; 362 aprint_normal_dev(sc->sc_dev, "rev %d, %d CLUTs\n", 363 ver == 0 ? 1 : 2, 364 (impl & 1) == 0 ? 2 : 3); 365 366 sc->sc_depth = 8; 367 368 #if NSX > 0 369 /* see if we've got an SX to help us */ 370 sc->sc_sx = NULL; 371 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); 372 dv != NULL; 373 dv = deviter_next(&di)) { 374 if (device_is_a(dv, "sx")) { 375 sc->sc_sx = device_private(dv); 376 } 377 } 378 deviter_release(&di); 379 if (sc->sc_sx != NULL) { 380 sc->sc_fb_paddr = bus_space_mmap(sc->sc_bustag, 381 sc->sc_fbaddr, 0, 0, 0) & 0xfffff000; 382 aprint_normal_dev(sc->sc_dev, "using %s\n", 383 device_xname(sc->sc_sx->sc_dev)); 384 aprint_normal_dev(sc->sc_dev, "fb paddr: %08x\n", 385 sc->sc_fb_paddr); 386 sx_write(sc->sc_sx, SX_PAGE_BOUND_LOWER, sc->sc_fb_paddr); 387 sx_write(sc->sc_sx, SX_PAGE_BOUND_UPPER, 388 sc->sc_fb_paddr + 0x03ffffff); 389 } 390 cg14_wait_idle(sc); 391 #endif 392 cg14_setup_wsdisplay(sc, isconsole); 393 #endif 394 395 /* Attach to /dev/fb */ 396 fb_attach(&sc->sc_fb, isconsole); 397 398 } 399 400 /* 401 * Keep track of the number of opens made. In the 24-bit driver, we need to 402 * switch to 24-bit mode on the first open, and switch back to 8-bit on 403 * the last close. This kind of nonsense is needed to give screenblank 404 * a fighting chance of working. 405 */ 406 407 int 408 cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l) 409 { 410 struct cgfourteen_softc *sc; 411 int oldopens; 412 413 sc = device_lookup_private(&cgfourteen_cd, minor(dev)); 414 if (sc == NULL) 415 return(ENXIO); 416 oldopens = sc->sc_opens++; 417 418 /* Setup the cg14 as we want it, and save the original PROM state */ 419 if (oldopens == 0) /* first open only, to make screenblank work */ 420 cg14_init(sc); 421 422 return (0); 423 } 424 425 int 426 cgfourteenclose(dev_t dev, int flags, int mode, struct lwp *l) 427 { 428 struct cgfourteen_softc *sc = 429 device_lookup_private(&cgfourteen_cd, minor(dev)); 430 int opens; 431 432 opens = --sc->sc_opens; 433 if (sc->sc_opens < 0) 434 opens = sc->sc_opens = 0; 435 436 /* 437 * Restore video state to make the PROM happy, on last close. 438 */ 439 if (opens == 0) { 440 cg14_reset(sc); 441 #if NSX > 0 442 if (sc->sc_sx) 443 glyphcache_wipe(&sc->sc_gc); 444 #endif 445 } 446 return (0); 447 } 448 449 int 450 cgfourteenioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 451 { 452 struct cgfourteen_softc *sc = 453 device_lookup_private(&cgfourteen_cd, minor(dev)); 454 struct fbgattr *fba; 455 int error; 456 457 switch (cmd) { 458 459 case FBIOGTYPE: 460 *(struct fbtype *)data = sc->sc_fb.fb_type; 461 break; 462 463 case FBIOGATTR: 464 fba = (struct fbgattr *)data; 465 fba->real_type = FBTYPE_MDICOLOR; 466 fba->owner = 0; /* XXX ??? */ 467 fba->fbtype = sc->sc_fb.fb_type; 468 fba->sattr.flags = 0; 469 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 470 fba->sattr.dev_specific[0] = -1; 471 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 472 fba->emu_types[1] = -1; 473 break; 474 475 case FBIOGETCMAP: 476 return(cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap, 477 CG14_CLUT_SIZE)); 478 479 case FBIOPUTCMAP: 480 /* copy to software map */ 481 #define p ((struct fbcmap *)data) 482 error = cg14_put_cmap(p, &sc->sc_cmap, CG14_CLUT_SIZE); 483 if (error) 484 return (error); 485 /* now blast them into the chip */ 486 /* XXX should use retrace interrupt */ 487 if (sc->sc_depth == 8) 488 cg14_load_hwcmap(sc, p->index, p->count); 489 #undef p 490 break; 491 492 case FBIOGVIDEO: 493 *(int *)data = cg14_get_video(sc); 494 break; 495 496 case FBIOSVIDEO: 497 cg14_set_video(sc, *(int *)data); 498 break; 499 500 case CG14_SET_PIXELMODE: { 501 int depth = *(int *)data; 502 503 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 504 return EINVAL; 505 506 cg14_set_depth(sc, depth); 507 cg14_init_cmap(sc); 508 } 509 break; 510 default: 511 return (ENOTTY); 512 } 513 return (0); 514 } 515 516 /* 517 * Undo the effect of an FBIOSVIDEO that turns the video off. 518 */ 519 static void 520 cgfourteenunblank(device_t dev) 521 { 522 struct cgfourteen_softc *sc = device_private(dev); 523 524 cg14_set_video(sc, 1); 525 #if NWSDISPLAY > 0 526 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) { 527 cg14_set_depth(sc, 8); 528 cg14_init_cmap(sc); 529 vcons_redraw_screen(sc->sc_vd.active); 530 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 531 } 532 #endif 533 } 534 535 /* 536 * Return the address that would map the given device at the given 537 * offset, allowing for the given protection, or return -1 for error. 538 */ 539 paddr_t 540 cgfourteenmmap(dev_t dev, off_t off, int prot) 541 { 542 struct cgfourteen_softc *sc = 543 device_lookup_private(&cgfourteen_cd, minor(dev)); 544 off_t offset = -1; 545 546 if (off & PGOFSET) 547 panic("cgfourteenmmap"); 548 549 if (off < 0) 550 return (-1); 551 552 if (off >= 0 && off < 0x10000) { 553 offset = sc->sc_regaddr; 554 } else if (off >= CG14_CURSOR_VOFF && 555 off < (CG14_CURSOR_VOFF + 0x1000)) { 556 offset = sc->sc_regaddr + CG14_OFFSET_CURS; 557 off -= CG14_CURSOR_VOFF; 558 } else if (off >= CG14_DIRECT_VOFF && 559 off < (CG14_DIRECT_VOFF + sc->sc_vramsize)) { 560 offset = sc->sc_fbaddr + CG14_FB_VRAM; 561 off -= CG14_DIRECT_VOFF; 562 } else if (off >= CG14_BGR_VOFF && 563 off < (CG14_BGR_VOFF + sc->sc_vramsize)) { 564 offset = sc->sc_fbaddr + CG14_FB_CBGR; 565 off -= CG14_BGR_VOFF; 566 } else if (off >= CG14_X32_VOFF && 567 off < (CG14_X32_VOFF + (sc->sc_vramsize >> 2))) { 568 offset = sc->sc_fbaddr + CG14_FB_PX32; 569 off -= CG14_X32_VOFF; 570 } else if (off >= CG14_B32_VOFF && 571 off < (CG14_B32_VOFF + (sc->sc_vramsize >> 2))) { 572 offset = sc->sc_fbaddr + CG14_FB_PB32; 573 off -= CG14_B32_VOFF; 574 } else if (off >= CG14_G32_VOFF && 575 off < (CG14_G32_VOFF + (sc->sc_vramsize >> 2))) { 576 offset = sc->sc_fbaddr + CG14_FB_PG32; 577 off -= CG14_G32_VOFF; 578 } else if (off >= CG14_R32_VOFF && 579 off < CG14_R32_VOFF + (sc->sc_vramsize >> 2)) { 580 offset = sc->sc_fbaddr + CG14_FB_PR32; 581 off -= CG14_R32_VOFF; 582 #if NSX > 0 583 /* 584 * for convenience we also map the SX ranges here: 585 * - one page userland registers 586 * - CG14-sized IO space at 0x800000000 ( not a typo, it's above 4GB ) 587 */ 588 } else if (sc->sc_sx == NULL) { 589 return -1; 590 } else if (off >= CG14_SXREG_VOFF && 591 off < (CG14_SXREG_VOFF + 0x400)) { 592 return (bus_space_mmap(sc->sc_sx->sc_tag, sc->sc_sx->sc_uregs, 593 0, prot, BUS_SPACE_MAP_LINEAR)); 594 } else if (off >= CG14_SXIO_VOFF && 595 off < (CG14_SXIO_VOFF + 0x03ffffff)) { 596 off -= CG14_SXIO_VOFF; 597 return (bus_space_mmap(sc->sc_sx->sc_tag, 0x800000000LL, 598 sc->sc_fb_paddr + off, 599 prot, BUS_SPACE_MAP_LINEAR)); 600 #endif 601 } else 602 return -1; 603 604 return (bus_space_mmap(sc->sc_bustag, offset, off, prot, 605 BUS_SPACE_MAP_LINEAR)); 606 } 607 608 int 609 cgfourteenpoll(dev_t dev, int events, struct lwp *l) 610 { 611 612 return (seltrue(dev, events, l)); 613 } 614 615 /* 616 * Miscellaneous helper functions 617 */ 618 619 /* Initialize the framebuffer, storing away useful state for later reset */ 620 static void 621 cg14_init(struct cgfourteen_softc *sc) 622 { 623 cg14_set_depth(sc, 32); 624 cg14_init_cmap(sc); 625 } 626 627 static void 628 /* Restore the state saved on cg14_init */ 629 cg14_reset(struct cgfourteen_softc *sc) 630 { 631 cg14_set_depth(sc, 8); 632 cg14_init_cmap(sc); 633 } 634 635 /* Enable/disable video display; power down monitor if DPMS-capable */ 636 static void 637 cg14_set_video(struct cgfourteen_softc *sc, int enable) 638 { 639 /* 640 * We can only use DPMS to power down the display if the chip revision 641 * is greater than 0. 642 */ 643 if (enable) { 644 if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 645 sc->sc_ctl->ctl_mctl |= (CG14_MCTL_ENABLEVID | 646 CG14_MCTL_POWERCTL); 647 else 648 sc->sc_ctl->ctl_mctl |= CG14_MCTL_ENABLEVID; 649 } else { 650 if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 651 sc->sc_ctl->ctl_mctl &= ~(CG14_MCTL_ENABLEVID | 652 CG14_MCTL_POWERCTL); 653 else 654 sc->sc_ctl->ctl_mctl &= ~CG14_MCTL_ENABLEVID; 655 } 656 } 657 658 /* Get status of video display */ 659 static int 660 cg14_get_video(struct cgfourteen_softc *sc) 661 { 662 return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0); 663 } 664 665 /* Read the software shadow colormap */ 666 static int 667 cg14_get_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 668 { 669 u_int i, start, count; 670 u_char *cp; 671 int error; 672 673 start = p->index; 674 count = p->count; 675 if (start >= cmsize || count > cmsize - start) 676 return (EINVAL); 677 678 for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) { 679 error = copyout(&cp[3], &p->red[i], 1); 680 if (error) 681 return error; 682 error = copyout(&cp[2], &p->green[i], 1); 683 if (error) 684 return error; 685 error = copyout(&cp[1], &p->blue[i], 1); 686 if (error) 687 return error; 688 } 689 return (0); 690 } 691 692 /* Write the software shadow colormap */ 693 static int 694 cg14_put_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 695 { 696 u_int i, start, count; 697 u_char *cp; 698 u_char cmap[256][4]; 699 int error; 700 701 start = p->index; 702 count = p->count; 703 if (start >= cmsize || count > cmsize - start) 704 return (EINVAL); 705 706 memcpy(&cmap, &cm->cm_map, sizeof cmap); 707 for (cp = &cmap[start][0], i = 0; i < count; cp += 4, i++) { 708 error = copyin(&p->red[i], &cp[3], 1); 709 if (error) 710 return error; 711 error = copyin(&p->green[i], &cp[2], 1); 712 if (error) 713 return error; 714 error = copyin(&p->blue[i], &cp[1], 1); 715 if (error) 716 return error; 717 cp[0] = 0; /* no alpha channel */ 718 } 719 memcpy(&cm->cm_map, &cmap, sizeof cmap); 720 return (0); 721 } 722 723 static void 724 cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors) 725 { 726 /* XXX switch to auto-increment, and on retrace intr */ 727 728 /* Setup pointers to source and dest */ 729 uint32_t *colp = &sc->sc_cmap.cm_chip[start]; 730 volatile uint32_t *lutp = &sc->sc_clut1->clut_lut[start]; 731 732 /* Copy by words */ 733 while (--ncolors >= 0) 734 *lutp++ = *colp++; 735 } 736 737 static void 738 cg14_setup_wsdisplay(struct cgfourteen_softc *sc, int is_cons) 739 { 740 struct wsemuldisplaydev_attach_args aa; 741 struct rasops_info *ri; 742 long defattr; 743 744 sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 745 "default", 746 0, 0, 747 NULL, 748 8, 16, 749 WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 750 WSSCREEN_RESIZE, 751 NULL 752 }; 753 754 cg14_set_depth(sc, 8); 755 756 sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 757 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 758 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 759 vcons_init(&sc->sc_vd, sc, &sc->sc_defaultscreen_descr, 760 &cg14_accessops); 761 sc->sc_vd.init_screen = cg14_init_screen; 762 sc->sc_vd.show_screen_cookie = &sc->sc_gc; 763 sc->sc_vd.show_screen_cb = glyphcache_adapt; 764 765 ri = &sc->sc_console_screen.scr_ri; 766 767 sc->sc_gc.gc_bitblt = cg14_bitblt_gc; 768 sc->sc_gc.gc_blitcookie = sc; 769 sc->sc_gc.gc_rectfill = cg14_rectfill_a; 770 sc->sc_gc.gc_rop = 0xc; 771 772 vcons_init_screen(&sc->sc_vd, &sc->sc_console_screen, 1, 773 &defattr); 774 775 /* clear the screen with the default background colour */ 776 if (sc->sc_sx != NULL) { 777 cg14_rectfill(sc, 0, 0, ri->ri_width, ri->ri_height, 778 ri->ri_devcmap[(defattr >> 16) & 0xf]); 779 } else { 780 memset(sc->sc_fb.fb_pixels, 781 ri->ri_devcmap[(defattr >> 16) & 0xf], 782 ri->ri_stride * ri->ri_height); 783 } 784 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 785 786 sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 787 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 788 sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 789 sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 790 glyphcache_init_align(&sc->sc_gc, sc->sc_fb.fb_type.fb_height + 5, 791 (sc->sc_vramsize / sc->sc_fb.fb_type.fb_width) - 792 sc->sc_fb.fb_type.fb_height - 5, 793 sc->sc_fb.fb_type.fb_width, 794 ri->ri_font->fontwidth, 795 ri->ri_font->fontheight, 796 defattr, 4); 797 798 if (is_cons) { 799 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 800 defattr); 801 vcons_replay_msgbuf(&sc->sc_console_screen); 802 } 803 804 aa.console = is_cons; 805 aa.scrdata = &sc->sc_screenlist; 806 aa.accessops = &cg14_accessops; 807 aa.accesscookie = &sc->sc_vd; 808 809 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint, CFARGS_NONE); 810 811 /* 812 * do this here since any output through firmware calls will mess 813 * with XLUT settings 814 */ 815 cg14_init_cmap(sc); 816 } 817 818 static void 819 cg14_init_cmap(struct cgfourteen_softc *sc) 820 { 821 struct rasops_info *ri = &sc->sc_console_screen.scr_ri; 822 int i, j = 0; 823 uint32_t r, g, b, c, cc; 824 uint8_t cmap[768]; 825 826 if (sc->sc_depth == 16) { 827 /* construct an R5G6B5 palette in CLUT1/2 */ 828 for (i = 0; i < 0x100; i++) { 829 /* upper byte first */ 830 r = (i & 0xf8); /* red component */ 831 r |= r >> 5; /* fill lower bits so 0xf8 */ 832 c = 0x40000000 | r; /* becomes 0xff */ 833 g = i & 0x7; /* upper 3 bits of green */ 834 g |= g << 3; /* 0x003f */ 835 c |= ((g << 10) & 0xf000); /* make it 4 */ 836 sc->sc_clut1->clut_lut[i] = c; 837 /* lower byte */ 838 g = i & 0xe0; /* lower half of green */ 839 g |= g >> 3; 840 cc = 0x40000000 | ((g << 4) & 0x0f00); 841 b = i & 0x1f; /* and blue */ 842 b = (b << 3) | (b >> 2); 843 cc |= (b << 16); 844 sc->sc_clut2->clut_lut[i] = cc; 845 } 846 847 /* 848 * because we alpha blend our components everything is half 849 * intensity, fix that with the gamma LUT 850 */ 851 852 sc->sc_dac->dac_mode &= ~6; /* 8bit mode, for simplicity */ 853 for (i = 0; i < 128; i++) { 854 sc->sc_dac->dac_addr = i; 855 sc->sc_dac->dac_gammalut = i << 1; 856 sc->sc_dac->dac_gammalut = i << 1; 857 sc->sc_dac->dac_gammalut = i << 1; 858 } 859 860 /* finally fill the XLUT */ 861 for (i = 0; i < 256; i++) 862 sc->sc_xlut->xlut_lut[i] = 863 CG14_LEFT_CLUT2 | CG14_LEFT_B | 864 CG14_RIGHT_CLUT1 | CG14_RIGHT_X; 865 } else { 866 /* in 8 or 24bit put a linear ramp in the gamma LUT */ 867 sc->sc_dac->dac_mode &= ~6; /* 8bit mode, for simplicity */ 868 for (i = 0; i < 256; i++) { 869 sc->sc_dac->dac_addr = i; 870 sc->sc_dac->dac_gammalut = i; 871 sc->sc_dac->dac_gammalut = i; 872 sc->sc_dac->dac_gammalut = i; 873 } 874 875 /* and zero the XLUT */ 876 for (i = 0; i < 256; i++) 877 sc->sc_xlut->xlut_lut[i] = 0; 878 879 if (sc->sc_depth == 8) { 880 rasops_get_cmap(ri, cmap, sizeof(cmap)); 881 882 for (i = 0; i < 256; i++) { 883 sc->sc_cmap.cm_map[i][3] = cmap[j]; 884 sc->sc_cmap.cm_map[i][2] = cmap[j + 1]; 885 sc->sc_cmap.cm_map[i][1] = cmap[j + 2]; 886 j += 3; 887 } 888 cg14_load_hwcmap(sc, 0, 256); 889 } 890 } 891 } 892 893 static int 894 cg14_putcmap(struct cgfourteen_softc *sc, struct wsdisplay_cmap *cm) 895 { 896 u_int index = cm->index; 897 u_int count = cm->count; 898 int i, error; 899 u_char rbuf[256], gbuf[256], bbuf[256]; 900 901 if (cm->index >= 256 || cm->count > 256 || 902 (cm->index + cm->count) > 256) 903 return EINVAL; 904 error = copyin(cm->red, &rbuf[index], count); 905 if (error) 906 return error; 907 error = copyin(cm->green, &gbuf[index], count); 908 if (error) 909 return error; 910 error = copyin(cm->blue, &bbuf[index], count); 911 if (error) 912 return error; 913 914 for (i = 0; i < count; i++) { 915 sc->sc_cmap.cm_map[index][3] = rbuf[index]; 916 sc->sc_cmap.cm_map[index][2] = gbuf[index]; 917 sc->sc_cmap.cm_map[index][1] = bbuf[index]; 918 index++; 919 } 920 921 if (sc->sc_depth == 8) 922 cg14_load_hwcmap(sc, 0, 256); 923 924 return 0; 925 } 926 927 static int 928 cg14_getcmap(struct cgfourteen_softc *sc, struct wsdisplay_cmap *cm) 929 { 930 uint8_t rbuf[256], gbuf[256], bbuf[256]; 931 u_int index = cm->index; 932 u_int count = cm->count; 933 int error, i; 934 935 if (index >= 255 || count > 256 || index + count > 256) 936 return EINVAL; 937 938 939 for (i = 0; i < count; i++) { 940 rbuf[i] = sc->sc_cmap.cm_map[index][3]; 941 gbuf[i] = sc->sc_cmap.cm_map[index][2]; 942 bbuf[i] = sc->sc_cmap.cm_map[index][1]; 943 index++; 944 } 945 error = copyout(rbuf, cm->red, count); 946 if (error) 947 return error; 948 error = copyout(gbuf, cm->green, count); 949 if (error) 950 return error; 951 error = copyout(bbuf, cm->blue, count); 952 if (error) 953 return error; 954 955 return 0; 956 } 957 958 static int 959 cg14_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 960 struct lwp *l) 961 { 962 struct vcons_data *vd = v; 963 struct cgfourteen_softc *sc = vd->cookie; 964 struct wsdisplay_fbinfo *wdf; 965 struct vcons_screen *ms = vd->active; 966 967 switch (cmd) { 968 969 case WSDISPLAYIO_GTYPE: 970 *(uint32_t *)data = WSDISPLAY_TYPE_SUNCG14; 971 return 0; 972 973 case WSDISPLAYIO_GINFO: 974 wdf = (void *)data; 975 wdf->height = ms->scr_ri.ri_height; 976 wdf->width = ms->scr_ri.ri_width; 977 wdf->depth = sc->sc_fbdepth; 978 wdf->cmsize = 256; 979 return 0; 980 981 case WSDISPLAYIO_GETCMAP: 982 return cg14_getcmap(sc, 983 (struct wsdisplay_cmap *)data); 984 985 case WSDISPLAYIO_PUTCMAP: 986 return cg14_putcmap(sc, 987 (struct wsdisplay_cmap *)data); 988 989 case WSDISPLAYIO_LINEBYTES: 990 *(u_int *)data = ms->scr_ri.ri_stride * (sc->sc_fbdepth >> 3); 991 return 0; 992 993 case WSDISPLAYIO_SMODE: 994 { 995 int new_mode = *(int*)data; 996 if (new_mode != sc->sc_mode) { 997 sc->sc_mode = new_mode; 998 if(new_mode == WSDISPLAYIO_MODE_EMUL) { 999 bus_space_write_1(sc->sc_bustag, 1000 sc->sc_regh, 1001 CG14_CURSOR_CONTROL, 0); 1002 1003 cg14_set_depth(sc, 8); 1004 cg14_init_cmap(sc); 1005 #if NSX > 0 1006 if (sc->sc_sx) 1007 glyphcache_wipe(&sc->sc_gc); 1008 #endif 1009 vcons_redraw_screen(ms); 1010 } else { 1011 1012 cg14_set_depth(sc, sc->sc_fbdepth); 1013 cg14_init_cmap(sc); 1014 } 1015 } 1016 } 1017 return 0; 1018 case WSDISPLAYIO_SVIDEO: 1019 cg14_set_video(sc, *(int *)data); 1020 return 0; 1021 case WSDISPLAYIO_GVIDEO: 1022 *(int *)data = cg14_get_video(sc) ? 1023 WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 1024 return 0; 1025 case WSDISPLAYIO_GCURPOS: 1026 { 1027 struct wsdisplay_curpos *cp = (void *)data; 1028 1029 cp->x = sc->sc_cursor.cc_pos.x; 1030 cp->y = sc->sc_cursor.cc_pos.y; 1031 } 1032 return 0; 1033 case WSDISPLAYIO_SCURPOS: 1034 { 1035 struct wsdisplay_curpos *cp = (void *)data; 1036 1037 cg14_move_cursor(sc, cp->x, cp->y); 1038 } 1039 return 0; 1040 case WSDISPLAYIO_GCURMAX: 1041 { 1042 struct wsdisplay_curpos *cp = (void *)data; 1043 1044 cp->x = 32; 1045 cp->y = 32; 1046 } 1047 return 0; 1048 case WSDISPLAYIO_SCURSOR: 1049 { 1050 struct wsdisplay_cursor *cursor = (void *)data; 1051 1052 return cg14_do_cursor(sc, cursor); 1053 } 1054 case PCI_IOC_CFGREAD: 1055 case PCI_IOC_CFGWRITE: 1056 return EINVAL; 1057 case WSDISPLAYIO_SET_DEPTH: 1058 { 1059 int new_depth = *(int*)data; 1060 1061 if ((new_depth == 8) || (new_depth == 32)) { 1062 sc->sc_fbdepth = new_depth; 1063 return 0; 1064 } 1065 return EINVAL; 1066 } 1067 case WSDISPLAYIO_GET_FBINFO: 1068 { 1069 struct wsdisplayio_fbinfo *fbi = data; 1070 1071 if (sc->sc_depth == 8) { 1072 fbi->fbi_stride = sc->sc_fb.fb_type.fb_width; 1073 fbi->fbi_bitsperpixel = 8; 1074 fbi->fbi_pixeltype = WSFB_CI; 1075 } else { 1076 fbi->fbi_stride = sc->sc_fb.fb_type.fb_width * 4; 1077 fbi->fbi_bitsperpixel = 32; 1078 fbi->fbi_pixeltype = WSFB_RGB; 1079 } 1080 fbi->fbi_fbsize = sc->sc_vramsize; 1081 fbi->fbi_width = sc->sc_fb.fb_type.fb_width; 1082 fbi->fbi_height = sc->sc_fb.fb_type.fb_height; 1083 fbi->fbi_subtype.fbi_rgbmasks.red_offset = 0; 1084 fbi->fbi_subtype.fbi_rgbmasks.red_size = 8; 1085 fbi->fbi_subtype.fbi_rgbmasks.green_offset = 8; 1086 fbi->fbi_subtype.fbi_rgbmasks.green_size = 8; 1087 fbi->fbi_subtype.fbi_rgbmasks.blue_offset = 16; 1088 fbi->fbi_subtype.fbi_rgbmasks.blue_size = 8; 1089 fbi->fbi_subtype.fbi_rgbmasks.alpha_offset = 0; 1090 fbi->fbi_subtype.fbi_rgbmasks.alpha_size = 0; 1091 return 0; 1092 } 1093 1094 } 1095 return EPASSTHROUGH; 1096 } 1097 1098 static paddr_t 1099 cg14_mmap(void *v, void *vs, off_t offset, int prot) 1100 { 1101 struct vcons_data *vd = v; 1102 struct cgfourteen_softc *sc = vd->cookie; 1103 uint32_t space; 1104 1105 space = sc->sc_fbdepth == 32 ? CG14_FB_CBGR : CG14_FB_VRAM; 1106 /* allow mmap()ing the full framebuffer, not just what we use */ 1107 if (offset < sc->sc_vramsize) 1108 return bus_space_mmap(sc->sc_bustag, 1109 BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 1110 sc->sc_physadr[CG14_PXL_IDX].sbr_offset), 1111 offset + space, prot, BUS_SPACE_MAP_LINEAR); 1112 1113 return -1; 1114 } 1115 1116 static void 1117 cg14_init_screen(void *cookie, struct vcons_screen *scr, 1118 int existing, long *defattr) 1119 { 1120 struct cgfourteen_softc *sc = cookie; 1121 struct rasops_info *ri = &scr->scr_ri; 1122 1123 ri->ri_depth = sc->sc_depth; 1124 ri->ri_width = sc->sc_fb.fb_type.fb_width; 1125 ri->ri_height = sc->sc_fb.fb_type.fb_height; 1126 ri->ri_stride = ri->ri_width * (sc->sc_depth >> 3); 1127 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 1128 1129 ri->ri_bits = (char *)sc->sc_fb.fb_pixels; 1130 1131 scr->scr_flags |= VCONS_LOADFONT; 1132 #if NSX > 0 1133 ri->ri_flg |= RI_8BIT_IS_RGB | RI_ENABLE_ALPHA | RI_PREFER_ALPHA; 1134 1135 /* 1136 * unaligned copies with horizontal overlap are slow, so don't bother 1137 * handling them in cg14_bitblt() and use putchar() instead 1138 */ 1139 if (sc->sc_sx != NULL) { 1140 scr->scr_flags |= VCONS_NO_COPYCOLS; 1141 } else 1142 #endif 1143 scr->scr_flags |= VCONS_DONT_READ; 1144 1145 if (existing) { 1146 ri->ri_flg |= RI_CLEAR; 1147 } 1148 1149 rasops_init(ri, 0, 0); 1150 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_HILIT | WSSCREEN_UNDERLINE | 1151 WSSCREEN_RESIZE; 1152 1153 rasops_reconfig(ri, 1154 sc->sc_fb.fb_type.fb_height / ri->ri_font->fontheight, 1155 sc->sc_fb.fb_type.fb_width / ri->ri_font->fontwidth); 1156 1157 ri->ri_hw = scr; 1158 #if NSX > 0 1159 if ((sc->sc_sx != NULL) && (sc->sc_depth == 8)) { 1160 ri->ri_ops.copyrows = cg14_copyrows; 1161 ri->ri_ops.copycols = cg14_copycols; 1162 ri->ri_ops.eraserows = cg14_eraserows; 1163 ri->ri_ops.erasecols = cg14_erasecols; 1164 ri->ri_ops.cursor = cg14_cursor; 1165 ri->ri_ops.allocattr = cg14_allocattr; 1166 if (FONT_IS_ALPHA(ri->ri_font)) { 1167 ri->ri_ops.putchar = cg14_putchar_aa; 1168 } else 1169 ri->ri_ops.putchar = cg14_putchar; 1170 } 1171 #endif /* NSX > 0 */ 1172 } 1173 1174 static void 1175 cg14_set_depth(struct cgfourteen_softc *sc, int depth) 1176 { 1177 1178 /* init mask */ 1179 if (sc->sc_sx != NULL) { 1180 sc->sc_mask = 0xffffffff; 1181 sx_write(sc->sc_sx, SX_QUEUED(R_MASK), sc->sc_mask); 1182 } 1183 1184 if (sc->sc_depth == depth) 1185 return; 1186 1187 switch (depth) { 1188 case 8: 1189 bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1190 CG14_MCTL, CG14_MCTL_ENABLEVID | 1191 CG14_MCTL_PIXMODE_8 | CG14_MCTL_POWERCTL); 1192 sc->sc_depth = 8; 1193 break; 1194 case 16: 1195 bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1196 CG14_MCTL, CG14_MCTL_ENABLEVID | 1197 CG14_MCTL_PIXMODE_16 | CG14_MCTL_POWERCTL); 1198 sc->sc_depth = 16; 1199 break; 1200 case 32: 1201 bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1202 CG14_MCTL, CG14_MCTL_ENABLEVID | 1203 CG14_MCTL_PIXMODE_32 | CG14_MCTL_POWERCTL); 1204 sc->sc_depth = 32; 1205 break; 1206 default: 1207 printf("%s: can't change to depth %d\n", 1208 device_xname(sc->sc_dev), depth); 1209 return; 1210 } 1211 1212 } 1213 1214 static void 1215 cg14_move_cursor(struct cgfourteen_softc *sc, int x, int y) 1216 { 1217 uint32_t pos; 1218 1219 sc->sc_cursor.cc_pos.x = x; 1220 sc->sc_cursor.cc_pos.y = y; 1221 pos = ((sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x ) << 16) | 1222 ((sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y ) & 0xffff); 1223 bus_space_write_4(sc->sc_bustag, sc->sc_regh, CG14_CURSOR_X, pos); 1224 } 1225 1226 static int 1227 cg14_do_cursor(struct cgfourteen_softc *sc, struct wsdisplay_cursor *cur) 1228 { 1229 if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1230 1231 bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1232 CG14_CURSOR_CONTROL, cur->enable ? CG14_CRSR_ENABLE : 0); 1233 } 1234 if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1235 1236 sc->sc_cursor.cc_hot.x = cur->hot.x; 1237 sc->sc_cursor.cc_hot.y = cur->hot.y; 1238 cur->which |= WSDISPLAY_CURSOR_DOPOS; 1239 } 1240 if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1241 1242 cg14_move_cursor(sc, cur->pos.x, cur->pos.y); 1243 } 1244 if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1245 int i; 1246 uint32_t val; 1247 1248 if ((cur->cmap.index > 2) || (cur->cmap.count > 3) || 1249 (cur->cmap.index + cur->cmap.count > 3)) 1250 return EINVAL; 1251 1252 for (i = 0; i < uimin(cur->cmap.count, 3); i++) { 1253 val = (cur->cmap.red[i] ) | 1254 (cur->cmap.green[i] << 8) | 1255 (cur->cmap.blue[i] << 16); 1256 bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1257 CG14_CURSOR_COLOR1 + ((i + cur->cmap.index) << 2), 1258 val); 1259 } 1260 } 1261 if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1262 uint32_t buffer[32], latch, tmp; 1263 int i; 1264 1265 copyin(cur->mask, buffer, 128); 1266 for (i = 0; i < 32; i++) { 1267 latch = 0; 1268 tmp = buffer[i] & 0x80808080; 1269 latch |= tmp >> 7; 1270 tmp = buffer[i] & 0x40404040; 1271 latch |= tmp >> 5; 1272 tmp = buffer[i] & 0x20202020; 1273 latch |= tmp >> 3; 1274 tmp = buffer[i] & 0x10101010; 1275 latch |= tmp >> 1; 1276 tmp = buffer[i] & 0x08080808; 1277 latch |= tmp << 1; 1278 tmp = buffer[i] & 0x04040404; 1279 latch |= tmp << 3; 1280 tmp = buffer[i] & 0x02020202; 1281 latch |= tmp << 5; 1282 tmp = buffer[i] & 0x01010101; 1283 latch |= tmp << 7; 1284 bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1285 CG14_CURSOR_PLANE0 + (i << 2), latch); 1286 } 1287 copyin(cur->image, buffer, 128); 1288 for (i = 0; i < 32; i++) { 1289 latch = 0; 1290 tmp = buffer[i] & 0x80808080; 1291 latch |= tmp >> 7; 1292 tmp = buffer[i] & 0x40404040; 1293 latch |= tmp >> 5; 1294 tmp = buffer[i] & 0x20202020; 1295 latch |= tmp >> 3; 1296 tmp = buffer[i] & 0x10101010; 1297 latch |= tmp >> 1; 1298 tmp = buffer[i] & 0x08080808; 1299 latch |= tmp << 1; 1300 tmp = buffer[i] & 0x04040404; 1301 latch |= tmp << 3; 1302 tmp = buffer[i] & 0x02020202; 1303 latch |= tmp << 5; 1304 tmp = buffer[i] & 0x01010101; 1305 latch |= tmp << 7; 1306 bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1307 CG14_CURSOR_PLANE1 + (i << 2), latch); 1308 } 1309 } 1310 return 0; 1311 } 1312 1313 #if NSX > 0 1314 1315 static void 1316 cg14_wait_idle(struct cgfourteen_softc *sc) 1317 { 1318 } 1319 1320 static void 1321 cg14_rectfill(struct cgfourteen_softc *sc, int x, int y, int wi, int he, 1322 uint32_t colour) 1323 { 1324 uint32_t addr, pptr; 1325 int line, cnt, pre, words; 1326 int stride = sc->sc_fb.fb_type.fb_width; 1327 1328 addr = sc->sc_fb_paddr + x + stride * y; 1329 sx_write(sc->sc_sx, SX_QUEUED(8), colour); 1330 sx_write(sc->sc_sx, SX_QUEUED(9), colour); 1331 /* 1332 * Calculate the number of pixels we need to do one by one 1333 * until we're 32bit aligned, then do the rest in 32bit 1334 * mode. Assumes that stride is always a multiple of 4. 1335 */ 1336 /* TODO: use 32bit writes with byte mask instead */ 1337 pre = addr & 3; 1338 if (pre != 0) pre = 4 - pre; 1339 for (line = 0; line < he; line++) { 1340 pptr = addr; 1341 cnt = wi; 1342 if (pre) { 1343 sxm(SX_STBS, pptr, 8, pre - 1); 1344 pptr += pre; 1345 cnt -= pre; 1346 } 1347 /* now do the aligned pixels in 32bit chunks */ 1348 while(cnt > 3) { 1349 words = uimin(32, cnt >> 2); 1350 sxm(SX_STS, pptr, 8, words - 1); 1351 pptr += words << 2; 1352 cnt -= words << 2; 1353 } 1354 /* do any remaining pixels byte-wise again */ 1355 if (cnt > 0) 1356 sxm(SX_STBS, pptr, 8, cnt - 1); 1357 addr += stride; 1358 } 1359 } 1360 1361 static void 1362 cg14_rectfill_a(void *cookie, int dstx, int dsty, 1363 int width, int height, long attr) 1364 { 1365 struct cgfourteen_softc *sc = cookie; 1366 1367 cg14_rectfill(sc, dstx, dsty, width, height, 1368 sc->sc_vd.active->scr_ri.ri_devcmap[(attr >> 24 & 0xf)]); 1369 } 1370 1371 static inline void 1372 cg14_set_mask(struct cgfourteen_softc *sc, uint32_t mask) 1373 { 1374 if (mask == sc->sc_mask) return; 1375 sc->sc_mask = mask; 1376 sx_write(sc->sc_sx, SX_QUEUED(R_MASK), mask); 1377 } 1378 /* 1379 * invert a rectangle, used only to (un)draw the cursor. 1380 * - does a scanline at a time 1381 * - does not handle wi > 64 or wi < 4, not that we need it for our fonts 1382 * - uses all 32bit accesses 1383 */ 1384 static void 1385 cg14_invert(struct cgfourteen_softc *sc, int x, int y, int wi, int he) 1386 { 1387 uint32_t addr, pptr, lmask, rmask; 1388 int line, cnt, pre, words, pwrds = 0, post, reg; 1389 int stride = sc->sc_fb.fb_type.fb_width; 1390 1391 addr = (sc->sc_fb_paddr + x + stride * y) & ~3; 1392 sx_write(sc->sc_sx, SX_ROP_CONTROL, 0x3C); /* ~src a / src a */ 1393 /* 1394 * Calculate the number of pixels we need to mask on each end of the 1395 * scanline and how many we can do without mask, if any 1396 */ 1397 pre = x & 3; 1398 if (pre != 0) { 1399 lmask = 0xffffffff >> pre; 1400 pre = 4 - pre; 1401 pwrds++; 1402 } 1403 post = (x + wi) & 3; 1404 if (post != 0) { 1405 rmask = ~(0xffffffff >> post); 1406 pwrds++; 1407 } 1408 words = (wi + pre + 3) >> 2; 1409 cnt = words - pwrds; 1410 1411 for (line = 0; line < he; line++) { 1412 pptr = addr; 1413 /* load a whole scanline */ 1414 sxm(SX_LD, pptr, 8, words - 1); 1415 reg = 8; 1416 if (pre) { 1417 cg14_set_mask(sc, lmask); 1418 sxi(SX_ROPB, 8, 8, 40, 0); 1419 reg++; 1420 } 1421 if (cnt > 0) { 1422 cg14_set_mask(sc, 0xffffffff); 1423 /* XXX handle cnt > 16 */ 1424 sxi(SX_ROP, reg, reg, reg + 32, cnt - 1); 1425 reg += cnt; 1426 } 1427 if (post) { 1428 cg14_set_mask(sc, rmask); 1429 sxi(SX_ROPB, reg, 7, reg + 32, 0); 1430 reg++; 1431 } 1432 sxm(SX_ST, pptr, 40, words - 1); 1433 addr += stride; 1434 } 1435 } 1436 1437 static inline void 1438 cg14_slurp(int reg, uint32_t addr, int cnt) 1439 { 1440 int num; 1441 while (cnt > 0) { 1442 num = uimin(32, cnt); 1443 sxm(SX_LD, addr, reg, num - 1); 1444 cnt -= num; 1445 reg += num; 1446 addr += (num << 2); 1447 } 1448 } 1449 1450 static inline void 1451 cg14_spit(int reg, uint32_t addr, int cnt) 1452 { 1453 int num; 1454 while (cnt > 0) { 1455 num = uimin(32, cnt); 1456 sxm(SX_ST, addr, reg, num - 1); 1457 cnt -= num; 1458 reg += num; 1459 addr += (num << 2); 1460 } 1461 } 1462 1463 static void 1464 cg14_bitblt(void *cookie, int xs, int ys, int xd, int yd, 1465 int wi, int he, int rop) 1466 { 1467 struct cgfourteen_softc *sc = cookie; 1468 uint32_t saddr, daddr, sptr, dptr; 1469 int line, cnt, stride = sc->sc_fb.fb_type.fb_width; 1470 int num, words, skip; 1471 1472 if (ys < yd) { 1473 /* need to go bottom-up */ 1474 saddr = sc->sc_fb_paddr + xs + stride * (ys + he - 1); 1475 daddr = sc->sc_fb_paddr + xd + stride * (yd + he - 1); 1476 skip = -stride; 1477 } else { 1478 saddr = sc->sc_fb_paddr + xs + stride * ys; 1479 daddr = sc->sc_fb_paddr + xd + stride * yd; 1480 skip = stride; 1481 } 1482 1483 if ((saddr & 3) == (daddr & 3)) { 1484 int pre = saddr & 3; /* pixels to copy byte-wise */ 1485 if (pre != 0) pre = 4 - pre; 1486 for (line = 0; line < he; line++) { 1487 sptr = saddr; 1488 dptr = daddr; 1489 cnt = wi; 1490 if (pre > 0) { 1491 sxm(SX_LDB, sptr, 32, pre - 1); 1492 sxm(SX_STB, dptr, 32, pre - 1); 1493 cnt -= pre; 1494 sptr += pre; 1495 dptr += pre; 1496 } 1497 words = cnt >> 2; 1498 while(cnt > 3) { 1499 num = uimin(120, words); 1500 cg14_slurp(8, sptr, num); 1501 cg14_spit(8, dptr, num); 1502 sptr += num << 2; 1503 dptr += num << 2; 1504 cnt -= num << 2; 1505 } 1506 if (cnt > 0) { 1507 sxm(SX_LDB, sptr, 32, cnt - 1); 1508 sxm(SX_STB, dptr, 32, cnt - 1); 1509 } 1510 saddr += skip; 1511 daddr += skip; 1512 } 1513 } else { 1514 /* unaligned, have to use byte mode */ 1515 /* funnel shifter & byte mask trickery? */ 1516 for (line = 0; line < he; line++) { 1517 sptr = saddr; 1518 dptr = daddr; 1519 cnt = wi; 1520 while(cnt > 31) { 1521 sxm(SX_LDB, sptr, 32, 31); 1522 sxm(SX_STB, dptr, 32, 31); 1523 sptr += 32; 1524 dptr += 32; 1525 cnt -= 32; 1526 } 1527 if (cnt > 0) { 1528 sxm(SX_LDB, sptr, 32, cnt - 1); 1529 sxm(SX_STB, dptr, 32, cnt - 1); 1530 } 1531 saddr += skip; 1532 daddr += skip; 1533 } 1534 } 1535 } 1536 1537 /* 1538 * for copying glyphs around 1539 * - uses all quads for reads 1540 * - uses quads for writes as far as possible 1541 * - limited by number of registers - won't do more than 120 wide 1542 * - doesn't handle overlaps 1543 */ 1544 static void 1545 cg14_bitblt_gc(void *cookie, int xs, int ys, int xd, int yd, 1546 int wi, int he, int rop) 1547 { 1548 struct cgfourteen_softc *sc = cookie; 1549 uint32_t saddr, daddr; 1550 int line, cnt = wi, stride = sc->sc_fb.fb_type.fb_width; 1551 int dreg = 8, swi = wi, dd; 1552 int in = 0, q = 0, out = 0, r; 1553 1554 saddr = sc->sc_fb_paddr + xs + stride * ys; 1555 daddr = sc->sc_fb_paddr + xd + stride * yd; 1556 1557 if (saddr & 3) { 1558 swi += saddr & 3; 1559 dreg += saddr & 3; 1560 saddr &= ~3; 1561 } 1562 swi = (swi + 3) >> 2; /* round up, number of quads to read */ 1563 1564 if (daddr & 3) { 1565 in = 4 - (daddr & 3); /* pixels to write in byte mode */ 1566 cnt -= in; 1567 } 1568 1569 q = cnt >> 2; 1570 out = cnt & 3; 1571 1572 for (line = 0; line < he; line++) { 1573 /* read source line, in all quads */ 1574 sxm(SX_LDUQ0, saddr, 8, swi - 1); 1575 /* now write it out */ 1576 dd = daddr; 1577 r = dreg; 1578 if (in > 0) { 1579 sxm(SX_STB, dd, r, in - 1); 1580 dd += in; 1581 r += in; 1582 } 1583 if (q > 0) { 1584 sxm(SX_STUQ0, dd, r, q - 1); 1585 r += q << 2; 1586 dd += q << 2; 1587 } 1588 if (out > 0) { 1589 sxm(SX_STB, dd, r, out - 1); 1590 } 1591 saddr += stride; 1592 daddr += stride; 1593 } 1594 } 1595 1596 static void 1597 cg14_putchar(void *cookie, int row, int col, u_int c, long attr) 1598 { 1599 struct rasops_info *ri = cookie; 1600 struct wsdisplay_font *font = PICK_FONT(ri, c); 1601 struct vcons_screen *scr = ri->ri_hw; 1602 struct cgfourteen_softc *sc = scr->scr_cookie; 1603 void *data; 1604 uint32_t fg, bg; 1605 int i, x, y, wi, he; 1606 uint32_t addr; 1607 int stride = sc->sc_fb.fb_type.fb_width; 1608 1609 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1610 return; 1611 1612 if (!CHAR_IN_FONT(c, font)) 1613 return; 1614 1615 if (row == ri->ri_crow && col == ri->ri_ccol) { 1616 ri->ri_flg &= ~RI_CURSOR; 1617 } 1618 1619 wi = font->fontwidth; 1620 he = font->fontheight; 1621 1622 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1623 fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 1624 1625 x = ri->ri_xorigin + col * wi; 1626 y = ri->ri_yorigin + row * he; 1627 1628 if (c == 0x20) { 1629 cg14_rectfill(sc, x, y, wi, he, bg); 1630 if (attr & WSATTR_UNDERLINE) 1631 cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1632 return; 1633 } 1634 1635 sx_write(sc->sc_sx, SX_QUEUED(8), bg); 1636 sx_write(sc->sc_sx, SX_QUEUED(9), fg); 1637 1638 data = WSFONT_GLYPH(c, font); 1639 addr = sc->sc_fb_paddr + x + stride * y; 1640 1641 if (attr & WSATTR_HILIT) { 1642 switch (font->stride) { 1643 case 1: { 1644 uint8_t *data8 = data; 1645 uint32_t reg; 1646 for (i = 0; i < he; i++) { 1647 reg = *data8; 1648 reg |= reg >> 1; 1649 cg14_set_mask(sc, reg << 24); 1650 sxm(SX_STBS, addr, 8, wi - 1); 1651 data8++; 1652 addr += stride; 1653 } 1654 break; 1655 } 1656 case 2: { 1657 uint16_t *data16 = data; 1658 uint32_t reg; 1659 for (i = 0; i < he; i++) { 1660 reg = *data16; 1661 reg |= reg >> 1; 1662 cg14_set_mask(sc, reg << 16); 1663 sxm(SX_STBS, addr, 8, wi - 1); 1664 data16++; 1665 addr += stride; 1666 } 1667 break; 1668 } 1669 } 1670 } else { 1671 switch (font->stride) { 1672 case 1: { 1673 uint8_t *data8 = data; 1674 uint32_t reg; 1675 for (i = 0; i < he; i++) { 1676 reg = *data8; 1677 cg14_set_mask(sc, reg << 24); 1678 sxm(SX_STBS, addr, 8, wi - 1); 1679 data8++; 1680 addr += stride; 1681 } 1682 break; 1683 } 1684 case 2: { 1685 uint16_t *data16 = data; 1686 uint32_t reg; 1687 for (i = 0; i < he; i++) { 1688 reg = *data16; 1689 cg14_set_mask(sc, reg << 16); 1690 sxm(SX_STBS, addr, 8, wi - 1); 1691 data16++; 1692 addr += stride; 1693 } 1694 break; 1695 } 1696 } 1697 } 1698 if (attr & WSATTR_UNDERLINE) 1699 cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1700 } 1701 1702 static void 1703 cg14_nuke_cursor(struct rasops_info *ri) 1704 { 1705 struct vcons_screen *scr = ri->ri_hw; 1706 struct cgfourteen_softc *sc = scr->scr_cookie; 1707 int wi, he, x, y; 1708 1709 if (ri->ri_flg & RI_CURSOR) { 1710 wi = ri->ri_font->fontwidth; 1711 he = ri->ri_font->fontheight; 1712 x = ri->ri_ccol * wi + ri->ri_xorigin; 1713 y = ri->ri_crow * he + ri->ri_yorigin; 1714 cg14_invert(sc, x, y, wi, he); 1715 ri->ri_flg &= ~RI_CURSOR; 1716 } 1717 } 1718 1719 static void 1720 cg14_cursor(void *cookie, int on, int row, int col) 1721 { 1722 struct rasops_info *ri = cookie; 1723 struct vcons_screen *scr = ri->ri_hw; 1724 struct cgfourteen_softc *sc = scr->scr_cookie; 1725 int x, y, wi, he; 1726 1727 wi = ri->ri_font->fontwidth; 1728 he = ri->ri_font->fontheight; 1729 1730 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1731 if (on) { 1732 if (ri->ri_flg & RI_CURSOR) { 1733 cg14_nuke_cursor(ri); 1734 } 1735 x = col * wi + ri->ri_xorigin; 1736 y = row * he + ri->ri_yorigin; 1737 cg14_invert(sc, x, y, wi, he); 1738 ri->ri_flg |= RI_CURSOR; 1739 } 1740 ri->ri_crow = row; 1741 ri->ri_ccol = col; 1742 } else { 1743 scr->scr_ri.ri_crow = row; 1744 scr->scr_ri.ri_ccol = col; 1745 scr->scr_ri.ri_flg &= ~RI_CURSOR; 1746 } 1747 1748 } 1749 1750 static int 1751 cg14_allocattr(void *cookie, int fg0, int bg0, int flg, long *attr) 1752 { 1753 struct rasops_info *ri = cookie; 1754 int fg = fg0, bg = bg0; 1755 1756 if ((flg & WSATTR_BLINK) != 0) 1757 return EINVAL; 1758 1759 if ((flg & WSATTR_REVERSE) != 0) { 1760 fg = bg0; 1761 bg = fg0; 1762 } 1763 1764 if (FONT_IS_ALPHA(ri->ri_font) && ((flg & WSATTR_HILIT) != 0)) { 1765 fg = fg0 < 8 ? fg0 + 8 : fg0; 1766 } 1767 1768 *attr = (bg << 16) | (fg << 24) | flg; 1769 return 0; 1770 } 1771 1772 static void 1773 cg14_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1774 { 1775 struct rasops_info *ri = cookie; 1776 struct wsdisplay_font *font = PICK_FONT(ri, c); 1777 struct vcons_screen *scr = ri->ri_hw; 1778 struct cgfourteen_softc *sc = scr->scr_cookie; 1779 int stride = sc->sc_fb.fb_type.fb_width; 1780 uint32_t bg, fg, addr, bg8, fg8, pixel, in, q, next; 1781 int i, j, x, y, wi, he, r, g, b, aval, cnt, reg; 1782 int r1, g1, b1, r0, g0, b0, fgo, bgo, rv; 1783 uint8_t *data8; 1784 1785 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1786 return; 1787 1788 if (!CHAR_IN_FONT(c, font)) 1789 return; 1790 1791 if (row == ri->ri_crow && col == ri->ri_ccol) { 1792 ri->ri_flg &= ~RI_CURSOR; 1793 } 1794 1795 wi = font->fontwidth; 1796 he = font->fontheight; 1797 1798 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1799 fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 1800 x = ri->ri_xorigin + col * wi; 1801 y = ri->ri_yorigin + row * he; 1802 if (c == 0x20) { 1803 cg14_rectfill(sc, x, y, wi, he, bg); 1804 if (attr & WSATTR_UNDERLINE) 1805 cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1806 return; 1807 } 1808 1809 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1810 if (rv == GC_OK) 1811 return; 1812 1813 addr = sc->sc_fb_paddr + x + stride * y; 1814 data8 = WSFONT_GLYPH(c, font); 1815 1816 /* 1817 * we need the RGB colours here, so get offsets into rasops_cmap 1818 */ 1819 fgo = ((attr >> 24) & 0xf) * 3; 1820 bgo = ((attr >> 16) & 0xf) * 3; 1821 1822 r0 = rasops_cmap[bgo]; 1823 r1 = rasops_cmap[fgo]; 1824 g0 = rasops_cmap[bgo + 1]; 1825 g1 = rasops_cmap[fgo + 1]; 1826 b0 = rasops_cmap[bgo + 2]; 1827 b1 = rasops_cmap[fgo + 2]; 1828 #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 1829 bg8 = R3G3B2(r0, g0, b0); 1830 fg8 = R3G3B2(r1, g1, b1); 1831 1832 for (i = 0; i < he; i++) { 1833 /* calculate one line of pixels */ 1834 for (j = 0; j < wi; j++) { 1835 aval = *data8; 1836 if (aval == 0) { 1837 pixel = bg8; 1838 } else if (aval == 255) { 1839 pixel = fg8; 1840 } else { 1841 r = aval * r1 + (255 - aval) * r0; 1842 g = aval * g1 + (255 - aval) * g0; 1843 b = aval * b1 + (255 - aval) * b0; 1844 pixel = ((r & 0xe000) >> 8) | 1845 ((g & 0xe000) >> 11) | 1846 ((b & 0xc000) >> 14); 1847 } 1848 /* 1849 * stick them into SX registers and hope we never have 1850 * to deal with fonts more than 120 pixels wide 1851 */ 1852 sx_write(sc->sc_sx, SX_QUEUED(j + 8), pixel); 1853 data8++; 1854 } 1855 /* now write them into video memory */ 1856 in = (addr & 3); 1857 next = addr; 1858 reg = 8; 1859 cnt = wi; 1860 if (in != 0) { 1861 in = 4 - in; /* pixels to write until aligned */ 1862 sxm(SX_STB, next, 8, in - 1); 1863 next += in; 1864 reg = 8 + in; 1865 cnt -= in; 1866 } 1867 q = cnt >> 2; /* number of writes we can do in quads */ 1868 if (q > 0) { 1869 sxm(SX_STUQ0, next, reg, q - 1); 1870 next += (q << 2); 1871 cnt -= (q << 2); 1872 reg += (q << 2); 1873 } 1874 if (cnt > 0) { 1875 sxm(SX_STB, next, reg, cnt - 1); 1876 } 1877 addr += stride; 1878 } 1879 1880 if (rv == GC_ADD) { 1881 glyphcache_add(&sc->sc_gc, c, x, y); 1882 } else if (attr & WSATTR_UNDERLINE) 1883 cg14_rectfill(sc, x, y + he - 2, wi, 1, fg); 1884 } 1885 1886 static void 1887 cg14_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1888 { 1889 struct rasops_info *ri = cookie; 1890 struct vcons_screen *scr = ri->ri_hw; 1891 struct cgfourteen_softc *sc = scr->scr_cookie; 1892 int32_t xs, xd, y, width, height; 1893 1894 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1895 if (ri->ri_crow == row && 1896 (ri->ri_ccol >= srccol && ri->ri_ccol < (srccol + ncols)) && 1897 (ri->ri_flg & RI_CURSOR)) { 1898 cg14_nuke_cursor(ri); 1899 } 1900 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1901 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1902 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1903 width = ri->ri_font->fontwidth * ncols; 1904 height = ri->ri_font->fontheight; 1905 cg14_bitblt(sc, xs, y, xd, y, width, height, 0x0c); 1906 if (ri->ri_crow == row && 1907 (ri->ri_ccol >= dstcol && ri->ri_ccol < (dstcol + ncols))) 1908 ri->ri_flg &= ~RI_CURSOR; 1909 } 1910 } 1911 1912 static void 1913 cg14_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1914 { 1915 struct rasops_info *ri = cookie; 1916 struct vcons_screen *scr = ri->ri_hw; 1917 struct cgfourteen_softc *sc = scr->scr_cookie; 1918 int32_t x, y, width, height, fg, bg, ul; 1919 1920 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1921 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1922 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1923 width = ri->ri_font->fontwidth * ncols; 1924 height = ri->ri_font->fontheight; 1925 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1926 cg14_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1927 if (ri->ri_crow == row && 1928 (ri->ri_ccol >= startcol && ri->ri_ccol < (startcol + ncols))) 1929 ri->ri_flg &= ~RI_CURSOR; 1930 1931 } 1932 } 1933 1934 static void 1935 cg14_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1936 { 1937 struct rasops_info *ri = cookie; 1938 struct vcons_screen *scr = ri->ri_hw; 1939 struct cgfourteen_softc *sc = scr->scr_cookie; 1940 int32_t x, ys, yd, width, height; 1941 1942 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1943 if ((ri->ri_crow >= srcrow && ri->ri_crow < (srcrow + nrows)) && 1944 (ri->ri_flg & RI_CURSOR)) { 1945 cg14_nuke_cursor(ri); 1946 } 1947 x = ri->ri_xorigin; 1948 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1949 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1950 width = ri->ri_emuwidth; 1951 height = ri->ri_font->fontheight * nrows; 1952 cg14_bitblt(sc, x, ys, x, yd, width, height, 0x0c); 1953 if (ri->ri_crow >= dstrow && ri->ri_crow < (dstrow + nrows)) 1954 ri->ri_flg &= ~RI_CURSOR; 1955 } 1956 } 1957 1958 static void 1959 cg14_eraserows(void *cookie, int row, int nrows, long fillattr) 1960 { 1961 struct rasops_info *ri = cookie; 1962 struct vcons_screen *scr = ri->ri_hw; 1963 struct cgfourteen_softc *sc = scr->scr_cookie; 1964 int32_t x, y, width, height, fg, bg, ul; 1965 1966 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1967 x = ri->ri_xorigin; 1968 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1969 width = ri->ri_emuwidth; 1970 height = ri->ri_font->fontheight * nrows; 1971 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1972 cg14_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1973 if (ri->ri_crow >= row && ri->ri_crow < (row + nrows)) 1974 ri->ri_flg &= ~RI_CURSOR; 1975 } 1976 } 1977 1978 #endif /* NSX > 0 */ 1979 1980