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