xref: /freebsd/sys/dev/fb/fb.c (revision 2b120974)
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>
42617b9080SKazutaka YOKOTA 
436e8394b8SKazutaka YOKOTA #include <vm/vm.h>
446e8394b8SKazutaka YOKOTA #include <vm/pmap.h>
45617b9080SKazutaka YOKOTA 
46617b9080SKazutaka YOKOTA #include <dev/fb/fbreg.h>
47617b9080SKazutaka YOKOTA 
48617b9080SKazutaka YOKOTA /* local arrays */
49617b9080SKazutaka YOKOTA 
50617b9080SKazutaka YOKOTA /*
51617b9080SKazutaka YOKOTA  * We need at least one entry each in order to initialize a video card
52617b9080SKazutaka YOKOTA  * for the kernel console.  The arrays will be increased dynamically
53617b9080SKazutaka YOKOTA  * when necessary.
54617b9080SKazutaka YOKOTA  */
55617b9080SKazutaka YOKOTA 
566e8394b8SKazutaka YOKOTA static int		vid_malloc;
57617b9080SKazutaka YOKOTA static int		adapters = 1;
5890500a9dSKazutaka YOKOTA static video_adapter_t	*adp_ini;
5990500a9dSKazutaka YOKOTA static video_adapter_t	**adapter = &adp_ini;
6090500a9dSKazutaka YOKOTA static video_switch_t	*vidsw_ini;
61617b9080SKazutaka YOKOTA        video_switch_t	**vidsw = &vidsw_ini;
6290500a9dSKazutaka YOKOTA 
6390500a9dSKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
646e8394b8SKazutaka YOKOTA static struct cdevsw	*vidcdevsw_ini;
656e8394b8SKazutaka YOKOTA static struct cdevsw	**vidcdevsw = &vidcdevsw_ini;
666e8394b8SKazutaka YOKOTA #endif
67617b9080SKazutaka YOKOTA 
68617b9080SKazutaka YOKOTA #define ARRAY_DELTA	4
69617b9080SKazutaka YOKOTA 
706e8394b8SKazutaka YOKOTA static int
71617b9080SKazutaka YOKOTA vid_realloc_array(void)
72617b9080SKazutaka YOKOTA {
73617b9080SKazutaka YOKOTA 	video_adapter_t **new_adp;
74617b9080SKazutaka YOKOTA 	video_switch_t **new_vidsw;
756e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
76617b9080SKazutaka YOKOTA 	struct cdevsw **new_cdevsw;
776e8394b8SKazutaka YOKOTA #endif
78617b9080SKazutaka YOKOTA 	int newsize;
79617b9080SKazutaka YOKOTA 	int s;
80617b9080SKazutaka YOKOTA 
816e8394b8SKazutaka YOKOTA 	if (!vid_malloc)
826e8394b8SKazutaka YOKOTA 		return ENOMEM;
836e8394b8SKazutaka YOKOTA 
84617b9080SKazutaka YOKOTA 	s = spltty();
85617b9080SKazutaka YOKOTA 	newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
867cc0979fSDavid Malone 	new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK | M_ZERO);
877cc0979fSDavid Malone 	new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF,
887cc0979fSDavid Malone 	    M_WAITOK | M_ZERO);
896e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
907cc0979fSDavid Malone 	new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF,
917cc0979fSDavid Malone 	    M_WAITOK | M_ZERO);
926e8394b8SKazutaka YOKOTA #endif
93617b9080SKazutaka YOKOTA 	bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
94617b9080SKazutaka YOKOTA 	bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
956e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
96617b9080SKazutaka YOKOTA 	bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
976e8394b8SKazutaka YOKOTA #endif
98617b9080SKazutaka YOKOTA 	if (adapters > 1) {
99617b9080SKazutaka YOKOTA 		free(adapter, M_DEVBUF);
100617b9080SKazutaka YOKOTA 		free(vidsw, M_DEVBUF);
1016e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
102617b9080SKazutaka YOKOTA 		free(vidcdevsw, M_DEVBUF);
1036e8394b8SKazutaka YOKOTA #endif
104617b9080SKazutaka YOKOTA 	}
105617b9080SKazutaka YOKOTA 	adapter = new_adp;
106617b9080SKazutaka YOKOTA 	vidsw = new_vidsw;
1076e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
108617b9080SKazutaka YOKOTA 	vidcdevsw = new_cdevsw;
1096e8394b8SKazutaka YOKOTA #endif
110617b9080SKazutaka YOKOTA 	adapters = newsize;
111617b9080SKazutaka YOKOTA 	splx(s);
112617b9080SKazutaka YOKOTA 
113617b9080SKazutaka YOKOTA 	if (bootverbose)
114617b9080SKazutaka YOKOTA 		printf("fb: new array size %d\n", adapters);
1156e8394b8SKazutaka YOKOTA 
1166e8394b8SKazutaka YOKOTA 	return 0;
117617b9080SKazutaka YOKOTA }
118617b9080SKazutaka YOKOTA 
1196e8394b8SKazutaka YOKOTA static void
1206e8394b8SKazutaka YOKOTA vid_malloc_init(void *arg)
1216e8394b8SKazutaka YOKOTA {
1226e8394b8SKazutaka YOKOTA 	vid_malloc = TRUE;
1236e8394b8SKazutaka YOKOTA }
1246e8394b8SKazutaka YOKOTA 
1256e8394b8SKazutaka YOKOTA SYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
12690500a9dSKazutaka YOKOTA 
127617b9080SKazutaka YOKOTA /*
128617b9080SKazutaka YOKOTA  * Low-level frame buffer driver functions
129617b9080SKazutaka YOKOTA  * frame buffer subdrivers, such as the VGA driver, call these functions
130617b9080SKazutaka YOKOTA  * to initialize the video_adapter structure and register it to the virtual
131617b9080SKazutaka YOKOTA  * frame buffer driver `fb'.
132617b9080SKazutaka YOKOTA  */
133617b9080SKazutaka YOKOTA 
134617b9080SKazutaka YOKOTA /* initialize the video_adapter_t structure */
135617b9080SKazutaka YOKOTA void
136617b9080SKazutaka YOKOTA vid_init_struct(video_adapter_t *adp, char *name, int type, int unit)
137617b9080SKazutaka YOKOTA {
138617b9080SKazutaka YOKOTA 	adp->va_flags = 0;
139617b9080SKazutaka YOKOTA 	adp->va_name = name;
140617b9080SKazutaka YOKOTA 	adp->va_type = type;
141617b9080SKazutaka YOKOTA 	adp->va_unit = unit;
142617b9080SKazutaka YOKOTA }
143617b9080SKazutaka YOKOTA 
144617b9080SKazutaka YOKOTA /* Register a video adapter */
145617b9080SKazutaka YOKOTA int
146617b9080SKazutaka YOKOTA vid_register(video_adapter_t *adp)
147617b9080SKazutaka YOKOTA {
1486e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
1496e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
150617b9080SKazutaka YOKOTA 	int index;
151617b9080SKazutaka YOKOTA 
152617b9080SKazutaka YOKOTA 	for (index = 0; index < adapters; ++index) {
153617b9080SKazutaka YOKOTA 		if (adapter[index] == NULL)
154617b9080SKazutaka YOKOTA 			break;
155617b9080SKazutaka YOKOTA 	}
1566e8394b8SKazutaka YOKOTA 	if (index >= adapters) {
1576e8394b8SKazutaka YOKOTA 		if (vid_realloc_array())
158617b9080SKazutaka YOKOTA 			return -1;
1596e8394b8SKazutaka YOKOTA 	}
160617b9080SKazutaka YOKOTA 
161617b9080SKazutaka YOKOTA 	adp->va_index = index;
162617b9080SKazutaka YOKOTA 	adp->va_token = NULL;
1636e8394b8SKazutaka YOKOTA 	list = (const video_driver_t **)videodriver_set.ls_items;
164617b9080SKazutaka YOKOTA 	while ((p = *list++) != NULL) {
165617b9080SKazutaka YOKOTA 		if (strcmp(p->name, adp->va_name) == 0) {
166617b9080SKazutaka YOKOTA 			adapter[index] = adp;
167617b9080SKazutaka YOKOTA 			vidsw[index] = p->vidsw;
168617b9080SKazutaka YOKOTA 			return index;
169617b9080SKazutaka YOKOTA 		}
170617b9080SKazutaka YOKOTA 	}
171617b9080SKazutaka YOKOTA 
172617b9080SKazutaka YOKOTA 	return -1;
173617b9080SKazutaka YOKOTA }
174617b9080SKazutaka YOKOTA 
175617b9080SKazutaka YOKOTA int
176617b9080SKazutaka YOKOTA vid_unregister(video_adapter_t *adp)
177617b9080SKazutaka YOKOTA {
178617b9080SKazutaka YOKOTA 	if ((adp->va_index < 0) || (adp->va_index >= adapters))
179617b9080SKazutaka YOKOTA 		return ENOENT;
180617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
181617b9080SKazutaka YOKOTA 		return ENOENT;
182617b9080SKazutaka YOKOTA 
183617b9080SKazutaka YOKOTA 	adapter[adp->va_index] = NULL;
184617b9080SKazutaka YOKOTA 	vidsw[adp->va_index] = NULL;
185617b9080SKazutaka YOKOTA 	return 0;
186617b9080SKazutaka YOKOTA }
187617b9080SKazutaka YOKOTA 
188617b9080SKazutaka YOKOTA /* Get video I/O function table */
189617b9080SKazutaka YOKOTA video_switch_t
190617b9080SKazutaka YOKOTA *vid_get_switch(char *name)
191617b9080SKazutaka YOKOTA {
1926e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
1936e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
194617b9080SKazutaka YOKOTA 
1956e8394b8SKazutaka YOKOTA 	list = (const video_driver_t **)videodriver_set.ls_items;
196617b9080SKazutaka YOKOTA 	while ((p = *list++) != NULL) {
197617b9080SKazutaka YOKOTA 		if (strcmp(p->name, name) == 0)
198617b9080SKazutaka YOKOTA 			return p->vidsw;
199617b9080SKazutaka YOKOTA 	}
200617b9080SKazutaka YOKOTA 
201617b9080SKazutaka YOKOTA 	return NULL;
202617b9080SKazutaka YOKOTA }
203617b9080SKazutaka YOKOTA 
204617b9080SKazutaka YOKOTA /*
205617b9080SKazutaka YOKOTA  * Video card client functions
206617b9080SKazutaka YOKOTA  * Video card clients, such as the console driver `syscons' and the frame
207617b9080SKazutaka YOKOTA  * buffer cdev driver, use these functions to claim and release a card for
208617b9080SKazutaka YOKOTA  * exclusive use.
209617b9080SKazutaka YOKOTA  */
210617b9080SKazutaka YOKOTA 
211617b9080SKazutaka YOKOTA /* find the video card specified by a driver name and a unit number */
212617b9080SKazutaka YOKOTA int
213617b9080SKazutaka YOKOTA vid_find_adapter(char *driver, int unit)
214617b9080SKazutaka YOKOTA {
215617b9080SKazutaka YOKOTA 	int i;
216617b9080SKazutaka YOKOTA 
217617b9080SKazutaka YOKOTA 	for (i = 0; i < adapters; ++i) {
218617b9080SKazutaka YOKOTA 		if (adapter[i] == NULL)
219617b9080SKazutaka YOKOTA 			continue;
220617b9080SKazutaka YOKOTA 		if (strcmp("*", driver) && strcmp(adapter[i]->va_name, driver))
221617b9080SKazutaka YOKOTA 			continue;
222617b9080SKazutaka YOKOTA 		if ((unit != -1) && (adapter[i]->va_unit != unit))
223617b9080SKazutaka YOKOTA 			continue;
224617b9080SKazutaka YOKOTA 		return i;
225617b9080SKazutaka YOKOTA 	}
226617b9080SKazutaka YOKOTA 	return -1;
227617b9080SKazutaka YOKOTA }
228617b9080SKazutaka YOKOTA 
229617b9080SKazutaka YOKOTA /* allocate a video card */
230617b9080SKazutaka YOKOTA int
231617b9080SKazutaka YOKOTA vid_allocate(char *driver, int unit, void *id)
232617b9080SKazutaka YOKOTA {
233617b9080SKazutaka YOKOTA 	int index;
234617b9080SKazutaka YOKOTA 	int s;
235617b9080SKazutaka YOKOTA 
236617b9080SKazutaka YOKOTA 	s = spltty();
237617b9080SKazutaka YOKOTA 	index = vid_find_adapter(driver, unit);
238617b9080SKazutaka YOKOTA 	if (index >= 0) {
239617b9080SKazutaka YOKOTA 		if (adapter[index]->va_token) {
240617b9080SKazutaka YOKOTA 			splx(s);
241617b9080SKazutaka YOKOTA 			return -1;
242617b9080SKazutaka YOKOTA 		}
243617b9080SKazutaka YOKOTA 		adapter[index]->va_token = id;
244617b9080SKazutaka YOKOTA 	}
245617b9080SKazutaka YOKOTA 	splx(s);
246617b9080SKazutaka YOKOTA 	return index;
247617b9080SKazutaka YOKOTA }
248617b9080SKazutaka YOKOTA 
249617b9080SKazutaka YOKOTA int
250617b9080SKazutaka YOKOTA vid_release(video_adapter_t *adp, void *id)
251617b9080SKazutaka YOKOTA {
252617b9080SKazutaka YOKOTA 	int error;
253617b9080SKazutaka YOKOTA 	int s;
254617b9080SKazutaka YOKOTA 
255617b9080SKazutaka YOKOTA 	s = spltty();
256617b9080SKazutaka YOKOTA 	if (adp->va_token == NULL) {
257617b9080SKazutaka YOKOTA 		error = EINVAL;
258617b9080SKazutaka YOKOTA 	} else if (adp->va_token != id) {
259617b9080SKazutaka YOKOTA 		error = EPERM;
260617b9080SKazutaka YOKOTA 	} else {
261617b9080SKazutaka YOKOTA 		adp->va_token = NULL;
262617b9080SKazutaka YOKOTA 		error = 0;
263617b9080SKazutaka YOKOTA 	}
264617b9080SKazutaka YOKOTA 	splx(s);
265617b9080SKazutaka YOKOTA 	return error;
266617b9080SKazutaka YOKOTA }
267617b9080SKazutaka YOKOTA 
268617b9080SKazutaka YOKOTA /* Get a video adapter structure */
269617b9080SKazutaka YOKOTA video_adapter_t
270617b9080SKazutaka YOKOTA *vid_get_adapter(int index)
271617b9080SKazutaka YOKOTA {
272617b9080SKazutaka YOKOTA 	if ((index < 0) || (index >= adapters))
273617b9080SKazutaka YOKOTA 		return NULL;
274617b9080SKazutaka YOKOTA 	return adapter[index];
275617b9080SKazutaka YOKOTA }
276617b9080SKazutaka YOKOTA 
277617b9080SKazutaka YOKOTA /* Configure drivers: this is a backdoor for the console driver XXX */
278617b9080SKazutaka YOKOTA int
279617b9080SKazutaka YOKOTA vid_configure(int flags)
280617b9080SKazutaka YOKOTA {
2816e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
2826e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
283617b9080SKazutaka YOKOTA 
2846e8394b8SKazutaka YOKOTA 	list = (const video_driver_t **)videodriver_set.ls_items;
285617b9080SKazutaka YOKOTA 	while ((p = *list++) != NULL) {
286617b9080SKazutaka YOKOTA 		if (p->configure != NULL)
287617b9080SKazutaka YOKOTA 			(*p->configure)(flags);
288617b9080SKazutaka YOKOTA 	}
289617b9080SKazutaka YOKOTA 
290617b9080SKazutaka YOKOTA 	return 0;
291617b9080SKazutaka YOKOTA }
292617b9080SKazutaka YOKOTA 
293617b9080SKazutaka YOKOTA /*
294617b9080SKazutaka YOKOTA  * Virtual frame buffer cdev driver functions
295617b9080SKazutaka YOKOTA  * The virtual frame buffer driver dispatches driver functions to
296617b9080SKazutaka YOKOTA  * appropriate subdrivers.
297617b9080SKazutaka YOKOTA  */
298617b9080SKazutaka YOKOTA 
2996e8394b8SKazutaka YOKOTA #define FB_DRIVER_NAME	"fb"
300617b9080SKazutaka YOKOTA 
301617b9080SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
302617b9080SKazutaka YOKOTA 
3036e8394b8SKazutaka YOKOTA #if experimental
3046e8394b8SKazutaka YOKOTA 
3056e8394b8SKazutaka YOKOTA static devclass_t	fb_devclass;
3066e8394b8SKazutaka YOKOTA 
3076e8394b8SKazutaka YOKOTA static int		fbprobe(device_t dev);
3086e8394b8SKazutaka YOKOTA static int		fbattach(device_t dev);
3096e8394b8SKazutaka YOKOTA 
3106e8394b8SKazutaka YOKOTA static device_method_t fb_methods[] = {
3116e8394b8SKazutaka YOKOTA 	DEVMETHOD(device_probe,		fbprobe),
3126e8394b8SKazutaka YOKOTA 	DEVMETHOD(device_attach,	fbattach),
3136e8394b8SKazutaka YOKOTA 
3146e8394b8SKazutaka YOKOTA 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
3156e8394b8SKazutaka YOKOTA 	{ 0, 0 }
3166e8394b8SKazutaka YOKOTA };
3176e8394b8SKazutaka YOKOTA 
3186e8394b8SKazutaka YOKOTA static driver_t fb_driver = {
3196e8394b8SKazutaka YOKOTA 	FB_DRIVER_NAME,
3206e8394b8SKazutaka YOKOTA 	fb_methods,
3216e8394b8SKazutaka YOKOTA 	0,
3226e8394b8SKazutaka YOKOTA };
3236e8394b8SKazutaka YOKOTA 
3246e8394b8SKazutaka YOKOTA static int
3256e8394b8SKazutaka YOKOTA fbprobe(device_t dev)
3266e8394b8SKazutaka YOKOTA {
3276e8394b8SKazutaka YOKOTA 	int unit;
3286e8394b8SKazutaka YOKOTA 
3296e8394b8SKazutaka YOKOTA 	unit = device_get_unit(dev);
3306e8394b8SKazutaka YOKOTA 	if (unit >= adapters)
3316e8394b8SKazutaka YOKOTA 		return ENXIO;
3326e8394b8SKazutaka YOKOTA 	if (adapter[unit] == NULL)
3336e8394b8SKazutaka YOKOTA 		return ENXIO;
3346e8394b8SKazutaka YOKOTA 
3356e8394b8SKazutaka YOKOTA 	device_set_desc(dev, "generic frame buffer");
3366e8394b8SKazutaka YOKOTA 	return 0;
3376e8394b8SKazutaka YOKOTA }
3386e8394b8SKazutaka YOKOTA 
3396e8394b8SKazutaka YOKOTA static int
3406e8394b8SKazutaka YOKOTA fbattach(device_t dev)
3416e8394b8SKazutaka YOKOTA {
3426e8394b8SKazutaka YOKOTA 	printf("fbattach: about to attach children\n");
3436e8394b8SKazutaka YOKOTA 	bus_generic_attach(dev);
3446e8394b8SKazutaka YOKOTA 	return 0;
3456e8394b8SKazutaka YOKOTA }
3466e8394b8SKazutaka YOKOTA 
3476e8394b8SKazutaka YOKOTA #endif /* experimental */
3486e8394b8SKazutaka YOKOTA 
349617b9080SKazutaka YOKOTA #define FB_UNIT(dev)	minor(dev)
350617b9080SKazutaka YOKOTA #define FB_MKMINOR(unit) (u)
351617b9080SKazutaka YOKOTA 
352617b9080SKazutaka YOKOTA static d_open_t		fbopen;
353617b9080SKazutaka YOKOTA static d_close_t	fbclose;
3546e8394b8SKazutaka YOKOTA static d_read_t		fbread;
3556e8394b8SKazutaka YOKOTA static d_write_t	fbwrite;
356617b9080SKazutaka YOKOTA static d_ioctl_t	fbioctl;
357617b9080SKazutaka YOKOTA static d_mmap_t		fbmmap;
358617b9080SKazutaka YOKOTA 
3596e8394b8SKazutaka YOKOTA #define CDEV_MAJOR	123	/* XXX */
360617b9080SKazutaka YOKOTA 
361617b9080SKazutaka YOKOTA static struct cdevsw fb_cdevsw = {
3624e2f199eSPoul-Henning Kamp 	/* open */	fbopen,
3634e2f199eSPoul-Henning Kamp 	/* close */	fbclose,
3646e8394b8SKazutaka YOKOTA 	/* read */	fbread,
3656e8394b8SKazutaka YOKOTA 	/* write */	fbwrite,
3664e2f199eSPoul-Henning Kamp 	/* ioctl */	fbioctl,
3674e2f199eSPoul-Henning Kamp 	/* poll */	nopoll,
3684e2f199eSPoul-Henning Kamp 	/* mmap */	fbmmap,
3694e2f199eSPoul-Henning Kamp 	/* strategy */	nostrategy,
3706e8394b8SKazutaka YOKOTA 	/* name */	FB_DRIVER_NAME,
3714e2f199eSPoul-Henning Kamp 	/* maj */	CDEV_MAJOR,
3724e2f199eSPoul-Henning Kamp 	/* dump */	nodump,
3734e2f199eSPoul-Henning Kamp 	/* psize */	nopsize,
3744e2f199eSPoul-Henning Kamp 	/* flags */	0,
3754e2f199eSPoul-Henning Kamp 	/* bmaj */	-1
376617b9080SKazutaka YOKOTA };
377617b9080SKazutaka YOKOTA 
3782b120974SPeter Wemm 
3792b120974SPeter Wemm static int
3802b120974SPeter Wemm fb_modevent(module_t mod, int type, void *data)
381617b9080SKazutaka YOKOTA {
382617b9080SKazutaka YOKOTA 
3832b120974SPeter Wemm 	switch (type) {
3842b120974SPeter Wemm 	case MOD_LOAD:
3852447bec8SPoul-Henning Kamp 		cdevsw_add(&fb_cdevsw);
3862b120974SPeter Wemm 		break;
3872b120974SPeter Wemm 	case MOD_UNLOAD:
3882b120974SPeter Wemm 		printf("fb module unload - not possible for this module type\n");
3892b120974SPeter Wemm 		return EINVAL;
390617b9080SKazutaka YOKOTA 	}
3912b120974SPeter Wemm 	return 0;
392617b9080SKazutaka YOKOTA }
393617b9080SKazutaka YOKOTA 
3942b120974SPeter Wemm static moduledata_t fb_mod = {
3952b120974SPeter Wemm 	"fb",
3962b120974SPeter Wemm 	fb_modevent,
3972b120974SPeter Wemm 	NULL
3982b120974SPeter Wemm };
3992b120974SPeter Wemm 
4002b120974SPeter Wemm DECLARE_MODULE(fb, fb_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
401617b9080SKazutaka YOKOTA 
402617b9080SKazutaka YOKOTA int
4036e8394b8SKazutaka YOKOTA fb_attach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
404617b9080SKazutaka YOKOTA {
405617b9080SKazutaka YOKOTA 	int s;
406617b9080SKazutaka YOKOTA 
407617b9080SKazutaka YOKOTA 	if (adp->va_index >= adapters)
408617b9080SKazutaka YOKOTA 		return EINVAL;
409617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
410617b9080SKazutaka YOKOTA 		return EINVAL;
411617b9080SKazutaka YOKOTA 
412617b9080SKazutaka YOKOTA 	s = spltty();
413617b9080SKazutaka YOKOTA 	adp->va_minor = minor(dev);
414617b9080SKazutaka YOKOTA 	vidcdevsw[adp->va_index] = cdevsw;
415617b9080SKazutaka YOKOTA 	splx(s);
416617b9080SKazutaka YOKOTA 
417617b9080SKazutaka YOKOTA 	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
418617b9080SKazutaka YOKOTA 	return 0;
419617b9080SKazutaka YOKOTA }
420617b9080SKazutaka YOKOTA 
421617b9080SKazutaka YOKOTA int
4226e8394b8SKazutaka YOKOTA fb_detach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
423617b9080SKazutaka YOKOTA {
424617b9080SKazutaka YOKOTA 	int s;
425617b9080SKazutaka YOKOTA 
426617b9080SKazutaka YOKOTA 	if (adp->va_index >= adapters)
427617b9080SKazutaka YOKOTA 		return EINVAL;
428617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
429617b9080SKazutaka YOKOTA 		return EINVAL;
430617b9080SKazutaka YOKOTA 	if (vidcdevsw[adp->va_index] != cdevsw)
431617b9080SKazutaka YOKOTA 		return EINVAL;
432617b9080SKazutaka YOKOTA 
433617b9080SKazutaka YOKOTA 	s = spltty();
434617b9080SKazutaka YOKOTA 	vidcdevsw[adp->va_index] = NULL;
435617b9080SKazutaka YOKOTA 	splx(s);
436617b9080SKazutaka YOKOTA 	return 0;
437617b9080SKazutaka YOKOTA }
438617b9080SKazutaka YOKOTA 
4396e8394b8SKazutaka YOKOTA static int
4406e8394b8SKazutaka YOKOTA fbopen(dev_t dev, int flag, int mode, struct proc *p)
4416e8394b8SKazutaka YOKOTA {
4426e8394b8SKazutaka YOKOTA 	int unit;
4436e8394b8SKazutaka YOKOTA 
4446e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4456e8394b8SKazutaka YOKOTA 	if (unit >= adapters)
4466e8394b8SKazutaka YOKOTA 		return ENXIO;
4476e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4486e8394b8SKazutaka YOKOTA 		return ENXIO;
4496e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_open)(makedev(0, adapter[unit]->va_minor),
4506e8394b8SKazutaka YOKOTA 					  flag, mode, p);
4516e8394b8SKazutaka YOKOTA }
4526e8394b8SKazutaka YOKOTA 
4536e8394b8SKazutaka YOKOTA static int
4546e8394b8SKazutaka YOKOTA fbclose(dev_t dev, int flag, int mode, struct proc *p)
4556e8394b8SKazutaka YOKOTA {
4566e8394b8SKazutaka YOKOTA 	int unit;
4576e8394b8SKazutaka YOKOTA 
4586e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4596e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4606e8394b8SKazutaka YOKOTA 		return ENXIO;
4616e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_close)(makedev(0, adapter[unit]->va_minor),
4626e8394b8SKazutaka YOKOTA 					   flag, mode, p);
4636e8394b8SKazutaka YOKOTA }
4646e8394b8SKazutaka YOKOTA 
4656e8394b8SKazutaka YOKOTA static int
4666e8394b8SKazutaka YOKOTA fbread(dev_t dev, struct uio *uio, int flag)
4676e8394b8SKazutaka YOKOTA {
4686e8394b8SKazutaka YOKOTA 	int unit;
4696e8394b8SKazutaka YOKOTA 
4706e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4716e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4726e8394b8SKazutaka YOKOTA 		return ENXIO;
4736e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_read)(makedev(0, adapter[unit]->va_minor),
4746e8394b8SKazutaka YOKOTA 					  uio, flag);
4756e8394b8SKazutaka YOKOTA }
4766e8394b8SKazutaka YOKOTA 
4776e8394b8SKazutaka YOKOTA static int
4786e8394b8SKazutaka YOKOTA fbwrite(dev_t dev, struct uio *uio, int flag)
4796e8394b8SKazutaka YOKOTA {
4806e8394b8SKazutaka YOKOTA 	int unit;
4816e8394b8SKazutaka YOKOTA 
4826e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4836e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4846e8394b8SKazutaka YOKOTA 		return ENXIO;
4856e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_write)(makedev(0, adapter[unit]->va_minor),
4866e8394b8SKazutaka YOKOTA 					   uio, flag);
4876e8394b8SKazutaka YOKOTA }
4886e8394b8SKazutaka YOKOTA 
4896e8394b8SKazutaka YOKOTA static int
4906e8394b8SKazutaka YOKOTA fbioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
4916e8394b8SKazutaka YOKOTA {
4926e8394b8SKazutaka YOKOTA 	int unit;
4936e8394b8SKazutaka YOKOTA 
4946e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
4956e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
4966e8394b8SKazutaka YOKOTA 		return ENXIO;
4976e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_ioctl)(makedev(0, adapter[unit]->va_minor),
4986e8394b8SKazutaka YOKOTA 					   cmd, arg, flag, p);
4996e8394b8SKazutaka YOKOTA }
5006e8394b8SKazutaka YOKOTA 
5016e8394b8SKazutaka YOKOTA static int
5026e8394b8SKazutaka YOKOTA fbmmap(dev_t dev, vm_offset_t offset, int nprot)
5036e8394b8SKazutaka YOKOTA {
5046e8394b8SKazutaka YOKOTA 	int unit;
5056e8394b8SKazutaka YOKOTA 
5066e8394b8SKazutaka YOKOTA 	unit = FB_UNIT(dev);
5076e8394b8SKazutaka YOKOTA 	if (vidcdevsw[unit] == NULL)
5086e8394b8SKazutaka YOKOTA 		return ENXIO;
5096e8394b8SKazutaka YOKOTA 	return (*vidcdevsw[unit]->d_mmap)(makedev(0, adapter[unit]->va_minor),
5106e8394b8SKazutaka YOKOTA 					  offset, nprot);
5116e8394b8SKazutaka YOKOTA }
5126e8394b8SKazutaka YOKOTA 
5136e8394b8SKazutaka YOKOTA #if experimental
51403016f42SPoul-Henning Kamp DEV_DRIVER_MODULE(fb, ???, fb_driver, fb_devclass, fb_cdevsw, 0, 0);
5156e8394b8SKazutaka YOKOTA #endif
5166e8394b8SKazutaka YOKOTA 
5176e8394b8SKazutaka YOKOTA /*
5186e8394b8SKazutaka YOKOTA  * Generic frame buffer cdev driver functions
5196e8394b8SKazutaka YOKOTA  * Frame buffer subdrivers may call these functions to implement common
5206e8394b8SKazutaka YOKOTA  * driver functions.
5216e8394b8SKazutaka YOKOTA  */
5226e8394b8SKazutaka YOKOTA 
5236e8394b8SKazutaka YOKOTA int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
5246e8394b8SKazutaka YOKOTA 	      struct proc *p)
5256e8394b8SKazutaka YOKOTA {
5266e8394b8SKazutaka YOKOTA 	int s;
5276e8394b8SKazutaka YOKOTA 
5286e8394b8SKazutaka YOKOTA 	s = spltty();
5296e8394b8SKazutaka YOKOTA 	if (!(sc->gfb_flags & FB_OPEN))
5306e8394b8SKazutaka YOKOTA 		sc->gfb_flags |= FB_OPEN;
5316e8394b8SKazutaka YOKOTA 	splx(s);
5326e8394b8SKazutaka YOKOTA 	return 0;
5336e8394b8SKazutaka YOKOTA }
5346e8394b8SKazutaka YOKOTA 
5356e8394b8SKazutaka YOKOTA int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
5366e8394b8SKazutaka YOKOTA 	       struct proc *p)
5376e8394b8SKazutaka YOKOTA {
5386e8394b8SKazutaka YOKOTA 	int s;
5396e8394b8SKazutaka YOKOTA 
5406e8394b8SKazutaka YOKOTA 	s = spltty();
5416e8394b8SKazutaka YOKOTA 	sc->gfb_flags &= ~FB_OPEN;
5426e8394b8SKazutaka YOKOTA 	splx(s);
5436e8394b8SKazutaka YOKOTA 	return 0;
5446e8394b8SKazutaka YOKOTA }
5456e8394b8SKazutaka YOKOTA 
5466e8394b8SKazutaka YOKOTA int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
5476e8394b8SKazutaka YOKOTA 	      int flag)
5486e8394b8SKazutaka YOKOTA {
5496e8394b8SKazutaka YOKOTA 	int size;
5506e8394b8SKazutaka YOKOTA 	int offset;
5516e8394b8SKazutaka YOKOTA 	int error;
5526e8394b8SKazutaka YOKOTA 	int len;
5536e8394b8SKazutaka YOKOTA 
5546e8394b8SKazutaka YOKOTA 	error = 0;
5556e8394b8SKazutaka YOKOTA 	size = adp->va_buffer_size/adp->va_info.vi_planes;
5566e8394b8SKazutaka YOKOTA 	while (uio->uio_resid > 0) {
5576e8394b8SKazutaka YOKOTA 		if (uio->uio_offset >= size)
5586e8394b8SKazutaka YOKOTA 			break;
5596e8394b8SKazutaka YOKOTA 		offset = uio->uio_offset%adp->va_window_size;
5606e8394b8SKazutaka YOKOTA 		len = imin(uio->uio_resid, size - uio->uio_offset);
5616e8394b8SKazutaka YOKOTA 		len = imin(len, adp->va_window_size - offset);
5626e8394b8SKazutaka YOKOTA 		if (len <= 0)
5636e8394b8SKazutaka YOKOTA 			break;
5646e8394b8SKazutaka YOKOTA 		(*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
5656e8394b8SKazutaka YOKOTA 		error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
5666e8394b8SKazutaka YOKOTA 		if (error)
5676e8394b8SKazutaka YOKOTA 			break;
5686e8394b8SKazutaka YOKOTA 	}
5696e8394b8SKazutaka YOKOTA 	return error;
5706e8394b8SKazutaka YOKOTA }
5716e8394b8SKazutaka YOKOTA 
5726e8394b8SKazutaka YOKOTA int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
5736e8394b8SKazutaka YOKOTA 	       int flag)
5746e8394b8SKazutaka YOKOTA {
5756e8394b8SKazutaka YOKOTA 	return ENODEV;
5766e8394b8SKazutaka YOKOTA }
5776e8394b8SKazutaka YOKOTA 
5786e8394b8SKazutaka YOKOTA int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
5796e8394b8SKazutaka YOKOTA 	       caddr_t arg, int flag, struct proc *p)
5806e8394b8SKazutaka YOKOTA {
5816e8394b8SKazutaka YOKOTA 	int error;
5826e8394b8SKazutaka YOKOTA 
5836e8394b8SKazutaka YOKOTA 	if (adp == NULL)	/* XXX */
5846e8394b8SKazutaka YOKOTA 		return ENXIO;
5856e8394b8SKazutaka YOKOTA 	error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
5866e8394b8SKazutaka YOKOTA 	if (error == ENOIOCTL)
5876e8394b8SKazutaka YOKOTA 		error = ENODEV;
5886e8394b8SKazutaka YOKOTA 	return error;
5896e8394b8SKazutaka YOKOTA }
5906e8394b8SKazutaka YOKOTA 
5916e8394b8SKazutaka YOKOTA int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
5926e8394b8SKazutaka YOKOTA 	      int prot)
5936e8394b8SKazutaka YOKOTA {
5946e8394b8SKazutaka YOKOTA 	return (*vidsw[adp->va_index]->mmap)(adp, offset, prot);
5956e8394b8SKazutaka YOKOTA }
5966e8394b8SKazutaka YOKOTA 
597617b9080SKazutaka YOKOTA #endif /* FB_INSTALL_CDEV */
598617b9080SKazutaka YOKOTA 
599617b9080SKazutaka YOKOTA static char
600617b9080SKazutaka YOKOTA *adapter_name(int type)
601617b9080SKazutaka YOKOTA {
602617b9080SKazutaka YOKOTA     static struct {
603617b9080SKazutaka YOKOTA 	int type;
604617b9080SKazutaka YOKOTA 	char *name;
605617b9080SKazutaka YOKOTA     } names[] = {
606617b9080SKazutaka YOKOTA 	{ KD_MONO,	"MDA" },
607617b9080SKazutaka YOKOTA 	{ KD_HERCULES,	"Hercules" },
608617b9080SKazutaka YOKOTA 	{ KD_CGA,	"CGA" },
609617b9080SKazutaka YOKOTA 	{ KD_EGA,	"EGA" },
610617b9080SKazutaka YOKOTA 	{ KD_VGA,	"VGA" },
611617b9080SKazutaka YOKOTA 	{ KD_PC98,	"PC-98x1" },
6126e8394b8SKazutaka YOKOTA 	{ KD_TGA,	"TGA" },
613617b9080SKazutaka YOKOTA 	{ -1,		"Unknown" },
614617b9080SKazutaka YOKOTA     };
615617b9080SKazutaka YOKOTA     int i;
616617b9080SKazutaka YOKOTA 
617617b9080SKazutaka YOKOTA     for (i = 0; names[i].type != -1; ++i)
618617b9080SKazutaka YOKOTA 	if (names[i].type == type)
619617b9080SKazutaka YOKOTA 	    break;
620617b9080SKazutaka YOKOTA     return names[i].name;
621617b9080SKazutaka YOKOTA }
622617b9080SKazutaka YOKOTA 
6236e8394b8SKazutaka YOKOTA /*
6246e8394b8SKazutaka YOKOTA  * Generic low-level frame buffer functions
6256e8394b8SKazutaka YOKOTA  * The low-level functions in the frame buffer subdriver may use these
6266e8394b8SKazutaka YOKOTA  * functions.
6276e8394b8SKazutaka YOKOTA  */
6286e8394b8SKazutaka YOKOTA 
629617b9080SKazutaka YOKOTA void
630617b9080SKazutaka YOKOTA fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
631617b9080SKazutaka YOKOTA {
632617b9080SKazutaka YOKOTA     if (level <= 0)
633617b9080SKazutaka YOKOTA 	return;
634617b9080SKazutaka YOKOTA 
635617b9080SKazutaka YOKOTA     printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
6366e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
637617b9080SKazutaka YOKOTA 	   adapter_name(adp->va_type), adp->va_type, adp->va_flags);
638617b9080SKazutaka YOKOTA     printf("%s%d: port:0x%x-0x%x, crtc:0x%x, mem:0x%x 0x%x\n",
6396e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index,
640617b9080SKazutaka YOKOTA 	   adp->va_io_base, adp->va_io_base + adp->va_io_size - 1,
641617b9080SKazutaka YOKOTA 	   adp->va_crtc_addr, adp->va_mem_base, adp->va_mem_size);
642617b9080SKazutaka YOKOTA     printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
6436e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index,
644617b9080SKazutaka YOKOTA 	   adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
6456e8394b8SKazutaka YOKOTA     printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
6466e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index,
6476e8394b8SKazutaka YOKOTA 	   (void *)adp->va_window, (int)adp->va_window_size/1024,
6486e8394b8SKazutaka YOKOTA 	   (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
649f359876fSKazutaka YOKOTA 	   (int)adp->va_buffer_size/1024);
650617b9080SKazutaka YOKOTA }
651617b9080SKazutaka YOKOTA 
652617b9080SKazutaka YOKOTA void
653617b9080SKazutaka YOKOTA fb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
654617b9080SKazutaka YOKOTA 		  int level)
655617b9080SKazutaka YOKOTA {
656617b9080SKazutaka YOKOTA     if (level <= 0)
657617b9080SKazutaka YOKOTA 	return;
658617b9080SKazutaka YOKOTA 
659617b9080SKazutaka YOKOTA     printf("%s%d: %s, mode:%d, flags:0x%x ",
660617b9080SKazutaka YOKOTA 	   driver, adp->va_unit, adp->va_name, info->vi_mode, info->vi_flags);
661617b9080SKazutaka YOKOTA     if (info->vi_flags & V_INFO_GRAPHICS)
662617b9080SKazutaka YOKOTA 	printf("G %dx%dx%d, %d plane(s), font:%dx%d, ",
663617b9080SKazutaka YOKOTA 	       info->vi_width, info->vi_height,
664617b9080SKazutaka YOKOTA 	       info->vi_depth, info->vi_planes,
665617b9080SKazutaka YOKOTA 	       info->vi_cwidth, info->vi_cheight);
666617b9080SKazutaka YOKOTA     else
667617b9080SKazutaka YOKOTA 	printf("T %dx%d, font:%dx%d, ",
668617b9080SKazutaka YOKOTA 	       info->vi_width, info->vi_height,
669617b9080SKazutaka YOKOTA 	       info->vi_cwidth, info->vi_cheight);
670617b9080SKazutaka YOKOTA     printf("win:0x%x\n", info->vi_window);
671617b9080SKazutaka YOKOTA }
6726e8394b8SKazutaka YOKOTA 
6736e8394b8SKazutaka YOKOTA int
6746e8394b8SKazutaka YOKOTA fb_type(int adp_type)
6756e8394b8SKazutaka YOKOTA {
6766e8394b8SKazutaka YOKOTA 	static struct {
6776e8394b8SKazutaka YOKOTA 		int	fb_type;
6786e8394b8SKazutaka YOKOTA 		int	va_type;
6796e8394b8SKazutaka YOKOTA 	} types[] = {
6806e8394b8SKazutaka YOKOTA 		{ FBTYPE_MDA,		KD_MONO },
6816e8394b8SKazutaka YOKOTA 		{ FBTYPE_HERCULES,	KD_HERCULES },
6826e8394b8SKazutaka YOKOTA 		{ FBTYPE_CGA,		KD_CGA },
6836e8394b8SKazutaka YOKOTA 		{ FBTYPE_EGA,		KD_EGA },
6846e8394b8SKazutaka YOKOTA 		{ FBTYPE_VGA,		KD_VGA },
6856e8394b8SKazutaka YOKOTA 		{ FBTYPE_PC98,		KD_PC98 },
6866e8394b8SKazutaka YOKOTA 		{ FBTYPE_TGA,		KD_TGA },
6876e8394b8SKazutaka YOKOTA 	};
6886e8394b8SKazutaka YOKOTA 	int i;
6896e8394b8SKazutaka YOKOTA 
6906e8394b8SKazutaka YOKOTA 	for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
6916e8394b8SKazutaka YOKOTA 		if (types[i].va_type == adp_type)
6926e8394b8SKazutaka YOKOTA 			return types[i].fb_type;
6936e8394b8SKazutaka YOKOTA 	}
6946e8394b8SKazutaka YOKOTA 	return -1;
6956e8394b8SKazutaka YOKOTA }
6966e8394b8SKazutaka YOKOTA 
6976e8394b8SKazutaka YOKOTA int
6986e8394b8SKazutaka YOKOTA fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
6996e8394b8SKazutaka YOKOTA {
7006e8394b8SKazutaka YOKOTA 	int error;
7016e8394b8SKazutaka YOKOTA 	int s;
7026e8394b8SKazutaka YOKOTA 
7036e8394b8SKazutaka YOKOTA 	/* assert(adp != NULL) */
7046e8394b8SKazutaka YOKOTA 
7056e8394b8SKazutaka YOKOTA 	error = 0;
7066e8394b8SKazutaka YOKOTA 	s = spltty();
7076e8394b8SKazutaka YOKOTA 
7086e8394b8SKazutaka YOKOTA 	switch (cmd) {
7096e8394b8SKazutaka YOKOTA 
7106e8394b8SKazutaka YOKOTA 	case FBIO_ADAPTER:	/* get video adapter index */
7116e8394b8SKazutaka YOKOTA 		*(int *)arg = adp->va_index;
7126e8394b8SKazutaka YOKOTA 		break;
7136e8394b8SKazutaka YOKOTA 
7146e8394b8SKazutaka YOKOTA 	case FBIO_ADPTYPE:	/* get video adapter type */
7156e8394b8SKazutaka YOKOTA 		*(int *)arg = adp->va_type;
7166e8394b8SKazutaka YOKOTA 		break;
7176e8394b8SKazutaka YOKOTA 
7186e8394b8SKazutaka YOKOTA 	case FBIO_ADPINFO:	/* get video adapter info */
7196e8394b8SKazutaka YOKOTA 	        ((video_adapter_info_t *)arg)->va_index = adp->va_index;
7206e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_type = adp->va_type;
7216e8394b8SKazutaka YOKOTA 		bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
7226e8394b8SKazutaka YOKOTA 		      imin(strlen(adp->va_name) + 1,
7236e8394b8SKazutaka YOKOTA 			   sizeof(((video_adapter_info_t *)arg)->va_name)));
7246e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
7256e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
7266e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
7276e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
7286e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
7296e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
7306e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
7316e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window
7322727ed91SAndrew Gallatin #ifdef __i386__
7336e8394b8SKazutaka YOKOTA 			= vtophys(adp->va_window);
7342727ed91SAndrew Gallatin #else
7352727ed91SAndrew Gallatin 			= adp->va_window;
7362727ed91SAndrew Gallatin #endif
7376e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window_size
7386e8394b8SKazutaka YOKOTA 			= adp->va_window_size;
7396e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window_gran
7406e8394b8SKazutaka YOKOTA 			= adp->va_window_gran;
7416e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_window_orig
7426e8394b8SKazutaka YOKOTA 			= adp->va_window_orig;
7436e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_unused0
7442727ed91SAndrew Gallatin #ifdef __i386__
7456e8394b8SKazutaka YOKOTA 			= (adp->va_buffer) ? vtophys(adp->va_buffer) : 0;
7462727ed91SAndrew Gallatin #else
7472727ed91SAndrew Gallatin 			= adp->va_buffer;
7482727ed91SAndrew Gallatin #endif
7496e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_buffer_size
7506e8394b8SKazutaka YOKOTA 			= adp->va_buffer_size;
7516e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
7526e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_initial_mode
7536e8394b8SKazutaka YOKOTA 			= adp->va_initial_mode;
7546e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_initial_bios_mode
7556e8394b8SKazutaka YOKOTA 			= adp->va_initial_bios_mode;
7566e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_line_width
7576e8394b8SKazutaka YOKOTA 			= adp->va_line_width;
7586e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_disp_start.x
7596e8394b8SKazutaka YOKOTA 			= adp->va_disp_start.x;
7606e8394b8SKazutaka YOKOTA 		((video_adapter_info_t *)arg)->va_disp_start.y
7616e8394b8SKazutaka YOKOTA 			= adp->va_disp_start.y;
7626e8394b8SKazutaka YOKOTA 		break;
7636e8394b8SKazutaka YOKOTA 
7646e8394b8SKazutaka YOKOTA 	case FBIO_MODEINFO:	/* get mode information */
7656e8394b8SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->get_info)(adp,
7666e8394b8SKazutaka YOKOTA 				((video_info_t *)arg)->vi_mode,
7676e8394b8SKazutaka YOKOTA 				(video_info_t *)arg);
7686e8394b8SKazutaka YOKOTA 		if (error)
7696e8394b8SKazutaka YOKOTA 			error = ENODEV;
7706e8394b8SKazutaka YOKOTA 		break;
7716e8394b8SKazutaka YOKOTA 
7726e8394b8SKazutaka YOKOTA 	case FBIO_FINDMODE:	/* find a matching video mode */
7736e8394b8SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->query_mode)(adp,
7746e8394b8SKazutaka YOKOTA 				(video_info_t *)arg);
7756e8394b8SKazutaka YOKOTA 		break;
7766e8394b8SKazutaka YOKOTA 
7776e8394b8SKazutaka YOKOTA 	case FBIO_GETMODE:	/* get video mode */
7786e8394b8SKazutaka YOKOTA 		*(int *)arg = adp->va_mode;
7796e8394b8SKazutaka YOKOTA 		break;
7806e8394b8SKazutaka YOKOTA 
7816e8394b8SKazutaka YOKOTA 	case FBIO_SETMODE:	/* set video mode */
7826e8394b8SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg);
7836e8394b8SKazutaka YOKOTA 		if (error)
7846e8394b8SKazutaka YOKOTA 			error = ENODEV;	/* EINVAL? */
7856e8394b8SKazutaka YOKOTA 		break;
7866e8394b8SKazutaka YOKOTA 
7876e8394b8SKazutaka YOKOTA 	case FBIO_GETWINORG:	/* get frame buffer window origin */
7886e8394b8SKazutaka YOKOTA 		*(u_int *)arg = adp->va_window_orig;
7896e8394b8SKazutaka YOKOTA 		break;
7906e8394b8SKazutaka YOKOTA 
7916e8394b8SKazutaka YOKOTA 	case FBIO_GETDISPSTART:	/* get display start address */
7926e8394b8SKazutaka YOKOTA 		((video_display_start_t *)arg)->x = adp->va_disp_start.x;
7936e8394b8SKazutaka YOKOTA 		((video_display_start_t *)arg)->y = adp->va_disp_start.y;
7946e8394b8SKazutaka YOKOTA 		break;
7956e8394b8SKazutaka YOKOTA 
7966e8394b8SKazutaka YOKOTA 	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
7976e8394b8SKazutaka YOKOTA 		*(u_int *)arg = adp->va_line_width;
7986e8394b8SKazutaka YOKOTA 		break;
7996e8394b8SKazutaka YOKOTA 
8006e8394b8SKazutaka YOKOTA 	case FBIO_GETPALETTE:	/* get color palette */
8016e8394b8SKazutaka YOKOTA 	case FBIO_SETPALETTE:	/* set color palette */
8026e8394b8SKazutaka YOKOTA 		/* XXX */
8036e8394b8SKazutaka YOKOTA 
8046e8394b8SKazutaka YOKOTA 	case FBIOPUTCMAP:
8056e8394b8SKazutaka YOKOTA 	case FBIOGETCMAP:
8066e8394b8SKazutaka YOKOTA 		/* XXX */
8076e8394b8SKazutaka YOKOTA 
8086e8394b8SKazutaka YOKOTA 	case FBIO_SETWINORG:	/* set frame buffer window origin */
8096e8394b8SKazutaka YOKOTA 	case FBIO_SETDISPSTART:	/* set display start address */
8106e8394b8SKazutaka YOKOTA 	case FBIO_SETLINEWIDTH:	/* set scan line width in pixel */
8116e8394b8SKazutaka YOKOTA 
8126e8394b8SKazutaka YOKOTA 	case FBIOGTYPE:
8136e8394b8SKazutaka YOKOTA 	case FBIOGATTR:
8146e8394b8SKazutaka YOKOTA 	case FBIOSVIDEO:
8156e8394b8SKazutaka YOKOTA 	case FBIOGVIDEO:
8166e8394b8SKazutaka YOKOTA 	case FBIOSCURSOR:
8176e8394b8SKazutaka YOKOTA 	case FBIOGCURSOR:
8186e8394b8SKazutaka YOKOTA 	case FBIOSCURPOS:
8196e8394b8SKazutaka YOKOTA 	case FBIOGCURPOS:
8206e8394b8SKazutaka YOKOTA 	case FBIOGCURMAX:
8216e8394b8SKazutaka YOKOTA 
8226e8394b8SKazutaka YOKOTA 	default:
8236e8394b8SKazutaka YOKOTA 		error = ENODEV;
8246e8394b8SKazutaka YOKOTA 		break;
8256e8394b8SKazutaka YOKOTA 	}
8266e8394b8SKazutaka YOKOTA 
8276e8394b8SKazutaka YOKOTA 	splx(s);
8286e8394b8SKazutaka YOKOTA 	return error;
8296e8394b8SKazutaka YOKOTA }
830