1 /* $NetBSD: p9100.c,v 1.23 2005/06/04 04:36:04 tsutsui Exp $ */ 2 3 /*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Matt Thomas. 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 * color display (p9100) driver. 41 * 42 * Does not handle interrupts, even though they can occur. 43 * 44 * XXX should defer colormap updates to vertical retrace interrupts 45 */ 46 47 #include <sys/cdefs.h> 48 __KERNEL_RCSID(0, "$NetBSD: p9100.c,v 1.23 2005/06/04 04:36:04 tsutsui Exp $"); 49 50 #include <sys/param.h> 51 #include <sys/systm.h> 52 #include <sys/buf.h> 53 #include <sys/device.h> 54 #include <sys/ioctl.h> 55 #include <sys/malloc.h> 56 #include <sys/mman.h> 57 #include <sys/tty.h> 58 #include <sys/conf.h> 59 60 #include <machine/bus.h> 61 #include <machine/autoconf.h> 62 63 #include <dev/sun/fbio.h> 64 #include <dev/sun/fbvar.h> 65 #include <dev/sun/btreg.h> 66 #include <dev/sun/btvar.h> 67 68 #include <dev/sbus/p9100reg.h> 69 70 #include <dev/sbus/sbusvar.h> 71 72 /*#include <dev/wscons/wsdisplayvar.h>*/ 73 #include <dev/wscons/wsconsio.h> 74 #include <dev/wsfont/wsfont.h> 75 #include <dev/rasops/rasops.h> 76 77 #include "opt_wsemul.h" 78 #include "rasops_glue.h" 79 80 #include "tctrl.h" 81 #if NTCTRL > 0 82 #include <machine/tctrl.h> 83 #include <sparc/dev/tctrlvar.h>/*XXX*/ 84 #endif 85 86 /* per-display variables */ 87 struct p9100_softc { 88 struct device sc_dev; /* base device */ 89 struct sbusdev sc_sd; /* sbus device */ 90 struct fbdevice sc_fb; /* frame buffer device */ 91 bus_space_tag_t sc_bustag; 92 93 bus_addr_t sc_ctl_paddr; /* phys address description */ 94 bus_size_t sc_ctl_psize; /* for device mmap() */ 95 bus_space_handle_t sc_ctl_memh; /* bus space handle */ 96 97 bus_addr_t sc_cmd_paddr; /* phys address description */ 98 bus_size_t sc_cmd_psize; /* for device mmap() */ 99 bus_space_handle_t sc_cmd_memh; /* bus space handle */ 100 101 bus_addr_t sc_fb_paddr; /* phys address description */ 102 bus_size_t sc_fb_psize; /* for device mmap() */ 103 bus_space_handle_t sc_fb_memh; /* bus space handle */ 104 105 uint32_t sc_junk; 106 uint32_t sc_mono_width; /* for setup_mono */ 107 108 uint32_t sc_width; 109 uint32_t sc_height; /* panel width / height */ 110 uint32_t sc_stride; 111 uint32_t sc_depth; 112 union bt_cmap sc_cmap; /* Brooktree color map */ 113 114 #ifdef PNOZZ_SOFT_PUTCHAR 115 void (*putchar)(void *c, int row, int col, u_int uc, long attr); 116 #endif 117 int sc_mode; 118 uint32_t sc_bg; 119 void (*switchcb)(void *, int, int); 120 void *switchcbarg; 121 struct callout switch_callout; 122 LIST_HEAD(, p9100_screen) screens; 123 struct p9100_screen *active, *wanted; 124 const struct wsscreen_descr *currenttype; 125 126 }; 127 128 struct p9100_screen { 129 struct rasops_info ri; 130 LIST_ENTRY(p9100_screen) next; 131 struct p9100_softc *sc; 132 const struct wsscreen_descr *type; 133 int active; 134 u_int16_t *chars; 135 long *attrs; 136 int dispoffset; 137 int mindispoffset; 138 int maxdispoffset; 139 140 int cursoron; 141 int cursorcol; 142 int cursorrow; 143 int cursordrawn; 144 }; 145 146 static struct p9100_screen p9100_console_screen; 147 148 extern const u_char rasops_cmap[768]; 149 150 struct wsscreen_descr p9100_defscreendesc = { 151 "default", 152 0, 0, 153 NULL, 154 8, 16, 155 WSSCREEN_WSCOLORS, 156 }; 157 158 const struct wsscreen_descr *_p9100_scrlist[] = { 159 &p9100_defscreendesc, 160 /* XXX other formats, graphics screen? */ 161 }; 162 163 struct wsscreen_list p9100_screenlist = { 164 sizeof(_p9100_scrlist) / sizeof(struct wsscreen_descr *), _p9100_scrlist 165 }; 166 167 /* autoconfiguration driver */ 168 static int p9100_sbus_match(struct device *, struct cfdata *, void *); 169 static void p9100_sbus_attach(struct device *, struct device *, void *); 170 171 static void p9100unblank(struct device *); 172 static void p9100_shutdown(void *); 173 174 CFATTACH_DECL(pnozz, sizeof(struct p9100_softc), 175 p9100_sbus_match, p9100_sbus_attach, NULL, NULL); 176 177 extern struct cfdriver pnozz_cd; 178 179 dev_type_open(p9100open); 180 dev_type_ioctl(p9100ioctl); 181 dev_type_mmap(p9100mmap); 182 183 const struct cdevsw pnozz_cdevsw = { 184 p9100open, nullclose, noread, nowrite, p9100ioctl, 185 nostop, notty, nopoll, p9100mmap, nokqfilter, 186 }; 187 188 /* frame buffer generic driver */ 189 static struct fbdriver p9100fbdriver = { 190 p9100unblank, p9100open, nullclose, p9100ioctl, nopoll, 191 p9100mmap, nokqfilter 192 }; 193 194 static void p9100loadcmap(struct p9100_softc *, int, int); 195 static void p9100_set_video(struct p9100_softc *, int); 196 static int p9100_get_video(struct p9100_softc *); 197 static uint32_t p9100_ctl_read_4(struct p9100_softc *, bus_size_t); 198 static void p9100_ctl_write_4(struct p9100_softc *, bus_size_t, uint32_t); 199 uint8_t p9100_ramdac_read(struct p9100_softc *, bus_size_t); 200 void p9100_ramdac_write(struct p9100_softc *, bus_size_t, uint8_t); 201 202 static void p9100_sync(struct p9100_softc *); 203 void p9100_bitblt(struct p9100_softc *, int, int, int, int, int, int, uint32_t); /* coordinates, rasop */ 204 void p9100_rectfill(struct p9100_softc *, int, int, int, int, 205 uint32_t); /* coordinates, colour */ 206 static void p9100_init_engine(struct p9100_softc *); 207 void p9100_setup_mono(struct p9100_softc *, int, int, int, int, 208 uint32_t, uint32_t); 209 void p9100_feed_line(struct p9100_softc *, int, uint8_t *); 210 static void p9100_set_color_reg(struct p9100_softc *, int, int32_t); 211 212 void p9100_cursor(void *, int, int, int); 213 int p9100_mapchar(void *, int, u_int *); 214 void p9100_putchar(void *, int, int, u_int, long); 215 void p9100_copycols(void *, int, int, int, int); 216 void p9100_erasecols(void *, int, int, int, long); 217 void p9100_copyrows(void *, int, int, int); 218 void p9100_eraserows(void *, int, int, long); 219 int p9100_allocattr(void *, int, int, int, long *); 220 221 void p9100_scroll(void *, void *, int); 222 223 int p9100_putcmap(struct p9100_softc *, struct wsdisplay_cmap *); 224 int p9100_getcmap(struct p9100_softc *, struct wsdisplay_cmap *); 225 int p9100_ioctl(void *, u_long, caddr_t, int, struct proc *); 226 paddr_t p9100_mmap(void *, off_t, int); 227 int p9100_alloc_screen(void *, const struct wsscreen_descr *, void **, 228 int *, int *, long *); 229 void p9100_free_screen(void *, void *); 230 int p9100_show_screen(void *, void *, int, void (*)(void *, int, int), 231 void *); 232 void p9100_switch_screen(struct p9100_softc *); 233 void p9100_restore_screen(struct p9100_screen *, 234 const struct wsscreen_descr *, u_int16_t *); 235 void p9100_clearscreen(struct p9100_softc *); 236 237 int p9100_load_font(void *, void *, struct wsdisplay_font *); 238 239 void p9100_init_screen(struct p9100_softc *, struct p9100_screen *, int, 240 long *); 241 242 int p9100_intr(void *); 243 244 struct wsdisplay_accessops p9100_accessops = { 245 p9100_ioctl, 246 p9100_mmap, 247 p9100_alloc_screen, 248 p9100_free_screen, 249 p9100_show_screen, 250 NULL, /* load_font */ 251 NULL, /* polls */ 252 NULL, /* getwschar */ 253 NULL, /* putwschar */ 254 NULL, /* scroll */ 255 NULL, /* getborder */ 256 NULL /* setborder */ 257 }; 258 259 /* 260 * Match a p9100. 261 */ 262 static int 263 p9100_sbus_match(struct device *parent, struct cfdata *cf, void *aux) 264 { 265 struct sbus_attach_args *sa = aux; 266 267 return (strcmp("p9100", sa->sa_name) == 0); 268 } 269 270 271 /* 272 * Attach a display. We need to notice if it is the console, too. 273 */ 274 static void 275 p9100_sbus_attach(struct device *parent, struct device *self, void *args) 276 { 277 struct p9100_softc *sc = (struct p9100_softc *)self; 278 struct sbus_attach_args *sa = args; 279 struct fbdevice *fb = &sc->sc_fb; 280 int isconsole; 281 int node; 282 int i, j; 283 284 #if NWSDISPLAY > 0 285 struct wsemuldisplaydev_attach_args aa; 286 struct rasops_info *ri; 287 unsigned long defattr; 288 #endif 289 290 /* Remember cookies for p9100_mmap() */ 291 sc->sc_bustag = sa->sa_bustag; 292 sc->sc_ctl_paddr = sbus_bus_addr(sa->sa_bustag, 293 sa->sa_reg[0].oa_space, sa->sa_reg[0].oa_base); 294 sc->sc_ctl_psize = 0x8000;/*(bus_size_t)sa->sa_reg[0].oa_size;*/ 295 296 sc->sc_cmd_paddr = sbus_bus_addr(sa->sa_bustag, 297 sa->sa_reg[1].oa_space, sa->sa_reg[1].oa_base); 298 sc->sc_cmd_psize = (bus_size_t)sa->sa_reg[1].oa_size; 299 300 sc->sc_fb_paddr = sbus_bus_addr(sa->sa_bustag, 301 sa->sa_reg[2].oa_space, sa->sa_reg[2].oa_base); 302 sc->sc_fb_psize = (bus_size_t)sa->sa_reg[2].oa_size; 303 304 fb->fb_driver = &p9100fbdriver; 305 fb->fb_device = &sc->sc_dev; 306 fb->fb_flags = sc->sc_dev.dv_cfdata->cf_flags & FB_USERMASK; 307 #ifdef PNOZZ_EMUL_CG3 308 fb->fb_type.fb_type = FBTYPE_SUN3COLOR; 309 #else 310 fb->fb_type.fb_type = FBTYPE_P9100; 311 #endif 312 fb->fb_pixels = NULL; 313 314 sc->sc_mode = WSDISPLAYIO_MODE_EMUL; 315 #ifdef PNOZZ_SOFT_PUTCHAR 316 sc->putchar = NULL; 317 #endif 318 319 LIST_INIT(&sc->screens); 320 sc->active = NULL; 321 sc->currenttype = &p9100_defscreendesc; 322 callout_init(&sc->switch_callout); 323 324 node = sa->sa_node; 325 isconsole = fb_is_console(node); 326 if (!isconsole) { 327 printf("\n%s: fatal error: PROM didn't configure device\n", 328 self->dv_xname); 329 return; 330 } 331 332 /* 333 * When the ROM has mapped in a p9100 display, the address 334 * maps only the video RAM, so in any case we have to map the 335 * registers ourselves. We only need the video RAM if we are 336 * going to print characters via rconsole. 337 */ 338 if (sbus_bus_map(sc->sc_bustag, 339 sa->sa_reg[0].oa_space, 340 sa->sa_reg[0].oa_base, 341 /* 342 * XXX for some reason the SBus resources don't cover 343 * all registers, so we just map what we need 344 */ 345 /*sc->sc_ctl_psize*/ 0x8000, 346 BUS_SPACE_MAP_LINEAR, &sc->sc_ctl_memh) != 0) { 347 printf("%s: cannot map control registers\n", self->dv_xname); 348 return; 349 } 350 351 if (sa->sa_npromvaddrs != 0) 352 fb->fb_pixels = (caddr_t)sa->sa_promvaddrs[0]; 353 354 if (fb->fb_pixels == NULL) { 355 if (sbus_bus_map(sc->sc_bustag, 356 sa->sa_reg[2].oa_space, 357 sa->sa_reg[2].oa_base, 358 sc->sc_fb_psize, 359 BUS_SPACE_MAP_LINEAR, &sc->sc_fb_memh) != 0) { 360 printf("%s: cannot map framebuffer\n", self->dv_xname); 361 return; 362 } 363 fb->fb_pixels = (char *)sc->sc_fb_memh; 364 } else { 365 sc->sc_fb_memh = (bus_space_handle_t) fb->fb_pixels; 366 } 367 368 i = p9100_ctl_read_4(sc, 0x0004); 369 switch ((i >> 26) & 7) { 370 case 5: fb->fb_type.fb_depth = 32; break; 371 case 7: fb->fb_type.fb_depth = 24; break; 372 case 3: fb->fb_type.fb_depth = 16; break; 373 case 2: fb->fb_type.fb_depth = 8; break; 374 default: { 375 panic("pnozz: can't determine screen depth (0x%02x)", i); 376 } 377 } 378 sc->sc_depth = (fb->fb_type.fb_depth >> 3); 379 380 /* XXX for some reason I get a kernel trap with this */ 381 sc->sc_width = prom_getpropint(node, "width", 800); 382 sc->sc_height = prom_getpropint(node, "height", 600); 383 384 sc->sc_stride = prom_getpropint(node, "linebytes", sc->sc_width * 385 (fb->fb_type.fb_depth >> 3)); 386 387 p9100_init_engine(sc); 388 389 fb_setsize_obp(fb, fb->fb_type.fb_depth, sc->sc_width, sc->sc_height, 390 node); 391 392 sbus_establish(&sc->sc_sd, &sc->sc_dev); 393 394 fb->fb_type.fb_size = fb->fb_type.fb_height * fb->fb_linebytes; 395 printf(": rev %d, %dx%d, depth %d mem %x", 396 (i & 7), fb->fb_type.fb_width, fb->fb_type.fb_height, 397 fb->fb_type.fb_depth, (unsigned int)sc->sc_fb_psize); 398 399 fb->fb_type.fb_cmsize = prom_getpropint(node, "cmsize", 256); 400 if ((1 << fb->fb_type.fb_depth) != fb->fb_type.fb_cmsize) 401 printf(", %d entry colormap", fb->fb_type.fb_cmsize); 402 403 /* Initialize the default color map. */ 404 /*bt_initcmap(&sc->sc_cmap, 256);*/ 405 j = 0; 406 for (i = 0; i < 256; i++) { 407 sc->sc_cmap.cm_map[i][0] = rasops_cmap[j]; 408 j++; 409 sc->sc_cmap.cm_map[i][1] = rasops_cmap[j]; 410 j++; 411 sc->sc_cmap.cm_map[i][2] = rasops_cmap[j]; 412 j++; 413 } 414 p9100loadcmap(sc, 0, 256); 415 416 /* make sure we are not blanked */ 417 if (isconsole) 418 p9100_set_video(sc, 1); 419 420 if (shutdownhook_establish(p9100_shutdown, sc) == NULL) { 421 panic("%s: could not establish shutdown hook", 422 sc->sc_dev.dv_xname); 423 } 424 425 if (isconsole) { 426 printf(" (console)\n"); 427 #ifdef RASTERCONSOLE 428 /*p9100loadcmap(sc, 255, 1);*/ 429 fbrcons_init(fb); 430 #endif 431 } else 432 printf("\n"); 433 434 #if NWSDISPLAY > 0 435 wsfont_init(); 436 437 p9100_init_screen(sc, &p9100_console_screen, 1, &defattr); 438 p9100_console_screen.active = 1; 439 sc->active = &p9100_console_screen; 440 ri = &p9100_console_screen.ri; 441 442 p9100_defscreendesc.nrows = ri->ri_rows; 443 p9100_defscreendesc.ncols = ri->ri_cols; 444 p9100_defscreendesc.textops = &ri->ri_ops; 445 p9100_defscreendesc.capabilities = ri->ri_caps; 446 447 if(isconsole) { 448 wsdisplay_cnattach(&p9100_defscreendesc, ri, 0, 0, defattr); 449 } 450 451 sc->sc_bg = (defattr >> 16) & 0xff; 452 453 p9100_clearscreen(sc); 454 455 aa.console = isconsole; 456 aa.scrdata = &p9100_screenlist; 457 aa.accessops = &p9100_accessops; 458 aa.accesscookie = sc; 459 460 config_found(self, &aa, wsemuldisplaydevprint); 461 #endif 462 /* attach the fb */ 463 fb_attach(fb, isconsole); 464 465 #if 0 466 p9100_rectfill(sc, 10, 10, 200, 200, 0x01); 467 p9100_rectfill(sc, 210, 10, 200, 200, 0xff); 468 p9100_bitblt(sc, 10, 10, 110, 110, 400, 200, ROP_SRC); 469 #endif 470 #if 0 471 p9100_setup_mono(sc, 750, 500, 32, 1, 1, 6); 472 { 473 uint32_t ev = 0xc3000000, odd = 0x3c000000; 474 for (i = 0; i < 16; i++) { 475 p9100_feed_line(sc, 1, (uint8_t*)&ev); 476 p9100_feed_line(sc, 1, (uint8_t*)&odd); 477 } 478 } 479 delay(4000000); 480 #endif 481 } 482 483 static void 484 p9100_shutdown(arg) 485 void *arg; 486 { 487 struct p9100_softc *sc = arg; 488 489 #ifdef RASTERCONSOLE 490 sc->sc_cmap.cm_map[0][0] = 0xff; 491 sc->sc_cmap.cm_map[0][1] = 0xff; 492 sc->sc_cmap.cm_map[0][2] = 0xff; 493 sc->sc_cmap.cm_map[1][0] = 0; 494 sc->sc_cmap.cm_map[1][1] = 0; 495 sc->sc_cmap.cm_map[1][2] = 0x00; 496 p9100loadcmap(sc, 0, 2); 497 sc->sc_cmap.cm_map[255][0] = 0; 498 sc->sc_cmap.cm_map[255][1] = 0; 499 sc->sc_cmap.cm_map[255][2] = 0; 500 p9100loadcmap(sc, 255, 1); 501 #endif 502 p9100_set_video(sc, 1); 503 } 504 505 int 506 p9100open(dev_t dev, int flags, int mode, struct proc *p) 507 { 508 int unit = minor(dev); 509 510 if (unit >= pnozz_cd.cd_ndevs || pnozz_cd.cd_devs[unit] == NULL) 511 return (ENXIO); 512 return (0); 513 } 514 515 int 516 p9100ioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) 517 { 518 struct p9100_softc *sc = pnozz_cd.cd_devs[minor(dev)]; 519 struct fbgattr *fba; 520 int error; 521 522 switch (cmd) { 523 524 case FBIOGTYPE: 525 *(struct fbtype *)data = sc->sc_fb.fb_type; 526 break; 527 528 case FBIOGATTR: 529 fba = (struct fbgattr *)data; 530 fba->real_type = sc->sc_fb.fb_type.fb_type; 531 fba->owner = 0; /* XXX ??? */ 532 fba->fbtype = sc->sc_fb.fb_type; 533 fba->sattr.flags = 0; 534 fba->sattr.emu_type = sc->sc_fb.fb_type.fb_type; 535 fba->sattr.dev_specific[0] = -1; 536 fba->emu_types[0] = sc->sc_fb.fb_type.fb_type; 537 fba->emu_types[1] = -1; 538 break; 539 540 case FBIOGETCMAP: 541 #define p ((struct fbcmap *)data) 542 return (bt_getcmap(p, &sc->sc_cmap, 256, 1)); 543 544 case FBIOPUTCMAP: 545 /* copy to software map */ 546 error = bt_putcmap(p, &sc->sc_cmap, 256, 1); 547 if (error) 548 return (error); 549 /* now blast them into the chip */ 550 /* XXX should use retrace interrupt */ 551 p9100loadcmap(sc, p->index, p->count); 552 #undef p 553 break; 554 555 case FBIOGVIDEO: 556 *(int *)data = p9100_get_video(sc); 557 break; 558 559 case FBIOSVIDEO: 560 p9100_set_video(sc, *(int *)data); 561 break; 562 563 default: 564 return (ENOTTY); 565 } 566 return (0); 567 } 568 569 static uint32_t 570 p9100_ctl_read_4(struct p9100_softc *sc, bus_size_t off) 571 { 572 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off); 573 return bus_space_read_4(sc->sc_bustag, sc->sc_ctl_memh, off); 574 } 575 576 static void 577 p9100_ctl_write_4(struct p9100_softc *sc, bus_size_t off, uint32_t v) 578 { 579 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off); 580 bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, v); 581 } 582 583 /* wait until the engine is idle */ 584 static void 585 p9100_sync(struct p9100_softc *sc) 586 { 587 while((p9100_ctl_read_4(sc, ENGINE_STATUS) & 588 (ENGINE_BUSY | BLITTER_BUSY)) != 0); 589 } 590 591 static void 592 p9100_set_color_reg(struct p9100_softc *sc, int reg, int32_t col) 593 { 594 uint32_t out; 595 596 switch(sc->sc_depth) 597 { 598 case 1: /* 8 bit */ 599 out = (col << 8) | col; 600 out |= out << 16; 601 break; 602 case 2: /* 16 bit */ 603 out = col | (col << 16); 604 break; 605 default: 606 out = col; 607 } 608 p9100_ctl_write_4(sc, reg, out); 609 } 610 611 /* initialize the drawing engine */ 612 static void 613 p9100_init_engine(struct p9100_softc *sc) 614 { 615 /* reset clipping rectangles */ 616 uint32_t rmax = ((sc->sc_width & 0x3fff) << 16) | 617 (sc->sc_height & 0x3fff); 618 619 p9100_ctl_write_4(sc, WINDOW_OFFSET, 0); 620 p9100_ctl_write_4(sc, WINDOW_MIN, 0); 621 p9100_ctl_write_4(sc, WINDOW_MAX, rmax); 622 p9100_ctl_write_4(sc, BYTE_CLIP_MIN, 0); 623 p9100_ctl_write_4(sc, BYTE_CLIP_MAX, rmax); 624 p9100_ctl_write_4(sc, DRAW_MODE, 0); 625 p9100_ctl_write_4(sc, PLANE_MASK, 0xffffffff); 626 p9100_ctl_write_4(sc, PATTERN0, 0xffffffff); 627 p9100_ctl_write_4(sc, PATTERN1, 0xffffffff); 628 p9100_ctl_write_4(sc, PATTERN2, 0xffffffff); 629 p9100_ctl_write_4(sc, PATTERN3, 0xffffffff); 630 } 631 632 /* screen-to-screen blit */ 633 void 634 p9100_bitblt(struct p9100_softc *sc, int xs, int ys, int xd, int yd, int wi, 635 int he, uint32_t rop) 636 { 637 uint32_t src, dst, srcw, dstw, junk; 638 639 src = ((xs & 0x3fff) << 16) | (ys & 0x3fff); 640 dst = ((xd & 0x3fff) << 16) | (yd & 0x3fff); 641 srcw = (((xs + wi - 1) & 0x3fff) << 16) | ((ys + he - 1) & 0x3fff); 642 dstw = (((xd + wi - 1) & 0x3fff) << 16) | ((yd + he - 1) & 0x3fff); 643 p9100_sync(sc); 644 p9100_ctl_write_4(sc, RASTER_OP, rop); 645 646 p9100_ctl_write_4(sc, ABS_XY0, src); 647 648 p9100_ctl_write_4(sc, ABS_XY1, srcw); 649 p9100_ctl_write_4(sc, ABS_XY2, dst); 650 p9100_ctl_write_4(sc, ABS_XY3, dstw); 651 junk = p9100_ctl_read_4(sc, COMMAND_BLIT); 652 } 653 654 /* solid rectangle fill */ 655 void 656 p9100_rectfill(struct p9100_softc *sc, int xs, int ys, int wi, int he, uint32_t col) 657 { 658 uint32_t src, srcw, junk; 659 660 src = ((xs & 0x3fff) << 16) | (ys & 0x3fff); 661 srcw = (((xs + wi) & 0x3fff) << 16) | ((ys + he) & 0x3fff); 662 p9100_sync(sc); 663 p9100_set_color_reg(sc, FOREGROUND_COLOR, col); 664 p9100_set_color_reg(sc, BACKGROUND_COLOR, col); 665 p9100_ctl_write_4(sc, RASTER_OP, ROP_PAT); 666 p9100_ctl_write_4(sc, COORD_INDEX, 0); 667 p9100_ctl_write_4(sc, RECT_RTW_XY, src); 668 p9100_ctl_write_4(sc, RECT_RTW_XY, srcw); 669 junk=p9100_ctl_read_4(sc, COMMAND_QUAD); 670 } 671 672 /* setup for mono->colour expansion */ 673 void 674 p9100_setup_mono(struct p9100_softc *sc, int x, int y, int wi, int he, 675 uint32_t fg, uint32_t bg) 676 { 677 p9100_sync(sc); 678 /* 679 * this doesn't make any sense to me either, but for some reason the 680 * chip applies the foreground colour to 0 pixels 681 */ 682 683 p9100_set_color_reg(sc,FOREGROUND_COLOR,bg); 684 p9100_set_color_reg(sc,BACKGROUND_COLOR,fg); 685 686 p9100_ctl_write_4(sc, RASTER_OP, ROP_SRC); 687 p9100_ctl_write_4(sc, ABS_X0, x); 688 p9100_ctl_write_4(sc, ABS_XY1, (x << 16) | (y & 0xFFFFL)); 689 p9100_ctl_write_4(sc, ABS_X2, (x + wi)); 690 p9100_ctl_write_4(sc, ABS_Y3, he); 691 /* now feed the data into the chip */ 692 sc->sc_mono_width = wi; 693 } 694 695 /* write monochrome data to the screen through the blitter */ 696 void 697 p9100_feed_line(struct p9100_softc *sc, int count, uint8_t *data) 698 { 699 int i; 700 uint32_t latch = 0, bork; 701 int shift = 24; 702 int to_go = sc->sc_mono_width; 703 704 for (i = 0; i < count; i++) { 705 bork = data[i]; 706 latch |= (bork << shift); 707 if (shift == 0) { 708 /* check how many bits are significant */ 709 if (to_go > 31) { 710 p9100_ctl_write_4(sc, (PIXEL_1 + 711 (31 << 2)), latch); 712 to_go -= 32; 713 } else 714 { 715 p9100_ctl_write_4(sc, (PIXEL_1 + 716 ((to_go - 1) << 2)), latch); 717 to_go = 0; 718 } 719 latch = 0; 720 shift = 24; 721 } else 722 shift -= 8; 723 } 724 if (shift != 24) 725 p9100_ctl_write_4(sc, (PIXEL_1 + ((to_go - 1) << 2)), latch); 726 } 727 728 void 729 p9100_clearscreen(struct p9100_softc *sc) 730 { 731 p9100_rectfill(sc, 0, 0, sc->sc_width, sc->sc_height, sc->sc_bg); 732 } 733 734 uint8_t 735 p9100_ramdac_read(struct p9100_softc *sc, bus_size_t off) 736 { 737 sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG); 738 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off); 739 return ((bus_space_read_4(sc->sc_bustag, 740 sc->sc_ctl_memh, off) >> 16) & 0xff); 741 } 742 743 void 744 p9100_ramdac_write(struct p9100_softc *sc, bus_size_t off, uint8_t v) 745 { 746 sc->sc_junk = p9100_ctl_read_4(sc, PWRUP_CNFG); 747 sc->sc_junk = bus_space_read_4(sc->sc_bustag, sc->sc_fb_memh, off); 748 bus_space_write_4(sc->sc_bustag, sc->sc_ctl_memh, off, 749 ((uint32_t)v) << 16); 750 } 751 752 /* 753 * Undo the effect of an FBIOSVIDEO that turns the video off. 754 */ 755 static void 756 p9100unblank(struct device *dev) 757 { 758 p9100_set_video((struct p9100_softc *)dev, 1); 759 } 760 761 static void 762 p9100_set_video(struct p9100_softc *sc, int enable) 763 { 764 u_int32_t v = p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1); 765 766 if (enable) 767 v |= VIDEO_ENABLED; 768 else 769 v &= ~VIDEO_ENABLED; 770 p9100_ctl_write_4(sc, SCRN_RPNT_CTL_1, v); 771 #if NTCTRL > 0 772 /* Turn On/Off the TFT if we know how. 773 */ 774 tadpole_set_video(enable); 775 #endif 776 } 777 778 static int 779 p9100_get_video(struct p9100_softc *sc) 780 { 781 return (p9100_ctl_read_4(sc, SCRN_RPNT_CTL_1) & VIDEO_ENABLED) != 0; 782 } 783 784 /* 785 * Load a subset of the current (new) colormap into the IBM RAMDAC. 786 */ 787 static void 788 p9100loadcmap(struct p9100_softc *sc, int start, int ncolors) 789 { 790 int i; 791 p9100_ramdac_write(sc, DAC_CMAP_WRIDX, start); 792 793 for (i=0;i<ncolors;i++) { 794 p9100_ramdac_write(sc, DAC_CMAP_DATA, 795 sc->sc_cmap.cm_map[i + start][0]); 796 p9100_ramdac_write(sc, DAC_CMAP_DATA, 797 sc->sc_cmap.cm_map[i + start][1]); 798 p9100_ramdac_write(sc, DAC_CMAP_DATA, 799 sc->sc_cmap.cm_map[i + start][2]); 800 } 801 } 802 803 /* 804 * Return the address that would map the given device at the given 805 * offset, allowing for the given protection, or return -1 for error. 806 */ 807 paddr_t 808 p9100mmap(dev_t dev, off_t off, int prot) 809 { 810 struct p9100_softc *sc = pnozz_cd.cd_devs[minor(dev)]; 811 812 if (off & PGOFSET) 813 panic("p9100mmap"); 814 if (off < 0) 815 return (-1); 816 817 #ifdef PNOZZ_EMUL_CG3 818 #define CG3_MMAP_OFFSET 0x04000000 819 /* Make Xsun think we are a CG3 (SUN3COLOR) 820 */ 821 if (off >= CG3_MMAP_OFFSET && off < CG3_MMAP_OFFSET + sc->sc_fb_psize) { 822 off -= CG3_MMAP_OFFSET; 823 return (bus_space_mmap(sc->sc_bustag, 824 sc->sc_fb_paddr, 825 off, 826 prot, 827 BUS_SPACE_MAP_LINEAR)); 828 } 829 #endif 830 831 if (off >= sc->sc_fb_psize + sc->sc_ctl_psize + sc->sc_cmd_psize) 832 return (-1); 833 834 if (off < sc->sc_fb_psize) { 835 return (bus_space_mmap(sc->sc_bustag, 836 sc->sc_fb_paddr, 837 off, 838 prot, 839 BUS_SPACE_MAP_LINEAR)); 840 } 841 off -= sc->sc_fb_psize; 842 if (off < sc->sc_ctl_psize) { 843 return (bus_space_mmap(sc->sc_bustag, 844 sc->sc_ctl_paddr, 845 off, 846 prot, 847 BUS_SPACE_MAP_LINEAR)); 848 } 849 off -= sc->sc_ctl_psize; 850 851 return (bus_space_mmap(sc->sc_bustag, 852 sc->sc_cmd_paddr, 853 off, 854 prot, 855 BUS_SPACE_MAP_LINEAR)); 856 } 857 858 /* wscons stuff */ 859 860 void 861 p9100_switch_screen(struct p9100_softc *sc) 862 { 863 struct p9100_screen *scr, *oldscr; 864 865 scr = sc->wanted; 866 if (!scr) { 867 printf("p9100_switch_screen: disappeared\n"); 868 (*sc->switchcb)(sc->switchcbarg, EIO, 0); 869 return; 870 } 871 oldscr = sc->active; /* can be NULL! */ 872 #ifdef DIAGNOSTIC 873 if (oldscr) { 874 if (!oldscr->active) 875 panic("p9100_switch_screen: not active"); 876 } 877 #endif 878 if (scr == oldscr) 879 return; 880 881 #ifdef DIAGNOSTIC 882 if (scr->active) 883 panic("p9100_switch_screen: active"); 884 #endif 885 886 if (oldscr) 887 oldscr->active = 0; 888 #ifdef notyet 889 if (sc->currenttype != type) { 890 p9100_set_screentype(sc, type); 891 sc->currenttype = type; 892 } 893 #endif 894 895 /* Clear the entire screen. */ 896 897 scr->active = 1; 898 p9100_restore_screen(scr, &p9100_defscreendesc, scr->chars); 899 900 sc->active = scr; 901 902 scr->ri.ri_ops.cursor(scr, scr->cursoron, scr->cursorrow, 903 scr->cursorcol); 904 905 sc->wanted = 0; 906 if (sc->switchcb) 907 (*sc->switchcb)(sc->switchcbarg, 0, 0); 908 } 909 910 void 911 p9100_restore_screen(struct p9100_screen *scr, 912 const struct wsscreen_descr *type, u_int16_t *mem) 913 { 914 int i, j, offset = 0; 915 uint16_t *charptr = scr->chars; 916 long *attrptr = scr->attrs; 917 918 p9100_clearscreen(scr->sc); 919 for (i = 0; i < scr->ri.ri_rows; i++) { 920 for (j = 0; j < scr->ri.ri_cols; j++) { 921 p9100_putchar(scr, i, j, charptr[offset], 922 attrptr[offset]); 923 offset++; 924 } 925 } 926 scr->cursordrawn = 0; 927 } 928 929 void 930 p9100_cursor(void *cookie, int on, int row, int col) 931 { 932 struct rasops_info *ri = cookie; 933 struct p9100_screen *scr = ri->ri_hw; 934 struct p9100_softc *sc = scr->sc; 935 int x, y, wi,he; 936 937 wi = ri->ri_font->fontwidth; 938 he = ri->ri_font->fontheight; 939 940 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 941 x = scr->cursorcol * wi + ri->ri_xorigin; 942 y = scr->cursorrow * he + ri->ri_yorigin; 943 if (scr->cursordrawn) { 944 p9100_bitblt(sc, x, y, x, y, wi, he, (ROP_SRC ^ 0xff)); 945 scr->cursordrawn = 0; 946 } 947 scr->cursorrow = row; 948 scr->cursorcol = col; 949 if ((scr->cursoron = on) != 0) 950 { 951 x = scr->cursorcol * wi + ri->ri_xorigin; 952 y = scr->cursorrow * he + ri->ri_yorigin; 953 p9100_bitblt(sc, x, y, x, y, wi, he, (ROP_SRC ^ 0xff)); 954 scr->cursordrawn = 1; 955 } 956 } else { 957 scr->cursoron = on; 958 scr->cursorrow = row; 959 scr->cursorcol = col; 960 scr->cursordrawn = 0; 961 } 962 } 963 964 #if 0 965 int 966 p9100_mapchar(void *cookie, int uni, u_int *index) 967 { 968 return 0; 969 } 970 #endif 971 972 void 973 p9100_putchar(void *cookie, int row, int col, u_int c, long attr) 974 { 975 struct rasops_info *ri = cookie; 976 struct p9100_screen *scr = ri->ri_hw; 977 struct p9100_softc *sc = scr->sc; 978 int pos; 979 980 if ((row >= 0) && (row < ri->ri_rows) && (col >= 0) && 981 (col < ri->ri_cols)) { 982 pos = col + row * ri->ri_cols; 983 scr->attrs[pos] = attr; 984 scr->chars[pos] = c; 985 986 #ifdef PNOZZ_SOFT_PUTCHAR 987 if ((sc->putchar != NULL) && ( scr->active) && 988 (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 989 p9100_sync(sc); 990 sc->putchar(cookie, row, col, c, attr); 991 } 992 #else 993 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 994 int fg, bg, uc, i; 995 uint8_t *data; 996 int x, y, wi,he; 997 998 wi = ri->ri_font->fontwidth; 999 he = ri->ri_font->fontheight; 1000 1001 if (!CHAR_IN_FONT(c, ri->ri_font)) 1002 return; 1003 bg = (u_char)ri->ri_devcmap[(attr >> 16) & 0xff]; 1004 fg = (u_char)ri->ri_devcmap[(attr >> 24) & 0xff]; 1005 x = ri->ri_xorigin + col * wi; 1006 y = ri->ri_yorigin + row * he; 1007 if (c == 0x20) { 1008 p9100_rectfill(sc, x, y, wi, he, bg); 1009 } else { 1010 uc = c-ri->ri_font->firstchar; 1011 data = (uint8_t *)ri->ri_font->data + uc * 1012 ri->ri_fontscale; 1013 1014 p9100_setup_mono(sc, x, y, wi, 1, fg, bg); 1015 for (i = 0; i < he; i++) { 1016 p9100_feed_line(sc, ri->ri_font->stride, 1017 data); 1018 data += ri->ri_font->stride; 1019 } 1020 /*p9100_sync(sc);*/ 1021 } 1022 } 1023 #endif 1024 } 1025 } 1026 1027 void 1028 p9100_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1029 { 1030 struct rasops_info *ri = cookie; 1031 struct p9100_screen *scr = ri->ri_hw; 1032 struct p9100_softc *sc = scr->sc; 1033 int32_t xs, xd, y, width, height; 1034 int from = srccol + row * ri->ri_cols; 1035 int to = dstcol + row * ri->ri_cols; 1036 1037 memmove(&scr->attrs[to], &scr->attrs[from], ncols * sizeof(long)); 1038 memmove(&scr->chars[to], &scr->chars[from], ncols * sizeof(uint16_t)); 1039 1040 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1041 xs = ri->ri_xorigin + ri->ri_font->fontwidth * srccol; 1042 xd = ri->ri_xorigin + ri->ri_font->fontwidth * dstcol; 1043 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1044 width = ri->ri_font->fontwidth * ncols; 1045 height = ri->ri_font->fontheight; 1046 p9100_bitblt(sc, xs, y, xd, y, width, height, ROP_SRC); 1047 } 1048 } 1049 1050 void 1051 p9100_erasecols(void *cookie, int row, int startcol, int ncols, long fillattr) 1052 { 1053 struct rasops_info *ri = cookie; 1054 struct p9100_screen *scr = ri->ri_hw; 1055 struct p9100_softc *sc = scr->sc; 1056 int32_t x, y, width, height, bg; 1057 int start = startcol + row * ri->ri_cols; 1058 int end = start + ncols, i; 1059 1060 for (i = start; i < end; i++) { 1061 scr->attrs[i] = fillattr; 1062 scr->chars[i] = 0x20; 1063 } 1064 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1065 x = ri->ri_xorigin + ri->ri_font->fontwidth * startcol; 1066 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1067 width = ri->ri_font->fontwidth * ncols; 1068 height = ri->ri_font->fontheight; 1069 bg = (fillattr >> 16) & 0xff; 1070 p9100_rectfill(sc, x, y, width, height, bg); 1071 } 1072 } 1073 1074 void 1075 p9100_copyrows(void *cookie, int srcrow, int dstrow, int nrows) 1076 { 1077 struct rasops_info *ri = cookie; 1078 struct p9100_screen *scr = ri->ri_hw; 1079 struct p9100_softc *sc = scr->sc; 1080 int32_t x, ys, yd, width, height; 1081 int from, to, len; 1082 1083 from = ri->ri_cols * srcrow; 1084 to = ri->ri_cols * dstrow; 1085 len = ri->ri_cols * nrows; 1086 1087 memmove(&scr->attrs[to], &scr->attrs[from], len * sizeof(long)); 1088 memmove(&scr->chars[to], &scr->chars[from], len * sizeof(uint16_t)); 1089 1090 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1091 x = ri->ri_xorigin; 1092 ys = ri->ri_yorigin + ri->ri_font->fontheight * srcrow; 1093 yd = ri->ri_yorigin + ri->ri_font->fontheight * dstrow; 1094 width = ri->ri_emuwidth; 1095 height = ri->ri_font->fontheight * nrows; 1096 p9100_bitblt(sc, x, ys, x, yd, width, height, ROP_SRC); 1097 } 1098 } 1099 1100 void 1101 p9100_eraserows(void *cookie, int row, int nrows, long fillattr) 1102 { 1103 struct rasops_info *ri = cookie; 1104 struct p9100_screen *scr = ri->ri_hw; 1105 struct p9100_softc *sc = scr->sc; 1106 int32_t x,y,width,height,bg; 1107 int start, end, i; 1108 1109 start = ri->ri_cols * row; 1110 end = ri->ri_cols * (row + nrows); 1111 1112 for (i = start; i < end; i++) { 1113 scr->attrs[i] = fillattr; 1114 scr->chars[i] = 0x20; 1115 } 1116 1117 if ((scr->active) && (sc->sc_mode == WSDISPLAYIO_MODE_EMUL)) { 1118 x = ri->ri_xorigin; 1119 y = ri->ri_yorigin + ri->ri_font->fontheight * row; 1120 width = ri->ri_emuwidth; 1121 height = ri->ri_font->fontheight * nrows; 1122 bg = (fillattr >> 16) & 0xff; 1123 p9100_rectfill(sc, x, y, width, height, bg); 1124 } 1125 } 1126 1127 int 1128 p9100_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) 1129 { 1130 if ((fg == 0) && (bg == 0)) 1131 { 1132 fg = WS_DEFAULT_FG; 1133 bg = WS_DEFAULT_BG; 1134 } 1135 if (flags & WSATTR_REVERSE) { 1136 *attrp = (bg & 0xff) << 24 | (fg & 0xff) << 16 | 1137 (flags & 0xff) << 8; 1138 } else 1139 *attrp = (fg & 0xff) << 24 | (bg & 0xff) << 16 | 1140 (flags & 0xff) << 8; 1141 return 0; 1142 } 1143 1144 /* 1145 * wsdisplay_accessops 1146 */ 1147 1148 int 1149 p9100_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 1150 { 1151 struct p9100_softc *sc = v; 1152 struct wsdisplay_fbinfo *wdf; 1153 struct p9100_screen *ms = sc->active; 1154 1155 switch (cmd) { 1156 case WSDISPLAYIO_GTYPE: 1157 *(u_int *)data = WSDISPLAY_TYPE_SB_P9100; 1158 return 0; 1159 1160 case FBIOGVIDEO: 1161 case WSDISPLAYIO_GVIDEO: 1162 *(int *)data = p9100_get_video(sc); 1163 return 0; 1164 1165 case WSDISPLAYIO_SVIDEO: 1166 case FBIOSVIDEO: 1167 p9100_set_video(sc, *(int *)data); 1168 return 0; 1169 1170 case WSDISPLAYIO_GINFO: 1171 wdf = (void *)data; 1172 wdf->height = ms->ri.ri_height; 1173 wdf->width = ms->ri.ri_width; 1174 wdf->depth = ms->ri.ri_depth; 1175 wdf->cmsize = 256; 1176 return 0; 1177 1178 case WSDISPLAYIO_GETCMAP: 1179 return p9100_getcmap(sc, (struct wsdisplay_cmap *)data); 1180 1181 case WSDISPLAYIO_PUTCMAP: 1182 return p9100_putcmap(sc, (struct wsdisplay_cmap *)data); 1183 1184 case WSDISPLAYIO_SMODE: 1185 { 1186 int new_mode = *(int*)data; 1187 if (new_mode != sc->sc_mode) 1188 { 1189 sc->sc_mode = new_mode; 1190 if (new_mode == WSDISPLAYIO_MODE_EMUL) 1191 { 1192 p9100_init_engine(sc); 1193 p9100loadcmap(sc,0,256); 1194 p9100_restore_screen(ms, 1195 ms->type, ms->chars); 1196 p9100_cursor(ms, ms->cursoron, 1197 ms->cursorrow, 1198 ms->cursorcol); 1199 } 1200 } 1201 } 1202 } 1203 return EPASSTHROUGH; 1204 } 1205 1206 paddr_t 1207 p9100_mmap(void *v, off_t offset, int prot) 1208 { 1209 struct p9100_softc *sc = v; 1210 paddr_t pa; 1211 1212 /* 'regular' framebuffer mmap()ing */ 1213 if (offset < sc->sc_fb_psize) { 1214 pa = bus_space_mmap(sc->sc_bustag, sc->sc_fb_paddr + offset, 0, 1215 prot, BUS_SPACE_MAP_LINEAR); 1216 return pa; 1217 } 1218 1219 if ((offset >= sc->sc_fb_paddr) && (offset < (sc->sc_fb_paddr + 1220 sc->sc_fb_psize))) { 1221 pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, 1222 BUS_SPACE_MAP_LINEAR); 1223 return pa; 1224 } 1225 1226 if ((offset >= sc->sc_ctl_paddr) && (offset < (sc->sc_ctl_paddr + 1227 sc->sc_ctl_psize))) { 1228 pa = bus_space_mmap(sc->sc_bustag, offset, 0, prot, 1229 BUS_SPACE_MAP_LINEAR); 1230 return pa; 1231 } 1232 1233 return -1; 1234 } 1235 1236 void 1237 p9100_init_screen(struct p9100_softc *sc, struct p9100_screen *scr, 1238 int existing, long *defattr) 1239 { 1240 struct rasops_info *ri = &scr->ri; 1241 int cnt; 1242 1243 scr->sc = sc; 1244 /*scr->type = type;*/ 1245 scr->dispoffset = 0; 1246 scr->cursorcol = 0; 1247 scr->cursorrow = 0; 1248 scr->cursordrawn=0; 1249 1250 ri->ri_depth = sc->sc_depth << 3; 1251 ri->ri_width = sc->sc_width; 1252 ri->ri_height = sc->sc_height; 1253 ri->ri_stride = sc->sc_stride; 1254 ri->ri_flg = RI_CENTER; 1255 1256 ri->ri_bits = bus_space_vaddr(sc->sc_bustag, sc->sc_fb_memh); 1257 1258 #ifdef DEBUG_P9100 1259 printf("addr: %08lx\n",(ulong)ri->ri_bits); 1260 #endif 1261 rasops_init(ri, sc->sc_height/8, sc->sc_width/8); 1262 ri->ri_caps = WSSCREEN_WSCOLORS; 1263 rasops_reconfig(ri, sc->sc_height / ri->ri_font->fontheight, 1264 sc->sc_width / ri->ri_font->fontwidth); 1265 1266 p9100_allocattr(ri, WS_DEFAULT_FG, WS_DEFAULT_BG, 0, defattr); 1267 1268 /* 1269 * we allocate both chars and attributes in one chunk, attributes first 1270 * because they have the (potentially) bigger alignment 1271 */ 1272 cnt=ri->ri_rows * ri->ri_cols; 1273 scr->attrs = (long *)malloc(cnt * (sizeof(long) + sizeof(uint16_t)), 1274 M_DEVBUF, M_WAITOK); 1275 scr->chars = (uint16_t *)&scr->attrs[cnt]; 1276 1277 /* enable acceleration */ 1278 ri->ri_hw = scr; 1279 ri->ri_ops.copyrows = p9100_copyrows; 1280 ri->ri_ops.copycols = p9100_copycols; 1281 ri->ri_ops.eraserows = p9100_eraserows; 1282 ri->ri_ops.erasecols = p9100_erasecols; 1283 ri->ri_ops.cursor = p9100_cursor; 1284 ri->ri_ops.allocattr = p9100_allocattr; 1285 #ifdef PNOZZ_SOFT_PUTCHAR 1286 if (sc->putchar == NULL) 1287 sc->putchar=ri->ri_ops.putchar; 1288 #endif 1289 ri->ri_ops.putchar = p9100_putchar; 1290 1291 if (existing) { 1292 scr->active = 1; 1293 } else { 1294 scr->active = 0; 1295 } 1296 1297 p9100_eraserows(&scr->ri, 0, ri->ri_rows, *defattr); 1298 1299 LIST_INSERT_HEAD(&sc->screens, scr, next); 1300 } 1301 1302 int 1303 p9100_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 1304 int *curxp, int *curyp, long *defattrp) 1305 { 1306 struct p9100_softc *sc = v; 1307 struct p9100_screen *scr; 1308 1309 scr = malloc(sizeof(struct p9100_screen), M_DEVBUF, M_WAITOK | M_ZERO); 1310 p9100_init_screen(sc, scr, 0, defattrp); 1311 1312 if (sc->active == NULL) { 1313 scr->active = 1; 1314 sc->active = scr; 1315 sc->currenttype = type; 1316 } 1317 1318 *cookiep = scr; 1319 *curxp = scr->cursorcol; 1320 *curyp = scr->cursorrow; 1321 return 0; 1322 } 1323 1324 void 1325 p9100_free_screen(void *v, void *cookie) 1326 { 1327 struct p9100_softc *sc = v; 1328 struct p9100_screen *scr = cookie; 1329 1330 LIST_REMOVE(scr, next); 1331 if (scr != &p9100_console_screen) { 1332 free(scr->attrs, M_DEVBUF); 1333 free(scr, M_DEVBUF); 1334 } else 1335 panic("p9100_free_screen: console"); 1336 1337 if (sc->active == scr) 1338 sc->active = 0; 1339 } 1340 1341 int 1342 p9100_show_screen(void *v, void *cookie, int waitok, 1343 void (*cb)(void *, int, int), void *cbarg) 1344 { 1345 struct p9100_softc *sc = v; 1346 struct p9100_screen *scr, *oldscr; 1347 1348 scr = cookie; 1349 oldscr = sc->active; 1350 if (scr == oldscr) 1351 return 0; 1352 1353 sc->wanted = scr; 1354 sc->switchcb = cb; 1355 sc->switchcbarg = cbarg; 1356 if (cb) { 1357 callout_reset(&sc->switch_callout, 0, 1358 (void(*)(void *))p9100_switch_screen, sc); 1359 return EAGAIN; 1360 } 1361 1362 p9100_switch_screen(sc); 1363 return 0; 1364 } 1365 1366 int 1367 p9100_putcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm) 1368 { 1369 u_int index = cm->index; 1370 u_int count = cm->count; 1371 int i, error; 1372 u_char rbuf[256], gbuf[256], bbuf[256]; 1373 u_char *r, *g, *b; 1374 1375 printf("putcmap: %d %d\n",index, count); 1376 if (cm->index >= 256 || cm->count > 256 || 1377 (cm->index + cm->count) > 256) 1378 return EINVAL; 1379 error = copyin(cm->red, &rbuf[index], count); 1380 if (error) 1381 return error; 1382 error = copyin(cm->green, &gbuf[index], count); 1383 if (error) 1384 return error; 1385 error = copyin(cm->blue, &bbuf[index], count); 1386 if (error) 1387 return error; 1388 1389 r = &rbuf[index]; 1390 g = &gbuf[index]; 1391 b = &bbuf[index]; 1392 1393 for (i = 0; i < count; i++) { 1394 sc->sc_cmap.cm_map[index][0] = *r; 1395 sc->sc_cmap.cm_map[index][1] = *g; 1396 sc->sc_cmap.cm_map[index][2] = *b; 1397 index++; 1398 r++, g++, b++; 1399 } 1400 p9100loadcmap(sc, 0, 256); 1401 return 0; 1402 } 1403 1404 int 1405 p9100_getcmap(struct p9100_softc *sc, struct wsdisplay_cmap *cm) 1406 { 1407 u_int index = cm->index; 1408 u_int count = cm->count; 1409 int error, i; 1410 uint8_t red[256],green[256],blue[256]; 1411 1412 if (index >= 255 || count > 256 || index + count > 256) 1413 return EINVAL; 1414 1415 i = index; 1416 while (i < (index + count)) { 1417 red[i] = sc->sc_cmap.cm_map[i][0]; 1418 green[i] = sc->sc_cmap.cm_map[i][1]; 1419 blue[i] = sc->sc_cmap.cm_map[i][2]; 1420 i++; 1421 } 1422 error = copyout(&red[index], cm->red, count); 1423 if (error) 1424 return error; 1425 error = copyout(&green[index], cm->green, count); 1426 if (error) 1427 return error; 1428 error = copyout(&blue[index], cm->blue, count); 1429 if (error) 1430 return error; 1431 1432 return 0; 1433 } 1434 1435 #if 0 1436 int 1437 p9100_load_font(void *v, void *cookie, struct wsdisplay_font *data) 1438 { 1439 1440 return 0; 1441 } 1442 #endif 1443 1444 int 1445 p9100_intr(void *arg) 1446 { 1447 /*p9100_softc *sc=arg; 1448 printf(".");*/ 1449 return 1; 1450 } 1451