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