1230557Sjimharris/*-
2230557Sjimharris * SPDX-License-Identifier: BSD-2-Clause
3230557Sjimharris *
4230557Sjimharris * Copyright (c) 1998 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5230557Sjimharris * All rights reserved.
6230557Sjimharris *
7230557Sjimharris * This code is derived from software contributed to The DragonFly Project
8230557Sjimharris * by Sascha Wildner <saw@online.de>
9230557Sjimharris *
10230557Sjimharris * Redistribution and use in source and binary forms, with or without
11230557Sjimharris * modification, are permitted provided that the following conditions
12230557Sjimharris * are met:
13230557Sjimharris * 1. Redistributions of source code must retain the above copyright
14230557Sjimharris *    notice, this list of conditions and the following disclaimer as
15230557Sjimharris *    the first lines of this file unmodified.
16230557Sjimharris * 2. Redistributions in binary form must reproduce the above copyright
17230557Sjimharris *    notice, this list of conditions and the following disclaimer in the
18230557Sjimharris *    documentation and/or other materials provided with the distribution.
19230557Sjimharris *
20230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21230557Sjimharris * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22230557Sjimharris * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23230557Sjimharris * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24230557Sjimharris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25230557Sjimharris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29230557Sjimharris * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30230557Sjimharris *
31230557Sjimharris */
32230557Sjimharris
33230557Sjimharris#include <sys/cdefs.h>
34230557Sjimharris#include "opt_vga.h"
35230557Sjimharris
36230557Sjimharris#ifndef VGA_NO_MODE_CHANGE
37230557Sjimharris
38230557Sjimharris#include <sys/param.h>
39230557Sjimharris#include <sys/systm.h>
40230557Sjimharris#include <sys/conf.h>
41230557Sjimharris#include <sys/tty.h>
42230557Sjimharris#include <sys/kernel.h>
43230557Sjimharris#include <sys/fbio.h>
44230557Sjimharris#include <sys/consio.h>
45230557Sjimharris
46230557Sjimharris#include <dev/fb/vesa.h>
47230557Sjimharris
48230557Sjimharris#include <dev/fb/fbreg.h>
49230557Sjimharris#include <dev/syscons/syscons.h>
50230557Sjimharris
51230557Sjimharrisstatic tsw_ioctl_t *prev_user_ioctl;
52230557Sjimharris
53230557Sjimharrisstatic int
54230557Sjimharrisvesa_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td)
55230557Sjimharris{
56230557Sjimharris	scr_stat *scp;
57230557Sjimharris	int mode;
58230557Sjimharris
59230557Sjimharris	scp = SC_STAT(tp);
60230557Sjimharris
61230557Sjimharris	switch (cmd) {
62230557Sjimharris	/* generic text modes */
63230557Sjimharris	case SW_TEXT_132x25: case SW_TEXT_132x30:
64230557Sjimharris	case SW_TEXT_132x43: case SW_TEXT_132x50:
65230557Sjimharris	case SW_TEXT_132x60:
66230557Sjimharris		if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
67230557Sjimharris			return ENODEV;
68230557Sjimharris		return sc_set_text_mode(scp, tp, cmd & 0xff, 0, 0, 0, 0);
69230557Sjimharris
70230557Sjimharris	/* text modes */
71230557Sjimharris	case SW_VESA_C80x60:
72230557Sjimharris	case SW_VESA_C132x25:
73230557Sjimharris	case SW_VESA_C132x43:
74230557Sjimharris	case SW_VESA_C132x50:
75230557Sjimharris	case SW_VESA_C132x60:
76230557Sjimharris		if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
77230557Sjimharris			return ENODEV;
78230557Sjimharris		mode = (cmd & 0xff) + M_VESA_BASE;
79230557Sjimharris		return sc_set_text_mode(scp, tp, mode, 0, 0, 0, 0);
80230557Sjimharris
81230557Sjimharris	/* graphics modes */
82230557Sjimharris	case SW_VESA_32K_320: 	case SW_VESA_64K_320:
83230557Sjimharris	case SW_VESA_FULL_320:
84230557Sjimharris
85230557Sjimharris	case SW_VESA_CG640x400:
86230557Sjimharris
87230557Sjimharris	case SW_VESA_CG640x480:
88230557Sjimharris	case SW_VESA_32K_640:	case SW_VESA_64K_640:
89230557Sjimharris	case SW_VESA_FULL_640:
90230557Sjimharris
91230557Sjimharris	case SW_VESA_800x600:	case SW_VESA_CG800x600:
92230557Sjimharris	case SW_VESA_32K_800:	case SW_VESA_64K_800:
93230557Sjimharris	case SW_VESA_FULL_800:
94230557Sjimharris
95230557Sjimharris	case SW_VESA_1024x768:	case SW_VESA_CG1024x768:
96230557Sjimharris	case SW_VESA_32K_1024:	case SW_VESA_64K_1024:
97230557Sjimharris	case SW_VESA_FULL_1024:
98230557Sjimharris
99230557Sjimharris	case SW_VESA_1280x1024:	case SW_VESA_CG1280x1024:
100230557Sjimharris	case SW_VESA_32K_1280:	case SW_VESA_64K_1280:
101230557Sjimharris	case SW_VESA_FULL_1280:
102230557Sjimharris		if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
103230557Sjimharris			return ENODEV;
104230557Sjimharris		mode = (cmd & 0xff) + M_VESA_BASE;
105230557Sjimharris		return sc_set_graphics_mode(scp, tp, mode);
106230557Sjimharris	default:
107230557Sjimharris		if (IOCGROUP(cmd) == 'V') {
108230557Sjimharris			if (!(scp->sc->adp->va_flags & V_ADP_MODECHANGE))
109230557Sjimharris				return ENODEV;
110230557Sjimharris
111230557Sjimharris			mode = (cmd & 0xff) + M_VESA_BASE;
112230557Sjimharris
113230557Sjimharris			if (((cmd & IOC_DIRMASK) == IOC_VOID) &&
114230557Sjimharris			    (mode > M_VESA_FULL_1280) &&
115230557Sjimharris			    (mode < M_VESA_MODE_MAX))
116230557Sjimharris				return sc_set_graphics_mode(scp, tp, mode);
117230557Sjimharris		}
118230557Sjimharris	}
119230557Sjimharris
120230557Sjimharris	if (prev_user_ioctl)
121230557Sjimharris		return (*prev_user_ioctl)(tp, cmd, data, td);
122230557Sjimharris	else
123230557Sjimharris		return ENOIOCTL;
124230557Sjimharris}
125230557Sjimharris
126230557Sjimharrisint
127230557Sjimharrisvesa_load_ioctl(void)
128230557Sjimharris{
129230557Sjimharris	if (prev_user_ioctl)
130230557Sjimharris		return EBUSY;
131230557Sjimharris	prev_user_ioctl = sc_user_ioctl;
132230557Sjimharris	sc_user_ioctl = vesa_ioctl;
133230557Sjimharris	return 0;
134230557Sjimharris}
135230557Sjimharris
136230557Sjimharrisint
137230557Sjimharrisvesa_unload_ioctl(void)
138230557Sjimharris{
139230557Sjimharris	if (sc_user_ioctl != vesa_ioctl)
140230557Sjimharris		return EBUSY;
141230557Sjimharris	sc_user_ioctl = prev_user_ioctl;
142230557Sjimharris	prev_user_ioctl = NULL;
143230557Sjimharris	return 0;
144230557Sjimharris}
145230557Sjimharris
146230557Sjimharris#endif /* VGA_NO_MODE_CHANGE */
147230557Sjimharris