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