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