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