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