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