1 /* $NetBSD: pm.c,v 1.6 2008/04/28 20:23:31 martin Exp $ */ 2 3 /*- 4 * Copyright (c) 2002, 2003 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 * Copyright (c) 1998, 1999 Tohru Nishimura. All rights reserved. 34 * 35 * Redistribution and use in source and binary forms, with or without 36 * modification, are permitted provided that the following conditions 37 * are met: 38 * 1. Redistributions of source code must retain the above copyright 39 * notice, this list of conditions and the following disclaimer. 40 * 2. Redistributions in binary form must reproduce the above copyright 41 * notice, this list of conditions and the following disclaimer in the 42 * documentation and/or other materials provided with the distribution. 43 * 3. All advertising materials mentioning features or use of this software 44 * must display the following acknowledgement: 45 * This product includes software developed by Tohru Nishimura 46 * for the NetBSD Project. 47 * 4. The name of the author may not be used to endorse or promote products 48 * derived from this software without specific prior written permission 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 51 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 52 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 53 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 54 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 57 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 58 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 59 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 */ 61 62 #include <sys/cdefs.h> 63 __KERNEL_RCSID(0, "$NetBSD: pm.c,v 1.6 2008/04/28 20:23:31 martin Exp $"); 64 65 #include <sys/param.h> 66 #include <sys/systm.h> 67 #include <sys/kernel.h> 68 #include <sys/device.h> 69 #include <sys/buf.h> 70 #include <sys/ioctl.h> 71 72 #include <machine/bus.h> 73 #include <machine/intr.h> 74 75 #include <dev/wscons/wsconsio.h> 76 #include <dev/wscons/wsdisplayvar.h> 77 #include <dev/rasops/rasops.h> 78 #include <dev/wsfont/wsfont.h> 79 80 #include <pmax/pmax/kn01.h> 81 82 #include <pmax/ibus/ibusvar.h> 83 #include <pmax/ibus/pmreg.h> 84 85 #include <uvm/uvm_extern.h> 86 87 #define CURSOR_MAX_SIZE 16 88 89 struct hwcmap256 { 90 uint8_t r[256]; 91 uint8_t g[256]; 92 uint8_t b[256]; 93 }; 94 95 struct hwcursor64 { 96 struct wsdisplay_curpos cc_pos; 97 struct wsdisplay_curpos cc_hot; 98 struct wsdisplay_curpos cc_size; 99 uint8_t cc_color[6]; 100 101 /* 102 * Max cursor size is 16x16. The X server pads bitmap scanlines to 103 * a word boundary. We take the easy route and waste some space. 104 */ 105 u_short cc_image[32 + 32]; 106 }; 107 108 struct pm_softc { 109 struct device sc_dev; 110 size_t sc_cmap_size; 111 size_t sc_fb_size; 112 int sc_type; 113 int sc_blanked; 114 int sc_curenb; 115 int sc_changed; 116 int sc_nscreens; 117 struct hwcursor64 sc_cursor; 118 struct hwcmap256 sc_cmap; 119 }; 120 #define WSDISPLAY_CMAP_DOLUT 0x20 121 122 int pm_match(struct device *, struct cfdata *, void *); 123 void pm_attach(struct device *, struct device *, void *); 124 int pm_ioctl(void *, void *, u_long, void *, int, struct lwp *); 125 paddr_t pm_mmap(void *, void *, off_t, int); 126 int pm_alloc_screen(void *, const struct wsscreen_descr *, 127 void **, int *, int *, long *); 128 void pm_free_screen(void *, void *); 129 int pm_show_screen(void *, void *, int, 130 void (*) (void *, int, int), void *); 131 void pm_cursor_off(void); 132 void pm_cursor_on(struct pm_softc *); 133 int pm_cnattach(void); 134 void pm_common_init(void); 135 int pm_flush(struct pm_softc *); 136 int pm_get_cmap(struct pm_softc *, struct wsdisplay_cmap *); 137 int pm_set_cmap(struct pm_softc *, struct wsdisplay_cmap *); 138 int pm_set_cursor(struct pm_softc *, struct wsdisplay_cursor *); 139 int pm_get_cursor(struct pm_softc *, struct wsdisplay_cursor *); 140 void pm_set_curpos(struct pm_softc *, struct wsdisplay_curpos *); 141 void pm_init_cmap(struct pm_softc *); 142 143 CFATTACH_DECL(pm, sizeof(struct pm_softc), 144 pm_match, pm_attach, NULL, NULL); 145 146 struct rasops_info pm_ri; 147 148 struct wsscreen_descr pm_stdscreen = { 149 "std", 0, 0, 150 0, /* textops */ 151 0, 0, 152 WSSCREEN_REVERSE 153 }; 154 155 const struct wsscreen_descr *_pm_scrlist[] = { 156 &pm_stdscreen, 157 }; 158 159 const struct wsscreen_list pm_screenlist = { 160 sizeof(_pm_scrlist) / sizeof(struct wsscreen_descr *), _pm_scrlist 161 }; 162 163 const struct wsdisplay_accessops pm_accessops = { 164 pm_ioctl, 165 pm_mmap, 166 pm_alloc_screen, 167 pm_free_screen, 168 pm_show_screen, 169 0 /* load_font */ 170 }; 171 172 u_int pm_creg; 173 174 int 175 pm_match(struct device *parent, struct cfdata *match, void *aux) 176 { 177 struct ibus_attach_args *ia; 178 void *pmaddr; 179 180 ia = aux; 181 pmaddr = (void *)ia->ia_addr; 182 183 if (strcmp(ia->ia_name, "pm") != 0) 184 return (0); 185 186 if (badaddr(pmaddr, 4)) 187 return (0); 188 189 return (1); 190 } 191 192 void 193 pm_attach(struct device *parent, struct device *self, void *aux) 194 { 195 struct pm_softc *sc; 196 struct rasops_info *ri; 197 struct wsemuldisplaydev_attach_args waa; 198 int console; 199 200 sc = (struct pm_softc *)self; 201 ri = &pm_ri; 202 console = (ri->ri_bits != NULL); 203 204 if (console) 205 sc->sc_nscreens = 1; 206 else 207 pm_common_init(); 208 209 printf(": %dx%d, %dbpp\n", ri->ri_width, ri->ri_height, ri->ri_depth); 210 211 pm_init_cmap(sc); 212 213 sc->sc_blanked = 0; 214 sc->sc_curenb = 0; 215 216 waa.console = console; 217 waa.scrdata = &pm_screenlist; 218 waa.accessops = &pm_accessops; 219 waa.accesscookie = sc; 220 221 config_found(self, &waa, wsemuldisplaydevprint); 222 } 223 224 void 225 pm_init_cmap(struct pm_softc *sc) 226 { 227 struct hwcmap256 *cm; 228 struct rasops_info *ri; 229 const uint8_t *p; 230 int index; 231 232 cm = &sc->sc_cmap; 233 ri = &pm_ri; 234 235 if (ri->ri_depth == 8) { 236 p = rasops_cmap; 237 for (index = 0; index < 256; index++, p += 3) { 238 cm->r[index] = p[0]; 239 cm->g[index] = p[1]; 240 cm->b[index] = p[2]; 241 } 242 243 sc->sc_type = WSDISPLAY_TYPE_PM_COLOR; 244 sc->sc_cmap_size = 256; 245 sc->sc_fb_size = 0x100000; 246 } else { 247 cm->r[0] = 0x00; 248 cm->g[0] = 0x00; 249 cm->b[0] = 0x00; 250 251 cm->r[1] = 0x00; 252 cm->g[1] = 0xff; 253 cm->b[1] = 0x00; 254 255 sc->sc_type = WSDISPLAY_TYPE_PM_MONO; 256 sc->sc_cmap_size = 2; 257 sc->sc_fb_size = 0x40000; 258 } 259 } 260 261 void 262 pm_common_init(void) 263 { 264 struct rasops_info *ri; 265 int cookie, bior, i; 266 PCCRegs *pcc; 267 VDACRegs *vdac; 268 uint16_t kn01csr; 269 270 kn01csr = *(volatile uint16_t *)MIPS_PHYS_TO_KSEG1(KN01_SYS_CSR); 271 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC); 272 vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC); 273 ri = &pm_ri; 274 275 ri->ri_flg = RI_CENTER; 276 ri->ri_depth = ((kn01csr & KN01_CSR_MONO) != 0 ? 1 : 8); 277 ri->ri_width = 1024; 278 ri->ri_height = 864; 279 ri->ri_stride = (ri->ri_depth == 8 ? 1024 : 2048 / 8); 280 ri->ri_bits = (void *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_FBUF_START); 281 282 /* 283 * Clear the screen. 284 */ 285 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 286 287 /* 288 * Get a font to use. 289 */ 290 bior = (ri->ri_depth == 8 ? WSDISPLAY_FONTORDER_L2R : 291 WSDISPLAY_FONTORDER_R2L); 292 293 wsfont_init(); 294 if (ri->ri_depth == 8) 295 cookie = wsfont_find(NULL, 12, 0, 0, bior, 296 WSDISPLAY_FONTORDER_L2R); 297 else 298 cookie = wsfont_find(NULL, 8, 0, 0, bior, 299 WSDISPLAY_FONTORDER_L2R); 300 if (cookie <= 0) 301 cookie = wsfont_find(NULL, 0, 0, 0, bior, 302 WSDISPLAY_FONTORDER_L2R); 303 if (cookie <= 0) { 304 printf("pm: font table is empty\n"); 305 return; 306 } 307 308 if (wsfont_lock(cookie, &ri->ri_font)) { 309 printf("pm: couldn't lock font\n"); 310 return; 311 } 312 ri->ri_wsfcookie = cookie; 313 314 /* 315 * Set up the raster operations set. 316 */ 317 rasops_init(ri, 1000, 1000); 318 319 pm_stdscreen.nrows = ri->ri_rows; 320 pm_stdscreen.ncols = ri->ri_cols; 321 pm_stdscreen.textops = &ri->ri_ops; 322 pm_stdscreen.capabilities = ri->ri_caps; 323 324 /* 325 * Initalize the VDAC. 326 */ 327 *(uint8_t *)MIPS_PHYS_TO_KSEG1(KN01_PHYS_COLMASK_START) = 0xff; 328 wbflush(); 329 330 vdac->overWA = 0x04; wbflush(); 331 vdac->over = 0x00; wbflush(); 332 vdac->over = 0x00; wbflush(); 333 vdac->over = 0x00; wbflush(); 334 vdac->overWA = 0x08; wbflush(); 335 vdac->over = 0x00; wbflush(); 336 vdac->over = 0x00; wbflush(); 337 vdac->over = 0x7f; wbflush(); 338 vdac->overWA = 0x0c; wbflush(); 339 vdac->over = 0xff; wbflush(); 340 vdac->over = 0xff; wbflush(); 341 vdac->over = 0xff; wbflush(); 342 343 /* 344 * Set in the initial colormap. 345 */ 346 if (ri->ri_depth == 8) { 347 vdac->mapWA = 0; 348 wbflush(); 349 350 for (i = 0; i < 256 * 3; i += 3) { 351 vdac->map = rasops_cmap[i]; 352 wbflush(); 353 vdac->map = rasops_cmap[i + 1]; 354 wbflush(); 355 vdac->map = rasops_cmap[i + 2]; 356 wbflush(); 357 } 358 } else { 359 vdac->mapWA = 0; 360 wbflush(); 361 362 for (i = 0; i < 256; i++) { 363 vdac->map = 0x00; 364 wbflush(); 365 vdac->map = (i < 128 ? 0x00 : 0xff); 366 wbflush(); 367 vdac->map = 0x00; 368 wbflush(); 369 } 370 } 371 372 /* 373 * Turn off the hardware cursor sprite for text mode. 374 */ 375 pcc->cmdr = PCC_FOPB | PCC_VBHI; 376 wbflush(); 377 pm_creg = 0; 378 pm_cursor_off(); 379 } 380 381 void 382 pm_cursor_off(void) 383 { 384 PCCRegs *pcc; 385 386 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC); 387 pcc->cmdr = (pm_creg &= ~(PCC_ENPA | PCC_ENPB)); 388 wbflush(); 389 } 390 391 void 392 pm_cursor_on(struct pm_softc *sc) 393 { 394 PCCRegs *pcc; 395 396 if (sc->sc_curenb) { 397 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC); 398 pcc->cmdr = (pm_creg |= (PCC_ENPA | PCC_ENPB)); 399 wbflush(); 400 } 401 } 402 403 int 404 pm_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 405 { 406 struct pm_softc *sc; 407 struct rasops_info *ri; 408 int turnoff, rv, i; 409 PCCRegs *pcc; 410 VDACRegs *vdac; 411 412 sc = v; 413 ri = &pm_ri; 414 rv = 0; 415 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC); 416 vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC); 417 418 switch (cmd) { 419 case WSDISPLAYIO_GTYPE: 420 *(u_int *)data = sc->sc_type; 421 break; 422 423 case WSDISPLAYIO_SMODE: 424 if (*(u_int *)data == WSDISPLAYIO_MODE_EMUL) { 425 pm_cursor_off(); 426 pm_init_cmap(sc); 427 memset(ri->ri_bits, 0, ri->ri_stride * ri->ri_height); 428 sc->sc_curenb = 0; 429 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 430 } 431 break; 432 433 case WSDISPLAYIO_GINFO: 434 #define wsd_fbip ((struct wsdisplay_fbinfo *)data) 435 wsd_fbip->height = ri->ri_height; 436 wsd_fbip->width = ri->ri_width; 437 wsd_fbip->depth = ri->ri_depth; 438 wsd_fbip->cmsize = sc->sc_cmap_size; 439 #undef fbt 440 break; 441 442 case WSDISPLAYIO_GETCMAP: 443 rv = pm_get_cmap(sc, (struct wsdisplay_cmap *)data); 444 break; 445 446 case WSDISPLAYIO_PUTCMAP: 447 rv = pm_set_cmap(sc, (struct wsdisplay_cmap *)data); 448 break; 449 450 case WSDISPLAYIO_SVIDEO: 451 turnoff = (*(int *)data == WSDISPLAYIO_VIDEO_OFF); 452 if ((sc->sc_blanked == 0) ^ turnoff) { 453 sc->sc_blanked = turnoff; 454 if (turnoff == 0) { 455 pcc->cmdr = 456 (pm_creg &= ~(PCC_FOPA | PCC_FOPB)); 457 wbflush(); 458 pm_cursor_on(sc); 459 sc->sc_changed |= WSDISPLAY_CURSOR_DOCMAP; 460 } else { 461 pm_cursor_off(); 462 pcc->cmdr = 463 (pm_creg |= (PCC_FOPA | PCC_FOPB)); 464 wbflush(); 465 vdac->overWA = 0x0c; 466 wbflush(); 467 for (i = 0; i < 3; i++) { 468 vdac->over = 0; 469 wbflush(); 470 } 471 } 472 } 473 break; 474 475 case WSDISPLAYIO_GVIDEO: 476 *(u_int *)data = (sc->sc_blanked ? 477 WSDISPLAYIO_VIDEO_OFF : WSDISPLAYIO_VIDEO_ON); 478 break; 479 480 case WSDISPLAYIO_GCURPOS: 481 *(struct wsdisplay_curpos *)data = sc->sc_cursor.cc_pos; 482 break; 483 484 case WSDISPLAYIO_SCURPOS: 485 pm_set_curpos(sc, (struct wsdisplay_curpos *)data); 486 sc->sc_changed |= WSDISPLAY_CURSOR_DOPOS; 487 break; 488 489 case WSDISPLAYIO_GCURMAX: 490 ((struct wsdisplay_curpos *)data)->x = 491 ((struct wsdisplay_curpos *)data)->y = CURSOR_MAX_SIZE; 492 break; 493 494 case WSDISPLAYIO_GCURSOR: 495 rv = pm_get_cursor(sc, (struct wsdisplay_cursor *)data); 496 break; 497 498 case WSDISPLAYIO_SCURSOR: 499 rv = pm_set_cursor(sc, (struct wsdisplay_cursor *)data); 500 break; 501 502 default: 503 rv = ENOTTY; 504 break; 505 } 506 507 pm_flush(sc); 508 return (rv); 509 } 510 511 paddr_t 512 pm_mmap(void *v, void *vs, off_t offset, int prot) 513 { 514 struct pm_softc *sc; 515 516 sc = v; 517 518 if (offset >= sc->sc_fb_size || offset < 0) 519 return (-1); 520 521 return (mips_btop(KN01_PHYS_FBUF_START + offset)); 522 } 523 524 int 525 pm_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 526 int *curxp, int *curyp, long *attrp) 527 { 528 struct pm_softc *sc; 529 struct rasops_info *ri; 530 long defattr; 531 532 sc = v; 533 ri = &pm_ri; 534 535 if (sc->sc_nscreens > 0) 536 return (ENOMEM); 537 538 *cookiep = ri; /* one and only for now */ 539 *curxp = 0; 540 *curyp = 0; 541 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 542 *attrp = defattr; 543 sc->sc_nscreens++; 544 return (0); 545 } 546 547 void 548 pm_free_screen(void *v, void *cookie) 549 { 550 551 panic("pm_free_screen: console"); 552 } 553 554 int 555 pm_show_screen(void *v, void *cookie, int waitok, 556 void (*cb)(void *, int, int), void *cbarg) 557 { 558 559 return (0); 560 } 561 562 /* EXPORT */ int 563 pm_cnattach(void) 564 { 565 struct rasops_info *ri; 566 long defattr; 567 568 ri = &pm_ri; 569 570 pm_common_init(); 571 (*ri->ri_ops.allocattr)(ri, 0, 0, 0, &defattr); 572 wsdisplay_cnattach(&pm_stdscreen, ri, 0, 0, defattr); 573 return (1); 574 } 575 576 int 577 pm_flush(struct pm_softc *sc) 578 { 579 VDACRegs *vdac; 580 PCCRegs *pcc; 581 uint8_t *cp; 582 int v, i, x, y; 583 u_short *p, *pe; 584 struct hwcmap256 *cm; 585 struct rasops_info *ri; 586 587 if (sc->sc_changed == 0) 588 return (1); 589 590 vdac = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_VDAC); 591 pcc = (void *)MIPS_PHYS_TO_KSEG1(KN01_SYS_PCC); 592 ri = &pm_ri; 593 v = sc->sc_changed; 594 595 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) { 596 if (sc->sc_curenb) 597 pm_cursor_on(sc); 598 else 599 pm_cursor_off(); 600 } 601 602 if ((v & (WSDISPLAY_CURSOR_DOPOS | WSDISPLAY_CURSOR_DOHOT)) != 0) { 603 x = sc->sc_cursor.cc_pos.x - sc->sc_cursor.cc_hot.x; 604 y = sc->sc_cursor.cc_pos.y - sc->sc_cursor.cc_hot.y; 605 pcc->xpos = x + PCC_X_OFFSET; 606 pcc->ypos = y + PCC_Y_OFFSET; 607 wbflush(); 608 } 609 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 610 cp = sc->sc_cursor.cc_color; 611 612 vdac->overWA = 0x04; 613 wbflush(); 614 for (i = 1; i < 6; i += 2) { 615 vdac->over = cp[i]; 616 wbflush(); 617 } 618 619 vdac->overWA = 0x08; 620 wbflush(); 621 vdac->over = 0x00; 622 wbflush(); 623 vdac->over = 0x00; 624 wbflush(); 625 vdac->over = 0x7f; 626 wbflush(); 627 628 vdac->overWA = 0x0c; 629 wbflush(); 630 for (i = 0; i < 6; i += 2) { 631 vdac->over = cp[i]; 632 wbflush(); 633 } 634 } 635 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 636 pcc->cmdr = (pm_creg | PCC_LODSA); 637 wbflush(); 638 639 p = sc->sc_cursor.cc_image; 640 x = 0xffff >> (16 - sc->sc_cursor.cc_size.x); 641 for (pe = p + 64; p < pe; p += 2) { 642 pcc->memory = *p & x; 643 wbflush(); 644 } 645 646 pcc->cmdr = (pm_creg &= ~PCC_LODSA); 647 wbflush(); 648 } 649 650 if ((v & WSDISPLAY_CMAP_DOLUT) != 0) { 651 cm = &sc->sc_cmap; 652 653 vdac->mapWA = 0; 654 wbflush(); 655 656 if (sc->sc_cmap_size == 2) { 657 for (i = 0; i < 128; i++) { 658 vdac->map = 0; 659 wbflush(); 660 vdac->map = cm->g[0]; 661 wbflush(); 662 vdac->map = 0; 663 wbflush(); 664 } 665 for (; i < 256; i++) { 666 vdac->map = 0; 667 wbflush(); 668 vdac->map = cm->g[1]; 669 wbflush(); 670 vdac->map = 0; 671 wbflush(); 672 } 673 } else { 674 for (i = 0; i < sc->sc_cmap_size; i++) { 675 vdac->map = cm->r[i]; 676 wbflush(); 677 vdac->map = cm->g[i]; 678 wbflush(); 679 vdac->map = cm->b[i]; 680 wbflush(); 681 } 682 } 683 } 684 685 sc->sc_changed = 0; 686 return (1); 687 } 688 689 int 690 pm_get_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p) 691 { 692 u_int index, count; 693 int rv; 694 695 index = p->index; 696 count = p->count; 697 698 if (index >= sc->sc_cmap_size || (index + count) > sc->sc_cmap_size) 699 return (EINVAL); 700 701 if ((rv = copyout(&sc->sc_cmap.r[index], p->red, count)) != 0) 702 return (rv); 703 if ((rv = copyout(&sc->sc_cmap.g[index], p->green, count)) != 0) 704 return (rv); 705 return (copyout(&sc->sc_cmap.b[index], p->blue, count)); 706 } 707 708 int 709 pm_set_cmap(struct pm_softc *sc, struct wsdisplay_cmap *p) 710 { 711 u_int index, count; 712 int rv; 713 714 index = p->index; 715 count = p->count; 716 717 if (index >= sc->sc_cmap_size || (index + count) > sc->sc_cmap_size) 718 return (EINVAL); 719 720 if ((rv = copyin(p->red, &sc->sc_cmap.r[index], count)) != 0) 721 return (rv); 722 if ((rv = copyin(p->green, &sc->sc_cmap.g[index], count)) != 0) 723 return (rv); 724 if ((rv = copyin(p->blue, &sc->sc_cmap.b[index], count)) != 0) 725 return (rv); 726 sc->sc_changed |= WSDISPLAY_CMAP_DOLUT; 727 return (0); 728 } 729 730 int 731 pm_set_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p) 732 { 733 u_int v, index, count; 734 struct hwcursor64 *cc; 735 int rv; 736 737 v = p->which; 738 cc = &sc->sc_cursor; 739 740 if ((v & WSDISPLAY_CURSOR_DOCUR) != 0) 741 sc->sc_curenb = p->enable; 742 if ((v & WSDISPLAY_CURSOR_DOPOS) != 0) 743 pm_set_curpos(sc, &p->pos); 744 if ((v & WSDISPLAY_CURSOR_DOHOT) != 0) 745 cc->cc_hot = p->hot; 746 if ((v & WSDISPLAY_CURSOR_DOCMAP) != 0) { 747 index = p->cmap.index; 748 count = p->cmap.count; 749 if (index >= 2 || (index + count) > 2) 750 return (EINVAL); 751 752 rv = copyin(p->cmap.red, &cc->cc_color[index], count); 753 if (rv != 0) 754 return (rv); 755 rv = copyin(p->cmap.green, &cc->cc_color[index + 2], count); 756 if (rv != 0) 757 return (rv); 758 rv = copyin(p->cmap.blue, &cc->cc_color[index + 4], count); 759 if (rv != 0) 760 return (rv); 761 } 762 if ((v & WSDISPLAY_CURSOR_DOSHAPE) != 0) { 763 if (p->size.x > CURSOR_MAX_SIZE || 764 p->size.y > CURSOR_MAX_SIZE) 765 return (EINVAL); 766 767 cc->cc_size = p->size; 768 memset(cc->cc_image, 0, sizeof(cc->cc_image)); 769 rv = copyin(p->image, cc->cc_image, p->size.y * 4); 770 if (rv != 0) 771 return (rv); 772 rv = copyin(p->mask, cc->cc_image+32, p->size.y * 4); 773 if (rv != 0) 774 return (rv); 775 } 776 777 sc->sc_changed |= v; 778 return (0); 779 } 780 781 int 782 pm_get_cursor(struct pm_softc *sc, struct wsdisplay_cursor *p) 783 { 784 785 return (ENOTTY); /* XXX */ 786 } 787 788 void 789 pm_set_curpos(struct pm_softc *sc, struct wsdisplay_curpos *curpos) 790 { 791 struct rasops_info *ri; 792 int x, y; 793 794 ri = &pm_ri; 795 x = curpos->x; 796 y = curpos->y; 797 798 if (y < 0) 799 y = 0; 800 else if (y > ri->ri_height) 801 y = ri->ri_height; 802 if (x < 0) 803 x = 0; 804 else if (x > ri->ri_width) 805 x = ri->ri_width; 806 sc->sc_cursor.cc_pos.x = x; 807 sc->sc_cursor.cc_pos.y = y; 808 } 809