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