1 /* $NetBSD: cgfourteen.c,v 1.76 2013/08/14 01:53:27 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 /* 63 * The following is for debugging only; it opens up a security hole 64 * enabled by allowing any user to map the control registers for the 65 * cg14 into their space. 66 */ 67 #undef CG14_MAP_REGS 68 69 #include "opt_wsemul.h" 70 #include "sx.h" 71 72 #include <sys/param.h> 73 #include <sys/systm.h> 74 #include <sys/buf.h> 75 #include <sys/device.h> 76 #include <sys/ioctl.h> 77 #include <sys/malloc.h> 78 #include <sys/kmem.h> 79 #include <sys/mman.h> 80 #include <sys/tty.h> 81 #include <sys/conf.h> 82 #include <dev/pci/pciio.h> 83 84 #include <uvm/uvm_extern.h> 85 86 #include <dev/sun/fbio.h> 87 #include <machine/autoconf.h> 88 #include <machine/pmap.h> 89 #include <dev/sun/fbvar.h> 90 #include <machine/cpu.h> 91 #include <dev/sbus/sbusvar.h> 92 93 #include "wsdisplay.h" 94 #include <dev/wscons/wsconsio.h> 95 #include <dev/wsfont/wsfont.h> 96 #include <dev/rasops/rasops.h> 97 98 #include <dev/wscons/wsdisplay_vconsvar.h> 99 100 #include <sparc/sparc/asm.h> 101 #include <sparc/dev/cgfourteenreg.h> 102 #include <sparc/dev/cgfourteenvar.h> 103 #include <sparc/dev/sxreg.h> 104 #include <sparc/dev/sxvar.h> 105 106 /* autoconfiguration driver */ 107 static int cgfourteenmatch(device_t, struct cfdata *, void *); 108 static void cgfourteenattach(device_t, device_t, void *); 109 static void cgfourteenunblank(device_t); 110 111 CFATTACH_DECL_NEW(cgfourteen, sizeof(struct cgfourteen_softc), 112 cgfourteenmatch, cgfourteenattach, NULL, NULL); 113 114 extern struct cfdriver cgfourteen_cd; 115 116 dev_type_open(cgfourteenopen); 117 dev_type_close(cgfourteenclose); 118 dev_type_ioctl(cgfourteenioctl); 119 dev_type_mmap(cgfourteenmmap); 120 dev_type_poll(cgfourteenpoll); 121 122 const struct cdevsw cgfourteen_cdevsw = { 123 cgfourteenopen, cgfourteenclose, noread, nowrite, cgfourteenioctl, 124 nostop, notty, cgfourteenpoll, cgfourteenmmap, nokqfilter, 125 }; 126 127 /* frame buffer generic driver */ 128 static struct fbdriver cgfourteenfbdriver = { 129 cgfourteenunblank, cgfourteenopen, cgfourteenclose, cgfourteenioctl, 130 cgfourteenpoll, cgfourteenmmap, nokqfilter 131 }; 132 133 static void cg14_set_video(struct cgfourteen_softc *, int); 134 static int cg14_get_video(struct cgfourteen_softc *); 135 static int cg14_get_cmap(struct fbcmap *, union cg14cmap *, int); 136 static int cg14_put_cmap(struct fbcmap *, union cg14cmap *, int); 137 static void cg14_load_hwcmap(struct cgfourteen_softc *, int, int); 138 static void cg14_init(struct cgfourteen_softc *); 139 static void cg14_reset(struct cgfourteen_softc *); 140 141 #if NWSDISPLAY > 0 142 static void cg14_setup_wsdisplay(struct cgfourteen_softc *, int); 143 static void cg14_init_cmap(struct cgfourteen_softc *); 144 static int cg14_putcmap(struct cgfourteen_softc *, struct wsdisplay_cmap *); 145 static int cg14_getcmap(struct cgfourteen_softc *, struct wsdisplay_cmap *); 146 static void cg14_set_depth(struct cgfourteen_softc *, int); 147 static void cg14_move_cursor(struct cgfourteen_softc *, int, int); 148 static int cg14_do_cursor(struct cgfourteen_softc *, 149 struct wsdisplay_cursor *); 150 151 #if NSX > 0 152 static void cg14_wait_idle(struct cgfourteen_softc *); 153 static void cg14_rectfill(struct cgfourteen_softc *, int, int, int, int, 154 uint32_t); 155 static void cg14_invert(struct cgfourteen_softc *, int, int, int, int); 156 static void cg14_bitblt(void *, int, int, int, int, int, int, int); 157 158 #if 0 159 static void cg14_putchar_aa(void *, int, int, u_int, long); 160 #endif 161 static void cg14_cursor(void *, int, int, int); 162 static void cg14_putchar(void *, int, int, u_int, long); 163 static void cg14_copycols(void *, int, int, int, int); 164 static void cg14_erasecols(void *, int, int, int, long); 165 static void cg14_copyrows(void *, int, int, int); 166 static void cg14_eraserows(void *, int, int, long); 167 #endif /* NSX > 0 */ 168 169 #endif 170 171 /* 172 * Match a cgfourteen. 173 */ 174 int 175 cgfourteenmatch(device_t parent, struct cfdata *cf, void *aux) 176 { 177 union obio_attach_args *uoba = aux; 178 struct sbus_attach_args *sa = &uoba->uoba_sbus; 179 180 /* 181 * The cgfourteen is a local-bus video adaptor, accessed directly 182 * via the processor, and not through device space or an external 183 * bus. Thus we look _only_ at the obio bus. 184 * Additionally, these things exist only on the Sun4m. 185 */ 186 187 if (uoba->uoba_isobio4 != 0 || !CPU_ISSUN4M) 188 return (0); 189 190 /* Check driver name */ 191 return (strcmp(cf->cf_name, sa->sa_name) == 0); 192 } 193 194 #if NWSDISPLAY > 0 195 static int cg14_ioctl(void *, void *, u_long, void *, int, struct lwp *); 196 static paddr_t cg14_mmap(void *, void *, off_t, int); 197 static void cg14_init_screen(void *, struct vcons_screen *, int, long *); 198 199 200 struct wsdisplay_accessops cg14_accessops = { 201 cg14_ioctl, 202 cg14_mmap, 203 NULL, /* alloc_screen */ 204 NULL, /* free_screen */ 205 NULL, /* show_screen */ 206 NULL, /* load_font */ 207 NULL, /* pollc */ 208 NULL /* scroll */ 209 }; 210 #endif 211 212 /* 213 * Attach a display. We need to notice if it is the console, too. 214 */ 215 void 216 cgfourteenattach(device_t parent, device_t self, void *aux) 217 { 218 union obio_attach_args *uoba = aux; 219 struct sbus_attach_args *sa = &uoba->uoba_sbus; 220 struct cgfourteen_softc *sc = device_private(self); 221 struct fbdevice *fb = &sc->sc_fb; 222 bus_space_handle_t bh; 223 int node; 224 volatile uint32_t *lut; 225 int i, isconsole, items; 226 uint32_t fbva[2] = {0, 0}; 227 uint32_t *ptr = fbva; 228 #if NSX > 0 229 device_t dv; 230 deviter_t di; 231 #endif 232 233 sc->sc_dev = self; 234 sc->sc_opens = 0; 235 node = sa->sa_node; 236 237 /* Remember cookies for cgfourteenmmap() */ 238 sc->sc_bustag = sa->sa_bustag; 239 240 fb->fb_driver = &cgfourteenfbdriver; 241 fb->fb_device = sc->sc_dev; 242 /* Mask out invalid flags from the user. */ 243 fb->fb_flags = device_cfdata(sc->sc_dev)->cf_flags & FB_USERMASK; 244 245 fb->fb_type.fb_type = FBTYPE_MDICOLOR; 246 fb->fb_type.fb_depth = 32; 247 248 fb_setsize_obp(fb, sc->sc_fb.fb_type.fb_depth, 1152, 900, node); 249 250 fb->fb_type.fb_cmsize = CG14_CLUT_SIZE; 251 252 if (sa->sa_nreg < 2) { 253 printf("%s: only %d register sets\n", 254 device_xname(self), sa->sa_nreg); 255 return; 256 } 257 memcpy(sc->sc_physadr, sa->sa_reg, 258 sa->sa_nreg * sizeof(struct sbus_reg)); 259 260 sc->sc_vramsize = sc->sc_physadr[CG14_PXL_IDX].sbr_size; 261 fb->fb_type.fb_size = sc->sc_vramsize; 262 263 printf(": %d MB VRAM", (uint32_t)(sc->sc_vramsize >> 20)); 264 /* 265 * Now map in the 8 useful pages of registers 266 */ 267 if (sa->sa_size < 0x10000) { 268 #ifdef DIAGNOSTIC 269 printf("warning: can't find all cgfourteen registers...\n"); 270 #endif 271 sa->sa_size = 0x10000; 272 } 273 if (sbus_bus_map(sa->sa_bustag, sa->sa_slot, 274 sa->sa_offset, 275 sa->sa_size, 276 0 /*BUS_SPACE_MAP_LINEAR*/, 277 &bh) != 0) { 278 printf("%s: cannot map control registers\n", 279 device_xname(self)); 280 return; 281 } 282 sc->sc_regh = bh; 283 sc->sc_regaddr = BUS_ADDR(sa->sa_slot, sa->sa_offset); 284 sc->sc_fbaddr = BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 285 sc->sc_physadr[CG14_PXL_IDX].sbr_offset); 286 287 sc->sc_ctl = (struct cg14ctl *) (bh); 288 sc->sc_hwc = (struct cg14curs *) (bh + CG14_OFFSET_CURS); 289 sc->sc_dac = (struct cg14dac *) (bh + CG14_OFFSET_DAC); 290 sc->sc_xlut = (struct cg14xlut *) (bh + CG14_OFFSET_XLUT); 291 sc->sc_clut1 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT1); 292 sc->sc_clut2 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT2); 293 sc->sc_clut3 = (struct cg14clut *) (bh + CG14_OFFSET_CLUT3); 294 sc->sc_clutincr = (u_int *) (bh + CG14_OFFSET_CLUTINCR); 295 296 /* 297 * Let the user know that we're here 298 */ 299 printf(": %dx%d", 300 fb->fb_type.fb_width, fb->fb_type.fb_height); 301 302 /* 303 * Enable the video. 304 */ 305 cg14_set_video(sc, 1); 306 307 /* 308 * Grab the initial colormap 309 */ 310 lut = sc->sc_clut1->clut_lut; 311 for (i = 0; i < CG14_CLUT_SIZE; i++) 312 sc->sc_cmap.cm_chip[i] = lut[i]; 313 314 /* See if we're the console */ 315 isconsole = fb_is_console(node); 316 317 #if NWSDISPLAY > 0 318 prom_getprop(sa->sa_node, "address", 4, &items, &ptr); 319 if (fbva[1] == 0) { 320 if (sbus_bus_map( sc->sc_bustag, 321 sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 322 sc->sc_physadr[CG14_PXL_IDX].sbr_offset, 323 sc->sc_vramsize, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, 324 &bh) != 0) { 325 printf("%s: cannot map pixels\n", 326 device_xname(sc->sc_dev)); 327 return; 328 } 329 sc->sc_fb.fb_pixels = bus_space_vaddr(sc->sc_bustag, bh); 330 } else { 331 sc->sc_fb.fb_pixels = (void *)fbva[1]; 332 } 333 334 if (isconsole) 335 printf(" (console)\n"); 336 else 337 printf("\n"); 338 339 sc->sc_depth = 8; 340 341 #if NSX > 0 342 /* see if we've got an SX to help us */ 343 sc->sc_sx = NULL; 344 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); 345 dv != NULL; 346 dv = deviter_next(&di)) { 347 if (device_is_a(dv, "sx")) { 348 sc->sc_sx = device_private(dv); 349 } 350 } 351 deviter_release(&di); 352 if (sc->sc_sx != NULL) { 353 sc->sc_fb_paddr = bus_space_mmap(sc->sc_bustag, 354 sc->sc_fbaddr, 0, 0, 0) & 0xfffff000; 355 aprint_normal_dev(sc->sc_dev, "using %s\n", 356 device_xname(sc->sc_sx->sc_dev)); 357 aprint_debug_dev(sc->sc_dev, "fb paddr: %08x\n", 358 sc->sc_fb_paddr); 359 sx_write(sc->sc_sx, SX_PAGE_BOUND_LOWER, sc->sc_fb_paddr); 360 sx_write(sc->sc_sx, SX_PAGE_BOUND_UPPER, 361 sc->sc_fb_paddr + 0x03ffffff); 362 } 363 cg14_wait_idle(sc); 364 #endif 365 cg14_setup_wsdisplay(sc, isconsole); 366 #endif 367 368 /* Attach to /dev/fb */ 369 fb_attach(&sc->sc_fb, isconsole); 370 } 371 372 /* 373 * Keep track of the number of opens made. In the 24-bit driver, we need to 374 * switch to 24-bit mode on the first open, and switch back to 8-bit on 375 * the last close. This kind of nonsense is needed to give screenblank 376 * a fighting chance of working. 377 */ 378 379 int 380 cgfourteenopen(dev_t dev, int flags, int mode, struct lwp *l) 381 { 382 struct cgfourteen_softc *sc; 383 int oldopens; 384 385 sc = device_lookup_private(&cgfourteen_cd, minor(dev)); 386 if (sc == NULL) 387 return(ENXIO); 388 oldopens = sc->sc_opens++; 389 390 /* Setup the cg14 as we want it, and save the original PROM state */ 391 if (oldopens == 0) /* first open only, to make screenblank work */ 392 cg14_init(sc); 393 394 return (0); 395 } 396 397 int 398 cgfourteenclose(dev_t dev, int flags, int mode, struct lwp *l) 399 { 400 struct cgfourteen_softc *sc = 401 device_lookup_private(&cgfourteen_cd, minor(dev)); 402 int opens; 403 404 opens = --sc->sc_opens; 405 if (sc->sc_opens < 0) 406 opens = sc->sc_opens = 0; 407 408 /* 409 * Restore video state to make the PROM happy, on last close. 410 */ 411 if (opens == 0) 412 cg14_reset(sc); 413 414 return (0); 415 } 416 417 int 418 cgfourteenioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 419 { 420 struct cgfourteen_softc *sc = 421 device_lookup_private(&cgfourteen_cd, minor(dev)); 422 struct fbgattr *fba; 423 int error; 424 425 switch (cmd) { 426 427 case FBIOGTYPE: 428 *(struct fbtype *)data = sc->sc_fb.fb_type; 429 break; 430 431 case FBIOGATTR: 432 fba = (struct fbgattr *)data; 433 fba->real_type = FBTYPE_MDICOLOR; 434 fba->owner = 0; /* XXX ??? */ 435 fba->fbtype = sc->sc_fb.fb_type; 436 fba->sattr.flags = 0; 437 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 438 fba->sattr.dev_specific[0] = -1; 439 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 440 fba->emu_types[1] = -1; 441 break; 442 443 case FBIOGETCMAP: 444 return(cg14_get_cmap((struct fbcmap *)data, &sc->sc_cmap, 445 CG14_CLUT_SIZE)); 446 447 case FBIOPUTCMAP: 448 /* copy to software map */ 449 #define p ((struct fbcmap *)data) 450 error = cg14_put_cmap(p, &sc->sc_cmap, CG14_CLUT_SIZE); 451 if (error) 452 return (error); 453 /* now blast them into the chip */ 454 /* XXX should use retrace interrupt */ 455 cg14_load_hwcmap(sc, p->index, p->count); 456 #undef p 457 break; 458 459 case FBIOGVIDEO: 460 *(int *)data = cg14_get_video(sc); 461 break; 462 463 case FBIOSVIDEO: 464 cg14_set_video(sc, *(int *)data); 465 break; 466 467 case CG14_SET_PIXELMODE: { 468 int depth = *(int *)data; 469 470 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) 471 return EINVAL; 472 473 cg14_set_depth(sc, depth); 474 } 475 break; 476 default: 477 return (ENOTTY); 478 } 479 return (0); 480 } 481 482 /* 483 * Undo the effect of an FBIOSVIDEO that turns the video off. 484 */ 485 static void 486 cgfourteenunblank(device_t dev) 487 { 488 struct cgfourteen_softc *sc = device_private(dev); 489 490 cg14_set_video(sc, 1); 491 #if NWSDISPLAY > 0 492 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) { 493 cg14_set_depth(sc, 8); 494 cg14_init_cmap(sc); 495 vcons_redraw_screen(sc->sc_vd.active); 496 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 497 } 498 #endif 499 } 500 501 /* 502 * Return the address that would map the given device at the given 503 * offset, allowing for the given protection, or return -1 for error. 504 */ 505 paddr_t 506 cgfourteenmmap(dev_t dev, off_t off, int prot) 507 { 508 struct cgfourteen_softc *sc = 509 device_lookup_private(&cgfourteen_cd, minor(dev)); 510 off_t offset = -1; 511 512 if (off & PGOFSET) 513 panic("cgfourteenmmap"); 514 515 if (off < 0) 516 return (-1); 517 518 if (off >= 0 && off < 0x10000) { 519 offset = sc->sc_regaddr; 520 } else if (off >= CG14_CURSOR_VOFF && 521 off < (CG14_CURSOR_VOFF + 0x1000)) { 522 offset = sc->sc_regaddr + CG14_OFFSET_CURS; 523 off -= CG14_CURSOR_VOFF; 524 } else if (off >= CG14_DIRECT_VOFF && 525 off < (CG14_DIRECT_VOFF + sc->sc_vramsize)) { 526 offset = sc->sc_fbaddr + CG14_FB_VRAM; 527 off -= CG14_DIRECT_VOFF; 528 } else if (off >= CG14_BGR_VOFF && 529 off < (CG14_BGR_VOFF + sc->sc_vramsize)) { 530 offset = sc->sc_fbaddr + CG14_FB_CBGR; 531 off -= CG14_BGR_VOFF; 532 } else if (off >= CG14_X32_VOFF && 533 off < (CG14_X32_VOFF + (sc->sc_vramsize >> 2))) { 534 offset = sc->sc_fbaddr + CG14_FB_PX32; 535 off -= CG14_X32_VOFF; 536 } else if (off >= CG14_B32_VOFF && 537 off < (CG14_B32_VOFF + (sc->sc_vramsize >> 2))) { 538 offset = sc->sc_fbaddr + CG14_FB_PB32; 539 off -= CG14_B32_VOFF; 540 } else if (off >= CG14_G32_VOFF && 541 off < (CG14_G32_VOFF + (sc->sc_vramsize >> 2))) { 542 offset = sc->sc_fbaddr + CG14_FB_PG32; 543 off -= CG14_G32_VOFF; 544 } else if (off >= CG14_R32_VOFF && 545 off < CG14_R32_VOFF + (sc->sc_vramsize >> 2)) { 546 offset = sc->sc_fbaddr + CG14_FB_PR32; 547 off -= CG14_R32_VOFF; 548 #if NSX > 0 549 /* 550 * for convenience we also map the SX ranges here: 551 * - one page userland registers 552 * - CG14-sized IO space at 0x800000000 ( not a typo, it's above 4GB ) 553 */ 554 } else if (sc->sc_sx == NULL) { 555 return -1; 556 } else if (off >= CG14_SXREG_VOFF && 557 off < (CG14_SXREG_VOFF + 0x400)) { 558 return (bus_space_mmap(sc->sc_sx->sc_tag, sc->sc_sx->sc_uregs, 559 0, prot, BUS_SPACE_MAP_LINEAR)); 560 } else if (off >= CG14_SXIO_VOFF && 561 off < (CG14_SXIO_VOFF + 0x03ffffff)) { 562 return (bus_space_mmap(sc->sc_sx->sc_tag, 0x800000000LL, 563 sc->sc_fb_paddr + (off - CG14_SXIO_VOFF), 564 prot, BUS_SPACE_MAP_LINEAR)); 565 #endif 566 } else 567 return -1; 568 569 return (bus_space_mmap(sc->sc_bustag, offset, off, prot, 570 BUS_SPACE_MAP_LINEAR)); 571 } 572 573 int 574 cgfourteenpoll(dev_t dev, int events, struct lwp *l) 575 { 576 577 return (seltrue(dev, events, l)); 578 } 579 580 /* 581 * Miscellaneous helper functions 582 */ 583 584 /* Initialize the framebuffer, storing away useful state for later reset */ 585 static void 586 cg14_init(struct cgfourteen_softc *sc) 587 { 588 #if 0 589 volatile uint32_t *clut; 590 volatile uint8_t *xlut; 591 int i; 592 593 /* 594 * We stash away the following to restore on close: 595 * 596 * color look-up table 1 (sc->sc_saveclut) 597 * x look-up table (sc->sc_savexlut) 598 * control register (sc->sc_savectl) 599 * cursor control register (sc->sc_savehwc) 600 */ 601 sc->sc_savectl = sc->sc_ctl->ctl_mctl; 602 sc->sc_savehwc = sc->sc_hwc->curs_ctl; 603 604 clut = (volatile uint32_t *) sc->sc_clut1->clut_lut; 605 xlut = (volatile uint8_t *) sc->sc_xlut->xlut_lut; 606 for (i = 0; i < CG14_CLUT_SIZE; i++) { 607 sc->sc_saveclut.cm_chip[i] = clut[i]; 608 sc->sc_savexlut[i] = xlut[i]; 609 } 610 611 /* 612 * Enable the video and put it in 8 bit mode 613 */ 614 sc->sc_ctl->ctl_mctl = CG14_MCTL_ENABLEVID | CG14_MCTL_PIXMODE_8 | 615 CG14_MCTL_POWERCTL; 616 #else 617 cg14_set_depth(sc, 32); 618 #endif 619 } 620 621 static void 622 /* Restore the state saved on cg14_init */ 623 cg14_reset(struct cgfourteen_softc *sc) 624 { 625 #if 0 626 volatile uint32_t *clut; 627 volatile uint8_t *xlut; 628 int i; 629 630 /* 631 * We restore the following, saved in cg14_init: 632 * 633 * color look-up table 1 (sc->sc_saveclut) 634 * x look-up table (sc->sc_savexlut) 635 * control register (sc->sc_savectl) 636 * cursor control register (sc->sc_savehwc) 637 * 638 * Note that we don't touch the video enable bits in the 639 * control register; otherwise, screenblank wouldn't work. 640 */ 641 sc->sc_ctl->ctl_mctl = (sc->sc_ctl->ctl_mctl & (CG14_MCTL_ENABLEVID | 642 CG14_MCTL_POWERCTL)) | 643 (sc->sc_savectl & ~(CG14_MCTL_ENABLEVID | 644 CG14_MCTL_POWERCTL)); 645 sc->sc_hwc->curs_ctl = sc->sc_savehwc; 646 647 clut = sc->sc_clut1->clut_lut; 648 xlut = sc->sc_xlut->xlut_lut; 649 for (i = 0; i < CG14_CLUT_SIZE; i++) { 650 clut[i] = sc->sc_saveclut.cm_chip[i]; 651 xlut[i] = sc->sc_savexlut[i]; 652 } 653 #else 654 cg14_set_depth(sc, 8); 655 #endif 656 } 657 658 /* Enable/disable video display; power down monitor if DPMS-capable */ 659 static void 660 cg14_set_video(struct cgfourteen_softc *sc, int enable) 661 { 662 /* 663 * We can only use DPMS to power down the display if the chip revision 664 * is greater than 0. 665 */ 666 if (enable) { 667 if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 668 sc->sc_ctl->ctl_mctl |= (CG14_MCTL_ENABLEVID | 669 CG14_MCTL_POWERCTL); 670 else 671 sc->sc_ctl->ctl_mctl |= CG14_MCTL_ENABLEVID; 672 } else { 673 if ((sc->sc_ctl->ctl_rsr & CG14_RSR_REVMASK) > 0) 674 sc->sc_ctl->ctl_mctl &= ~(CG14_MCTL_ENABLEVID | 675 CG14_MCTL_POWERCTL); 676 else 677 sc->sc_ctl->ctl_mctl &= ~CG14_MCTL_ENABLEVID; 678 } 679 } 680 681 /* Get status of video display */ 682 static int 683 cg14_get_video(struct cgfourteen_softc *sc) 684 { 685 return ((sc->sc_ctl->ctl_mctl & CG14_MCTL_ENABLEVID) != 0); 686 } 687 688 /* Read the software shadow colormap */ 689 static int 690 cg14_get_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 691 { 692 u_int i, start, count; 693 u_char *cp; 694 int error; 695 696 start = p->index; 697 count = p->count; 698 if (start >= cmsize || count > cmsize - start) 699 return (EINVAL); 700 701 for (cp = &cm->cm_map[start][0], i = 0; i < count; cp += 4, i++) { 702 error = copyout(&cp[3], &p->red[i], 1); 703 if (error) 704 return error; 705 error = copyout(&cp[2], &p->green[i], 1); 706 if (error) 707 return error; 708 error = copyout(&cp[1], &p->blue[i], 1); 709 if (error) 710 return error; 711 } 712 return (0); 713 } 714 715 /* Write the software shadow colormap */ 716 static int 717 cg14_put_cmap(struct fbcmap *p, union cg14cmap *cm, int cmsize) 718 { 719 u_int i, start, count; 720 u_char *cp; 721 u_char cmap[256][4]; 722 int error; 723 724 start = p->index; 725 count = p->count; 726 if (start >= cmsize || count > cmsize - start) 727 return (EINVAL); 728 729 memcpy(&cmap, &cm->cm_map, sizeof cmap); 730 for (cp = &cmap[start][0], i = 0; i < count; cp += 4, i++) { 731 error = copyin(&p->red[i], &cp[3], 1); 732 if (error) 733 return error; 734 error = copyin(&p->green[i], &cp[2], 1); 735 if (error) 736 return error; 737 error = copyin(&p->blue[i], &cp[1], 1); 738 if (error) 739 return error; 740 cp[0] = 0; /* no alpha channel */ 741 } 742 memcpy(&cm->cm_map, &cmap, sizeof cmap); 743 return (0); 744 } 745 746 static void 747 cg14_load_hwcmap(struct cgfourteen_softc *sc, int start, int ncolors) 748 { 749 /* XXX switch to auto-increment, and on retrace intr */ 750 751 /* Setup pointers to source and dest */ 752 uint32_t *colp = &sc->sc_cmap.cm_chip[start]; 753 volatile uint32_t *lutp = &sc->sc_clut1->clut_lut[start]; 754 755 /* Copy by words */ 756 while (--ncolors >= 0) 757 *lutp++ = *colp++; 758 } 759 760 #if NWSDISPLAY > 0 761 static void 762 cg14_setup_wsdisplay(struct cgfourteen_softc *sc, int is_cons) 763 { 764 struct wsemuldisplaydev_attach_args aa; 765 struct rasops_info *ri; 766 long defattr; 767 768 sc->sc_defaultscreen_descr = (struct wsscreen_descr){ 769 "default", 770 0, 0, 771 NULL, 772 8, 16, 773 WSSCREEN_WSCOLORS | WSSCREEN_HILIT, 774 NULL 775 }; 776 sc->sc_screens[0] = &sc->sc_defaultscreen_descr; 777 sc->sc_screenlist = (struct wsscreen_list){1, sc->sc_screens}; 778 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 779 vcons_init(&sc->sc_vd, sc, &sc->sc_defaultscreen_descr, 780 &cg14_accessops); 781 sc->sc_vd.init_screen = cg14_init_screen; 782 783 ri = &sc->sc_console_screen.scr_ri; 784 785 if (is_cons) { 786 vcons_init_screen(&sc->sc_vd, &sc->sc_console_screen, 1, 787 &defattr); 788 789 /* clear the screen with the default background colour */ 790 memset(sc->sc_fb.fb_pixels, 791 (defattr >> 16) & 0xff, 792 ri->ri_stride * ri->ri_height); 793 sc->sc_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 794 795 sc->sc_defaultscreen_descr.textops = &ri->ri_ops; 796 sc->sc_defaultscreen_descr.capabilities = ri->ri_caps; 797 sc->sc_defaultscreen_descr.nrows = ri->ri_rows; 798 sc->sc_defaultscreen_descr.ncols = ri->ri_cols; 799 wsdisplay_cnattach(&sc->sc_defaultscreen_descr, ri, 0, 0, 800 defattr); 801 vcons_replay_msgbuf(&sc->sc_console_screen); 802 } else { 803 /* 804 * since we're not the console we can postpone the rest 805 * until someone actually allocates a screen for us 806 */ 807 } 808 809 cg14_init_cmap(sc); 810 811 aa.console = is_cons; 812 aa.scrdata = &sc->sc_screenlist; 813 aa.accessops = &cg14_accessops; 814 aa.accesscookie = &sc->sc_vd; 815 816 config_found(sc->sc_dev, &aa, wsemuldisplaydevprint); 817 } 818 819 static void 820 cg14_init_cmap(struct cgfourteen_softc *sc) 821 { 822 int i, j = 0; 823 824 for (i = 0; i < 256; i++) { 825 826 sc->sc_cmap.cm_map[i][3] = rasops_cmap[j]; 827 sc->sc_cmap.cm_map[i][2] = rasops_cmap[j + 1]; 828 sc->sc_cmap.cm_map[i][1] = rasops_cmap[j + 2]; 829 j += 3; 830 } 831 cg14_load_hwcmap(sc, 0, 256); 832 } 833 834 static int 835 cg14_putcmap(struct cgfourteen_softc *sc, struct wsdisplay_cmap *cm) 836 { 837 u_int index = cm->index; 838 u_int count = cm->count; 839 int i, error; 840 u_char rbuf[256], gbuf[256], bbuf[256]; 841 842 if (cm->index >= 256 || cm->count > 256 || 843 (cm->index + cm->count) > 256) 844 return EINVAL; 845 error = copyin(cm->red, &rbuf[index], count); 846 if (error) 847 return error; 848 error = copyin(cm->green, &gbuf[index], count); 849 if (error) 850 return error; 851 error = copyin(cm->blue, &bbuf[index], count); 852 if (error) 853 return error; 854 855 for (i = 0; i < count; i++) { 856 sc->sc_cmap.cm_map[index][3] = rbuf[index]; 857 sc->sc_cmap.cm_map[index][2] = gbuf[index]; 858 sc->sc_cmap.cm_map[index][1] = bbuf[index]; 859 860 index++; 861 } 862 cg14_load_hwcmap(sc, 0, 256); 863 return 0; 864 } 865 866 static int 867 cg14_getcmap(struct cgfourteen_softc *sc, struct wsdisplay_cmap *cm) 868 { 869 uint8_t rbuf[256], gbuf[256], bbuf[256]; 870 u_int index = cm->index; 871 u_int count = cm->count; 872 int error, i; 873 874 if (index >= 255 || count > 256 || index + count > 256) 875 return EINVAL; 876 877 878 for (i = 0; i < count; i++) { 879 rbuf[i] = sc->sc_cmap.cm_map[index][3]; 880 gbuf[i] = sc->sc_cmap.cm_map[index][2]; 881 bbuf[i] = sc->sc_cmap.cm_map[index][1]; 882 883 index++; 884 } 885 error = copyout(rbuf, cm->red, count); 886 if (error) 887 return error; 888 error = copyout(gbuf, cm->green, count); 889 if (error) 890 return error; 891 error = copyout(bbuf, cm->blue, count); 892 if (error) 893 return error; 894 895 return 0; 896 } 897 898 static int 899 cg14_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 900 struct lwp *l) 901 { 902 struct vcons_data *vd = v; 903 struct cgfourteen_softc *sc = vd->cookie; 904 struct wsdisplay_fbinfo *wdf; 905 struct vcons_screen *ms = vd->active; 906 907 switch (cmd) { 908 909 case WSDISPLAYIO_GTYPE: 910 *(uint32_t *)data = WSDISPLAY_TYPE_SUNCG14; 911 return 0; 912 913 case WSDISPLAYIO_GINFO: 914 wdf = (void *)data; 915 wdf->height = ms->scr_ri.ri_height; 916 wdf->width = ms->scr_ri.ri_width; 917 wdf->depth = 32; 918 wdf->cmsize = 256; 919 return 0; 920 921 case WSDISPLAYIO_GETCMAP: 922 return cg14_getcmap(sc, 923 (struct wsdisplay_cmap *)data); 924 925 case WSDISPLAYIO_PUTCMAP: 926 return cg14_putcmap(sc, 927 (struct wsdisplay_cmap *)data); 928 929 case WSDISPLAYIO_LINEBYTES: 930 *(u_int *)data = ms->scr_ri.ri_stride << 2; 931 return 0; 932 933 case WSDISPLAYIO_SMODE: 934 { 935 int new_mode = *(int*)data; 936 if (new_mode != sc->sc_mode) { 937 sc->sc_mode = new_mode; 938 if(new_mode == WSDISPLAYIO_MODE_EMUL) { 939 bus_space_write_1(sc->sc_bustag, 940 sc->sc_regh, 941 CG14_CURSOR_CONTROL, 0); 942 943 cg14_set_depth(sc, 8); 944 cg14_init_cmap(sc); 945 vcons_redraw_screen(ms); 946 } else { 947 948 cg14_set_depth(sc, 32); 949 } 950 } 951 } 952 return 0; 953 case WSDISPLAYIO_SVIDEO: 954 cg14_set_video(sc, *(int *)data); 955 return 0; 956 case WSDISPLAYIO_GVIDEO: 957 return cg14_get_video(sc) ? 958 WSDISPLAYIO_VIDEO_ON : WSDISPLAYIO_VIDEO_OFF; 959 case WSDISPLAYIO_GCURPOS: 960 { 961 struct wsdisplay_curpos *cp = (void *)data; 962 963 cp->x = sc->sc_cursor.cc_pos.x; 964 cp->y = sc->sc_cursor.cc_pos.y; 965 } 966 return 0; 967 case WSDISPLAYIO_SCURPOS: 968 { 969 struct wsdisplay_curpos *cp = (void *)data; 970 971 cg14_move_cursor(sc, cp->x, cp->y); 972 } 973 return 0; 974 case WSDISPLAYIO_GCURMAX: 975 { 976 struct wsdisplay_curpos *cp = (void *)data; 977 978 cp->x = 32; 979 cp->y = 32; 980 } 981 return 0; 982 case WSDISPLAYIO_SCURSOR: 983 { 984 struct wsdisplay_cursor *cursor = (void *)data; 985 986 return cg14_do_cursor(sc, cursor); 987 } 988 case PCI_IOC_CFGREAD: 989 case PCI_IOC_CFGWRITE: 990 return EINVAL; 991 992 } 993 return EPASSTHROUGH; 994 } 995 996 static paddr_t 997 cg14_mmap(void *v, void *vs, off_t offset, int prot) 998 { 999 struct vcons_data *vd = v; 1000 struct cgfourteen_softc *sc = vd->cookie; 1001 1002 /* allow mmap()ing the full framebuffer, not just what we use */ 1003 if (offset < sc->sc_vramsize) 1004 return bus_space_mmap(sc->sc_bustag, 1005 BUS_ADDR(sc->sc_physadr[CG14_PXL_IDX].sbr_slot, 1006 sc->sc_physadr[CG14_PXL_IDX].sbr_offset), 1007 offset + CG14_FB_CBGR, prot, BUS_SPACE_MAP_LINEAR); 1008 1009 return -1; 1010 } 1011 1012 static void 1013 cg14_init_screen(void *cookie, struct vcons_screen *scr, 1014 int existing, long *defattr) 1015 { 1016 struct cgfourteen_softc *sc = cookie; 1017 struct rasops_info *ri = &scr->scr_ri; 1018 1019 ri->ri_depth = 8; 1020 ri->ri_width = sc->sc_fb.fb_type.fb_width; 1021 ri->ri_height = sc->sc_fb.fb_type.fb_height; 1022 ri->ri_stride = ri->ri_width; 1023 ri->ri_flg = RI_CENTER | RI_FULLCLEAR; 1024 1025 ri->ri_bits = (char *)sc->sc_fb.fb_pixels; 1026 #if NSX > 0 1027 /* 1028 * unaligned copies with horizontal overlap are slow, so don't bother 1029 * handling them in cg14_bitblt() and use putchar() instead 1030 */ 1031 if (sc->sc_sx != NULL) { 1032 scr->scr_flags |= VCONS_NO_COPYCOLS; 1033 } else 1034 #endif 1035 scr->scr_flags |= VCONS_DONT_READ; 1036 1037 if (existing) { 1038 ri->ri_flg |= RI_CLEAR; 1039 } 1040 1041 rasops_init(ri, 0, 0); 1042 ri->ri_caps = WSSCREEN_WSCOLORS; 1043 1044 rasops_reconfig(ri, 1045 sc->sc_fb.fb_type.fb_height / ri->ri_font->fontheight, 1046 sc->sc_fb.fb_type.fb_width / ri->ri_font->fontwidth); 1047 1048 ri->ri_hw = scr; 1049 #if NSX > 0 1050 if (sc->sc_sx != NULL) { 1051 ri->ri_ops.copyrows = cg14_copyrows; 1052 ri->ri_ops.copycols = cg14_copycols; 1053 ri->ri_ops.eraserows = cg14_eraserows; 1054 ri->ri_ops.erasecols = cg14_erasecols; 1055 ri->ri_ops.cursor = cg14_cursor; 1056 #if 0 1057 if (FONT_IS_ALPHA(ri->ri_font)) { 1058 ri->ri_ops.putchar = cg14_putchar_aa; 1059 } else 1060 #endif 1061 ri->ri_ops.putchar = cg14_putchar; 1062 } 1063 #endif /* NSX > 0 */ 1064 } 1065 1066 static void 1067 cg14_set_depth(struct cgfourteen_softc *sc, int depth) 1068 { 1069 int i; 1070 1071 if (sc->sc_depth == depth) 1072 return; 1073 1074 switch (depth) { 1075 case 8: 1076 bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1077 CG14_MCTL, CG14_MCTL_ENABLEVID | 1078 CG14_MCTL_PIXMODE_8 | CG14_MCTL_POWERCTL); 1079 sc->sc_depth = 8; 1080 /* everything is CLUT1 */ 1081 for (i = 0; i < CG14_CLUT_SIZE; i++) 1082 sc->sc_xlut->xlut_lut[i] = 0; 1083 break; 1084 case 32: 1085 bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1086 CG14_MCTL, CG14_MCTL_ENABLEVID | 1087 CG14_MCTL_PIXMODE_32 | CG14_MCTL_POWERCTL); 1088 sc->sc_depth = 32; 1089 for (i = 0; i < CG14_CLUT_SIZE; i++) 1090 sc->sc_xlut->xlut_lut[i] = 0; 1091 break; 1092 default: 1093 printf("%s: can't change to depth %d\n", 1094 device_xname(sc->sc_dev), depth); 1095 } 1096 } 1097 1098 static void 1099 cg14_move_cursor(struct cgfourteen_softc *sc, int x, int y) 1100 { 1101 uint32_t pos; 1102 1103 sc->sc_cursor.cc_pos.x = x; 1104 sc->sc_cursor.cc_pos.y = y; 1105 pos = ((sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x ) << 16) | 1106 ((sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y ) & 0xffff); 1107 bus_space_write_4(sc->sc_bustag, sc->sc_regh, CG14_CURSOR_X, pos); 1108 } 1109 1110 static int 1111 cg14_do_cursor(struct cgfourteen_softc *sc, struct wsdisplay_cursor *cur) 1112 { 1113 if (cur->which & WSDISPLAY_CURSOR_DOCUR) { 1114 1115 bus_space_write_1(sc->sc_bustag, sc->sc_regh, 1116 CG14_CURSOR_CONTROL, cur->enable ? CG14_CRSR_ENABLE : 0); 1117 } 1118 if (cur->which & WSDISPLAY_CURSOR_DOHOT) { 1119 1120 sc->sc_cursor.cc_hot.x = cur->hot.x; 1121 sc->sc_cursor.cc_hot.y = cur->hot.y; 1122 cur->which |= WSDISPLAY_CURSOR_DOPOS; 1123 } 1124 if (cur->which & WSDISPLAY_CURSOR_DOPOS) { 1125 1126 cg14_move_cursor(sc, cur->pos.x, cur->pos.y); 1127 } 1128 if (cur->which & WSDISPLAY_CURSOR_DOCMAP) { 1129 int i; 1130 uint32_t val; 1131 1132 for (i = 0; i < min(cur->cmap.count, 3); i++) { 1133 val = (cur->cmap.red[i] ) | 1134 (cur->cmap.green[i] << 8) | 1135 (cur->cmap.blue[i] << 16); 1136 bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1137 CG14_CURSOR_COLOR1 + ((i + cur->cmap.index) << 2), 1138 val); 1139 } 1140 } 1141 if (cur->which & WSDISPLAY_CURSOR_DOSHAPE) { 1142 uint32_t buffer[32], latch, tmp; 1143 int i; 1144 1145 copyin(cur->mask, buffer, 128); 1146 for (i = 0; i < 32; i++) { 1147 latch = 0; 1148 tmp = buffer[i] & 0x80808080; 1149 latch |= tmp >> 7; 1150 tmp = buffer[i] & 0x40404040; 1151 latch |= tmp >> 5; 1152 tmp = buffer[i] & 0x20202020; 1153 latch |= tmp >> 3; 1154 tmp = buffer[i] & 0x10101010; 1155 latch |= tmp >> 1; 1156 tmp = buffer[i] & 0x08080808; 1157 latch |= tmp << 1; 1158 tmp = buffer[i] & 0x04040404; 1159 latch |= tmp << 3; 1160 tmp = buffer[i] & 0x02020202; 1161 latch |= tmp << 5; 1162 tmp = buffer[i] & 0x01010101; 1163 latch |= tmp << 7; 1164 bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1165 CG14_CURSOR_PLANE0 + (i << 2), latch); 1166 } 1167 copyin(cur->image, buffer, 128); 1168 for (i = 0; i < 32; i++) { 1169 latch = 0; 1170 tmp = buffer[i] & 0x80808080; 1171 latch |= tmp >> 7; 1172 tmp = buffer[i] & 0x40404040; 1173 latch |= tmp >> 5; 1174 tmp = buffer[i] & 0x20202020; 1175 latch |= tmp >> 3; 1176 tmp = buffer[i] & 0x10101010; 1177 latch |= tmp >> 1; 1178 tmp = buffer[i] & 0x08080808; 1179 latch |= tmp << 1; 1180 tmp = buffer[i] & 0x04040404; 1181 latch |= tmp << 3; 1182 tmp = buffer[i] & 0x02020202; 1183 latch |= tmp << 5; 1184 tmp = buffer[i] & 0x01010101; 1185 latch |= tmp << 7; 1186 bus_space_write_4(sc->sc_bustag, sc->sc_regh, 1187 CG14_CURSOR_PLANE1 + (i << 2), latch); 1188 } 1189 } 1190 return 0; 1191 } 1192 1193 #if NSX > 0 1194 1195 static void 1196 cg14_wait_idle(struct cgfourteen_softc *sc) 1197 { 1198 } 1199 1200 static void 1201 cg14_rectfill(struct cgfourteen_softc *sc, int x, int y, int wi, int he, 1202 uint32_t colour) 1203 { 1204 uint32_t addr, pptr; 1205 int line, cnt, pre, words; 1206 int stride = sc->sc_fb.fb_type.fb_width; 1207 1208 addr = sc->sc_fb_paddr + x + stride * y; 1209 sx_write(sc->sc_sx, SX_QUEUED(8), colour); 1210 sx_write(sc->sc_sx, SX_QUEUED(9), colour); 1211 /* 1212 * Calculate the number of pixels we need to do one by one 1213 * until we're 32bit aligned, then do the rest in 32bit 1214 * mode. Assumes that stride is always a multiple of 4. 1215 */ 1216 /* TODO: use 32bit writes with byte mask instead */ 1217 pre = addr & 3; 1218 if (pre != 0) pre = 4 - pre; 1219 for (line = 0; line < he; line++) { 1220 pptr = addr; 1221 cnt = wi; 1222 if (pre) { 1223 sta(pptr, ASI_SX, SX_STBS(8, pre - 1, pptr & 7)); 1224 pptr += pre; 1225 cnt -= pre; 1226 } 1227 /* now do the aligned pixels in 32bit chunks */ 1228 while(cnt > 31) { 1229 words = min(32, cnt >> 2); 1230 sta(pptr, ASI_SX, SX_STS(8, words - 1, pptr & 7)); 1231 pptr += words << 2; 1232 cnt -= words << 2; 1233 } 1234 /* do any remaining pixels byte-wise again */ 1235 if (cnt > 0) 1236 sta(pptr, ASI_SX, SX_STBS(8, cnt - 1, pptr & 7)); 1237 addr += stride; 1238 } 1239 } 1240 1241 static void 1242 cg14_invert(struct cgfourteen_softc *sc, int x, int y, int wi, int he) 1243 { 1244 uint32_t addr, pptr; 1245 int line, cnt, pre, words; 1246 int stride = sc->sc_fb.fb_type.fb_width; 1247 1248 addr = sc->sc_fb_paddr + x + stride * y; 1249 sx_write(sc->sc_sx, SX_ROP_CONTROL, 0x33); /* ~src a */ 1250 /* 1251 * Calculate the number of pixels we need to do one by one 1252 * until we're 32bit aligned, then do the rest in 32bit 1253 * mode. Assumes that stride is always a multiple of 4. 1254 */ 1255 /* TODO: use 32bit writes with byte mask instead */ 1256 pre = addr & 3; 1257 if (pre != 0) pre = 4 - pre; 1258 for (line = 0; line < he; line++) { 1259 pptr = addr; 1260 cnt = wi; 1261 if (pre) { 1262 sta(pptr, ASI_SX, SX_LDB(8, pre - 1, pptr & 7)); 1263 sx_write(sc->sc_sx, SX_INSTRUCTIONS, 1264 SX_ROP(8, 8, 32, pre - 1)); 1265 sta(pptr, ASI_SX, SX_STB(32, pre - 1, pptr & 7)); 1266 pptr += pre; 1267 cnt -= pre; 1268 } 1269 /* now do the aligned pixels in 32bit chunks */ 1270 while(cnt > 15) { 1271 words = min(16, cnt >> 2); 1272 sta(pptr, ASI_SX, SX_LD(8, words - 1, pptr & 7)); 1273 sx_write(sc->sc_sx, SX_INSTRUCTIONS, 1274 SX_ROP(8, 8, 32, words - 1)); 1275 sta(pptr, ASI_SX, SX_ST(32, words - 1, pptr & 7)); 1276 pptr += words << 2; 1277 cnt -= words << 2; 1278 } 1279 /* do any remaining pixels byte-wise again */ 1280 if (cnt > 0) 1281 sta(pptr, ASI_SX, SX_LDB(8, cnt - 1, pptr & 7)); 1282 sx_write(sc->sc_sx, SX_INSTRUCTIONS, 1283 SX_ROP(8, 8, 32, cnt - 1)); 1284 sta(pptr, ASI_SX, SX_STB(32, cnt - 1, pptr & 7)); 1285 addr += stride; 1286 } 1287 } 1288 1289 static inline void 1290 cg14_slurp(int reg, uint32_t addr, int cnt) 1291 { 1292 int num; 1293 while (cnt > 0) { 1294 num = min(32, cnt); 1295 sta(addr, ASI_SX, SX_LD(reg, num - 1, addr & 7)); 1296 cnt -= num; 1297 reg += num; 1298 addr += (num << 2); 1299 } 1300 } 1301 1302 static inline void 1303 cg14_spit(int reg, uint32_t addr, int cnt) 1304 { 1305 int num; 1306 while (cnt > 0) { 1307 num = min(32, cnt); 1308 sta(addr, ASI_SX, SX_ST(reg, num - 1, addr & 7)); 1309 cnt -= num; 1310 reg += num; 1311 addr += (num << 2); 1312 } 1313 } 1314 1315 static void 1316 cg14_bitblt(void *cookie, int xs, int ys, int xd, int yd, 1317 int wi, int he, int rop) 1318 { 1319 struct cgfourteen_softc *sc = cookie; 1320 uint32_t saddr, daddr, sptr, dptr; 1321 int line, cnt, stride = sc->sc_fb.fb_type.fb_width; 1322 int num, words, skip; 1323 1324 if (ys < yd) { 1325 /* need to go bottom-up */ 1326 saddr = sc->sc_fb_paddr + xs + stride * (ys + he - 1); 1327 daddr = sc->sc_fb_paddr + xd + stride * (yd + he - 1); 1328 skip = -stride; 1329 } else { 1330 saddr = sc->sc_fb_paddr + xs + stride * ys; 1331 daddr = sc->sc_fb_paddr + xd + stride * yd; 1332 skip = stride; 1333 } 1334 1335 if ((saddr & 3) == (daddr & 3)) { 1336 int pre = saddr & 3; /* pixels to copy byte-wise */ 1337 if (pre != 0) pre = 4 - pre; 1338 for (line = 0; line < he; line++) { 1339 sptr = saddr; 1340 dptr = daddr; 1341 cnt = wi; 1342 if (pre > 0) { 1343 sta(sptr, ASI_SX, 1344 SX_LDB(32, pre - 1, sptr & 7)); 1345 sta(dptr, ASI_SX, 1346 SX_STB(32, pre - 1, dptr & 7)); 1347 cnt -= pre; 1348 sptr += pre; 1349 dptr += pre; 1350 } 1351 words = cnt >> 2; 1352 while(cnt > 3) { 1353 num = min(120, words); 1354 cg14_slurp(8, sptr, num); 1355 cg14_spit(8, dptr, num); 1356 sptr += num << 2; 1357 dptr += num << 2; 1358 cnt -= num << 2; 1359 } 1360 if (cnt > 0) { 1361 sta(sptr, ASI_SX, 1362 SX_LDB(32, cnt - 1, sptr & 7)); 1363 sta(dptr, ASI_SX, 1364 SX_STB(32, cnt - 1, dptr & 7)); 1365 } 1366 saddr += skip; 1367 daddr += skip; 1368 } 1369 } else { 1370 /* unaligned, have to use byte mode */ 1371 /* funnel shifter & byte mask trickery? */ 1372 for (line = 0; line < he; line++) { 1373 sptr = saddr; 1374 dptr = daddr; 1375 cnt = wi; 1376 while(cnt > 31) { 1377 sta(sptr, ASI_SX, SX_LDB(32, 31, sptr & 7)); 1378 sta(dptr, ASI_SX, SX_STB(32, 31, dptr & 7)); 1379 sptr += 32; 1380 dptr += 32; 1381 cnt -= 32; 1382 } 1383 if (cnt > 0) { 1384 sta(sptr, ASI_SX, 1385 SX_LDB(32, cnt - 1, sptr & 7)); 1386 sta(dptr, ASI_SX, 1387 SX_STB(32, cnt - 1, dptr & 7)); 1388 } 1389 saddr += skip; 1390 daddr += skip; 1391 } 1392 } 1393 } 1394 1395 1396 static void 1397 cg14_putchar(void *cookie, int row, int col, u_int c, long attr) 1398 { 1399 struct rasops_info *ri = cookie; 1400 struct wsdisplay_font *font = PICK_FONT(ri, c); 1401 struct vcons_screen *scr = ri->ri_hw; 1402 struct cgfourteen_softc *sc = scr->scr_cookie; 1403 void *data; 1404 uint32_t fg, bg; 1405 int i, x, y, wi, he; 1406 uint32_t addr; 1407 int stride = sc->sc_fb.fb_type.fb_width; 1408 1409 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1410 return; 1411 1412 if (!CHAR_IN_FONT(c, font)) 1413 return; 1414 1415 wi = font->fontwidth; 1416 he = font->fontheight; 1417 1418 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1419 fg = ri->ri_devcmap[(attr >> 24) & 0xf]; 1420 sx_write(sc->sc_sx, SX_QUEUED(8), bg); 1421 sx_write(sc->sc_sx, SX_QUEUED(9), fg); 1422 1423 x = ri->ri_xorigin + col * wi; 1424 y = ri->ri_yorigin + row * he; 1425 1426 if (c == 0x20) { 1427 cg14_rectfill(sc, x, y, wi, he, bg); 1428 return; 1429 } 1430 1431 data = WSFONT_GLYPH(c, font); 1432 addr = sc->sc_fb_paddr + x + stride * y; 1433 1434 switch (font->stride) { 1435 case 1: { 1436 uint8_t *data8 = data; 1437 uint32_t reg; 1438 for (i = 0; i < he; i++) { 1439 reg = *data8; 1440 sx_write(sc->sc_sx, SX_QUEUED(R_MASK), 1441 reg << 24); 1442 sta(addr, ASI_SX, SX_STBS(8, wi - 1, addr & 7)); 1443 data8++; 1444 addr += stride; 1445 } 1446 break; 1447 } 1448 case 2: { 1449 uint16_t *data16 = data; 1450 uint32_t reg; 1451 for (i = 0; i < he; i++) { 1452 reg = *data16; 1453 sx_write(sc->sc_sx, SX_QUEUED(R_MASK), 1454 reg << 16); 1455 sta(addr, ASI_SX, SX_STBS(8, wi - 1, addr & 7)); 1456 data16++; 1457 addr += stride; 1458 } 1459 break; 1460 } 1461 } 1462 } 1463 1464 static void 1465 cg14_cursor(void *cookie, int on, int row, int col) 1466 { 1467 struct rasops_info *ri = cookie; 1468 struct vcons_screen *scr = ri->ri_hw; 1469 struct cgfourteen_softc *sc = scr->scr_cookie; 1470 int x, y, wi, he; 1471 1472 wi = ri->ri_font->fontwidth; 1473 he = ri->ri_font->fontheight; 1474 1475 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1476 x = ri->ri_ccol * wi + ri->ri_xorigin; 1477 y = ri->ri_crow * he + ri->ri_yorigin; 1478 if (ri->ri_flg & RI_CURSOR) { 1479 cg14_invert(sc, x, y, wi, he); 1480 ri->ri_flg &= ~RI_CURSOR; 1481 } 1482 ri->ri_crow = row; 1483 ri->ri_ccol = col; 1484 if (on) { 1485 x = ri->ri_ccol * wi + ri->ri_xorigin; 1486 y = ri->ri_crow * he + ri->ri_yorigin; 1487 cg14_invert(sc, x, y, wi, he); 1488 ri->ri_flg |= RI_CURSOR; 1489 } 1490 } else { 1491 scr->scr_ri.ri_crow = row; 1492 scr->scr_ri.ri_ccol = col; 1493 scr->scr_ri.ri_flg &= ~RI_CURSOR; 1494 } 1495 1496 } 1497 1498 #if 0 1499 static void 1500 r128fb_putchar_aa(void *cookie, int row, int col, u_int c, long attr) 1501 { 1502 struct rasops_info *ri = cookie; 1503 struct wsdisplay_font *font = PICK_FONT(ri, c); 1504 struct vcons_screen *scr = ri->ri_hw; 1505 struct r128fb_softc *sc = scr->scr_cookie; 1506 uint32_t bg, latch = 0, bg8, fg8, pixel; 1507 int i, x, y, wi, he, r, g, b, aval; 1508 int r1, g1, b1, r0, g0, b0, fgo, bgo; 1509 uint8_t *data8; 1510 int rv, cnt = 0; 1511 1512 if (sc->sc_mode != WSDISPLAYIO_MODE_EMUL) 1513 return; 1514 1515 if (!CHAR_IN_FONT(c, font)) 1516 return; 1517 1518 wi = font->fontwidth; 1519 he = font->fontheight; 1520 1521 bg = ri->ri_devcmap[(attr >> 16) & 0xf]; 1522 x = ri->ri_xorigin + col * wi; 1523 y = ri->ri_yorigin + row * he; 1524 if (c == 0x20) { 1525 r128fb_rectfill(sc, x, y, wi, he, bg); 1526 return; 1527 } 1528 1529 rv = glyphcache_try(&sc->sc_gc, c, x, y, attr); 1530 if (rv == GC_OK) 1531 return; 1532 1533 data8 = WSFONT_GLYPH(c, font); 1534 1535 r128fb_wait(sc, 5); 1536 bus_space_write_4(sc->sc_memt, sc->sc_regh, 1537 R128_DP_GUI_MASTER_CNTL, 1538 R128_GMC_BRUSH_SOLID_COLOR | 1539 R128_GMC_SRC_DATATYPE_COLOR | 1540 R128_ROP3_S | 1541 R128_DP_SRC_SOURCE_HOST_DATA | 1542 sc->sc_master_cntl); 1543 1544 bus_space_write_4(sc->sc_memt, sc->sc_regh, 1545 R128_DP_CNTL, 1546 R128_DST_Y_TOP_TO_BOTTOM | 1547 R128_DST_X_LEFT_TO_RIGHT); 1548 1549 /* needed? */ 1550 bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_SRC_X_Y, 0); 1551 bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_X_Y, 1552 (x << 16) | y); 1553 bus_space_write_4(sc->sc_memt, sc->sc_regh, R128_DST_WIDTH_HEIGHT, 1554 (wi << 16) | he); 1555 1556 /* 1557 * we need the RGB colours here, so get offsets into rasops_cmap 1558 */ 1559 fgo = ((attr >> 24) & 0xf) * 3; 1560 bgo = ((attr >> 16) & 0xf) * 3; 1561 1562 r0 = rasops_cmap[bgo]; 1563 r1 = rasops_cmap[fgo]; 1564 g0 = rasops_cmap[bgo + 1]; 1565 g1 = rasops_cmap[fgo + 1]; 1566 b0 = rasops_cmap[bgo + 2]; 1567 b1 = rasops_cmap[fgo + 2]; 1568 #define R3G3B2(r, g, b) ((r & 0xe0) | ((g >> 3) & 0x1c) | (b >> 6)) 1569 bg8 = R3G3B2(r0, g0, b0); 1570 fg8 = R3G3B2(r1, g1, b1); 1571 1572 r128fb_wait(sc, 16); 1573 1574 for (i = 0; i < ri->ri_fontscale; i++) { 1575 aval = *data8; 1576 if (aval == 0) { 1577 pixel = bg8; 1578 } else if (aval == 255) { 1579 pixel = fg8; 1580 } else { 1581 r = aval * r1 + (255 - aval) * r0; 1582 g = aval * g1 + (255 - aval) * g0; 1583 b = aval * b1 + (255 - aval) * b0; 1584 pixel = ((r & 0xe000) >> 8) | 1585 ((g & 0xe000) >> 11) | 1586 ((b & 0xc000) >> 14); 1587 } 1588 latch = (latch << 8) | pixel; 1589 /* write in 32bit chunks */ 1590 if ((i & 3) == 3) { 1591 bus_space_write_stream_4(sc->sc_memt, sc->sc_regh, 1592 R128_HOST_DATA0, latch); 1593 /* 1594 * not strictly necessary, old data should be shifted 1595 * out 1596 */ 1597 latch = 0; 1598 cnt++; 1599 if (cnt > 15) { 1600 r128fb_wait(sc, 16); 1601 cnt = 0; 1602 } 1603 } 1604 data8++; 1605 } 1606 /* if we have pixels left in latch write them out */ 1607 if ((i & 3) != 0) { 1608 latch = latch << ((4 - (i & 3)) << 3); 1609 bus_space_write_stream_4(sc->sc_memt, sc->sc_regh, 1610 R128_HOST_DATA0, latch); 1611 } 1612 if (rv == GC_ADD) { 1613 glyphcache_add(&sc->sc_gc, c, x, y); 1614 } 1615 } 1616 #endif 1617 1618 static void 1619 cg14_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1620 { 1621 struct rasops_info *ri = cookie; 1622 struct vcons_screen *scr = ri->ri_hw; 1623 struct cgfourteen_softc *sc = scr->scr_cookie; 1624 int32_t xs, xd, y, width, height; 1625 1626 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1627 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1628 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1629 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1630 width = ri->ri_font->fontwidth * ncols; 1631 height = ri->ri_font->fontheight; 1632 cg14_bitblt(sc, xs, y, xd, y, width, height, 0x0c); 1633 } 1634 } 1635 1636 static void 1637 cg14_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1638 { 1639 struct rasops_info *ri = cookie; 1640 struct vcons_screen *scr = ri->ri_hw; 1641 struct cgfourteen_softc *sc = scr->scr_cookie; 1642 int32_t x, y, width, height, fg, bg, ul; 1643 1644 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1645 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1646 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1647 width = ri->ri_font->fontwidth * ncols; 1648 height = ri->ri_font->fontheight; 1649 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1650 1651 cg14_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1652 } 1653 } 1654 1655 static void 1656 cg14_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1657 { 1658 struct rasops_info *ri = cookie; 1659 struct vcons_screen *scr = ri->ri_hw; 1660 struct cgfourteen_softc *sc = scr->scr_cookie; 1661 int32_t x, ys, yd, width, height; 1662 1663 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1664 x = ri->ri_xorigin; 1665 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1666 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1667 width = ri->ri_emuwidth; 1668 height = ri->ri_font->fontheight * nrows; 1669 cg14_bitblt(sc, x, ys, x, yd, width, height, 0x0c); 1670 } 1671 } 1672 1673 static void 1674 cg14_eraserows(void *cookie, int row, int nrows, long fillattr) 1675 { 1676 struct rasops_info *ri = cookie; 1677 struct vcons_screen *scr = ri->ri_hw; 1678 struct cgfourteen_softc *sc = scr->scr_cookie; 1679 int32_t x, y, width, height, fg, bg, ul; 1680 1681 if (sc->sc_mode == WSDISPLAYIO_MODE_EMUL) { 1682 x = ri->ri_xorigin; 1683 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1684 width = ri->ri_emuwidth; 1685 height = ri->ri_font->fontheight * nrows; 1686 rasops_unpack_attr(fillattr, &fg, &bg, &ul); 1687 1688 cg14_rectfill(sc, x, y, width, height, ri->ri_devcmap[bg]); 1689 } 1690 } 1691 1692 #endif /* NSX > 0 */ 1693 1694 #endif 1695