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