1 /* $OpenBSD: zx.c,v 1.21 2020/05/25 09:55:49 jsg Exp $ */ 2 /* $NetBSD: zx.c,v 1.5 2002/10/02 16:52:46 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 2003, Miodrag Vallat. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 26 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 * 29 * Derived from NetBSD syssrc/sys/dev/sbus/zx.c under the following licence 30 * terms: 31 * 32 * Copyright (c) 2002 The NetBSD Foundation, Inc. 33 * All rights reserved. 34 * 35 * This code is derived from software contributed to The NetBSD Foundation 36 * by Andrew Doran. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 1. Redistributions of source code must retain the above copyright 42 * notice, this list of conditions and the following disclaimer. 43 * 2. Redistributions in binary form must reproduce the above copyright 44 * notice, this list of conditions and the following disclaimer in the 45 * documentation and/or other materials provided with the distribution. 46 * 47 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 48 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 49 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 50 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 51 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 57 * POSSIBILITY OF SUCH DAMAGE. 58 */ 59 60 /* 61 * Driver for the Sun ZX display adapter. This would be called 'leo', but 62 * NetBSD/amiga already has a driver by that name. The XFree86 and Linux 63 * drivers were used as "living documentation" when writing this; thanks 64 * to the authors. 65 */ 66 67 #include <sys/param.h> 68 #include <sys/systm.h> 69 #include <sys/device.h> 70 #include <sys/ioctl.h> 71 #include <sys/malloc.h> 72 #include <sys/mman.h> 73 #include <sys/tty.h> 74 #include <sys/conf.h> 75 76 #include <uvm/uvm_extern.h> 77 78 #include <machine/autoconf.h> 79 #include <machine/bus.h> 80 #include <machine/cpu.h> 81 #include <machine/conf.h> 82 83 #include <dev/wscons/wsconsio.h> 84 #include <dev/wscons/wsdisplayvar.h> 85 #include <dev/rasops/rasops.h> 86 #include <machine/fbvar.h> 87 88 #include <dev/sbus/zxreg.h> 89 #include <dev/sbus/sbusvar.h> 90 91 #define ZX_WID_SHARED_8 0 92 #define ZX_WID_SHARED_24 1 93 #define ZX_WID_DBL_8 2 94 #define ZX_WID_DBL_24 3 95 96 /* 97 * Per-instance data. 98 */ 99 100 struct zx_cmap { 101 u_int8_t cm_red[256]; 102 u_int8_t cm_green[256]; 103 u_int8_t cm_blue[256]; 104 }; 105 106 struct zx_softc { 107 struct sunfb sc_sunfb; 108 109 bus_space_tag_t sc_bustag; 110 bus_addr_t sc_paddr; 111 112 struct zx_cmap sc_cmap; /* shadow color map for overlay plane */ 113 114 volatile struct zx_command *sc_zc; 115 volatile struct zx_cross *sc_zx; 116 volatile struct zx_draw *sc_zd_ss0; 117 volatile struct zx_draw_ss1 *sc_zd_ss1; 118 volatile struct zx_cursor *sc_zcu; 119 120 int sc_nscreens; 121 }; 122 123 int zx_ioctl(void *, u_long, caddr_t, int, struct proc *); 124 paddr_t zx_mmap(void *, off_t, int); 125 void zx_setcolor(void *, u_int, u_int8_t, u_int8_t, u_int8_t); 126 void zx_reset(struct zx_softc *, u_int); 127 void zx_burner(void *, u_int, u_int); 128 129 struct wsdisplay_accessops zx_accessops = { 130 .ioctl = zx_ioctl, 131 .mmap = zx_mmap, 132 .burn_screen = zx_burner 133 }; 134 135 /* Force 32-bit writes. */ 136 #define SETREG(r, v) (*((volatile u_int32_t *)&r) = (v)) 137 138 #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \ 139 ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID) 140 141 #define ZX_BWIDTH 13 142 #define ZX_WWIDTH 11 /* word width */ 143 144 #define ZX_COORDS(x, y) ((x) | ((y) << ZX_WWIDTH)) 145 146 void zx_attach(struct device *, struct device *, void *); 147 int zx_match(struct device *, void *, void *); 148 149 int zx_putcmap(struct zx_softc *); 150 void zx_copyrect(struct rasops_info *, int, int, int, int, int, int); 151 int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int); 152 int zx_cross_wait(struct zx_softc *); 153 void zx_fillrect(struct rasops_info *, int, int, int, int, uint32_t, int); 154 int zx_intr(void *); 155 void zx_prom(void *); 156 157 int zx_putchar(void *, int, int, u_int, uint32_t); 158 int zx_copycols(void *, int, int, int, int); 159 int zx_erasecols(void *, int, int, int, uint32_t); 160 int zx_copyrows(void *, int, int, int); 161 int zx_eraserows(void *, int, int, uint32_t); 162 int zx_do_cursor(struct rasops_info *); 163 164 struct cfattach zx_ca = { 165 sizeof(struct zx_softc), zx_match, zx_attach 166 }; 167 168 struct cfdriver zx_cd = { 169 NULL, "zx", DV_DULL 170 }; 171 172 int 173 zx_match(struct device *parent, void *vcf, void *aux) 174 { 175 struct sbus_attach_args *sa = aux; 176 177 if (strcmp(sa->sa_name, "SUNW,leo") == 0) 178 return (1); 179 180 return (0); 181 } 182 183 void 184 zx_attach(struct device *parent, struct device *self, void *args) 185 { 186 struct zx_softc *sc = (struct zx_softc *)self; 187 struct sbus_attach_args *sa = args; 188 struct rasops_info *ri; 189 bus_space_tag_t bt; 190 bus_space_handle_t bh; 191 int node, isconsole = 0; 192 const char *nam; 193 194 bt = sa->sa_bustag; 195 ri = &sc->sc_sunfb.sf_ro; 196 node = sa->sa_node; 197 198 /* 199 * Map the various parts of the card. 200 */ 201 sc->sc_bustag = bt; 202 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); 203 204 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, 205 sizeof(struct zx_command), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 206 printf(": couldn't map command registers\n"); 207 return; 208 } 209 sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh); 210 211 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, 212 sizeof(struct zx_draw), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 213 printf(": couldn't map ss0 drawing registers\n"); 214 return; 215 } 216 sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh); 217 218 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, 219 sizeof(struct zx_draw_ss1), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 220 printf(": couldn't map ss1 drawing registers\n"); 221 return; 222 } 223 sc->sc_zd_ss1 = (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh); 224 225 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, 226 sizeof(struct zx_cross), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 227 printf(": couldn't map cross registers\n"); 228 return; 229 } 230 sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh); 231 232 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, 233 sizeof(struct zx_cursor), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 234 printf(": couldn't map cursor registers\n"); 235 return; 236 } 237 sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh); 238 239 nam = getpropstring(node, "model"); 240 if (*nam == '\0') 241 nam = sa->sa_name; 242 printf(": %s", nam); 243 244 isconsole = node == fbnode; 245 246 /* 247 * The console is using the 8-bit overlay plane, while the prom 248 * will correctly report 32 bit depth. 249 * The following is an equivalent for 250 * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); 251 * forcing the depth value not to be overwritten. 252 * Furthermore, the linebytes value is in fact 8192 bytes. 253 */ 254 sc->sc_sunfb.sf_depth = 8; 255 sc->sc_sunfb.sf_width = getpropint(node, "width", 1152); 256 sc->sc_sunfb.sf_height = getpropint(node, "height", 900); 257 sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH; 258 sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH; 259 260 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 261 262 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, 263 round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 264 0, &bh) != 0) { 265 printf("%s: couldn't map video memory\n", self->dv_xname); 266 return; 267 } 268 ri->ri_bits = bus_space_vaddr(bt, bh); 269 ri->ri_hw = sc; 270 271 fbwscons_init(&sc->sc_sunfb, 0, isconsole); 272 273 /* 274 * Watch out! rasops_init() invoked via fbwscons_init() did not 275 * compute ri_bits correctly when centering the display, because 276 * it has been tricked with the low depth value. 277 * Recompute now. 278 */ 279 ri->ri_emustride = ri->ri_emuwidth * 4; 280 ri->ri_delta = ri->ri_stride - ri->ri_emustride; 281 ri->ri_pelbytes = 4; 282 ri->ri_xscale = ri->ri_font->fontwidth * 4; 283 ri->ri_bits = ri->ri_origbits; 284 ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3; 285 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 286 ri->ri_stride; 287 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) 288 / ri->ri_stride; 289 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) 290 % ri->ri_stride) / 4); 291 292 ri->ri_ops.copyrows = zx_copyrows; 293 ri->ri_ops.copycols = zx_copycols; 294 ri->ri_ops.eraserows = zx_eraserows; 295 ri->ri_ops.erasecols = zx_erasecols; 296 ri->ri_ops.putchar = zx_putchar; 297 ri->ri_do_cursor = zx_do_cursor; 298 299 if (isconsole) { 300 /* zx_reset() below will clear screen, so restart at 1st row */ 301 fbwscons_console_init(&sc->sc_sunfb, 0); 302 } 303 304 /* reset cursor & frame buffer controls */ 305 zx_reset(sc, WSDISPLAYIO_MODE_EMUL); 306 307 /* enable video */ 308 zx_burner(sc, 1, 0); 309 310 fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole); 311 } 312 313 int 314 zx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p) 315 { 316 struct zx_softc *sc = dev; 317 struct wsdisplay_fbinfo *wdf; 318 319 /* 320 * Note that, although the emulation (text) mode is running in 321 * a 8-bit plane, we advertize the frame buffer as the full-blown 322 * 32-bit beast it is. 323 */ 324 switch (cmd) { 325 case WSDISPLAYIO_GTYPE: 326 *(u_int *)data = WSDISPLAY_TYPE_SUNLEO; 327 break; 328 case WSDISPLAYIO_GINFO: 329 wdf = (struct wsdisplay_fbinfo *)data; 330 wdf->height = sc->sc_sunfb.sf_height; 331 wdf->width = sc->sc_sunfb.sf_width; 332 wdf->depth = 32; 333 wdf->cmsize = 0; 334 break; 335 case WSDISPLAYIO_GETSUPPORTEDDEPTH: 336 *(u_int *)data = WSDISPLAYIO_DEPTH_24_32; 337 break; 338 case WSDISPLAYIO_LINEBYTES: 339 *(u_int *)data = sc->sc_sunfb.sf_linebytes; 340 break; 341 342 case WSDISPLAYIO_GETCMAP: 343 case WSDISPLAYIO_PUTCMAP: 344 break; 345 346 case WSDISPLAYIO_SMODE: 347 zx_reset(sc, *(u_int *)data); 348 break; 349 350 case WSDISPLAYIO_SVIDEO: 351 case WSDISPLAYIO_GVIDEO: 352 break; 353 354 default: 355 return (-1); 356 } 357 358 return (0); 359 } 360 361 /* 362 * Return the address that would map the given device at the given 363 * offset, allowing for the given protection, or return -1 for error. 364 */ 365 paddr_t 366 zx_mmap(void *v, off_t offset, int prot) 367 { 368 struct zx_softc *sc = v; 369 370 if (offset & PGOFSET) 371 return (-1); 372 373 /* Allow mapping as a dumb framebuffer from offset 0 */ 374 if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) { 375 return (bus_space_mmap(sc->sc_bustag, sc->sc_paddr, 376 ZX_OFF_SS0 + offset, prot, BUS_SPACE_MAP_LINEAR)); 377 } 378 379 return (-1); 380 } 381 382 void 383 zx_setcolor(void *v, u_int index, u_int8_t r, u_int8_t g, u_int8_t b) 384 { 385 struct zx_softc *sc = v; 386 387 sc->sc_cmap.cm_red[index] = r; 388 sc->sc_cmap.cm_green[index] = g; 389 sc->sc_cmap.cm_blue[index] = b; 390 } 391 392 void 393 zx_reset(struct zx_softc *sc, u_int mode) 394 { 395 volatile struct zx_draw *zd; 396 volatile struct zx_command *zc; 397 u_int32_t i; 398 const u_char *color; 399 u_int8_t *r, *g, *b; 400 401 zd = sc->sc_zd_ss0; 402 zc = sc->sc_zc; 403 404 if (mode == WSDISPLAYIO_MODE_EMUL) { 405 /* Back from X11 to emulation mode, or first reset */ 406 zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0); 407 zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30); 408 zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20); 409 zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30); 410 411 i = sc->sc_zd_ss1->zd_misc; 412 i |= ZX_SS1_MISC_ENABLE; 413 SETREG(sc->sc_zd_ss1->zd_misc, i); 414 415 /* 416 * XXX 417 * If zc_fill is not set to that value, there will be black 418 * bars left in the margins. But then with this value, the 419 * screen gets cleared. Go figure. 420 */ 421 SETREG(zd->zd_wid, 0xffffffff); 422 SETREG(zd->zd_wmask, 0xffff); 423 SETREG(zd->zd_vclipmin, 0); 424 SETREG(zd->zd_vclipmax, (sc->sc_sunfb.sf_width - 1) | 425 ((sc->sc_sunfb.sf_height - 1) << 16)); 426 SETREG(zd->zd_fg, 0); 427 SETREG(zd->zd_planemask, 0xff000000); 428 SETREG(zd->zd_rop, ZX_STD_ROP); 429 SETREG(zd->zd_widclip, 0); 430 431 SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1, 432 sc->sc_sunfb.sf_height - 1)); 433 SETREG(zc->zc_addrspace, ZX_ADDRSPC_FONT_OBGR); 434 SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS); 435 SETREG(zc->zc_fontt, 0); 436 437 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 438 ; 439 440 /* 441 * Initialize the 8-bit colormap 442 */ 443 r = sc->sc_cmap.cm_red; 444 g = sc->sc_cmap.cm_green; 445 b = sc->sc_cmap.cm_blue; 446 color = rasops_cmap; 447 for (i = 0; i < 256; i++) { 448 *r++ = *color++; 449 *g++ = *color++; 450 *b++ = *color++; 451 } 452 fbwscons_setcolormap(&sc->sc_sunfb, zx_setcolor); 453 zx_putcmap(sc); 454 } else { 455 /* Starting X11 - switch to 24bit WID */ 456 SETREG(zd->zd_wid, 1); 457 SETREG(zd->zd_widclip, 0); 458 SETREG(zd->zd_wmask, 0xffff); 459 SETREG(zd->zd_planemask, 0x00ffffff); 460 SETREG(zc->zc_extent, ZX_COORDS(sc->sc_sunfb.sf_width - 1, 461 sc->sc_sunfb.sf_height - 1)); 462 SETREG(zc->zc_fill, 0); 463 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 464 ; 465 466 SETREG(zc->zc_addrspace, ZX_ADDRSPC_OBGR); 467 SETREG(zd->zd_rop, ZX_ATTR_RGBE_ENABLE | 468 ZX_ROP_NEW /* | ZX_ATTR_FORCE_WID */); 469 } 470 } 471 472 int 473 zx_cross_wait(struct zx_softc *sc) 474 { 475 volatile struct zx_cross *zx; 476 int i; 477 478 zx = sc->sc_zx; 479 480 for (i = 300000; i != 0; i--) { 481 if ((zx->zx_csr & ZX_CROSS_CSR_PROGRESS) == 0) 482 break; 483 DELAY(1); 484 } 485 486 if (i == 0) 487 printf("%s: zx_cross_wait: timed out\n", 488 sc->sc_sunfb.sf_dev.dv_xname); 489 490 return (i); 491 } 492 493 int 494 zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value) 495 { 496 volatile struct zx_cross *zx; 497 u_int tmp; 498 499 zx = sc->sc_zx; 500 SETREG(zx->zx_type, ZX_CROSS_TYPE_WID); 501 502 if (!zx_cross_wait(sc)) 503 return (1); 504 505 if (type == ZX_WID_DBL_8) 506 tmp = (index & 0x0f) + 0x40; 507 else /* ZX_WID_DBL_24 */ 508 tmp = index & 0x3f; 509 510 SETREG(zx->zx_type, 0x5800 + tmp); 511 SETREG(zx->zx_value, value); 512 SETREG(zx->zx_type, ZX_CROSS_TYPE_WID); 513 SETREG(zx->zx_csr, ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2); 514 515 return (0); 516 } 517 518 int 519 zx_putcmap(struct zx_softc *sc) 520 { 521 volatile struct zx_cross *zx; 522 u_int32_t i; 523 u_int8_t *r, *g, *b; 524 525 zx = sc->sc_zx; 526 527 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0); 528 if (!zx_cross_wait(sc)) 529 return (1); 530 531 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUTDATA); 532 533 r = sc->sc_cmap.cm_red; 534 g = sc->sc_cmap.cm_green; 535 b = sc->sc_cmap.cm_blue; 536 for (i = 0; i < 256; i++) { 537 SETREG(zx->zx_value, *r++ | (*g++ << 8) | (*b++ << 16)); 538 } 539 540 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0); 541 i = zx->zx_csr; 542 i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2; 543 SETREG(zx->zx_csr, i); 544 return (0); 545 } 546 547 void 548 zx_burner(void *v, u_int on, u_int flags) 549 { 550 struct zx_softc *sc = v; 551 volatile struct zx_cross *zx; 552 u_int32_t i; 553 554 zx = sc->sc_zx; 555 556 SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO); 557 i = zx->zx_csr; 558 if (on) { 559 i |= ZX_CROSS_CSR_ENABLE; 560 } else { 561 i &= ~ZX_CROSS_CSR_ENABLE; 562 } 563 SETREG(zx->zx_csr, i); 564 } 565 566 void 567 zx_fillrect(struct rasops_info *ri, int x, int y, int w, int h, uint32_t attr, 568 int rop) 569 { 570 struct zx_softc *sc; 571 volatile struct zx_command *zc; 572 volatile struct zx_draw *zd; 573 int fg, bg; 574 575 sc = ri->ri_hw; 576 zc = sc->sc_zc; 577 zd = sc->sc_zd_ss0; 578 579 ri->ri_ops.unpack_attr(ri, attr, &fg, &bg, NULL); 580 x = x * ri->ri_font->fontwidth + ri->ri_xorigin; 581 y = y * ri->ri_font->fontheight + ri->ri_yorigin; 582 w = ri->ri_font->fontwidth * w - 1; 583 h = ri->ri_font->fontheight * h - 1; 584 585 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 586 ; 587 588 SETREG(zd->zd_rop, rop); 589 SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24); 590 SETREG(zc->zc_extent, ZX_COORDS(w, h)); 591 SETREG(zc->zc_fill, ZX_COORDS(x, y) | ZX_EXTENT_DIR_BACKWARDS); 592 } 593 594 void 595 zx_copyrect(struct rasops_info *ri, int sx, int sy, int dx, int dy, int w, 596 int h) 597 { 598 struct zx_softc *sc; 599 volatile struct zx_command *zc; 600 volatile struct zx_draw *zd; 601 int dir; 602 603 sc = ri->ri_hw; 604 zc = sc->sc_zc; 605 zd = sc->sc_zd_ss0; 606 607 sx = sx * ri->ri_font->fontwidth + ri->ri_xorigin; 608 sy = sy * ri->ri_font->fontheight + ri->ri_yorigin; 609 dx = dx * ri->ri_font->fontwidth + ri->ri_xorigin; 610 dy = dy * ri->ri_font->fontheight + ri->ri_yorigin; 611 w = w * ri->ri_font->fontwidth - 1; 612 h = h * ri->ri_font->fontheight - 1; 613 614 if (sy < dy || sx < dx) { 615 dir = ZX_EXTENT_DIR_BACKWARDS; 616 sx += w; 617 sy += h; 618 dx += w; 619 dy += h; 620 } else 621 dir = ZX_EXTENT_DIR_FORWARDS; 622 623 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 624 ; 625 626 SETREG(zd->zd_rop, ZX_STD_ROP); 627 SETREG(zc->zc_extent, ZX_COORDS(w, h) | dir); 628 SETREG(zc->zc_src, ZX_COORDS(sx, sy)); 629 SETREG(zc->zc_copy, ZX_COORDS(dx, dy)); 630 } 631 632 int 633 zx_do_cursor(struct rasops_info *ri) 634 { 635 636 zx_fillrect(ri, ri->ri_ccol, ri->ri_crow, 1, 1, WSCOL_BLACK << 16, 637 ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE | 638 ZX_ATTR_FORCE_WID); 639 640 return 0; 641 } 642 643 int 644 zx_erasecols(void *cookie, int row, int col, int num, uint32_t attr) 645 { 646 struct rasops_info *ri; 647 648 ri = (struct rasops_info *)cookie; 649 650 zx_fillrect(ri, col, row, num, 1, attr, ZX_STD_ROP); 651 652 return 0; 653 } 654 655 int 656 zx_eraserows(void *cookie, int row, int num, uint32_t attr) 657 { 658 struct rasops_info *ri; 659 struct zx_softc *sc; 660 volatile struct zx_command *zc; 661 volatile struct zx_draw *zd; 662 int fg, bg; 663 664 ri = (struct rasops_info *)cookie; 665 666 if (num == ri->ri_rows && (ri->ri_flg & RI_FULLCLEAR)) { 667 sc = ri->ri_hw; 668 zc = sc->sc_zc; 669 zd = sc->sc_zd_ss0; 670 671 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, NULL); 672 673 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 674 ; 675 676 SETREG(zd->zd_rop, ZX_STD_ROP); 677 SETREG(zd->zd_fg, ri->ri_devcmap[bg] << 24); 678 SETREG(zc->zc_extent, 679 ZX_COORDS(ri->ri_width - 1, ri->ri_height - 1)); 680 SETREG(zc->zc_fill, ZX_COORDS(0, 0) | ZX_EXTENT_DIR_BACKWARDS); 681 } else 682 zx_fillrect(ri, 0, row, ri->ri_cols, num, attr, ZX_STD_ROP); 683 684 return 0; 685 } 686 687 int 688 zx_copyrows(void *cookie, int src, int dst, int num) 689 { 690 struct rasops_info *ri; 691 692 ri = (struct rasops_info *)cookie; 693 694 zx_copyrect(ri, 0, src, 0, dst, ri->ri_cols, num); 695 696 return 0; 697 } 698 699 int 700 zx_copycols(void *cookie, int row, int src, int dst, int num) 701 { 702 struct rasops_info *ri; 703 704 ri = (struct rasops_info *)cookie; 705 706 zx_copyrect(ri, src, row, dst, row, num, 1); 707 708 return 0; 709 } 710 711 int 712 zx_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr) 713 { 714 struct rasops_info *ri; 715 struct zx_softc *sc; 716 struct wsdisplay_font *font; 717 volatile struct zx_command *zc; 718 volatile struct zx_draw *zd; 719 volatile u_int32_t *dp; 720 u_int8_t *fb; 721 int fs, i, fg, bg, ul; 722 723 ri = (struct rasops_info *)cookie; 724 font = ri->ri_font; 725 ri->ri_ops.unpack_attr(cookie, attr, &fg, &bg, &ul); 726 fg = ri->ri_devcmap[fg]; 727 bg = ri->ri_devcmap[bg]; 728 729 dp = (volatile u_int32_t *)ri->ri_bits + 730 ZX_COORDS(col * font->fontwidth, row * font->fontheight); 731 732 sc = ri->ri_hw; 733 zc = sc->sc_zc; 734 zd = sc->sc_zd_ss0; 735 736 if (uc == ' ') { 737 zx_fillrect(ri, col, row, 1, 1, attr, ZX_STD_ROP); 738 if (ul == 0) 739 return 0; 740 741 dp += font->fontheight << ZX_WWIDTH; 742 743 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 744 ; 745 746 SETREG(zd->zd_rop, ZX_STD_ROP); 747 SETREG(zd->zd_fg, fg << 24); 748 SETREG(zd->zd_bg, bg << 24); 749 SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth)); 750 } else { 751 fb = (u_int8_t *)font->data + (uc - font->firstchar) * 752 ri->ri_fontscale; 753 fs = font->stride; 754 755 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 756 ; 757 758 SETREG(zd->zd_rop, ZX_STD_ROP); 759 SETREG(zd->zd_fg, fg << 24); 760 SETREG(zd->zd_bg, bg << 24); 761 SETREG(zc->zc_fontmsk, 0xffffffff << (32 - font->fontwidth)); 762 763 if (font->fontwidth <= 8) { 764 for (i = font->fontheight; i != 0; 765 i--, dp += 1 << ZX_WWIDTH) { 766 *dp = *fb << 24; 767 fb += fs; 768 } 769 } else { 770 for (i = font->fontheight; i != 0; 771 i--, dp += 1 << ZX_WWIDTH) { 772 *dp = *((u_int16_t *)fb) << 16; 773 fb += fs; 774 } 775 } 776 } 777 778 /* underline */ 779 if (ul) { 780 dp -= 2 << ZX_WWIDTH; 781 *dp = 0xffffffff; 782 } 783 784 return 0; 785 } 786