scvidctl.c revision 59689
1234353Sdim/*- 2193323Sed * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer as 10193323Sed * the first lines of this file unmodified. 11193323Sed * 2. Redistributions in binary form must reproduce the above copyright 12193323Sed * notice, this list of conditions and the following disclaimer in the 13193323Sed * documentation and/or other materials provided with the distribution. 14193323Sed * 15193323Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16193323Sed * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17193323Sed * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18193323Sed * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19193323Sed * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20193323Sed * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21249423Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22193323Sed * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23239462Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24193323Sed * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25193323Sed * 26193323Sed * $FreeBSD: head/sys/dev/syscons/scvidctl.c 59689 2000-04-27 13:34:32Z nyan $ 27249423Sdim */ 28249423Sdim 29234353Sdim#include "opt_syscons.h" 30207618Srdivacky 31193323Sed#include <sys/param.h> 32202375Srdivacky#include <sys/systm.h> 33198090Srdivacky#include <sys/conf.h> 34198090Srdivacky#include <sys/signalvar.h> 35193323Sed#include <sys/tty.h> 36199481Srdivacky#include <sys/kernel.h> 37199481Srdivacky 38224145Sdim#include <machine/console.h> 39224145Sdim 40224145Sdim#include <dev/fb/fbreg.h> 41193323Sed#include <dev/syscons/syscons.h> 42193323Sed 43198090Srdivacky/* for compatibility with previous versions */ 44198090Srdivacky/* 3.0-RELEASE used the following structure */ 45198090Srdivackytypedef struct old_video_adapter { 46198090Srdivacky int va_index; 47198090Srdivacky int va_type; 48198090Srdivacky int va_flags; 49198090Srdivacky/* flag bits are the same as the -CURRENT 50198090Srdivacky#define V_ADP_COLOR (1<<0) 51198090Srdivacky#define V_ADP_MODECHANGE (1<<1) 52198090Srdivacky#define V_ADP_STATESAVE (1<<2) 53198090Srdivacky#define V_ADP_STATELOAD (1<<3) 54198090Srdivacky#define V_ADP_FONT (1<<4) 55193323Sed#define V_ADP_PALETTE (1<<5) 56226633Sdim#define V_ADP_BORDER (1<<6) 57226633Sdim#define V_ADP_VESA (1<<7) 58239462Sdim*/ 59226633Sdim int va_crtc_addr; 60226633Sdim u_int va_window; /* virtual address */ 61226633Sdim size_t va_window_size; 62239462Sdim size_t va_window_gran; 63239462Sdim u_int va_buffer; /* virtual address */ 64226633Sdim size_t va_buffer_size; 65239462Sdim int va_initial_mode; 66239462Sdim int va_initial_bios_mode; 67239462Sdim int va_mode; 68239462Sdim} old_video_adapter_t; 69239462Sdim 70239462Sdim#define OLD_CONS_ADPINFO _IOWR('c', 101, old_video_adapter_t) 71239462Sdim 72239462Sdim/* 3.1-RELEASE used the following structure */ 73239462Sdimtypedef struct old_video_adapter_info { 74239462Sdim int va_index; 75239462Sdim int va_type; 76239462Sdim char va_name[16]; 77226633Sdim int va_unit; 78226633Sdim int va_flags; 79226633Sdim int va_io_base; 80226633Sdim int va_io_size; 81226633Sdim int va_crtc_addr; 82226633Sdim int va_mem_base; 83226633Sdim int va_mem_size; 84239462Sdim u_int va_window; /* virtual address */ 85226633Sdim size_t va_window_size; 86226633Sdim size_t va_window_gran; 87234353Sdim u_int va_buffer;; 88234353Sdim size_t va_buffer_size; 89234353Sdim int va_initial_mode; 90239462Sdim int va_initial_bios_mode; 91234353Sdim int va_mode; 92234353Sdim int va_line_width; 93193323Sed} old_video_adapter_info_t; 94224145Sdim 95224145Sdim#define OLD_CONS_ADPINFO2 _IOWR('c', 101, old_video_adapter_info_t) 96224145Sdim 97224145Sdim/* 3.0-RELEASE and 3.1-RELEASE used the following structure */ 98224145Sdimtypedef struct old_video_info { 99224145Sdim int vi_mode; 100193323Sed int vi_flags; 101218893Sdim/* flag bits are the same as the -CURRENT 102234353Sdim#define V_INFO_COLOR (1<<0) 103226633Sdim#define V_INFO_GRAPHICS (1<<1) 104226633Sdim#define V_INFO_LINEAR (1<<2) 105226633Sdim#define V_INFO_VESA (1<<3) 106226633Sdim*/ 107226633Sdim int vi_width; 108226633Sdim int vi_height; 109226633Sdim int vi_cwidth; 110226633Sdim int vi_cheight; 111226633Sdim int vi_depth; 112226633Sdim int vi_planes; 113226633Sdim u_int vi_window; /* physical address */ 114226633Sdim size_t vi_window_size; 115226633Sdim size_t vi_window_gran; 116226633Sdim u_int vi_buffer; /* physical address */ 117226633Sdim size_t vi_buffer_size; 118226633Sdim} old_video_info_t; 119226633Sdim 120226633Sdim#define OLD_CONS_MODEINFO _IOWR('c', 102, old_video_info_t) 121226633Sdim#define OLD_CONS_FINDMODE _IOWR('c', 103, old_video_info_t) 122226633Sdim 123226633Sdimint 124226633Sdimsc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize, 125226633Sdim int fontsize) 126226633Sdim{ 127226633Sdim video_info_t info; 128226633Sdim u_char *font; 129226633Sdim int prev_ysize; 130226633Sdim int error; 131226633Sdim int s; 132226633Sdim 133226633Sdim if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) 134226633Sdim return ENODEV; 135226633Sdim 136226633Sdim /* adjust argument values */ 137226633Sdim if (fontsize <= 0) 138226633Sdim fontsize = info.vi_cheight; 139226633Sdim if (fontsize < 14) { 140226633Sdim fontsize = 8; 141226633Sdim#ifndef SC_NO_FONT_LOADING 142226633Sdim if (!(scp->sc->fonts_loaded & FONT_8)) 143226633Sdim return EINVAL; 144226633Sdim font = scp->sc->font_8; 145226633Sdim#else 146226633Sdim font = NULL; 147226633Sdim#endif 148226633Sdim } else if (fontsize >= 16) { 149226633Sdim fontsize = 16; 150226633Sdim#ifndef SC_NO_FONT_LOADING 151226633Sdim if (!(scp->sc->fonts_loaded & FONT_16)) 152226633Sdim return EINVAL; 153226633Sdim font = scp->sc->font_16; 154226633Sdim#else 155226633Sdim font = NULL; 156226633Sdim#endif 157226633Sdim } else { 158226633Sdim fontsize = 14; 159226633Sdim#ifndef SC_NO_FONT_LOADING 160226633Sdim if (!(scp->sc->fonts_loaded & FONT_14)) 161226633Sdim return EINVAL; 162226633Sdim font = scp->sc->font_14; 163226633Sdim#else 164226633Sdim font = NULL; 165226633Sdim#endif 166226633Sdim } 167226633Sdim if ((xsize <= 0) || (xsize > info.vi_width)) 168226633Sdim xsize = info.vi_width; 169226633Sdim if ((ysize <= 0) || (ysize > info.vi_height)) 170226633Sdim ysize = info.vi_height; 171226633Sdim 172226633Sdim /* stop screen saver, etc */ 173226633Sdim s = spltty(); 174226633Sdim if ((error = sc_clean_up(scp))) { 175226633Sdim splx(s); 176226633Sdim return error; 177226633Sdim } 178226633Sdim 179226633Sdim if (sc_render_match(scp, scp->sc->adp->va_name, 0) == NULL) { 180226633Sdim splx(s); 181226633Sdim return ENODEV; 182226633Sdim } 183226633Sdim 184226633Sdim /* set up scp */ 185226633Sdim#ifndef SC_NO_HISTORY 186226633Sdim if (scp->history != NULL) 187226633Sdim sc_hist_save(scp); 188226633Sdim#endif 189226633Sdim prev_ysize = scp->ysize; 190226633Sdim /* 191226633Sdim * This is a kludge to fend off scrn_update() while we 192226633Sdim * muck around with scp. XXX 193226633Sdim */ 194226633Sdim scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 195226633Sdim scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE); 196226633Sdim scp->mode = mode; 197226633Sdim scp->xsize = xsize; 198226633Sdim scp->ysize = ysize; 199226633Sdim scp->xoff = 0; 200226633Sdim scp->yoff = 0; 201226633Sdim scp->xpixel = scp->xsize*8; 202226633Sdim scp->ypixel = scp->ysize*fontsize; 203226633Sdim scp->font = font; 204226633Sdim scp->font_size = fontsize; 205226633Sdim 206226633Sdim /* allocate buffers */ 207226633Sdim sc_alloc_scr_buffer(scp, TRUE, TRUE); 208226633Sdim sc_init_emulator(scp, NULL); 209226633Sdim#ifndef SC_NO_CUTPASTE 210226633Sdim sc_alloc_cut_buffer(scp, FALSE); 211226633Sdim#endif 212226633Sdim#ifndef SC_NO_HISTORY 213226633Sdim sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE); 214226633Sdim#endif 215226633Sdim splx(s); 216226633Sdim 217226633Sdim if (scp == scp->sc->cur_scp) 218226633Sdim set_mode(scp); 219226633Sdim scp->status &= ~UNKNOWN_MODE; 220226633Sdim 221226633Sdim if (tp == NULL) 222226633Sdim return 0; 223226633Sdim DPRINTF(5, ("ws_*size (%d,%d), size (%d,%d)\n", 224226633Sdim tp->t_winsize.ws_col, tp->t_winsize.ws_row, scp->xsize, scp->ysize)); 225226633Sdim if (tp->t_winsize.ws_col != scp->xsize 226226633Sdim || tp->t_winsize.ws_row != scp->ysize) { 227226633Sdim tp->t_winsize.ws_col = scp->xsize; 228226633Sdim tp->t_winsize.ws_row = scp->ysize; 229226633Sdim pgsignal(tp->t_pgrp, SIGWINCH, 1); 230226633Sdim } 231226633Sdim 232226633Sdim return 0; 233226633Sdim} 234226633Sdim 235226633Sdimint 236226633Sdimsc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode) 237226633Sdim{ 238226633Sdim#ifdef SC_NO_MODE_CHANGE 239226633Sdim return ENODEV; 240226633Sdim#else 241226633Sdim video_info_t info; 242226633Sdim int error; 243226633Sdim int s; 244226633Sdim 245226633Sdim if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info)) 246226633Sdim return ENODEV; 247226633Sdim 248226633Sdim /* stop screen saver, etc */ 249226633Sdim s = spltty(); 250226633Sdim if ((error = sc_clean_up(scp))) { 251226633Sdim splx(s); 252226633Sdim return error; 253226633Sdim } 254226633Sdim 255226633Sdim if (sc_render_match(scp, scp->sc->adp->va_name, GRAPHICS_MODE) == NULL) { 256226633Sdim splx(s); 257226633Sdim return ENODEV; 258226633Sdim } 259226633Sdim 260226633Sdim /* set up scp */ 261226633Sdim scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE | MOUSE_HIDDEN); 262226633Sdim scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE); 263226633Sdim scp->mode = mode; 264226633Sdim /* 265226633Sdim * Don't change xsize and ysize; preserve the previous vty 266226633Sdim * and history buffers. 267193323Sed */ 268193323Sed scp->xoff = 0; 269193323Sed scp->yoff = 0; 270234353Sdim scp->xpixel = info.vi_width; 271234353Sdim scp->ypixel = info.vi_height; 272234353Sdim scp->font = NULL; 273226633Sdim scp->font_size = 0; 274226633Sdim#ifndef SC_NO_SYSMOUSE 275226633Sdim /* move the mouse cursor at the center of the screen */ 276226633Sdim sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2); 277193323Sed#endif 278193323Sed sc_init_emulator(scp, NULL); 279234353Sdim splx(s); 280226633Sdim 281226633Sdim if (scp == scp->sc->cur_scp) 282226633Sdim set_mode(scp); 283226633Sdim /* clear_graphics();*/ 284226633Sdim scp->status &= ~UNKNOWN_MODE; 285226633Sdim 286226633Sdim if (tp == NULL) 287226633Sdim return 0; 288226633Sdim if (tp->t_winsize.ws_xpixel != scp->xpixel 289226633Sdim || tp->t_winsize.ws_ypixel != scp->ypixel) { 290226633Sdim tp->t_winsize.ws_xpixel = scp->xpixel; 291226633Sdim tp->t_winsize.ws_ypixel = scp->ypixel; 292226633Sdim pgsignal(tp->t_pgrp, SIGWINCH, 1); 293226633Sdim } 294226633Sdim 295226633Sdim return 0; 296226633Sdim#endif /* SC_NO_MODE_CHANGE */ 297226633Sdim} 298226633Sdim 299226633Sdimint 300249423Sdimsc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, 301226633Sdim int fontsize) 302226633Sdim{ 303226633Sdim#ifndef SC_PIXEL_MODE 304226633Sdim return ENODEV; 305226633Sdim#else 306226633Sdim video_info_t info; 307226633Sdim u_char *font; 308226633Sdim int prev_ysize; 309226633Sdim int error; 310226633Sdim int s; 311226633Sdim 312226633Sdim if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info)) 313226633Sdim return ENODEV; /* this shouldn't happen */ 314226633Sdim 315226633Sdim /* adjust argument values */ 316226633Sdim if (fontsize <= 0) 317226633Sdim fontsize = info.vi_cheight; 318226633Sdim if (fontsize < 14) { 319226633Sdim fontsize = 8; 320226633Sdim#ifndef SC_NO_FONT_LOADING 321226633Sdim if (!(scp->sc->fonts_loaded & FONT_8)) 322226633Sdim return EINVAL; 323226633Sdim font = scp->sc->font_8; 324226633Sdim#else 325226633Sdim font = NULL; 326226633Sdim#endif 327226633Sdim } else if (fontsize >= 16) { 328226633Sdim fontsize = 16; 329226633Sdim#ifndef SC_NO_FONT_LOADING 330226633Sdim if (!(scp->sc->fonts_loaded & FONT_16)) 331226633Sdim return EINVAL; 332226633Sdim font = scp->sc->font_16; 333226633Sdim#else 334226633Sdim font = NULL; 335226633Sdim#endif 336226633Sdim } else { 337226633Sdim fontsize = 14; 338226633Sdim#ifndef SC_NO_FONT_LOADING 339226633Sdim if (!(scp->sc->fonts_loaded & FONT_14)) 340226633Sdim return EINVAL; 341226633Sdim font = scp->sc->font_14; 342226633Sdim#else 343226633Sdim font = NULL; 344226633Sdim#endif 345226633Sdim } 346226633Sdim if (xsize <= 0) 347226633Sdim xsize = info.vi_width/8; 348226633Sdim if (ysize <= 0) 349226633Sdim ysize = info.vi_height/fontsize; 350226633Sdim 351226633Sdim if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize)) 352226633Sdim return EINVAL; 353226633Sdim 354226633Sdim /* only 16 color, 4 plane modes are supported XXX */ 355226633Sdim if ((info.vi_depth != 4) || (info.vi_planes != 4)) 356226633Sdim return ENODEV; 357226633Sdim 358249423Sdim /* 359226633Sdim * set_pixel_mode() currently does not support video modes whose 360226633Sdim * memory size is larger than 64K. Because such modes require 361234353Sdim * bank switching to access the entire screen. XXX 362226633Sdim */ 363226633Sdim if (info.vi_width*info.vi_height/8 > info.vi_window_size) 364226633Sdim return ENODEV; 365226633Sdim 366226633Sdim /* stop screen saver, etc */ 367226633Sdim s = spltty(); 368226633Sdim if ((error = sc_clean_up(scp))) { 369226633Sdim splx(s); 370226633Sdim return error; 371226633Sdim } 372234353Sdim 373226633Sdim if (sc_render_match(scp, scp->sc->adp->va_name, PIXEL_MODE) == NULL) { 374226633Sdim splx(s); 375226633Sdim return ENODEV; 376226633Sdim } 377226633Sdim 378193323Sed#if 0 379193323Sed if (scp->tsw) 380193323Sed (*scp->tsw->te_term)(scp, scp->ts); 381234353Sdim scp->tsw = NULL; 382234353Sdim scp->ts = NULL; 383234353Sdim#endif 384226633Sdim 385226633Sdim /* set up scp */ 386193323Sed#ifndef SC_NO_HISTORY 387193323Sed if (scp->history != NULL) 388234353Sdim sc_hist_save(scp); 389226633Sdim#endif 390226633Sdim prev_ysize = scp->ysize; 391226633Sdim scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 392226633Sdim scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE); 393226633Sdim scp->xsize = xsize; 394226633Sdim scp->ysize = ysize; 395226633Sdim scp->xoff = (scp->xpixel/8 - xsize)/2; 396226633Sdim scp->yoff = (scp->ypixel/fontsize - ysize)/2; 397226633Sdim scp->font = font; 398226633Sdim scp->font_size = fontsize; 399226633Sdim 400226633Sdim /* allocate buffers */ 401226633Sdim sc_alloc_scr_buffer(scp, TRUE, TRUE); 402226633Sdim sc_init_emulator(scp, NULL); 403226633Sdim#ifndef SC_NO_CUTPASTE 404226633Sdim sc_alloc_cut_buffer(scp, FALSE); 405226633Sdim#endif 406226633Sdim#ifndef SC_NO_HISTORY 407226633Sdim sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE); 408226633Sdim#endif 409226633Sdim splx(s); 410226633Sdim 411226633Sdim if (scp == scp->sc->cur_scp) { 412226633Sdim sc_set_border(scp, scp->border); 413226633Sdim sc_set_cursor_image(scp); 414226633Sdim } 415239462Sdim 416239462Sdim scp->status &= ~UNKNOWN_MODE; 417226633Sdim 418226633Sdim if (tp == NULL) 419226633Sdim return 0; 420226633Sdim if (tp->t_winsize.ws_col != scp->xsize 421226633Sdim || tp->t_winsize.ws_row != scp->ysize) { 422226633Sdim tp->t_winsize.ws_col = scp->xsize; 423226633Sdim tp->t_winsize.ws_row = scp->ysize; 424226633Sdim pgsignal(tp->t_pgrp, SIGWINCH, 1); 425226633Sdim } 426226633Sdim 427226633Sdim return 0; 428226633Sdim#endif /* SC_PIXEL_MODE */ 429226633Sdim} 430226633Sdim 431226633Sdim#define fb_ioctl(a, c, d) \ 432226633Sdim (((a) == NULL) ? ENODEV : \ 433226633Sdim (*vidsw[(a)->va_index]->ioctl)((a), (c), (caddr_t)(d))) 434226633Sdim 435226633Sdimint 436226633Sdimsc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) 437226633Sdim{ 438226633Sdim scr_stat *scp; 439226633Sdim video_adapter_t *adp; 440226633Sdim video_info_t info; 441226633Sdim video_adapter_info_t adp_info; 442226633Sdim int error; 443226633Sdim int s; 444226633Sdim 445226633Sdim scp = SC_STAT(tp->t_dev); 446226633Sdim if (scp == NULL) /* tp == SC_MOUSE */ 447226633Sdim return ENOIOCTL; 448226633Sdim adp = scp->sc->adp; 449226633Sdim if (adp == NULL) /* shouldn't happen??? */ 450226633Sdim return ENODEV; 451226633Sdim 452226633Sdim switch (cmd) { 453226633Sdim 454226633Sdim case CONS_CURRENTADP: /* get current adapter index */ 455226633Sdim case FBIO_ADAPTER: 456226633Sdim return fb_ioctl(adp, FBIO_ADAPTER, data); 457234353Sdim 458234353Sdim case CONS_CURRENT: /* get current adapter type */ 459234353Sdim case FBIO_ADPTYPE: 460226633Sdim return fb_ioctl(adp, FBIO_ADPTYPE, data); 461226633Sdim 462226633Sdim case OLD_CONS_ADPINFO: /* adapter information (old interface) */ 463226633Sdim if (((old_video_adapter_t *)data)->va_index >= 0) { 464226633Sdim adp = vid_get_adapter(((old_video_adapter_t *)data)->va_index); 465226633Sdim if (adp == NULL) 466226633Sdim return ENODEV; 467226633Sdim } 468226633Sdim ((old_video_adapter_t *)data)->va_index = adp->va_index; 469226633Sdim ((old_video_adapter_t *)data)->va_type = adp->va_type; 470226633Sdim ((old_video_adapter_t *)data)->va_flags = adp->va_flags; 471226633Sdim ((old_video_adapter_t *)data)->va_crtc_addr = adp->va_crtc_addr; 472226633Sdim ((old_video_adapter_t *)data)->va_window = adp->va_window; 473226633Sdim ((old_video_adapter_t *)data)->va_window_size = adp->va_window_size; 474226633Sdim ((old_video_adapter_t *)data)->va_window_gran = adp->va_window_gran; 475226633Sdim ((old_video_adapter_t *)data)->va_buffer = adp->va_buffer; 476226633Sdim ((old_video_adapter_t *)data)->va_buffer_size = adp->va_buffer_size; 477226633Sdim ((old_video_adapter_t *)data)->va_mode = adp->va_mode; 478226633Sdim ((old_video_adapter_t *)data)->va_initial_mode = adp->va_initial_mode; 479193323Sed ((old_video_adapter_t *)data)->va_initial_bios_mode 480226633Sdim = adp->va_initial_bios_mode; 481226633Sdim return 0; 482226633Sdim 483226633Sdim case OLD_CONS_ADPINFO2: /* adapter information (yet another old I/F) */ 484226633Sdim adp_info.va_index = ((old_video_adapter_info_t *)data)->va_index; 485226633Sdim if (adp_info.va_index >= 0) { 486226633Sdim adp = vid_get_adapter(adp_info.va_index); 487239462Sdim if (adp == NULL) 488239462Sdim return ENODEV; 489239462Sdim } 490239462Sdim error = fb_ioctl(adp, FBIO_ADPINFO, &adp_info); 491239462Sdim if (error == 0) 492239462Sdim bcopy(&adp_info, data, sizeof(old_video_adapter_info_t)); 493239462Sdim return error; 494239462Sdim 495239462Sdim case CONS_ADPINFO: /* adapter information */ 496239462Sdim case FBIO_ADPINFO: 497239462Sdim if (((video_adapter_info_t *)data)->va_index >= 0) { 498239462Sdim adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index); 499226633Sdim if (adp == NULL) 500226633Sdim return ENODEV; 501226633Sdim } 502226633Sdim return fb_ioctl(adp, FBIO_ADPINFO, data); 503226633Sdim 504226633Sdim case CONS_GET: /* get current video mode */ 505226633Sdim case FBIO_GETMODE: 506226633Sdim *(int *)data = scp->mode; 507226633Sdim return 0; 508226633Sdim 509226633Sdim#ifndef SC_NO_MODE_CHANGE 510226633Sdim case FBIO_SETMODE: /* set video mode */ 511249423Sdim if (!(adp->va_flags & V_ADP_MODECHANGE)) 512226633Sdim return ENODEV; 513226633Sdim info.vi_mode = *(int *)data; 514226633Sdim error = fb_ioctl(adp, FBIO_MODEINFO, &info); 515226633Sdim if (error) 516249423Sdim return error; 517249423Sdim if (info.vi_flags & V_INFO_GRAPHICS) 518249423Sdim return sc_set_graphics_mode(scp, tp, *(int *)data); 519249423Sdim else 520249423Sdim return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0); 521249423Sdim#endif /* SC_NO_MODE_CHANGE */ 522249423Sdim 523249423Sdim case OLD_CONS_MODEINFO: /* get mode information (old infterface) */ 524249423Sdim info.vi_mode = ((old_video_info_t *)data)->vi_mode; 525249423Sdim error = fb_ioctl(adp, FBIO_MODEINFO, &info); 526249423Sdim if (error == 0) 527249423Sdim bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t)); 528249423Sdim return error; 529249423Sdim 530226633Sdim case CONS_MODEINFO: /* get mode information */ 531226633Sdim case FBIO_MODEINFO: 532239462Sdim return fb_ioctl(adp, FBIO_MODEINFO, data); 533239462Sdim 534226633Sdim case OLD_CONS_FINDMODE: /* find a matching video mode (old interface) */ 535226633Sdim bzero(&info, sizeof(info)); 536226633Sdim bcopy((old_video_info_t *)data, &info, sizeof(old_video_info_t)); 537234353Sdim error = fb_ioctl(adp, FBIO_FINDMODE, &info); 538226633Sdim if (error == 0) 539234353Sdim bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t)); 540249423Sdim return error; 541249423Sdim 542239462Sdim case CONS_FINDMODE: /* find a matching video mode */ 543234353Sdim case FBIO_FINDMODE: 544249423Sdim return fb_ioctl(adp, FBIO_FINDMODE, data); 545249423Sdim 546249423Sdim case CONS_SETWINORG: /* set frame buffer window origin */ 547249423Sdim case FBIO_SETWINORG: 548249423Sdim if (scp != scp->sc->cur_scp) 549249423Sdim return ENODEV; /* XXX */ 550249423Sdim return fb_ioctl(adp, FBIO_SETWINORG, data); 551249423Sdim 552249423Sdim case FBIO_GETWINORG: /* get frame buffer window origin */ 553249423Sdim if (scp != scp->sc->cur_scp) 554249423Sdim return ENODEV; /* XXX */ 555239462Sdim return fb_ioctl(adp, FBIO_GETWINORG, data); 556239462Sdim 557243830Sdim case FBIO_GETDISPSTART: 558249423Sdim case FBIO_SETDISPSTART: 559249423Sdim case FBIO_GETLINEWIDTH: 560249423Sdim case FBIO_SETLINEWIDTH: 561249423Sdim if (scp != scp->sc->cur_scp) 562249423Sdim return ENODEV; /* XXX */ 563249423Sdim return fb_ioctl(adp, cmd, data); 564249423Sdim 565249423Sdim case FBIO_GETPALETTE: 566249423Sdim case FBIO_SETPALETTE: 567249423Sdim case FBIOPUTCMAP: 568249423Sdim case FBIOGETCMAP: 569249423Sdim case FBIOGTYPE: 570249423Sdim case FBIOGATTR: 571249423Sdim case FBIOSVIDEO: 572249423Sdim case FBIOGVIDEO: 573249423Sdim case FBIOSCURSOR: 574249423Sdim case FBIOGCURSOR: 575243830Sdim case FBIOSCURPOS: 576243830Sdim case FBIOGCURPOS: 577243830Sdim case FBIOGCURMAX: 578243830Sdim if (scp != scp->sc->cur_scp) 579243830Sdim return ENODEV; /* XXX */ 580243830Sdim return fb_ioctl(adp, cmd, data); 581243830Sdim 582243830Sdim#ifndef SC_NO_MODE_CHANGE 583249423Sdim /* generic text modes */ 584249423Sdim case SW_TEXT_80x25: case SW_TEXT_80x30: 585249423Sdim case SW_TEXT_80x43: case SW_TEXT_80x50: 586193323Sed case SW_TEXT_80x60: 587193323Sed /* FALL THROUGH */ 588193323Sed 589234353Sdim /* VGA TEXT MODES */ 590234353Sdim case SW_VGA_C40x25: 591234353Sdim case SW_VGA_C80x25: case SW_VGA_M80x25: 592226633Sdim case SW_VGA_C80x30: case SW_VGA_M80x30: 593226633Sdim case SW_VGA_C80x50: case SW_VGA_M80x50: 594226633Sdim case SW_VGA_C80x60: case SW_VGA_M80x60: 595226633Sdim case SW_VGA_C90x25: case SW_VGA_M90x25: 596193323Sed case SW_VGA_C90x30: case SW_VGA_M90x30: 597193323Sed case SW_VGA_C90x43: case SW_VGA_M90x43: 598234353Sdim case SW_VGA_C90x50: case SW_VGA_M90x50: 599226633Sdim case SW_VGA_C90x60: case SW_VGA_M90x60: 600226633Sdim case SW_B40x25: case SW_C40x25: 601226633Sdim case SW_B80x25: case SW_C80x25: 602226633Sdim case SW_ENH_B40x25: case SW_ENH_C40x25: 603226633Sdim case SW_ENH_B80x25: case SW_ENH_C80x25: 604226633Sdim case SW_ENH_B80x43: case SW_ENH_C80x43: 605226633Sdim case SW_EGAMONO80x25: 606226633Sdim 607226633Sdim#ifdef PC98 608226633Sdim /* PC98 TEXT MODES */ 609226633Sdim case SW_PC98_80x25: 610226633Sdim case SW_PC98_80x30: 611226633Sdim#endif 612226633Sdim if (!(adp->va_flags & V_ADP_MODECHANGE)) 613226633Sdim return ENODEV; 614226633Sdim return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0); 615226633Sdim 616226633Sdim /* GRAPHICS MODES */ 617226633Sdim case SW_BG320: case SW_BG640: 618226633Sdim case SW_CG320: case SW_CG320_D: case SW_CG640_E: 619226633Sdim case SW_CG640x350: case SW_ENH_CG640: 620226633Sdim case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320: 621226633Sdim case SW_VGA_MODEX: 622234353Sdim#ifdef PC98 623234353Sdim /* PC98 GRAPHICS MODES */ 624234353Sdim case SW_PC98_EGC640x400: case SW_PC98_PEGC640x400: 625234353Sdim case SW_PC98_PEGC640x480: 626226633Sdim#endif 627226633Sdim if (!(adp->va_flags & V_ADP_MODECHANGE)) 628226633Sdim return ENODEV; 629226633Sdim return sc_set_graphics_mode(scp, tp, cmd & 0xff); 630226633Sdim#endif /* SC_NO_MODE_CHANGE */ 631226633Sdim 632226633Sdim case KDSETMODE: /* set current mode of this (virtual) console */ 633226633Sdim switch (*(int *)data) { 634226633Sdim case KD_TEXT: /* switch to TEXT (known) mode */ 635226633Sdim /* 636226633Sdim * If scp->mode is of graphics modes, we don't know which 637226633Sdim * text mode to switch back to... 638226633Sdim */ 639226633Sdim if (scp->status & GRAPHICS_MODE) 640226633Sdim return EINVAL; 641226633Sdim /* restore fonts & palette ! */ 642226633Sdim#if 0 643226633Sdim#ifndef SC_NO_FONT_LOADING 644226633Sdim if (ISFONTAVAIL(adp->va_flags) 645226633Sdim && !(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 646226633Sdim /* 647226633Sdim * FONT KLUDGE 648226633Sdim * Don't load fonts for now... XXX 649226633Sdim */ 650226633Sdim if (scp->sc->fonts_loaded & FONT_8) 651226633Sdim sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256); 652226633Sdim if (scp->sc->fonts_loaded & FONT_14) 653226633Sdim sc_load_font(scp, 0, 14, scp->sc->font_14, 0, 256); 654226633Sdim if (scp->sc->fonts_loaded & FONT_16) 655226633Sdim sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256); 656226633Sdim } 657226633Sdim#endif /* SC_NO_FONT_LOADING */ 658226633Sdim#endif 659226633Sdim 660226633Sdim#ifndef SC_NO_PALETTE_LOADING 661226633Sdim load_palette(adp, scp->sc->palette); 662226633Sdim#endif 663226633Sdim 664226633Sdim#ifndef PC98 665226633Sdim /* move hardware cursor out of the way */ 666226633Sdim (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1); 667226633Sdim#endif 668226633Sdim 669226633Sdim /* FALL THROUGH */ 670226633Sdim 671226633Sdim case KD_TEXT1: /* switch to TEXT (known) mode */ 672226633Sdim /* 673226633Sdim * If scp->mode is of graphics modes, we don't know which 674226633Sdim * text/pixel mode to switch back to... 675226633Sdim */ 676226633Sdim if (scp->status & GRAPHICS_MODE) 677226633Sdim return EINVAL; 678226633Sdim s = spltty(); 679226633Sdim if ((error = sc_clean_up(scp))) { 680226633Sdim splx(s); 681226633Sdim return error; 682226633Sdim } 683226633Sdim#ifndef PC98 684226633Sdim scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 685226633Sdim splx(s); 686226633Sdim /* no restore fonts & palette */ 687226633Sdim if (scp == scp->sc->cur_scp) 688226633Sdim set_mode(scp); 689226633Sdim sc_clear_screen(scp); 690226633Sdim scp->status &= ~UNKNOWN_MODE; 691226633Sdim#else /* PC98 */ 692226633Sdim scp->status &= ~UNKNOWN_MODE; 693226633Sdim /* no restore fonts & palette */ 694226633Sdim if (scp == scp->sc->cur_scp) 695226633Sdim set_mode(scp); 696226633Sdim sc_clear_screen(scp); 697226633Sdim splx(s); 698226633Sdim#endif /* PC98 */ 699239462Sdim return 0; 700239462Sdim 701239462Sdim#ifdef SC_PIXEL_MODE 702239462Sdim case KD_PIXEL: /* pixel (raster) display */ 703239462Sdim if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE))) 704239462Sdim return EINVAL; 705226633Sdim if (scp->status & GRAPHICS_MODE) 706226633Sdim return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize, 707226633Sdim scp->font_size); 708226633Sdim s = spltty(); 709226633Sdim if ((error = sc_clean_up(scp))) { 710226633Sdim splx(s); 711226633Sdim return error; 712226633Sdim } 713234353Sdim scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); 714226633Sdim splx(s); 715226633Sdim if (scp == scp->sc->cur_scp) { 716226633Sdim set_mode(scp); 717226633Sdim#ifndef SC_NO_PALETTE_LOADING 718226633Sdim load_palette(adp, scp->sc->palette); 719226633Sdim#endif 720226633Sdim } 721226633Sdim sc_clear_screen(scp); 722226633Sdim scp->status &= ~UNKNOWN_MODE; 723226633Sdim return 0; 724226633Sdim#endif /* SC_PIXEL_MODE */ 725226633Sdim 726234353Sdim case KD_GRAPHICS: /* switch to GRAPHICS (unknown) mode */ 727226633Sdim s = spltty(); 728226633Sdim if ((error = sc_clean_up(scp))) { 729226633Sdim splx(s); 730226633Sdim return error; 731226633Sdim } 732226633Sdim scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN; 733234353Sdim splx(s); 734234353Sdim#ifdef PC98 735226633Sdim if (scp == scp->sc->cur_scp) 736234353Sdim set_mode(scp); 737226633Sdim#endif 738226633Sdim return 0; 739226633Sdim 740226633Sdim default: 741234353Sdim return EINVAL; 742226633Sdim } 743226633Sdim /* NOT REACHED */ 744234353Sdim 745226633Sdim#ifdef SC_PIXEL_MODE 746226633Sdim case KDRASTER: /* set pixel (raster) display mode */ 747226633Sdim if (ISUNKNOWNSC(scp) || ISTEXTSC(scp)) 748234353Sdim return ENODEV; 749226633Sdim return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1], 750234353Sdim ((int *)data)[2]); 751234353Sdim#endif /* SC_PIXEL_MODE */ 752234353Sdim 753234353Sdim case KDGETMODE: /* get current mode of this (virtual) console */ 754234353Sdim /* 755234353Sdim * From the user program's point of view, KD_PIXEL is the same 756226633Sdim * as KD_TEXT... 757234353Sdim */ 758226633Sdim *data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT; 759226633Sdim return 0; 760226633Sdim 761226633Sdim case KDSBORDER: /* set border color of this (virtual) console */ 762226633Sdim scp->border = *data; 763249423Sdim if (scp == scp->sc->cur_scp) 764249423Sdim sc_set_border(scp, scp->border); 765249423Sdim return 0; 766249423Sdim } 767249423Sdim 768249423Sdim return ENOIOCTL; 769249423Sdim} 770249423Sdim 771226633Sdimstatic LIST_HEAD(, sc_renderer) sc_rndr_list = 772234353Sdim LIST_HEAD_INITIALIZER(sc_rndr_list); 773226633Sdim 774226633Sdimint 775226633Sdimsc_render_add(sc_renderer_t *rndr) 776226633Sdim{ 777226633Sdim LIST_INSERT_HEAD(&sc_rndr_list, rndr, link); 778226633Sdim return 0; 779226633Sdim} 780234353Sdim 781234353Sdimint 782234353Sdimsc_render_remove(sc_renderer_t *rndr) 783234353Sdim{ 784226633Sdim /* 785226633Sdim LIST_REMOVE(rndr, link); 786226633Sdim */ 787226633Sdim return EBUSY; /* XXX */ 788226633Sdim} 789226633Sdim 790226633Sdimsc_rndr_sw_t 791226633Sdim*sc_render_match(scr_stat *scp, char *name, int mode) 792226633Sdim{ 793226633Sdim const sc_renderer_t **list; 794226633Sdim const sc_renderer_t *p; 795226633Sdim 796226633Sdim if (!LIST_EMPTY(&sc_rndr_list)) { 797226633Sdim LIST_FOREACH(p, &sc_rndr_list, link) { 798226633Sdim if ((strcmp(p->name, name) == 0) 799226633Sdim && (mode == p->mode)) { 800226633Sdim scp->status &= 801226633Sdim ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 802226633Sdim return p->rndrsw; 803226633Sdim } 804226633Sdim } 805226633Sdim } else { 806226633Sdim list = (const sc_renderer_t **)scrndr_set.ls_items; 807226633Sdim while ((p = *list++) != NULL) { 808226633Sdim if ((strcmp(p->name, name) == 0) 809226633Sdim && (mode == p->mode)) { 810226633Sdim scp->status &= 811226633Sdim ~(VR_CURSOR_ON | VR_CURSOR_BLINK); 812226633Sdim return p->rndrsw; 813226633Sdim } 814226633Sdim } 815226633Sdim } 816226633Sdim 817226633Sdim return NULL; 818193323Sed} 819226633Sdim