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 #ifndef SC_NO_FONT_LOADING 156 if (!(scp->sc->fonts_loaded & FONT_8)) 157 return EINVAL; 158 font = scp->sc->font_8; 159 #else 160 font = NULL; 161 #endif 162 } else if (fontsize >= 16) { 163 fontsize = 16; 164 #ifndef SC_NO_FONT_LOADING 165 if (!(scp->sc->fonts_loaded & FONT_16)) 166 return EINVAL; 167 font = scp->sc->font_16; 168 #else 169 font = NULL; 170 #endif 171 } else { 172 fontsize = 14; 173 #ifndef SC_NO_FONT_LOADING 174 if (!(scp->sc->fonts_loaded & FONT_14)) 175 return EINVAL; 176 font = scp->sc->font_14; 177 #else 178 font = NULL; 179 #endif 180 } 181 if ((xsize <= 0) || (xsize > info.vi_width)) 182 xsize = info.vi_width; 183 if ((ysize <= 0) || (ysize > info.vi_height)) 184 ysize = info.vi_height; 185 186 /* stop screen saver, etc */ 187 s = spltty(); 188 if ((error = sc_clean_up(scp))) { 189 splx(s); 190 return error; 191 } 192 193 if (sc_render_match(scp, scp->sc->adp->va_name, 0) == NULL) { 194 splx(s); 195 return ENODEV; 196 } 197 198 /* set up scp */ 199 #ifndef SC_NO_HISTORY 200 if (scp->history != NULL) 201 sc_hist_save(scp); 202 #endif 203 prev_ysize = scp->ysize; 204 /* 205 * This is a kludge to fend off scrn_update() while we 206 * muck around with scp. XXX 207 */ 208 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 209 scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE); 210 scp->mode = mode; 211 scp->xsize = xsize; 212 scp->ysize = ysize; 213 scp->xoff = 0; 214 scp->yoff = 0; 215 scp->xpixel = scp->xsize*8; 216 scp->ypixel = scp->ysize*fontsize; 217 scp->font = font; 218 scp->font_size = fontsize; 219 scp->font_width = fontwidth; 220 221 /* allocate buffers */ 222 sc_alloc_scr_buffer(scp, TRUE, TRUE); 223 sc_init_emulator(scp, NULL); 224 #ifndef SC_NO_CUTPASTE 225 sc_alloc_cut_buffer(scp, FALSE); 226 #endif 227 #ifndef SC_NO_HISTORY 228 sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE); 229 #endif 230 splx(s); 231 232 if (scp == scp->sc->cur_scp) 233 set_mode(scp); 234 scp->status &= ~UNKNOWN_MODE; 235 236 if (tp == NULL) 237 return 0; 238 DPRINTF(5, ("ws_*size (%d,%d), size (%d,%d)\n", 239 tp->t_winsize.ws_col, tp->t_winsize.ws_row, scp->xsize, scp->ysize)); 240 if (tp->t_winsize.ws_col != scp->xsize 241 || tp->t_winsize.ws_row != scp->ysize) { 242 tp->t_winsize.ws_col = scp->xsize; 243 tp->t_winsize.ws_row = scp->ysize; 244 245 tty_signal_pgrp(tp, SIGWINCH); 246 } 247 248 return 0; 249 } 250 251 int 252 sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) 253 { 254 #ifdef SC_NO_MODE_CHANGE 255 return ENODEV; 256 #else 257 video_info_t info; 258 int error; 259 int s; 260 261 if (vidd_get_info(scp->sc->adp, mode, &info)) 262 return ENODEV; 263 264 /* stop screen saver, etc */ 265 s = spltty(); 266 if ((error = sc_clean_up(scp))) { 267 splx(s); 268 return error; 269 } 270 271 if (sc_render_match(scp, scp->sc->adp->va_name, GRAPHICS_MODE) == NULL) { 272 splx(s); 273 return ENODEV; 274 } 275 276 /* set up scp */ 277 scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE | MOUSE_HIDDEN); 278 scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE); 279 scp->mode = mode; 280 /* 281 * Don't change xsize and ysize; preserve the previous vty 282 * and history buffers. 283 */ 284 scp->xoff = 0; 285 scp->yoff = 0; 286 scp->xpixel = info.vi_width; 287 scp->ypixel = info.vi_height; 288 scp->font = NULL; 289 scp->font_size = 0; 290 #ifndef SC_NO_SYSMOUSE 291 /* move the mouse cursor at the center of the screen */ 292 sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2); 293 #endif 294 sc_init_emulator(scp, NULL); 295 splx(s); 296 297 if (scp == scp->sc->cur_scp) 298 set_mode(scp); 299 /* clear_graphics();*/ 300 scp->status &= ~UNKNOWN_MODE; 301 302 if (tp == NULL) 303 return 0; 304 if (tp->t_winsize.ws_xpixel != scp->xpixel 305 || tp->t_winsize.ws_ypixel != scp->ypixel) { 306 tp->t_winsize.ws_xpixel = scp->xpixel; 307 tp->t_winsize.ws_ypixel = scp->ypixel; 308 309 tty_signal_pgrp(tp, SIGWINCH); 310 } 311 312 return 0; 313 #endif /* SC_NO_MODE_CHANGE */ 314 } 315 316 int 317 sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 318 int fontsize, int fontwidth) 319 { 320 #ifndef SC_PIXEL_MODE 321 return ENODEV; 322 #else 323 video_info_t info; 324 ksiginfo_t ksi; 325 u_char *font; 326 int prev_ysize; 327 int error; 328 int s; 329 330 if (vidd_get_info(scp->sc->adp, scp->mode, &info)) 331 return ENODEV; /* this shouldn't happen */ 332 333 /* adjust argument values */ 334 if (fontsize <= 0) 335 fontsize = info.vi_cheight; 336 if (fontsize < 14) { 337 fontsize = 8; 338 #ifndef SC_NO_FONT_LOADING 339 if (!(scp->sc->fonts_loaded & FONT_8)) 340 return EINVAL; 341 font = scp->sc->font_8; 342 #else 343 font = NULL; 344 #endif 345 } else if (fontsize >= 16) { 346 fontsize = 16; 347 #ifndef SC_NO_FONT_LOADING 348 if (!(scp->sc->fonts_loaded & FONT_16)) 349 return EINVAL; 350 font = scp->sc->font_16; 351 #else 352 font = NULL; 353 #endif 354 } else { 355 fontsize = 14; 356 #ifndef SC_NO_FONT_LOADING 357 if (!(scp->sc->fonts_loaded & FONT_14)) 358 return EINVAL; 359 font = scp->sc->font_14; 360 #else 361 font = NULL; 362 #endif 363 } 364 if (xsize <= 0) 365 xsize = info.vi_width/8; 366 if (ysize <= 0) 367 ysize = info.vi_height/fontsize; 368 369 if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize)) 370 return EINVAL; 371 372 if (!sc_support_pixel_mode(&info)) 373 return ENODEV; 374 375 /* stop screen saver, etc */ 376 s = spltty(); 377 if ((error = sc_clean_up(scp))) { 378 splx(s); 379 return error; 380 } 381 382 if (sc_render_match(scp, scp->sc->adp->va_name, PIXEL_MODE) == NULL) { 383 splx(s); 384 return ENODEV; 385 } 386 387 #if 0 388 if (scp->tsw) 389 (*scp->tsw->te_term)(scp, scp->ts); 390 scp->tsw = NULL; 391 scp->ts = NULL; 392 #endif 393 394 /* set up scp */ 395 #ifndef SC_NO_HISTORY 396 if (scp->history != NULL) 397 sc_hist_save(scp); 398 #endif 399 prev_ysize = scp->ysize; 400 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 401 scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE); 402 scp->xsize = xsize; 403 scp->ysize = ysize; 404 scp->xoff = (scp->xpixel/8 - xsize)/2; 405 scp->yoff = (scp->ypixel/fontsize - ysize)/2; 406 scp->font = font; 407 scp->font_size = fontsize; 408 scp->font_width = fontwidth; 409 410 /* allocate buffers */ 411 sc_alloc_scr_buffer(scp, TRUE, TRUE); 412 sc_init_emulator(scp, NULL); 413 #ifndef SC_NO_CUTPASTE 414 sc_alloc_cut_buffer(scp, FALSE); 415 #endif 416 #ifndef SC_NO_HISTORY 417 sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE); 418 #endif 419 splx(s); 420 421 if (scp == scp->sc->cur_scp) { 422 sc_set_border(scp, scp->border); 423 sc_set_cursor_image(scp); 424 } 425 426 scp->status &= ~UNKNOWN_MODE; 427 428 if (tp == NULL) 429 return 0; 430 if (tp->t_winsize.ws_col != scp->xsize 431 || tp->t_winsize.ws_row != scp->ysize) { 432 tp->t_winsize.ws_col = scp->xsize; 433 tp->t_winsize.ws_row = scp->ysize; 434 if (tp->t_pgrp != NULL) { 435 ksiginfo_init(&ksi); 436 ksi.ksi_signo = SIGWINCH; 437 ksi.ksi_code = SI_KERNEL; 438 PGRP_LOCK(tp->t_pgrp); 439 pgsignal(tp->t_pgrp, SIGWINCH, 1, &ksi); 440 PGRP_UNLOCK(tp->t_pgrp); 441 } 442 } 443 444 return 0; 445 #endif /* SC_PIXEL_MODE */ 446 } 447 448 int 449 sc_support_pixel_mode(void *arg) 450 { 451 #ifdef SC_PIXEL_MODE 452 video_info_t *info = arg; 453 454 if ((info->vi_flags & V_INFO_GRAPHICS) == 0) 455 return (0); 456 457 /* 458 * We currently support the following graphic modes: 459 * 460 * - 4 bpp planar modes whose memory size does not exceed 64K 461 * - 15, 16, 24 and 32 bpp linear modes 462 */ 463 switch (info->vi_mem_model) { 464 case V_INFO_MM_PLANAR: 465 if (info->vi_planes != 4) 466 break; 467 /* 468 * A memory size >64K requires bank switching to access 469 * the entire screen. XXX 470 */ 471 if (info->vi_width * info->vi_height / 8 > info->vi_window_size) 472 break; 473 return (1); 474 case V_INFO_MM_DIRECT: 475 if ((info->vi_flags & V_INFO_LINEAR) == 0 && 476 info->vi_depth != 15 && info->vi_depth != 16 && 477 info->vi_depth != 24 && info->vi_depth != 32) 478 break; 479 return (1); 480 case V_INFO_MM_PACKED: 481 if ((info->vi_flags & V_INFO_LINEAR) == 0 && 482 info->vi_depth != 8) 483 break; 484 return (1); 485 } 486 #endif 487 return (0); 488 } 489 490 #define fb_ioctl(a, c, d) \ 491 (((a) == NULL) ? ENODEV : \ 492 vidd_ioctl((a), (c), (caddr_t)(d))) 493 494 int 495 sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) 496 { 497 scr_stat *scp; 498 video_adapter_t *adp; 499 video_info_t info; 500 video_adapter_info_t adp_info; 501 int error; 502 int s; 503 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 504 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 505 int ival; 506 #endif 507 508 scp = SC_STAT(tp); 509 if (scp == NULL) /* tp == SC_MOUSE */ 510 return ENOIOCTL; 511 adp = scp->sc->adp; 512 if (adp == NULL) /* shouldn't happen??? */ 513 return ENODEV; 514 515 switch (cmd) { 516 517 case CONS_CURRENTADP: /* get current adapter index */ 518 case FBIO_ADAPTER: 519 return fb_ioctl(adp, FBIO_ADAPTER, data); 520 521 case CONS_CURRENT: /* get current adapter type */ 522 case FBIO_ADPTYPE: 523 return fb_ioctl(adp, FBIO_ADPTYPE, data); 524 525 case OLD_CONS_ADPINFO: /* adapter information (old interface) */ 526 if (((old_video_adapter_t *)data)->va_index >= 0) { 527 adp = vid_get_adapter(((old_video_adapter_t *)data)->va_index); 528 if (adp == NULL) 529 return ENODEV; 530 } 531 ((old_video_adapter_t *)data)->va_index = adp->va_index; 532 ((old_video_adapter_t *)data)->va_type = adp->va_type; 533 ((old_video_adapter_t *)data)->va_flags = adp->va_flags; 534 ((old_video_adapter_t *)data)->va_crtc_addr = adp->va_crtc_addr; 535 ((old_video_adapter_t *)data)->va_window = adp->va_window; 536 ((old_video_adapter_t *)data)->va_window_size = adp->va_window_size; 537 ((old_video_adapter_t *)data)->va_window_gran = adp->va_window_gran; 538 ((old_video_adapter_t *)data)->va_buffer = adp->va_buffer; 539 ((old_video_adapter_t *)data)->va_buffer_size = adp->va_buffer_size; 540 ((old_video_adapter_t *)data)->va_mode = adp->va_mode; 541 ((old_video_adapter_t *)data)->va_initial_mode = adp->va_initial_mode; 542 ((old_video_adapter_t *)data)->va_initial_bios_mode 543 = adp->va_initial_bios_mode; 544 return 0; 545 546 case OLD_CONS_ADPINFO2: /* adapter information (yet another old I/F) */ 547 adp_info.va_index = ((old_video_adapter_info_t *)data)->va_index; 548 if (adp_info.va_index >= 0) { 549 adp = vid_get_adapter(adp_info.va_index); 550 if (adp == NULL) 551 return ENODEV; 552 } 553 error = fb_ioctl(adp, FBIO_ADPINFO, &adp_info); 554 if (error == 0) 555 bcopy(&adp_info, data, sizeof(old_video_adapter_info_t)); 556 return error; 557 558 case CONS_ADPINFO: /* adapter information */ 559 case FBIO_ADPINFO: 560 if (((video_adapter_info_t *)data)->va_index >= 0) { 561 adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index); 562 if (adp == NULL) 563 return ENODEV; 564 } 565 return fb_ioctl(adp, FBIO_ADPINFO, data); 566 567 case CONS_GET: /* get current video mode */ 568 case FBIO_GETMODE: 569 *(int *)data = scp->mode; 570 return 0; 571 572 #ifndef SC_NO_MODE_CHANGE 573 case FBIO_SETMODE: /* set video mode */ 574 if (!(adp->va_flags & V_ADP_MODECHANGE)) 575 return ENODEV; 576 info.vi_mode = *(int *)data; 577 error = fb_ioctl(adp, FBIO_MODEINFO, &info); 578 if (error) 579 return error; 580 if (info.vi_flags & V_INFO_GRAPHICS) 581 return sc_set_graphics_mode(scp, tp, *(int *)data); 582 else 583 return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0, 0); 584 #endif /* SC_NO_MODE_CHANGE */ 585 586 case OLD_CONS_MODEINFO: /* get mode information (old infterface) */ 587 info.vi_mode = ((old_video_info_t *)data)->vi_mode; 588 error = fb_ioctl(adp, FBIO_MODEINFO, &info); 589 if (error == 0) 590 bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t)); 591 return error; 592 593 case CONS_MODEINFO: /* get mode information */ 594 case FBIO_MODEINFO: 595 return fb_ioctl(adp, FBIO_MODEINFO, data); 596 597 case OLD_CONS_FINDMODE: /* find a matching video mode (old interface) */ 598 bzero(&info, sizeof(info)); 599 bcopy((old_video_info_t *)data, &info, sizeof(old_video_info_t)); 600 error = fb_ioctl(adp, FBIO_FINDMODE, &info); 601 if (error == 0) 602 bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t)); 603 return error; 604 605 case CONS_FINDMODE: /* find a matching video mode */ 606 case FBIO_FINDMODE: 607 return fb_ioctl(adp, FBIO_FINDMODE, data); 608 609 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 610 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 611 case _IO('c', 104): 612 ival = IOCPARM_IVAL(data); 613 data = (caddr_t)&ival; 614 /* FALLTHROUGH */ 615 #endif 616 case CONS_SETWINORG: /* set frame buffer window origin */ 617 case FBIO_SETWINORG: 618 if (scp != scp->sc->cur_scp) 619 return ENODEV; /* XXX */ 620 return fb_ioctl(adp, FBIO_SETWINORG, data); 621 622 case FBIO_GETWINORG: /* get frame buffer window origin */ 623 if (scp != scp->sc->cur_scp) 624 return ENODEV; /* XXX */ 625 return fb_ioctl(adp, FBIO_GETWINORG, data); 626 627 case FBIO_GETDISPSTART: 628 case FBIO_SETDISPSTART: 629 case FBIO_GETLINEWIDTH: 630 case FBIO_SETLINEWIDTH: 631 if (scp != scp->sc->cur_scp) 632 return ENODEV; /* XXX */ 633 return fb_ioctl(adp, cmd, data); 634 635 case FBIO_GETPALETTE: 636 case FBIO_SETPALETTE: 637 case FBIOPUTCMAP: 638 case FBIOGETCMAP: 639 case FBIOGTYPE: 640 case FBIOGATTR: 641 case FBIOSVIDEO: 642 case FBIOGVIDEO: 643 case FBIOSCURSOR: 644 case FBIOGCURSOR: 645 case FBIOSCURPOS: 646 case FBIOGCURPOS: 647 case FBIOGCURMAX: 648 if (scp != scp->sc->cur_scp) 649 return ENODEV; /* XXX */ 650 return fb_ioctl(adp, cmd, data); 651 652 case FBIO_BLANK: 653 if (scp != scp->sc->cur_scp) 654 return ENODEV; /* XXX */ 655 return fb_ioctl(adp, cmd, data); 656 657 #ifndef SC_NO_MODE_CHANGE 658 /* generic text modes */ 659 case SW_TEXT_80x25: case SW_TEXT_80x30: 660 case SW_TEXT_80x43: case SW_TEXT_80x50: 661 case SW_TEXT_80x60: 662 /* FALLTHROUGH */ 663 664 /* VGA TEXT MODES */ 665 case SW_VGA_C40x25: 666 case SW_VGA_C80x25: case SW_VGA_M80x25: 667 case SW_VGA_C80x30: case SW_VGA_M80x30: 668 case SW_VGA_C80x50: case SW_VGA_M80x50: 669 case SW_VGA_C80x60: case SW_VGA_M80x60: 670 case SW_VGA_C90x25: case SW_VGA_M90x25: 671 case SW_VGA_C90x30: case SW_VGA_M90x30: 672 case SW_VGA_C90x43: case SW_VGA_M90x43: 673 case SW_VGA_C90x50: case SW_VGA_M90x50: 674 case SW_VGA_C90x60: case SW_VGA_M90x60: 675 case SW_B40x25: case SW_C40x25: 676 case SW_B80x25: case SW_C80x25: 677 case SW_ENH_B40x25: case SW_ENH_C40x25: 678 case SW_ENH_B80x25: case SW_ENH_C80x25: 679 case SW_ENH_B80x43: case SW_ENH_C80x43: 680 case SW_EGAMONO80x25: 681 682 #ifdef PC98 683 /* PC98 TEXT MODES */ 684 case SW_PC98_80x25: 685 case SW_PC98_80x30: 686 #endif 687 if (!(adp->va_flags & V_ADP_MODECHANGE)) 688 return ENODEV; 689 return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0, 0); 690 691 /* GRAPHICS MODES */ 692 case SW_BG320: case SW_BG640: 693 case SW_CG320: case SW_CG320_D: case SW_CG640_E: 694 case SW_CG640x350: case SW_ENH_CG640: 695 case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 696 case SW_VGA_MODEX: 697 #ifdef PC98 698 /* PC98 GRAPHICS MODES */ 699 case SW_PC98_EGC640x400: case SW_PC98_PEGC640x400: 700 case SW_PC98_PEGC640x480: 701 #endif 702 if (!(adp->va_flags & V_ADP_MODECHANGE)) 703 return ENODEV; 704 return sc_set_graphics_mode(scp, tp, cmd & 0xff); 705 #endif /* SC_NO_MODE_CHANGE */ 706 707 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 708 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 709 case _IO('K', 10): 710 ival = IOCPARM_IVAL(data); 711 data = (caddr_t)&ival; 712 /* FALLTHROUGH */ 713 #endif 714 case KDSETMODE: /* set current mode of this (virtual) console */ 715 switch (*(int *)data) { 716 case KD_TEXT: /* switch to TEXT (known) mode */ 717 /* 718 * If scp->mode is of graphics modes, we don't know which 719 * text mode to switch back to... 720 */ 721 if (scp->status & GRAPHICS_MODE) 722 return EINVAL; 723 /* restore fonts & palette ! */ 724 #if 0 725 #ifndef SC_NO_FONT_LOADING 726 if (ISFONTAVAIL(adp->va_flags) 727 && !(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 728 /* 729 * FONT KLUDGE 730 * Don't load fonts for now... XXX 731 */ 732 if (scp->sc->fonts_loaded & FONT_8) 733 sc_load_font(scp, 0, 8, 8, scp->sc->font_8, 0, 256); 734 if (scp->sc->fonts_loaded & FONT_14) 735 sc_load_font(scp, 0, 14, 8, scp->sc->font_14, 0, 256); 736 if (scp->sc->fonts_loaded & FONT_16) 737 sc_load_font(scp, 0, 16, 8, scp->sc->font_16, 0, 256); 738 } 739 #endif /* SC_NO_FONT_LOADING */ 740 #endif 741 742 #ifndef SC_NO_PALETTE_LOADING 743 #ifdef SC_PIXEL_MODE 744 if (adp->va_info.vi_mem_model == V_INFO_MM_DIRECT) 745 vidd_load_palette(adp, scp->sc->palette2); 746 else 747 #endif 748 vidd_load_palette(adp, scp->sc->palette); 749 #endif 750 751 #ifndef PC98 752 /* move hardware cursor out of the way */ 753 vidd_set_hw_cursor(adp, -1, -1); 754 #endif 755 756 /* FALLTHROUGH */ 757 758 case KD_TEXT1: /* switch to TEXT (known) mode */ 759 /* 760 * If scp->mode is of graphics modes, we don't know which 761 * text/pixel mode to switch back to... 762 */ 763 if (scp->status & GRAPHICS_MODE) 764 return EINVAL; 765 s = spltty(); 766 if ((error = sc_clean_up(scp))) { 767 splx(s); 768 return error; 769 } 770 #ifndef PC98 771 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 772 splx(s); 773 /* no restore fonts & palette */ 774 if (scp == scp->sc->cur_scp) 775 set_mode(scp); 776 sc_clear_screen(scp); 777 scp->status &= ~UNKNOWN_MODE; 778 #else /* PC98 */ 779 scp->status &= ~UNKNOWN_MODE; 780 /* no restore fonts & palette */ 781 if (scp == scp->sc->cur_scp) 782 set_mode(scp); 783 sc_clear_screen(scp); 784 splx(s); 785 #endif /* PC98 */ 786 return 0; 787 788 #ifdef SC_PIXEL_MODE 789 case KD_PIXEL: /* pixel (raster) display */ 790 if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 791 return EINVAL; 792 if (scp->status & GRAPHICS_MODE) 793 return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 794 scp->font_size, scp->font_width); 795 s = spltty(); 796 if ((error = sc_clean_up(scp))) { 797 splx(s); 798 return error; 799 } 800 scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 801 splx(s); 802 if (scp == scp->sc->cur_scp) { 803 set_mode(scp); 804 #ifndef SC_NO_PALETTE_LOADING 805 if (adp->va_info.vi_mem_model == V_INFO_MM_DIRECT) 806 vidd_load_palette(adp, scp->sc->palette2); 807 else 808 vidd_load_palette(adp, scp->sc->palette); 809 #endif 810 } 811 sc_clear_screen(scp); 812 scp->status &= ~UNKNOWN_MODE; 813 return 0; 814 #endif /* SC_PIXEL_MODE */ 815 816 case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 817 s = spltty(); 818 if ((error = sc_clean_up(scp))) { 819 splx(s); 820 return error; 821 } 822 scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 823 splx(s); 824 #ifdef PC98 825 if (scp == scp->sc->cur_scp) 826 set_mode(scp); 827 #endif 828 return 0; 829 830 default: 831 return EINVAL; 832 } 833 /* NOT REACHED */ 834 835 #ifdef SC_PIXEL_MODE 836 case KDRASTER: /* set pixel (raster) display mode */ 837 if (ISUNKNOWNSC(scp) || ISTEXTSC(scp)) 838 return ENODEV; 839 return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 840 ((int *)data)[2], 8); 841 #endif /* SC_PIXEL_MODE */ 842 843 case KDGETMODE: /* get current mode of this (virtual) console */ 844 /* 845 * From the user program's point of view, KD_PIXEL is the same 846 * as KD_TEXT... 847 */ 848 *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT; 849 return 0; 850 851 #if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \ 852 defined(COMPAT_FREEBSD4) || defined(COMPAT_43) 853 case _IO('K', 13): 854 ival = IOCPARM_IVAL(data); 855 data = (caddr_t)&ival; 856 /* FALLTHROUGH */ 857 #endif 858 case KDSBORDER: /* set border color of this (virtual) console */ 859 scp->border = *(int *)data; 860 if (scp == scp->sc->cur_scp) 861 sc_set_border(scp, scp->border); 862 return 0; 863 } 864 865 return ENOIOCTL; 866 } 867 868 static LIST_HEAD(, sc_renderer) sc_rndr_list = 869 LIST_HEAD_INITIALIZER(sc_rndr_list); 870 871 int 872 sc_render_add(sc_renderer_t *rndr) 873 { 874 LIST_INSERT_HEAD(&sc_rndr_list, rndr, link); 875 return 0; 876 } 877 878 int 879 sc_render_remove(sc_renderer_t *rndr) 880 { 881 /* 882 LIST_REMOVE(rndr, link); 883 */ 884 return EBUSY; /* XXX */ 885 } 886 887 sc_rndr_sw_t 888 *sc_render_match(scr_stat *scp, char *name, int mode) 889 { 890 const sc_renderer_t **list; 891 const sc_renderer_t *p; 892 893 if (!LIST_EMPTY(&sc_rndr_list)) { 894 LIST_FOREACH(p, &sc_rndr_list, link) { 895 if ((strcmp(p->name, name) == 0) 896 && (mode == p->mode)) { 897 scp->status &= 898 ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 899 return p->rndrsw; 900 } 901 } 902 } else { 903 SET_FOREACH(list, scrndr_set) { 904 p = *list; 905 if ((strcmp(p->name, name) == 0) 906 && (mode == p->mode)) { 907 scp->status &= 908 ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 909 return p->rndrsw; 910 } 911 } 912 } 913 914 return NULL; 915 } 916