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