1 /* $NetBSD: zx.c,v 1.38 2010/12/09 04:35:36 uebayasi 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 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 /* 33 * Driver for the Sun ZX display adapter. This would be called 'leo', but 34 * NetBSD/amiga already has a driver by that name. The XFree86 and Linux 35 * drivers were used as "living documentation" when writing this; thanks 36 * to the authors. 37 * 38 * Issues (which can be solved with wscons, happily enough): 39 * 40 * o There is lots of unnecessary mucking about rasops in here, primarily 41 * to appease the sparc fb code. 42 * 43 * o RASTERCONSOLE is required. X needs the board set up correctly, and 44 * that's difficult to reconcile with using the PROM for output. 45 */ 46 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD: zx.c,v 1.38 2010/12/09 04:35:36 uebayasi Exp $"); 49 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/device.h> 53 #include <sys/ioctl.h> 54 #include <sys/malloc.h> 55 #include <sys/mman.h> 56 #include <sys/tty.h> 57 #include <sys/conf.h> 58 #include <sys/syslog.h> 59 #include <sys/buf.h> 60 #ifdef DEBUG 61 /* for log(9) in zxioctl() */ 62 #include <sys/lwp.h> 63 #include <sys/proc.h> 64 #endif 65 66 #include <sys/bus.h> 67 #include <machine/autoconf.h> 68 69 #include <dev/sun/fbio.h> 70 #include <dev/sun/fbvar.h> 71 72 #include "wsdisplay.h" 73 #if NWSDISPLAY > 0 74 #include <dev/wscons/wsconsio.h> 75 #include <dev/wsfont/wsfont.h> 76 #include <dev/rasops/rasops.h> 77 #include <dev/wscons/wsdisplay_vconsvar.h> 78 79 #include "opt_wsemul.h" 80 #endif 81 82 #include <dev/sbus/zxreg.h> 83 #include <dev/sbus/zxvar.h> 84 #include <dev/sbus/sbusvar.h> 85 86 #include <dev/wscons/wsconsio.h> 87 88 #include "ioconf.h" 89 90 #if (NWSDISPLAY == 0) && !defined(RASTERCONSOLE) 91 #error Sorry, this driver needs WSCONS or RASTERCONSOLE 92 #endif 93 94 #if (NWSDISPLAY > 0) && defined(RASTERCONSOLE) 95 #error Sorry, RASTERCONSOLE and WSCONS are mutually exclusive 96 #endif 97 98 #define ZX_STD_ROP (ZX_ROP_NEW | ZX_ATTR_WE_ENABLE | \ 99 ZX_ATTR_OE_ENABLE | ZX_ATTR_FORCE_WID) 100 101 static void zx_attach(device_t, device_t, void *); 102 static int zx_match(device_t, cfdata_t, void *); 103 104 static void zx_blank(device_t); 105 static int zx_cmap_put(struct zx_softc *); 106 static void zx_copyrect(struct zx_softc *, int, int, int, int, int, int); 107 static int zx_cross_loadwid(struct zx_softc *, u_int, u_int, u_int); 108 static int zx_cross_wait(struct zx_softc *); 109 static void zx_fillrect(struct zx_softc *, int, int, int, int, uint32_t, int); 110 static int zx_intr(void *); 111 static void zx_reset(struct zx_softc *); 112 static void zx_unblank(device_t); 113 114 static void zx_cursor_blank(struct zx_softc *); 115 static void zx_cursor_color(struct zx_softc *); 116 static void zx_cursor_move(struct zx_softc *); 117 static void zx_cursor_set(struct zx_softc *); 118 static void zx_cursor_unblank(struct zx_softc *); 119 120 static void zx_copycols(void *, int, int, int, int); 121 static void zx_copyrows(void *, int, int, int); 122 static void zx_do_cursor(void *, int, int, int); 123 static void zx_erasecols(void *, int, int, int, long); 124 static void zx_eraserows(void *, int, int, long); 125 static void zx_putchar(void *, int, int, u_int, long); 126 127 struct zx_mmo { 128 off_t mo_va; 129 off_t mo_pa; 130 off_t mo_size; 131 } static const zx_mmo[] = { 132 { ZX_FB0_VOFF, ZX_OFF_SS0, 0x00800000 }, 133 { ZX_LC0_VOFF, ZX_OFF_LC_SS0_USR, 0x00001000 }, 134 { ZX_LD0_VOFF, ZX_OFF_LD_SS0, 0x00001000 }, 135 { ZX_LX0_CURSOR_VOFF, ZX_OFF_LX_CURSOR, 0x00001000 }, 136 { ZX_FB1_VOFF, ZX_OFF_SS1, 0x00800000 }, 137 { ZX_LC1_VOFF, ZX_OFF_LC_SS1_USR, 0x00001000 }, 138 { ZX_LD1_VOFF, ZX_OFF_LD_SS1, 0x00001000 }, 139 { ZX_LX_KRN_VOFF, ZX_OFF_LX_CROSS, 0x00001000 }, 140 { ZX_LC0_KRN_VOFF, ZX_OFF_LC_SS0_KRN, 0x00001000 }, 141 { ZX_LC1_KRN_VOFF, ZX_OFF_LC_SS1_KRN, 0x00001000 }, 142 { ZX_LD_GBL_VOFF, ZX_OFF_LD_GBL, 0x00001000 }, 143 }; 144 145 CFATTACH_DECL_NEW(zx, sizeof(struct zx_softc), 146 zx_match, zx_attach, NULL, NULL); 147 148 static dev_type_open(zxopen); 149 static dev_type_close(zxclose); 150 static dev_type_ioctl(zxioctl); 151 static dev_type_mmap(zxmmap); 152 153 static struct fbdriver zx_fbdriver = { 154 zx_unblank, zxopen, zxclose, zxioctl, nopoll, zxmmap 155 }; 156 157 #if NWSDISPLAY > 0 158 struct wsscreen_descr zx_defaultscreen = { 159 "std", 160 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 161 /* doesn't matter - you can't really have more than one leo */ 162 NULL, /* textops */ 163 8, 16, /* font width/height */ 164 WSSCREEN_WSCOLORS, /* capabilities */ 165 NULL /* modecookie */ 166 }; 167 168 static int zx_ioctl(void *, void *, u_long, void *, int, struct lwp *); 169 static paddr_t zx_mmap(void *, void *, off_t, int); 170 static void zx_init_screen(void *, struct vcons_screen *, int, long *); 171 172 static int zx_putcmap(struct zx_softc *, struct wsdisplay_cmap *); 173 static int zx_getcmap(struct zx_softc *, struct wsdisplay_cmap *); 174 175 struct wsdisplay_accessops zx_accessops = { 176 zx_ioctl, 177 zx_mmap, 178 NULL, /* alloc_screen */ 179 NULL, /* free_screen */ 180 NULL, /* show_screen */ 181 NULL, /* load_font */ 182 NULL, /* pollc */ 183 NULL /* scroll */ 184 }; 185 186 const struct wsscreen_descr *_zx_scrlist[] = { 187 &zx_defaultscreen 188 }; 189 190 struct wsscreen_list zx_screenlist = { 191 sizeof(_zx_scrlist) / sizeof(struct wsscreen_descr *), 192 _zx_scrlist 193 }; 194 195 196 extern const u_char rasops_cmap[768]; 197 198 static struct vcons_screen zx_console_screen; 199 #endif /* NWSDISPLAY > 0 */ 200 201 static int 202 zx_match(device_t parent, cfdata_t cf, void *aux) 203 { 204 struct sbus_attach_args *sa; 205 206 sa = (struct sbus_attach_args *)aux; 207 208 return (strcmp(sa->sa_name, "SUNW,leo") == 0); 209 } 210 211 static void 212 zx_attach(device_t parent, device_t self, void *args) 213 { 214 struct zx_softc *sc; 215 struct sbus_attach_args *sa; 216 bus_space_handle_t bh; 217 bus_space_tag_t bt; 218 struct fbdevice *fb; 219 #if NWSDISPLAY > 0 220 struct wsemuldisplaydev_attach_args aa; 221 struct rasops_info *ri = &zx_console_screen.scr_ri; 222 unsigned long defattr; 223 #endif 224 int isconsole, width, height; 225 226 sc = device_private(self); 227 sc->sc_dv = self; 228 229 sa = args; 230 fb = &sc->sc_fb; 231 bt = sa->sa_bustag; 232 sc->sc_bt = bt; 233 sc->sc_paddr = sbus_bus_addr(bt, sa->sa_slot, sa->sa_offset); 234 235 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_SS0, 236 0x800000, BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_LARGE, &bh) != 0) { 237 aprint_error_dev(self, "can't map bits\n"); 238 return; 239 } 240 fb->fb_pixels = (void *)bus_space_vaddr(bt, bh); 241 sc->sc_pixels = (uint32_t *)fb->fb_pixels; 242 243 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LC_SS0_USR, 244 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 245 aprint_error_dev(self, "can't map zc\n"); 246 return; 247 } 248 249 sc->sc_bhzc = bh; 250 251 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS0, 252 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 253 aprint_error_dev(self, "can't map ld/ss0\n"); 254 return; 255 } 256 sc->sc_bhzdss0 = bh; 257 258 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LD_SS1, 259 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 260 aprint_error_dev(self, "can't map ld/ss1\n"); 261 return; 262 } 263 sc->sc_bhzdss1 = bh; 264 265 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CROSS, 266 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 267 aprint_error_dev(self, "can't map zx\n"); 268 return; 269 } 270 sc->sc_bhzx = bh; 271 272 if (sbus_bus_map(bt, sa->sa_slot, sa->sa_offset + ZX_OFF_LX_CURSOR, 273 PAGE_SIZE, BUS_SPACE_MAP_LINEAR, &bh) != 0) { 274 aprint_error_dev(self, "can't map zcu\n"); 275 return; 276 } 277 sc->sc_bhzcu = bh; 278 279 fb->fb_driver = &zx_fbdriver; 280 fb->fb_device = sc->sc_dv; 281 fb->fb_flags = device_cfdata(sc->sc_dv)->cf_flags & FB_USERMASK; 282 fb->fb_pfour = NULL; 283 fb->fb_linebytes = prom_getpropint(sa->sa_node, "linebytes", 8192); 284 285 width = prom_getpropint(sa->sa_node, "width", 1280); 286 height = prom_getpropint(sa->sa_node, "height", 1024); 287 fb_setsize_obp(fb, 32, width, height, sa->sa_node); 288 289 fb->fb_type.fb_cmsize = 256; 290 fb->fb_type.fb_depth = 32; 291 fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; 292 fb->fb_type.fb_type = FBTYPE_SUNLEO; 293 294 printf(": %d x %d", fb->fb_type.fb_width, fb->fb_type.fb_height); 295 isconsole = fb_is_console(sa->sa_node); 296 if (isconsole) 297 printf(" (console)"); 298 printf("\n"); 299 300 if (sa->sa_nintr != 0) 301 bus_intr_establish(bt, sa->sa_pri, IPL_NONE, zx_intr, sc); 302 303 sc->sc_cmap = malloc(768, M_DEVBUF, M_NOWAIT); 304 zx_reset(sc); 305 306 #if NWSDISPLAY > 0 307 sc->sc_width = fb->fb_type.fb_width; 308 sc->sc_stride = 8192; /* 32 bit */ 309 sc->sc_height = fb->fb_type.fb_height; 310 311 /* setup rasops and so on for wsdisplay */ 312 wsfont_init(); 313 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 314 sc->sc_bg = WS_DEFAULT_BG; 315 316 vcons_init(&sc->vd, sc, &zx_defaultscreen, &zx_accessops); 317 sc->vd.init_screen = zx_init_screen; 318 319 if (isconsole) { 320 /* we mess with zx_console_screen only once */ 321 vcons_init_screen(&sc->vd, &zx_console_screen, 1, 322 &defattr); 323 zx_console_screen.scr_flags |= VCONS_SCREEN_IS_STATIC; 324 325 zx_defaultscreen.textops = &ri->ri_ops; 326 zx_defaultscreen.capabilities = WSSCREEN_WSCOLORS; 327 zx_defaultscreen.nrows = ri->ri_rows; 328 zx_defaultscreen.ncols = ri->ri_cols; 329 zx_fillrect(sc, 0, 0, width, height, 330 ri->ri_devcmap[defattr >> 16], ZX_STD_ROP); 331 wsdisplay_cnattach(&zx_defaultscreen, ri, 0, 0, defattr); 332 vcons_replay_msgbuf(&zx_console_screen); 333 } else { 334 /* 335 * we're not the console so we just clear the screen and don't 336 * set up any sort of text display 337 */ 338 if (zx_defaultscreen.textops == NULL) { 339 /* 340 * ugly, but... 341 * we want the console settings to win, so we only 342 * touch anything when we find an untouched screen 343 * definition. In this case we fill it from fb to 344 * avoid problems in case no zx is the console 345 */ 346 ri = &sc->sc_fb.fb_rinfo; 347 zx_defaultscreen.textops = &ri->ri_ops; 348 zx_defaultscreen.capabilities = ri->ri_caps; 349 zx_defaultscreen.nrows = ri->ri_rows; 350 zx_defaultscreen.ncols = ri->ri_cols; 351 } 352 } 353 354 aa.scrdata = &zx_screenlist; 355 aa.console = isconsole; 356 aa.accessops = &zx_accessops; 357 aa.accesscookie = &sc->vd; 358 config_found(sc->sc_dv, &aa, wsemuldisplaydevprint); 359 #endif 360 fb_attach(&sc->sc_fb, isconsole); 361 } 362 363 static int 364 zxopen(dev_t dev, int flags, int mode, struct lwp *l) 365 { 366 367 if (device_lookup(&zx_cd, minor(dev)) == NULL) 368 return (ENXIO); 369 return (0); 370 } 371 372 static int 373 zxclose(dev_t dev, int flags, int mode, struct lwp *l) 374 { 375 struct zx_softc *sc; 376 377 sc = device_lookup_private(&zx_cd, minor(dev)); 378 379 zx_reset(sc); 380 zx_cursor_blank(sc); 381 return (0); 382 } 383 384 static int 385 zxioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l) 386 { 387 struct zx_softc *sc; 388 struct fbcmap *cm; 389 struct fbcursor *cu; 390 uint32_t curbits[2][32]; 391 int rv, v, count, i; 392 393 sc = device_lookup_private(&zx_cd, minor(dev)); 394 395 switch (cmd) { 396 case FBIOGTYPE: 397 *(struct fbtype *)data = sc->sc_fb.fb_type; 398 break; 399 400 case FBIOGATTR: 401 #define fba ((struct fbgattr *)data) 402 fba->real_type = sc->sc_fb.fb_type.fb_type; 403 fba->owner = 0; /* XXX ??? */ 404 fba->fbtype = sc->sc_fb.fb_type; 405 fba->sattr.flags = 0; 406 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 407 fba->sattr.dev_specific[0] = -1; 408 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 409 fba->emu_types[1] = -1; 410 fba->emu_types[2] = -1; 411 #undef fba 412 break; 413 414 case FBIOGVIDEO: 415 *(int *)data = ((sc->sc_flags & ZX_BLANKED) != 0); 416 break; 417 418 case FBIOSVIDEO: 419 if (*(int *)data) 420 zx_unblank(sc->sc_dv); 421 else 422 zx_blank(sc->sc_dv); 423 break; 424 425 case FBIOGETCMAP: 426 cm = (struct fbcmap *)data; 427 if (cm->index > 256 || cm->count > 256 - cm->index) 428 return (EINVAL); 429 rv = copyout(sc->sc_cmap + cm->index, cm->red, cm->count); 430 if (rv == 0) 431 rv = copyout(sc->sc_cmap + 256 + cm->index, cm->green, 432 cm->count); 433 if (rv == 0) 434 rv = copyout(sc->sc_cmap + 512 + cm->index, cm->blue, 435 cm->count); 436 return (rv); 437 438 case FBIOPUTCMAP: 439 cm = (struct fbcmap *)data; 440 if (cm->index > 256 || cm->count > 256 - cm->index) 441 return (EINVAL); 442 rv = copyin(cm->red, sc->sc_cmap + cm->index, cm->count); 443 if (rv == 0) 444 rv = copyin(cm->green, sc->sc_cmap + 256 + cm->index, 445 cm->count); 446 if (rv == 0) 447 rv = copyin(cm->blue, sc->sc_cmap + 512 + cm->index, 448 cm->count); 449 zx_cmap_put(sc); 450 return (rv); 451 452 case FBIOGCURPOS: 453 *(struct fbcurpos *)data = sc->sc_curpos; 454 break; 455 456 case FBIOSCURPOS: 457 sc->sc_curpos = *(struct fbcurpos *)data; 458 zx_cursor_move(sc); 459 break; 460 461 case FBIOGCURMAX: 462 ((struct fbcurpos *)data)->x = 32; 463 ((struct fbcurpos *)data)->y = 32; 464 break; 465 466 case FBIOSCURSOR: 467 cu = (struct fbcursor *)data; 468 v = cu->set; 469 470 if ((v & FB_CUR_SETSHAPE) != 0) { 471 if ((u_int)cu->size.x > 32 || (u_int)cu->size.y > 32) 472 return (EINVAL); 473 count = cu->size.y * 4; 474 rv = copyin(cu->mask, curbits[0], count); 475 if (rv) 476 return rv; 477 rv = copyin(cu->image, curbits[1], count); 478 if (rv) 479 return rv; 480 } 481 if ((v & FB_CUR_SETCUR) != 0) { 482 if (cu->enable) 483 zx_cursor_unblank(sc); 484 else 485 zx_cursor_blank(sc); 486 } 487 if ((v & (FB_CUR_SETPOS | FB_CUR_SETHOT)) != 0) { 488 if ((v & FB_CUR_SETPOS) != 0) 489 sc->sc_curpos = cu->pos; 490 if ((v & FB_CUR_SETHOT) != 0) 491 sc->sc_curhot = cu->hot; 492 zx_cursor_move(sc); 493 } 494 if ((v & FB_CUR_SETCMAP) != 0) { 495 if (cu->cmap.index > 2 || 496 cu->cmap.count > 2 - cu->cmap.index) 497 return (EINVAL); 498 for (i = 0; i < cu->cmap.count; i++) { 499 if ((v = fubyte(&cu->cmap.red[i])) < 0) 500 return (EFAULT); 501 sc->sc_curcmap[i + cu->cmap.index + 0] = v; 502 if ((v = fubyte(&cu->cmap.green[i])) < 0) 503 return (EFAULT); 504 sc->sc_curcmap[i + cu->cmap.index + 2] = v; 505 if ((v = fubyte(&cu->cmap.blue[i])) < 0) 506 return (EFAULT); 507 sc->sc_curcmap[i + cu->cmap.index + 4] = v; 508 } 509 zx_cursor_color(sc); 510 } 511 if ((v & FB_CUR_SETSHAPE) != 0) { 512 sc->sc_cursize = cu->size; 513 count = cu->size.y * 4; 514 memset(sc->sc_curbits, 0, sizeof(sc->sc_curbits)); 515 memcpy(sc->sc_curbits[0], curbits[0], count); 516 memcpy(sc->sc_curbits[1], curbits[1], count); 517 zx_cursor_set(sc); 518 } 519 break; 520 521 case FBIOGCURSOR: 522 cu = (struct fbcursor *)data; 523 524 cu->set = FB_CUR_SETALL; 525 cu->enable = ((sc->sc_flags & ZX_CURSOR) != 0); 526 cu->pos = sc->sc_curpos; 527 cu->hot = sc->sc_curhot; 528 cu->size = sc->sc_cursize; 529 530 if (cu->image != NULL) { 531 count = sc->sc_cursize.y * 4; 532 rv = copyout(sc->sc_curbits[1], cu->image, count); 533 if (rv) 534 return (rv); 535 rv = copyout(sc->sc_curbits[0], cu->mask, count); 536 if (rv) 537 return (rv); 538 } 539 if (cu->cmap.red != NULL) { 540 if (cu->cmap.index > 2 || 541 cu->cmap.count > 2 - cu->cmap.index) 542 return (EINVAL); 543 for (i = 0; i < cu->cmap.count; i++) { 544 v = sc->sc_curcmap[i + cu->cmap.index + 0]; 545 if (subyte(&cu->cmap.red[i], v)) 546 return (EFAULT); 547 v = sc->sc_curcmap[i + cu->cmap.index + 2]; 548 if (subyte(&cu->cmap.green[i], v)) 549 return (EFAULT); 550 v = sc->sc_curcmap[i + cu->cmap.index + 4]; 551 if (subyte(&cu->cmap.blue[i], v)) 552 return (EFAULT); 553 } 554 } else { 555 cu->cmap.index = 0; 556 cu->cmap.count = 2; 557 } 558 break; 559 560 default: 561 #ifdef DEBUG 562 log(LOG_NOTICE, "zxioctl(0x%lx) (%s[%d])\n", cmd, 563 l->l_proc->p_comm, l->l_proc->p_pid); 564 #endif 565 return (ENOTTY); 566 } 567 568 return (0); 569 } 570 571 static int 572 zx_intr(void *cookie) 573 { 574 575 return (1); 576 } 577 578 static void 579 zx_reset(struct zx_softc *sc) 580 { 581 struct fbtype *fbt; 582 u_int i; 583 584 fbt = &sc->sc_fb.fb_type; 585 586 zx_cross_loadwid(sc, ZX_WID_DBL_8, 0, 0x2c0); 587 zx_cross_loadwid(sc, ZX_WID_DBL_8, 1, 0x30); 588 zx_cross_loadwid(sc, ZX_WID_DBL_8, 2, 0x20); 589 zx_cross_loadwid(sc, ZX_WID_DBL_24, 1, 0x30); 590 591 i = bus_space_read_4(sc->sc_bt, sc->sc_bhzdss1, zd_misc); 592 i |= ZX_SS1_MISC_ENABLE; 593 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss1, zd_misc, i); 594 595 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_wid, 1); 596 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_widclip, 0); 597 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_wmask, 0xffff); 598 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_vclipmin, 0); 599 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_vclipmax, 600 (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 16)); 601 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, 0); 602 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_planemask, 0xffffffff); 603 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP); 604 605 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent, 606 (fbt->fb_width - 1) | ((fbt->fb_height - 1) << 11)); 607 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_addrspace, 608 ZX_ADDRSPC_FONT_OBGR); 609 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fontt, 0); 610 611 for (i = 0; i < 256; i++) { 612 sc->sc_cmap[i] = rasops_cmap[i * 3]; 613 sc->sc_cmap[i + 256] = rasops_cmap[i * 3 + 1]; 614 sc->sc_cmap[i + 512] = rasops_cmap[i * 3 + 2]; 615 } 616 617 zx_cmap_put(sc); 618 } 619 620 static int 621 zx_cross_wait(struct zx_softc *sc) 622 { 623 int i; 624 625 for (i = 300000; i != 0; i--) { 626 if ((bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) & 627 ZX_CROSS_CSR_PROGRESS) == 0) 628 break; 629 DELAY(1); 630 } 631 632 if (i == 0) 633 printf("zx_cross_wait: timed out\n"); 634 635 return (i); 636 } 637 638 static int 639 zx_cross_loadwid(struct zx_softc *sc, u_int type, u_int index, u_int value) 640 { 641 u_int tmp = 0; 642 643 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_WID); 644 645 if (zx_cross_wait(sc)) 646 return (1); 647 648 if (type == ZX_WID_DBL_8) 649 tmp = (index & 0x0f) + 0x40; 650 else if (type == ZX_WID_DBL_24) 651 tmp = index & 0x3f; 652 653 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, 0x5800 + tmp); 654 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_value, value); 655 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_WID); 656 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, 657 ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2); 658 659 return (0); 660 } 661 662 static int 663 zx_cmap_put(struct zx_softc *sc) 664 { 665 const u_char *b; 666 u_int i, t; 667 668 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_CLUT0); 669 670 zx_cross_wait(sc); 671 672 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, 673 ZX_CROSS_TYPE_CLUTDATA); 674 675 for (i = 0, b = sc->sc_cmap; i < 256; i++) { 676 t = b[i]; 677 t |= b[i + 256] << 8; 678 t |= b[i + 512] << 16; 679 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_value, t); 680 } 681 682 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_CLUT0); 683 i = bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr); 684 i = i | ZX_CROSS_CSR_UNK | ZX_CROSS_CSR_UNK2; 685 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, i); 686 return (0); 687 } 688 689 static void 690 zx_cursor_move(struct zx_softc *sc) 691 { 692 int sx, sy, x, y; 693 694 x = sc->sc_curpos.x - sc->sc_curhot.x; 695 y = sc->sc_curpos.y - sc->sc_curhot.y; 696 697 if (x < 0) { 698 sx = min(-x, 32); 699 x = 0; 700 } else 701 sx = 0; 702 703 if (y < 0) { 704 sy = min(-y, 32); 705 y = 0; 706 } else 707 sy = 0; 708 709 if (sx != sc->sc_shiftx || sy != sc->sc_shifty) { 710 sc->sc_shiftx = sx; 711 sc->sc_shifty = sy; 712 zx_cursor_set(sc); 713 } 714 715 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_sxy, 716 ((y & 0x7ff) << 11) | (x & 0x7ff)); 717 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 718 bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x30); 719 720 /* XXX Necessary? */ 721 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 722 bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80); 723 } 724 725 static void 726 zx_cursor_set(struct zx_softc *sc) 727 { 728 int i, j, data; 729 730 if ((sc->sc_flags & ZX_CURSOR) != 0) 731 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 732 bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) & 733 ~0x80); 734 735 for (j = 0; j < 2; j++) { 736 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_type, 0x20 << j); 737 738 for (i = sc->sc_shifty; i < 32; i++) { 739 data = sc->sc_curbits[j][i]; 740 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, 741 data >> sc->sc_shiftx); 742 } 743 for (i = sc->sc_shifty; i != 0; i--) 744 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, 0); 745 } 746 747 if ((sc->sc_flags & ZX_CURSOR) != 0) 748 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 749 bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80); 750 } 751 752 static void 753 zx_cursor_blank(struct zx_softc *sc) 754 { 755 756 sc->sc_flags &= ~ZX_CURSOR; 757 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 758 bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) & ~0x80); 759 } 760 761 static void 762 zx_cursor_unblank(struct zx_softc *sc) 763 { 764 765 sc->sc_flags |= ZX_CURSOR; 766 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 767 bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x80); 768 } 769 770 static void 771 zx_cursor_color(struct zx_softc *sc) 772 { 773 uint8_t tmp; 774 775 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_type, 0x50); 776 777 tmp = sc->sc_curcmap[0] | (sc->sc_curcmap[2] << 8) | 778 (sc->sc_curcmap[4] << 16); 779 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, tmp); 780 781 tmp = sc->sc_curcmap[1] | (sc->sc_curcmap[3] << 8) | 782 (sc->sc_curcmap[5] << 16); 783 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_data, sc->sc_curcmap[1]); 784 785 bus_space_write_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc, 786 bus_space_read_4(sc->sc_bt, sc->sc_bhzcu, zcu_misc) | 0x03); 787 } 788 789 static void 790 zx_blank(device_t dv) 791 { 792 struct zx_softc *sc; 793 794 sc = device_private(dv); 795 796 if ((sc->sc_flags & ZX_BLANKED) != 0) 797 return; 798 sc->sc_flags |= ZX_BLANKED; 799 800 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_VIDEO); 801 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, 802 bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) & 803 ~ZX_CROSS_CSR_ENABLE); 804 } 805 806 static void 807 zx_unblank(device_t dv) 808 { 809 struct zx_softc *sc; 810 811 sc = device_private(dv); 812 813 if ((sc->sc_flags & ZX_BLANKED) == 0) 814 return; 815 sc->sc_flags &= ~ZX_BLANKED; 816 817 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_type, ZX_CROSS_TYPE_VIDEO); 818 bus_space_write_4(sc->sc_bt, sc->sc_bhzx, zx_csr, 819 bus_space_read_4(sc->sc_bt, sc->sc_bhzx, zx_csr) | 820 ZX_CROSS_CSR_ENABLE); 821 } 822 823 static paddr_t 824 zxmmap(dev_t dev, off_t off, int prot) 825 { 826 struct zx_softc *sc; 827 const struct zx_mmo *mm, *mmmax; 828 829 sc = device_lookup_private(&zx_cd, minor(dev)); 830 off = trunc_page(off); 831 mm = zx_mmo; 832 mmmax = mm + sizeof(zx_mmo) / sizeof(zx_mmo[0]); 833 834 for (; mm < mmmax; mm++) 835 if (off >= mm->mo_va && off < mm->mo_va + mm->mo_size) { 836 off = off - mm->mo_va + mm->mo_pa; 837 return (bus_space_mmap(sc->sc_bt, sc->sc_paddr, 838 off, prot, BUS_SPACE_MAP_LINEAR)); 839 } 840 841 return (-1); 842 } 843 844 static void 845 zx_fillrect(struct zx_softc *sc, int x, int y, int w, int h, uint32_t bg, 846 int rop) 847 { 848 849 850 while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) & 851 ZX_CSR_BLT_BUSY) != 0) 852 ; 853 854 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, rop); 855 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, bg); 856 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent, 857 (w - 1) | ((h - 1) << 11)); 858 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fill, 859 x | (y << 11) | 0x80000000); 860 } 861 862 static void 863 zx_copyrect(struct zx_softc *sc, int sx, int sy, int dx, int dy, int w, 864 int h) 865 { 866 uint32_t dir; 867 868 w -= 1; 869 h -= 1; 870 871 if (sy < dy || sx < dx) { 872 dir = 0x80000000; 873 sx += w; 874 sy += h; 875 dx += w; 876 dy += h; 877 } else 878 dir = 0; 879 880 while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) & 881 ZX_CSR_BLT_BUSY) != 0) 882 ; 883 884 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP); 885 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_extent, 886 w | (h << 11) | dir); 887 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_src, sx | (sy << 11)); 888 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_copy, dx | (dy << 11)); 889 } 890 891 static void 892 zx_do_cursor(void *cookie, int on, int row, int col) 893 { 894 struct rasops_info *ri = cookie; 895 struct vcons_screen *scr = ri->ri_hw; 896 struct zx_softc *sc = scr->scr_cookie; 897 int x, y, wi, he; 898 899 wi = ri->ri_font->fontwidth; 900 he = ri->ri_font->fontheight; 901 902 if (ri->ri_flg & RI_CURSOR) { 903 x = ri->ri_ccol * wi + ri->ri_xorigin; 904 y = ri->ri_crow * he + ri->ri_yorigin; 905 zx_fillrect(sc, x, y, wi, he, 0xff000000, 906 ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE | 907 ZX_ATTR_FORCE_WID); 908 ri->ri_flg &= ~RI_CURSOR; 909 } 910 911 ri->ri_crow = row; 912 ri->ri_ccol = col; 913 914 if (on) 915 { 916 x = ri->ri_ccol * wi + ri->ri_xorigin; 917 y = ri->ri_crow * he + ri->ri_yorigin; 918 zx_fillrect(sc, x, y, wi, he, 0xff000000, 919 ZX_ROP_NEW_XOR_OLD | ZX_ATTR_WE_ENABLE | ZX_ATTR_OE_ENABLE | 920 ZX_ATTR_FORCE_WID); 921 ri->ri_flg |= RI_CURSOR; 922 } 923 } 924 925 static void 926 zx_erasecols(void *cookie, int row, int startcol, int ncols, long attr) 927 { 928 struct rasops_info *ri = cookie; 929 struct vcons_screen *scr = ri->ri_hw; 930 struct zx_softc *sc = scr->scr_cookie; 931 int32_t x, y, width, height, bg; 932 933 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 934 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 935 width = ri->ri_font->fontwidth * ncols; 936 height = ri->ri_font->fontheight; 937 bg = ((uint32_t)ri->ri_devcmap[(attr >> 16) & 0xff]) << 24; 938 zx_fillrect(sc, x, y, width, height, bg, ZX_STD_ROP); 939 } 940 941 static void 942 zx_eraserows(void *cookie, int row, int nrows, long attr) 943 { 944 struct rasops_info *ri = cookie; 945 struct vcons_screen *scr = ri->ri_hw; 946 struct zx_softc *sc = scr->scr_cookie; 947 int32_t x, y, width, height, bg; 948 949 if ((row == 0) && (nrows == ri->ri_rows)) { 950 x = y = 0; 951 width = ri->ri_width; 952 height = ri->ri_height; 953 } else { 954 x = ri->ri_xorigin; 955 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 956 width = ri->ri_emuwidth; 957 height = ri->ri_font->fontheight * nrows; 958 } 959 bg = ((uint32_t)ri->ri_devcmap[(attr >> 16) & 0xff]) << 24; 960 zx_fillrect(sc, x, y, width, height, bg, ZX_STD_ROP); 961 } 962 963 static void 964 zx_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 965 { 966 struct rasops_info *ri = cookie; 967 struct vcons_screen *scr = ri->ri_hw; 968 struct zx_softc *sc = scr->scr_cookie; 969 int32_t x, ys, yd, width, height; 970 971 x = ri->ri_xorigin; 972 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 973 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 974 width = ri->ri_emuwidth; 975 height = ri->ri_font->fontheight * nrows; 976 zx_copyrect(sc, x, ys, x, yd, width, height); 977 } 978 979 static void 980 zx_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 981 { 982 struct rasops_info *ri = cookie; 983 struct vcons_screen *scr = ri->ri_hw; 984 struct zx_softc *sc = scr->scr_cookie; 985 int32_t xs, xd, y, width, height; 986 987 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 988 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 989 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 990 width = ri->ri_font->fontwidth * ncols; 991 height = ri->ri_font->fontheight; 992 zx_copyrect(sc, xs, y, xd, y, width, height); 993 } 994 995 static void 996 zx_putchar(void *cookie, int row, int col, u_int uc, long attr) 997 { 998 struct rasops_info *ri = cookie; 999 struct wsdisplay_font *font = PICK_FONT(ri, uc); 1000 struct vcons_screen *scr = ri->ri_hw; 1001 struct zx_softc *sc = scr->scr_cookie; 1002 volatile uint32_t *dp; 1003 uint8_t *fb; 1004 int fs, i, ul; 1005 uint32_t fg, bg; 1006 1007 rasops_unpack_attr(attr, &fg, &bg, &ul); 1008 bg = ((uint32_t)ri->ri_devcmap[bg]) << 24; 1009 fg = ((uint32_t)ri->ri_devcmap[fg]) << 24; 1010 if (uc == ' ') { 1011 int x, y; 1012 1013 x = ri->ri_xorigin + font->fontwidth * col; 1014 y = ri->ri_yorigin + font->fontheight * row; 1015 zx_fillrect(sc, x, y, font->fontwidth, 1016 font->fontheight, bg, ZX_STD_ROP); 1017 return; 1018 } 1019 1020 dp = (volatile uint32_t *)sc->sc_pixels + 1021 ((row * font->fontheight + ri->ri_yorigin) << 11) + 1022 (col * font->fontwidth + ri->ri_xorigin); 1023 fb = (uint8_t *)font->data + (uc - font->firstchar) * 1024 ri->ri_fontscale; 1025 fs = font->stride; 1026 1027 while ((bus_space_read_4(sc->sc_bt, sc->sc_bhzc, zc_csr) & 1028 ZX_CSR_BLT_BUSY) != 0) 1029 ; 1030 1031 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_rop, ZX_STD_ROP); 1032 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_fg, fg); 1033 bus_space_write_4(sc->sc_bt, sc->sc_bhzdss0, zd_bg, bg); 1034 bus_space_write_4(sc->sc_bt, sc->sc_bhzc, zc_fontmsk, 1035 0xffffffff << (32 - font->fontwidth)); 1036 1037 if (font->fontwidth <= 8) { 1038 for (i = font->fontheight; i != 0; i--, dp += 2048) { 1039 *dp = *fb << 24; 1040 fb += fs; 1041 } 1042 } else { 1043 for (i = font->fontheight; i != 0; i--, dp += 2048) { 1044 *dp = *((uint16_t *)fb) << 16; 1045 fb += fs; 1046 } 1047 } 1048 1049 if (ul) { 1050 dp -= 4096; 1051 *dp = 0xffffffff; 1052 } 1053 } 1054 1055 #if NWSDISPLAY > 0 1056 static int 1057 zx_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, 1058 struct lwp *l) 1059 { 1060 /* we'll probably need to add more stuff here */ 1061 struct vcons_data *vd = v; 1062 struct zx_softc *sc = vd->cookie; 1063 struct wsdisplay_fbinfo *wdf; 1064 struct rasops_info *ri = &sc->sc_fb.fb_rinfo; 1065 struct vcons_screen *ms = sc->vd.active; 1066 switch (cmd) { 1067 case WSDISPLAYIO_GTYPE: 1068 *(u_int *)data = WSDISPLAY_TYPE_SUNTCX; 1069 return 0; 1070 case WSDISPLAYIO_GINFO: 1071 wdf = (void *)data; 1072 wdf->height = ri->ri_height; 1073 wdf->width = ri->ri_width; 1074 wdf->depth = ri->ri_depth; 1075 wdf->cmsize = 256; 1076 return 0; 1077 1078 case WSDISPLAYIO_GETCMAP: 1079 return zx_getcmap(sc, 1080 (struct wsdisplay_cmap *)data); 1081 case WSDISPLAYIO_PUTCMAP: 1082 return zx_putcmap(sc, 1083 (struct wsdisplay_cmap *)data); 1084 1085 case WSDISPLAYIO_SMODE: 1086 { 1087 int new_mode = *(int*)data; 1088 if (new_mode != sc->sc_mode) 1089 { 1090 sc->sc_mode = new_mode; 1091 if(new_mode == WSDISPLAYIO_MODE_EMUL) 1092 { 1093 zx_reset(sc); 1094 vcons_redraw_screen(ms); 1095 } 1096 } 1097 } 1098 } 1099 return EPASSTHROUGH; 1100 } 1101 1102 static paddr_t 1103 zx_mmap(void *v, void *vs, off_t offset, int prot) 1104 { 1105 /* I'm not at all sure this is the right thing to do */ 1106 return zxmmap(0, offset, prot); /* assume minor dev 0 for now */ 1107 } 1108 1109 static int 1110 zx_putcmap(struct zx_softc *sc, struct wsdisplay_cmap *cm) 1111 { 1112 u_int index = cm->index; 1113 u_int count = cm->count; 1114 int error,i; 1115 if (index >= 256 || count > 256 || index + count > 256) 1116 return EINVAL; 1117 1118 for (i = 0; i < count; i++) 1119 { 1120 error = copyin(&cm->red[i], 1121 &sc->sc_cmap[index + i], 1); 1122 if (error) 1123 return error; 1124 error = copyin(&cm->green[i], 1125 &sc->sc_cmap[index + i + 256], 1); 1126 if (error) 1127 return error; 1128 error = copyin(&cm->blue[i], 1129 &sc->sc_cmap[index + i + 512], 1); 1130 if (error) 1131 return error; 1132 } 1133 zx_cmap_put(sc); 1134 1135 return 0; 1136 } 1137 1138 static int 1139 zx_getcmap(struct zx_softc *sc, struct wsdisplay_cmap *cm) 1140 { 1141 u_int index = cm->index; 1142 u_int count = cm->count; 1143 int error,i; 1144 1145 if (index >= 256 || count > 256 || index + count > 256) 1146 return EINVAL; 1147 1148 for (i = 0; i < count; i++) 1149 { 1150 error = copyout(&sc->sc_cmap[index + i], 1151 &cm->red[i], 1); 1152 if (error) 1153 return error; 1154 error = copyout(&sc->sc_cmap[index + i + 256], 1155 &cm->green[i], 1); 1156 if (error) 1157 return error; 1158 error = copyout(&sc->sc_cmap[index + i + 256], 1159 &cm->blue[i], 1); 1160 if (error) 1161 return error; 1162 } 1163 1164 return 0; 1165 } 1166 1167 static void 1168 zx_init_screen(void *cookie, struct vcons_screen *scr, 1169 int existing, long *defattr) 1170 { 1171 struct zx_softc *sc = cookie; 1172 struct rasops_info *ri = &scr->scr_ri; 1173 1174 ri->ri_depth = 8; /*sc->sc_fb.fb_type.fb_depth = 32;*/ 1175 ri->ri_width = sc->sc_width; 1176 ri->ri_height = sc->sc_height; 1177 ri->ri_stride = sc->sc_stride; 1178 ri->ri_flg = RI_CENTER; 1179 1180 ri->ri_bits = (void *)sc->sc_pixels; 1181 1182 rasops_init(ri, sc->sc_height/8, sc->sc_width/8); 1183 ri->ri_caps = WSSCREEN_WSCOLORS | WSSCREEN_REVERSE; 1184 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 1185 sc->sc_width / ri->ri_font->fontwidth); 1186 1187 ri->ri_hw = scr; 1188 1189 ri->ri_ops.cursor = zx_do_cursor; 1190 ri->ri_ops.copycols = zx_copycols; 1191 ri->ri_ops.copyrows = zx_copyrows; 1192 ri->ri_ops.erasecols = zx_erasecols; 1193 ri->ri_ops.eraserows = zx_eraserows; 1194 ri->ri_ops.putchar = zx_putchar; 1195 } 1196 1197 #endif /* NWSDISPLAY > 0 */ 1198