xref: /freebsd/sys/dev/fb/fb.c (revision 7ac40f5f)
1617b9080SKazutaka YOKOTA /*-
2617b9080SKazutaka YOKOTA  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3617b9080SKazutaka YOKOTA  * All rights reserved.
4617b9080SKazutaka YOKOTA  *
5617b9080SKazutaka YOKOTA  * Redistribution and use in source and binary forms, with or without
6617b9080SKazutaka YOKOTA  * modification, are permitted provided that the following conditions
7617b9080SKazutaka YOKOTA  * are met:
8617b9080SKazutaka YOKOTA  * 1. Redistributions of source code must retain the above copyright
9617b9080SKazutaka YOKOTA  *    notice, this list of conditions and the following disclaimer as
10617b9080SKazutaka YOKOTA  *    the first lines of this file unmodified.
11617b9080SKazutaka YOKOTA  * 2. Redistributions in binary form must reproduce the above copyright
12617b9080SKazutaka YOKOTA  *    notice, this list of conditions and the following disclaimer in the
13617b9080SKazutaka YOKOTA  *    documentation and/or other materials provided with the distribution.
14617b9080SKazutaka YOKOTA  * 3. The name of the author may not be used to endorse or promote products
15617b9080SKazutaka YOKOTA  *    derived from this software without specific prior written permission.
16617b9080SKazutaka YOKOTA  *
17617b9080SKazutaka YOKOTA  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18617b9080SKazutaka YOKOTA  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19617b9080SKazutaka YOKOTA  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20617b9080SKazutaka YOKOTA  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21617b9080SKazutaka YOKOTA  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22617b9080SKazutaka YOKOTA  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23617b9080SKazutaka YOKOTA  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24617b9080SKazutaka YOKOTA  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25617b9080SKazutaka YOKOTA  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26617b9080SKazutaka YOKOTA  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27617b9080SKazutaka YOKOTA  *
28c3aac50fSPeter Wemm  * $FreeBSD$
29617b9080SKazutaka YOKOTA  */
30617b9080SKazutaka YOKOTA 
31617b9080SKazutaka YOKOTA #include "opt_fb.h"
32617b9080SKazutaka YOKOTA 
33617b9080SKazutaka YOKOTA #include <sys/param.h>
34617b9080SKazutaka YOKOTA #include <sys/systm.h>
35617b9080SKazutaka YOKOTA #include <sys/conf.h>
366e8394b8SKazutaka YOKOTA #include <sys/bus.h>
37617b9080SKazutaka YOKOTA #include <sys/kernel.h>
38617b9080SKazutaka YOKOTA #include <sys/malloc.h>
392b120974SPeter Wemm #include <sys/module.h>
406e8394b8SKazutaka YOKOTA #include <sys/uio.h>
416e8394b8SKazutaka YOKOTA #include <sys/fbio.h>
42f41325dbSPeter Wemm #include <sys/linker_set.h>
43617b9080SKazutaka YOKOTA 
446e8394b8SKazutaka YOKOTA #include <vm/vm.h>
456e8394b8SKazutaka YOKOTA #include <vm/pmap.h>
46617b9080SKazutaka YOKOTA 
47617b9080SKazutaka YOKOTA #include <dev/fb/fbreg.h>
48617b9080SKazutaka YOKOTA 
49f41325dbSPeter Wemm SET_DECLARE(videodriver_set, const video_driver_t);
50f41325dbSPeter Wemm 
51617b9080SKazutaka YOKOTA /* local arrays */
52617b9080SKazutaka YOKOTA 
53617b9080SKazutaka YOKOTA /*
54617b9080SKazutaka YOKOTA  * We need at least one entry each in order to initialize a video card
55617b9080SKazutaka YOKOTA  * for the kernel console.  The arrays will be increased dynamically
56617b9080SKazutaka YOKOTA  * when necessary.
57617b9080SKazutaka YOKOTA  */
58617b9080SKazutaka YOKOTA 
596e8394b8SKazutaka YOKOTA static int		vid_malloc;
60617b9080SKazutaka YOKOTA static int		adapters = 1;
6190500a9dSKazutaka YOKOTA static video_adapter_t	*adp_ini;
6290500a9dSKazutaka YOKOTA static video_adapter_t	**adapter = &adp_ini;
6390500a9dSKazutaka YOKOTA static video_switch_t	*vidsw_ini;
64617b9080SKazutaka YOKOTA        video_switch_t	**vidsw = &vidsw_ini;
6590500a9dSKazutaka YOKOTA 
6690500a9dSKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
676e8394b8SKazutaka YOKOTA static struct cdevsw	*vidcdevsw_ini;
686e8394b8SKazutaka YOKOTA static struct cdevsw	**vidcdevsw = &vidcdevsw_ini;
696e8394b8SKazutaka YOKOTA #endif
70617b9080SKazutaka YOKOTA 
71617b9080SKazutaka YOKOTA #define ARRAY_DELTA	4
72617b9080SKazutaka YOKOTA 
736e8394b8SKazutaka YOKOTA static int
74617b9080SKazutaka YOKOTA vid_realloc_array(void)
75617b9080SKazutaka YOKOTA {
76617b9080SKazutaka YOKOTA 	video_adapter_t **new_adp;
77617b9080SKazutaka YOKOTA 	video_switch_t **new_vidsw;
786e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
79617b9080SKazutaka YOKOTA 	struct cdevsw **new_cdevsw;
806e8394b8SKazutaka YOKOTA #endif
81617b9080SKazutaka YOKOTA 	int newsize;
82617b9080SKazutaka YOKOTA 	int s;
83617b9080SKazutaka YOKOTA 
846e8394b8SKazutaka YOKOTA 	if (!vid_malloc)
856e8394b8SKazutaka YOKOTA 		return ENOMEM;
866e8394b8SKazutaka YOKOTA 
87617b9080SKazutaka YOKOTA 	s = spltty();
88617b9080SKazutaka YOKOTA 	newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
89a163d034SWarner Losh 	new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK | M_ZERO);
907cc0979fSDavid Malone 	new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF,
91a163d034SWarner Losh 	    M_WAITOK | M_ZERO);
926e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
937cc0979fSDavid Malone 	new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF,
94a163d034SWarner Losh 	    M_WAITOK | M_ZERO);
956e8394b8SKazutaka YOKOTA #endif
96617b9080SKazutaka YOKOTA 	bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
97617b9080SKazutaka YOKOTA 	bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
986e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
99617b9080SKazutaka YOKOTA 	bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
1006e8394b8SKazutaka YOKOTA #endif
101617b9080SKazutaka YOKOTA 	if (adapters > 1) {
102617b9080SKazutaka YOKOTA 		free(adapter, M_DEVBUF);
103617b9080SKazutaka YOKOTA 		free(vidsw, M_DEVBUF);
1046e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
105617b9080SKazutaka YOKOTA 		free(vidcdevsw, M_DEVBUF);
1066e8394b8SKazutaka YOKOTA #endif
107617b9080SKazutaka YOKOTA 	}
108617b9080SKazutaka YOKOTA 	adapter = new_adp;
109617b9080SKazutaka YOKOTA 	vidsw = new_vidsw;
1106e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
111617b9080SKazutaka YOKOTA 	vidcdevsw = new_cdevsw;
1126e8394b8SKazutaka YOKOTA #endif
113617b9080SKazutaka YOKOTA 	adapters = newsize;
114617b9080SKazutaka YOKOTA 	splx(s);
115617b9080SKazutaka YOKOTA 
116617b9080SKazutaka YOKOTA 	if (bootverbose)
117617b9080SKazutaka YOKOTA 		printf("fb: new array size %d\n", adapters);
1186e8394b8SKazutaka YOKOTA 
1196e8394b8SKazutaka YOKOTA 	return 0;
120617b9080SKazutaka YOKOTA }
121617b9080SKazutaka YOKOTA 
1226e8394b8SKazutaka YOKOTA static void
1236e8394b8SKazutaka YOKOTA vid_malloc_init(void *arg)
1246e8394b8SKazutaka YOKOTA {
1256e8394b8SKazutaka YOKOTA 	vid_malloc = TRUE;
1266e8394b8SKazutaka YOKOTA }
1276e8394b8SKazutaka YOKOTA 
1286e8394b8SKazutaka YOKOTA SYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
12990500a9dSKazutaka YOKOTA 
130617b9080SKazutaka YOKOTA /*
131617b9080SKazutaka YOKOTA  * Low-level frame buffer driver functions
132617b9080SKazutaka YOKOTA  * frame buffer subdrivers, such as the VGA driver, call these functions
133617b9080SKazutaka YOKOTA  * to initialize the video_adapter structure and register it to the virtual
134617b9080SKazutaka YOKOTA  * frame buffer driver `fb'.
135617b9080SKazutaka YOKOTA  */
136617b9080SKazutaka YOKOTA 
137617b9080SKazutaka YOKOTA /* initialize the video_adapter_t structure */
138617b9080SKazutaka YOKOTA void
139617b9080SKazutaka YOKOTA vid_init_struct(video_adapter_t *adp, char *name, int type, int unit)
140617b9080SKazutaka YOKOTA {
141617b9080SKazutaka YOKOTA 	adp->va_flags = 0;
142617b9080SKazutaka YOKOTA 	adp->va_name = name;
143617b9080SKazutaka YOKOTA 	adp->va_type = type;
144617b9080SKazutaka YOKOTA 	adp->va_unit = unit;
145617b9080SKazutaka YOKOTA }
146617b9080SKazutaka YOKOTA 
147617b9080SKazutaka YOKOTA /* Register a video adapter */
148617b9080SKazutaka YOKOTA int
149617b9080SKazutaka YOKOTA vid_register(video_adapter_t *adp)
150617b9080SKazutaka YOKOTA {
1516e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
1526e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
153617b9080SKazutaka YOKOTA 	int index;
154617b9080SKazutaka YOKOTA 
155617b9080SKazutaka YOKOTA 	for (index = 0; index < adapters; ++index) {
156617b9080SKazutaka YOKOTA 		if (adapter[index] == NULL)
157617b9080SKazutaka YOKOTA 			break;
158617b9080SKazutaka YOKOTA 	}
1596e8394b8SKazutaka YOKOTA 	if (index >= adapters) {
1606e8394b8SKazutaka YOKOTA 		if (vid_realloc_array())
161617b9080SKazutaka YOKOTA 			return -1;
1626e8394b8SKazutaka YOKOTA 	}
163617b9080SKazutaka YOKOTA 
164617b9080SKazutaka YOKOTA 	adp->va_index = index;
165617b9080SKazutaka YOKOTA 	adp->va_token = NULL;
166f41325dbSPeter Wemm 	SET_FOREACH(list, videodriver_set) {
167f41325dbSPeter Wemm 		p = *list;
168617b9080SKazutaka YOKOTA 		if (strcmp(p->name, adp->va_name) == 0) {
169617b9080SKazutaka YOKOTA 			adapter[index] = adp;
170617b9080SKazutaka YOKOTA 			vidsw[index] = p->vidsw;
171617b9080SKazutaka YOKOTA 			return index;
172617b9080SKazutaka YOKOTA 		}
173617b9080SKazutaka YOKOTA 	}
174617b9080SKazutaka YOKOTA 
175617b9080SKazutaka YOKOTA 	return -1;
176617b9080SKazutaka YOKOTA }
177617b9080SKazutaka YOKOTA 
178617b9080SKazutaka YOKOTA int
179617b9080SKazutaka YOKOTA vid_unregister(video_adapter_t *adp)
180617b9080SKazutaka YOKOTA {
181617b9080SKazutaka YOKOTA 	if ((adp->va_index < 0) || (adp->va_index >= adapters))
182617b9080SKazutaka YOKOTA 		return ENOENT;
183617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
184617b9080SKazutaka YOKOTA 		return ENOENT;
185617b9080SKazutaka YOKOTA 
186617b9080SKazutaka YOKOTA 	adapter[adp->va_index] = NULL;
187617b9080SKazutaka YOKOTA 	vidsw[adp->va_index] = NULL;
188617b9080SKazutaka YOKOTA 	return 0;
189617b9080SKazutaka YOKOTA }
190617b9080SKazutaka YOKOTA 
191617b9080SKazutaka YOKOTA /* Get video I/O function table */
192617b9080SKazutaka YOKOTA video_switch_t
193617b9080SKazutaka YOKOTA *vid_get_switch(char *name)
194617b9080SKazutaka YOKOTA {
1956e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
1966e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
197617b9080SKazutaka YOKOTA 
198f41325dbSPeter Wemm 	SET_FOREACH(list, videodriver_set) {
199f41325dbSPeter Wemm 		p = *list;
200617b9080SKazutaka YOKOTA 		if (strcmp(p->name, name) == 0)
201617b9080SKazutaka YOKOTA 			return p->vidsw;
202617b9080SKazutaka YOKOTA 	}
203617b9080SKazutaka YOKOTA 
204617b9080SKazutaka YOKOTA 	return NULL;
205617b9080SKazutaka YOKOTA }
206617b9080SKazutaka YOKOTA 
207617b9080SKazutaka YOKOTA /*
208617b9080SKazutaka YOKOTA  * Video card client functions
209617b9080SKazutaka YOKOTA  * Video card clients, such as the console driver `syscons' and the frame
210617b9080SKazutaka YOKOTA  * buffer cdev driver, use these functions to claim and release a card for
211617b9080SKazutaka YOKOTA  * exclusive use.
212617b9080SKazutaka YOKOTA  */
213617b9080SKazutaka YOKOTA 
214617b9080SKazutaka YOKOTA /* find the video card specified by a driver name and a unit number */
215617b9080SKazutaka YOKOTA int
216617b9080SKazutaka YOKOTA vid_find_adapter(char *driver, int unit)
217617b9080SKazutaka YOKOTA {
218617b9080SKazutaka YOKOTA 	int i;
219617b9080SKazutaka YOKOTA 
220617b9080SKazutaka YOKOTA 	for (i = 0; i < adapters; ++i) {
221617b9080SKazutaka YOKOTA 		if (adapter[i] == NULL)
222617b9080SKazutaka YOKOTA 			continue;
223617b9080SKazutaka YOKOTA 		if (strcmp("*", driver) && strcmp(adapter[i]->va_name, driver))
224617b9080SKazutaka YOKOTA 			continue;
225617b9080SKazutaka YOKOTA 		if ((unit != -1) && (adapter[i]->va_unit != unit))
226617b9080SKazutaka YOKOTA 			continue;
227617b9080SKazutaka YOKOTA 		return i;
228617b9080SKazutaka YOKOTA 	}
229617b9080SKazutaka YOKOTA 	return -1;
230617b9080SKazutaka YOKOTA }
231617b9080SKazutaka YOKOTA 
232617b9080SKazutaka YOKOTA /* allocate a video card */
233617b9080SKazutaka YOKOTA int
234617b9080SKazutaka YOKOTA vid_allocate(char *driver, int unit, void *id)
235617b9080SKazutaka YOKOTA {
236617b9080SKazutaka YOKOTA 	int index;
237617b9080SKazutaka YOKOTA 	int s;
238617b9080SKazutaka YOKOTA 
239617b9080SKazutaka YOKOTA 	s = spltty();
240617b9080SKazutaka YOKOTA 	index = vid_find_adapter(driver, unit);
241617b9080SKazutaka YOKOTA 	if (index >= 0) {
242617b9080SKazutaka YOKOTA 		if (adapter[index]->va_token) {
243617b9080SKazutaka YOKOTA 			splx(s);
244617b9080SKazutaka YOKOTA 			return -1;
245617b9080SKazutaka YOKOTA 		}
246617b9080SKazutaka YOKOTA 		adapter[index]->va_token = id;
247617b9080SKazutaka YOKOTA 	}
248617b9080SKazutaka YOKOTA 	splx(s);
249617b9080SKazutaka YOKOTA 	return index;
250617b9080SKazutaka YOKOTA }
251617b9080SKazutaka YOKOTA 
252617b9080SKazutaka YOKOTA int
253617b9080SKazutaka YOKOTA vid_release(video_adapter_t *adp, void *id)
254617b9080SKazutaka YOKOTA {
255617b9080SKazutaka YOKOTA 	int error;
256617b9080SKazutaka YOKOTA 	int s;
257617b9080SKazutaka YOKOTA 
258617b9080SKazutaka YOKOTA 	s = spltty();
259617b9080SKazutaka YOKOTA 	if (adp->va_token == NULL) {
260617b9080SKazutaka YOKOTA 		error = EINVAL;
261617b9080SKazutaka YOKOTA 	} else if (adp->va_token != id) {
262617b9080SKazutaka YOKOTA 		error = EPERM;
263617b9080SKazutaka YOKOTA 	} else {
264617b9080SKazutaka YOKOTA 		adp->va_token = NULL;
265617b9080SKazutaka YOKOTA 		error = 0;
266617b9080SKazutaka YOKOTA 	}
267617b9080SKazutaka YOKOTA 	splx(s);
268617b9080SKazutaka YOKOTA 	return error;
269617b9080SKazutaka YOKOTA }
270617b9080SKazutaka YOKOTA 
271617b9080SKazutaka YOKOTA /* Get a video adapter structure */
272617b9080SKazutaka YOKOTA video_adapter_t
273617b9080SKazutaka YOKOTA *vid_get_adapter(int index)
274617b9080SKazutaka YOKOTA {
275617b9080SKazutaka YOKOTA 	if ((index < 0) || (index >= adapters))
276617b9080SKazutaka YOKOTA 		return NULL;
277617b9080SKazutaka YOKOTA 	return adapter[index];
278617b9080SKazutaka YOKOTA }
279617b9080SKazutaka YOKOTA 
280617b9080SKazutaka YOKOTA /* Configure drivers: this is a backdoor for the console driver XXX */
281617b9080SKazutaka YOKOTA int
282617b9080SKazutaka YOKOTA vid_configure(int flags)
283617b9080SKazutaka YOKOTA {
2846e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
2856e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
286617b9080SKazutaka YOKOTA 
287f41325dbSPeter Wemm 	SET_FOREACH(list, videodriver_set) {
288f41325dbSPeter Wemm 		p = *list;
289617b9080SKazutaka YOKOTA 		if (p->configure != NULL)
290617b9080SKazutaka YOKOTA 			(*p->configure)(flags);
291617b9080SKazutaka YOKOTA 	}
292617b9080SKazutaka YOKOTA 
293617b9080SKazutaka YOKOTA 	return 0;
294617b9080SKazutaka YOKOTA }
295617b9080SKazutaka YOKOTA 
296617b9080SKazutaka YOKOTA /*
297617b9080SKazutaka YOKOTA  * Virtual frame buffer cdev driver functions
298617b9080SKazutaka YOKOTA  * The virtual frame buffer driver dispatches driver functions to
299617b9080SKazutaka YOKOTA  * appropriate subdrivers.
300617b9080SKazutaka YOKOTA  */
301617b9080SKazutaka YOKOTA 
3026e8394b8SKazutaka YOKOTA #define FB_DRIVER_NAME	"fb"
303617b9080SKazutaka YOKOTA 
304617b9080SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
305617b9080SKazutaka YOKOTA 
3066e8394b8SKazutaka YOKOTA #if experimental
3076e8394b8SKazutaka YOKOTA 
3086e8394b8SKazutaka YOKOTA static devclass_t	fb_devclass;
3096e8394b8SKazutaka YOKOTA 
3106e8394b8SKazutaka YOKOTA static int		fbprobe(device_t dev);
3116e8394b8SKazutaka YOKOTA static int		fbattach(device_t dev);
3126e8394b8SKazutaka YOKOTA 
3136e8394b8SKazutaka YOKOTA static device_method_t fb_methods[] = {
3146e8394b8SKazutaka YOKOTA 	DEVMETHOD(device_probe,		fbprobe),
3156e8394b8SKazutaka YOKOTA 	DEVMETHOD(device_attach,	fbattach),
3166e8394b8SKazutaka YOKOTA 
3176e8394b8SKazutaka YOKOTA 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
3186e8394b8SKazutaka YOKOTA 	{ 0, 0 }
3196e8394b8SKazutaka YOKOTA };
3206e8394b8SKazutaka YOKOTA 
3216e8394b8SKazutaka YOKOTA static driver_t fb_driver = {
3226e8394b8SKazutaka YOKOTA 	FB_DRIVER_NAME,
3236e8394b8SKazutaka YOKOTA 	fb_methods,
3246e8394b8SKazutaka YOKOTA 	0,
3256e8394b8SKazutaka YOKOTA };
3266e8394b8SKazutaka YOKOTA 
3276e8394b8SKazutaka YOKOTA static int
3286e8394b8SKazutaka YOKOTA fbprobe(device_t dev)
3296e8394b8SKazutaka YOKOTA {
3306e8394b8SKazutaka YOKOTA 	int unit;
3316e8394b8SKazutaka YOKOTA 
3326e8394b8SKazutaka YOKOTA 	unit = device_get_unit(dev);
3336e8394b8SKazutaka YOKOTA 	if (unit >= adapters)
3346e8394b8SKazutaka YOKOTA 		return ENXIO;
3356e8394b8SKazutaka YOKOTA 	if (adapter[unit] == NULL)
3366e8394b8SKazutaka YOKOTA 		return ENXIO;
3376e8394b8SKazutaka YOKOTA 
3386e8394b8SKazutaka YOKOTA 	device_set_desc(dev, "generic frame buffer");
3396e8394b8SKazutaka YOKOTA 	return 0;
3406e8394b8SKazutaka YOKOTA }
3416e8394b8SKazutaka YOKOTA 
3426e8394b8SKazutaka YOKOTA static int
3436e8394b8SKazutaka YOKOTA fbattach(device_t dev)
3446e8394b8SKazutaka YOKOTA {
3456e8394b8SKazutaka YOKOTA 	printf("fbattach: about to attach children\n");
3466e8394b8SKazutaka YOKOTA 	bus_generic_attach(dev);
3476e8394b8SKazutaka YOKOTA 	return 0;
3486e8394b8SKazutaka YOKOTA }
3496e8394b8SKazutaka YOKOTA 
3506e8394b8SKazutaka YOKOTA #endif /* experimental */
3516e8394b8SKazutaka YOKOTA 
352617b9080SKazutaka YOKOTA #define FB_UNIT(dev)	minor(dev)
353617b9080SKazutaka YOKOTA #define FB_MKMINOR(unit) (u)
354617b9080SKazutaka YOKOTA 
3556d473442SPoul-Henning Kamp #if experimental
356617b9080SKazutaka YOKOTA static d_open_t		fbopen;
357617b9080SKazutaka YOKOTA static d_close_t	fbclose;
3586e8394b8SKazutaka YOKOTA static d_read_t		fbread;
3596e8394b8SKazutaka YOKOTA static d_write_t	fbwrite;
360617b9080SKazutaka YOKOTA static d_ioctl_t	fbioctl;
361617b9080SKazutaka YOKOTA static d_mmap_t		fbmmap;
362617b9080SKazutaka YOKOTA 
3636e8394b8SKazutaka YOKOTA #define CDEV_MAJOR	123	/* XXX */
364617b9080SKazutaka YOKOTA 
365617b9080SKazutaka YOKOTA static struct cdevsw fb_cdevsw = {
3667ac40f5fSPoul-Henning Kamp 	.d_open =	fbopen,
3677ac40f5fSPoul-Henning Kamp 	.d_close =	fbclose,
3687ac40f5fSPoul-Henning Kamp 	.d_read =	fbread,
3697ac40f5fSPoul-Henning Kamp 	.d_write =	fbwrite,
3707ac40f5fSPoul-Henning Kamp 	.d_ioctl =	fbioctl,
3717ac40f5fSPoul-Henning Kamp 	.d_mmap =	fbmmap,
3727ac40f5fSPoul-Henning Kamp 	.d_name =	FB_DRIVER_NAME,
3737ac40f5fSPoul-Henning Kamp 	.d_maj =	CDEV_MAJOR,
374617b9080SKazutaka YOKOTA };
3756d473442SPoul-Henning Kamp #endif
376617b9080SKazutaka YOKOTA 
3772b120974SPeter Wemm 
3782b120974SPeter Wemm static int
3792b120974SPeter Wemm fb_modevent(module_t mod, int type, void *data)
380617b9080SKazutaka YOKOTA {
381617b9080SKazutaka YOKOTA 
3822b120974SPeter Wemm 	switch (type) {
3832b120974SPeter Wemm 	case MOD_LOAD:
3842b120974SPeter Wemm 		break;
3852b120974SPeter Wemm 	case MOD_UNLOAD:
3862b120974SPeter Wemm 		printf("fb module unload - not possible for this module type\n");
3872b120974SPeter Wemm 		return EINVAL;
388617b9080SKazutaka YOKOTA 	}
3892b120974SPeter Wemm 	return 0;
390617b9080SKazutaka YOKOTA }
391617b9080SKazutaka YOKOTA 
3922b120974SPeter Wemm static moduledata_t fb_mod = {
3932b120974SPeter Wemm 	"fb",
3942b120974SPeter Wemm 	fb_modevent,
3952b120974SPeter Wemm 	NULL
3962b120974SPeter Wemm };
3972b120974SPeter Wemm 
3982b120974SPeter Wemm DECLARE_MODULE(fb, fb_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
399617b9080SKazutaka YOKOTA 
400617b9080SKazutaka YOKOTA int
4016e8394b8SKazutaka YOKOTA fb_attach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
402617b9080SKazutaka YOKOTA {
403617b9080SKazutaka YOKOTA 	int s;
404617b9080SKazutaka YOKOTA 
405617b9080SKazutaka YOKOTA 	if (adp->va_index >= adapters)
406617b9080SKazutaka YOKOTA 		return EINVAL;
407617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
408617b9080SKazutaka YOKOTA 		return EINVAL;
409617b9080SKazutaka YOKOTA 
410617b9080SKazutaka YOKOTA 	s = spltty();
411617b9080SKazutaka YOKOTA 	adp->va_minor = minor(dev);
412617b9080SKazutaka YOKOTA 	vidcdevsw[adp->va_index] = cdevsw;
413617b9080SKazutaka YOKOTA 	splx(s);
414617b9080SKazutaka YOKOTA 
415617b9080SKazutaka YOKOTA 	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
416617b9080SKazutaka YOKOTA 	return 0;
417617b9080SKazutaka YOKOTA }
418617b9080SKazutaka YOKOTA 
419617b9080SKazutaka YOKOTA int
4206e8394b8SKazutaka YOKOTA fb_detach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
421617b9080SKazutaka YOKOTA {
422617b9080SKazutaka YOKOTA 	int s;
423617b9080SKazutaka YOKOTA 
424617b9080SKazutaka YOKOTA 	if (adp->va_index >= adapters)
425617b9080SKazutaka YOKOTA 		return EINVAL;
426617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
427617b9080SKazutaka YOKOTA 		return EINVAL;
428617b9080SKazutaka YOKOTA 	if (vidcdevsw[adp->va_index] != cdevsw)
429617b9080SKazutaka YOKOTA 		return EINVAL;
430617b9080SKazutaka YOKOTA 
431617b9080SKazutaka YOKOTA 	s = spltty();
432617b9080SKazutaka YOKOTA 	vidcdevsw[adp->va_index] = NULL;
433617b9080SKazutaka YOKOTA 	splx(s);
434617b9080SKazutaka YOKOTA 	return 0;
435617b9080SKazutaka YOKOTA }
436617b9080SKazutaka YOKOTA 
4376d473442SPoul-Henning Kamp #if experimental
4386e8394b8SKazutaka YOKOTA static int
439b40ce416SJulian Elischer fbopen(dev_t dev, int flag, int mode, struct thread *td)
4406e8394b8SKazutaka YOKOTA {
4416e8394b8SKazutaka YOKOTA 	int unit;
4426e8394b8SKazutaka YOKOTA 
4436e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4446e8394b8SKazutaka YOKOTA 	if (unit >= adapters)
4456e8394b8SKazutaka YOKOTA 		return ENXIO;
4466e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4476e8394b8SKazutaka YOKOTA 		return ENXIO;
4486e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_open)(makedev(0, adapter[unit]->va_minor),
449b40ce416SJulian Elischer 					  flag, mode, td);
4506e8394b8SKazutaka YOKOTA }
4516e8394b8SKazutaka YOKOTA 
4526e8394b8SKazutaka YOKOTA static int
453b40ce416SJulian Elischer fbclose(dev_t dev, int flag, int mode, struct thread *td)
4546e8394b8SKazutaka YOKOTA {
4556e8394b8SKazutaka YOKOTA 	int unit;
4566e8394b8SKazutaka YOKOTA 
4576e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4586e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4596e8394b8SKazutaka YOKOTA 		return ENXIO;
4606e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_close)(makedev(0, adapter[unit]->va_minor),
461b40ce416SJulian Elischer 					   flag, mode, td);
4626e8394b8SKazutaka YOKOTA }
4636e8394b8SKazutaka YOKOTA 
4646e8394b8SKazutaka YOKOTA static int
4656e8394b8SKazutaka YOKOTA fbread(dev_t dev, struct uio *uio, int flag)
4666e8394b8SKazutaka YOKOTA {
4676e8394b8SKazutaka YOKOTA 	int unit;
4686e8394b8SKazutaka YOKOTA 
4696e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4706e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4716e8394b8SKazutaka YOKOTA 		return ENXIO;
4726e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_read)(makedev(0, adapter[unit]->va_minor),
4736e8394b8SKazutaka YOKOTA 					  uio, flag);
4746e8394b8SKazutaka YOKOTA }
4756e8394b8SKazutaka YOKOTA 
4766e8394b8SKazutaka YOKOTA static int
4776e8394b8SKazutaka YOKOTA fbwrite(dev_t dev, struct uio *uio, int flag)
4786e8394b8SKazutaka YOKOTA {
4796e8394b8SKazutaka YOKOTA 	int unit;
4806e8394b8SKazutaka YOKOTA 
4816e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4826e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4836e8394b8SKazutaka YOKOTA 		return ENXIO;
4846e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_write)(makedev(0, adapter[unit]->va_minor),
4856e8394b8SKazutaka YOKOTA 					   uio, flag);
4866e8394b8SKazutaka YOKOTA }
4876e8394b8SKazutaka YOKOTA 
4886e8394b8SKazutaka YOKOTA static int
489b40ce416SJulian Elischer fbioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
4906e8394b8SKazutaka YOKOTA {
4916e8394b8SKazutaka YOKOTA 	int unit;
4926e8394b8SKazutaka YOKOTA 
4936e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4946e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4956e8394b8SKazutaka YOKOTA 		return ENXIO;
4966e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_ioctl)(makedev(0, adapter[unit]->va_minor),
497b40ce416SJulian Elischer 					   cmd, arg, flag, td);
4986e8394b8SKazutaka YOKOTA }
4996e8394b8SKazutaka YOKOTA 
5006e8394b8SKazutaka YOKOTA static int
50107159f9cSMaxime Henrion fbmmap(dev_t dev, vm_offset_t offset, vm_offset_t *paddr, int nprot)
5026e8394b8SKazutaka YOKOTA {
5036e8394b8SKazutaka YOKOTA 	int unit;
5046e8394b8SKazutaka YOKOTA 
5056e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
5066e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
5076e8394b8SKazutaka YOKOTA 		return ENXIO;
5086e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_mmap)(makedev(0, adapter[unit]->va_minor),
50907159f9cSMaxime Henrion 					  offset, paddr, nprot);
5106e8394b8SKazutaka YOKOTA }
5116e8394b8SKazutaka YOKOTA 
51203016f42SPoul-Henning Kamp DEV_DRIVER_MODULE(fb, ???, fb_driver, fb_devclass, fb_cdevsw, 0, 0);
5136e8394b8SKazutaka YOKOTA #endif
5146e8394b8SKazutaka YOKOTA 
5156e8394b8SKazutaka YOKOTA /*
5166e8394b8SKazutaka YOKOTA  * Generic frame buffer cdev driver functions
5176e8394b8SKazutaka YOKOTA  * Frame buffer subdrivers may call these functions to implement common
5186e8394b8SKazutaka YOKOTA  * driver functions.
5196e8394b8SKazutaka YOKOTA  */
5206e8394b8SKazutaka YOKOTA 
5216e8394b8SKazutaka YOKOTA int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
522b40ce416SJulian Elischer 	      struct thread *td)
5236e8394b8SKazutaka YOKOTA {
5246e8394b8SKazutaka YOKOTA 	int s;
5256e8394b8SKazutaka YOKOTA 
5266e8394b8SKazutaka YOKOTA 	s = spltty();
5276e8394b8SKazutaka YOKOTA 	if (!(sc->gfb_flags & FB_OPEN))
5286e8394b8SKazutaka YOKOTA 		sc->gfb_flags |= FB_OPEN;
5296e8394b8SKazutaka YOKOTA 	splx(s);
5306e8394b8SKazutaka YOKOTA 	return 0;
5316e8394b8SKazutaka YOKOTA }
5326e8394b8SKazutaka YOKOTA 
5336e8394b8SKazutaka YOKOTA int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
534b40ce416SJulian Elischer 	       struct thread *td)
5356e8394b8SKazutaka YOKOTA {
5366e8394b8SKazutaka YOKOTA 	int s;
5376e8394b8SKazutaka YOKOTA 
5386e8394b8SKazutaka YOKOTA 	s = spltty();
5396e8394b8SKazutaka YOKOTA 	sc->gfb_flags &= ~FB_OPEN;
5406e8394b8SKazutaka YOKOTA 	splx(s);
5416e8394b8SKazutaka YOKOTA 	return 0;
5426e8394b8SKazutaka YOKOTA }
5436e8394b8SKazutaka YOKOTA 
5446e8394b8SKazutaka YOKOTA int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
5456e8394b8SKazutaka YOKOTA 	      int flag)
5466e8394b8SKazutaka YOKOTA {
5476e8394b8SKazutaka YOKOTA 	int size;
5486e8394b8SKazutaka YOKOTA 	int offset;
5496e8394b8SKazutaka YOKOTA 	int error;
5506e8394b8SKazutaka YOKOTA 	int len;
5516e8394b8SKazutaka YOKOTA 
5526e8394b8SKazutaka YOKOTA 	error = 0;
5536e8394b8SKazutaka YOKOTA 	size = adp->va_buffer_size/adp->va_info.vi_planes;
5546e8394b8SKazutaka YOKOTA 	while (uio->uio_resid > 0) {
5556e8394b8SKazutaka YOKOTA 		if (uio->uio_offset >= size)
5566e8394b8SKazutaka YOKOTA 			break;
5576e8394b8SKazutaka YOKOTA 		offset = uio->uio_offset%adp->va_window_size;
5586e8394b8SKazutaka YOKOTA 		len = imin(uio->uio_resid, size - uio->uio_offset);
5596e8394b8SKazutaka YOKOTA 		len = imin(len, adp->va_window_size - offset);
5606e8394b8SKazutaka YOKOTA 		if (len <= 0)
5616e8394b8SKazutaka YOKOTA 			break;
5626e8394b8SKazutaka YOKOTA 		(*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
5636e8394b8SKazutaka YOKOTA 		error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
5646e8394b8SKazutaka YOKOTA 		if (error)
5656e8394b8SKazutaka YOKOTA 			break;
5666e8394b8SKazutaka YOKOTA 	}
5676e8394b8SKazutaka YOKOTA 	return error;
5686e8394b8SKazutaka YOKOTA }
5696e8394b8SKazutaka YOKOTA 
5706e8394b8SKazutaka YOKOTA int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
5716e8394b8SKazutaka YOKOTA 	       int flag)
5726e8394b8SKazutaka YOKOTA {
5736e8394b8SKazutaka YOKOTA 	return ENODEV;
5746e8394b8SKazutaka YOKOTA }
5756e8394b8SKazutaka YOKOTA 
5766e8394b8SKazutaka YOKOTA int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
577b40ce416SJulian Elischer 	       caddr_t arg, int flag, struct thread *td)
5786e8394b8SKazutaka YOKOTA {
5796e8394b8SKazutaka YOKOTA 	int error;
5806e8394b8SKazutaka YOKOTA 
5816e8394b8SKazutaka YOKOTA 	if (adp == NULL)	/* XXX */
5826e8394b8SKazutaka YOKOTA 		return ENXIO;
5836e8394b8SKazutaka YOKOTA 	error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
5846e8394b8SKazutaka YOKOTA 	if (error == ENOIOCTL)
5856e8394b8SKazutaka YOKOTA 		error = ENODEV;
5866e8394b8SKazutaka YOKOTA 	return error;
5876e8394b8SKazutaka YOKOTA }
5886e8394b8SKazutaka YOKOTA 
5896e8394b8SKazutaka YOKOTA int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
59007159f9cSMaxime Henrion 	      vm_offset_t *paddr, int prot)
5916e8394b8SKazutaka YOKOTA {
59207159f9cSMaxime Henrion 	return (*vidsw[adp->va_index]->mmap)(adp, offset, paddr, prot);
5936e8394b8SKazutaka YOKOTA }
5946e8394b8SKazutaka YOKOTA 
595617b9080SKazutaka YOKOTA #endif /* FB_INSTALL_CDEV */
596617b9080SKazutaka YOKOTA 
597617b9080SKazutaka YOKOTA static char
598617b9080SKazutaka YOKOTA *adapter_name(int type)
599617b9080SKazutaka YOKOTA {
600617b9080SKazutaka YOKOTA     static struct {
601617b9080SKazutaka YOKOTA 	int type;
602617b9080SKazutaka YOKOTA 	char *name;
603617b9080SKazutaka YOKOTA     } names[] = {
604617b9080SKazutaka YOKOTA 	{ KD_MONO,	"MDA" },
605617b9080SKazutaka YOKOTA 	{ KD_HERCULES,	"Hercules" },
606617b9080SKazutaka YOKOTA 	{ KD_CGA,	"CGA" },
607617b9080SKazutaka YOKOTA 	{ KD_EGA,	"EGA" },
608617b9080SKazutaka YOKOTA 	{ KD_VGA,	"VGA" },
609617b9080SKazutaka YOKOTA 	{ KD_PC98,	"PC-98x1" },
6106e8394b8SKazutaka YOKOTA 	{ KD_TGA,	"TGA" },
611617b9080SKazutaka YOKOTA 	{ -1,		"Unknown" },
612617b9080SKazutaka YOKOTA     };
613617b9080SKazutaka YOKOTA     int i;
614617b9080SKazutaka YOKOTA 
615617b9080SKazutaka YOKOTA     for (i = 0; names[i].type != -1; ++i)
616617b9080SKazutaka YOKOTA 	if (names[i].type == type)
617617b9080SKazutaka YOKOTA 	    break;
618617b9080SKazutaka YOKOTA     return names[i].name;
619617b9080SKazutaka YOKOTA }
620617b9080SKazutaka YOKOTA 
6216e8394b8SKazutaka YOKOTA /*
6226e8394b8SKazutaka YOKOTA  * Generic low-level frame buffer functions
6236e8394b8SKazutaka YOKOTA  * The low-level functions in the frame buffer subdriver may use these
6246e8394b8SKazutaka YOKOTA  * functions.
6256e8394b8SKazutaka YOKOTA  */
6266e8394b8SKazutaka YOKOTA 
627617b9080SKazutaka YOKOTA void
628617b9080SKazutaka YOKOTA fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
629617b9080SKazutaka YOKOTA {
630617b9080SKazutaka YOKOTA     if (level <= 0)
631617b9080SKazutaka YOKOTA 	return;
632617b9080SKazutaka YOKOTA 
633617b9080SKazutaka YOKOTA     printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
6346e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
635617b9080SKazutaka YOKOTA 	   adapter_name(adp->va_type), adp->va_type, adp->va_flags);
6360301e9c8SDavid E. O'Brien     printf("%s%d: port:0x%lx-0x%lx, crtc:0x%lx, mem:0x%lx 0x%x\n",
6370301e9c8SDavid E. O'Brien 	   FB_DRIVER_NAME, adp->va_index, (u_long)adp->va_io_base,
6380301e9c8SDavid E. O'Brien 	   (u_long)adp->va_io_base + adp->va_io_size - 1,
6390301e9c8SDavid E. O'Brien 	   (u_long)adp->va_crtc_addr, (u_long)adp->va_mem_base,
6400301e9c8SDavid E. O'Brien 	   adp->va_mem_size);
641617b9080SKazutaka YOKOTA     printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
6426e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index,
643617b9080SKazutaka YOKOTA 	   adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
6446e8394b8SKazutaka YOKOTA     printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
6456e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index,
6466e8394b8SKazutaka YOKOTA 	   (void *)adp->va_window, (int)adp->va_window_size/1024,
6476e8394b8SKazutaka YOKOTA 	   (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
648f359876fSKazutaka YOKOTA 	   (int)adp->va_buffer_size/1024);
649617b9080SKazutaka YOKOTA }
650617b9080SKazutaka YOKOTA 
651617b9080SKazutaka YOKOTA void
652617b9080SKazutaka YOKOTA fb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
653617b9080SKazutaka YOKOTA 		  int level)
654617b9080SKazutaka YOKOTA {
655617b9080SKazutaka YOKOTA     if (level <= 0)
656617b9080SKazutaka YOKOTA 	return;
657617b9080SKazutaka YOKOTA 
658617b9080SKazutaka YOKOTA     printf("%s%d: %s, mode:%d, flags:0x%x ",
659617b9080SKazutaka YOKOTA 	   driver, adp->va_unit, adp->va_name, info->vi_mode, info->vi_flags);
660617b9080SKazutaka YOKOTA     if (info->vi_flags & V_INFO_GRAPHICS)
661617b9080SKazutaka YOKOTA 	printf("G %dx%dx%d, %d plane(s), font:%dx%d, ",
662617b9080SKazutaka YOKOTA 	       info->vi_width, info->vi_height,
663617b9080SKazutaka YOKOTA 	       info->vi_depth, info->vi_planes,
664617b9080SKazutaka YOKOTA 	       info->vi_cwidth, info->vi_cheight);
665617b9080SKazutaka YOKOTA     else
666617b9080SKazutaka YOKOTA 	printf("T %dx%d, font:%dx%d, ",
667617b9080SKazutaka YOKOTA 	       info->vi_width, info->vi_height,
668617b9080SKazutaka YOKOTA 	       info->vi_cwidth, info->vi_cheight);
6690301e9c8SDavid E. O'Brien     printf("win:0x%lx\n", (u_long)info->vi_window);
670617b9080SKazutaka YOKOTA }
6716e8394b8SKazutaka YOKOTA 
6726e8394b8SKazutaka YOKOTA int
6736e8394b8SKazutaka YOKOTA fb_type(int adp_type)
6746e8394b8SKazutaka YOKOTA {
6756e8394b8SKazutaka YOKOTA 	static struct {
6766e8394b8SKazutaka YOKOTA 		int	fb_type;
6776e8394b8SKazutaka YOKOTA 		int	va_type;
6786e8394b8SKazutaka YOKOTA 	} types[] = {
6796e8394b8SKazutaka YOKOTA 		{ FBTYPE_MDA,		KD_MONO },
6806e8394b8SKazutaka YOKOTA 		{ FBTYPE_HERCULES,	KD_HERCULES },
6816e8394b8SKazutaka YOKOTA 		{ FBTYPE_CGA,		KD_CGA },
6826e8394b8SKazutaka YOKOTA 		{ FBTYPE_EGA,		KD_EGA },
6836e8394b8SKazutaka YOKOTA 		{ FBTYPE_VGA,		KD_VGA },
6846e8394b8SKazutaka YOKOTA 		{ FBTYPE_PC98,		KD_PC98 },
6856e8394b8SKazutaka YOKOTA 		{ FBTYPE_TGA,		KD_TGA },
6866e8394b8SKazutaka YOKOTA 	};
6876e8394b8SKazutaka YOKOTA 	int i;
6886e8394b8SKazutaka YOKOTA 
6896e8394b8SKazutaka YOKOTA 	for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
6906e8394b8SKazutaka YOKOTA 		if (types[i].va_type == adp_type)
6916e8394b8SKazutaka YOKOTA 			return types[i].fb_type;
6926e8394b8SKazutaka YOKOTA 	}
6936e8394b8SKazutaka YOKOTA 	return -1;
6946e8394b8SKazutaka YOKOTA }
6956e8394b8SKazutaka YOKOTA 
6966e8394b8SKazutaka YOKOTA int
6976e8394b8SKazutaka YOKOTA fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
6986e8394b8SKazutaka YOKOTA {
6996e8394b8SKazutaka YOKOTA 	int error;
7006e8394b8SKazutaka YOKOTA 	int s;
7016e8394b8SKazutaka YOKOTA 
7026e8394b8SKazutaka YOKOTA 	/* assert(adp != NULL) */
7036e8394b8SKazutaka YOKOTA 
7046e8394b8SKazutaka YOKOTA 	error = 0;
7056e8394b8SKazutaka YOKOTA 	s = spltty();
7066e8394b8SKazutaka YOKOTA 
7076e8394b8SKazutaka YOKOTA 	switch (cmd) {
7086e8394b8SKazutaka YOKOTA 
7096e8394b8SKazutaka YOKOTA 	case FBIO_ADAPTER:	/* get video adapter index */
7106e8394b8SKazutaka YOKOTA 		*(int *)arg = adp->va_index;
7116e8394b8SKazutaka YOKOTA 		break;
7126e8394b8SKazutaka YOKOTA 
7136e8394b8SKazutaka YOKOTA 	case FBIO_ADPTYPE:	/* get video adapter type */
7146e8394b8SKazutaka YOKOTA 		*(int *)arg = adp->va_type;
7156e8394b8SKazutaka YOKOTA 		break;
7166e8394b8SKazutaka YOKOTA 
7176e8394b8SKazutaka YOKOTA 	case FBIO_ADPINFO:	/* get video adapter info */
7186e8394b8SKazutaka YOKOTA 	        ((video_adapter_info_t *)arg)->va_index = adp->va_index;
7196e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_type = adp->va_type;
7206e8394b8SKazutaka YOKOTA 		bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
7216e8394b8SKazutaka YOKOTA 		      imin(strlen(adp->va_name) + 1,
7226e8394b8SKazutaka YOKOTA 			   sizeof(((video_adapter_info_t *)arg)->va_name)));
7236e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
7246e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
7256e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
7266e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
7276e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
7286e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
7296e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
7306e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window
7312727ed91SAndrew Gallatin #ifdef __i386__
7326e8394b8SKazutaka YOKOTA 			= vtophys(adp->va_window);
7332727ed91SAndrew Gallatin #else
7342727ed91SAndrew Gallatin 			= adp->va_window;
7352727ed91SAndrew Gallatin #endif
7366e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window_size
7376e8394b8SKazutaka YOKOTA 			= adp->va_window_size;
7386e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window_gran
7396e8394b8SKazutaka YOKOTA 			= adp->va_window_gran;
7406e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window_orig
7416e8394b8SKazutaka YOKOTA 			= adp->va_window_orig;
7426e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_unused0
7432727ed91SAndrew Gallatin #ifdef __i386__
7446e8394b8SKazutaka YOKOTA 			= (adp->va_buffer) ? vtophys(adp->va_buffer) : 0;
7452727ed91SAndrew Gallatin #else
7462727ed91SAndrew Gallatin 			= adp->va_buffer;
7472727ed91SAndrew Gallatin #endif
7486e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_buffer_size
7496e8394b8SKazutaka YOKOTA 			= adp->va_buffer_size;
7506e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
7516e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_initial_mode
7526e8394b8SKazutaka YOKOTA 			= adp->va_initial_mode;
7536e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_initial_bios_mode
7546e8394b8SKazutaka YOKOTA 			= adp->va_initial_bios_mode;
7556e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_line_width
7566e8394b8SKazutaka YOKOTA 			= adp->va_line_width;
7576e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_disp_start.x
7586e8394b8SKazutaka YOKOTA 			= adp->va_disp_start.x;
7596e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_disp_start.y
7606e8394b8SKazutaka YOKOTA 			= adp->va_disp_start.y;
7616e8394b8SKazutaka YOKOTA 		break;
7626e8394b8SKazutaka YOKOTA 
7636e8394b8SKazutaka YOKOTA 	case FBIO_MODEINFO:	/* get mode information */
7646e8394b8SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->get_info)(adp,
7656e8394b8SKazutaka YOKOTA 				((video_info_t *)arg)->vi_mode,
7666e8394b8SKazutaka YOKOTA 				(video_info_t *)arg);
7676e8394b8SKazutaka YOKOTA 		if (error)
7686e8394b8SKazutaka YOKOTA 			error = ENODEV;
7696e8394b8SKazutaka YOKOTA 		break;
7706e8394b8SKazutaka YOKOTA 
7716e8394b8SKazutaka YOKOTA 	case FBIO_FINDMODE:	/* find a matching video mode */
7726e8394b8SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->query_mode)(adp,
7736e8394b8SKazutaka YOKOTA 				(video_info_t *)arg);
7746e8394b8SKazutaka YOKOTA 		break;
7756e8394b8SKazutaka YOKOTA 
7766e8394b8SKazutaka YOKOTA 	case FBIO_GETMODE:	/* get video mode */
7776e8394b8SKazutaka YOKOTA 		*(int *)arg = adp->va_mode;
7786e8394b8SKazutaka YOKOTA 		break;
7796e8394b8SKazutaka YOKOTA 
7806e8394b8SKazutaka YOKOTA 	case FBIO_SETMODE:	/* set video mode */
7816e8394b8SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg);
7826e8394b8SKazutaka YOKOTA 		if (error)
7836e8394b8SKazutaka YOKOTA 			error = ENODEV;	/* EINVAL? */
7846e8394b8SKazutaka YOKOTA 		break;
7856e8394b8SKazutaka YOKOTA 
7866e8394b8SKazutaka YOKOTA 	case FBIO_GETWINORG:	/* get frame buffer window origin */
7876e8394b8SKazutaka YOKOTA 		*(u_int *)arg = adp->va_window_orig;
7886e8394b8SKazutaka YOKOTA 		break;
7896e8394b8SKazutaka YOKOTA 
7906e8394b8SKazutaka YOKOTA 	case FBIO_GETDISPSTART:	/* get display start address */
7916e8394b8SKazutaka YOKOTA 		((video_display_start_t *)arg)->x = adp->va_disp_start.x;
7926e8394b8SKazutaka YOKOTA 		((video_display_start_t *)arg)->y = adp->va_disp_start.y;
7936e8394b8SKazutaka YOKOTA 		break;
7946e8394b8SKazutaka YOKOTA 
7956e8394b8SKazutaka YOKOTA 	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
7966e8394b8SKazutaka YOKOTA 		*(u_int *)arg = adp->va_line_width;
7976e8394b8SKazutaka YOKOTA 		break;
7986e8394b8SKazutaka YOKOTA 
799eac47d67SKazutaka YOKOTA 	case FBIO_BLANK:	/* blank display */
800eac47d67SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->blank_display)(adp, *(int *)arg);
801eac47d67SKazutaka YOKOTA 		break;
802eac47d67SKazutaka YOKOTA 
8036e8394b8SKazutaka YOKOTA 	case FBIO_GETPALETTE:	/* get color palette */
8046e8394b8SKazutaka YOKOTA 	case FBIO_SETPALETTE:	/* set color palette */
8056e8394b8SKazutaka YOKOTA 		/* XXX */
8066e8394b8SKazutaka YOKOTA 
8076e8394b8SKazutaka YOKOTA 	case FBIOPUTCMAP:
8086e8394b8SKazutaka YOKOTA 	case FBIOGETCMAP:
809eac47d67SKazutaka YOKOTA 	case FBIOPUTCMAPI:
810eac47d67SKazutaka YOKOTA 	case FBIOGETCMAPI:
8116e8394b8SKazutaka YOKOTA 		/* XXX */
8126e8394b8SKazutaka YOKOTA 
8136e8394b8SKazutaka YOKOTA 	case FBIO_SETWINORG:	/* set frame buffer window origin */
8146e8394b8SKazutaka YOKOTA 	case FBIO_SETDISPSTART:	/* set display start address */
8156e8394b8SKazutaka YOKOTA 	case FBIO_SETLINEWIDTH:	/* set scan line width in pixel */
8166e8394b8SKazutaka YOKOTA 
8176e8394b8SKazutaka YOKOTA 	case FBIOGTYPE:
8186e8394b8SKazutaka YOKOTA 	case FBIOGATTR:
8196e8394b8SKazutaka YOKOTA 	case FBIOSVIDEO:
8206e8394b8SKazutaka YOKOTA 	case FBIOGVIDEO:
821eac47d67SKazutaka YOKOTA 	case FBIOVERTICAL:
8226e8394b8SKazutaka YOKOTA 	case FBIOSCURSOR:
8236e8394b8SKazutaka YOKOTA 	case FBIOGCURSOR:
8246e8394b8SKazutaka YOKOTA 	case FBIOSCURPOS:
8256e8394b8SKazutaka YOKOTA 	case FBIOGCURPOS:
8266e8394b8SKazutaka YOKOTA 	case FBIOGCURMAX:
827eac47d67SKazutaka YOKOTA 	case FBIOMONINFO:
828eac47d67SKazutaka YOKOTA 	case FBIOGXINFO:
8296e8394b8SKazutaka YOKOTA 
8306e8394b8SKazutaka YOKOTA 	default:
8316e8394b8SKazutaka YOKOTA 		error = ENODEV;
8326e8394b8SKazutaka YOKOTA 		break;
8336e8394b8SKazutaka YOKOTA 	}
8346e8394b8SKazutaka YOKOTA 
8356e8394b8SKazutaka YOKOTA 	splx(s);
8366e8394b8SKazutaka YOKOTA 	return error;
8376e8394b8SKazutaka YOKOTA }
838