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