1 /* $NetBSD: hpcfb.c,v 1.22 2002/09/01 11:38:29 takemura Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 5 * Shin Takemura and PocketBSD Project. All rights reserved. 6 * Copyright (c) 2000,2001 7 * SATO Kazumi. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the PocketBSD project 20 * and its contributors. 21 * 4. Neither the name of the project nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 */ 38 39 /* 40 * jump scroll, scroll thread, multiscreen, virtual text vram 41 * and hpcfb_emulops functions 42 * written by SATO Kazumi. 43 */ 44 45 #include <sys/cdefs.h> 46 __KERNEL_RCSID(0, "$NetBSD: hpcfb.c,v 1.22 2002/09/01 11:38:29 takemura Exp $"); 47 48 #define FBDEBUG 49 static const char _copyright[] __attribute__ ((unused)) = 50 "Copyright (c) 1999 Shin Takemura. All rights reserved."; 51 static const char _rcsid[] __attribute__ ((unused)) = 52 "$NetBSD: hpcfb.c,v 1.22 2002/09/01 11:38:29 takemura Exp $"; 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/kernel.h> 57 #include <sys/signalvar.h> 58 #include <sys/map.h> 59 #include <sys/proc.h> 60 #include <sys/kthread.h> 61 #include <sys/lock.h> 62 #include <sys/user.h> 63 #include <sys/device.h> 64 #include <sys/conf.h> 65 #include <sys/malloc.h> 66 #include <sys/buf.h> 67 #include <sys/ioctl.h> 68 69 #include <uvm/uvm_extern.h> 70 71 #include <machine/bus.h> 72 73 #include <dev/wscons/wsconsio.h> 74 #include <dev/wscons/wsdisplayvar.h> 75 #include <dev/wscons/wscons_callbacks.h> 76 77 #include <dev/wsfont/wsfont.h> 78 #include <dev/rasops/rasops.h> 79 80 #include <dev/hpc/hpcfbvar.h> 81 #include <dev/hpc/hpcfbio.h> 82 83 #include "bivideo.h" 84 #if NBIVIDEO > 0 85 #include <dev/hpc/bivideovar.h> 86 #endif 87 88 #ifdef FBDEBUG 89 int hpcfb_debug = 0; 90 #define DPRINTF(arg) if (hpcfb_debug) printf arg; 91 #else 92 #define DPRINTF(arg) 93 #endif 94 95 #ifndef HPCFB_MAX_COLUMN 96 #define HPCFB_MAX_COLUMN 130 97 #endif /* HPCFB_MAX_COLUMN */ 98 #ifndef HPCFB_MAX_ROW 99 #define HPCFB_MAX_ROW 80 100 #endif /* HPCFB_MAX_ROW */ 101 102 /* 103 * currently experimental 104 #define HPCFB_JUMP 105 */ 106 107 struct hpcfb_vchar { 108 u_int c; 109 long attr; 110 }; 111 112 struct hpcfb_tvrow { 113 int maxcol; 114 int spacecol; 115 struct hpcfb_vchar col[HPCFB_MAX_COLUMN]; 116 }; 117 118 struct hpcfb_devconfig { 119 struct rasops_info dc_rinfo; /* rasops information */ 120 121 int dc_blanked; /* currently had video disabled */ 122 struct hpcfb_softc *dc_sc; 123 int dc_rows; 124 int dc_cols; 125 struct hpcfb_tvrow *dc_tvram; 126 int dc_curx; 127 int dc_cury; 128 #ifdef HPCFB_JUMP 129 int dc_min_row; 130 int dc_max_row; 131 int dc_scroll; 132 struct callout dc_scroll_ch; 133 int dc_scroll_src; 134 int dc_scroll_dst; 135 int dc_scroll_num; 136 #endif /* HPCFB_JUMP */ 137 volatile int dc_state; 138 #define HPCFB_DC_CURRENT 0x80000000 139 #define HPCFB_DC_DRAWING 0x01 /* drawing raster ops */ 140 #define HPCFB_DC_TDRAWING 0x02 /* drawing tvram */ 141 #define HPCFB_DC_SCROLLPENDING 0x04 /* scroll is pending */ 142 #define HPCFB_DC_UPDATE 0x08 /* tvram update */ 143 #define HPCFB_DC_SCRDELAY 0x10 /* scroll time but delay it */ 144 #define HPCFB_DC_SCRTHREAD 0x20 /* in scroll thread or callout */ 145 #define HPCFB_DC_UPDATEALL 0x40 /* need to redraw all */ 146 #define HPCFB_DC_ABORT 0x80 /* abort redrawing */ 147 #define HPCFB_DC_SWITCHREQ 0x100 /* switch request exist */ 148 int dc_memsize; 149 u_char *dc_fbaddr; 150 }; 151 152 #define IS_DRAWABLE(dc) \ 153 (((dc)->dc_state&HPCFB_DC_CURRENT)&& \ 154 (((dc)->dc_state&(HPCFB_DC_DRAWING|HPCFB_DC_SWITCHREQ)) == 0)) 155 156 #define HPCFB_MAX_SCREEN 5 157 #define HPCFB_MAX_JUMP 5 158 159 struct hpcfb_softc { 160 struct device sc_dev; 161 struct hpcfb_devconfig *sc_dc; /* device configuration */ 162 const struct hpcfb_accessops *sc_accessops; 163 void *sc_accessctx; 164 void *sc_powerhook; /* power management hook */ 165 struct device *sc_wsdisplay; 166 int sc_screen_resumed; 167 int sc_polling; 168 int sc_mapping; 169 struct proc *sc_thread; 170 struct lock sc_lock; 171 void *sc_wantedscreen; 172 void (*sc_switchcb)(void *, int, int); 173 void *sc_switchcbarg; 174 struct callout sc_switch_callout; 175 int sc_nfbconf; 176 struct hpcfb_fbconf *sc_fbconflist; 177 }; 178 179 /* 180 * function prototypes 181 */ 182 int hpcfbmatch(struct device *, struct cfdata *, void *); 183 void hpcfbattach(struct device *, struct device *, void *); 184 int hpcfbprint(void *, const char *); 185 186 int hpcfb_ioctl(void *, u_long, caddr_t, int, struct proc *); 187 paddr_t hpcfb_mmap(void *, off_t, int); 188 189 void hpcfb_refresh_screen(struct hpcfb_softc *); 190 void hpcfb_doswitch(struct hpcfb_softc *); 191 192 #ifdef HPCFB_JUMP 193 static void hpcfb_create_thread(void *); 194 static void hpcfb_thread(void *); 195 #endif /* HPCFB_JUMP */ 196 197 static int hpcfb_init(struct hpcfb_fbconf *, struct hpcfb_devconfig *); 198 static int hpcfb_alloc_screen(void *, const struct wsscreen_descr *, 199 void **, int *, int *, long *); 200 static void hpcfb_free_screen(void *, void *); 201 static int hpcfb_show_screen(void *, void *, int, 202 void (*) (void *, int, int), void *); 203 static void hpcfb_pollc(void *, int); 204 static void hpcfb_power(int, void *); 205 static void hpcfb_cmap_reorder(struct hpcfb_fbconf *, 206 struct hpcfb_devconfig *); 207 208 static int pow(int, int); 209 210 void hpcfb_cursor(void *, int, int, int); 211 int hpcfb_mapchar(void *, int, unsigned int *); 212 void hpcfb_putchar(void *, int, int, u_int, long); 213 void hpcfb_copycols(void *, int, int, int, int); 214 void hpcfb_erasecols(void *, int, int, int, long); 215 void hpcfb_redraw(void *, int, int, int); 216 void hpcfb_copyrows(void *, int, int, int); 217 void hpcfb_eraserows(void *, int, int, long); 218 int hpcfb_allocattr(void *, int, int, int, long *); 219 void hpcfb_cursor_raw(void *, int, int, int); 220 221 #ifdef HPCFB_JUMP 222 void hpcfb_update(void *); 223 void hpcfb_do_scroll(void *); 224 void hpcfb_check_update(void *); 225 #endif /* HPCFB_JUMP */ 226 227 struct wsdisplay_emulops hpcfb_emulops = { 228 hpcfb_cursor, 229 hpcfb_mapchar, 230 hpcfb_putchar, 231 hpcfb_copycols, 232 hpcfb_erasecols, 233 hpcfb_copyrows, 234 hpcfb_eraserows, 235 hpcfb_allocattr 236 }; 237 238 /* 239 * static variables 240 */ 241 struct cfattach hpcfb_ca = { 242 sizeof(struct hpcfb_softc), hpcfbmatch, hpcfbattach, 243 }; 244 245 struct wsscreen_descr hpcfb_stdscreen = { 246 "std", 247 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 248 &hpcfb_emulops, /* XXX */ 249 0, 0, 250 WSSCREEN_REVERSE 251 }; 252 253 const struct wsscreen_descr *_hpcfb_scrlist[] = { 254 &hpcfb_stdscreen, 255 /* XXX other formats, graphics screen? */ 256 }; 257 258 struct wsscreen_list hpcfb_screenlist = { 259 sizeof(_hpcfb_scrlist) / sizeof(struct wsscreen_descr *), 260 _hpcfb_scrlist 261 }; 262 263 struct wsdisplay_accessops hpcfb_accessops = { 264 hpcfb_ioctl, 265 hpcfb_mmap, 266 hpcfb_alloc_screen, 267 hpcfb_free_screen, 268 hpcfb_show_screen, 269 0 /* load_font */, 270 hpcfb_pollc 271 }; 272 273 void hpcfb_tv_putchar(struct hpcfb_devconfig *, int, int, u_int, long); 274 void hpcfb_tv_copycols(struct hpcfb_devconfig *, int, int, int, int); 275 void hpcfb_tv_erasecols(struct hpcfb_devconfig *, int, int, int, long); 276 void hpcfb_tv_copyrows(struct hpcfb_devconfig *, int, int, int); 277 void hpcfb_tv_eraserows(struct hpcfb_devconfig *, int, int, long); 278 279 struct wsdisplay_emulops rasops_emul; 280 281 static int hpcfbconsole; 282 struct hpcfb_devconfig hpcfb_console_dc; 283 struct wsscreen_descr hpcfb_console_wsscreen; 284 struct hpcfb_tvrow hpcfb_console_tvram[HPCFB_MAX_ROW]; 285 286 /* 287 * function bodies 288 */ 289 static int 290 pow(int x, int n) 291 { 292 int res = 1; 293 while (0 < n--) { 294 res *= x; 295 } 296 return (res); 297 } 298 299 int 300 hpcfbmatch(struct device *parent, struct cfdata *match, void *aux) 301 { 302 return (1); 303 } 304 305 void 306 hpcfbattach(struct device *parent, struct device *self, void *aux) 307 { 308 struct hpcfb_softc *sc = (struct hpcfb_softc *)self; 309 struct hpcfb_attach_args *ha = aux; 310 struct wsemuldisplaydev_attach_args wa; 311 312 sc->sc_accessops = ha->ha_accessops; 313 sc->sc_accessctx = ha->ha_accessctx; 314 sc->sc_nfbconf = ha->ha_nfbconf; 315 sc->sc_fbconflist = ha->ha_fbconflist; 316 317 if (hpcfbconsole) { 318 sc->sc_dc = &hpcfb_console_dc; 319 hpcfb_console_dc.dc_sc = sc; 320 printf(": %dx%d pixels, %d colors, %dx%d chars", 321 sc->sc_dc->dc_rinfo.ri_width,sc->sc_dc->dc_rinfo.ri_height, 322 pow(2, sc->sc_dc->dc_rinfo.ri_depth), 323 sc->sc_dc->dc_rinfo.ri_cols,sc->sc_dc->dc_rinfo.ri_rows); 324 /* Set video chip dependent CLUT if any. */ 325 if (sc->sc_accessops->setclut) 326 sc->sc_accessops->setclut(sc->sc_accessctx, 327 &hpcfb_console_dc.dc_rinfo); 328 } 329 printf("\n"); 330 331 sc->sc_polling = 0; /* XXX */ 332 sc->sc_mapping = 0; /* XXX */ 333 callout_init(&sc->sc_switch_callout); 334 335 /* Add a power hook to power management */ 336 sc->sc_powerhook = powerhook_establish(hpcfb_power, sc); 337 if (sc->sc_powerhook == NULL) 338 printf("%s: WARNING: unable to establish power hook\n", 339 sc->sc_dev.dv_xname); 340 341 wa.console = hpcfbconsole; 342 wa.scrdata = &hpcfb_screenlist; 343 wa.accessops = &hpcfb_accessops; 344 wa.accesscookie = sc; 345 346 sc->sc_wsdisplay = config_found(self, &wa, wsemuldisplaydevprint); 347 348 #ifdef HPCFB_JUMP 349 /* 350 * Create a kernel thread to scroll, 351 */ 352 kthread_create(hpcfb_create_thread, sc); 353 #endif /* HPCFB_JUMP */ 354 } 355 356 #ifdef HPCFB_JUMP 357 void 358 hpcfb_create_thread(void *arg) 359 { 360 struct hpcfb_softc *sc = arg; 361 362 if (kthread_create1(hpcfb_thread, sc, &sc->sc_thread, 363 "%s", sc->sc_dev.dv_xname) == 0) 364 return; 365 366 /* 367 * We were unable to create the HPCFB thread; bail out. 368 */ 369 sc->sc_thread = 0; 370 printf("%s: unable to create thread, kernel hpcfb scroll support disabled\n", 371 sc->sc_dev.dv_xname); 372 } 373 374 void 375 hpcfb_thread(void *arg) 376 { 377 struct hpcfb_softc *sc = arg; 378 379 /* 380 * Loop forever, doing a periodic check for update events. 381 */ 382 for (;;) { 383 /* HPCFB_LOCK(sc); */ 384 sc->sc_dc->dc_state |= HPCFB_DC_SCRTHREAD; 385 if (!sc->sc_mapping) /* draw only EMUL mode */ 386 hpcfb_update(sc->sc_dc); 387 sc->sc_dc->dc_state &= ~HPCFB_DC_SCRTHREAD; 388 /* APM_UNLOCK(sc); */ 389 (void) tsleep(sc, PWAIT, "hpcfb", (8 * hz) / 7 / 10); 390 } 391 } 392 #endif /* HPCFB_JUMP */ 393 394 /* Print function (for parent devices). */ 395 int 396 hpcfbprint(void *aux, const char *pnp) 397 { 398 if (pnp) 399 printf("hpcfb at %s", pnp); 400 401 return (UNCONF); 402 } 403 404 int 405 hpcfb_cnattach(struct hpcfb_fbconf *fbconf) 406 { 407 struct hpcfb_fbconf __fbconf __attribute__((__unused__)); 408 long defattr; 409 410 DPRINTF(("%s(%d): hpcfb_cnattach()\n", __FILE__, __LINE__)); 411 #if NBIVIDEO > 0 412 if (fbconf == 0) { 413 memset(&__fbconf, 0, sizeof(struct hpcfb_fbconf)); 414 if (bivideo_getcnfb(&__fbconf) != 0) 415 return (ENXIO); 416 fbconf = &__fbconf; 417 } 418 #endif /* NBIVIDEO > 0 */ 419 memset(&hpcfb_console_dc, 0, sizeof(struct hpcfb_devconfig)); 420 if (hpcfb_init(fbconf, &hpcfb_console_dc) != 0) 421 return (ENXIO); 422 hpcfb_console_dc.dc_state |= HPCFB_DC_CURRENT; 423 424 hpcfb_console_dc.dc_tvram = hpcfb_console_tvram; 425 /* clear screen */ 426 memset(hpcfb_console_tvram, 0, sizeof(hpcfb_console_tvram)); 427 hpcfb_redraw(&hpcfb_console_dc, 0, hpcfb_console_dc.dc_rows, 1); 428 429 hpcfb_console_wsscreen = hpcfb_stdscreen; 430 hpcfb_console_wsscreen.nrows = hpcfb_console_dc.dc_rows; 431 hpcfb_console_wsscreen.ncols = hpcfb_console_dc.dc_cols; 432 hpcfb_console_wsscreen.capabilities = hpcfb_console_dc.dc_rinfo.ri_caps; 433 hpcfb_allocattr(&hpcfb_console_dc, 434 WSCOL_WHITE, WSCOL_BLACK, 0, &defattr); 435 wsdisplay_cnattach(&hpcfb_console_wsscreen, &hpcfb_console_dc, 436 0, 0, defattr); 437 hpcfbconsole = 1; 438 439 return (0); 440 } 441 442 int 443 hpcfb_init(struct hpcfb_fbconf *fbconf, struct hpcfb_devconfig *dc) 444 { 445 struct rasops_info *ri; 446 vaddr_t fbaddr; 447 448 fbaddr = (vaddr_t)fbconf->hf_baseaddr; 449 dc->dc_fbaddr = (u_char *)fbaddr; 450 451 /* init rasops */ 452 ri = &dc->dc_rinfo; 453 memset(ri, 0, sizeof(struct rasops_info)); 454 ri->ri_depth = fbconf->hf_pixel_width; 455 ri->ri_bits = (caddr_t)fbaddr; 456 ri->ri_width = fbconf->hf_width; 457 ri->ri_height = fbconf->hf_height; 458 ri->ri_stride = fbconf->hf_bytes_per_line; 459 #if 0 460 ri->ri_flg = RI_FORCEMONO | RI_CURSOR; 461 #else 462 ri->ri_flg = RI_CURSOR; 463 #endif 464 switch (ri->ri_depth) { 465 case 8: 466 if (32 <= fbconf->hf_pack_width && 467 (fbconf->hf_order_flags & HPCFB_REVORDER_BYTE) && 468 (fbconf->hf_order_flags & HPCFB_REVORDER_WORD)) { 469 ri->ri_flg |= RI_BSWAP; 470 } 471 break; 472 default: 473 if (fbconf->hf_order_flags & HPCFB_REVORDER_BYTE) { 474 #if BYTE_ORDER == BIG_ENDIAN 475 ri->ri_flg |= RI_BSWAP; 476 #endif 477 } else { 478 #if BYTE_ORDER == LITTLE_ENDIAN 479 ri->ri_flg |= RI_BSWAP; 480 #endif 481 } 482 break; 483 } 484 485 if (rasops_init(ri, HPCFB_MAX_ROW, HPCFB_MAX_COLUMN)) { 486 panic("%s(%d): rasops_init() failed!", __FILE__, __LINE__); 487 } 488 489 /* over write color map of rasops */ 490 hpcfb_cmap_reorder (fbconf, dc); 491 492 dc->dc_curx = -1; 493 dc->dc_cury = -1; 494 dc->dc_rows = dc->dc_rinfo.ri_rows; 495 dc->dc_cols = dc->dc_rinfo.ri_cols; 496 #ifdef HPCFB_JUMP 497 dc->dc_max_row = 0; 498 dc->dc_min_row = dc->dc_rows; 499 dc->dc_scroll = 0; 500 callout_init(&dc->dc_scroll_ch); 501 #endif /* HPCFB_JUMP */ 502 dc->dc_memsize = ri->ri_stride * ri->ri_height; 503 /* hook rasops in hpcfb_ops */ 504 rasops_emul = ri->ri_ops; /* struct copy */ 505 ri->ri_ops = hpcfb_emulops; /* struct copy */ 506 507 return (0); 508 } 509 510 static void 511 hpcfb_cmap_reorder(struct hpcfb_fbconf *fbconf, struct hpcfb_devconfig *dc) 512 { 513 struct rasops_info *ri = &dc->dc_rinfo; 514 int reverse = fbconf->hf_access_flags & HPCFB_ACCESS_REVERSE; 515 int *cmap = ri->ri_devcmap; 516 int i, j, bg, fg, tmp; 517 518 /* 519 * Set forground and background so that the screen 520 * looks black on white. 521 * Normally, black = 00 and white = ff. 522 * HPCFB_ACCESS_REVERSE means black = ff and white = 00. 523 */ 524 switch (fbconf->hf_pixel_width) { 525 case 1: 526 /* FALLTHROUGH */ 527 case 2: 528 /* FALLTHROUGH */ 529 case 4: 530 if (reverse) { 531 bg = 0; 532 fg = ~0; 533 } else { 534 bg = ~0; 535 fg = 0; 536 } 537 /* for gray-scale LCD, hi-contrast color map */ 538 cmap[0] = bg; 539 for (i = 1; i < 16; i++) 540 cmap[i] = fg; 541 break; 542 case 8: 543 /* FALLTHROUGH */ 544 case 16: 545 if (reverse) { 546 for (i = 0, j = 15; i < 8; i++, j--) { 547 tmp = cmap[i]; 548 cmap[i] = cmap[j]; 549 cmap[j] = tmp; 550 } 551 } 552 break; 553 } 554 } 555 556 int 557 hpcfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p) 558 { 559 struct hpcfb_softc *sc = v; 560 struct hpcfb_devconfig *dc = sc->sc_dc; 561 struct wsdisplay_fbinfo *wdf; 562 563 DPRINTF(("hpcfb_ioctl(cmd=0x%lx)\n", cmd)); 564 switch (cmd) { 565 case WSKBDIO_BELL: 566 return (0); 567 break; 568 569 case WSDISPLAYIO_GTYPE: 570 *(u_int *)data = WSDISPLAY_TYPE_HPCFB; 571 return (0); 572 573 case WSDISPLAYIO_GINFO: 574 wdf = (void *)data; 575 wdf->height = dc->dc_rinfo.ri_height; 576 wdf->width = dc->dc_rinfo.ri_width; 577 wdf->depth = dc->dc_rinfo.ri_depth; 578 wdf->cmsize = 256; /* XXXX */ 579 return (0); 580 581 case WSDISPLAYIO_SMODE: 582 if (*(int *)data == WSDISPLAYIO_MODE_EMUL){ 583 if (sc->sc_mapping){ 584 sc->sc_mapping = 0; 585 if (dc->dc_state&HPCFB_DC_DRAWING) 586 dc->dc_state &= ~HPCFB_DC_ABORT; 587 #ifdef HPCFB_FORCE_REDRAW 588 hpcfb_refresh_screen(sc); 589 #else 590 dc->dc_state |= HPCFB_DC_UPDATEALL; 591 #endif 592 } 593 } else { 594 if (!sc->sc_mapping) { 595 sc->sc_mapping = 1; 596 dc->dc_state |= HPCFB_DC_ABORT; 597 } 598 sc->sc_mapping = 1; 599 } 600 if (sc && sc->sc_accessops->iodone) 601 (*sc->sc_accessops->iodone)(sc->sc_accessctx); 602 return (0); 603 604 case WSDISPLAYIO_GETCMAP: 605 case WSDISPLAYIO_PUTCMAP: 606 case WSDISPLAYIO_SVIDEO: 607 case WSDISPLAYIO_GVIDEO: 608 case WSDISPLAYIO_GETPARAM: 609 case WSDISPLAYIO_SETPARAM: 610 case HPCFBIO_GCONF: 611 case HPCFBIO_SCONF: 612 case HPCFBIO_GDSPCONF: 613 case HPCFBIO_SDSPCONF: 614 case HPCFBIO_GOP: 615 case HPCFBIO_SOP: 616 return ((*sc->sc_accessops->ioctl)(sc->sc_accessctx, 617 cmd, data, flag, p)); 618 619 default: 620 if (IOCGROUP(cmd) != 't') 621 DPRINTF(("%s(%d): hpcfb_ioctl(%lx, %lx) grp=%c num=%ld\n", 622 __FILE__, __LINE__, 623 cmd, (u_long)data, (char)IOCGROUP(cmd), cmd&0xff)); 624 break; 625 } 626 627 return (EPASSTHROUGH); /* Inappropriate ioctl for device */ 628 } 629 630 paddr_t 631 hpcfb_mmap(void *v, off_t offset, int prot) 632 { 633 struct hpcfb_softc *sc = v; 634 635 return ((*sc->sc_accessops->mmap)(sc->sc_accessctx, offset, prot)); 636 } 637 638 static void 639 hpcfb_power(int why, void *arg) 640 { 641 struct hpcfb_softc *sc = arg; 642 643 if (sc->sc_dc == NULL) 644 return; /* You have no screen yet. */ 645 646 switch (why) { 647 case PWR_STANDBY: 648 break; 649 case PWR_SOFTSUSPEND: 650 /* XXX, casting to 'struct wsdisplay_softc *' means 651 that you should not call the method here... */ 652 sc->sc_screen_resumed = wsdisplay_getactivescreen( 653 (struct wsdisplay_softc *)sc->sc_wsdisplay); 654 if (wsdisplay_switch(sc->sc_wsdisplay, 655 WSDISPLAY_NULLSCREEN, 656 1 /* waitok */) == 0) { 657 wsscreen_switchwait( 658 (struct wsdisplay_softc *)sc->sc_wsdisplay, 659 WSDISPLAY_NULLSCREEN); 660 } else { 661 sc->sc_screen_resumed = WSDISPLAY_NULLSCREEN; 662 } 663 664 sc->sc_dc->dc_state &= ~HPCFB_DC_CURRENT; 665 break; 666 case PWR_SOFTRESUME: 667 sc->sc_dc->dc_state |= HPCFB_DC_CURRENT; 668 if (sc->sc_screen_resumed != WSDISPLAY_NULLSCREEN) 669 wsdisplay_switch(sc->sc_wsdisplay, 670 sc->sc_screen_resumed, 671 1 /* waitok */); 672 break; 673 } 674 } 675 676 void 677 hpcfb_refresh_screen(struct hpcfb_softc *sc) 678 { 679 struct hpcfb_devconfig *dc = sc->sc_dc; 680 int x, y; 681 682 DPRINTF(("hpcfb_refres_screen()\n")); 683 if (dc == NULL) 684 return; 685 686 #ifdef HPCFB_JUMP 687 if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 688 dc->dc_state &= ~HPCFB_DC_SCROLLPENDING; 689 dc->dc_state &= ~HPCFB_DC_UPDATE; 690 callout_stop(&dc->dc_scroll_ch); 691 } 692 #endif /* HPCFB_JUMP */ 693 /* 694 * refresh screen 695 */ 696 dc->dc_state &= ~HPCFB_DC_UPDATEALL; 697 x = dc->dc_curx; 698 y = dc->dc_cury; 699 if (0 <= x && 0 <= y) 700 hpcfb_cursor_raw(dc, 0, y, x); /* disable cursor */ 701 /* redraw all text */ 702 hpcfb_redraw(dc, 0, dc->dc_rows, 1); 703 if (0 <= x && 0 <= y) 704 hpcfb_cursor_raw(dc, 1, y, x); /* enable cursor */ 705 } 706 707 static int 708 hpcfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep, 709 int *curxp, int *curyp, long *attrp) 710 { 711 struct hpcfb_softc *sc = v; 712 struct hpcfb_devconfig *dc; 713 714 DPRINTF(("%s(%d): hpcfb_alloc_screen()\n", __FILE__, __LINE__)); 715 716 dc = malloc(sizeof(struct hpcfb_devconfig), M_DEVBUF, M_WAITOK|M_ZERO); 717 if (dc == NULL) 718 return (ENOMEM); 719 720 dc->dc_sc = sc; 721 if (hpcfb_init(&sc->sc_fbconflist[0], dc) != 0) 722 return (EINVAL); 723 if (sc->sc_accessops->font) { 724 sc->sc_accessops->font(sc->sc_accessctx, 725 dc->dc_rinfo.ri_font); 726 } 727 /* Set video chip dependent CLUT if any. */ 728 if (sc->sc_accessops->setclut) 729 sc->sc_accessops->setclut(sc->sc_accessctx, &dc->dc_rinfo); 730 printf("hpcfb: %dx%d pixels, %d colors, %dx%d chars\n", 731 dc->dc_rinfo.ri_width, dc->dc_rinfo.ri_height, 732 pow(2, dc->dc_rinfo.ri_depth), 733 dc->dc_rinfo.ri_cols, dc->dc_rinfo.ri_rows); 734 735 /* 736 * XXX, wsdisplay won't reffer the information in wsscreen_descr 737 * structure until alloc_screen will be called, at least, under 738 * current implementation... 739 */ 740 hpcfb_stdscreen.nrows = dc->dc_rows; 741 hpcfb_stdscreen.ncols = dc->dc_cols; 742 hpcfb_stdscreen.capabilities = dc->dc_rinfo.ri_caps; 743 744 dc->dc_fbaddr = dc->dc_rinfo.ri_bits; 745 dc->dc_rows = dc->dc_rinfo.ri_rows; 746 dc->dc_cols = dc->dc_rinfo.ri_cols; 747 dc->dc_memsize = dc->dc_rinfo.ri_stride * dc->dc_rinfo.ri_height; 748 749 dc->dc_curx = -1; 750 dc->dc_cury = -1; 751 dc->dc_tvram = malloc(sizeof(struct hpcfb_tvrow)*dc->dc_rows, 752 M_DEVBUF, M_WAITOK|M_ZERO); 753 if (dc->dc_tvram == NULL){ 754 free(dc, M_DEVBUF); 755 return (ENOMEM); 756 } 757 758 *curxp = 0; 759 *curyp = 0; 760 *cookiep = dc; 761 hpcfb_allocattr(*cookiep, WSCOL_WHITE, WSCOL_BLACK, 0, attrp); 762 DPRINTF(("%s(%d): hpcfb_alloc_screen(): 0x%p\n", 763 __FILE__, __LINE__, dc)); 764 765 return (0); 766 } 767 768 static void 769 hpcfb_free_screen(void *v, void *cookie) 770 { 771 struct hpcfb_devconfig *dc = cookie; 772 773 DPRINTF(("%s(%d): hpcfb_free_screen(0x%p)\n", 774 __FILE__, __LINE__, cookie)); 775 #ifdef DIAGNOSTIC 776 if (dc == &hpcfb_console_dc) 777 panic("hpcfb_free_screen: console"); 778 #endif 779 free(dc->dc_tvram, M_DEVBUF); 780 free(dc, M_DEVBUF); 781 } 782 783 static int 784 hpcfb_show_screen(void *v, void *cookie, int waitok, 785 void (*cb)(void *, int, int), void *cbarg) 786 { 787 struct hpcfb_softc *sc = v; 788 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 789 struct hpcfb_devconfig *odc; 790 791 DPRINTF(("%s(%d): hpcfb_show_screen(0x%p)\n", 792 __FILE__, __LINE__, dc)); 793 794 odc = sc->sc_dc; 795 796 if (dc == NULL || odc == dc) { 797 hpcfb_refresh_screen(sc); 798 return (0); 799 } 800 801 if (odc != NULL) { 802 odc->dc_state |= HPCFB_DC_SWITCHREQ; 803 804 if ((odc->dc_state&HPCFB_DC_DRAWING) != 0) { 805 odc->dc_state |= HPCFB_DC_ABORT; 806 } 807 } 808 809 sc->sc_wantedscreen = cookie; 810 sc->sc_switchcb = cb; 811 sc->sc_switchcbarg = cbarg; 812 if (cb) { 813 callout_reset(&sc->sc_switch_callout, 0, 814 (void(*)(void *))hpcfb_doswitch, sc); 815 return (EAGAIN); 816 } 817 818 hpcfb_doswitch(sc); 819 return (0); 820 } 821 822 void 823 hpcfb_doswitch(struct hpcfb_softc *sc) 824 { 825 struct hpcfb_devconfig *dc; 826 struct hpcfb_devconfig *odc; 827 828 DPRINTF(("hpcfb_doswitch()\n")); 829 odc = sc->sc_dc; 830 dc = sc->sc_wantedscreen; 831 832 if (!dc) { 833 (*sc->sc_switchcb)(sc->sc_switchcbarg, EIO, 0); 834 odc->dc_state &= ~HPCFB_DC_SWITCHREQ; 835 return; 836 } 837 838 if (odc == dc) { 839 odc->dc_state &= ~HPCFB_DC_SWITCHREQ; 840 return; 841 } 842 843 if (odc) { 844 #ifdef HPCFB_JUMP 845 odc->dc_state |= HPCFB_DC_ABORT; 846 #endif /* HPCFB_JUMP */ 847 848 if (odc->dc_curx >= 0 && odc->dc_cury >= 0) 849 hpcfb_cursor_raw(odc, 0, odc->dc_cury, odc->dc_curx); 850 /* disable cursor */ 851 /* disable old screen */ 852 odc->dc_state &= ~HPCFB_DC_CURRENT; 853 /* XXX, This is too dangerous. 854 odc->dc_rinfo.ri_bits = NULL; 855 */ 856 } 857 /* switch screen to new one */ 858 dc->dc_state |= HPCFB_DC_CURRENT; 859 dc->dc_state &= ~HPCFB_DC_ABORT; 860 dc->dc_rinfo.ri_bits = dc->dc_fbaddr; 861 sc->sc_dc = dc; 862 863 /* redraw screen image */ 864 hpcfb_refresh_screen(sc); 865 866 sc->sc_wantedscreen = NULL; 867 if (sc->sc_switchcb) 868 (*sc->sc_switchcb)(sc->sc_switchcbarg, 0, 0); 869 870 if (odc != NULL) 871 odc->dc_state &= ~HPCFB_DC_SWITCHREQ; 872 dc->dc_state &= ~HPCFB_DC_SWITCHREQ; 873 return; 874 } 875 876 static void 877 hpcfb_pollc(void *v, int on) 878 { 879 struct hpcfb_softc *sc = v; 880 881 if (sc == NULL) 882 return; 883 sc->sc_polling = on; 884 if (sc->sc_accessops->iodone) 885 (*sc->sc_accessops->iodone)(sc->sc_accessctx); 886 if (on) { 887 hpcfb_refresh_screen(sc); 888 if (sc->sc_accessops->iodone) 889 (*sc->sc_accessops->iodone)(sc->sc_accessctx); 890 } 891 892 return; 893 } 894 895 /* 896 * cursor 897 */ 898 void 899 hpcfb_cursor(void *cookie, int on, int row, int col) 900 { 901 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 902 903 if (on) { 904 dc->dc_curx = col; 905 dc->dc_cury = row; 906 } else { 907 dc->dc_curx = -1; 908 dc->dc_cury = -1; 909 } 910 911 hpcfb_cursor_raw(cookie, on, row, col); 912 } 913 914 void 915 hpcfb_cursor_raw(cookie, on, row, col) 916 void *cookie; 917 int on, row, col; 918 { 919 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 920 struct hpcfb_softc *sc = dc->dc_sc; 921 struct rasops_info *ri = &dc->dc_rinfo; 922 int curwidth, curheight; 923 int xoff, yoff; 924 925 #ifdef HPCFB_JUMP 926 if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 927 dc->dc_state |= HPCFB_DC_UPDATE; 928 return; 929 } 930 #endif /* HPCFB_JUMP */ 931 if (!IS_DRAWABLE(dc)) { 932 return; 933 } 934 935 if (ri->ri_bits == NULL) 936 return; 937 938 dc->dc_state |= HPCFB_DC_DRAWING; 939 if (sc && sc->sc_accessops->cursor) { 940 xoff = col * ri->ri_font->fontwidth; 941 yoff = row * ri->ri_font->fontheight; 942 curheight = ri->ri_font->fontheight; 943 curwidth = ri->ri_font->fontwidth; 944 (*sc->sc_accessops->cursor)(sc->sc_accessctx, 945 on, xoff, yoff, curwidth, curheight); 946 } else 947 rasops_emul.cursor(ri, on, row, col); 948 dc->dc_state &= ~HPCFB_DC_DRAWING; 949 } 950 951 /* 952 * mapchar 953 */ 954 int 955 hpcfb_mapchar(void *cookie, int c, unsigned int *cp) 956 { 957 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 958 struct rasops_info *ri = &dc->dc_rinfo; 959 960 return (rasops_emul.mapchar(ri, c, cp)); 961 } 962 963 /* 964 * putchar 965 */ 966 void 967 hpcfb_tv_putchar(struct hpcfb_devconfig *dc, int row, int col, u_int uc, 968 long attr) 969 { 970 struct hpcfb_tvrow *vscn = dc->dc_tvram; 971 struct hpcfb_vchar *vc = &vscn[row].col[col]; 972 struct hpcfb_vchar *vcb; 973 974 if (vscn == 0) 975 return; 976 977 dc->dc_state |= HPCFB_DC_TDRAWING; 978 #ifdef HPCFB_JUMP 979 if (row < dc->dc_min_row) 980 dc->dc_min_row = row; 981 if (row > dc->dc_max_row) 982 dc->dc_max_row = row; 983 984 #endif /* HPCFB_JUMP */ 985 if (vscn[row].maxcol +1 == col) 986 vscn[row].maxcol = col; 987 else if (vscn[row].maxcol < col) { 988 vcb = &vscn[row].col[vscn[row].maxcol+1]; 989 memset(vcb, 0, 990 sizeof(struct hpcfb_vchar)*(col-vscn[row].maxcol-1)); 991 vscn[row].maxcol = col; 992 } 993 vc->c = uc; 994 vc->attr = attr; 995 dc->dc_state &= ~HPCFB_DC_TDRAWING; 996 #ifdef HPCFB_JUMP 997 hpcfb_check_update(dc); 998 #endif /* HPCFB_JUMP */ 999 } 1000 1001 void 1002 hpcfb_putchar(void *cookie, int row, int col, u_int uc, long attr) 1003 { 1004 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1005 struct hpcfb_softc *sc = dc->dc_sc; 1006 struct rasops_info *ri = &dc->dc_rinfo; 1007 int xoff; 1008 int yoff; 1009 int fclr, uclr; 1010 struct wsdisplay_font *font; 1011 1012 hpcfb_tv_putchar(dc, row, col, uc, attr); 1013 #ifdef HPCFB_JUMP 1014 if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1015 dc->dc_state |= HPCFB_DC_UPDATE; 1016 return; 1017 } 1018 #endif /* HPCFB_JUMP */ 1019 1020 if (!IS_DRAWABLE(dc)) { 1021 return; 1022 } 1023 1024 if (ri->ri_bits == NULL) 1025 return; 1026 1027 dc->dc_state |= HPCFB_DC_DRAWING; 1028 if (sc && sc->sc_accessops->putchar 1029 && (dc->dc_state&HPCFB_DC_CURRENT)) { 1030 font = ri->ri_font; 1031 yoff = row * ri->ri_font->fontheight; 1032 xoff = col * ri->ri_font->fontwidth; 1033 fclr = ri->ri_devcmap[((u_int)attr >> 24) & 15]; 1034 uclr = ri->ri_devcmap[((u_int)attr >> 16) & 15]; 1035 1036 (*sc->sc_accessops->putchar)(sc->sc_accessctx, 1037 xoff, yoff, font, fclr, uclr, uc, attr); 1038 } else 1039 rasops_emul.putchar(ri, row, col, uc, attr); 1040 dc->dc_state &= ~HPCFB_DC_DRAWING; 1041 #ifdef HPCFB_JUMP 1042 hpcfb_check_update(dc); 1043 #endif /* HPCFB_JUMP */ 1044 } 1045 1046 /* 1047 * copycols 1048 */ 1049 void 1050 hpcfb_tv_copycols(struct hpcfb_devconfig *dc, int row, int srccol, int dstcol, 1051 int ncols) 1052 { 1053 struct hpcfb_tvrow *vscn = dc->dc_tvram; 1054 struct hpcfb_vchar *svc = &vscn[row].col[srccol]; 1055 struct hpcfb_vchar *dvc = &vscn[row].col[dstcol]; 1056 1057 if (vscn == 0) 1058 return; 1059 1060 dc->dc_state |= HPCFB_DC_TDRAWING; 1061 #ifdef HPCFB_JUMP 1062 if (row < dc->dc_min_row) 1063 dc->dc_min_row = row; 1064 if (row > dc->dc_max_row) 1065 dc->dc_max_row = row; 1066 #endif /* HPCFB_JUMP */ 1067 1068 memcpy(dvc, svc, ncols*sizeof(struct hpcfb_vchar)); 1069 if (vscn[row].maxcol < srccol+ncols-1) 1070 vscn[row].maxcol = srccol+ncols-1; 1071 if (vscn[row].maxcol < dstcol+ncols-1) 1072 vscn[row].maxcol = dstcol+ncols-1; 1073 dc->dc_state &= ~HPCFB_DC_TDRAWING; 1074 #ifdef HPCFB_JUMP 1075 hpcfb_check_update(dc); 1076 #endif /* HPCFB_JUMP */ 1077 } 1078 1079 void 1080 hpcfb_copycols(void *cookie, int row, int srccol, int dstcol, int ncols) 1081 { 1082 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1083 struct hpcfb_softc *sc = dc->dc_sc; 1084 struct rasops_info *ri = &dc->dc_rinfo; 1085 int srcxoff,dstxoff; 1086 int srcyoff,dstyoff; 1087 int height, width; 1088 1089 hpcfb_tv_copycols(dc, row, srccol, dstcol, ncols); 1090 #ifdef HPCFB_JUMP 1091 if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1092 dc->dc_state |= HPCFB_DC_UPDATE; 1093 return; 1094 } 1095 #endif /* HPCFB_JUMP */ 1096 if (!IS_DRAWABLE(dc)) { 1097 return; 1098 } 1099 1100 if (ri->ri_bits == NULL) 1101 return; 1102 1103 dc->dc_state |= HPCFB_DC_DRAWING; 1104 if (sc && sc->sc_accessops->bitblit 1105 && (dc->dc_state&HPCFB_DC_CURRENT)) { 1106 srcxoff = srccol * ri->ri_font->fontwidth; 1107 srcyoff = row * ri->ri_font->fontheight; 1108 dstxoff = dstcol * ri->ri_font->fontwidth; 1109 dstyoff = row * ri->ri_font->fontheight; 1110 width = ncols * ri->ri_font->fontwidth; 1111 height = ri->ri_font->fontheight; 1112 (*sc->sc_accessops->bitblit)(sc->sc_accessctx, 1113 srcxoff, srcyoff, dstxoff, dstyoff, height, width); 1114 } else 1115 rasops_emul.copycols(ri, row, srccol, dstcol, ncols); 1116 dc->dc_state &= ~HPCFB_DC_DRAWING; 1117 #ifdef HPCFB_JUMP 1118 hpcfb_check_update(dc); 1119 #endif /* HPCFB_JUMP */ 1120 } 1121 1122 1123 /* 1124 * erasecols 1125 */ 1126 void 1127 hpcfb_tv_erasecols(struct hpcfb_devconfig *dc, int row, int startcol, 1128 int ncols, long attr) 1129 { 1130 struct hpcfb_tvrow *vscn = dc->dc_tvram; 1131 1132 if (vscn == 0) 1133 return; 1134 1135 dc->dc_state |= HPCFB_DC_TDRAWING; 1136 #ifdef HPCFB_JUMP 1137 if (row < dc->dc_min_row) 1138 dc->dc_min_row = row; 1139 if (row > dc->dc_max_row) 1140 dc->dc_max_row = row; 1141 #endif /* HPCFB_JUMP */ 1142 1143 vscn[row].maxcol = startcol-1; 1144 if (vscn[row].spacecol < startcol+ncols-1) 1145 vscn[row].spacecol = startcol+ncols-1; 1146 dc->dc_state &= ~HPCFB_DC_TDRAWING; 1147 #ifdef HPCFB_JUMP 1148 hpcfb_check_update(dc); 1149 #endif /* HPCFB_JUMP */ 1150 } 1151 1152 void 1153 hpcfb_erasecols(void *cookie, int row, int startcol, int ncols, long attr) 1154 { 1155 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1156 struct hpcfb_softc *sc = dc->dc_sc; 1157 struct rasops_info *ri = &dc->dc_rinfo; 1158 int xoff, yoff; 1159 int width, height; 1160 1161 hpcfb_tv_erasecols(dc, row, startcol, ncols, attr); 1162 #ifdef HPCFB_JUMP 1163 if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1164 dc->dc_state |= HPCFB_DC_UPDATE; 1165 return; 1166 } 1167 #endif /* HPCFB_JUMP */ 1168 if (!IS_DRAWABLE(dc)) { 1169 return; 1170 } 1171 1172 if (ri->ri_bits == NULL) 1173 return; 1174 1175 dc->dc_state |= HPCFB_DC_DRAWING; 1176 if (sc && sc->sc_accessops->erase 1177 && (dc->dc_state&HPCFB_DC_CURRENT)) { 1178 xoff = startcol * ri->ri_font->fontwidth; 1179 yoff = row * ri->ri_font->fontheight; 1180 width = ncols * ri->ri_font->fontwidth; 1181 height = ri->ri_font->fontheight; 1182 (*sc->sc_accessops->erase)(sc->sc_accessctx, 1183 xoff, yoff, height, width, attr); 1184 } else 1185 rasops_emul.erasecols(ri, row, startcol, ncols, attr); 1186 dc->dc_state &= ~HPCFB_DC_DRAWING; 1187 #ifdef HPCFB_JUMP 1188 hpcfb_check_update(dc); 1189 #endif /* HPCFB_JUMP */ 1190 } 1191 1192 /* 1193 * Copy rows. 1194 */ 1195 void 1196 hpcfb_tv_copyrows(struct hpcfb_devconfig *dc, int src, int dst, int num) 1197 { 1198 struct hpcfb_tvrow *vscn = dc->dc_tvram; 1199 struct hpcfb_tvrow *svc = &vscn[src]; 1200 struct hpcfb_tvrow *dvc = &vscn[dst]; 1201 int i; 1202 int d; 1203 1204 if (vscn == 0) 1205 return; 1206 1207 dc->dc_state |= HPCFB_DC_TDRAWING; 1208 #ifdef HPCFB_JUMP 1209 if (dst < dc->dc_min_row) 1210 dc->dc_min_row = dst; 1211 if (dst + num > dc->dc_max_row) 1212 dc->dc_max_row = dst + num -1; 1213 #endif /* HPCFB_JUMP */ 1214 1215 if (svc > dvc) 1216 d = 1; 1217 else if (svc < dvc) { 1218 svc += num-1; 1219 dvc += num-1; 1220 d = -1; 1221 } else { 1222 dc->dc_state &= ~HPCFB_DC_TDRAWING; 1223 #ifdef HPCFB_JUMP 1224 hpcfb_check_update(dc); 1225 #endif /* HPCFB_JUMP */ 1226 return; 1227 } 1228 1229 for (i = 0; i < num; i++) { 1230 memcpy(&dvc->col[0], &svc->col[0], sizeof(struct hpcfb_vchar)*(svc->maxcol+1)); 1231 if (svc->maxcol < dvc->maxcol && dvc->spacecol < dvc->maxcol) 1232 dvc->spacecol = dvc->maxcol; 1233 dvc->maxcol = svc->maxcol; 1234 svc+=d; 1235 dvc+=d; 1236 } 1237 dc->dc_state &= ~HPCFB_DC_TDRAWING; 1238 #ifdef HPCFB_JUMP 1239 hpcfb_check_update(dc); 1240 #endif /* HPCFB_JUMP */ 1241 } 1242 1243 void 1244 hpcfb_redraw(cookie, row, num, all) 1245 void *cookie; 1246 int row, num; 1247 int all; 1248 { 1249 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1250 struct rasops_info *ri = &dc->dc_rinfo; 1251 int cols; 1252 struct hpcfb_tvrow *vscn = dc->dc_tvram; 1253 struct hpcfb_vchar *svc; 1254 int i, j; 1255 1256 #ifdef HPCFB_JUMP 1257 if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1258 dc->dc_state |= HPCFB_DC_UPDATE; 1259 return; 1260 } 1261 #endif /* HPCFB_JUMP */ 1262 if (dc->dc_sc != NULL 1263 && !dc->dc_sc->sc_polling 1264 && dc->dc_sc->sc_mapping) 1265 return; 1266 1267 dc->dc_state &= ~HPCFB_DC_ABORT; 1268 1269 if (vscn == 0) 1270 return; 1271 1272 if (!IS_DRAWABLE(dc)) { 1273 return; 1274 } 1275 1276 if (ri->ri_bits == NULL) 1277 return; 1278 1279 dc->dc_state |= HPCFB_DC_DRAWING; 1280 dc->dc_state |= HPCFB_DC_TDRAWING; 1281 for (i = 0; i < num; i++) { 1282 if (dc->dc_state&HPCFB_DC_ABORT) 1283 break; 1284 if ((dc->dc_state&HPCFB_DC_CURRENT) == 0) 1285 break; 1286 cols = vscn[row+i].maxcol; 1287 for (j = 0; j <= cols; j++) { 1288 if (dc->dc_state&HPCFB_DC_ABORT) 1289 continue; 1290 if ((dc->dc_state&HPCFB_DC_CURRENT) == 0) 1291 continue; 1292 svc = &vscn[row+i].col[j]; 1293 rasops_emul.putchar(ri, row + i, j, svc->c, svc->attr); 1294 } 1295 if (all) 1296 cols = dc->dc_cols-1; 1297 else 1298 cols = vscn[row+i].spacecol; 1299 for (; j <= cols; j++) { 1300 if (dc->dc_state&HPCFB_DC_ABORT) 1301 continue; 1302 if ((dc->dc_state&HPCFB_DC_CURRENT) == 0) 1303 continue; 1304 rasops_emul.putchar(ri, row + i, j, ' ', 0); 1305 } 1306 vscn[row+i].spacecol = 0; 1307 } 1308 if (dc->dc_state&HPCFB_DC_ABORT) 1309 dc->dc_state &= ~HPCFB_DC_ABORT; 1310 dc->dc_state &= ~HPCFB_DC_DRAWING; 1311 dc->dc_state &= ~HPCFB_DC_TDRAWING; 1312 #ifdef HPCFB_JUMP 1313 hpcfb_check_update(dc); 1314 #endif /* HPCFB_JUMP */ 1315 } 1316 1317 #ifdef HPCFB_JUMP 1318 void 1319 hpcfb_update(void *v) 1320 { 1321 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v; 1322 1323 /* callout_stop(&dc->dc_scroll_ch); */ 1324 dc->dc_state &= ~HPCFB_DC_SCROLLPENDING; 1325 if (dc->dc_curx > 0 && dc->dc_cury > 0) 1326 hpcfb_cursor_raw(dc, 0, dc->dc_cury, dc->dc_curx); 1327 if ((dc->dc_state&HPCFB_DC_UPDATEALL)) { 1328 hpcfb_redraw(dc, 0, dc->dc_rows, 1); 1329 dc->dc_state &= ~(HPCFB_DC_UPDATE|HPCFB_DC_UPDATEALL); 1330 } else if ((dc->dc_state&HPCFB_DC_UPDATE)) { 1331 hpcfb_redraw(dc, dc->dc_min_row, 1332 dc->dc_max_row - dc->dc_min_row, 0); 1333 dc->dc_state &= ~HPCFB_DC_UPDATE; 1334 } else { 1335 hpcfb_redraw(dc, dc->dc_scroll_dst, dc->dc_scroll_num, 0); 1336 } 1337 if (dc->dc_curx > 0 && dc->dc_cury > 0) 1338 hpcfb_cursor_raw(dc, 1, dc->dc_cury, dc->dc_curx); 1339 } 1340 1341 void 1342 hpcfb_do_scroll(void *v) 1343 { 1344 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v; 1345 1346 dc->dc_state |= HPCFB_DC_SCRTHREAD; 1347 if (dc->dc_state&(HPCFB_DC_DRAWING|HPCFB_DC_TDRAWING)) 1348 dc->dc_state |= HPCFB_DC_SCRDELAY; 1349 else if (dc->dc_sc != NULL && dc->dc_sc->sc_thread) 1350 wakeup(dc->dc_sc); 1351 else if (dc->dc_sc != NULL && !dc->dc_sc->sc_mapping) { 1352 /* draw only EMUL mode */ 1353 hpcfb_update(v); 1354 } 1355 dc->dc_state &= ~HPCFB_DC_SCRTHREAD; 1356 } 1357 1358 void 1359 hpcfb_check_update(void *v) 1360 { 1361 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)v; 1362 1363 if (dc->dc_sc != NULL 1364 && dc->dc_sc->sc_polling 1365 && (dc->dc_state&HPCFB_DC_SCROLLPENDING)){ 1366 callout_stop(&dc->dc_scroll_ch); 1367 dc->dc_state &= ~HPCFB_DC_SCRDELAY; 1368 hpcfb_update(v); 1369 } 1370 else if (dc->dc_state&HPCFB_DC_SCRDELAY){ 1371 dc->dc_state &= ~HPCFB_DC_SCRDELAY; 1372 hpcfb_update(v); 1373 } else if (dc->dc_state&HPCFB_DC_UPDATEALL){ 1374 dc->dc_state &= ~HPCFB_DC_UPDATEALL; 1375 hpcfb_update(v); 1376 } 1377 } 1378 #endif /* HPCFB_JUMP */ 1379 1380 void 1381 hpcfb_copyrows(void *cookie, int src, int dst, int num) 1382 { 1383 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1384 struct rasops_info *ri = &dc->dc_rinfo; 1385 struct hpcfb_softc *sc = dc->dc_sc; 1386 int srcyoff, dstyoff; 1387 int width, height; 1388 1389 hpcfb_tv_copyrows(cookie, src, dst, num); 1390 1391 if (!IS_DRAWABLE(dc)) { 1392 return; 1393 } 1394 1395 if (ri->ri_bits == NULL) 1396 return; 1397 1398 if (sc && sc->sc_accessops->bitblit 1399 && (dc->dc_state&HPCFB_DC_CURRENT)) { 1400 dc->dc_state |= HPCFB_DC_DRAWING; 1401 srcyoff = src * ri->ri_font->fontheight; 1402 dstyoff = dst * ri->ri_font->fontheight; 1403 width = dc->dc_cols * ri->ri_font->fontwidth; 1404 height = num * ri->ri_font->fontheight; 1405 (*sc->sc_accessops->bitblit)(sc->sc_accessctx, 1406 0, srcyoff, 0, dstyoff, height, width); 1407 dc->dc_state &= ~HPCFB_DC_DRAWING; 1408 } 1409 else { 1410 #ifdef HPCFB_JUMP 1411 if (sc && sc->sc_polling) { 1412 hpcfb_check_update(dc); 1413 } else if ((dc->dc_state&HPCFB_DC_SCROLLPENDING) == 0) { 1414 dc->dc_state |= HPCFB_DC_SCROLLPENDING; 1415 dc->dc_scroll = 1; 1416 dc->dc_scroll_src = src; 1417 dc->dc_scroll_dst = dst; 1418 dc->dc_scroll_num = num; 1419 callout_reset(&dc->dc_scroll_ch, hz/100, &hpcfb_do_scroll, dc); 1420 return; 1421 } else if (dc->dc_scroll++ < dc->dc_rows/HPCFB_MAX_JUMP) { 1422 dc->dc_state |= HPCFB_DC_UPDATE; 1423 return; 1424 } else { 1425 dc->dc_state &= ~HPCFB_DC_SCROLLPENDING; 1426 callout_stop(&dc->dc_scroll_ch); 1427 } 1428 if (dc->dc_state&HPCFB_DC_UPDATE) { 1429 dc->dc_state &= ~HPCFB_DC_UPDATE; 1430 hpcfb_redraw(cookie, dc->dc_min_row, 1431 dc->dc_max_row - dc->dc_min_row, 0); 1432 dc->dc_max_row = 0; 1433 dc->dc_min_row = dc->dc_rows; 1434 if (dc->dc_curx > 0 && dc->dc_cury > 0) 1435 hpcfb_cursor(dc, 1, dc->dc_cury, dc->dc_curx); 1436 return; 1437 } 1438 #endif /* HPCFB_JUMP */ 1439 hpcfb_redraw(cookie, dst, num, 0); 1440 } 1441 #ifdef HPCFB_JUMP 1442 hpcfb_check_update(dc); 1443 #endif /* HPCFB_JUMP */ 1444 } 1445 1446 /* 1447 * eraserows 1448 */ 1449 void 1450 hpcfb_tv_eraserows(struct hpcfb_devconfig *dc, int row, int nrow, long attr) 1451 { 1452 struct hpcfb_tvrow *vscn = dc->dc_tvram; 1453 int cols; 1454 int i; 1455 1456 if (vscn == 0) 1457 return; 1458 1459 dc->dc_state |= HPCFB_DC_TDRAWING; 1460 dc->dc_state &= ~HPCFB_DC_TDRAWING; 1461 #ifdef HPCFB_JUMP 1462 if (row < dc->dc_min_row) 1463 dc->dc_min_row = row; 1464 if (row + nrow > dc->dc_max_row) 1465 dc->dc_max_row = row + nrow; 1466 #endif /* HPCFB_JUMP */ 1467 1468 for (i = 0; i < nrow; i++) { 1469 cols = vscn[row+i].maxcol; 1470 if (vscn[row+i].spacecol < cols) 1471 vscn[row+i].spacecol = cols; 1472 vscn[row+i].maxcol = -1; 1473 } 1474 #ifdef HPCFB_JUMP 1475 hpcfb_check_update(dc); 1476 #endif /* HPCFB_JUMP */ 1477 } 1478 1479 void 1480 hpcfb_eraserows(void *cookie, int row, int nrow, long attr) 1481 { 1482 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1483 struct hpcfb_softc *sc = dc->dc_sc; 1484 struct rasops_info *ri = &dc->dc_rinfo; 1485 int yoff; 1486 int width; 1487 int height; 1488 1489 hpcfb_tv_eraserows(dc, row, nrow, attr); 1490 #ifdef HPCFB_JUMP 1491 if (dc->dc_state&HPCFB_DC_SCROLLPENDING) { 1492 dc->dc_state |= HPCFB_DC_UPDATE; 1493 return; 1494 } 1495 #endif /* HPCFB_JUMP */ 1496 if (!IS_DRAWABLE(dc)) { 1497 return; 1498 } 1499 1500 if (ri->ri_bits == NULL) 1501 return; 1502 1503 dc->dc_state |= HPCFB_DC_DRAWING; 1504 if (sc && sc->sc_accessops->erase 1505 && (dc->dc_state&HPCFB_DC_CURRENT)) { 1506 yoff = row * ri->ri_font->fontheight; 1507 width = dc->dc_cols * ri->ri_font->fontwidth; 1508 height = nrow * ri->ri_font->fontheight; 1509 (*sc->sc_accessops->erase)(sc->sc_accessctx, 1510 0, yoff, height, width, attr); 1511 } else 1512 rasops_emul.eraserows(ri, row, nrow, attr); 1513 dc->dc_state &= ~HPCFB_DC_DRAWING; 1514 #ifdef HPCFB_JUMP 1515 hpcfb_check_update(dc); 1516 #endif /* HPCFB_JUMP */ 1517 } 1518 1519 /* 1520 * allocattr 1521 */ 1522 int 1523 hpcfb_allocattr(void *cookie, int fg, int bg, int flags, long *attrp) 1524 { 1525 struct hpcfb_devconfig *dc = (struct hpcfb_devconfig *)cookie; 1526 struct rasops_info *ri = &dc->dc_rinfo; 1527 1528 return (rasops_emul.allocattr(ri, fg, bg, flags, attrp)); 1529 } 1530