scvesactl.c revision 149640
11553Srgrimes/*-
21553Srgrimes * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
31553Srgrimes * All rights reserved.
41553Srgrimes *
51553Srgrimes * This code is derived from software contributed to The DragonFly Project
61553Srgrimes * by Sascha Wildner <saw@online.de>
71553Srgrimes *
81553Srgrimes * Redistribution and use in source and binary forms, with or without
91553Srgrimes * modification, are permitted provided that the following conditions
101553Srgrimes * are met:
111553Srgrimes * 1. Redistributions of source code must retain the above copyright
121553Srgrimes *    notice, this list of conditions and the following disclaimer as
131553Srgrimes *    the first lines of this file unmodified.
141553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151553Srgrimes *    notice, this list of conditions and the following disclaimer in the
161553Srgrimes *    documentation and/or other materials provided with the distribution.
171553Srgrimes *
181553Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
191553Srgrimes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
201553Srgrimes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
211553Srgrimes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
221553Srgrimes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
231553Srgrimes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
241553Srgrimes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
251553Srgrimes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
261553Srgrimes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
271553Srgrimes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
281553Srgrimes *
291553Srgrimes */
301553Srgrimes
311553Srgrimes#include <sys/cdefs.h>
321553Srgrimes__FBSDID("$FreeBSD: head/sys/dev/syscons/scvesactl.c 149640 2005-08-30 18:58:17Z rodrigc $");
331553Srgrimes
341553Srgrimes#include "opt_vga.h"
351553Srgrimes
3629780Scharnier#ifndef VGA_NO_MODE_CHANGE
371553Srgrimes
381553Srgrimes#include <sys/param.h>
391553Srgrimes#include <sys/systm.h>
401553Srgrimes#include <sys/conf.h>
411553Srgrimes#include <sys/tty.h>
4229780Scharnier#include <sys/kernel.h>
4315637Sjoerg#include <sys/fbio.h>
4429780Scharnier#include <sys/consio.h>
4529780Scharnier
4650042Smdodd#include <machine/pc/vesa.h>
471553Srgrimes
481553Srgrimes#include <dev/fb/fbreg.h>
491553Srgrimes#include <dev/syscons/syscons.h>
501553Srgrimes
5129780Scharnierstatic d_ioctl_t *prev_user_ioctl;
521553Srgrimes
5331492Swollmanstatic int
5429780Scharniervesa_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
5529780Scharnier{
561553Srgrimes	scr_stat *scp;
5729780Scharnier	struct tty *tp;
5829780Scharnier	int mode;
591553Srgrimes
6029780Scharnier	tp = dev->si_tty;
611553Srgrimes	if (!tp)
6250039Smdodd		return ENXIO;
6331492Swollman	scp = SC_STAT(tp->t_dev);
641553Srgrimes
651553Srgrimes	switch (cmd) {
661553Srgrimes
671553Srgrimes	/* generic text modes */
6815637Sjoerg	case SW_TEXT_132x25: case SW_TEXT_132x30:
6915637Sjoerg	case SW_TEXT_132x43: case SW_TEXT_132x50:
7015637Sjoerg	case SW_TEXT_132x60:
7115637Sjoerg		if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
721553Srgrimes			return ENODEV;
731553Srgrimes		return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0, 0);
741553Srgrimes
751553Srgrimes	/* text modes */
7627618Simp	case SW_VESA_C80x60:
7727618Simp	case SW_VESA_C132x25:
7839084Swollman	case SW_VESA_C132x43:
791553Srgrimes	case SW_VESA_C132x50:
8039084Swollman	case SW_VESA_C132x60:
8139084Swollman		if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
8239084Swollman			return ENODEV;
8339084Swollman		mode = (cmd & 0xff) + M_VESA_BASE;
841553Srgrimes		return sc_set_text_mode(scp, tp, mode, 0, 0, 0, 0);
8539084Swollman
8650039Smdodd	/* graphics modes */
871553Srgrimes	case SW_VESA_32K_320: 	case SW_VESA_64K_320:
881553Srgrimes	case SW_VESA_FULL_320:
891553Srgrimes
9015637Sjoerg	case SW_VESA_CG640x400:
911553Srgrimes
921553Srgrimes	case SW_VESA_CG640x480:
931553Srgrimes	case SW_VESA_32K_640:	case SW_VESA_64K_640:
941553Srgrimes	case SW_VESA_FULL_640:
951553Srgrimes
961553Srgrimes	case SW_VESA_800x600:	case SW_VESA_CG800x600:
971553Srgrimes	case SW_VESA_32K_800:	case SW_VESA_64K_800:
981553Srgrimes	case SW_VESA_FULL_800:
9927618Simp
10027618Simp	case SW_VESA_1024x768:	case SW_VESA_CG1024x768:
10127618Simp	case SW_VESA_32K_1024:	case SW_VESA_64K_1024:
1021553Srgrimes	case SW_VESA_FULL_1024:
1031553Srgrimes
1041553Srgrimes	case SW_VESA_1280x1024:	case SW_VESA_CG1280x1024:
1051553Srgrimes	case SW_VESA_32K_1280:	case SW_VESA_64K_1280:
1061553Srgrimes	case SW_VESA_FULL_1280:
1071553Srgrimes		if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
1081553Srgrimes			return ENODEV;
1091553Srgrimes		mode = (cmd & 0xff) + M_VESA_BASE;
1101553Srgrimes		return sc_set_graphics_mode(scp, tp, mode);
1111553Srgrimes	default:
1121553Srgrimes		if (IOCGROUP(cmd) == 'V') {
1131553Srgrimes			if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
1141553Srgrimes				return ENODEV;
11515637Sjoerg
1161553Srgrimes			mode = (cmd & 0xff) + M_VESA_BASE;
1171553Srgrimes
1181553Srgrimes			/* Only set graphics mode in non-pcvt case */
11931492Swollman			if (((cmd & IOC_DIRMASK) == IOC_VOID) &&
12031492Swollman			    (mode > M_VESA_FULL_1280) &&
12131492Swollman			    (mode < M_VESA_MODE_MAX))
12231492Swollman				return sc_set_graphics_mode(scp, tp, mode);
1231553Srgrimes		}
1241553Srgrimes	}
1251553Srgrimes
12650039Smdodd	if (prev_user_ioctl)
1271553Srgrimes		return (*prev_user_ioctl)(dev, cmd, data, flag, td);
1281553Srgrimes	else
12950039Smdodd		return ENOIOCTL;
1301553Srgrimes}
1311553Srgrimes
1321553Srgrimesint
1331553Srgrimesvesa_load_ioctl(void)
1341553Srgrimes{
1351553Srgrimes	if (prev_user_ioctl)
1361553Srgrimes		return EBUSY;
13750039Smdodd	prev_user_ioctl = sc_user_ioctl;
1381553Srgrimes	sc_user_ioctl = vesa_ioctl;
1391553Srgrimes	return 0;
14050039Smdodd}
14150039Smdodd
14250039Smdoddint
14350039Smdoddvesa_unload_ioctl(void)
14450039Smdodd{
14550039Smdodd	if (sc_user_ioctl != vesa_ioctl)
1461553Srgrimes		return EBUSY;
1471553Srgrimes	sc_user_ioctl = prev_user_ioctl;
1481553Srgrimes	prev_user_ioctl = NULL;
1491553Srgrimes	return 0;
15050039Smdodd}
1511553Srgrimes
1521553Srgrimes#endif	/* SC_NO_MODE_CHANGE */
15350039Smdodd