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