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