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