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