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