scvidctl.c revision 60833
1214501Srpaulo/*-
2214501Srpaulo * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3214501Srpaulo * All rights reserved.
4214501Srpaulo *
5214501Srpaulo * Redistribution and use in source and binary forms, with or without
6214501Srpaulo * modification, are permitted provided that the following conditions
7214501Srpaulo * are met:
8214501Srpaulo * 1. Redistributions of source code must retain the above copyright
9214501Srpaulo *    notice, this list of conditions and the following disclaimer as
10214501Srpaulo *    the first lines of this file unmodified.
11214501Srpaulo * 2. Redistributions in binary form must reproduce the above copyright
12214501Srpaulo *    notice, this list of conditions and the following disclaimer in the
13214501Srpaulo *    documentation and/or other materials provided with the distribution.
14214501Srpaulo *
15214501Srpaulo * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16214501Srpaulo * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17214501Srpaulo * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18214501Srpaulo * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19214501Srpaulo * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20214501Srpaulo * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21214501Srpaulo * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22214501Srpaulo * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23214501Srpaulo * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24214501Srpaulo * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25214501Srpaulo *
26214501Srpaulo * $FreeBSD: head/sys/dev/syscons/scvidctl.c 60833 2000-05-23 20:41:01Z jake $
27214501Srpaulo */
28214501Srpaulo
29214501Srpaulo#include "opt_syscons.h"
30214501Srpaulo
31214501Srpaulo#include <sys/param.h>
32214501Srpaulo#include <sys/systm.h>
33214501Srpaulo#include <sys/conf.h>
34214501Srpaulo#include <sys/signalvar.h>
35214501Srpaulo#include <sys/tty.h>
36214501Srpaulo#include <sys/kernel.h>
37214501Srpaulo
38214501Srpaulo#include <machine/console.h>
39214501Srpaulo
40214501Srpaulo#include <dev/fb/fbreg.h>
41214501Srpaulo#include <dev/syscons/syscons.h>
42214501Srpaulo
43214501Srpaulo/* for compatibility with previous versions */
44214501Srpaulo/* 3.0-RELEASE used the following structure */
45214501Srpaulotypedef struct old_video_adapter {
46214501Srpaulo    int			va_index;
47214501Srpaulo    int			va_type;
48214501Srpaulo    int			va_flags;
49214501Srpaulo/* flag bits are the same as the -CURRENT
50214501Srpaulo#define V_ADP_COLOR	(1<<0)
51214501Srpaulo#define V_ADP_MODECHANGE (1<<1)
52214501Srpaulo#define V_ADP_STATESAVE	(1<<2)
53214501Srpaulo#define V_ADP_STATELOAD	(1<<3)
54214501Srpaulo#define V_ADP_FONT	(1<<4)
55214501Srpaulo#define V_ADP_PALETTE	(1<<5)
56214501Srpaulo#define V_ADP_BORDER	(1<<6)
57214501Srpaulo#define V_ADP_VESA	(1<<7)
58214501Srpaulo*/
59214501Srpaulo    int			va_crtc_addr;
60214501Srpaulo    u_int		va_window;	/* virtual address */
61214501Srpaulo    size_t		va_window_size;
62214501Srpaulo    size_t		va_window_gran;
63214501Srpaulo    u_int		va_buffer;	/* virtual address */
64214501Srpaulo    size_t		va_buffer_size;
65214501Srpaulo    int			va_initial_mode;
66214501Srpaulo    int			va_initial_bios_mode;
67214501Srpaulo    int			va_mode;
68214501Srpaulo} old_video_adapter_t;
69214501Srpaulo
70214501Srpaulo#define OLD_CONS_ADPINFO _IOWR('c', 101, old_video_adapter_t)
71214501Srpaulo
72214501Srpaulo/* 3.1-RELEASE used the following structure */
73214501Srpaulotypedef struct old_video_adapter_info {
74214501Srpaulo    int			va_index;
75214501Srpaulo    int			va_type;
76214501Srpaulo    char		va_name[16];
77214501Srpaulo    int			va_unit;
78214501Srpaulo    int			va_flags;
79214501Srpaulo    int			va_io_base;
80214501Srpaulo    int			va_io_size;
81214501Srpaulo    int			va_crtc_addr;
82214501Srpaulo    int			va_mem_base;
83214501Srpaulo    int			va_mem_size;
84214501Srpaulo    u_int		va_window;	/* virtual address */
85214501Srpaulo    size_t		va_window_size;
86214501Srpaulo    size_t		va_window_gran;
87214501Srpaulo    u_int		va_buffer;;
88214501Srpaulo    size_t		va_buffer_size;
89214501Srpaulo    int			va_initial_mode;
90214501Srpaulo    int			va_initial_bios_mode;
91214501Srpaulo    int			va_mode;
92214501Srpaulo    int			va_line_width;
93214501Srpaulo} old_video_adapter_info_t;
94214501Srpaulo
95214501Srpaulo#define OLD_CONS_ADPINFO2 _IOWR('c', 101, old_video_adapter_info_t)
96214501Srpaulo
97214501Srpaulo/* 3.0-RELEASE and 3.1-RELEASE used the following structure */
98214501Srpaulotypedef struct old_video_info {
99214501Srpaulo    int			vi_mode;
100214501Srpaulo    int			vi_flags;
101214501Srpaulo/* flag bits are the same as the -CURRENT
102214501Srpaulo#define V_INFO_COLOR	(1<<0)
103214501Srpaulo#define V_INFO_GRAPHICS	(1<<1)
104214501Srpaulo#define V_INFO_LINEAR	(1<<2)
105214501Srpaulo#define V_INFO_VESA	(1<<3)
106214501Srpaulo*/
107214501Srpaulo    int			vi_width;
108214501Srpaulo    int			vi_height;
109214501Srpaulo    int			vi_cwidth;
110214501Srpaulo    int			vi_cheight;
111214501Srpaulo    int			vi_depth;
112214501Srpaulo    int			vi_planes;
113214501Srpaulo    u_int		vi_window;	/* physical address */
114214501Srpaulo    size_t		vi_window_size;
115214501Srpaulo    size_t		vi_window_gran;
116214501Srpaulo    u_int		vi_buffer;	/* physical address */
117214501Srpaulo    size_t		vi_buffer_size;
118214501Srpaulo} old_video_info_t;
119214501Srpaulo
120214501Srpaulo#define OLD_CONS_MODEINFO _IOWR('c', 102, old_video_info_t)
121214501Srpaulo#define OLD_CONS_FINDMODE _IOWR('c', 103, old_video_info_t)
122214501Srpaulo
123214501Srpauloint
124214501Srpaulosc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
125214501Srpaulo		 int fontsize)
126214501Srpaulo{
127214501Srpaulo    video_info_t info;
128214501Srpaulo    u_char *font;
129214501Srpaulo    int prev_ysize;
130214501Srpaulo    int error;
131214501Srpaulo    int s;
132214501Srpaulo
133214501Srpaulo    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info))
134214501Srpaulo	return ENODEV;
135214501Srpaulo
136214501Srpaulo    /* adjust argument values */
137214501Srpaulo    if (fontsize <= 0)
138214501Srpaulo	fontsize = info.vi_cheight;
139214501Srpaulo    if (fontsize < 14) {
140214501Srpaulo	fontsize = 8;
141214501Srpaulo#ifndef SC_NO_FONT_LOADING
142214501Srpaulo	if (!(scp->sc->fonts_loaded & FONT_8))
143214501Srpaulo	    return EINVAL;
144214501Srpaulo	font = scp->sc->font_8;
145214501Srpaulo#else
146214501Srpaulo	font = NULL;
147214501Srpaulo#endif
148214501Srpaulo    } else if (fontsize >= 16) {
149214501Srpaulo	fontsize = 16;
150214501Srpaulo#ifndef SC_NO_FONT_LOADING
151214501Srpaulo	if (!(scp->sc->fonts_loaded & FONT_16))
152214501Srpaulo	    return EINVAL;
153214501Srpaulo	font = scp->sc->font_16;
154214501Srpaulo#else
155214501Srpaulo	font = NULL;
156214501Srpaulo#endif
157214501Srpaulo    } else {
158214501Srpaulo	fontsize = 14;
159214501Srpaulo#ifndef SC_NO_FONT_LOADING
160214501Srpaulo	if (!(scp->sc->fonts_loaded & FONT_14))
161214501Srpaulo	    return EINVAL;
162214501Srpaulo	font = scp->sc->font_14;
163214501Srpaulo#else
164214501Srpaulo	font = NULL;
165214501Srpaulo#endif
166214501Srpaulo    }
167214501Srpaulo    if ((xsize <= 0) || (xsize > info.vi_width))
168214501Srpaulo	xsize = info.vi_width;
169214501Srpaulo    if ((ysize <= 0) || (ysize > info.vi_height))
170214501Srpaulo	ysize = info.vi_height;
171214501Srpaulo
172214501Srpaulo    /* stop screen saver, etc */
173214501Srpaulo    s = spltty();
174214501Srpaulo    if ((error = sc_clean_up(scp))) {
175214501Srpaulo	splx(s);
176214501Srpaulo	return error;
177214501Srpaulo    }
178214501Srpaulo
179214501Srpaulo    if (sc_render_match(scp, scp->sc->adp->va_name, 0) == NULL) {
180214501Srpaulo	splx(s);
181214501Srpaulo	return ENODEV;
182214501Srpaulo    }
183214501Srpaulo
184214501Srpaulo    /* set up scp */
185214501Srpaulo#ifndef SC_NO_HISTORY
186214501Srpaulo    if (scp->history != NULL)
187214501Srpaulo	sc_hist_save(scp);
188214501Srpaulo#endif
189214501Srpaulo    prev_ysize = scp->ysize;
190214501Srpaulo    /*
191214501Srpaulo     * This is a kludge to fend off scrn_update() while we
192214501Srpaulo     * muck around with scp. XXX
193214501Srpaulo     */
194214501Srpaulo    scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
195214501Srpaulo    scp->status &= ~(GRAPHICS_MODE | PIXEL_MODE | MOUSE_VISIBLE);
196214501Srpaulo    scp->mode = mode;
197214501Srpaulo    scp->xsize = xsize;
198214501Srpaulo    scp->ysize = ysize;
199214501Srpaulo    scp->xoff = 0;
200214501Srpaulo    scp->yoff = 0;
201214501Srpaulo    scp->xpixel = scp->xsize*8;
202214501Srpaulo    scp->ypixel = scp->ysize*fontsize;
203214501Srpaulo    scp->font = font;
204214501Srpaulo    scp->font_size = fontsize;
205214501Srpaulo
206214501Srpaulo    /* allocate buffers */
207214501Srpaulo    sc_alloc_scr_buffer(scp, TRUE, TRUE);
208214501Srpaulo    sc_init_emulator(scp, NULL);
209214501Srpaulo#ifndef SC_NO_CUTPASTE
210214501Srpaulo    sc_alloc_cut_buffer(scp, FALSE);
211214501Srpaulo#endif
212214501Srpaulo#ifndef SC_NO_HISTORY
213214501Srpaulo    sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE);
214214501Srpaulo#endif
215214501Srpaulo    splx(s);
216214501Srpaulo
217214501Srpaulo    if (scp == scp->sc->cur_scp)
218214501Srpaulo	set_mode(scp);
219214501Srpaulo    scp->status &= ~UNKNOWN_MODE;
220214501Srpaulo
221214501Srpaulo    if (tp == NULL)
222214501Srpaulo	return 0;
223214501Srpaulo    DPRINTF(5, ("ws_*size (%d,%d), size (%d,%d)\n",
224214501Srpaulo	tp->t_winsize.ws_col, tp->t_winsize.ws_row, scp->xsize, scp->ysize));
225214501Srpaulo    if (tp->t_winsize.ws_col != scp->xsize
226214501Srpaulo	|| tp->t_winsize.ws_row != scp->ysize) {
227214501Srpaulo	tp->t_winsize.ws_col = scp->xsize;
228214501Srpaulo	tp->t_winsize.ws_row = scp->ysize;
229214501Srpaulo	pgsignal(tp->t_pgrp, SIGWINCH, 1);
230214501Srpaulo    }
231214501Srpaulo
232214501Srpaulo    return 0;
233214501Srpaulo}
234214501Srpaulo
235214501Srpauloint
236214501Srpaulosc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
237214501Srpaulo{
238214501Srpaulo#ifdef SC_NO_MODE_CHANGE
239214501Srpaulo    return ENODEV;
240214501Srpaulo#else
241214501Srpaulo    video_info_t info;
242214501Srpaulo    int error;
243214501Srpaulo    int s;
244214501Srpaulo
245214501Srpaulo    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, mode, &info))
246214501Srpaulo	return ENODEV;
247214501Srpaulo
248214501Srpaulo    /* stop screen saver, etc */
249214501Srpaulo    s = spltty();
250214501Srpaulo    if ((error = sc_clean_up(scp))) {
251214501Srpaulo	splx(s);
252214501Srpaulo	return error;
253214501Srpaulo    }
254214501Srpaulo
255214501Srpaulo    if (sc_render_match(scp, scp->sc->adp->va_name, GRAPHICS_MODE) == NULL) {
256214501Srpaulo	splx(s);
257214501Srpaulo	return ENODEV;
258214501Srpaulo    }
259214501Srpaulo
260214501Srpaulo    /* set up scp */
261214501Srpaulo    scp->status |= (UNKNOWN_MODE | GRAPHICS_MODE | MOUSE_HIDDEN);
262214501Srpaulo    scp->status &= ~(PIXEL_MODE | MOUSE_VISIBLE);
263214501Srpaulo    scp->mode = mode;
264214501Srpaulo    /*
265214501Srpaulo     * Don't change xsize and ysize; preserve the previous vty
266214501Srpaulo     * and history buffers.
267214501Srpaulo     */
268214501Srpaulo    scp->xoff = 0;
269214501Srpaulo    scp->yoff = 0;
270214501Srpaulo    scp->xpixel = info.vi_width;
271214501Srpaulo    scp->ypixel = info.vi_height;
272214501Srpaulo    scp->font = NULL;
273214501Srpaulo    scp->font_size = 0;
274214501Srpaulo#ifndef SC_NO_SYSMOUSE
275214501Srpaulo    /* move the mouse cursor at the center of the screen */
276214501Srpaulo    sc_mouse_move(scp, scp->xpixel / 2, scp->ypixel / 2);
277214501Srpaulo#endif
278214501Srpaulo    sc_init_emulator(scp, NULL);
279214501Srpaulo    splx(s);
280214501Srpaulo
281214501Srpaulo    if (scp == scp->sc->cur_scp)
282214501Srpaulo	set_mode(scp);
283214501Srpaulo    /* clear_graphics();*/
284214501Srpaulo    scp->status &= ~UNKNOWN_MODE;
285214501Srpaulo
286214501Srpaulo    if (tp == NULL)
287214501Srpaulo	return 0;
288214501Srpaulo    if (tp->t_winsize.ws_xpixel != scp->xpixel
289214501Srpaulo	|| tp->t_winsize.ws_ypixel != scp->ypixel) {
290214501Srpaulo	tp->t_winsize.ws_xpixel = scp->xpixel;
291214501Srpaulo	tp->t_winsize.ws_ypixel = scp->ypixel;
292214501Srpaulo	pgsignal(tp->t_pgrp, SIGWINCH, 1);
293214501Srpaulo    }
294214501Srpaulo
295214501Srpaulo    return 0;
296214501Srpaulo#endif /* SC_NO_MODE_CHANGE */
297214501Srpaulo}
298214501Srpaulo
299214501Srpauloint
300214501Srpaulosc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
301214501Srpaulo		  int fontsize)
302214501Srpaulo{
303214501Srpaulo#ifndef SC_PIXEL_MODE
304214501Srpaulo    return ENODEV;
305214501Srpaulo#else
306214501Srpaulo    video_info_t info;
307214501Srpaulo    u_char *font;
308214501Srpaulo    int prev_ysize;
309214501Srpaulo    int error;
310214501Srpaulo    int s;
311214501Srpaulo
312214501Srpaulo    if ((*vidsw[scp->sc->adapter]->get_info)(scp->sc->adp, scp->mode, &info))
313214501Srpaulo	return ENODEV;		/* this shouldn't happen */
314214501Srpaulo
315214501Srpaulo    /* adjust argument values */
316214501Srpaulo    if (fontsize <= 0)
317214501Srpaulo	fontsize = info.vi_cheight;
318214501Srpaulo    if (fontsize < 14) {
319214501Srpaulo	fontsize = 8;
320214501Srpaulo#ifndef SC_NO_FONT_LOADING
321214501Srpaulo	if (!(scp->sc->fonts_loaded & FONT_8))
322214501Srpaulo	    return EINVAL;
323214501Srpaulo	font = scp->sc->font_8;
324214501Srpaulo#else
325214501Srpaulo	font = NULL;
326214501Srpaulo#endif
327214501Srpaulo    } else if (fontsize >= 16) {
328214501Srpaulo	fontsize = 16;
329214501Srpaulo#ifndef SC_NO_FONT_LOADING
330214501Srpaulo	if (!(scp->sc->fonts_loaded & FONT_16))
331214501Srpaulo	    return EINVAL;
332214501Srpaulo	font = scp->sc->font_16;
333214501Srpaulo#else
334214501Srpaulo	font = NULL;
335214501Srpaulo#endif
336214501Srpaulo    } else {
337214501Srpaulo	fontsize = 14;
338214501Srpaulo#ifndef SC_NO_FONT_LOADING
339214501Srpaulo	if (!(scp->sc->fonts_loaded & FONT_14))
340214501Srpaulo	    return EINVAL;
341214501Srpaulo	font = scp->sc->font_14;
342214501Srpaulo#else
343214501Srpaulo	font = NULL;
344214501Srpaulo#endif
345214501Srpaulo    }
346214501Srpaulo    if (xsize <= 0)
347214501Srpaulo	xsize = info.vi_width/8;
348214501Srpaulo    if (ysize <= 0)
349214501Srpaulo	ysize = info.vi_height/fontsize;
350214501Srpaulo
351214501Srpaulo    if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize))
352214501Srpaulo	return EINVAL;
353214501Srpaulo
354214501Srpaulo    /* only 16 color, 4 plane modes are supported XXX */
355214501Srpaulo    if ((info.vi_depth != 4) || (info.vi_planes != 4))
356214501Srpaulo	return ENODEV;
357214501Srpaulo
358214501Srpaulo    /*
359214501Srpaulo     * set_pixel_mode() currently does not support video modes whose
360214501Srpaulo     * memory size is larger than 64K. Because such modes require
361214501Srpaulo     * bank switching to access the entire screen. XXX
362214501Srpaulo     */
363214501Srpaulo    if (info.vi_width*info.vi_height/8 > info.vi_window_size)
364214501Srpaulo	return ENODEV;
365214501Srpaulo
366214501Srpaulo    /* stop screen saver, etc */
367214501Srpaulo    s = spltty();
368214501Srpaulo    if ((error = sc_clean_up(scp))) {
369214501Srpaulo	splx(s);
370214501Srpaulo	return error;
371214501Srpaulo    }
372214501Srpaulo
373214501Srpaulo    if (sc_render_match(scp, scp->sc->adp->va_name, PIXEL_MODE) == NULL) {
374214501Srpaulo	splx(s);
375214501Srpaulo	return ENODEV;
376214501Srpaulo    }
377214501Srpaulo
378214501Srpaulo#if 0
379214501Srpaulo    if (scp->tsw)
380214501Srpaulo	(*scp->tsw->te_term)(scp, scp->ts);
381214501Srpaulo    scp->tsw = NULL;
382214501Srpaulo    scp->ts = NULL;
383214501Srpaulo#endif
384214501Srpaulo
385214501Srpaulo    /* set up scp */
386214501Srpaulo#ifndef SC_NO_HISTORY
387214501Srpaulo    if (scp->history != NULL)
388214501Srpaulo	sc_hist_save(scp);
389214501Srpaulo#endif
390214501Srpaulo    prev_ysize = scp->ysize;
391214501Srpaulo    scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN);
392214501Srpaulo    scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE);
393214501Srpaulo    scp->xsize = xsize;
394214501Srpaulo    scp->ysize = ysize;
395214501Srpaulo    scp->xoff = (scp->xpixel/8 - xsize)/2;
396214501Srpaulo    scp->yoff = (scp->ypixel/fontsize - ysize)/2;
397214501Srpaulo    scp->font = font;
398214501Srpaulo    scp->font_size = fontsize;
399214501Srpaulo
400214501Srpaulo    /* allocate buffers */
401214501Srpaulo    sc_alloc_scr_buffer(scp, TRUE, TRUE);
402214501Srpaulo    sc_init_emulator(scp, NULL);
403214501Srpaulo#ifndef SC_NO_CUTPASTE
404214501Srpaulo    sc_alloc_cut_buffer(scp, FALSE);
405214501Srpaulo#endif
406214501Srpaulo#ifndef SC_NO_HISTORY
407214501Srpaulo    sc_alloc_history_buffer(scp, 0, prev_ysize, FALSE);
408214501Srpaulo#endif
409214501Srpaulo    splx(s);
410214501Srpaulo
411214501Srpaulo    if (scp == scp->sc->cur_scp) {
412214501Srpaulo	sc_set_border(scp, scp->border);
413214501Srpaulo	sc_set_cursor_image(scp);
414214501Srpaulo    }
415214501Srpaulo
416214501Srpaulo    scp->status &= ~UNKNOWN_MODE;
417214501Srpaulo
418214501Srpaulo    if (tp == NULL)
419214501Srpaulo	return 0;
420214501Srpaulo    if (tp->t_winsize.ws_col != scp->xsize
421214501Srpaulo	|| tp->t_winsize.ws_row != scp->ysize) {
422214501Srpaulo	tp->t_winsize.ws_col = scp->xsize;
423214501Srpaulo	tp->t_winsize.ws_row = scp->ysize;
424214501Srpaulo	pgsignal(tp->t_pgrp, SIGWINCH, 1);
425214501Srpaulo    }
426214501Srpaulo
427214501Srpaulo    return 0;
428214501Srpaulo#endif /* SC_PIXEL_MODE */
429214501Srpaulo}
430214501Srpaulo
431214501Srpaulo#define fb_ioctl(a, c, d)		\
432214501Srpaulo	(((a) == NULL) ? ENODEV : 	\
433214501Srpaulo			 (*vidsw[(a)->va_index]->ioctl)((a), (c), (caddr_t)(d)))
434214501Srpaulo
435214501Srpauloint
436214501Srpaulosc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p)
437214501Srpaulo{
438214501Srpaulo    scr_stat *scp;
439214501Srpaulo    video_adapter_t *adp;
440214501Srpaulo    video_info_t info;
441214501Srpaulo    video_adapter_info_t adp_info;
442214501Srpaulo    int error;
443214501Srpaulo    int s;
444214501Srpaulo
445214501Srpaulo    scp = SC_STAT(tp->t_dev);
446214501Srpaulo    if (scp == NULL)		/* tp == SC_MOUSE */
447214501Srpaulo	return ENOIOCTL;
448214501Srpaulo    adp = scp->sc->adp;
449214501Srpaulo    if (adp == NULL)		/* shouldn't happen??? */
450214501Srpaulo	return ENODEV;
451214501Srpaulo
452214501Srpaulo    switch (cmd) {
453214501Srpaulo
454214501Srpaulo    case CONS_CURRENTADP:	/* get current adapter index */
455214501Srpaulo    case FBIO_ADAPTER:
456214501Srpaulo	return fb_ioctl(adp, FBIO_ADAPTER, data);
457214501Srpaulo
458214501Srpaulo    case CONS_CURRENT:  	/* get current adapter type */
459214501Srpaulo    case FBIO_ADPTYPE:
460214501Srpaulo	return fb_ioctl(adp, FBIO_ADPTYPE, data);
461214501Srpaulo
462214501Srpaulo    case OLD_CONS_ADPINFO:	/* adapter information (old interface) */
463214501Srpaulo	if (((old_video_adapter_t *)data)->va_index >= 0) {
464214501Srpaulo	    adp = vid_get_adapter(((old_video_adapter_t *)data)->va_index);
465214501Srpaulo	    if (adp == NULL)
466214501Srpaulo		return ENODEV;
467214501Srpaulo	}
468214501Srpaulo	((old_video_adapter_t *)data)->va_index = adp->va_index;
469214501Srpaulo	((old_video_adapter_t *)data)->va_type = adp->va_type;
470214501Srpaulo	((old_video_adapter_t *)data)->va_flags = adp->va_flags;
471214501Srpaulo	((old_video_adapter_t *)data)->va_crtc_addr = adp->va_crtc_addr;
472214501Srpaulo	((old_video_adapter_t *)data)->va_window = adp->va_window;
473214501Srpaulo	((old_video_adapter_t *)data)->va_window_size = adp->va_window_size;
474214501Srpaulo	((old_video_adapter_t *)data)->va_window_gran = adp->va_window_gran;
475214501Srpaulo	((old_video_adapter_t *)data)->va_buffer = adp->va_buffer;
476214501Srpaulo	((old_video_adapter_t *)data)->va_buffer_size = adp->va_buffer_size;
477214501Srpaulo	((old_video_adapter_t *)data)->va_mode = adp->va_mode;
478214501Srpaulo	((old_video_adapter_t *)data)->va_initial_mode = adp->va_initial_mode;
479214501Srpaulo	((old_video_adapter_t *)data)->va_initial_bios_mode
480214501Srpaulo	    = adp->va_initial_bios_mode;
481214501Srpaulo	return 0;
482214501Srpaulo
483214501Srpaulo    case OLD_CONS_ADPINFO2:	/* adapter information (yet another old I/F) */
484214501Srpaulo	adp_info.va_index = ((old_video_adapter_info_t *)data)->va_index;
485214501Srpaulo	if (adp_info.va_index >= 0) {
486214501Srpaulo	    adp = vid_get_adapter(adp_info.va_index);
487214501Srpaulo	    if (adp == NULL)
488214501Srpaulo		return ENODEV;
489214501Srpaulo	}
490214501Srpaulo	error = fb_ioctl(adp, FBIO_ADPINFO, &adp_info);
491214501Srpaulo	if (error == 0)
492214501Srpaulo	    bcopy(&adp_info, data, sizeof(old_video_adapter_info_t));
493214501Srpaulo	return error;
494214501Srpaulo
495214501Srpaulo    case CONS_ADPINFO:		/* adapter information */
496214501Srpaulo    case FBIO_ADPINFO:
497214501Srpaulo	if (((video_adapter_info_t *)data)->va_index >= 0) {
498214501Srpaulo	    adp = vid_get_adapter(((video_adapter_info_t *)data)->va_index);
499214501Srpaulo	    if (adp == NULL)
500		return ENODEV;
501	}
502	return fb_ioctl(adp, FBIO_ADPINFO, data);
503
504    case CONS_GET:      	/* get current video mode */
505    case FBIO_GETMODE:
506	*(int *)data = scp->mode;
507	return 0;
508
509#ifndef SC_NO_MODE_CHANGE
510    case FBIO_SETMODE:		/* set video mode */
511	if (!(adp->va_flags & V_ADP_MODECHANGE))
512 	    return ENODEV;
513	info.vi_mode = *(int *)data;
514	error = fb_ioctl(adp, FBIO_MODEINFO, &info);
515	if (error)
516	    return error;
517	if (info.vi_flags & V_INFO_GRAPHICS)
518	    return sc_set_graphics_mode(scp, tp, *(int *)data);
519	else
520	    return sc_set_text_mode(scp, tp, *(int *)data, 0, 0, 0);
521#endif /* SC_NO_MODE_CHANGE */
522
523    case OLD_CONS_MODEINFO:	/* get mode information (old infterface) */
524	info.vi_mode = ((old_video_info_t *)data)->vi_mode;
525	error = fb_ioctl(adp, FBIO_MODEINFO, &info);
526	if (error == 0)
527	    bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t));
528	return error;
529
530    case CONS_MODEINFO:		/* get mode information */
531    case FBIO_MODEINFO:
532	return fb_ioctl(adp, FBIO_MODEINFO, data);
533
534    case OLD_CONS_FINDMODE:	/* find a matching video mode (old interface) */
535	bzero(&info, sizeof(info));
536	bcopy((old_video_info_t *)data, &info, sizeof(old_video_info_t));
537	error = fb_ioctl(adp, FBIO_FINDMODE, &info);
538	if (error == 0)
539	    bcopy(&info, (old_video_info_t *)data, sizeof(old_video_info_t));
540	return error;
541
542    case CONS_FINDMODE:		/* find a matching video mode */
543    case FBIO_FINDMODE:
544	return fb_ioctl(adp, FBIO_FINDMODE, data);
545
546    case CONS_SETWINORG:	/* set frame buffer window origin */
547    case FBIO_SETWINORG:
548	if (scp != scp->sc->cur_scp)
549	    return ENODEV;	/* XXX */
550	return fb_ioctl(adp, FBIO_SETWINORG, data);
551
552    case FBIO_GETWINORG:	/* get frame buffer window origin */
553	if (scp != scp->sc->cur_scp)
554	    return ENODEV;	/* XXX */
555	return fb_ioctl(adp, FBIO_GETWINORG, data);
556
557    case FBIO_GETDISPSTART:
558    case FBIO_SETDISPSTART:
559    case FBIO_GETLINEWIDTH:
560    case FBIO_SETLINEWIDTH:
561	if (scp != scp->sc->cur_scp)
562	    return ENODEV;	/* XXX */
563	return fb_ioctl(adp, cmd, data);
564
565    case FBIO_GETPALETTE:
566    case FBIO_SETPALETTE:
567    case FBIOPUTCMAP:
568    case FBIOGETCMAP:
569    case FBIOGTYPE:
570    case FBIOGATTR:
571    case FBIOSVIDEO:
572    case FBIOGVIDEO:
573    case FBIOSCURSOR:
574    case FBIOGCURSOR:
575    case FBIOSCURPOS:
576    case FBIOGCURPOS:
577    case FBIOGCURMAX:
578	if (scp != scp->sc->cur_scp)
579	    return ENODEV;	/* XXX */
580	return fb_ioctl(adp, cmd, data);
581
582#ifndef SC_NO_MODE_CHANGE
583    /* generic text modes */
584    case SW_TEXT_80x25:	case SW_TEXT_80x30:
585    case SW_TEXT_80x43: case SW_TEXT_80x50:
586    case SW_TEXT_80x60:
587	/* FALL THROUGH */
588
589    /* VGA TEXT MODES */
590    case SW_VGA_C40x25:
591    case SW_VGA_C80x25: case SW_VGA_M80x25:
592    case SW_VGA_C80x30: case SW_VGA_M80x30:
593    case SW_VGA_C80x50: case SW_VGA_M80x50:
594    case SW_VGA_C80x60: case SW_VGA_M80x60:
595    case SW_VGA_C90x25: case SW_VGA_M90x25:
596    case SW_VGA_C90x30: case SW_VGA_M90x30:
597    case SW_VGA_C90x43: case SW_VGA_M90x43:
598    case SW_VGA_C90x50: case SW_VGA_M90x50:
599    case SW_VGA_C90x60: case SW_VGA_M90x60:
600    case SW_B40x25:     case SW_C40x25:
601    case SW_B80x25:     case SW_C80x25:
602    case SW_ENH_B40x25: case SW_ENH_C40x25:
603    case SW_ENH_B80x25: case SW_ENH_C80x25:
604    case SW_ENH_B80x43: case SW_ENH_C80x43:
605    case SW_EGAMONO80x25:
606
607#ifdef PC98
608    /* PC98 TEXT MODES */
609    case SW_PC98_80x25:
610    case SW_PC98_80x30:
611#endif
612	if (!(adp->va_flags & V_ADP_MODECHANGE))
613 	    return ENODEV;
614	return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0);
615
616    /* GRAPHICS MODES */
617    case SW_BG320:     case SW_BG640:
618    case SW_CG320:     case SW_CG320_D:   case SW_CG640_E:
619    case SW_CG640x350: case SW_ENH_CG640:
620    case SW_BG640x480: case SW_CG640x480: case SW_VGA_CG320:
621    case SW_VGA_MODEX:
622#ifdef PC98
623    /* PC98 GRAPHICS MODES */
624    case SW_PC98_EGC640x400:	case SW_PC98_PEGC640x400:
625    case SW_PC98_PEGC640x480:
626#endif
627	if (!(adp->va_flags & V_ADP_MODECHANGE))
628	    return ENODEV;
629	return sc_set_graphics_mode(scp, tp, cmd & 0xff);
630#endif /* SC_NO_MODE_CHANGE */
631
632    case KDSETMODE:     	/* set current mode of this (virtual) console */
633	switch (*(int *)data) {
634	case KD_TEXT:   	/* switch to TEXT (known) mode */
635	    /*
636	     * If scp->mode is of graphics modes, we don't know which
637	     * text mode to switch back to...
638	     */
639	    if (scp->status & GRAPHICS_MODE)
640		return EINVAL;
641	    /* restore fonts & palette ! */
642#if 0
643#ifndef SC_NO_FONT_LOADING
644	    if (ISFONTAVAIL(adp->va_flags)
645		&& !(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
646		/*
647		 * FONT KLUDGE
648		 * Don't load fonts for now... XXX
649		 */
650		if (scp->sc->fonts_loaded & FONT_8)
651		    sc_load_font(scp, 0, 8, scp->sc->font_8, 0, 256);
652		if (scp->sc->fonts_loaded & FONT_14)
653		    sc_load_font(scp, 0, 14, scp->sc->font_14, 0, 256);
654		if (scp->sc->fonts_loaded & FONT_16)
655		    sc_load_font(scp, 0, 16, scp->sc->font_16, 0, 256);
656	    }
657#endif /* SC_NO_FONT_LOADING */
658#endif
659
660#ifndef SC_NO_PALETTE_LOADING
661	    load_palette(adp, scp->sc->palette);
662#endif
663
664#ifndef PC98
665	    /* move hardware cursor out of the way */
666	    (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
667#endif
668
669	    /* FALL THROUGH */
670
671	case KD_TEXT1:  	/* switch to TEXT (known) mode */
672	    /*
673	     * If scp->mode is of graphics modes, we don't know which
674	     * text/pixel mode to switch back to...
675	     */
676	    if (scp->status & GRAPHICS_MODE)
677		return EINVAL;
678	    s = spltty();
679	    if ((error = sc_clean_up(scp))) {
680		splx(s);
681		return error;
682	    }
683#ifndef PC98
684	    scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
685	    splx(s);
686	    /* no restore fonts & palette */
687	    if (scp == scp->sc->cur_scp)
688		set_mode(scp);
689	    sc_clear_screen(scp);
690	    scp->status &= ~UNKNOWN_MODE;
691#else /* PC98 */
692	    scp->status &= ~UNKNOWN_MODE;
693	    /* no restore fonts & palette */
694	    if (scp == scp->sc->cur_scp)
695		set_mode(scp);
696	    sc_clear_screen(scp);
697	    splx(s);
698#endif /* PC98 */
699	    return 0;
700
701#ifdef SC_PIXEL_MODE
702	case KD_PIXEL:		/* pixel (raster) display */
703	    if (!(scp->status & (GRAPHICS_MODE | PIXEL_MODE)))
704		return EINVAL;
705	    if (scp->status & GRAPHICS_MODE)
706		return sc_set_pixel_mode(scp, tp, scp->xsize, scp->ysize,
707					 scp->font_size);
708	    s = spltty();
709	    if ((error = sc_clean_up(scp))) {
710		splx(s);
711		return error;
712	    }
713	    scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN);
714	    splx(s);
715	    if (scp == scp->sc->cur_scp) {
716		set_mode(scp);
717#ifndef SC_NO_PALETTE_LOADING
718		load_palette(adp, scp->sc->palette);
719#endif
720	    }
721	    sc_clear_screen(scp);
722	    scp->status &= ~UNKNOWN_MODE;
723	    return 0;
724#endif /* SC_PIXEL_MODE */
725
726	case KD_GRAPHICS:	/* switch to GRAPHICS (unknown) mode */
727	    s = spltty();
728	    if ((error = sc_clean_up(scp))) {
729		splx(s);
730		return error;
731	    }
732	    scp->status |= UNKNOWN_MODE | MOUSE_HIDDEN;
733	    splx(s);
734#ifdef PC98
735	    if (scp == scp->sc->cur_scp)
736		set_mode(scp);
737#endif
738	    return 0;
739
740	default:
741	    return EINVAL;
742	}
743	/* NOT REACHED */
744
745#ifdef SC_PIXEL_MODE
746    case KDRASTER:		/* set pixel (raster) display mode */
747	if (ISUNKNOWNSC(scp) || ISTEXTSC(scp))
748	    return ENODEV;
749	return sc_set_pixel_mode(scp, tp, ((int *)data)[0], ((int *)data)[1],
750				 ((int *)data)[2]);
751#endif /* SC_PIXEL_MODE */
752
753    case KDGETMODE:     	/* get current mode of this (virtual) console */
754	/*
755	 * From the user program's point of view, KD_PIXEL is the same
756	 * as KD_TEXT...
757	 */
758	*data = ISGRAPHSC(scp) ? KD_GRAPHICS : KD_TEXT;
759	return 0;
760
761    case KDSBORDER:     	/* set border color of this (virtual) console */
762	scp->border = *data;
763	if (scp == scp->sc->cur_scp)
764	    sc_set_border(scp, scp->border);
765	return 0;
766    }
767
768    return ENOIOCTL;
769}
770
771static LIST_HEAD(, struct sc_renderer) sc_rndr_list =
772	LIST_HEAD_INITIALIZER(sc_rndr_list);
773
774int
775sc_render_add(sc_renderer_t *rndr)
776{
777	LIST_INSERT_HEAD(&sc_rndr_list, rndr, link);
778	return 0;
779}
780
781int
782sc_render_remove(sc_renderer_t *rndr)
783{
784	/*
785	LIST_REMOVE(rndr, link);
786	*/
787	return EBUSY;	/* XXX */
788}
789
790sc_rndr_sw_t
791*sc_render_match(scr_stat *scp, char *name, int mode)
792{
793	const sc_renderer_t **list;
794	const sc_renderer_t *p;
795
796	if (!LIST_EMPTY(&sc_rndr_list)) {
797		LIST_FOREACH(p, &sc_rndr_list, link) {
798			if ((strcmp(p->name, name) == 0)
799				&& (mode == p->mode)) {
800				scp->status &=
801				    ~(VR_CURSOR_ON | VR_CURSOR_BLINK);
802				return p->rndrsw;
803			}
804		}
805	} else {
806		list = (const sc_renderer_t **)scrndr_set.ls_items;
807		while ((p = *list++) != NULL) {
808			if ((strcmp(p->name, name) == 0)
809				&& (mode == p->mode)) {
810				scp->status &=
811				    ~(VR_CURSOR_ON | VR_CURSOR_BLINK);
812				return p->rndrsw;
813			}
814		}
815	}
816
817	return NULL;
818}
819