scvidctl.c revision 39287
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. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote 14 * products derived from this software without specific prior written 15 * permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Id$ 30 */ 31 32#include "sc.h" 33#include "opt_syscons.h" 34 35#if NSC > 0 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/signalvar.h> 40#include <sys/tty.h> 41#include <sys/kernel.h> 42 43#include <machine/apm_bios.h> 44#include <machine/console.h> 45 46#include <i386/isa/videoio.h> 47#include <i386/isa/syscons.h> 48 49/* video ioctl */ 50 51extern scr_stat *cur_console; 52extern u_short *Crtat; 53extern int fonts_loaded; 54extern int sc_history_size; 55extern u_char palette[]; 56 57int 58sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize, 59 int fontsize) 60{ 61 video_adapter_t *adp; 62 video_info_t info; 63 int error; 64 int s; 65 int i; 66 67 if ((*biosvidsw.get_info)(scp->adp, mode, &info)) 68 return ENODEV; 69 adp = get_adapter(scp); 70 71 /* adjust argument values */ 72 if (fontsize <= 0) 73 fontsize = info.vi_cheight; 74 if (fontsize < 14) { 75 fontsize = 8; 76 if (!(fonts_loaded & FONT_8)) 77 return EINVAL; 78 } else if (fontsize >= 16) { 79 fontsize = 16; 80 if (!(fonts_loaded & FONT_16)) 81 return EINVAL; 82 } else { 83 fontsize = 14; 84 if (!(fonts_loaded & FONT_14)) 85 return EINVAL; 86 } 87 if ((xsize <= 0) || (xsize > info.vi_width)) 88 xsize = info.vi_width; 89 if ((ysize <= 0) || (ysize > info.vi_height)) 90 ysize = info.vi_height; 91 92 /* stop screen saver, etc */ 93 s = spltty(); 94 if ((error = sc_clean_up(scp))) { 95 splx(s); 96 return error; 97 } 98 99 /* set up scp */ 100 if (scp->history != NULL) 101 i = imax(scp->history_size / scp->xsize 102 - imax(sc_history_size, scp->ysize), 0); 103 else 104 i = 0; 105 /* 106 * This is a kludge to fend off scrn_update() while we 107 * muck around with scp. XXX 108 */ 109 scp->status |= UNKNOWN_MODE; 110 scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE); 111 scp->mode = mode; 112 scp->font_size = fontsize; 113 scp->xsize = xsize; 114 scp->ysize = ysize; 115 scp->xpixel = scp->xsize*8; 116 scp->ypixel = scp->ysize*fontsize; 117 118 /* allocate buffers */ 119 sc_alloc_scr_buffer(scp, TRUE, TRUE); 120 if (ISMOUSEAVAIL(adp->va_flags)) 121 sc_alloc_cut_buffer(scp, FALSE); 122 sc_alloc_history_buffer(scp, sc_history_size, i, FALSE); 123 splx(s); 124 125 if (scp == cur_console) 126 set_mode(scp); 127 scp->status &= ~UNKNOWN_MODE; 128 129 if (tp == NULL) 130 return 0; 131 if (tp->t_winsize.ws_col != scp->xsize 132 || tp->t_winsize.ws_row != scp->ysize) { 133 tp->t_winsize.ws_col = scp->xsize; 134 tp->t_winsize.ws_row = scp->ysize; 135 pgsignal(tp->t_pgrp, SIGWINCH, 1); 136 } 137 138 return 0; 139} 140 141int 142sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) 143{ 144 video_adapter_t *adp; 145 video_info_t info; 146 int error; 147 int s; 148 149 if ((*biosvidsw.get_info)(scp->adp, mode, &info)) 150 return ENODEV; 151 adp = get_adapter(scp); 152 153 /* stop screen saver, etc */ 154 s = spltty(); 155 if ((error = sc_clean_up(scp))) { 156 splx(s); 157 return error; 158 } 159 160 /* set up scp */ 161 scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE); 162 scp->status &= ~PIXEL_MODE; 163 scp->mode = mode; 164 scp->xpixel = info.vi_width; 165 scp->ypixel = info.vi_height; 166 scp->xsize = info.vi_width/8; 167 scp->ysize = info.vi_height/info.vi_cheight; 168 scp->font_size = FONT_NONE; 169 /* move the mouse cursor at the center of the screen */ 170 sc_move_mouse(scp, scp->xpixel / 2, scp->ypixel / 2); 171 splx(s); 172 173 if (scp == cur_console) 174 set_mode(scp); 175 /* clear_graphics();*/ 176 scp->status &= ~UNKNOWN_MODE; 177 178 if (tp == NULL) 179 return 0; 180 if (tp->t_winsize.ws_xpixel != scp->xpixel 181 || tp->t_winsize.ws_ypixel != scp->ypixel) { 182 tp->t_winsize.ws_xpixel = scp->xpixel; 183 tp->t_winsize.ws_ypixel = scp->ypixel; 184 pgsignal(tp->t_pgrp, SIGWINCH, 1); 185 } 186 187 return 0; 188} 189 190int 191sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 192 int fontsize) 193{ 194 video_adapter_t *adp; 195 video_info_t info; 196 int error; 197 int s; 198 int i; 199 200 if ((*biosvidsw.get_info)(scp->adp, scp->mode, &info)) 201 return ENODEV; /* this shouldn't happen */ 202 adp = get_adapter(scp); 203 204#ifdef SC_VIDEO_DEBUG 205 if (scp->scr_buf != NULL) { 206 printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n", 207 scp->mode, xsize, ysize, fontsize); 208 } 209#endif 210 211 /* adjust argument values */ 212 if ((fontsize <= 0) || (fontsize == FONT_NONE)) 213 fontsize = info.vi_cheight; 214 if (fontsize < 14) { 215 fontsize = 8; 216 if (!(fonts_loaded & FONT_8)) 217 return EINVAL; 218 } else if (fontsize >= 16) { 219 fontsize = 16; 220 if (!(fonts_loaded & FONT_16)) 221 return EINVAL; 222 } else { 223 fontsize = 14; 224 if (!(fonts_loaded & FONT_14)) 225 return EINVAL; 226 } 227 if (xsize <= 0) 228 xsize = info.vi_width/8; 229 if (ysize <= 0) 230 ysize = info.vi_height/fontsize; 231 232#ifdef SC_VIDEO_DEBUG 233 if (scp->scr_buf != NULL) { 234 printf("set_pixel_mode(): mode:%x, col:%d, row:%d, font:%d\n", 235 scp->mode, xsize, ysize, fontsize); 236 printf("set_pixel_mode(): Crtat:%x, %dx%d, xoff:%d, yoff:%d\n", 237 Crtat, info.vi_width, info.vi_height, 238 (info.vi_width/8 - xsize)/2, 239 (info.vi_height/fontsize - ysize)/2); 240 } 241#endif 242 243 /* stop screen saver, etc */ 244 s = spltty(); 245 if ((error = sc_clean_up(scp))) { 246 splx(s); 247 return error; 248 } 249 250 /* set up scp */ 251 if (scp->history != NULL) 252 i = imax(scp->history_size / scp->xsize 253 - imax(sc_history_size, scp->ysize), 0); 254 else 255 i = 0; 256 scp->status |= (UNKNOWN_MODE | PIXEL_MODE); 257 scp->status &= ~(GRAPHICS_MODE | MOUSE_ENABLED); 258 scp->xsize = xsize; 259 scp->ysize = ysize; 260 scp->font_size = fontsize; 261 scp->xoff = (scp->xpixel/8 - xsize)/2; 262 scp->yoff = (scp->ypixel/fontsize - ysize)/2; 263 264 /* allocate buffers */ 265 sc_alloc_scr_buffer(scp, TRUE, TRUE); 266 if (ISMOUSEAVAIL(adp->va_flags)) 267 sc_alloc_cut_buffer(scp, FALSE); 268 sc_alloc_history_buffer(scp, sc_history_size, i, FALSE); 269 splx(s); 270 271 /* FIXME */ 272 if (scp == cur_console) 273 bzero(Crtat, scp->xpixel*scp->ypixel/8); 274 275 scp->status &= ~UNKNOWN_MODE; 276 277#ifdef SC_VIDEO_DEBUG 278 printf("set_pixel_mode(): status:%x\n", scp->status); 279#endif 280 281 if (tp == NULL) 282 return 0; 283 if (tp->t_winsize.ws_col != scp->xsize 284 || tp->t_winsize.ws_row != scp->ysize) { 285 tp->t_winsize.ws_col = scp->xsize; 286 tp->t_winsize.ws_row = scp->ysize; 287 pgsignal(tp->t_pgrp, SIGWINCH, 1); 288 } 289 290 return 0; 291} 292 293int 294sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) 295{ 296 scr_stat *scp; 297 video_adapter_t *adp; 298 int error; 299 int s; 300 301 scp = sc_get_scr_stat(tp->t_dev); 302 303 switch (cmd) { 304 305 case CONS_CURRENT: /* get current adapter type */ 306 adp = get_adapter(scp); 307 *(int *)data = adp->va_type; 308 return 0; 309 310 case CONS_CURRENTADP: /* get current adapter index */ 311 *(int *)data = scp->adp; 312 return 0; 313 314 case CONS_ADPINFO: /* adapter information */ 315 adp = (*biosvidsw.adapter)(((video_adapter_t *)data)->va_index); 316 if (adp == NULL) 317 return ENODEV; 318 bcopy(adp, data, sizeof(*adp)); 319 return 0; 320 321 case CONS_GET: /* get current video mode */ 322 *(int *)data = scp->mode; 323 return 0; 324 325 case CONS_MODEINFO: /* get mode information */ 326 return ((*biosvidsw.get_info)(scp->adp, 327 ((video_info_t *)data)->vi_mode, (video_info_t *)data) 328 ? ENODEV : 0); 329 330 case CONS_FINDMODE: /* find a matching video mode */ 331 return ((*biosvidsw.query_mode)(scp->adp, (video_info_t *)data) 332 ? ENODEV : 0); 333 334 case CONS_SETWINORG: 335 return ((*biosvidsw.set_win_org)(scp->adp, *(u_int *)data) 336 ? ENODEV : 0); 337 338 /* VGA TEXT MODES */ 339 case SW_VGA_C40x25: 340 case SW_VGA_C80x25: case SW_VGA_M80x25: 341 case SW_VGA_C80x30: case SW_VGA_M80x30: 342 case SW_VGA_C80x50: case SW_VGA_M80x50: 343 case SW_VGA_C80x60: case SW_VGA_M80x60: 344 case SW_B40x25: case SW_C40x25: 345 case SW_B80x25: case SW_C80x25: 346 case SW_ENH_B40x25: case SW_ENH_C40x25: 347 case SW_ENH_B80x25: case SW_ENH_C80x25: 348 case SW_ENH_B80x43: case SW_ENH_C80x43: 349 case SW_EGAMONO80x25: 350 adp = get_adapter(scp); 351 if (!(adp->va_flags & V_ADP_MODECHANGE)) 352 return ENODEV; 353 return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0); 354 355 /* GRAPHICS MODES */ 356 case SW_BG320: case SW_BG640: 357 case SW_CG320: case SW_CG320_D: case SW_CG640_E: 358 case SW_CG640x350: case SW_ENH_CG640: 359 case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 360 case SW_VGA_MODEX: 361 adp = get_adapter(scp); 362 if (!(adp->va_flags & V_ADP_MODECHANGE)) 363 return ENODEV; 364 return sc_set_graphics_mode(scp, tp, cmd & 0xff); 365 366 case KDSETMODE: /* set current mode of this (virtual) console */ 367 switch (*data) { 368 case KD_TEXT: /* switch to TEXT (known) mode */ 369 /* 370 * If scp->mode is of graphics modes, we don't know which 371 * text mode to switch back to... 372 */ 373 if (scp->status & GRAPHICS_MODE) 374 return EINVAL; 375 /* restore fonts & palette ! */ 376#if 0 377 adp = get_adapter(scp); 378 if (ISFONTAVAIL(adp->va_flags) 379 && !(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 380 /* 381 * FONT KLUDGE 382 * Don't load fonts for now... XXX 383 */ 384 if (fonts_loaded & FONT_8) 385 copy_font(scp, LOAD, 8, font_8); 386 if (fonts_loaded & FONT_14) 387 copy_font(scp, LOAD, 14, font_14); 388 if (fonts_loaded & FONT_16) 389 copy_font(scp, LOAD, 16, font_16); 390 } 391#endif 392 load_palette(scp, palette); 393 394 /* move hardware cursor out of the way */ 395 (*biosvidsw.set_hw_cursor)(scp->adp, -1, -1); 396 397 /* FALL THROUGH */ 398 399 case KD_TEXT1: /* switch to TEXT (known) mode */ 400 /* 401 * If scp->mode is of graphics modes, we don't know which 402 * text/pixel mode to switch back to... 403 */ 404 if (scp->status & GRAPHICS_MODE) 405 return EINVAL; 406 s = spltty(); 407 if ((error = sc_clean_up(scp))) { 408 splx(s); 409 return error; 410 } 411 scp->status |= UNKNOWN_MODE; 412 splx(s); 413 /* no restore fonts & palette */ 414 if (scp == cur_console) { 415 set_mode(scp); 416 /* FIXME */ 417 if (scp->status & PIXEL_MODE) 418 bzero(Crtat, scp->xpixel*scp->ypixel/8); 419 } 420 sc_clear_screen(scp); 421 scp->status &= ~UNKNOWN_MODE; 422 return 0; 423 424 case KD_PIXEL: /* pixel (raster) display */ 425 if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 426 return EINVAL; 427 if (!(scp->status & PIXEL_MODE)) 428 return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 429 scp->font_size); 430 s = spltty(); 431 if ((error = sc_clean_up(scp))) { 432 splx(s); 433 return error; 434 } 435 scp->status |= (UNKNOWN_MODE | PIXEL_MODE); 436 splx(s); 437 if (scp == cur_console) { 438 set_mode(scp); 439 load_palette(scp, palette); 440 /* FIXME */ 441 bzero(Crtat, scp->xpixel*scp->ypixel/8); 442 } 443 sc_clear_screen(scp); 444 scp->status &= ~UNKNOWN_MODE; 445 return 0; 446 447 case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 448 s = spltty(); 449 if ((error = sc_clean_up(scp))) { 450 splx(s); 451 return error; 452 } 453 scp->status |= UNKNOWN_MODE; 454 splx(s); 455 return 0; 456 457 default: 458 return EINVAL; 459 } 460 /* NOT REACHED */ 461 462 case KDRASTER: /* set pixel (raster) display mode */ 463 if (ISUNKNOWNSC(scp) || ISTEXTSC(scp)) 464 return ENODEV; 465 return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 466 ((int *)data)[2]); 467 468 case KDGETMODE: /* get current mode of this (virtual) console */ 469 /* 470 * From the user program's point of view, KD_PIXEL is the same 471 * as KD_TEXT... 472 */ 473 *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT; 474 return 0; 475 476 case KDSBORDER: /* set border color of this (virtual) console */ 477 scp->border = *data; 478 if (scp == cur_console) 479 set_border(cur_console, scp->border); 480 return 0; 481 } 482 483 return ENOIOCTL; 484} 485 486#endif /* NSC > 0 */ 487