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