139287Ssos/*-
239643Syokota * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
339287Ssos * All rights reserved.
439287Ssos *
5146736Sdelphij * This code is derived from software contributed to The DragonFly Project
6146736Sdelphij * by Sascha Wildner <saw@online.de>
7146736Sdelphij *
839287Ssos * Redistribution and use in source and binary forms, with or without
939287Ssos * modification, are permitted provided that the following conditions
1039287Ssos * are met:
1139287Ssos * 1. Redistributions of source code must retain the above copyright
1239643Syokota *    notice, this list of conditions and the following disclaimer as
1339643Syokota *    the first lines of this file unmodified.
1439287Ssos * 2. Redistributions in binary form must reproduce the above copyright
1539287Ssos *    notice, this list of conditions and the following disclaimer in the
1639287Ssos *    documentation and/or other materials provided with the distribution.
1739287Ssos *
1839643Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1939643Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2039643Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2139643Syokota * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2239643Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2339643Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2439643Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2539643Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2639643Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2739643Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2839287Ssos */
2939287Ssos
30119420Sobrien#include <sys/cdefs.h>
31119420Sobrien__FBSDID("$FreeBSD$");
32119420Sobrien
33162711Sru#include "opt_compat.h"
3439287Ssos#include "opt_syscons.h"
3539287Ssos
3639287Ssos#include <sys/param.h>
3739287Ssos#include <sys/systm.h>
3851404Syokota#include <sys/conf.h>
3939287Ssos#include <sys/signalvar.h>
4039287Ssos#include <sys/tty.h>
4139287Ssos#include <sys/kernel.h>
4266834Sphk#include <sys/fbio.h>
4366834Sphk#include <sys/consio.h>
4491140Stanimura#include <sys/filedesc.h>
4591140Stanimura#include <sys/lock.h>
4691140Stanimura#include <sys/sx.h>
4791140Stanimura#include <sys/mutex.h>
4891140Stanimura#include <sys/proc.h>
4939287Ssos
5042504Syokota#include <dev/fb/fbreg.h>
5142504Syokota#include <dev/syscons/syscons.h>
5239287Ssos
5378161SpeterSET_DECLARE(scrndr_set, const sc_renderer_t);
5478161Speter
5542504Syokota/* for compatibility with previous versions */
5648104Syokota/* 3.0-RELEASE used the following structure */
5742504Syokotatypedef struct old_video_adapter {
5842504Syokota    int			va_index;
5942504Syokota    int			va_type;
6042504Syokota    int			va_flags;
6148104Syokota/* flag bits are the same as the -CURRENT
6242504Syokota#define V_ADP_COLOR	(1<<0)
6342504Syokota#define V_ADP_MODECHANGE (1<<1)
6442504Syokota#define V_ADP_STATESAVE	(1<<2)
6542504Syokota#define V_ADP_STATELOAD	(1<<3)
6642504Syokota#define V_ADP_FONT	(1<<4)
6742504Syokota#define V_ADP_PALETTE	(1<<5)
6842504Syokota#define V_ADP_BORDER	(1<<6)
6942504Syokota#define V_ADP_VESA	(1<<7)
7048104Syokota*/
7142504Syokota    int			va_crtc_addr;
7242504Syokota    u_int		va_window;	/* virtual address */
7342504Syokota    size_t		va_window_size;
7442504Syokota    size_t		va_window_gran;
7542504Syokota    u_int		va_buffer;	/* virtual address */
7642504Syokota    size_t		va_buffer_size;
7742504Syokota    int			va_initial_mode;
7842504Syokota    int			va_initial_bios_mode;
7942504Syokota    int			va_mode;
8042504Syokota} old_video_adapter_t;
8139287Ssos
8242504Syokota#define OLD_CONS_ADPINFO _IOWR('c', 101, old_video_adapter_t)
8342504Syokota
8448104Syokota/* 3.1-RELEASE used the following structure */
8548104Syokotatypedef struct old_video_adapter_info {
8648104Syokota    int			va_index;
8748104Syokota    int			va_type;
8848104Syokota    char		va_name[16];
8948104Syokota    int			va_unit;
9048104Syokota    int			va_flags;
9148104Syokota    int			va_io_base;
9248104Syokota    int			va_io_size;
9348104Syokota    int			va_crtc_addr;
9448104Syokota    int			va_mem_base;
9548104Syokota    int			va_mem_size;
9648104Syokota    u_int		va_window;	/* virtual address */
9748104Syokota    size_t		va_window_size;
9848104Syokota    size_t		va_window_gran;
99132107Sstefanf    u_int		va_buffer;
10048104Syokota    size_t		va_buffer_size;
10148104Syokota    int			va_initial_mode;
10248104Syokota    int			va_initial_bios_mode;
10348104Syokota    int			va_mode;
10448104Syokota    int			va_line_width;
10548104Syokota} old_video_adapter_info_t;
10639287Ssos
10748104Syokota#define OLD_CONS_ADPINFO2 _IOWR('c', 101, old_video_adapter_info_t)
10848104Syokota
10948104Syokota/* 3.0-RELEASE and 3.1-RELEASE used the following structure */
11048104Syokotatypedef struct old_video_info {
11148104Syokota    int			vi_mode;
11248104Syokota    int			vi_flags;
11348104Syokota/* flag bits are the same as the -CURRENT
11448104Syokota#define V_INFO_COLOR	(1<<0)
11548104Syokota#define V_INFO_GRAPHICS	(1<<1)
11648104Syokota#define V_INFO_LINEAR	(1<<2)
11748104Syokota#define V_INFO_VESA	(1<<3)
11848104Syokota*/
11948104Syokota    int			vi_width;
12048104Syokota    int			vi_height;
12148104Syokota    int			vi_cwidth;
12248104Syokota    int			vi_cheight;
12348104Syokota    int			vi_depth;
12448104Syokota    int			vi_planes;
12548104Syokota    u_int		vi_window;	/* physical address */
12648104Syokota    size_t		vi_window_size;
12748104Syokota    size_t		vi_window_gran;
12848104Syokota    u_int		vi_buffer;	/* physical address */
12948104Syokota    size_t		vi_buffer_size;
13048104Syokota} old_video_info_t;
13148104Syokota
13248104Syokota#define OLD_CONS_MODEINFO _IOWR('c', 102, old_video_info_t)
13348104Syokota#define OLD_CONS_FINDMODE _IOWR('c', 103, old_video_info_t)
13448104Syokota
13539287Ssosint
13639287Ssossc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
137149640Srodrigc		 int fontsize, int fontwidth)
13839287Ssos{
13939287Ssos    video_info_t info;
140242529Sed    struct winsize wsz;
14148104Syokota    u_char *font;
14248667Syokota    int prev_ysize;
14339287Ssos    int error;
14439287Ssos    int s;
14539287Ssos
146174985Swkoszek    if (vidd_get_info(scp->sc->adp, mode, &info))
14739287Ssos	return ENODEV;
14848104Syokota
14939287Ssos    /* adjust argument values */
150149828Srodrigc    if (fontwidth <= 0)
151149828Srodrigc	fontwidth = info.vi_cwidth;
15239287Ssos    if (fontsize <= 0)
15339287Ssos	fontsize = info.vi_cheight;
154216079Sjkim    if (fontsize < 14)
15539287Ssos	fontsize = 8;
156216079Sjkim    else if (fontsize >= 16)
15739287Ssos	fontsize = 16;
158216079Sjkim    else
15939287Ssos	fontsize = 14;
16048104Syokota#ifndef SC_NO_FONT_LOADING
161216079Sjkim    switch (fontsize) {
162216079Sjkim    case 8:
163216079Sjkim	if ((scp->sc->fonts_loaded & FONT_8) == 0)
164216079Sjkim	    return (EINVAL);
165216079Sjkim	font = scp->sc->font_8;
166216079Sjkim	break;
167216079Sjkim    case 14:
168216079Sjkim	if ((scp->sc->fonts_loaded & FONT_14) == 0)
169216079Sjkim	    return (EINVAL);
17048104Syokota	font = scp->sc->font_14;
171216079Sjkim	break;
172216079Sjkim    case 16:
173216079Sjkim	if ((scp->sc->fonts_loaded & FONT_16) == 0)
174216079Sjkim	    return (EINVAL);
175216079Sjkim	font = scp->sc->font_16;
176216079Sjkim	break;
177216079Sjkim    }
17848104Syokota#else
179216079Sjkim    font = NULL;
18048104Syokota#endif
18139287Ssos    if ((xsize <= 0) || (xsize > info.vi_width))
18239287Ssos	xsize = info.vi_width;
18339287Ssos    if ((ysize <= 0) || (ysize > info.vi_height))
18439287Ssos	ysize = info.vi_height;
18539287Ssos
18639287Ssos    /* stop screen saver, etc */
18739287Ssos    s = spltty();
18839287Ssos    if ((error = sc_clean_up(scp))) {
18939287Ssos	splx(s);
19039287Ssos	return error;
19139287Ssos    }
19239287Ssos
19356043Syokota    if (sc_render_match(scp, scp->sc->adp->va_name, 0) == NULL) {
19448104Syokota	splx(s);
19548104Syokota	return ENODEV;
19648104Syokota    }
19748104Syokota
19839287Ssos    /* set up scp */
19951394Syokota#ifndef SC_NO_HISTORY
20051394Syokota    if (scp->history != NULL)
20151394Syokota	sc_hist_save(scp);
20251394Syokota#endif
20348667Syokota    prev_ysize = scp->ysize;
20439287Ssos    /*
20539287Ssos     * This is a kludge to fend off scrn_update() while we
20639287Ssos     * muck around with scp. XXX
20739287Ssos     */
20858872Syokota    scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
20958872Syokota    scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE);
21039287Ssos    scp->mode = mode;
21139287Ssos    scp->xsize = xsize;
21239287Ssos    scp->ysize = ysize;
21342504Syokota    scp->xoff = 0;
21442504Syokota    scp->yoff = 0;
21539287Ssos    scp->xpixel = scp->xsize*8;
21639287Ssos    scp->ypixel = scp->ysize*fontsize;
21748104Syokota    scp->font = font;
21848104Syokota    scp->font_size = fontsize;
219149640Srodrigc    scp->font_width = fontwidth;
22039287Ssos
22139287Ssos    /* allocate buffers */
22239287Ssos    sc_alloc_scr_buffer(scp, TRUE, TRUE);
22356043Syokota    sc_init_emulator(scp, NULL);
22448104Syokota#ifndef SC_NO_CUTPASTE
22548104Syokota    sc_alloc_cut_buffer(scp, FALSE);
22648104Syokota#endif
22748104Syokota#ifndef SC_NO_HISTORY
22848667Syokota    sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE);
22948104Syokota#endif
23039287Ssos    splx(s);
23139287Ssos
23248104Syokota    if (scp == scp->sc->cur_scp)
23339287Ssos	set_mode(scp);
23439287Ssos    scp->status &= ~UNKNOWN_MODE;
23539287Ssos
23639287Ssos    if (tp == NULL)
23739287Ssos	return 0;
238242529Sed    wsz.ws_col = scp->xsize;
239242529Sed    wsz.ws_row = scp->ysize;
240242529Sed    tty_set_winsize(tp, &wsz);
24139287Ssos    return 0;
24239287Ssos}
24339287Ssos
24439287Ssosint
24539287Ssossc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
24639287Ssos{
24748104Syokota#ifdef SC_NO_MODE_CHANGE
24848104Syokota    return ENODEV;
24948104Syokota#else
25039287Ssos    video_info_t info;
251242529Sed    struct winsize wsz;
25239287Ssos    int error;
25339287Ssos    int s;
25439287Ssos
255174985Swkoszek    if (vidd_get_info(scp->sc->adp, mode, &info))
25639287Ssos	return ENODEV;
25739287Ssos
25839287Ssos    /* stop screen saver, etc */
25939287Ssos    s = spltty();
26039287Ssos    if ((error = sc_clean_up(scp))) {
26139287Ssos	splx(s);
26239287Ssos	return error;
26339287Ssos    }
26439287Ssos
26556043Syokota    if (sc_render_match(scp, scp->sc->adp->va_name, GRAPHICS_MODE) == NULL) {
26648104Syokota	splx(s);
26748104Syokota	return ENODEV;
26848104Syokota    }
26948104Syokota
27039287Ssos    /* set up scp */
27158872Syokota    scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE | MOUSE_HIDDEN);
27258872Syokota    scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE);
27339287Ssos    scp->mode = mode;
27450447Syokota    /*
27550447Syokota     * Don't change xsize and ysize; preserve the previous vty
27650447Syokota     * and history buffers.
27750447Syokota     */
27842504Syokota    scp->xoff = 0;
27942504Syokota    scp->yoff = 0;
28039287Ssos    scp->xpixel = info.vi_width;
28139287Ssos    scp->ypixel = info.vi_height;
28248104Syokota    scp->font = NULL;
28356328Syokota    scp->font_size = 0;
28448104Syokota#ifndef SC_NO_SYSMOUSE
28539287Ssos    /* move the mouse cursor at the center of the screen */
28648104Syokota    sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
28748104Syokota#endif
28856043Syokota    sc_init_emulator(scp, NULL);
28939287Ssos    splx(s);
29039287Ssos
29148104Syokota    if (scp == scp->sc->cur_scp)
29239287Ssos	set_mode(scp);
29339287Ssos    /* clear_graphics();*/
29439287Ssos    scp->status &= ~UNKNOWN_MODE;
29539287Ssos
29639287Ssos    if (tp == NULL)
29739287Ssos	return 0;
298242529Sed    wsz.ws_col = scp->xsize;
299242529Sed    wsz.ws_row = scp->ysize;
300242529Sed    tty_set_winsize(tp, &wsz);
30139287Ssos    return 0;
30248104Syokota#endif /* SC_NO_MODE_CHANGE */
30339287Ssos}
30439287Ssos
30539287Ssosint
30639287Ssossc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
307149640Srodrigc		  int fontsize, int fontwidth)
30839287Ssos{
30948104Syokota#ifndef SC_PIXEL_MODE
31048104Syokota    return ENODEV;
31148104Syokota#else
31239287Ssos    video_info_t info;
313242529Sed    struct winsize wsz;
31448104Syokota    u_char *font;
31548667Syokota    int prev_ysize;
31639287Ssos    int error;
31739287Ssos    int s;
31839287Ssos
319174985Swkoszek    if (vidd_get_info(scp->sc->adp, scp->mode, &info))
32039287Ssos	return ENODEV;		/* this shouldn't happen */
32139287Ssos
32239287Ssos    /* adjust argument values */
32356328Syokota    if (fontsize <= 0)
32439287Ssos	fontsize = info.vi_cheight;
325216079Sjkim    if (fontsize < 14)
32639287Ssos	fontsize = 8;
327216079Sjkim    else if (fontsize >= 16)
32839287Ssos	fontsize = 16;
329216079Sjkim    else
33039287Ssos	fontsize = 14;
33148104Syokota#ifndef SC_NO_FONT_LOADING
332216079Sjkim    switch (fontsize) {
333216079Sjkim    case 8:
334216079Sjkim	if ((scp->sc->fonts_loaded & FONT_8) == 0)
335216079Sjkim	    return (EINVAL);
336216079Sjkim	font = scp->sc->font_8;
337216079Sjkim	break;
338216079Sjkim    case 14:
339216079Sjkim	if ((scp->sc->fonts_loaded & FONT_14) == 0)
340216079Sjkim	    return (EINVAL);
34148104Syokota	font = scp->sc->font_14;
342216079Sjkim	break;
343216079Sjkim    case 16:
344216079Sjkim	if ((scp->sc->fonts_loaded & FONT_16) == 0)
345216079Sjkim	    return (EINVAL);
346216079Sjkim	font = scp->sc->font_16;
347216079Sjkim	break;
348216079Sjkim    }
34948104Syokota#else
350216079Sjkim    font = NULL;
35148104Syokota#endif
35239287Ssos    if (xsize <= 0)
35339287Ssos	xsize = info.vi_width/8;
35439287Ssos    if (ysize <= 0)
35539287Ssos	ysize = info.vi_height/fontsize;
35639287Ssos
35739591Syokota    if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize))
35839591Syokota	return EINVAL;
35939591Syokota
360204281Sjkim    if (!sc_support_pixel_mode(&info))
36139591Syokota	return ENODEV;
36239591Syokota
36339287Ssos    /* stop screen saver, etc */
36439287Ssos    s = spltty();
36539287Ssos    if ((error = sc_clean_up(scp))) {
36639287Ssos	splx(s);
36739287Ssos	return error;
36839287Ssos    }
36939287Ssos
37056043Syokota    if (sc_render_match(scp, scp->sc->adp->va_name, PIXEL_MODE) == NULL) {
37148104Syokota	splx(s);
37248104Syokota	return ENODEV;
37348104Syokota    }
37448104Syokota
37556043Syokota#if 0
37656043Syokota    if (scp->tsw)
37756043Syokota	(*scp->tsw->te_term)(scp, scp->ts);
37856043Syokota    scp->tsw = NULL;
37956043Syokota    scp->ts = NULL;
38056043Syokota#endif
38156043Syokota
38239287Ssos    /* set up scp */
38351394Syokota#ifndef SC_NO_HISTORY
38451394Syokota    if (scp->history != NULL)
38551394Syokota	sc_hist_save(scp);
38651394Syokota#endif
38748667Syokota    prev_ysize = scp->ysize;
38858872Syokota    scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN);
38958872Syokota    scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE);
39039287Ssos    scp->xsize = xsize;
39139287Ssos    scp->ysize = ysize;
39239287Ssos    scp->xoff = (scp->xpixel/8 - xsize)/2;
39339287Ssos    scp->yoff = (scp->ypixel/fontsize - ysize)/2;
39448104Syokota    scp->font = font;
39548104Syokota    scp->font_size = fontsize;
396149640Srodrigc    scp->font_width = fontwidth;
39739287Ssos
39839287Ssos    /* allocate buffers */
39939287Ssos    sc_alloc_scr_buffer(scp, TRUE, TRUE);
40056043Syokota    sc_init_emulator(scp, NULL);
40148104Syokota#ifndef SC_NO_CUTPASTE
40248104Syokota    sc_alloc_cut_buffer(scp, FALSE);
40348104Syokota#endif
40448104Syokota#ifndef SC_NO_HISTORY
40548667Syokota    sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE);
40648104Syokota#endif
40739287Ssos    splx(s);
40839287Ssos
40948104Syokota    if (scp == scp->sc->cur_scp) {
41056043Syokota	sc_set_border(scp, scp->border);
41148104Syokota	sc_set_cursor_image(scp);
41248104Syokota    }
41339287Ssos
41439287Ssos    scp->status &= ~UNKNOWN_MODE;
41539287Ssos
41639287Ssos    if (tp == NULL)
41739287Ssos	return 0;
418242529Sed    wsz.ws_col = scp->xsize;
419242529Sed    wsz.ws_row = scp->ysize;
420242529Sed    tty_set_winsize(tp, &wsz);
42139287Ssos    return 0;
42248104Syokota#endif /* SC_PIXEL_MODE */
42339287Ssos}
42439287Ssos
425204281Sjkimint
426204281Sjkimsc_support_pixel_mode(void *arg)
427204281Sjkim{
428204281Sjkim#ifdef SC_PIXEL_MODE
429204281Sjkim	video_info_t *info = arg;
430204281Sjkim
431204281Sjkim	if ((info->vi_flags & V_INFO_GRAPHICS) == 0)
432204281Sjkim		return (0);
433204281Sjkim
434204281Sjkim	/*
435204281Sjkim	 * We currently support the following graphic modes:
436204281Sjkim	 *
437204281Sjkim	 * - 4 bpp planar modes whose memory size does not exceed 64K
438204281Sjkim	 * - 15, 16, 24 and 32 bpp linear modes
439204281Sjkim	 */
440204281Sjkim	switch (info->vi_mem_model) {
441204281Sjkim	case V_INFO_MM_PLANAR:
442204281Sjkim		if (info->vi_planes != 4)
443204281Sjkim			break;
444204281Sjkim		/*
445204281Sjkim		 * A memory size >64K requires bank switching to access
446204281Sjkim		 * the entire screen. XXX
447204281Sjkim		 */
448204281Sjkim		if (info->vi_width * info->vi_height / 8 > info->vi_window_size)
449204281Sjkim			break;
450204281Sjkim		return (1);
451204281Sjkim	case V_INFO_MM_DIRECT:
452204281Sjkim		if ((info->vi_flags & V_INFO_LINEAR) == 0 &&
453204281Sjkim		    info->vi_depth != 15 && info->vi_depth != 16 &&
454204281Sjkim		    info->vi_depth != 24 && info->vi_depth != 32)
455204281Sjkim			break;
456204281Sjkim		return (1);
457204281Sjkim	case V_INFO_MM_PACKED:
458204281Sjkim		if ((info->vi_flags & V_INFO_LINEAR) == 0 &&
459204281Sjkim		    info->vi_depth != 8)
460204281Sjkim			break;
461204281Sjkim		return (1);
462204281Sjkim	}
463204281Sjkim#endif
464204281Sjkim	return (0);
465204281Sjkim}
466204281Sjkim
46748104Syokota#define fb_ioctl(a, c, d)		\
46848104Syokota	(((a) == NULL) ? ENODEV : 	\
469174985Swkoszek			 vidd_ioctl((a), (c), (caddr_t)(d)))
47048104Syokota
47139287Ssosint
472181905Sedsc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
47339287Ssos{
47439287Ssos    scr_stat *scp;
47548104Syokota    video_adapter_t *adp;
47648104Syokota    video_info_t info;
47748104Syokota    video_adapter_info_t adp_info;
47839287Ssos    int error;
47939287Ssos    int s;
480162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
481162711Sru    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
482162711Sru    int ival;
483162711Sru#endif
48439287Ssos
485181905Sed    scp = SC_STAT(tp);
48648104Syokota    if (scp == NULL)		/* tp == SC_MOUSE */
48748104Syokota	return ENOIOCTL;
48848104Syokota    adp = scp->sc->adp;
48948104Syokota    if (adp == NULL)		/* shouldn't happen??? */
49048104Syokota	return ENODEV;
49139287Ssos
49239287Ssos    switch (cmd) {
49339287Ssos
49448104Syokota    case CONS_CURRENTADP:	/* get current adapter index */
49548104Syokota    case FBIO_ADAPTER:
49648104Syokota	return fb_ioctl(adp, FBIO_ADAPTER, data);
49748104Syokota
49839287Ssos    case CONS_CURRENT:  	/* get current adapter type */
49948104Syokota    case FBIO_ADPTYPE:
50048104Syokota	return fb_ioctl(adp, FBIO_ADPTYPE, data);
50139287Ssos
50248104Syokota    case OLD_CONS_ADPINFO:	/* adapter information (old interface) */
50348104Syokota	if (((old_video_adapter_t *)data)->va_index >= 0) {
50448104Syokota	    adp = vid_get_adapter(((old_video_adapter_t *)data)->va_index);
50548104Syokota	    if (adp == NULL)
50648104Syokota		return ENODEV;
50748104Syokota	}
50848104Syokota	((old_video_adapter_t *)data)->va_index = adp->va_index;
50948104Syokota	((old_video_adapter_t *)data)->va_type = adp->va_type;
51048104Syokota	((old_video_adapter_t *)data)->va_flags = adp->va_flags;
51148104Syokota	((old_video_adapter_t *)data)->va_crtc_addr = adp->va_crtc_addr;
51248104Syokota	((old_video_adapter_t *)data)->va_window = adp->va_window;
51348104Syokota	((old_video_adapter_t *)data)->va_window_size = adp->va_window_size;
51448104Syokota	((old_video_adapter_t *)data)->va_window_gran = adp->va_window_gran;
51548104Syokota	((old_video_adapter_t *)data)->va_buffer = adp->va_buffer;
51648104Syokota	((old_video_adapter_t *)data)->va_buffer_size = adp->va_buffer_size;
51748104Syokota	((old_video_adapter_t *)data)->va_mode = adp->va_mode;
51848104Syokota	((old_video_adapter_t *)data)->va_initial_mode = adp->va_initial_mode;
51942504Syokota	((old_video_adapter_t *)data)->va_initial_bios_mode
52048104Syokota	    = adp->va_initial_bios_mode;
52142504Syokota	return 0;
52242504Syokota
52348104Syokota    case OLD_CONS_ADPINFO2:	/* adapter information (yet another old I/F) */
52448104Syokota	adp_info.va_index = ((old_video_adapter_info_t *)data)->va_index;
52548104Syokota	if (adp_info.va_index >= 0) {
52648104Syokota	    adp = vid_get_adapter(adp_info.va_index);
52748104Syokota	    if (adp == NULL)
52848104Syokota		return ENODEV;
52948104Syokota	}
53048104Syokota	error = fb_ioctl(adp, FBIO_ADPINFO, &adp_info);
53148104Syokota	if (error == 0)
53248104Syokota	    bcopy(&adp_info, data, sizeof(old_video_adapter_info_t));
53348104Syokota	return error;
53448104Syokota
53539287Ssos    case CONS_ADPINFO:		/* adapter information */
53648104Syokota    case FBIO_ADPINFO:
53748104Syokota	if (((video_adapter_info_t *)data)->va_index >= 0) {
53848104Syokota	    adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index);
53948104Syokota	    if (adp == NULL)
54048104Syokota		return ENODEV;
54148104Syokota	}
54248104Syokota	return fb_ioctl(adp, FBIO_ADPINFO, data);
54339287Ssos
54439287Ssos    case CONS_GET:      	/* get current video mode */
54548104Syokota    case FBIO_GETMODE:
54639287Ssos	*(int *)data = scp->mode;
54739287Ssos	return 0;
54839287Ssos
54948104Syokota#ifndef SC_NO_MODE_CHANGE
55048104Syokota    case FBIO_SETMODE:		/* set video mode */
55148104Syokota	if (!(adp->va_flags & V_ADP_MODECHANGE))
55248104Syokota 	    return ENODEV;
55348104Syokota	info.vi_mode = *(int *)data;
55448104Syokota	error = fb_ioctl(adp, FBIO_MODEINFO, &info);
55548104Syokota	if (error)
55648104Syokota	    return error;
55748104Syokota	if (info.vi_flags & V_INFO_GRAPHICS)
55848104Syokota	    return sc_set_graphics_mode(scp, tp, *(int *)data);
55948104Syokota	else
560149640Srodrigc	    return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0, 0);
56148104Syokota#endif /* SC_NO_MODE_CHANGE */
56248104Syokota
56348104Syokota    case OLD_CONS_MODEINFO:	/* get mode information (old infterface) */
56448104Syokota	info.vi_mode = ((old_video_info_t *)data)->vi_mode;
56548104Syokota	error = fb_ioctl(adp, FBIO_MODEINFO, &info);
56648104Syokota	if (error == 0)
56748104Syokota	    bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t));
56848104Syokota	return error;
56948104Syokota
57039287Ssos    case CONS_MODEINFO:		/* get mode information */
57148104Syokota    case FBIO_MODEINFO:
57248104Syokota	return fb_ioctl(adp, FBIO_MODEINFO, data);
57339287Ssos
57448104Syokota    case OLD_CONS_FINDMODE:	/* find a matching video mode (old interface) */
57548104Syokota	bzero(&info, sizeof(info));
57648104Syokota	bcopy((old_video_info_t *)data, &info, sizeof(old_video_info_t));
57748104Syokota	error = fb_ioctl(adp, FBIO_FINDMODE, &info);
57848104Syokota	if (error == 0)
57948104Syokota	    bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t));
58048104Syokota	return error;
58148104Syokota
58239287Ssos    case CONS_FINDMODE:		/* find a matching video mode */
58348104Syokota    case FBIO_FINDMODE:
58448104Syokota	return fb_ioctl(adp, FBIO_FINDMODE, data);
58539287Ssos
586162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
587162711Sru    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
588162711Sru    case _IO('c', 104):
589162711Sru	ival = IOCPARM_IVAL(data);
590162711Sru	data = (caddr_t)&ival;
591162711Sru	/* FALLTHROUGH */
592162711Sru#endif
59348104Syokota    case CONS_SETWINORG:	/* set frame buffer window origin */
59448104Syokota    case FBIO_SETWINORG:
59548104Syokota	if (scp != scp->sc->cur_scp)
59648104Syokota	    return ENODEV;	/* XXX */
59748104Syokota	return fb_ioctl(adp, FBIO_SETWINORG, data);
59839287Ssos
59948104Syokota    case FBIO_GETWINORG:	/* get frame buffer window origin */
60048104Syokota	if (scp != scp->sc->cur_scp)
60148104Syokota	    return ENODEV;	/* XXX */
60248104Syokota	return fb_ioctl(adp, FBIO_GETWINORG, data);
60348104Syokota
60448104Syokota    case FBIO_GETDISPSTART:
60548104Syokota    case FBIO_SETDISPSTART:
60648104Syokota    case FBIO_GETLINEWIDTH:
60748104Syokota    case FBIO_SETLINEWIDTH:
60848104Syokota	if (scp != scp->sc->cur_scp)
60948104Syokota	    return ENODEV;	/* XXX */
61048104Syokota	return fb_ioctl(adp, cmd, data);
61148104Syokota
61248104Syokota    case FBIO_GETPALETTE:
61348104Syokota    case FBIO_SETPALETTE:
61448104Syokota    case FBIOPUTCMAP:
61548104Syokota    case FBIOGETCMAP:
61648104Syokota    case FBIOGTYPE:
61748104Syokota    case FBIOGATTR:
61848104Syokota    case FBIOSVIDEO:
61948104Syokota    case FBIOGVIDEO:
62048104Syokota    case FBIOSCURSOR:
62148104Syokota    case FBIOGCURSOR:
62248104Syokota    case FBIOSCURPOS:
62348104Syokota    case FBIOGCURPOS:
62448104Syokota    case FBIOGCURMAX:
62548104Syokota	if (scp != scp->sc->cur_scp)
62648104Syokota	    return ENODEV;	/* XXX */
62748104Syokota	return fb_ioctl(adp, cmd, data);
62848104Syokota
62981039Syokota    case FBIO_BLANK:
63081039Syokota	if (scp != scp->sc->cur_scp)
63181039Syokota	    return ENODEV;	/* XXX */
63281039Syokota	return fb_ioctl(adp, cmd, data);
63381039Syokota
63448104Syokota#ifndef SC_NO_MODE_CHANGE
63539591Syokota    /* generic text modes */
63639591Syokota    case SW_TEXT_80x25:	case SW_TEXT_80x30:
63739591Syokota    case SW_TEXT_80x43: case SW_TEXT_80x50:
63839591Syokota    case SW_TEXT_80x60:
639102412Scharnier	/* FALLTHROUGH */
64039591Syokota
64139287Ssos    /* VGA TEXT MODES */
64239287Ssos    case SW_VGA_C40x25:
64339287Ssos    case SW_VGA_C80x25: case SW_VGA_M80x25:
64439287Ssos    case SW_VGA_C80x30: case SW_VGA_M80x30:
64539287Ssos    case SW_VGA_C80x50: case SW_VGA_M80x50:
64639287Ssos    case SW_VGA_C80x60: case SW_VGA_M80x60:
64748104Syokota    case SW_VGA_C90x25: case SW_VGA_M90x25:
64848104Syokota    case SW_VGA_C90x30: case SW_VGA_M90x30:
64948104Syokota    case SW_VGA_C90x43: case SW_VGA_M90x43:
65048104Syokota    case SW_VGA_C90x50: case SW_VGA_M90x50:
65148104Syokota    case SW_VGA_C90x60: case SW_VGA_M90x60:
65239287Ssos    case SW_B40x25:     case SW_C40x25:
65339287Ssos    case SW_B80x25:     case SW_C80x25:
65439287Ssos    case SW_ENH_B40x25: case SW_ENH_C40x25:
65539287Ssos    case SW_ENH_B80x25: case SW_ENH_C80x25:
65639287Ssos    case SW_ENH_B80x43: case SW_ENH_C80x43:
65739287Ssos    case SW_EGAMONO80x25:
65842504Syokota
65942504Syokota#ifdef PC98
66042504Syokota    /* PC98 TEXT MODES */
66142504Syokota    case SW_PC98_80x25:
66242504Syokota    case SW_PC98_80x30:
66342504Syokota#endif
66448104Syokota	if (!(adp->va_flags & V_ADP_MODECHANGE))
66539287Ssos 	    return ENODEV;
666149640Srodrigc	return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0, 0);
66739287Ssos
66839287Ssos    /* GRAPHICS MODES */
66939287Ssos    case SW_BG320:     case SW_BG640:
67039287Ssos    case SW_CG320:     case SW_CG320_D:   case SW_CG640_E:
67139287Ssos    case SW_CG640x350: case SW_ENH_CG640:
67239287Ssos    case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:
67339287Ssos    case SW_VGA_MODEX:
67459689Snyan#ifdef PC98
67559689Snyan    /* PC98 GRAPHICS MODES */
67659689Snyan    case SW_PC98_EGC640x400:	case SW_PC98_PEGC640x400:
67759689Snyan    case SW_PC98_PEGC640x480:
67859689Snyan#endif
67948104Syokota	if (!(adp->va_flags & V_ADP_MODECHANGE))
68039287Ssos	    return ENODEV;
68139287Ssos	return sc_set_graphics_mode(scp, tp, cmd & 0xff);
68248104Syokota#endif /* SC_NO_MODE_CHANGE */
68339287Ssos
684162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
685162711Sru    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
686162711Sru    case _IO('K', 10):
687162711Sru	ival = IOCPARM_IVAL(data);
688162711Sru	data = (caddr_t)&ival;
689162711Sru	/* FALLTHROUGH */
690162711Sru#endif
69139287Ssos    case KDSETMODE:     	/* set current mode of this (virtual) console */
692162711Sru	switch (*(int *)data) {
69339287Ssos	case KD_TEXT:   	/* switch to TEXT (known) mode */
69439287Ssos	    /*
69539287Ssos	     * If scp->mode is of graphics modes, we don't know which
69639287Ssos	     * text mode to switch back to...
69739287Ssos	     */
69839287Ssos	    if (scp->status & GRAPHICS_MODE)
69939287Ssos		return EINVAL;
70039287Ssos	    /* restore fonts & palette ! */
70139287Ssos#if 0
70248104Syokota#ifndef SC_NO_FONT_LOADING
70348104Syokota	    if (ISFONTAVAIL(adp->va_flags)
70439287Ssos		&& !(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
70539287Ssos		/*
70639287Ssos		 * FONT KLUDGE
70739287Ssos		 * Don't load fonts for now... XXX
70839287Ssos		 */
70948104Syokota		if (scp->sc->fonts_loaded & FONT_8)
710150686Smarius		    sc_load_font(scp, 0, 8, 8, scp->sc->font_8, 0, 256);
71148104Syokota		if (scp->sc->fonts_loaded & FONT_14)
712150686Smarius		    sc_load_font(scp, 0, 14, 8, scp->sc->font_14, 0, 256);
71348104Syokota		if (scp->sc->fonts_loaded & FONT_16)
714150686Smarius		    sc_load_font(scp, 0, 16, 8, scp->sc->font_16, 0, 256);
71539287Ssos	    }
71648104Syokota#endif /* SC_NO_FONT_LOADING */
71739287Ssos#endif
71839287Ssos
71948104Syokota#ifndef SC_NO_PALETTE_LOADING
720204265Sjkim#ifdef SC_PIXEL_MODE
721205865Sjkim	    if (adp->va_info.vi_mem_model == V_INFO_MM_DIRECT)
722204265Sjkim		vidd_load_palette(adp, scp->sc->palette2);
723204265Sjkim	    else
724204265Sjkim#endif
725174985Swkoszek	    vidd_load_palette(adp, scp->sc->palette);
72648104Syokota#endif
72748104Syokota
72848104Syokota#ifndef PC98
72939287Ssos	    /* move hardware cursor out of the way */
730174985Swkoszek	    vidd_set_hw_cursor(adp, -1, -1);
73148104Syokota#endif
73239287Ssos
733102412Scharnier	    /* FALLTHROUGH */
73439287Ssos
73539287Ssos	case KD_TEXT1:  	/* switch to TEXT (known) mode */
73639287Ssos	    /*
73739287Ssos	     * If scp->mode is of graphics modes, we don't know which
73839287Ssos	     * text/pixel mode to switch back to...
73939287Ssos	     */
74039287Ssos	    if (scp->status & GRAPHICS_MODE)
74139287Ssos		return EINVAL;
74239287Ssos	    s = spltty();
74339287Ssos	    if ((error = sc_clean_up(scp))) {
74439287Ssos		splx(s);
74539287Ssos		return error;
74639287Ssos	    }
74742504Syokota#ifndef PC98
74858872Syokota	    scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
74939287Ssos	    splx(s);
75039287Ssos	    /* no restore fonts & palette */
75148104Syokota	    if (scp == scp->sc->cur_scp)
75239287Ssos		set_mode(scp);
75339287Ssos	    sc_clear_screen(scp);
75439287Ssos	    scp->status &= ~UNKNOWN_MODE;
75542504Syokota#else /* PC98 */
75642504Syokota	    scp->status &= ~UNKNOWN_MODE;
75742504Syokota	    /* no restore fonts & palette */
75848104Syokota	    if (scp == scp->sc->cur_scp)
75942504Syokota		set_mode(scp);
76042504Syokota	    sc_clear_screen(scp);
76142504Syokota	    splx(s);
76242504Syokota#endif /* PC98 */
76339287Ssos	    return 0;
76439287Ssos
76548104Syokota#ifdef SC_PIXEL_MODE
76639287Ssos	case KD_PIXEL:		/* pixel (raster) display */
76739287Ssos	    if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
76839287Ssos		return EINVAL;
76939591Syokota	    if (scp->status & GRAPHICS_MODE)
77039287Ssos		return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize,
771149640Srodrigc					 scp->font_size, scp->font_width);
77239287Ssos	    s = spltty();
77339287Ssos	    if ((error = sc_clean_up(scp))) {
77439287Ssos		splx(s);
77539287Ssos		return error;
77639287Ssos	    }
77758872Syokota	    scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN);
77839287Ssos	    splx(s);
77948104Syokota	    if (scp == scp->sc->cur_scp) {
78039287Ssos		set_mode(scp);
78148104Syokota#ifndef SC_NO_PALETTE_LOADING
782205865Sjkim		if (adp->va_info.vi_mem_model == V_INFO_MM_DIRECT)
783204265Sjkim		    vidd_load_palette(adp, scp->sc->palette2);
784204265Sjkim		else
785204265Sjkim		    vidd_load_palette(adp, scp->sc->palette);
78648104Syokota#endif
78739287Ssos	    }
78839287Ssos	    sc_clear_screen(scp);
78939287Ssos	    scp->status &= ~UNKNOWN_MODE;
79039287Ssos	    return 0;
79148104Syokota#endif /* SC_PIXEL_MODE */
79239287Ssos
79339287Ssos	case KD_GRAPHICS:	/* switch to GRAPHICS (unknown) mode */
79439287Ssos	    s = spltty();
79539287Ssos	    if ((error = sc_clean_up(scp))) {
79639287Ssos		splx(s);
79739287Ssos		return error;
79839287Ssos	    }
79958872Syokota	    scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
80039287Ssos	    splx(s);
80142504Syokota#ifdef PC98
80248104Syokota	    if (scp == scp->sc->cur_scp)
80342504Syokota		set_mode(scp);
80442504Syokota#endif
80539287Ssos	    return 0;
80639287Ssos
80739287Ssos	default:
80839287Ssos	    return EINVAL;
80939287Ssos	}
81039287Ssos	/* NOT REACHED */
81139287Ssos
81248104Syokota#ifdef SC_PIXEL_MODE
81339287Ssos    case KDRASTER:		/* set pixel (raster) display mode */
81439287Ssos	if (ISUNKNOWNSC(scp) || ISTEXTSC(scp))
81539287Ssos	    return ENODEV;
81639287Ssos	return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1],
817149640Srodrigc				 ((int *)data)[2], 8);
81848104Syokota#endif /* SC_PIXEL_MODE */
81939287Ssos
82039287Ssos    case KDGETMODE:     	/* get current mode of this (virtual) console */
82139287Ssos	/*
82239287Ssos	 * From the user program's point of view, KD_PIXEL is the same
82339287Ssos	 * as KD_TEXT...
82439287Ssos	 */
82539287Ssos	*data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT;
82639287Ssos	return 0;
82739287Ssos
828162711Sru#if defined(COMPAT_FREEBSD6) || defined(COMPAT_FREEBSD5) || \
829162711Sru    defined(COMPAT_FREEBSD4) || defined(COMPAT_43)
830162711Sru    case _IO('K', 13):
831162711Sru	ival = IOCPARM_IVAL(data);
832162711Sru	data = (caddr_t)&ival;
833162711Sru	/* FALLTHROUGH */
834162711Sru#endif
83539287Ssos    case KDSBORDER:     	/* set border color of this (virtual) console */
836162711Sru	scp->border = *(int *)data;
83748104Syokota	if (scp == scp->sc->cur_scp)
83856043Syokota	    sc_set_border(scp, scp->border);
83939287Ssos	return 0;
84039287Ssos    }
84139287Ssos
84239287Ssos    return ENOIOCTL;
84339287Ssos}
84439287Ssos
84560938Sjakestatic LIST_HEAD(, sc_renderer) sc_rndr_list =
84656043Syokota	LIST_HEAD_INITIALIZER(sc_rndr_list);
84756043Syokota
84856043Syokotaint
84956043Syokotasc_render_add(sc_renderer_t *rndr)
85056043Syokota{
85156043Syokota	LIST_INSERT_HEAD(&sc_rndr_list, rndr, link);
85256043Syokota	return 0;
85356043Syokota}
85456043Syokota
85556043Syokotaint
85656043Syokotasc_render_remove(sc_renderer_t *rndr)
85756043Syokota{
85856043Syokota	/*
85956043Syokota	LIST_REMOVE(rndr, link);
86056043Syokota	*/
86156043Syokota	return EBUSY;	/* XXX */
86256043Syokota}
86356043Syokota
86456043Syokotasc_rndr_sw_t
86556043Syokota*sc_render_match(scr_stat *scp, char *name, int mode)
86656043Syokota{
86756043Syokota	const sc_renderer_t **list;
86856043Syokota	const sc_renderer_t *p;
86956043Syokota
87056043Syokota	if (!LIST_EMPTY(&sc_rndr_list)) {
87156043Syokota		LIST_FOREACH(p, &sc_rndr_list, link) {
87256043Syokota			if ((strcmp(p->name, name) == 0)
87356043Syokota				&& (mode == p->mode)) {
87456043Syokota				scp->status &=
87556043Syokota				    ~(VR_CURSOR_ON | VR_CURSOR_BLINK);
87656043Syokota				return p->rndrsw;
87756043Syokota			}
87856043Syokota		}
87956043Syokota	} else {
88078161Speter		SET_FOREACH(list, scrndr_set) {
88178161Speter			p = *list;
88256043Syokota			if ((strcmp(p->name, name) == 0)
88356043Syokota				&& (mode == p->mode)) {
88456043Syokota				scp->status &=
88556043Syokota				    ~(VR_CURSOR_ON | VR_CURSOR_BLINK);
88656043Syokota				return p->rndrsw;
88756043Syokota			}
88856043Syokota		}
88956043Syokota	}
89056043Syokota
89156043Syokota	return NULL;
89256043Syokota}
893