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