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