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