1 /* $NetBSD: zx.c,v 1.16 2005/12/11 12:23:44 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2002 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Andrew Doran. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * Driver for the Sun ZX display adapter. This would be called 'leo', but 41 * NetBSD/amiga already has a driver by that name. The XFree86 and Linux 42 * drivers were used as "living documentation" when writing this; thanks 43 * to the authors. 44 * 45 * Issues (which can be solved with wscons, happily enough): 46 * 47 * o There is lots of unnecessary mucking about rasops in here, primarily 48 * to appease the sparc fb code. 49 * 50 * o RASTERCONSOLE is required. X needs the board set up correctly, and 51 * that's difficult to reconcile with using the PROM for output. 52 */ 53 54 #include <sys/cdefs.h> 55 __KERNEL_RCSID(0, "$NetBSD: zx.c,v 1.16 2005/12/11 12:23:44 christos Exp $"); 56 57 #include <sys/param.h> 58 #include <sys/systm.h> 59 #include <sys/device.h> 60 #include <sys/ioctl.h> 61 #include <sys/malloc.h> 62 #include <sys/mman.h> 63 #include <sys/tty.h> 64 #include <sys/conf.h> 65 #include <sys/syslog.h> 66 #include <sys/buf.h> 67 68 #include <machine/bus.h> 69 #include <machine/autoconf.h> 70 71 #include <uvm/uvm_extern.h> 72 73 #include <dev/sun/fbio.h> 74 #include <dev/sun/fbvar.h> 75 76 #include <dev/sbus/zxreg.h> 77 #include <dev/sbus/zxvar.h> 78 #include <dev/sbus/sbusvar.h> 79 80 #include <dev/wscons/wsconsio.h> 81 82 #ifndef RASTERCONSOLE 83 #error Sorry, this driver needs the RASTERCONSOLE option 84 #endif 85 86 /* Force 32-bit writes. */ 87 #define SETREG(r, v) (*((volatile u_int32_t *)&r) = (v)) 88 89 #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \ 90 ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID) 91 92 void zx_attach(struct device *, struct device *, void *); 93 int zx_match(struct device *, struct cfdata *, void *); 94 95 void zx_blank(struct device *); 96 int zx_cmap_put(struct zx_softc *); 97 void zx_copyrect(struct rasops_info *, int, int, int, int, int, int); 98 int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int); 99 int zx_cross_wait(struct zx_softc *); 100 void zx_fillrect(struct rasops_info *, int, int, int, int, long, int); 101 int zx_intr(void *); 102 void zx_reset(struct zx_softc *); 103 void zx_unblank(struct device *); 104 105 void zx_cursor_blank(struct zx_softc *); 106 void zx_cursor_color(struct zx_softc *); 107 void zx_cursor_move(struct zx_softc *); 108 void zx_cursor_set(struct zx_softc *); 109 void zx_cursor_unblank(struct zx_softc *); 110 111 void zx_copycols(void *, int, int, int, int); 112 void zx_copyrows(void *, int, int, int); 113 void zx_cursor(void *, int, int, int); 114 void zx_do_cursor(struct rasops_info *); 115 void zx_erasecols(void *, int, int, int, long); 116 void zx_eraserows(void *, int, int, long); 117 void zx_putchar(void *, int, int, u_int, long); 118 119 struct zx_mmo { 120 off_t mo_va; 121 off_t mo_pa; 122 off_t mo_size; 123 } static const zx_mmo[] = { 124 { ZX_FB0_VOFF, ZX_OFF_SS0, 0x00800000 }, 125 { ZX_LC0_VOFF, ZX_OFF_LC_SS0_USR, 0x00001000 }, 126 { ZX_LD0_VOFF, ZX_OFF_LD_SS0, 0x00001000 }, 127 { ZX_LX0_CURSOR_VOFF, ZX_OFF_LX_CURSOR, 0x00001000 }, 128 { ZX_FB1_VOFF, ZX_OFF_SS1, 0x00800000 }, 129 { ZX_LC1_VOFF, ZX_OFF_LC_SS1_USR, 0x00001000 }, 130 { ZX_LD1_VOFF, ZX_OFF_LD_SS1, 0x00001000 }, 131 { ZX_LX_KRN_VOFF, ZX_OFF_LX_CROSS, 0x00001000 }, 132 { ZX_LC0_KRN_VOFF, ZX_OFF_LC_SS0_KRN, 0x00001000 }, 133 { ZX_LC1_KRN_VOFF, ZX_OFF_LC_SS1_KRN, 0x00001000 }, 134 { ZX_LD_GBL_VOFF, ZX_OFF_LD_GBL, 0x00001000 }, 135 }; 136 137 CFATTACH_DECL(zx, sizeof(struct zx_softc), 138 zx_match, zx_attach, NULL, NULL); 139 140 extern struct cfdriver zx_cd; 141 142 dev_type_open(zxopen); 143 dev_type_close(zxclose); 144 dev_type_ioctl(zxioctl); 145 dev_type_mmap(zxmmap); 146 147 static struct fbdriver zx_fbdriver = { 148 zx_unblank, zxopen, zxclose, zxioctl, nopoll, zxmmap 149 }; 150 151 int 152 zx_match(struct device *parent, struct cfdata *cf, void *aux) 153 { 154 struct sbus_attach_args *sa; 155 156 sa = (struct sbus_attach_args *)aux; 157 158 return (strcmp(sa->sa_name, "SUNW,leo") == 0); 159 } 160 161 void 162 zx_attach(struct device *parent, struct device *self, void *args) 163 { 164 struct zx_softc *sc; 165 struct sbus_attach_args *sa; 166 bus_space_handle_t bh; 167 bus_space_tag_t bt; 168 struct fbdevice *fb; 169 struct rasops_info *ri; 170 volatile struct zx_command *zc; 171 int isconsole; 172 173 sc = (struct zx_softc *)self; 174 sa = args; 175 fb = &sc->sc_fb; 176 ri = &fb->fb_rinfo; 177 bt = sa->sa_bustag; 178 sc->sc_bt = bt; 179 180 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); 181 182 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, 183 0x800000, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 184 printf("%s: can't map bits\n", self->dv_xname); 185 return; 186 } 187 fb->fb_pixels = (caddr_t)bus_space_vaddr(bt, bh); 188 sc->sc_pixels = (u_int32_t *)fb->fb_pixels; 189 190 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, 191 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 192 printf("%s: can't map zc\n", self->dv_xname); 193 return; 194 } 195 sc->sc_zc = (struct zx_command *)bus_space_vaddr(bt, bh); 196 197 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, 198 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 199 printf("%s: can't map ld/ss0\n", self->dv_xname); 200 return; 201 } 202 sc->sc_zd_ss0 = (struct zx_draw *)bus_space_vaddr(bt, bh); 203 204 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, 205 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 206 printf("%s: can't map ld/ss1\n", self->dv_xname); 207 return; 208 } 209 sc->sc_zd_ss1 = 210 (struct zx_draw_ss1 *)bus_space_vaddr(bt, bh); 211 212 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, 213 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 214 printf("%s: can't map zx\n", self->dv_xname); 215 return; 216 } 217 sc->sc_zx = (struct zx_cross *)bus_space_vaddr(bt, bh); 218 219 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, 220 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 221 printf("%s: can't map zcu\n", self->dv_xname); 222 return; 223 } 224 sc->sc_zcu = (struct zx_cursor *)bus_space_vaddr(bt, bh); 225 226 fb->fb_driver = &zx_fbdriver; 227 fb->fb_device = &sc->sc_dv; 228 fb->fb_flags = sc->sc_dv.dv_cfdata->cf_flags & FB_USERMASK; 229 fb->fb_pfour = NULL; 230 fb->fb_linebytes = 8192; 231 232 fb_setsize_obp(fb, 32, 1280, 1024, sa->sa_node); 233 234 fb->fb_type.fb_cmsize = 256; 235 fb->fb_type.fb_depth = 32; 236 fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; 237 fb->fb_type.fb_type = FBTYPE_SUNLEO; 238 239 printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height); 240 isconsole = fb_is_console(sa->sa_node); 241 if (isconsole) 242 printf(" (console)"); 243 printf("\n"); 244 245 sbus_establish(&sc->sc_sd, &sc->sc_dv); 246 if (sa->sa_nintr != 0) 247 bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc); 248 249 sc->sc_cmap = malloc(768, M_DEVBUF, M_NOWAIT); 250 fb_attach(&sc->sc_fb, isconsole); 251 zx_reset(sc); 252 253 /* 254 * Attach to rcons. XXX At this point, rasops_do_cursor() will be 255 * called before we get our hooks in place. So, we mask off access 256 * to the framebuffer until it's done. 257 */ 258 zc = sc->sc_zc; 259 SETREG(zc->zc_fontt, 1); 260 SETREG(zc->zc_fontmsk, 0); 261 262 fbrcons_init(&sc->sc_fb); 263 264 SETREG(zc->zc_fontt, 0); 265 SETREG(zc->zc_fontmsk, 0xffffffff); 266 267 ri->ri_hw = sc; 268 ri->ri_do_cursor = zx_do_cursor; 269 ri->ri_ops.copycols = zx_copycols; 270 ri->ri_ops.copyrows = zx_copyrows; 271 ri->ri_ops.erasecols = zx_erasecols; 272 ri->ri_ops.eraserows = zx_eraserows; 273 ri->ri_ops.putchar = zx_putchar; 274 275 sc->sc_fontw = ri->ri_font->fontwidth; 276 sc->sc_fonth = ri->ri_font->fontheight; 277 } 278 279 int 280 zxopen(dev_t dev, int flags, int mode, struct lwp *l) 281 { 282 283 if (device_lookup(&zx_cd, minor(dev)) == NULL) 284 return (ENXIO); 285 return (0); 286 } 287 288 int 289 zxclose(dev_t dev, int flags, int mode, struct lwp *l) 290 { 291 struct zx_softc *sc; 292 293 sc = (struct zx_softc *)device_lookup(&zx_cd, minor(dev)); 294 295 zx_reset(sc); 296 zx_cursor_blank(sc); 297 return (0); 298 } 299 300 int 301 zxioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct lwp *l) 302 { 303 struct zx_softc *sc; 304 struct fbcmap *cm; 305 struct fbcursor *cu; 306 uint32_t curbits[2][32]; 307 int rv, v, count, i; 308 309 sc = zx_cd.cd_devs[minor(dev)]; 310 311 switch (cmd) { 312 case FBIOGTYPE: 313 *(struct fbtype *)data = sc->sc_fb.fb_type; 314 break; 315 316 case FBIOGATTR: 317 #define fba ((struct fbgattr *)data) 318 fba->real_type = sc->sc_fb.fb_type.fb_type; 319 fba->owner = 0; /* XXX ??? */ 320 fba->fbtype = sc->sc_fb.fb_type; 321 fba->sattr.flags = 0; 322 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 323 fba->sattr.dev_specific[0] = -1; 324 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 325 fba->emu_types[1] = -1; 326 fba->emu_types[2] = -1; 327 #undef fba 328 break; 329 330 case FBIOGVIDEO: 331 *(int *)data = ((sc->sc_flags & ZX_BLANKED) != 0); 332 break; 333 334 case FBIOSVIDEO: 335 if (*(int *)data) 336 zx_unblank(&sc->sc_dv); 337 else 338 zx_blank(&sc->sc_dv); 339 break; 340 341 case FBIOGETCMAP: 342 cm = (struct fbcmap *)data; 343 if (cm->index > 256 || cm->count > 256 - cm->index) 344 return (EINVAL); 345 rv = copyout(sc->sc_cmap + cm->index, cm->red, cm->count); 346 if (rv == 0) 347 rv = copyout(sc->sc_cmap + 256 + cm->index, cm->green, 348 cm->count); 349 if (rv == 0) 350 rv = copyout(sc->sc_cmap + 512 + cm->index, cm->blue, 351 cm->count); 352 return (rv); 353 354 case FBIOPUTCMAP: 355 cm = (struct fbcmap *)data; 356 if (cm->index > 256 || cm->count > 256 - cm->index) 357 return (EINVAL); 358 rv = copyin(cm->red, sc->sc_cmap + cm->index, cm->count); 359 if (rv == 0) 360 rv = copyin(cm->green, sc->sc_cmap + 256 + cm->index, 361 cm->count); 362 if (rv == 0) 363 rv = copyin(cm->blue, sc->sc_cmap + 512 + cm->index, 364 cm->count); 365 zx_cmap_put(sc); 366 return (rv); 367 368 case FBIOGCURPOS: 369 *(struct fbcurpos *)data = sc->sc_curpos; 370 break; 371 372 case FBIOSCURPOS: 373 sc->sc_curpos = *(struct fbcurpos *)data; 374 zx_cursor_move(sc); 375 break; 376 377 case FBIOGCURMAX: 378 ((struct fbcurpos *)data)->x = 32; 379 ((struct fbcurpos *)data)->y = 32; 380 break; 381 382 case FBIOSCURSOR: 383 cu = (struct fbcursor *)data; 384 v = cu->set; 385 386 if ((v & FB_CUR_SETSHAPE) != 0) { 387 if ((u_int)cu->size.x > 32 || (u_int)cu->size.y > 32) 388 return (EINVAL); 389 count = cu->size.y * 4; 390 rv = copyin(cu->mask, curbits[0], count); 391 if (rv) 392 return rv; 393 rv = copyin(cu->image, curbits[1], count); 394 if (rv) 395 return rv; 396 } 397 if ((v & FB_CUR_SETCUR) != 0) { 398 if (cu->enable) 399 zx_cursor_unblank(sc); 400 else 401 zx_cursor_blank(sc); 402 } 403 if ((v & (FB_CUR_SETPOS | FB_CUR_SETHOT)) != 0) { 404 if ((v & FB_CUR_SETPOS) != 0) 405 sc->sc_curpos = cu->pos; 406 if ((v & FB_CUR_SETHOT) != 0) 407 sc->sc_curhot = cu->hot; 408 zx_cursor_move(sc); 409 } 410 if ((v & FB_CUR_SETCMAP) != 0) { 411 if (cu->cmap.index > 2 || 412 cu->cmap.count > 2 - cu->cmap.index) 413 return (EINVAL); 414 for (i = 0; i < cu->cmap.count; i++) { 415 if ((v = fubyte(&cu->cmap.red[i])) < 0) 416 return (EFAULT); 417 sc->sc_curcmap[i + cu->cmap.index + 0] = v; 418 if ((v = fubyte(&cu->cmap.green[i])) < 0) 419 return (EFAULT); 420 sc->sc_curcmap[i + cu->cmap.index + 2] = v; 421 if ((v = fubyte(&cu->cmap.blue[i])) < 0) 422 return (EFAULT); 423 sc->sc_curcmap[i + cu->cmap.index + 4] = v; 424 } 425 zx_cursor_color(sc); 426 } 427 if ((v & FB_CUR_SETSHAPE) != 0) { 428 sc->sc_cursize = cu->size; 429 count = cu->size.y * 4; 430 memset(sc->sc_curbits, 0, sizeof(sc->sc_curbits)); 431 memcpy(sc->sc_curbits[0], curbits[0], count); 432 memcpy(sc->sc_curbits[1], curbits[1], count); 433 zx_cursor_set(sc); 434 } 435 break; 436 437 case FBIOGCURSOR: 438 cu = (struct fbcursor *)data; 439 440 cu->set = FB_CUR_SETALL; 441 cu->enable = ((sc->sc_flags & ZX_CURSOR) != 0); 442 cu->pos = sc->sc_curpos; 443 cu->hot = sc->sc_curhot; 444 cu->size = sc->sc_cursize; 445 446 if (cu->image != NULL) { 447 count = sc->sc_cursize.y * 4; 448 rv = copyout(sc->sc_curbits[1], cu->image, count); 449 if (rv) 450 return (rv); 451 rv = copyout(sc->sc_curbits[0], cu->mask, count); 452 if (rv) 453 return (rv); 454 } 455 if (cu->cmap.red != NULL) { 456 if (cu->cmap.index > 2 || 457 cu->cmap.count > 2 - cu->cmap.index) 458 return (EINVAL); 459 for (i = 0; i < cu->cmap.count; i++) { 460 v = sc->sc_curcmap[i + cu->cmap.index + 0]; 461 if (subyte(&cu->cmap.red[i], v)) 462 return (EFAULT); 463 v = sc->sc_curcmap[i + cu->cmap.index + 2]; 464 if (subyte(&cu->cmap.green[i], v)) 465 return (EFAULT); 466 v = sc->sc_curcmap[i + cu->cmap.index + 4]; 467 if (subyte(&cu->cmap.blue[i], v)) 468 return (EFAULT); 469 } 470 } else { 471 cu->cmap.index = 0; 472 cu->cmap.count = 2; 473 } 474 break; 475 476 default: 477 #ifdef DEBUG 478 log(LOG_NOTICE, "zxioctl(0x%lx) (%s[%d])\n", cmd, 479 p->p_comm, p->p_pid); 480 #endif 481 return (ENOTTY); 482 } 483 484 return (0); 485 } 486 487 int 488 zx_intr(void *cookie) 489 { 490 491 return (1); 492 } 493 494 void 495 zx_reset(struct zx_softc *sc) 496 { 497 volatile struct zx_draw *zd; 498 volatile struct zx_command *zc; 499 struct fbtype *fbt; 500 u_int i; 501 502 zd = sc->sc_zd_ss0; 503 zc = sc->sc_zc; 504 fbt = &sc->sc_fb.fb_type; 505 506 zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0); 507 zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30); 508 zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20); 509 zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30); 510 511 i = sc->sc_zd_ss1->zd_misc; 512 i |= ZX_SS1_MISC_ENABLE; 513 SETREG(sc->sc_zd_ss1->zd_misc, i); 514 515 SETREG(zd->zd_wid, 0xffffffff); 516 SETREG(zd->zd_widclip, 0); 517 SETREG(zd->zd_wmask, 0xffff); 518 SETREG(zd->zd_vclipmin, 0); 519 SETREG(zd->zd_vclipmax, 520 (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 16)); 521 SETREG(zd->zd_fg, 0); 522 SETREG(zd->zd_planemask, 0xff000000); 523 SETREG(zd->zd_rop, ZX_STD_ROP); 524 525 SETREG(zc->zc_extent, 526 (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 11)); 527 SETREG(zc->zc_addrspace, ZX_ADDRSPC_FONT_OBGR); 528 SETREG(zc->zc_fontt, 0); 529 530 for (i = 0; i < 256; i++) { 531 sc->sc_cmap[i] = rasops_cmap[i * 3]; 532 sc->sc_cmap[i + 256] = rasops_cmap[i * 3 + 1]; 533 sc->sc_cmap[i + 512] = rasops_cmap[i * 3 + 2]; 534 } 535 536 zx_cmap_put(sc); 537 } 538 539 int 540 zx_cross_wait(struct zx_softc *sc) 541 { 542 volatile struct zx_cross *zx; 543 int i; 544 545 zx = sc->sc_zx; 546 547 for (i = 300000; i != 0; i--) { 548 if ((zx->zx_csr & ZX_CROSS_CSR_PROGRESS) == 0) 549 break; 550 DELAY(1); 551 } 552 553 if (i == 0) 554 printf("zx_cross_wait: timed out\n"); 555 556 return (i); 557 } 558 559 int 560 zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value) 561 { 562 volatile struct zx_cross *zx; 563 u_int tmp = 0; 564 565 zx = sc->sc_zx; 566 SETREG(zx->zx_type, ZX_CROSS_TYPE_WID); 567 568 if (zx_cross_wait(sc)) 569 return (1); 570 571 if (type == ZX_WID_DBL_8) 572 tmp = (index & 0x0f) + 0x40; 573 else if (type == ZX_WID_DBL_24) 574 tmp = index & 0x3f; 575 576 SETREG(zx->zx_type, 0x5800 + tmp); 577 SETREG(zx->zx_value, value); 578 SETREG(zx->zx_type, ZX_CROSS_TYPE_WID); 579 SETREG(zx->zx_csr, ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2); 580 581 return (0); 582 } 583 584 int 585 zx_cmap_put(struct zx_softc *sc) 586 { 587 volatile struct zx_cross *zx; 588 const u_char *b; 589 u_int i, t; 590 591 zx = sc->sc_zx; 592 593 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0); 594 if (zx_cross_wait(sc)) 595 return (1); 596 597 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUTDATA); 598 599 for (i = 0, b = sc->sc_cmap; i < 256; i++) { 600 t = b[i]; 601 t |= b[i + 256] << 8; 602 t |= b[i + 512] << 16; 603 SETREG(zx->zx_value, t); 604 } 605 606 SETREG(zx->zx_type, ZX_CROSS_TYPE_CLUT0); 607 i = zx->zx_csr; 608 i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2; 609 SETREG(zx->zx_csr, i); 610 return (0); 611 } 612 613 void 614 zx_cursor_move(struct zx_softc *sc) 615 { 616 volatile struct zx_cursor *zcu; 617 int sx, sy, x, y; 618 619 x = sc->sc_curpos.x - sc->sc_curhot.x; 620 y = sc->sc_curpos.y - sc->sc_curhot.y; 621 zcu = sc->sc_zcu; 622 623 if (x < 0) { 624 sx = min(-x, 32); 625 x = 0; 626 } else 627 sx = 0; 628 629 if (y < 0) { 630 sy = min(-y, 32); 631 y = 0; 632 } else 633 sy = 0; 634 635 if (sx != sc->sc_shiftx || sy != sc->sc_shifty) { 636 sc->sc_shiftx = sx; 637 sc->sc_shifty = sy; 638 zx_cursor_set(sc); 639 } 640 641 SETREG(zcu->zcu_sxy, ((y & 0x7ff) << 11) | (x & 0x7ff)); 642 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x30); 643 644 /* XXX Necessary? */ 645 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x80); 646 } 647 648 void 649 zx_cursor_set(struct zx_softc *sc) 650 { 651 volatile struct zx_cursor *zcu; 652 int i, j, data; 653 654 zcu = sc->sc_zcu; 655 656 if ((sc->sc_flags & ZX_CURSOR) != 0) 657 SETREG(zcu->zcu_misc, zcu->zcu_misc & ~0x80); 658 659 for (j = 0; j < 2; j++) { 660 SETREG(zcu->zcu_type, 0x20 << j); 661 662 for (i = sc->sc_shifty; i < 32; i++) { 663 data = sc->sc_curbits[j][i]; 664 SETREG(zcu->zcu_data, data >> sc->sc_shiftx); 665 } 666 for (i = sc->sc_shifty; i != 0; i--) 667 SETREG(zcu->zcu_data, 0); 668 } 669 670 if ((sc->sc_flags & ZX_CURSOR) != 0) 671 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x80); 672 } 673 674 void 675 zx_cursor_blank(struct zx_softc *sc) 676 { 677 volatile struct zx_cursor *zcu; 678 679 sc->sc_flags &= ~ZX_CURSOR; 680 zcu = sc->sc_zcu; 681 SETREG(zcu->zcu_misc, zcu->zcu_misc & ~0x80); 682 } 683 684 void 685 zx_cursor_unblank(struct zx_softc *sc) 686 { 687 volatile struct zx_cursor *zcu; 688 689 sc->sc_flags |= ZX_CURSOR; 690 zcu = sc->sc_zcu; 691 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x80); 692 } 693 694 void 695 zx_cursor_color(struct zx_softc *sc) 696 { 697 volatile struct zx_cursor *zcu; 698 u_int8_t tmp; 699 700 zcu = sc->sc_zcu; 701 702 SETREG(zcu->zcu_type, 0x50); 703 704 tmp = sc->sc_curcmap[0] | (sc->sc_curcmap[2] << 8) | 705 (sc->sc_curcmap[4] << 16); 706 SETREG(zcu->zcu_data, tmp); 707 708 tmp = sc->sc_curcmap[1] | (sc->sc_curcmap[3] << 8) | 709 (sc->sc_curcmap[5] << 16); 710 SETREG(zcu->zcu_data, sc->sc_curcmap[1]); 711 712 SETREG(zcu->zcu_misc, zcu->zcu_misc | 0x03); 713 } 714 715 void 716 zx_blank(struct device *dv) 717 { 718 struct zx_softc *sc; 719 volatile struct zx_cross *zx; 720 721 sc = (struct zx_softc *)dv; 722 723 if ((sc->sc_flags & ZX_BLANKED) != 0) 724 return; 725 sc->sc_flags |= ZX_BLANKED; 726 727 zx = sc->sc_zx; 728 SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO); 729 SETREG(zx->zx_csr, zx->zx_csr & ~ZX_CROSS_CSR_ENABLE); 730 } 731 732 void 733 zx_unblank(struct device *dv) 734 { 735 struct zx_softc *sc; 736 volatile struct zx_cross *zx; 737 738 sc = (struct zx_softc *)dv; 739 740 if ((sc->sc_flags & ZX_BLANKED) == 0) 741 return; 742 sc->sc_flags &= ~ZX_BLANKED; 743 744 zx = sc->sc_zx; 745 SETREG(zx->zx_type, ZX_CROSS_TYPE_VIDEO); 746 SETREG(zx->zx_csr, zx->zx_csr | ZX_CROSS_CSR_ENABLE); 747 } 748 749 paddr_t 750 zxmmap(dev_t dev, off_t off, int prot) 751 { 752 struct zx_softc *sc; 753 const struct zx_mmo *mm, *mmmax; 754 755 sc = device_lookup(&zx_cd, minor(dev)); 756 off = trunc_page(off); 757 mm = zx_mmo; 758 mmmax = mm + sizeof(zx_mmo) / sizeof(zx_mmo[0]); 759 760 for (; mm < mmmax; mm++) 761 if (off >= mm->mo_va && off < mm->mo_va + mm->mo_size) { 762 off = off - mm->mo_va + mm->mo_pa; 763 return (bus_space_mmap(sc->sc_bt, sc->sc_paddr, 764 off, prot, BUS_SPACE_MAP_LINEAR)); 765 } 766 767 return (-1); 768 } 769 770 void 771 zx_fillrect(struct rasops_info *ri, int x, int y, int w, int h, long attr, 772 int rop) 773 { 774 struct zx_softc *sc; 775 volatile struct zx_command *zc; 776 volatile struct zx_draw *zd; 777 int fg, bg; 778 779 sc = ri->ri_hw; 780 zc = sc->sc_zc; 781 zd = sc->sc_zd_ss0; 782 783 rasops_unpack_attr(attr, &fg, &bg, NULL); 784 x = x * sc->sc_fontw + ri->ri_xorigin; 785 y = y * sc->sc_fonth + ri->ri_yorigin; 786 w = sc->sc_fontw * w - 1; 787 h = sc->sc_fonth * h - 1; 788 789 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 790 ; 791 792 SETREG(zd->zd_rop, rop); 793 SETREG(zd->zd_fg, (bg & 7) ? 0x00000000 : 0xff000000); 794 SETREG(zc->zc_extent, w | (h << 11)); 795 SETREG(zc->zc_fill, x | (y << 11) | 0x80000000); 796 } 797 798 void 799 zx_copyrect(struct rasops_info *ri, int sx, int sy, int dx, int dy, int w, 800 int h) 801 { 802 struct zx_softc *sc; 803 volatile struct zx_command *zc; 804 volatile struct zx_draw *zd; 805 int dir; 806 807 sc = ri->ri_hw; 808 zc = sc->sc_zc; 809 zd = sc->sc_zd_ss0; 810 811 sx = sx * sc->sc_fontw + ri->ri_xorigin; 812 sy = sy * sc->sc_fonth + ri->ri_yorigin; 813 dx = dx * sc->sc_fontw + ri->ri_xorigin; 814 dy = dy * sc->sc_fonth + ri->ri_yorigin; 815 w = w * sc->sc_fontw - 1; 816 h = h * sc->sc_fonth - 1; 817 818 if (sy < dy || sx < dx) { 819 dir = 0x80000000; 820 sx += w; 821 sy += h; 822 dx += w; 823 dy += h; 824 } else 825 dir = 0; 826 827 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 828 ; 829 830 SETREG(zd->zd_rop, ZX_STD_ROP); 831 SETREG(zc->zc_extent, w | (h << 11) | dir); 832 SETREG(zc->zc_src, sx | (sy << 11)); 833 SETREG(zc->zc_copy, dx | (dy << 11)); 834 } 835 836 void 837 zx_do_cursor(struct rasops_info *ri) 838 { 839 840 zx_fillrect(ri, ri->ri_ccol, ri->ri_crow, 1, 1, 0, 841 ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE | 842 ZX_ATTR_FORCE_WID); 843 } 844 845 void 846 zx_erasecols(void *cookie, int row, int col, int num, long attr) 847 { 848 struct rasops_info *ri; 849 850 ri = (struct rasops_info *)cookie; 851 852 zx_fillrect(ri, col, row, num, 1, attr, ZX_STD_ROP); 853 } 854 855 void 856 zx_eraserows(void *cookie, int row, int num, long attr) 857 { 858 struct rasops_info *ri; 859 860 ri = (struct rasops_info *)cookie; 861 862 zx_fillrect(ri, 0, row, ri->ri_cols, num, attr, ZX_STD_ROP); 863 } 864 865 void 866 zx_copyrows(void *cookie, int src, int dst, int num) 867 { 868 struct rasops_info *ri; 869 870 ri = (struct rasops_info *)cookie; 871 872 zx_copyrect(ri, 0, src, 0, dst, ri->ri_cols, num); 873 } 874 875 void 876 zx_copycols(void *cookie, int row, int src, int dst, int num) 877 { 878 struct rasops_info *ri; 879 880 ri = (struct rasops_info *)cookie; 881 882 zx_copyrect(ri, src, row, dst, row, num, 1); 883 } 884 885 void 886 zx_putchar(void *cookie, int row, int col, u_int uc, long attr) 887 { 888 struct rasops_info *ri; 889 struct zx_softc *sc; 890 struct wsdisplay_font *font; 891 volatile struct zx_command *zc; 892 volatile struct zx_draw *zd; 893 volatile u_int32_t *dp; 894 u_int8_t *fb; 895 int fs, i, fg, bg, ul; 896 897 ri = (struct rasops_info *)cookie; 898 899 if (uc == ' ') { 900 zx_fillrect(ri, col, row, 1, 1, attr, ZX_STD_ROP); 901 return; 902 } 903 904 sc = (struct zx_softc *)ri->ri_hw; 905 font = ri->ri_font; 906 zc = sc->sc_zc; 907 zd = sc->sc_zd_ss0; 908 909 dp = (volatile u_int32_t *)sc->sc_pixels + 910 ((row * sc->sc_fonth + ri->ri_yorigin) << 11) + 911 (col * sc->sc_fontw + ri->ri_xorigin); 912 fb = (u_int8_t *)font->data + (uc - font->firstchar) * 913 ri->ri_fontscale; 914 fs = font->stride; 915 rasops_unpack_attr(attr, &fg, &bg, &ul); 916 917 while ((zc->zc_csr & ZX_CSR_BLT_BUSY) != 0) 918 ; 919 920 SETREG(zd->zd_rop, ZX_STD_ROP); 921 SETREG(zd->zd_fg, (fg & 7) ? 0x00000000 : 0xff000000); 922 SETREG(zd->zd_bg, (bg & 7) ? 0x00000000 : 0xff000000); 923 SETREG(zc->zc_fontmsk, 0xffffffff << (32 - sc->sc_fontw)); 924 925 if (sc->sc_fontw <= 8) { 926 for (i = sc->sc_fonth; i != 0; i--, dp += 2048) { 927 *dp = *fb << 24; 928 fb += fs; 929 } 930 } else { 931 for (i = sc->sc_fonth; i != 0; i--, dp += 2048) { 932 *dp = *((u_int16_t *)fb) << 16; 933 fb += fs; 934 } 935 } 936 937 if (ul) { 938 dp -= 4096; 939 *dp = 0xffffffff; 940 } 941 } 942