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