xref: /freebsd/sys/dev/fb/fb.c (revision aad970f1)
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  */
28617b9080SKazutaka YOKOTA 
29aad970f1SDavid E. O'Brien #include <sys/cdefs.h>
30aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$");
31aad970f1SDavid E. O'Brien 
32617b9080SKazutaka YOKOTA #include "opt_fb.h"
33617b9080SKazutaka YOKOTA 
34617b9080SKazutaka YOKOTA #include <sys/param.h>
35617b9080SKazutaka YOKOTA #include <sys/systm.h>
36617b9080SKazutaka YOKOTA #include <sys/conf.h>
376e8394b8SKazutaka YOKOTA #include <sys/bus.h>
38617b9080SKazutaka YOKOTA #include <sys/kernel.h>
39617b9080SKazutaka YOKOTA #include <sys/malloc.h>
402b120974SPeter Wemm #include <sys/module.h>
416e8394b8SKazutaka YOKOTA #include <sys/uio.h>
426e8394b8SKazutaka YOKOTA #include <sys/fbio.h>
43f41325dbSPeter Wemm #include <sys/linker_set.h>
44617b9080SKazutaka YOKOTA 
456e8394b8SKazutaka YOKOTA #include <vm/vm.h>
466e8394b8SKazutaka YOKOTA #include <vm/pmap.h>
47617b9080SKazutaka YOKOTA 
48617b9080SKazutaka YOKOTA #include <dev/fb/fbreg.h>
49617b9080SKazutaka YOKOTA 
50f41325dbSPeter Wemm SET_DECLARE(videodriver_set, const video_driver_t);
51f41325dbSPeter Wemm 
52617b9080SKazutaka YOKOTA /* local arrays */
53617b9080SKazutaka YOKOTA 
54617b9080SKazutaka YOKOTA /*
55617b9080SKazutaka YOKOTA  * We need at least one entry each in order to initialize a video card
56617b9080SKazutaka YOKOTA  * for the kernel console.  The arrays will be increased dynamically
57617b9080SKazutaka YOKOTA  * when necessary.
58617b9080SKazutaka YOKOTA  */
59617b9080SKazutaka YOKOTA 
606e8394b8SKazutaka YOKOTA static int		vid_malloc;
61617b9080SKazutaka YOKOTA static int		adapters = 1;
6290500a9dSKazutaka YOKOTA static video_adapter_t	*adp_ini;
6390500a9dSKazutaka YOKOTA static video_adapter_t	**adapter = &adp_ini;
6490500a9dSKazutaka YOKOTA static video_switch_t	*vidsw_ini;
65617b9080SKazutaka YOKOTA        video_switch_t	**vidsw = &vidsw_ini;
6690500a9dSKazutaka YOKOTA 
6790500a9dSKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
686e8394b8SKazutaka YOKOTA static struct cdevsw	*vidcdevsw_ini;
696e8394b8SKazutaka YOKOTA static struct cdevsw	**vidcdevsw = &vidcdevsw_ini;
706e8394b8SKazutaka YOKOTA #endif
71617b9080SKazutaka YOKOTA 
72617b9080SKazutaka YOKOTA #define ARRAY_DELTA	4
73617b9080SKazutaka YOKOTA 
746e8394b8SKazutaka YOKOTA static int
75617b9080SKazutaka YOKOTA vid_realloc_array(void)
76617b9080SKazutaka YOKOTA {
77617b9080SKazutaka YOKOTA 	video_adapter_t **new_adp;
78617b9080SKazutaka YOKOTA 	video_switch_t **new_vidsw;
796e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
80617b9080SKazutaka YOKOTA 	struct cdevsw **new_cdevsw;
816e8394b8SKazutaka YOKOTA #endif
82617b9080SKazutaka YOKOTA 	int newsize;
83617b9080SKazutaka YOKOTA 	int s;
84617b9080SKazutaka YOKOTA 
856e8394b8SKazutaka YOKOTA 	if (!vid_malloc)
866e8394b8SKazutaka YOKOTA 		return ENOMEM;
876e8394b8SKazutaka YOKOTA 
88617b9080SKazutaka YOKOTA 	s = spltty();
89617b9080SKazutaka YOKOTA 	newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
90a163d034SWarner Losh 	new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK | M_ZERO);
917cc0979fSDavid Malone 	new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF,
92a163d034SWarner Losh 	    M_WAITOK | M_ZERO);
936e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
947cc0979fSDavid Malone 	new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF,
95a163d034SWarner Losh 	    M_WAITOK | M_ZERO);
966e8394b8SKazutaka YOKOTA #endif
97617b9080SKazutaka YOKOTA 	bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
98617b9080SKazutaka YOKOTA 	bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
996e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
100617b9080SKazutaka YOKOTA 	bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
1016e8394b8SKazutaka YOKOTA #endif
102617b9080SKazutaka YOKOTA 	if (adapters > 1) {
103617b9080SKazutaka YOKOTA 		free(adapter, M_DEVBUF);
104617b9080SKazutaka YOKOTA 		free(vidsw, M_DEVBUF);
1056e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
106617b9080SKazutaka YOKOTA 		free(vidcdevsw, M_DEVBUF);
1076e8394b8SKazutaka YOKOTA #endif
108617b9080SKazutaka YOKOTA 	}
109617b9080SKazutaka YOKOTA 	adapter = new_adp;
110617b9080SKazutaka YOKOTA 	vidsw = new_vidsw;
1116e8394b8SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
112617b9080SKazutaka YOKOTA 	vidcdevsw = new_cdevsw;
1136e8394b8SKazutaka YOKOTA #endif
114617b9080SKazutaka YOKOTA 	adapters = newsize;
115617b9080SKazutaka YOKOTA 	splx(s);
116617b9080SKazutaka YOKOTA 
117617b9080SKazutaka YOKOTA 	if (bootverbose)
118617b9080SKazutaka YOKOTA 		printf("fb: new array size %d\n", adapters);
1196e8394b8SKazutaka YOKOTA 
1206e8394b8SKazutaka YOKOTA 	return 0;
121617b9080SKazutaka YOKOTA }
122617b9080SKazutaka YOKOTA 
1236e8394b8SKazutaka YOKOTA static void
1246e8394b8SKazutaka YOKOTA vid_malloc_init(void *arg)
1256e8394b8SKazutaka YOKOTA {
1266e8394b8SKazutaka YOKOTA 	vid_malloc = TRUE;
1276e8394b8SKazutaka YOKOTA }
1286e8394b8SKazutaka YOKOTA 
1296e8394b8SKazutaka YOKOTA SYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
13090500a9dSKazutaka YOKOTA 
131617b9080SKazutaka YOKOTA /*
132617b9080SKazutaka YOKOTA  * Low-level frame buffer driver functions
133617b9080SKazutaka YOKOTA  * frame buffer subdrivers, such as the VGA driver, call these functions
134617b9080SKazutaka YOKOTA  * to initialize the video_adapter structure and register it to the virtual
135617b9080SKazutaka YOKOTA  * frame buffer driver `fb'.
136617b9080SKazutaka YOKOTA  */
137617b9080SKazutaka YOKOTA 
138617b9080SKazutaka YOKOTA /* initialize the video_adapter_t structure */
139617b9080SKazutaka YOKOTA void
140617b9080SKazutaka YOKOTA vid_init_struct(video_adapter_t *adp, char *name, int type, int unit)
141617b9080SKazutaka YOKOTA {
142617b9080SKazutaka YOKOTA 	adp->va_flags = 0;
143617b9080SKazutaka YOKOTA 	adp->va_name = name;
144617b9080SKazutaka YOKOTA 	adp->va_type = type;
145617b9080SKazutaka YOKOTA 	adp->va_unit = unit;
146617b9080SKazutaka YOKOTA }
147617b9080SKazutaka YOKOTA 
148617b9080SKazutaka YOKOTA /* Register a video adapter */
149617b9080SKazutaka YOKOTA int
150617b9080SKazutaka YOKOTA vid_register(video_adapter_t *adp)
151617b9080SKazutaka YOKOTA {
1526e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
1536e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
154617b9080SKazutaka YOKOTA 	int index;
155617b9080SKazutaka YOKOTA 
156617b9080SKazutaka YOKOTA 	for (index = 0; index < adapters; ++index) {
157617b9080SKazutaka YOKOTA 		if (adapter[index] == NULL)
158617b9080SKazutaka YOKOTA 			break;
159617b9080SKazutaka YOKOTA 	}
1606e8394b8SKazutaka YOKOTA 	if (index >= adapters) {
1616e8394b8SKazutaka YOKOTA 		if (vid_realloc_array())
162617b9080SKazutaka YOKOTA 			return -1;
1636e8394b8SKazutaka YOKOTA 	}
164617b9080SKazutaka YOKOTA 
165617b9080SKazutaka YOKOTA 	adp->va_index = index;
166617b9080SKazutaka YOKOTA 	adp->va_token = NULL;
167f41325dbSPeter Wemm 	SET_FOREACH(list, videodriver_set) {
168f41325dbSPeter Wemm 		p = *list;
169617b9080SKazutaka YOKOTA 		if (strcmp(p->name, adp->va_name) == 0) {
170617b9080SKazutaka YOKOTA 			adapter[index] = adp;
171617b9080SKazutaka YOKOTA 			vidsw[index] = p->vidsw;
172617b9080SKazutaka YOKOTA 			return index;
173617b9080SKazutaka YOKOTA 		}
174617b9080SKazutaka YOKOTA 	}
175617b9080SKazutaka YOKOTA 
176617b9080SKazutaka YOKOTA 	return -1;
177617b9080SKazutaka YOKOTA }
178617b9080SKazutaka YOKOTA 
179617b9080SKazutaka YOKOTA int
180617b9080SKazutaka YOKOTA vid_unregister(video_adapter_t *adp)
181617b9080SKazutaka YOKOTA {
182617b9080SKazutaka YOKOTA 	if ((adp->va_index < 0) || (adp->va_index >= adapters))
183617b9080SKazutaka YOKOTA 		return ENOENT;
184617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
185617b9080SKazutaka YOKOTA 		return ENOENT;
186617b9080SKazutaka YOKOTA 
187617b9080SKazutaka YOKOTA 	adapter[adp->va_index] = NULL;
188617b9080SKazutaka YOKOTA 	vidsw[adp->va_index] = NULL;
189617b9080SKazutaka YOKOTA 	return 0;
190617b9080SKazutaka YOKOTA }
191617b9080SKazutaka YOKOTA 
192617b9080SKazutaka YOKOTA /* Get video I/O function table */
193617b9080SKazutaka YOKOTA video_switch_t
194617b9080SKazutaka YOKOTA *vid_get_switch(char *name)
195617b9080SKazutaka YOKOTA {
1966e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
1976e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
198617b9080SKazutaka YOKOTA 
199f41325dbSPeter Wemm 	SET_FOREACH(list, videodriver_set) {
200f41325dbSPeter Wemm 		p = *list;
201617b9080SKazutaka YOKOTA 		if (strcmp(p->name, name) == 0)
202617b9080SKazutaka YOKOTA 			return p->vidsw;
203617b9080SKazutaka YOKOTA 	}
204617b9080SKazutaka YOKOTA 
205617b9080SKazutaka YOKOTA 	return NULL;
206617b9080SKazutaka YOKOTA }
207617b9080SKazutaka YOKOTA 
208617b9080SKazutaka YOKOTA /*
209617b9080SKazutaka YOKOTA  * Video card client functions
210617b9080SKazutaka YOKOTA  * Video card clients, such as the console driver `syscons' and the frame
211617b9080SKazutaka YOKOTA  * buffer cdev driver, use these functions to claim and release a card for
212617b9080SKazutaka YOKOTA  * exclusive use.
213617b9080SKazutaka YOKOTA  */
214617b9080SKazutaka YOKOTA 
215617b9080SKazutaka YOKOTA /* find the video card specified by a driver name and a unit number */
216617b9080SKazutaka YOKOTA int
217617b9080SKazutaka YOKOTA vid_find_adapter(char *driver, int unit)
218617b9080SKazutaka YOKOTA {
219617b9080SKazutaka YOKOTA 	int i;
220617b9080SKazutaka YOKOTA 
221617b9080SKazutaka YOKOTA 	for (i = 0; i < adapters; ++i) {
222617b9080SKazutaka YOKOTA 		if (adapter[i] == NULL)
223617b9080SKazutaka YOKOTA 			continue;
224617b9080SKazutaka YOKOTA 		if (strcmp("*", driver) && strcmp(adapter[i]->va_name, driver))
225617b9080SKazutaka YOKOTA 			continue;
226617b9080SKazutaka YOKOTA 		if ((unit != -1) && (adapter[i]->va_unit != unit))
227617b9080SKazutaka YOKOTA 			continue;
228617b9080SKazutaka YOKOTA 		return i;
229617b9080SKazutaka YOKOTA 	}
230617b9080SKazutaka YOKOTA 	return -1;
231617b9080SKazutaka YOKOTA }
232617b9080SKazutaka YOKOTA 
233617b9080SKazutaka YOKOTA /* allocate a video card */
234617b9080SKazutaka YOKOTA int
235617b9080SKazutaka YOKOTA vid_allocate(char *driver, int unit, void *id)
236617b9080SKazutaka YOKOTA {
237617b9080SKazutaka YOKOTA 	int index;
238617b9080SKazutaka YOKOTA 	int s;
239617b9080SKazutaka YOKOTA 
240617b9080SKazutaka YOKOTA 	s = spltty();
241617b9080SKazutaka YOKOTA 	index = vid_find_adapter(driver, unit);
242617b9080SKazutaka YOKOTA 	if (index >= 0) {
243617b9080SKazutaka YOKOTA 		if (adapter[index]->va_token) {
244617b9080SKazutaka YOKOTA 			splx(s);
245617b9080SKazutaka YOKOTA 			return -1;
246617b9080SKazutaka YOKOTA 		}
247617b9080SKazutaka YOKOTA 		adapter[index]->va_token = id;
248617b9080SKazutaka YOKOTA 	}
249617b9080SKazutaka YOKOTA 	splx(s);
250617b9080SKazutaka YOKOTA 	return index;
251617b9080SKazutaka YOKOTA }
252617b9080SKazutaka YOKOTA 
253617b9080SKazutaka YOKOTA int
254617b9080SKazutaka YOKOTA vid_release(video_adapter_t *adp, void *id)
255617b9080SKazutaka YOKOTA {
256617b9080SKazutaka YOKOTA 	int error;
257617b9080SKazutaka YOKOTA 	int s;
258617b9080SKazutaka YOKOTA 
259617b9080SKazutaka YOKOTA 	s = spltty();
260617b9080SKazutaka YOKOTA 	if (adp->va_token == NULL) {
261617b9080SKazutaka YOKOTA 		error = EINVAL;
262617b9080SKazutaka YOKOTA 	} else if (adp->va_token != id) {
263617b9080SKazutaka YOKOTA 		error = EPERM;
264617b9080SKazutaka YOKOTA 	} else {
265617b9080SKazutaka YOKOTA 		adp->va_token = NULL;
266617b9080SKazutaka YOKOTA 		error = 0;
267617b9080SKazutaka YOKOTA 	}
268617b9080SKazutaka YOKOTA 	splx(s);
269617b9080SKazutaka YOKOTA 	return error;
270617b9080SKazutaka YOKOTA }
271617b9080SKazutaka YOKOTA 
272617b9080SKazutaka YOKOTA /* Get a video adapter structure */
273617b9080SKazutaka YOKOTA video_adapter_t
274617b9080SKazutaka YOKOTA *vid_get_adapter(int index)
275617b9080SKazutaka YOKOTA {
276617b9080SKazutaka YOKOTA 	if ((index < 0) || (index >= adapters))
277617b9080SKazutaka YOKOTA 		return NULL;
278617b9080SKazutaka YOKOTA 	return adapter[index];
279617b9080SKazutaka YOKOTA }
280617b9080SKazutaka YOKOTA 
281617b9080SKazutaka YOKOTA /* Configure drivers: this is a backdoor for the console driver XXX */
282617b9080SKazutaka YOKOTA int
283617b9080SKazutaka YOKOTA vid_configure(int flags)
284617b9080SKazutaka YOKOTA {
2856e8394b8SKazutaka YOKOTA 	const video_driver_t **list;
2866e8394b8SKazutaka YOKOTA 	const video_driver_t *p;
287617b9080SKazutaka YOKOTA 
288f41325dbSPeter Wemm 	SET_FOREACH(list, videodriver_set) {
289f41325dbSPeter Wemm 		p = *list;
290617b9080SKazutaka YOKOTA 		if (p->configure != NULL)
291617b9080SKazutaka YOKOTA 			(*p->configure)(flags);
292617b9080SKazutaka YOKOTA 	}
293617b9080SKazutaka YOKOTA 
294617b9080SKazutaka YOKOTA 	return 0;
295617b9080SKazutaka YOKOTA }
296617b9080SKazutaka YOKOTA 
297617b9080SKazutaka YOKOTA /*
298617b9080SKazutaka YOKOTA  * Virtual frame buffer cdev driver functions
299617b9080SKazutaka YOKOTA  * The virtual frame buffer driver dispatches driver functions to
300617b9080SKazutaka YOKOTA  * appropriate subdrivers.
301617b9080SKazutaka YOKOTA  */
302617b9080SKazutaka YOKOTA 
3036e8394b8SKazutaka YOKOTA #define FB_DRIVER_NAME	"fb"
304617b9080SKazutaka YOKOTA 
305617b9080SKazutaka YOKOTA #ifdef FB_INSTALL_CDEV
306617b9080SKazutaka YOKOTA 
3076e8394b8SKazutaka YOKOTA #if experimental
3086e8394b8SKazutaka YOKOTA 
3096e8394b8SKazutaka YOKOTA static devclass_t	fb_devclass;
3106e8394b8SKazutaka YOKOTA 
3116e8394b8SKazutaka YOKOTA static int		fbprobe(device_t dev);
3126e8394b8SKazutaka YOKOTA static int		fbattach(device_t dev);
3136e8394b8SKazutaka YOKOTA 
3146e8394b8SKazutaka YOKOTA static device_method_t fb_methods[] = {
3156e8394b8SKazutaka YOKOTA 	DEVMETHOD(device_probe,		fbprobe),
3166e8394b8SKazutaka YOKOTA 	DEVMETHOD(device_attach,	fbattach),
3176e8394b8SKazutaka YOKOTA 
3186e8394b8SKazutaka YOKOTA 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
3196e8394b8SKazutaka YOKOTA 	{ 0, 0 }
3206e8394b8SKazutaka YOKOTA };
3216e8394b8SKazutaka YOKOTA 
3226e8394b8SKazutaka YOKOTA static driver_t fb_driver = {
3236e8394b8SKazutaka YOKOTA 	FB_DRIVER_NAME,
3246e8394b8SKazutaka YOKOTA 	fb_methods,
3256e8394b8SKazutaka YOKOTA 	0,
3266e8394b8SKazutaka YOKOTA };
3276e8394b8SKazutaka YOKOTA 
3286e8394b8SKazutaka YOKOTA static int
3296e8394b8SKazutaka YOKOTA fbprobe(device_t dev)
3306e8394b8SKazutaka YOKOTA {
3316e8394b8SKazutaka YOKOTA 	int unit;
3326e8394b8SKazutaka YOKOTA 
3336e8394b8SKazutaka YOKOTA 	unit = device_get_unit(dev);
3346e8394b8SKazutaka YOKOTA 	if (unit >= adapters)
3356e8394b8SKazutaka YOKOTA 		return ENXIO;
3366e8394b8SKazutaka YOKOTA 	if (adapter[unit] == NULL)
3376e8394b8SKazutaka YOKOTA 		return ENXIO;
3386e8394b8SKazutaka YOKOTA 
3396e8394b8SKazutaka YOKOTA 	device_set_desc(dev, "generic frame buffer");
3406e8394b8SKazutaka YOKOTA 	return 0;
3416e8394b8SKazutaka YOKOTA }
3426e8394b8SKazutaka YOKOTA 
3436e8394b8SKazutaka YOKOTA static int
3446e8394b8SKazutaka YOKOTA fbattach(device_t dev)
3456e8394b8SKazutaka YOKOTA {
3466e8394b8SKazutaka YOKOTA 	printf("fbattach: about to attach children\n");
3476e8394b8SKazutaka YOKOTA 	bus_generic_attach(dev);
3486e8394b8SKazutaka YOKOTA 	return 0;
3496e8394b8SKazutaka YOKOTA }
3506e8394b8SKazutaka YOKOTA 
3516e8394b8SKazutaka YOKOTA #endif /* experimental */
3526e8394b8SKazutaka YOKOTA 
353617b9080SKazutaka YOKOTA #define FB_UNIT(dev)	minor(dev)
354617b9080SKazutaka YOKOTA #define FB_MKMINOR(unit) (u)
355617b9080SKazutaka YOKOTA 
3566d473442SPoul-Henning Kamp #if experimental
357617b9080SKazutaka YOKOTA static d_open_t		fbopen;
358617b9080SKazutaka YOKOTA static d_close_t	fbclose;
3596e8394b8SKazutaka YOKOTA static d_read_t		fbread;
3606e8394b8SKazutaka YOKOTA static d_write_t	fbwrite;
361617b9080SKazutaka YOKOTA static d_ioctl_t	fbioctl;
362617b9080SKazutaka YOKOTA static d_mmap_t		fbmmap;
363617b9080SKazutaka YOKOTA 
3646e8394b8SKazutaka YOKOTA #define CDEV_MAJOR	123	/* XXX */
365617b9080SKazutaka YOKOTA 
366617b9080SKazutaka YOKOTA static struct cdevsw fb_cdevsw = {
3677ac40f5fSPoul-Henning Kamp 	.d_open =	fbopen,
3687ac40f5fSPoul-Henning Kamp 	.d_close =	fbclose,
3697ac40f5fSPoul-Henning Kamp 	.d_read =	fbread,
3707ac40f5fSPoul-Henning Kamp 	.d_write =	fbwrite,
3717ac40f5fSPoul-Henning Kamp 	.d_ioctl =	fbioctl,
3727ac40f5fSPoul-Henning Kamp 	.d_mmap =	fbmmap,
3737ac40f5fSPoul-Henning Kamp 	.d_name =	FB_DRIVER_NAME,
3747ac40f5fSPoul-Henning Kamp 	.d_maj =	CDEV_MAJOR,
375617b9080SKazutaka YOKOTA };
3766d473442SPoul-Henning Kamp #endif
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:
3852b120974SPeter Wemm 		break;
3862b120974SPeter Wemm 	case MOD_UNLOAD:
3872b120974SPeter Wemm 		printf("fb module unload - not possible for this module type\n");
3882b120974SPeter Wemm 		return EINVAL;
389617b9080SKazutaka YOKOTA 	}
3902b120974SPeter Wemm 	return 0;
391617b9080SKazutaka YOKOTA }
392617b9080SKazutaka YOKOTA 
3932b120974SPeter Wemm static moduledata_t fb_mod = {
3942b120974SPeter Wemm 	"fb",
3952b120974SPeter Wemm 	fb_modevent,
3962b120974SPeter Wemm 	NULL
3972b120974SPeter Wemm };
3982b120974SPeter Wemm 
3992b120974SPeter Wemm DECLARE_MODULE(fb, fb_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
400617b9080SKazutaka YOKOTA 
401617b9080SKazutaka YOKOTA int
4026e8394b8SKazutaka YOKOTA fb_attach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
403617b9080SKazutaka YOKOTA {
404617b9080SKazutaka YOKOTA 	int s;
405617b9080SKazutaka YOKOTA 
406617b9080SKazutaka YOKOTA 	if (adp->va_index >= adapters)
407617b9080SKazutaka YOKOTA 		return EINVAL;
408617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
409617b9080SKazutaka YOKOTA 		return EINVAL;
410617b9080SKazutaka YOKOTA 
411617b9080SKazutaka YOKOTA 	s = spltty();
412617b9080SKazutaka YOKOTA 	adp->va_minor = minor(dev);
413617b9080SKazutaka YOKOTA 	vidcdevsw[adp->va_index] = cdevsw;
414617b9080SKazutaka YOKOTA 	splx(s);
415617b9080SKazutaka YOKOTA 
416617b9080SKazutaka YOKOTA 	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
417617b9080SKazutaka YOKOTA 	return 0;
418617b9080SKazutaka YOKOTA }
419617b9080SKazutaka YOKOTA 
420617b9080SKazutaka YOKOTA int
4216e8394b8SKazutaka YOKOTA fb_detach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
422617b9080SKazutaka YOKOTA {
423617b9080SKazutaka YOKOTA 	int s;
424617b9080SKazutaka YOKOTA 
425617b9080SKazutaka YOKOTA 	if (adp->va_index >= adapters)
426617b9080SKazutaka YOKOTA 		return EINVAL;
427617b9080SKazutaka YOKOTA 	if (adapter[adp->va_index] != adp)
428617b9080SKazutaka YOKOTA 		return EINVAL;
429617b9080SKazutaka YOKOTA 	if (vidcdevsw[adp->va_index] != cdevsw)
430617b9080SKazutaka YOKOTA 		return EINVAL;
431617b9080SKazutaka YOKOTA 
432617b9080SKazutaka YOKOTA 	s = spltty();
433617b9080SKazutaka YOKOTA 	vidcdevsw[adp->va_index] = NULL;
434617b9080SKazutaka YOKOTA 	splx(s);
435617b9080SKazutaka YOKOTA 	return 0;
436617b9080SKazutaka YOKOTA }
437617b9080SKazutaka YOKOTA 
4386d473442SPoul-Henning Kamp #if experimental
4396e8394b8SKazutaka YOKOTA static int
440b40ce416SJulian Elischer fbopen(dev_t dev, int flag, int mode, struct thread *td)
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),
450b40ce416SJulian Elischer 					  flag, mode, td);
4516e8394b8SKazutaka YOKOTA }
4526e8394b8SKazutaka YOKOTA 
4536e8394b8SKazutaka YOKOTA static int
454b40ce416SJulian Elischer fbclose(dev_t dev, int flag, int mode, struct thread *td)
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),
462b40ce416SJulian Elischer 					   flag, mode, td);
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
490b40ce416SJulian Elischer fbioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
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),
498b40ce416SJulian Elischer 					   cmd, arg, flag, td);
4996e8394b8SKazutaka YOKOTA }
5006e8394b8SKazutaka YOKOTA 
5016e8394b8SKazutaka YOKOTA static int
502227f9a1cSJake Burkholder fbmmap(dev_t dev, vm_offset_t offset, vm_paddr_t *paddr, 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),
51007159f9cSMaxime Henrion 					  offset, paddr, nprot);
5116e8394b8SKazutaka YOKOTA }
5126e8394b8SKazutaka YOKOTA 
513dfc161b4SJake Burkholder DEV_DRIVER_MODULE(fb, foo, fb_driver, fb_devclass, fb_cdevsw, 0, 0);
5146e8394b8SKazutaka YOKOTA #endif
5156e8394b8SKazutaka YOKOTA 
5166e8394b8SKazutaka YOKOTA /*
5176e8394b8SKazutaka YOKOTA  * Generic frame buffer cdev driver functions
5186e8394b8SKazutaka YOKOTA  * Frame buffer subdrivers may call these functions to implement common
5196e8394b8SKazutaka YOKOTA  * driver functions.
5206e8394b8SKazutaka YOKOTA  */
5216e8394b8SKazutaka YOKOTA 
5226e8394b8SKazutaka YOKOTA int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
523b40ce416SJulian Elischer 	      struct thread *td)
5246e8394b8SKazutaka YOKOTA {
5256e8394b8SKazutaka YOKOTA 	int s;
5266e8394b8SKazutaka YOKOTA 
5276e8394b8SKazutaka YOKOTA 	s = spltty();
5286e8394b8SKazutaka YOKOTA 	if (!(sc->gfb_flags & FB_OPEN))
5296e8394b8SKazutaka YOKOTA 		sc->gfb_flags |= FB_OPEN;
5306e8394b8SKazutaka YOKOTA 	splx(s);
5316e8394b8SKazutaka YOKOTA 	return 0;
5326e8394b8SKazutaka YOKOTA }
5336e8394b8SKazutaka YOKOTA 
5346e8394b8SKazutaka YOKOTA int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
535b40ce416SJulian Elischer 	       struct thread *td)
5366e8394b8SKazutaka YOKOTA {
5376e8394b8SKazutaka YOKOTA 	int s;
5386e8394b8SKazutaka YOKOTA 
5396e8394b8SKazutaka YOKOTA 	s = spltty();
5406e8394b8SKazutaka YOKOTA 	sc->gfb_flags &= ~FB_OPEN;
5416e8394b8SKazutaka YOKOTA 	splx(s);
5426e8394b8SKazutaka YOKOTA 	return 0;
5436e8394b8SKazutaka YOKOTA }
5446e8394b8SKazutaka YOKOTA 
5456e8394b8SKazutaka YOKOTA int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
5466e8394b8SKazutaka YOKOTA 	      int flag)
5476e8394b8SKazutaka YOKOTA {
5486e8394b8SKazutaka YOKOTA 	int size;
5496e8394b8SKazutaka YOKOTA 	int offset;
5506e8394b8SKazutaka YOKOTA 	int error;
5516e8394b8SKazutaka YOKOTA 	int len;
5526e8394b8SKazutaka YOKOTA 
5536e8394b8SKazutaka YOKOTA 	error = 0;
5546e8394b8SKazutaka YOKOTA 	size = adp->va_buffer_size/adp->va_info.vi_planes;
5556e8394b8SKazutaka YOKOTA 	while (uio->uio_resid > 0) {
5566e8394b8SKazutaka YOKOTA 		if (uio->uio_offset >= size)
5576e8394b8SKazutaka YOKOTA 			break;
5586e8394b8SKazutaka YOKOTA 		offset = uio->uio_offset%adp->va_window_size;
5596e8394b8SKazutaka YOKOTA 		len = imin(uio->uio_resid, size - uio->uio_offset);
5606e8394b8SKazutaka YOKOTA 		len = imin(len, adp->va_window_size - offset);
5616e8394b8SKazutaka YOKOTA 		if (len <= 0)
5626e8394b8SKazutaka YOKOTA 			break;
5636e8394b8SKazutaka YOKOTA 		(*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
5646e8394b8SKazutaka YOKOTA 		error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
5656e8394b8SKazutaka YOKOTA 		if (error)
5666e8394b8SKazutaka YOKOTA 			break;
5676e8394b8SKazutaka YOKOTA 	}
5686e8394b8SKazutaka YOKOTA 	return error;
5696e8394b8SKazutaka YOKOTA }
5706e8394b8SKazutaka YOKOTA 
5716e8394b8SKazutaka YOKOTA int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
5726e8394b8SKazutaka YOKOTA 	       int flag)
5736e8394b8SKazutaka YOKOTA {
5746e8394b8SKazutaka YOKOTA 	return ENODEV;
5756e8394b8SKazutaka YOKOTA }
5766e8394b8SKazutaka YOKOTA 
5776e8394b8SKazutaka YOKOTA int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
578b40ce416SJulian Elischer 	       caddr_t arg, int flag, struct thread *td)
5796e8394b8SKazutaka YOKOTA {
5806e8394b8SKazutaka YOKOTA 	int error;
5816e8394b8SKazutaka YOKOTA 
5826e8394b8SKazutaka YOKOTA 	if (adp == NULL)	/* XXX */
5836e8394b8SKazutaka YOKOTA 		return ENXIO;
5846e8394b8SKazutaka YOKOTA 	error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
5856e8394b8SKazutaka YOKOTA 	if (error == ENOIOCTL)
5866e8394b8SKazutaka YOKOTA 		error = ENODEV;
5876e8394b8SKazutaka YOKOTA 	return error;
5886e8394b8SKazutaka YOKOTA }
5896e8394b8SKazutaka YOKOTA 
5906e8394b8SKazutaka YOKOTA int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
59107159f9cSMaxime Henrion 	      vm_offset_t *paddr, int prot)
5926e8394b8SKazutaka YOKOTA {
59307159f9cSMaxime Henrion 	return (*vidsw[adp->va_index]->mmap)(adp, offset, paddr, prot);
5946e8394b8SKazutaka YOKOTA }
5956e8394b8SKazutaka YOKOTA 
596617b9080SKazutaka YOKOTA #endif /* FB_INSTALL_CDEV */
597617b9080SKazutaka YOKOTA 
598617b9080SKazutaka YOKOTA static char
599617b9080SKazutaka YOKOTA *adapter_name(int type)
600617b9080SKazutaka YOKOTA {
601617b9080SKazutaka YOKOTA     static struct {
602617b9080SKazutaka YOKOTA 	int type;
603617b9080SKazutaka YOKOTA 	char *name;
604617b9080SKazutaka YOKOTA     } names[] = {
605617b9080SKazutaka YOKOTA 	{ KD_MONO,	"MDA" },
606617b9080SKazutaka YOKOTA 	{ KD_HERCULES,	"Hercules" },
607617b9080SKazutaka YOKOTA 	{ KD_CGA,	"CGA" },
608617b9080SKazutaka YOKOTA 	{ KD_EGA,	"EGA" },
609617b9080SKazutaka YOKOTA 	{ KD_VGA,	"VGA" },
610617b9080SKazutaka YOKOTA 	{ KD_PC98,	"PC-98x1" },
6116e8394b8SKazutaka YOKOTA 	{ KD_TGA,	"TGA" },
612617b9080SKazutaka YOKOTA 	{ -1,		"Unknown" },
613617b9080SKazutaka YOKOTA     };
614617b9080SKazutaka YOKOTA     int i;
615617b9080SKazutaka YOKOTA 
616617b9080SKazutaka YOKOTA     for (i = 0; names[i].type != -1; ++i)
617617b9080SKazutaka YOKOTA 	if (names[i].type == type)
618617b9080SKazutaka YOKOTA 	    break;
619617b9080SKazutaka YOKOTA     return names[i].name;
620617b9080SKazutaka YOKOTA }
621617b9080SKazutaka YOKOTA 
6226e8394b8SKazutaka YOKOTA /*
6236e8394b8SKazutaka YOKOTA  * Generic low-level frame buffer functions
6246e8394b8SKazutaka YOKOTA  * The low-level functions in the frame buffer subdriver may use these
6256e8394b8SKazutaka YOKOTA  * functions.
6266e8394b8SKazutaka YOKOTA  */
6276e8394b8SKazutaka YOKOTA 
628617b9080SKazutaka YOKOTA void
629617b9080SKazutaka YOKOTA fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
630617b9080SKazutaka YOKOTA {
631617b9080SKazutaka YOKOTA     if (level <= 0)
632617b9080SKazutaka YOKOTA 	return;
633617b9080SKazutaka YOKOTA 
634617b9080SKazutaka YOKOTA     printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
6356e8394b8SKazutaka YOKOTA 	   FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
636617b9080SKazutaka YOKOTA 	   adapter_name(adp->va_type), adp->va_type, adp->va_flags);
6370301e9c8SDavid E. O'Brien     printf("%s%d: port:0x%lx-0x%lx, crtc:0x%lx, mem:0x%lx 0x%x\n",
6380301e9c8SDavid E. O'Brien 	   FB_DRIVER_NAME, adp->va_index, (u_long)adp->va_io_base,
6390301e9c8SDavid E. O'Brien 	   (u_long)adp->va_io_base + adp->va_io_size - 1,
6400301e9c8SDavid E. O'Brien 	   (u_long)adp->va_crtc_addr, (u_long)adp->va_mem_base,
6410301e9c8SDavid E. O'Brien 	   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);
6700301e9c8SDavid E. O'Brien     printf("win:0x%lx\n", (u_long)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 
800eac47d67SKazutaka YOKOTA 	case FBIO_BLANK:	/* blank display */
801eac47d67SKazutaka YOKOTA 		error = (*vidsw[adp->va_index]->blank_display)(adp, *(int *)arg);
802eac47d67SKazutaka YOKOTA 		break;
803eac47d67SKazutaka YOKOTA 
8046e8394b8SKazutaka YOKOTA 	case FBIO_GETPALETTE:	/* get color palette */
8056e8394b8SKazutaka YOKOTA 	case FBIO_SETPALETTE:	/* set color palette */
8066e8394b8SKazutaka YOKOTA 		/* XXX */
8076e8394b8SKazutaka YOKOTA 
8086e8394b8SKazutaka YOKOTA 	case FBIOPUTCMAP:
8096e8394b8SKazutaka YOKOTA 	case FBIOGETCMAP:
810eac47d67SKazutaka YOKOTA 	case FBIOPUTCMAPI:
811eac47d67SKazutaka YOKOTA 	case FBIOGETCMAPI:
8126e8394b8SKazutaka YOKOTA 		/* XXX */
8136e8394b8SKazutaka YOKOTA 
8146e8394b8SKazutaka YOKOTA 	case FBIO_SETWINORG:	/* set frame buffer window origin */
8156e8394b8SKazutaka YOKOTA 	case FBIO_SETDISPSTART:	/* set display start address */
8166e8394b8SKazutaka YOKOTA 	case FBIO_SETLINEWIDTH:	/* set scan line width in pixel */
8176e8394b8SKazutaka YOKOTA 
8186e8394b8SKazutaka YOKOTA 	case FBIOGTYPE:
8196e8394b8SKazutaka YOKOTA 	case FBIOGATTR:
8206e8394b8SKazutaka YOKOTA 	case FBIOSVIDEO:
8216e8394b8SKazutaka YOKOTA 	case FBIOGVIDEO:
822eac47d67SKazutaka YOKOTA 	case FBIOVERTICAL:
8236e8394b8SKazutaka YOKOTA 	case FBIOSCURSOR:
8246e8394b8SKazutaka YOKOTA 	case FBIOGCURSOR:
8256e8394b8SKazutaka YOKOTA 	case FBIOSCURPOS:
8266e8394b8SKazutaka YOKOTA 	case FBIOGCURPOS:
8276e8394b8SKazutaka YOKOTA 	case FBIOGCURMAX:
828eac47d67SKazutaka YOKOTA 	case FBIOMONINFO:
829eac47d67SKazutaka YOKOTA 	case FBIOGXINFO:
8306e8394b8SKazutaka YOKOTA 
8316e8394b8SKazutaka YOKOTA 	default:
8326e8394b8SKazutaka YOKOTA 		error = ENODEV;
8336e8394b8SKazutaka YOKOTA 		break;
8346e8394b8SKazutaka YOKOTA 	}
8356e8394b8SKazutaka YOKOTA 
8366e8394b8SKazutaka YOKOTA 	splx(s);
8376e8394b8SKazutaka YOKOTA 	return error;
8386e8394b8SKazutaka YOKOTA }
839