1 /* $OpenBSD: zx.c,v 1.25 2024/05/13 01:15:53 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 155 int zx_putchar(void *, int, int, u_int, uint32_t); 156 int zx_copycols(void *, int, int, int, int); 157 int zx_erasecols(void *, int, int, int, uint32_t); 158 int zx_copyrows(void *, int, int, int); 159 int zx_eraserows(void *, int, int, uint32_t); 160 int zx_do_cursor(struct rasops_info *); 161 162 const struct cfattach zx_ca = { 163 sizeof(struct zx_softc), zx_match, zx_attach 164 }; 165 166 struct cfdriver zx_cd = { 167 NULL, "zx", DV_DULL 168 }; 169 170 int 171 zx_match(struct device *parent, void *vcf, void *aux) 172 { 173 struct sbus_attach_args *sa = aux; 174 175 if (strcmp(sa->sa_name, "SUNW,leo") == 0) 176 return (1); 177 178 return (0); 179 } 180 181 void 182 zx_attach(struct device *parent, struct device *self, void *args) 183 { 184 struct zx_softc *sc = (struct zx_softc *)self; 185 struct sbus_attach_args *sa = args; 186 struct rasops_info *ri; 187 bus_space_tag_t bt; 188 bus_space_handle_t bh; 189 int node, isconsole = 0; 190 const char *nam; 191 192 bt = sa->sa_bustag; 193 ri = &sc->sc_sunfb.sf_ro; 194 node = sa->sa_node; 195 196 /* 197 * Map the various parts of the card. 198 */ 199 sc->sc_bustag = bt; 200 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); 201 202 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, 203 sizeof(struct zx_command), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 204 printf(": couldn't map command registers\n"); 205 return; 206 } 207 sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh); 208 209 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, 210 sizeof(struct zx_draw), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 211 printf(": couldn't map ss0 drawing registers\n"); 212 return; 213 } 214 sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh); 215 216 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, 217 sizeof(struct zx_draw_ss1), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 218 printf(": couldn't map ss1 drawing registers\n"); 219 return; 220 } 221 sc->sc_zd_ss1 = (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh); 222 223 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, 224 sizeof(struct zx_cross), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 225 printf(": couldn't map cross registers\n"); 226 return; 227 } 228 sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh); 229 230 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, 231 sizeof(struct zx_cursor), BUS_SPACE_MAP_LINEAR, 0, &bh) != 0) { 232 printf(": couldn't map cursor registers\n"); 233 return; 234 } 235 sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh); 236 237 nam = getpropstring(node, "model"); 238 if (*nam == '\0') 239 nam = sa->sa_name; 240 printf(": %s", nam); 241 242 isconsole = node == fbnode; 243 244 /* 245 * The console is using the 8-bit overlay plane, while the prom 246 * will correctly report 32 bit depth. 247 * The following is an equivalent for 248 * fb_setsize(&sc->sc_sunfb, 8, 1152, 900, node, ca->ca_bustype); 249 * forcing the depth value not to be overwritten. 250 * Furthermore, the linebytes value is in fact 8192 bytes. 251 */ 252 sc->sc_sunfb.sf_depth = 8; 253 sc->sc_sunfb.sf_width = getpropint(node, "width", 1152); 254 sc->sc_sunfb.sf_height = getpropint(node, "height", 900); 255 sc->sc_sunfb.sf_linebytes = 1 << ZX_BWIDTH; 256 sc->sc_sunfb.sf_fbsize = sc->sc_sunfb.sf_height << ZX_BWIDTH; 257 258 printf(", %dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height); 259 260 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, 261 round_page(sc->sc_sunfb.sf_fbsize), BUS_SPACE_MAP_LINEAR, 262 0, &bh) != 0) { 263 printf("%s: couldn't map video memory\n", self->dv_xname); 264 return; 265 } 266 ri->ri_bits = bus_space_vaddr(bt, bh); 267 ri->ri_hw = sc; 268 269 fbwscons_init(&sc->sc_sunfb, 0, isconsole); 270 271 /* 272 * Watch out! rasops_init() invoked via fbwscons_init() did not 273 * compute ri_bits correctly when centering the display, because 274 * it has been tricked with the low depth value. 275 * Recompute now. 276 */ 277 ri->ri_emustride = ri->ri_emuwidth * 4; 278 ri->ri_delta = ri->ri_stride - ri->ri_emustride; 279 ri->ri_pelbytes = 4; 280 ri->ri_xscale = ri->ri_font->fontwidth * 4; 281 ri->ri_bits = ri->ri_origbits; 282 ri->ri_bits += (((ri->ri_width * 4) - ri->ri_emustride) >> 1) & ~3; 283 ri->ri_bits += ((ri->ri_height - ri->ri_emuheight) >> 1) * 284 ri->ri_stride; 285 ri->ri_yorigin = (int)(ri->ri_bits - ri->ri_origbits) 286 / ri->ri_stride; 287 ri->ri_xorigin = (((int)(ri->ri_bits - ri->ri_origbits) 288 % ri->ri_stride) / 4); 289 290 ri->ri_ops.copyrows = zx_copyrows; 291 ri->ri_ops.copycols = zx_copycols; 292 ri->ri_ops.eraserows = zx_eraserows; 293 ri->ri_ops.erasecols = zx_erasecols; 294 ri->ri_ops.putchar = zx_putchar; 295 ri->ri_do_cursor = zx_do_cursor; 296 297 if (isconsole) { 298 /* zx_reset() below will clear screen, so restart at 1st row */ 299 fbwscons_console_init(&sc->sc_sunfb, 0); 300 } 301 302 /* reset cursor & frame buffer controls */ 303 zx_reset(sc, WSDISPLAYIO_MODE_EMUL); 304 305 /* enable video */ 306 zx_burner(sc, 1, 0); 307 308 fbwscons_attach(&sc->sc_sunfb, &zx_accessops, isconsole); 309 } 310 311 int 312 zx_ioctl(void *dev, u_long cmd, caddr_t data, int flags, struct proc *p) 313 { 314 struct zx_softc *sc = dev; 315 struct wsdisplay_fbinfo *wdf; 316 317 /* 318 * Note that, although the emulation (text) mode is running in 319 * an 8-bit plane, we advertise the frame buffer as the full-blown 320 * 32-bit beast it is. 321 */ 322 switch (cmd) { 323 case WSDISPLAYIO_GTYPE: 324 *(u_int *)data = WSDISPLAY_TYPE_SUNLEO; 325 break; 326 case WSDISPLAYIO_GINFO: 327 wdf = (struct wsdisplay_fbinfo *)data; 328 wdf->height = sc->sc_sunfb.sf_height; 329 wdf->width = sc->sc_sunfb.sf_width; 330 wdf->depth = 32; 331 wdf->stride = sc->sc_sunfb.sf_linebytes; 332 wdf->offset = 0; 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