1 /*- 2 * (MPSAFE) 3 * 4 * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The DragonFly Project 8 * by Sascha Wildner <saw@online.de>. 9 * 10 * Simple font scaling code by Sascha Wildner and Matthew Dillon 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer as 17 * the first lines of this file unmodified. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $FreeBSD: src/sys/dev/syscons/scvidctl.c,v 1.19.2.2 2000/05/05 09:16:08 nyan Exp $ 34 */ 35 36 #include "opt_syscons.h" 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/conf.h> 41 #include <sys/signalvar.h> 42 #include <sys/tty.h> 43 #include <sys/kernel.h> 44 #include <sys/thread2.h> 45 46 #include <machine/console.h> 47 #include <machine/framebuffer.h> 48 49 #include <dev/video/fb/fbreg.h> 50 #include "syscons.h" 51 52 SET_DECLARE(scrndr_set, const sc_renderer_t); 53 54 int 55 sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize, 56 int fontsize) 57 { 58 video_info_t info; 59 u_char *font; 60 int prev_ysize; 61 int new_ysize; 62 int error; 63 64 lwkt_gettoken(&vga_token); 65 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) { 66 lwkt_reltoken(&vga_token); 67 return ENODEV; 68 } 69 70 /* adjust argument values */ 71 if (fontsize <= 0) 72 fontsize = info.vi_cheight; 73 if (fontsize < 14) { 74 fontsize = 8; 75 #ifndef SC_NO_FONT_LOADING 76 if (!(scp->sc->fonts_loaded & FONT_8)) 77 return EINVAL; 78 font = scp->sc->font_8; 79 #else 80 font = NULL; 81 #endif 82 } else if (fontsize >= 16) { 83 fontsize = 16; 84 #ifndef SC_NO_FONT_LOADING 85 if (!(scp->sc->fonts_loaded & FONT_16)) 86 return EINVAL; 87 font = scp->sc->font_16; 88 #else 89 font = NULL; 90 #endif 91 } else { 92 fontsize = 14; 93 #ifndef SC_NO_FONT_LOADING 94 if (!(scp->sc->fonts_loaded & FONT_14)) 95 return EINVAL; 96 font = scp->sc->font_14; 97 #else 98 font = NULL; 99 #endif 100 } 101 if ((xsize <= 0) || (xsize > info.vi_width)) 102 xsize = info.vi_width; 103 if ((ysize <= 0) || (ysize > info.vi_height)) 104 ysize = info.vi_height; 105 106 /* stop screen saver, etc */ 107 if ((error = sc_clean_up(scp, FALSE))) { 108 lwkt_reltoken(&vga_token); 109 return error; 110 } 111 112 if (scp->sc->fbi != NULL && 113 sc_render_match(scp, "kms", V_INFO_MM_TEXT) == NULL) { 114 lwkt_reltoken(&vga_token); 115 return ENODEV; 116 } 117 if (scp->sc->fbi == NULL && 118 sc_render_match(scp, scp->sc->adp->va_name, V_INFO_MM_TEXT) == NULL) { 119 lwkt_reltoken(&vga_token); 120 return ENODEV; 121 } 122 123 /* set up scp */ 124 new_ysize = 0; 125 #ifndef SC_NO_HISTORY 126 if (scp->history != NULL) { 127 sc_hist_save(scp); 128 new_ysize = sc_vtb_rows(scp->history); 129 } 130 #endif 131 prev_ysize = scp->ysize; 132 /* 133 * This is a kludge to fend off scrn_update() while we 134 * muck around with scp. XXX 135 */ 136 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 137 scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE); 138 scp->mode = mode; 139 scp->model = V_INFO_MM_TEXT; 140 scp->xsize = xsize; 141 scp->ysize = ysize; 142 scp->xoff = 0; 143 scp->yoff = 0; 144 scp->xpixel = scp->xsize*8; 145 scp->ypixel = scp->ysize*fontsize; 146 scp->font = font; 147 scp->font_height = fontsize; 148 scp->font_width = 8; 149 150 /* allocate buffers */ 151 sc_alloc_scr_buffer(scp, TRUE, TRUE); 152 sc_init_emulator(scp, NULL); 153 #ifndef SC_NO_CUTPASTE 154 sc_alloc_cut_buffer(scp, FALSE); 155 #endif 156 #ifndef SC_NO_HISTORY 157 sc_alloc_history_buffer(scp, new_ysize, prev_ysize, FALSE); 158 #endif 159 160 if (scp == scp->sc->cur_scp) 161 set_mode(scp); 162 scp->status &= ~UNKNOWN_MODE; 163 164 if (tp) { 165 DPRINTF(5, ("ws_*size (%d,%d), size (%d,%d)\n", 166 tp->t_winsize.ws_col, tp->t_winsize.ws_row, 167 scp->xsize, scp->ysize)); 168 if (tp->t_winsize.ws_col != scp->xsize || 169 tp->t_winsize.ws_row != scp->ysize) { 170 tp->t_winsize.ws_col = scp->xsize; 171 tp->t_winsize.ws_row = scp->ysize; 172 pgsignal(tp->t_pgrp, SIGWINCH, 1); 173 } 174 } 175 lwkt_reltoken(&vga_token); 176 177 return 0; 178 } 179 180 int 181 sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) 182 { 183 #ifdef SC_NO_MODE_CHANGE 184 return ENODEV; 185 #else 186 video_info_t info; 187 int error; 188 189 lwkt_gettoken(&vga_token); 190 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) { 191 lwkt_reltoken(&vga_token); 192 return ENODEV; 193 } 194 lwkt_reltoken(&vga_token); 195 196 /* stop screen saver, etc */ 197 crit_enter(); 198 if ((error = sc_clean_up(scp, FALSE))) { 199 crit_exit(); 200 return error; 201 } 202 203 if (scp->sc->fbi != NULL && 204 sc_render_match(scp, "kms", V_INFO_MM_OTHER) == NULL) { 205 crit_exit(); 206 return ENODEV; 207 } 208 if (scp->sc->fbi == NULL && 209 sc_render_match(scp, scp->sc->adp->va_name, V_INFO_MM_OTHER) == NULL) { 210 crit_exit(); 211 return ENODEV; 212 } 213 214 /* set up scp */ 215 scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE | MOUSE_HIDDEN); 216 scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE); 217 scp->mode = mode; 218 scp->model = V_INFO_MM_OTHER; 219 /* 220 * Don't change xsize and ysize; preserve the previous vty 221 * and history buffers. 222 */ 223 scp->xoff = 0; 224 scp->yoff = 0; 225 scp->xpixel = info.vi_width; 226 scp->ypixel = info.vi_height; 227 scp->font = NULL; 228 scp->font_height = 0; 229 scp->font_width = 0; 230 #ifndef SC_NO_SYSMOUSE 231 /* move the mouse cursor at the center of the screen */ 232 sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2); 233 #endif 234 sc_init_emulator(scp, NULL); 235 crit_exit(); 236 237 if (scp == scp->sc->cur_scp) 238 set_mode(scp); 239 /* clear_graphics();*/ 240 refresh_ega_palette(scp); 241 scp->status &= ~UNKNOWN_MODE; 242 243 if (tp) { 244 if (tp->t_winsize.ws_xpixel != scp->xpixel || 245 tp->t_winsize.ws_ypixel != scp->ypixel) { 246 tp->t_winsize.ws_xpixel = scp->xpixel; 247 tp->t_winsize.ws_ypixel = scp->ypixel; 248 pgsignal(tp->t_pgrp, SIGWINCH, 1); 249 } 250 } 251 252 return 0; 253 #endif /* SC_NO_MODE_CHANGE */ 254 } 255 256 int 257 sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 258 int fontsize) 259 { 260 #ifndef SC_PIXEL_MODE 261 return ENODEV; 262 #else 263 video_info_t info; 264 u_char *font; 265 int prev_ysize; 266 int new_ysize; 267 int error; 268 269 lwkt_gettoken(&vga_token); 270 if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) { 271 lwkt_reltoken(&vga_token); 272 return ENODEV; /* this shouldn't happen */ 273 } 274 lwkt_reltoken(&vga_token); 275 276 /* adjust argument values */ 277 if (fontsize <= 0) 278 fontsize = info.vi_cheight; 279 if (fontsize < 14) { 280 fontsize = 8; 281 #ifndef SC_NO_FONT_LOADING 282 if (!(scp->sc->fonts_loaded & FONT_8)) 283 return EINVAL; 284 font = scp->sc->font_8; 285 #else 286 font = NULL; 287 #endif 288 } else if (fontsize >= 16) { 289 fontsize = 16; 290 #ifndef SC_NO_FONT_LOADING 291 if (!(scp->sc->fonts_loaded & FONT_16)) 292 return EINVAL; 293 font = scp->sc->font_16; 294 #else 295 font = NULL; 296 #endif 297 } else { 298 fontsize = 14; 299 #ifndef SC_NO_FONT_LOADING 300 if (!(scp->sc->fonts_loaded & FONT_14)) 301 return EINVAL; 302 font = scp->sc->font_14; 303 #else 304 font = NULL; 305 #endif 306 } 307 if (xsize <= 0) 308 xsize = info.vi_width/8; 309 if (ysize <= 0) 310 ysize = info.vi_height/fontsize; 311 312 if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize)) 313 return EINVAL; 314 315 /* 316 * We currently support the following graphic modes: 317 * 318 * - 4 bpp planar modes whose memory size does not exceed 64K 319 * - 8 bbp packed pixel modes 320 * - 15, 16, 24 and 32 bpp direct modes with linear frame buffer 321 */ 322 323 if (info.vi_mem_model == V_INFO_MM_PLANAR) { 324 if (info.vi_planes != 4) 325 return ENODEV; 326 327 /* 328 * A memory size >64K requires bank switching to access the entire 329 * screen. XXX 330 */ 331 332 if (info.vi_width * info.vi_height / 8 > info.vi_window_size) 333 return ENODEV; 334 } else if (info.vi_mem_model == V_INFO_MM_PACKED) { 335 if (info.vi_depth != 8) 336 return ENODEV; 337 } else if (info.vi_mem_model == V_INFO_MM_DIRECT) { 338 if (!(info.vi_flags & V_INFO_LINEAR) && 339 (info.vi_depth != 15) && (info.vi_depth != 16) && 340 (info.vi_depth != 24) && (info.vi_depth != 32)) 341 return ENODEV; 342 } else 343 return ENODEV; 344 345 /* stop screen saver, etc */ 346 crit_enter(); 347 if ((error = sc_clean_up(scp, FALSE))) { 348 crit_exit(); 349 return error; 350 } 351 352 if (sc_render_match(scp, scp->sc->adp->va_name, info.vi_mem_model) == NULL) { 353 crit_exit(); 354 return ENODEV; 355 } 356 357 #if 0 358 if (scp->tsw) 359 (*scp->tsw->te_term)(scp, scp->ts); 360 scp->tsw = NULL; 361 scp->ts = NULL; 362 #endif 363 364 /* set up scp */ 365 new_ysize = 0; 366 #ifndef SC_NO_HISTORY 367 if (scp->history != NULL) { 368 sc_hist_save(scp); 369 new_ysize = sc_vtb_rows(scp->history); 370 } 371 #endif 372 prev_ysize = scp->ysize; 373 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 374 scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE); 375 scp->model = info.vi_mem_model; 376 scp->xsize = xsize; 377 scp->ysize = ysize; 378 scp->xoff = (scp->xpixel/8 - xsize)/2; 379 scp->yoff = (scp->ypixel/fontsize - ysize)/2; 380 scp->font = font; 381 scp->font_height = fontsize; 382 scp->font_width = 8; 383 384 /* allocate buffers */ 385 sc_alloc_scr_buffer(scp, TRUE, TRUE); 386 sc_init_emulator(scp, NULL); 387 #ifndef SC_NO_CUTPASTE 388 sc_alloc_cut_buffer(scp, FALSE); 389 #endif 390 #ifndef SC_NO_HISTORY 391 sc_alloc_history_buffer(scp, new_ysize, prev_ysize, FALSE); 392 #endif 393 crit_exit(); 394 395 if (scp == scp->sc->cur_scp) { 396 sc_set_border(scp, scp->border); 397 sc_set_cursor_image(scp); 398 } 399 400 scp->status &= ~UNKNOWN_MODE; 401 402 if (tp) { 403 if (tp->t_winsize.ws_col != scp->xsize || 404 tp->t_winsize.ws_row != scp->ysize) { 405 tp->t_winsize.ws_col = scp->xsize; 406 tp->t_winsize.ws_row = scp->ysize; 407 pgsignal(tp->t_pgrp, SIGWINCH, 1); 408 } 409 } 410 411 return 0; 412 #endif /* SC_PIXEL_MODE */ 413 } 414 415 #define fb_ioctl(a, c, d) \ 416 (((a) == NULL) ? ENODEV : \ 417 (*vidsw[(a)->va_index]->ioctl)((a), (c), (caddr_t)(d))) 418 419 int 420 sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag) 421 { 422 scr_stat *scp; 423 video_adapter_t *adp; 424 #ifndef SC_NO_MODE_CHANGE 425 video_info_t info; 426 #endif 427 int error, ret; 428 429 KKASSERT(tp->t_dev); 430 431 scp = SC_STAT(tp->t_dev); 432 if (scp == NULL) /* tp == SC_MOUSE */ 433 return ENOIOCTL; 434 adp = scp->sc->adp; 435 if (adp == NULL && scp->sc->fbi == NULL) /* shouldn't happen??? */ 436 return ENODEV; 437 438 lwkt_gettoken(&vga_token); 439 switch (cmd) { 440 441 case CONS_CURRENTADP: /* get current adapter index */ 442 case FBIO_ADAPTER: 443 if (scp->sc->fbi != NULL) { 444 ret = ENODEV; 445 } else { 446 ret = fb_ioctl(adp, FBIO_ADAPTER, data); 447 } 448 lwkt_reltoken(&vga_token); 449 return ret; 450 451 case CONS_CURRENT: /* get current adapter type */ 452 case FBIO_ADPTYPE: 453 if (scp->sc->fbi != NULL) { 454 ret = ENODEV; 455 } else { 456 ret = fb_ioctl(adp, FBIO_ADPTYPE, data); 457 } 458 lwkt_reltoken(&vga_token); 459 return ret; 460 461 case CONS_ADPINFO: /* adapter information */ 462 case FBIO_ADPINFO: 463 if (scp->sc->fbi != NULL) { 464 lwkt_reltoken(&vga_token); 465 return ENODEV; 466 } 467 if (((video_adapter_info_t *)data)->va_index >= 0) { 468 adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index); 469 if (adp == NULL) { 470 lwkt_reltoken(&vga_token); 471 return ENODEV; 472 } 473 } 474 ret = fb_ioctl(adp, FBIO_ADPINFO, data); 475 lwkt_reltoken(&vga_token); 476 return ret; 477 478 case CONS_GET: /* get current video mode */ 479 case FBIO_GETMODE: 480 *(int *)data = scp->mode; 481 lwkt_reltoken(&vga_token); 482 return 0; 483 484 #ifndef SC_NO_MODE_CHANGE 485 case CONS_SET: 486 case FBIO_SETMODE: /* set video mode */ 487 if (scp->sc->fbi != NULL) { 488 lwkt_reltoken(&vga_token); 489 if (*(int *)data != 0) 490 return ENODEV; 491 else 492 return 0; 493 } 494 if (!(adp->va_flags & V_ADP_MODECHANGE)) { 495 lwkt_reltoken(&vga_token); 496 return ENODEV; 497 } 498 info.vi_mode = *(int *)data; 499 error = fb_ioctl(adp, FBIO_MODEINFO, &info); 500 if (error) { 501 lwkt_reltoken(&vga_token); 502 return error; 503 } 504 if (info.vi_flags & V_INFO_GRAPHICS) { 505 lwkt_reltoken(&vga_token); 506 return sc_set_graphics_mode(scp, tp, *(int *)data); 507 } else { 508 lwkt_reltoken(&vga_token); 509 return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0); 510 } 511 #endif /* SC_NO_MODE_CHANGE */ 512 513 case CONS_MODEINFO: /* get mode information */ 514 case FBIO_MODEINFO: 515 if (scp->sc->fbi != NULL) { 516 /* Fabricate some mode information for KMS framebuffer */ 517 video_info_t *vinfo = (video_info_t *)data; 518 vinfo->vi_mode = 0; 519 vinfo->vi_flags = V_INFO_COLOR; 520 vinfo->vi_width = scp->xsize; 521 vinfo->vi_height = scp->ysize; 522 vinfo->vi_cwidth = scp->font_width; 523 vinfo->vi_cheight = scp->font_height; 524 vinfo->vi_window = 0; 525 vinfo->vi_window_size = 0; 526 vinfo->vi_buffer = 0; 527 vinfo->vi_buffer_size = 0; 528 vinfo->vi_mem_model = V_INFO_MM_TEXT; 529 ret = 0; 530 } else { 531 ret = fb_ioctl(adp, FBIO_MODEINFO, data); 532 } 533 lwkt_reltoken(&vga_token); 534 return ret; 535 536 case CONS_FINDMODE: /* find a matching video mode */ 537 case FBIO_FINDMODE: 538 if (scp->sc->fbi != NULL) { 539 ret = ENODEV; 540 } else { 541 ret = fb_ioctl(adp, FBIO_FINDMODE, data); 542 } 543 lwkt_reltoken(&vga_token); 544 return ret; 545 546 case CONS_SETWINORG: /* set frame buffer window origin */ 547 case FBIO_SETWINORG: 548 if (scp != scp->sc->cur_scp) { 549 lwkt_reltoken(&vga_token); 550 return ENODEV; /* XXX */ 551 } 552 if (scp->sc->fbi != NULL) { 553 lwkt_reltoken(&vga_token); 554 return ENODEV; 555 } 556 ret = fb_ioctl(adp, FBIO_SETWINORG, data); 557 lwkt_reltoken(&vga_token); 558 return ret; 559 560 case FBIO_GETWINORG: /* get frame buffer window origin */ 561 if (scp != scp->sc->cur_scp) { 562 lwkt_reltoken(&vga_token); 563 return ENODEV; /* XXX */ 564 } 565 if (scp->sc->fbi != NULL) { 566 ret = ENODEV; 567 } else { 568 ret = fb_ioctl(adp, FBIO_GETWINORG, data); 569 } 570 lwkt_reltoken(&vga_token); 571 return ret; 572 573 case FBIO_GETDISPSTART: 574 case FBIO_SETDISPSTART: 575 case FBIO_GETLINEWIDTH: 576 case FBIO_SETLINEWIDTH: 577 if (scp != scp->sc->cur_scp) { 578 lwkt_reltoken(&vga_token); 579 return ENODEV; /* XXX */ 580 } 581 if (scp->sc->fbi != NULL) { 582 if (cmd == FBIO_GETLINEWIDTH) { 583 *(u_int *)data = scp->sc->fbi->stride; 584 ret = 0; 585 } else { 586 ret = ENODEV; 587 } 588 } else { 589 ret = fb_ioctl(adp, cmd, data); 590 } 591 lwkt_reltoken(&vga_token); 592 return ret; 593 594 case FBIO_BLANK: 595 if (scp != scp->sc->cur_scp) { 596 lwkt_reltoken(&vga_token); 597 return ENODEV; 598 } 599 if (scp->sc->fbi != NULL && ISGRAPHSC(scp)) { 600 if (*(int *)data == V_DISPLAY_ON) 601 sc_stop_scrn_saver(scp->sc); 602 else 603 sc_start_scrn_saver(scp->sc); 604 ret = 0; 605 } else { 606 ret = ENODEV; 607 } 608 lwkt_reltoken(&vga_token); 609 return ret; 610 611 case FBIO_GETPALETTE: 612 case FBIO_SETPALETTE: 613 case FBIOPUTCMAP: 614 case FBIOGETCMAP: 615 case FBIOGTYPE: 616 case FBIOGATTR: 617 case FBIOSVIDEO: 618 case FBIOGVIDEO: 619 case FBIOSCURSOR: 620 case FBIOGCURSOR: 621 case FBIOSCURPOS: 622 case FBIOGCURPOS: 623 case FBIOGCURMAX: 624 if (scp != scp->sc->cur_scp) { 625 lwkt_reltoken(&vga_token); 626 return ENODEV; /* XXX */ 627 } 628 if (scp->sc->fbi != NULL) { 629 if (cmd == FBIOGTYPE) { 630 ((struct fbtype *)data)->fb_type = FBTYPE_DUMBFB; 631 ((struct fbtype *)data)->fb_height = scp->sc->fbi->height; 632 ((struct fbtype *)data)->fb_width = scp->sc->fbi->width; 633 ((struct fbtype *)data)->fb_depth = scp->sc->fbi->depth; 634 ((struct fbtype *)data)->fb_cmsize = 0; 635 ((struct fbtype *)data)->fb_size = 636 scp->sc->fbi->height * scp->sc->fbi->stride; 637 ret = 0; 638 } else { 639 ret = ENODEV; 640 } 641 } else { 642 ret = fb_ioctl(adp, cmd, data); 643 } 644 lwkt_reltoken(&vga_token); 645 return ret; 646 647 case KDSETMODE: /* set current mode of this (virtual) console */ 648 switch (*(int *)data) { 649 case KD_TEXT: /* switch to TEXT (known) mode */ 650 /* 651 * If scp->mode is of graphics modes, we don't know which 652 * text mode to switch back to... 653 */ 654 if (scp->status & GRAPHICS_MODE) { 655 lwkt_reltoken(&vga_token); 656 return EINVAL; 657 } 658 /* restore fonts & palette ! */ 659 #if 0 660 #ifndef SC_NO_FONT_LOADING 661 if (scp->sc->fbi == NULL && ISFONTAVAIL(adp->va_flags) 662 && !(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) { 663 /* 664 * FONT KLUDGE 665 * Don't load fonts for now... XXX 666 */ 667 if (scp->sc->fonts_loaded & FONT_8) 668 sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256); 669 if (scp->sc->fonts_loaded & FONT_14) 670 sc_load_font(scp, 0, 14, scp->sc->font_14, 0, 256); 671 if (scp->sc->fonts_loaded & FONT_16) 672 sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256); 673 } 674 #endif /* SC_NO_FONT_LOADING */ 675 #endif 676 677 if (scp->sc->fbi == NULL) 678 load_palette(adp, scp->sc->palette); 679 680 /* move hardware cursor out of the way */ 681 if (scp->sc->fbi == NULL) 682 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1); 683 /* FALL THROUGH */ 684 685 case KD_TEXT1: /* switch to TEXT (known) mode */ 686 /* 687 * If scp->mode is of graphics modes, we don't know which 688 * text/pixel mode to switch back to... 689 */ 690 if (scp->status & GRAPHICS_MODE) { 691 lwkt_reltoken(&vga_token); 692 return EINVAL; 693 } 694 crit_enter(); 695 if ((error = sc_clean_up(scp, FALSE))) { 696 crit_exit(); 697 lwkt_reltoken(&vga_token); 698 return error; 699 } 700 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 701 crit_exit(); 702 /* no restore fonts & palette */ 703 if (scp == scp->sc->cur_scp) 704 set_mode(scp); 705 sc_clear_screen(scp); 706 scp->status &= ~UNKNOWN_MODE; 707 lwkt_reltoken(&vga_token); 708 return 0; 709 710 #ifdef SC_PIXEL_MODE 711 case KD_PIXEL: /* pixel (raster) display */ 712 if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) { 713 lwkt_reltoken(&vga_token); 714 return EINVAL; 715 } 716 if (scp->sc->fbi != NULL) { 717 lwkt_reltoken(&vga_token); 718 return ENODEV; 719 } 720 if (scp->status & GRAPHICS_MODE) { 721 lwkt_reltoken(&vga_token); 722 return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 723 scp->font_height); 724 } 725 crit_enter(); 726 if ((error = sc_clean_up(scp, FALSE))) { 727 crit_exit(); 728 lwkt_reltoken(&vga_token); 729 return error; 730 } 731 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 732 crit_exit(); 733 if (scp == scp->sc->cur_scp) { 734 set_mode(scp); 735 load_palette(adp, scp->sc->palette); 736 } 737 sc_clear_screen(scp); 738 scp->status &= ~UNKNOWN_MODE; 739 lwkt_reltoken(&vga_token); 740 return 0; 741 #endif /* SC_PIXEL_MODE */ 742 743 case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 744 crit_enter(); 745 if ((error = sc_clean_up(scp, FALSE))) { 746 crit_exit(); 747 lwkt_reltoken(&vga_token); 748 return error; 749 } 750 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 751 crit_exit(); 752 lwkt_reltoken(&vga_token); 753 return 0; 754 755 default: 756 lwkt_reltoken(&vga_token); 757 return EINVAL; 758 } 759 /* NOT REACHED */ 760 761 #ifdef SC_PIXEL_MODE 762 case KDRASTER: /* set pixel (raster) display mode */ 763 if (scp->sc->fbi != NULL || ISUNKNOWNSC(scp) || ISTEXTSC(scp)) { 764 lwkt_reltoken(&vga_token); 765 return ENODEV; 766 } 767 lwkt_reltoken(&vga_token); 768 return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 769 ((int *)data)[2]); 770 #endif /* SC_PIXEL_MODE */ 771 772 case KDGETMODE: /* get current mode of this (virtual) console */ 773 /* 774 * From the user program's point of view, KD_PIXEL is the same 775 * as KD_TEXT... 776 */ 777 *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT; 778 lwkt_reltoken(&vga_token); 779 return 0; 780 781 case KDSBORDER: /* set border color of this (virtual) console */ 782 /* Only values in the range [0..15] allowed */ 783 if (*(int *)data < 0 || *(int *)data > 15) { 784 lwkt_reltoken(&vga_token); 785 return EINVAL; 786 } 787 scp->border = *(int *)data; 788 if (scp == scp->sc->cur_scp) 789 sc_set_border(scp, scp->border); 790 lwkt_reltoken(&vga_token); 791 return 0; 792 } 793 794 lwkt_reltoken(&vga_token); 795 return ENOIOCTL; 796 } 797 798 static LIST_HEAD(, sc_renderer) sc_rndr_list = 799 LIST_HEAD_INITIALIZER(sc_rndr_list); 800 801 int 802 sc_render_add(sc_renderer_t *rndr) 803 { 804 LIST_INSERT_HEAD(&sc_rndr_list, rndr, link); 805 return 0; 806 } 807 808 int 809 sc_render_remove(sc_renderer_t *rndr) 810 { 811 /* 812 LIST_REMOVE(rndr, link); 813 */ 814 return EBUSY; /* XXX */ 815 } 816 817 sc_rndr_sw_t * 818 sc_render_match(scr_stat *scp, char *name, int model) 819 { 820 const sc_renderer_t **list; 821 const sc_renderer_t *p; 822 823 if (!LIST_EMPTY(&sc_rndr_list)) { 824 LIST_FOREACH(p, &sc_rndr_list, link) { 825 if ((strcmp(p->name, name) == 0) && 826 (model == p->model)) { 827 scp->status &= 828 ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 829 return p->rndrsw; 830 } 831 } 832 } else { 833 SET_FOREACH(list, scrndr_set) { 834 p = *list; 835 if ((strcmp(p->name, name) == 0) && 836 (model == p->model)) { 837 scp->status &= 838 ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 839 return p->rndrsw; 840 } 841 } 842 } 843 844 return NULL; 845 } 846 847 #define VIRTUAL_TTY(sc, x) ((SC_DEV((sc),(x)) != NULL) ? \ 848 (SC_DEV((sc),(x))->si_tty) : NULL) 849 850 void 851 sc_update_render(scr_stat *scp) 852 { 853 sc_rndr_sw_t *rndr; 854 sc_term_sw_t *sw; 855 struct tty *tp; 856 int prev_ysize, new_ysize; 857 #ifndef SC_NO_HISTORY 858 int old_xpos, old_ypos; 859 #endif 860 int error; 861 862 sw = scp->tsw; 863 if (sw == NULL) { 864 return; 865 } 866 867 if (scp->rndr == NULL) 868 return; 869 870 if (scp->fbi_generation == scp->sc->fbi_generation) 871 return; 872 873 crit_enter(); 874 scp->fbi_generation = scp->sc->fbi_generation; 875 /* Needed in case we are implicitly leaving PIXEL_MODE here */ 876 if (scp->model != V_INFO_MM_OTHER) 877 scp->model = V_INFO_MM_TEXT; 878 rndr = NULL; 879 if (strcmp(sw->te_renderer, "*") != 0) { 880 rndr = sc_render_match(scp, sw->te_renderer, scp->model); 881 } 882 if (rndr == NULL && scp->sc->fbi != NULL) { 883 rndr = sc_render_match(scp, "kms", scp->model); 884 } 885 if (rndr == NULL) { /* this shouldn't happen */ 886 rndr = sc_render_match(scp, scp->sc->adp->va_name, scp->model); 887 if (rndr != NULL) 888 scp->rndr = rndr; 889 crit_exit(); 890 return; 891 } 892 893 scp->rndr = rndr; 894 /* Mostly copied from sc_set_text_mode */ 895 if ((error = sc_clean_up(scp, FALSE))) { 896 crit_exit(); 897 return; 898 } 899 new_ysize = 0; 900 #ifndef SC_NO_HISTORY 901 old_xpos = old_ypos = 0; 902 if (scp->history != NULL) { 903 if (scp->xsize > 0) { 904 old_xpos = scp->xpos; 905 old_ypos = scp->ypos; 906 } 907 sc_hist_save(scp); 908 new_ysize = sc_vtb_rows(scp->history); 909 } 910 #endif 911 prev_ysize = scp->ysize; 912 scp->status |= MOUSE_HIDDEN; 913 if (scp->status & GRAPHICS_MODE) { 914 /* 915 * We don't handle GRAPHICS_MODE at all when using a KMS 916 * framebuffer, so silently switch to UNKNOWN_MODE then. 917 */ 918 scp->status |= UNKNOWN_MODE; 919 scp->status &= ~GRAPHICS_MODE; 920 } 921 /* Implicitly leave PIXEL_MODE, but stay in UNKNOWN mode */ 922 scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE); 923 scp->xpixel = scp->sc->fbi->width; 924 scp->ypixel = scp->sc->fbi->height; 925 926 /* 927 * Assume square pixels for now 928 */ 929 sc_font_scale(scp, 0, 0); 930 931 DPRINTF(1, ("kms console: scale-to %dx%d cols=%d rows=%d\n", 932 scp->blk_width, scp->blk_height, scp->xsize, scp->ysize)); 933 934 /* allocate buffers */ 935 sc_alloc_scr_buffer(scp, TRUE, TRUE); 936 sc_init_emulator(scp, NULL); 937 #ifndef SC_NO_CUTPASTE 938 sc_alloc_cut_buffer(scp, FALSE); 939 #endif 940 #ifndef SC_NO_HISTORY 941 sc_alloc_history_buffer(scp, new_ysize, prev_ysize, FALSE); 942 if (scp->history != NULL) { 943 sc_hist_getback(scp, prev_ysize); 944 sc_move_cursor(scp, old_xpos, old_ypos); 945 } 946 #endif 947 crit_exit(); 948 tp = VIRTUAL_TTY(scp->sc, scp->index); 949 if (tp == NULL) 950 return; 951 if (tp->t_winsize.ws_col != scp->xsize || 952 tp->t_winsize.ws_row != scp->ysize) { 953 tp->t_winsize.ws_col = scp->xsize; 954 tp->t_winsize.ws_row = scp->ysize; 955 pgsignal(tp->t_pgrp, SIGWINCH, 1); 956 } 957 } 958