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