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