1 /* $NetBSD: grf.c,v 1.58 2012/03/13 18:40:27 elad Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1990 The Regents of the University of California. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * from: Utah $Hdr: grf.c 1.31 91/01/21$ 37 * 38 * @(#)grf.c 7.8 (Berkeley) 5/7/91 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: grf.c,v 1.58 2012/03/13 18:40:27 elad Exp $"); 43 44 /* 45 * Graphics display driver for the Amiga 46 * This is the hardware-independent portion of the driver. 47 * Hardware access is through the grf_softc->g_mode routine. 48 */ 49 50 #include "view.h" 51 #include "grf.h" 52 #include "kbd.h" 53 #include "wsdisplay.h" 54 55 #include <sys/param.h> 56 #include <sys/proc.h> 57 #include <sys/ioctl.h> 58 #include <sys/device.h> 59 #include <sys/file.h> 60 #include <sys/malloc.h> 61 #include <sys/systm.h> 62 #include <sys/vnode.h> 63 #include <sys/mman.h> 64 #include <sys/bus.h> 65 #include <sys/kauth.h> 66 67 #include <machine/cpu.h> 68 69 #include <dev/cons.h> 70 #include <dev/sun/fbio.h> 71 #include <dev/wscons/wsconsio.h> 72 #include <dev/wscons/wsdisplayvar.h> 73 #include <dev/rasops/rasops.h> 74 #include <dev/wscons/wsdisplay_vconsvar.h> 75 76 #include <amiga/amiga/color.h> /* DEBUG */ 77 #include <amiga/amiga/device.h> 78 #include <amiga/dev/grfioctl.h> 79 #include <amiga/dev/grfws.h> 80 #include <amiga/dev/grfvar.h> 81 #include <amiga/dev/itevar.h> 82 #include <amiga/dev/kbdvar.h> 83 #include <amiga/dev/viewioctl.h> 84 85 #include <sys/conf.h> 86 87 #if NGRF > 0 88 #include "ite.h" 89 #if NITE == 0 90 #define ite_on(u,f) 91 #define ite_off(u,f) 92 #define ite_reinit(d) 93 #endif 94 95 int grfon(dev_t); 96 int grfoff(dev_t); 97 int grfsinfo(dev_t, struct grfdyninfo *); 98 99 void grfattach(device_t, device_t, void *); 100 int grfmatch(device_t, cfdata_t, void *); 101 int grfprint(void *, const char *); 102 #ifdef DEBUG 103 void grfdebug(struct grf_softc *, const char *, ...); 104 #endif 105 /* 106 * pointers to grf drivers device structs 107 */ 108 struct grf_softc *grfsp[NGRF]; 109 110 CFATTACH_DECL_NEW(grf, 0, 111 grfmatch, grfattach, NULL, NULL); 112 113 dev_type_open(grfopen); 114 dev_type_close(grfclose); 115 dev_type_ioctl(grfioctl); 116 dev_type_mmap(grfmmap); 117 118 const struct cdevsw grf_cdevsw = { 119 grfopen, grfclose, nullread, nullwrite, grfioctl, 120 nostop, notty, nopoll, grfmmap, nokqfilter, 121 }; 122 123 /* 124 * only used in console init. 125 */ 126 static cfdata_t cfdata; 127 128 #if NWSDISPLAY > 0 129 static struct vcons_screen console_vcons; 130 131 static void grf_init_screen(void *, struct vcons_screen *, int, long *); 132 static struct rasops_info *grf_setup_rasops(struct grf_softc *, 133 struct vcons_screen *); 134 static paddr_t grf_wsmmap_md(off_t off); 135 136 cons_decl(grf); 137 #endif 138 139 /* 140 * match if the unit of grf matches its perspective 141 * low level board driver. 142 */ 143 int 144 grfmatch(device_t pdp, cfdata_t cfp, void *auxp) 145 { 146 147 if (cfp->cf_unit != ((struct grf_softc *)pdp)->g_unit) 148 return(0); 149 cfdata = cfp; 150 return(1); 151 } 152 153 /* 154 * Attach.. plug pointer in and print some info. 155 * Then try and attach a wsdisplay or ite to us. 156 * Note: dp is NULL durring console init. 157 */ 158 void 159 grfattach(device_t pdp, device_t dp, void *auxp) 160 { 161 #if NWSDISPLAY > 0 162 struct wsemuldisplaydev_attach_args wa; 163 long defattr; 164 #endif 165 struct grf_softc *gp; 166 int maj; 167 168 gp = (struct grf_softc *)pdp; 169 grfsp[gp->g_unit] = (struct grf_softc *)pdp; 170 171 /* 172 * find our major device number 173 */ 174 maj = cdevsw_lookup_major(&grf_cdevsw); 175 176 gp->g_grfdev = makedev(maj, gp->g_unit); 177 if (dp != NULL) { 178 printf(": width %d height %d", gp->g_display.gd_dwidth, 179 gp->g_display.gd_dheight); 180 if (gp->g_display.gd_colors == 2) 181 printf(" monochrome\n"); 182 else 183 printf(" colors %d\n", gp->g_display.gd_colors); 184 #if NWSDISPLAY > 0 185 vcons_init(&gp->g_vd, gp, gp->g_screens[0], gp->g_accessops); 186 gp->g_vd.init_screen = grf_init_screen; 187 if (gp->g_flags & GF_CONSOLE) { 188 console_vcons.scr_flags |= VCONS_SCREEN_IS_STATIC; 189 vcons_init_screen(&gp->g_vd, 190 &console_vcons, 1, &defattr); 191 gp->g_screens[0]->textops = 192 &console_vcons.scr_ri.ri_ops; 193 wsdisplay_cnattach(gp->g_screens[0], 194 &console_vcons.scr_ri, 0, 0, defattr); 195 vcons_replay_msgbuf(&console_vcons); 196 } 197 198 /* attach wsdisplay */ 199 wa.console = (gp->g_flags & GF_CONSOLE) != 0; 200 wa.scrdata = &gp->g_screenlist; 201 wa.accessops = gp->g_accessops; 202 wa.accesscookie = &gp->g_vd; 203 config_found(dp, &wa, wsemuldisplaydevprint); 204 #endif /* NWSDISPLAY > 0 */ 205 } 206 207 #if NWSDISPLAY == 0 208 /* 209 * try and attach an ite 210 */ 211 amiga_config_found(cfdata, dp, gp, grfprint); 212 #endif 213 } 214 215 int 216 grfprint(void *auxp, const char *pnp) 217 { 218 if (pnp) 219 aprint_normal("ite at %s", pnp); 220 return(UNCONF); 221 } 222 223 /*ARGSUSED*/ 224 int 225 grfopen(dev_t dev, int flags, int devtype, struct lwp *l) 226 { 227 struct grf_softc *gp; 228 229 if (GRFUNIT(dev) >= NGRF || (gp = grfsp[GRFUNIT(dev)]) == NULL) 230 return(ENXIO); 231 232 if ((gp->g_flags & GF_ALIVE) == 0) 233 return(ENXIO); 234 235 if ((gp->g_flags & (GF_OPEN|GF_EXCLUDE)) == (GF_OPEN|GF_EXCLUDE)) 236 return(EBUSY); 237 238 return(0); 239 } 240 241 /*ARGSUSED*/ 242 int 243 grfclose(dev_t dev, int flags, int mode, struct lwp *l) 244 { 245 struct grf_softc *gp; 246 247 gp = grfsp[GRFUNIT(dev)]; 248 (void)grfoff(dev); 249 gp->g_flags &= GF_ALIVE; 250 return(0); 251 } 252 253 /*ARGSUSED*/ 254 int 255 grfioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 256 { 257 struct grf_softc *gp; 258 int error; 259 260 gp = grfsp[GRFUNIT(dev)]; 261 error = 0; 262 263 switch (cmd) { 264 case OGRFIOCGINFO: 265 /* argl.. no bank-member.. */ 266 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)-4); 267 break; 268 case GRFIOCGINFO: 269 memcpy(data, (void *)&gp->g_display, sizeof(struct grfinfo)); 270 break; 271 case GRFIOCON: 272 error = grfon(dev); 273 break; 274 case GRFIOCOFF: 275 error = grfoff(dev); 276 break; 277 case GRFIOCSINFO: 278 error = grfsinfo(dev, (struct grfdyninfo *) data); 279 break; 280 case GRFGETVMODE: 281 return(gp->g_mode(gp, GM_GRFGETVMODE, data, 0, 0)); 282 case GRFSETVMODE: 283 error = gp->g_mode(gp, GM_GRFSETVMODE, data, 0, 0); 284 if (error == 0 && gp->g_itedev && !(gp->g_flags & GF_GRFON)) 285 ite_reinit(gp->g_itedev); 286 break; 287 case GRFGETNUMVM: 288 return(gp->g_mode(gp, GM_GRFGETNUMVM, data, 0, 0)); 289 /* 290 * these are all hardware dependent, and have to be resolved 291 * in the respective driver. 292 */ 293 case GRFIOCPUTCMAP: 294 case GRFIOCGETCMAP: 295 case GRFIOCSSPRITEPOS: 296 case GRFIOCGSPRITEPOS: 297 case GRFIOCSSPRITEINF: 298 case GRFIOCGSPRITEINF: 299 case GRFIOCGSPRITEMAX: 300 case GRFIOCBITBLT: 301 case GRFIOCSETMON: 302 case GRFTOGGLE: /* Toggles between Cirrus boards and native ECS on 303 Amiga. 15/11/94 ill */ 304 /* 305 * We need the minor dev number to get the overlay/image 306 * information for grf_ul. 307 */ 308 return(gp->g_mode(gp, GM_GRFIOCTL, data, cmd, dev)); 309 310 case GRFIOCBLANK: /* blank ioctl, IOCON/OFF will turn ite on */ 311 case FBIOSVIDEO: 312 error = gp->g_mode(gp, GM_GRFIOCTL, data, GRFIOCBLANK, dev); 313 if (!error) 314 gp->g_blank = *(int *)data; 315 return (error); 316 317 case FBIOGVIDEO: 318 *(int *)data = gp->g_blank; 319 return (0); 320 321 default: 322 #if NVIEW > 0 323 /* 324 * check to see whether it's a command recognized by the 325 * view code if the unit is 0 326 * XXX 327 */ 328 if (GRFUNIT(dev) == 0) { 329 extern const struct cdevsw view_cdevsw; 330 331 return((*view_cdevsw.d_ioctl)(dev, cmd, data, flag, l)); 332 } 333 #endif 334 error = EPASSTHROUGH; 335 break; 336 337 } 338 return(error); 339 } 340 341 /* 342 * map the contents of a graphics display card into process' 343 * memory space. 344 */ 345 paddr_t 346 grfmmap(dev_t dev, off_t off, int prot) 347 { 348 struct grf_softc *gp; 349 struct grfinfo *gi; 350 351 gp = grfsp[GRFUNIT(dev)]; 352 gi = &gp->g_display; 353 354 /* 355 * control registers 356 */ 357 if (off >= 0 && off < gi->gd_regsize) 358 return(((paddr_t)gi->gd_regaddr + off) >> PGSHIFT); 359 360 /* 361 * frame buffer 362 */ 363 if (off >= gi->gd_regsize && off < gi->gd_regsize+gi->gd_fbsize) { 364 off -= gi->gd_regsize; 365 return(((paddr_t)gi->gd_fbaddr + off) >> PGSHIFT); 366 } 367 /* bogus */ 368 return(-1); 369 } 370 371 int 372 grfon(dev_t dev) 373 { 374 struct grf_softc *gp; 375 376 gp = grfsp[GRFUNIT(dev)]; 377 378 if (gp->g_flags & GF_GRFON) 379 return(0); 380 381 gp->g_flags |= GF_GRFON; 382 if (gp->g_itedev != NODEV) 383 ite_off(gp->g_itedev, 3); 384 385 return(gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVON : GM_GRFON, 386 NULL, 0, 0)); 387 } 388 389 int 390 grfoff(dev_t dev) 391 { 392 struct grf_softc *gp; 393 int error; 394 395 gp = grfsp[GRFUNIT(dev)]; 396 397 if ((gp->g_flags & GF_GRFON) == 0) 398 return(0); 399 400 gp->g_flags &= ~GF_GRFON; 401 error = gp->g_mode(gp, (dev & GRFOVDEV) ? GM_GRFOVOFF : GM_GRFOFF, 402 NULL, 0, 0); 403 404 /* 405 * Closely tied together no X's 406 */ 407 if (gp->g_itedev != NODEV) 408 ite_on(gp->g_itedev, 2); 409 410 return(error); 411 } 412 413 int 414 grfsinfo(dev_t dev, struct grfdyninfo *dyninfo) 415 { 416 struct grf_softc *gp; 417 int error; 418 419 gp = grfsp[GRFUNIT(dev)]; 420 error = gp->g_mode(gp, GM_GRFCONFIG, dyninfo, 0, 0); 421 422 /* 423 * Closely tied together no X's 424 */ 425 if (gp->g_itedev != NODEV) 426 ite_reinit(gp->g_itedev); 427 return(error); 428 } 429 430 #if NWSDISPLAY > 0 431 void 432 grfcnprobe(struct consdev *cd) 433 { 434 struct grf_softc *gp; 435 int unit; 436 437 /* 438 * Find the first working grf device for being console. 439 * Ignore unit 0 (grfcc), which should use amidisplaycc instead. 440 */ 441 for (unit = 1; unit < NGRF; unit++) { 442 gp = grfsp[unit]; 443 if (gp != NULL && (gp->g_flags & GF_ALIVE)) { 444 cd->cn_pri = CN_INTERNAL; 445 cd->cn_dev = NODEV; /* initialized later by wscons */ 446 return; 447 } 448 } 449 450 /* no grf console alive */ 451 cd->cn_pri = CN_DEAD; 452 } 453 454 void 455 grfcninit(struct consdev *cd) 456 { 457 struct grf_softc *gp; 458 struct rasops_info *ri; 459 long defattr; 460 int unit; 461 462 /* find console grf and set up wsdisplay for it */ 463 for (unit = 1; unit < NGRF; unit++) { 464 gp = grfsp[unit]; 465 if (gp != NULL && (gp->g_flags & GF_ALIVE)) { 466 gp->g_flags |= GF_CONSOLE; /* we are console! */ 467 gp->g_screens[0]->ncols = gp->g_display.gd_fbwidth / 468 gp->g_screens[0]->fontwidth; 469 gp->g_screens[0]->nrows = gp->g_display.gd_fbheight / 470 gp->g_screens[0]->fontheight; 471 472 ri = grf_setup_rasops(gp, &console_vcons); 473 console_vcons.scr_cookie = gp; 474 defattr = 0; /* XXX */ 475 476 wsdisplay_preattach(gp->g_screens[0], ri, 0, 0, 477 defattr); 478 #if NKBD > 0 479 /* tell kbd device it is used as console keyboard */ 480 kbd_cnattach(); 481 #endif 482 return; 483 } 484 } 485 panic("grfcninit: lost console"); 486 } 487 488 static void 489 grf_init_screen(void *cookie, struct vcons_screen *scr, int existing, 490 long *defattr) 491 { 492 struct grf_softc *gp; 493 struct rasops_info *ri; 494 495 gp = cookie; 496 ri = grf_setup_rasops(gp, scr); 497 } 498 499 static struct rasops_info * 500 grf_setup_rasops(struct grf_softc *gp, struct vcons_screen *scr) 501 { 502 struct rasops_info *ri; 503 int i; 504 505 ri = &scr->scr_ri; 506 scr->scr_flags |= VCONS_DONT_READ; 507 memset(ri, 0, sizeof(struct rasops_info)); 508 509 ri->ri_rows = gp->g_screens[0]->nrows; 510 ri->ri_cols = gp->g_screens[0]->ncols; 511 ri->ri_hw = scr; 512 ri->ri_ops.cursor = gp->g_emulops->cursor; 513 ri->ri_ops.mapchar = gp->g_emulops->mapchar; 514 ri->ri_ops.copyrows = gp->g_emulops->copyrows; 515 ri->ri_ops.eraserows = gp->g_emulops->eraserows; 516 ri->ri_ops.copycols = gp->g_emulops->copycols; 517 ri->ri_ops.erasecols = gp->g_emulops->erasecols; 518 ri->ri_ops.putchar = gp->g_emulops->putchar; 519 ri->ri_ops.allocattr = gp->g_emulops->allocattr; 520 521 /* multiplication table for row-offsets */ 522 for (i = 0; i < ri->ri_rows; i++) 523 gp->g_rowoffset[i] = i * ri->ri_cols; 524 525 return ri; 526 } 527 528 paddr_t 529 grf_wsmmap(void *v, void *vs, off_t off, int prot) 530 { 531 struct vcons_data *vd; 532 struct grf_softc *gp; 533 struct grfinfo *gi; 534 535 vd = v; 536 gp = vd->cookie; 537 gi = &gp->g_display; 538 539 /* Normal fb mapping */ 540 if (off < gi->gd_fbsize) 541 return grf_wsmmap_md(((bus_addr_t)gp->g_fbkva) + off); 542 543 if (kauth_authorize_machdep(kauth_cred_get(), KAUTH_MACHDEP_UNMANAGEDMEM, 544 NULL, NULL, NULL, NULL) != 0) { 545 aprint_normal("%s: permission to mmap denied.\n", 546 device_xname(&gp->g_device)); 547 return -1; 548 } 549 550 if ((off >= (bus_addr_t)gp->g_fbkva ) && 551 (off < ( (bus_addr_t)gp->g_fbkva + (size_t)gi->gd_fbsize))) 552 return grf_wsmmap_md(off); 553 554 /* Handle register mapping */ 555 if ((off >= (bus_addr_t)gi->gd_regaddr) && 556 (off < ((bus_addr_t)gi->gd_regaddr + (size_t)gi->gd_regsize))) 557 return grf_wsmmap_md(off); 558 559 return -1; 560 } 561 562 static paddr_t 563 grf_wsmmap_md(off_t off) 564 { 565 #if defined(__m68k__) 566 return (paddr_t) m68k_btop(off); 567 #else 568 return -1; /* FIXME */ 569 #endif 570 } 571 572 int 573 grf_wsioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) 574 { 575 struct vcons_data *vd; 576 struct grf_softc *gp; 577 578 vd = v; 579 gp = vd->cookie; 580 581 switch (cmd) { 582 /* XXX: check if ptr to implementation is not null */ 583 case WSDISPLAYIO_GINFO: 584 return gp->g_wsioctl->ginfo(gp, data); 585 case WSDISPLAYIO_SMODE: 586 return gp->g_wsioctl->smode(gp, data); 587 case WSDISPLAYIO_GMODE: 588 return gp->g_wsioctl->gmode(gp, data); 589 case WSDISPLAYIO_GTYPE: 590 return gp->g_wsioctl->gtype(gp, data); 591 case WSDISPLAYIO_SVIDEO: 592 return gp->g_wsioctl->svideo(gp, data); 593 case WSDISPLAYIO_GVIDEO: 594 return gp->g_wsioctl->gvideo(gp, data); 595 case WSDISPLAYIO_GETCMAP: 596 return gp->g_wsioctl->getcmap(gp, data); 597 case WSDISPLAYIO_PUTCMAP: 598 return gp->g_wsioctl->putcmap(gp, data); 599 } 600 601 return EPASSTHROUGH; 602 } 603 604 /* wsdisplay_accessops ioctls */ 605 606 int 607 grf_wsaogetcmap(void *c, void *data) 608 { 609 u_int index, count; 610 struct grf_softc *gp; 611 struct wsdisplay_cmap *cm; 612 613 cm = (struct wsdisplay_cmap*) data; 614 gp = c; 615 index = 0; 616 count = 0; 617 618 if (gp->g_wsmode == WSDISPLAYIO_MODE_EMUL) 619 return EINVAL; 620 621 if (index >= 255 || count > 256 || index + count > 256) 622 return EINVAL; 623 624 /* 625 * TODO: copyout values for r, g, b. This function should be 626 * driver-specific... 627 */ 628 629 return 0; 630 } 631 632 int 633 grf_wsaoputcmap(void *c, void *data) 634 { 635 /* 636 * We probably couldn't care less about color map in MODE_EMUL, 637 * I don't know about X11 yet. Also, these ioctls could be used by 638 * fullscreen console programs (think wsdisplay picture viewer, or 639 * the wsimgshow tool written by Yasushi Oshima). 640 */ 641 struct grf_softc *gp; 642 643 gp = c; 644 645 if (gp->g_wsmode == WSDISPLAYIO_MODE_EMUL) 646 return EINVAL; 647 /* ... */ 648 649 return 0; 650 } 651 652 int 653 grf_wsaosvideo(void *c, void *data) 654 { 655 #if 0 656 struct grf_softc *gp; 657 dev_t dev; 658 int rv; 659 660 gp = c; 661 dev = (dev_t) &gp->g_grfdev; 662 663 if (*(u_int *)data == WSDISPLAYIO_VIDEO_OFF) { 664 if ((gp->g_flags & GF_GRFON) == 0) 665 rv = 0; 666 else { 667 gp->g_flags &= ~GF_GRFON; 668 rv = gp->g_mode(gp, (dev & GRFOVDEV) ? 669 GM_GRFOVOFF : GM_GRFOFF, NULL, 0, 0); 670 } 671 672 } else { 673 if ((gp->g_flags & GF_GRFON)) 674 rv = 0; 675 else 676 gp->g_flags |= GF_GRFON; 677 rv = gp->g_mode(gp, (dev & GRFOVDEV) ? 678 GM_GRFOVON : GM_GRFON, NULL, 0, 0); 679 } 680 681 return rv; 682 #endif 683 return 0; 684 } 685 686 int 687 grf_wsaogvideo(void *c, void *data) 688 { 689 struct grf_softc *gp; 690 691 gp = c; 692 693 if(gp->g_flags & GF_GRFON) 694 *(u_int *)data = WSDISPLAYIO_VIDEO_ON; 695 else 696 *(u_int *)data = WSDISPLAYIO_VIDEO_OFF; 697 698 return 0; 699 } 700 701 int 702 grf_wsaogtype(void *c, void *data) 703 { 704 struct grf_softc *gp; 705 706 gp = c; 707 708 *(u_int *)data = WSDISPLAY_TYPE_GRF; 709 return 0; 710 } 711 712 int 713 grf_wsaogmode(void *c, void *data) 714 { 715 struct grf_softc *gp; 716 717 gp = c; 718 719 *(u_int *)data = gp->g_wsmode; 720 return 0; 721 } 722 723 int 724 grf_wsaosmode(void *c, void *data) 725 { 726 /* XXX: should provide hw-dependent impl of this in grf_xxx driver? */ 727 struct grf_softc *gp; 728 729 gp = c; 730 731 if ((*(int*) data) != gp->g_wsmode) { 732 gp->g_wsmode = (*(int*) data); 733 if ((*(int*) data) == WSDISPLAYIO_MODE_EMUL) { 734 //vcons_redraw_screen( active vcons screen ); 735 } 736 } 737 return 0; 738 } 739 740 int 741 grf_wsaoginfo(void *c, void *data) 742 { 743 struct wsdisplay_fbinfo *fbinfo; 744 struct grf_softc *gp; 745 struct grfinfo *gi; 746 747 gp = c; 748 749 fbinfo = (struct wsdisplay_fbinfo *)data; 750 gi = &gp->g_display; 751 752 /* 753 * TODO: better sanity checking, it is possible that 754 * wsdisplay is initialized, but no screen is opened 755 * (for example, device is not used). 756 */ 757 758 /* 759 * We shold return truth about current mode here because 760 * X11 wsfb driver denepds on this! 761 */ 762 fbinfo->height = gi->gd_fbheight; 763 fbinfo->width = gi->gd_fbwidth; 764 fbinfo->depth = gi->gd_planes; 765 fbinfo->cmsize = gi->gd_colors; 766 767 return 0; 768 } 769 770 #endif /* NWSDISPLAY > 0 */ 771 772 #ifdef DEBUG 773 void 774 grfdebug(struct grf_softc *gp, const char *fmt, ...) 775 { 776 static int ccol = 0, crow = 1; 777 volatile char *cp; 778 char buf[256]; 779 va_list ap; 780 int ncols; 781 char *bp; 782 783 va_start(ap, fmt); 784 vsnprintf(buf, 256, fmt, ap); 785 va_end(ap); 786 787 cp = gp->g_fbkva; 788 ncols = gp->g_display.gd_fbwidth / 8; 789 cp += (crow * ncols + ccol) << 2; 790 for (bp = buf; *bp != '\0'; bp++) { 791 if (*bp == '\n') { 792 ccol = 0; 793 crow++; 794 continue; 795 } 796 *cp++ = *bp; 797 *cp = 0x0a; 798 cp += 3; 799 ccol++; 800 } 801 } 802 #endif /* DEBUG */ 803 804 #endif /* NGRF > 0 */ 805