fb.c revision 132199
142421Syokota/*-
242421Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
342421Syokota * All rights reserved.
442421Syokota *
542421Syokota * Redistribution and use in source and binary forms, with or without
642421Syokota * modification, are permitted provided that the following conditions
742421Syokota * are met:
842421Syokota * 1. Redistributions of source code must retain the above copyright
942421Syokota *    notice, this list of conditions and the following disclaimer as
1042421Syokota *    the first lines of this file unmodified.
1142421Syokota * 2. Redistributions in binary form must reproduce the above copyright
1242421Syokota *    notice, this list of conditions and the following disclaimer in the
1342421Syokota *    documentation and/or other materials provided with the distribution.
1442421Syokota * 3. The name of the author may not be used to endorse or promote products
1542421Syokota *    derived from this software without specific prior written permission.
1642421Syokota *
1742421Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
1842421Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1942421Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2042421Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2142421Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2242421Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2342421Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2442421Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2542421Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2642421Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2742421Syokota */
2842421Syokota
29119418Sobrien#include <sys/cdefs.h>
30119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/fb/fb.c 132199 2004-07-15 08:26:07Z phk $");
31119418Sobrien
3242421Syokota#include "opt_fb.h"
3342421Syokota
3442421Syokota#include <sys/param.h>
3542421Syokota#include <sys/systm.h>
3642421Syokota#include <sys/conf.h>
3748104Syokota#include <sys/bus.h>
3842421Syokota#include <sys/kernel.h>
3942421Syokota#include <sys/malloc.h>
4071862Speter#include <sys/module.h>
4148104Syokota#include <sys/uio.h>
4248104Syokota#include <sys/fbio.h>
4378161Speter#include <sys/linker_set.h>
4442421Syokota
4548104Syokota#include <vm/vm.h>
4648104Syokota#include <vm/pmap.h>
4742421Syokota
4842421Syokota#include <dev/fb/fbreg.h>
4942421Syokota
5078161SpeterSET_DECLARE(videodriver_set, const video_driver_t);
5178161Speter
5242421Syokota/* local arrays */
5342421Syokota
5442421Syokota/*
5542421Syokota * We need at least one entry each in order to initialize a video card
5642421Syokota * for the kernel console.  The arrays will be increased dynamically
5742421Syokota * when necessary.
5842421Syokota */
5942564Syokota
6048104Syokotastatic int		vid_malloc;
6142564Syokotastatic int		adapters = 1;
6242421Syokotastatic video_adapter_t	*adp_ini;
6342564Syokotastatic video_adapter_t	**adapter = &adp_ini;
6442421Syokotastatic video_switch_t	*vidsw_ini;
6542421Syokota       video_switch_t	**vidsw = &vidsw_ini;
6642421Syokota
6742564Syokota#ifdef FB_INSTALL_CDEV
6848104Syokotastatic struct cdevsw	*vidcdevsw_ini;
6948104Syokotastatic struct cdevsw	**vidcdevsw = &vidcdevsw_ini;
7048104Syokota#endif
7142564Syokota
7242421Syokota#define ARRAY_DELTA	4
7342421Syokota
7448104Syokotastatic int
7542421Syokotavid_realloc_array(void)
7642421Syokota{
7742421Syokota	video_adapter_t **new_adp;
7842421Syokota	video_switch_t **new_vidsw;
7948104Syokota#ifdef FB_INSTALL_CDEV
8042421Syokota	struct cdevsw **new_cdevsw;
8148104Syokota#endif
8242421Syokota	int newsize;
8342421Syokota	int s;
8442421Syokota
8548104Syokota	if (!vid_malloc)
8648104Syokota		return ENOMEM;
8748104Syokota
8842421Syokota	s = spltty();
8942421Syokota	newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
90111119Simp	new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK | M_ZERO);
9169781Sdwmalone	new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF,
92111119Simp	    M_WAITOK | M_ZERO);
9348104Syokota#ifdef FB_INSTALL_CDEV
9469781Sdwmalone	new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF,
95111119Simp	    M_WAITOK | M_ZERO);
9648104Syokota#endif
9742421Syokota	bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
9842421Syokota	bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
9948104Syokota#ifdef FB_INSTALL_CDEV
10042421Syokota	bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
10148104Syokota#endif
10242421Syokota	if (adapters > 1) {
10342421Syokota		free(adapter, M_DEVBUF);
10442421Syokota		free(vidsw, M_DEVBUF);
10548104Syokota#ifdef FB_INSTALL_CDEV
10642421Syokota		free(vidcdevsw, M_DEVBUF);
10748104Syokota#endif
10842421Syokota	}
10942421Syokota	adapter = new_adp;
11042421Syokota	vidsw = new_vidsw;
11148104Syokota#ifdef FB_INSTALL_CDEV
11242421Syokota	vidcdevsw = new_cdevsw;
11348104Syokota#endif
11442421Syokota	adapters = newsize;
11542421Syokota	splx(s);
11642421Syokota
11742421Syokota	if (bootverbose)
11842421Syokota		printf("fb: new array size %d\n", adapters);
11948104Syokota
12048104Syokota	return 0;
12142421Syokota}
12242421Syokota
12348104Syokotastatic void
12448104Syokotavid_malloc_init(void *arg)
12548104Syokota{
12648104Syokota	vid_malloc = TRUE;
12748104Syokota}
12842564Syokota
12948104SyokotaSYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
13048104Syokota
13142421Syokota/*
13242421Syokota * Low-level frame buffer driver functions
13342421Syokota * frame buffer subdrivers, such as the VGA driver, call these functions
13442421Syokota * to initialize the video_adapter structure and register it to the virtual
13542421Syokota * frame buffer driver `fb'.
13642421Syokota */
13742421Syokota
13842421Syokota/* initialize the video_adapter_t structure */
13942421Syokotavoid
14042421Syokotavid_init_struct(video_adapter_t *adp, char *name, int type, int unit)
14142421Syokota{
14242421Syokota	adp->va_flags = 0;
14342421Syokota	adp->va_name = name;
14442421Syokota	adp->va_type = type;
14542421Syokota	adp->va_unit = unit;
14642421Syokota}
14742421Syokota
14842421Syokota/* Register a video adapter */
14942421Syokotaint
15042421Syokotavid_register(video_adapter_t *adp)
15142421Syokota{
15248104Syokota	const video_driver_t **list;
15348104Syokota	const video_driver_t *p;
15442421Syokota	int index;
15542421Syokota
15642421Syokota	for (index = 0; index < adapters; ++index) {
15742421Syokota		if (adapter[index] == NULL)
15842421Syokota			break;
15942421Syokota	}
16048104Syokota	if (index >= adapters) {
16148104Syokota		if (vid_realloc_array())
16248104Syokota			return -1;
16348104Syokota	}
16442421Syokota
16542421Syokota	adp->va_index = index;
16642421Syokota	adp->va_token = NULL;
16778161Speter	SET_FOREACH(list, videodriver_set) {
16878161Speter		p = *list;
16942421Syokota		if (strcmp(p->name, adp->va_name) == 0) {
17042421Syokota			adapter[index] = adp;
17142421Syokota			vidsw[index] = p->vidsw;
17242421Syokota			return index;
17342421Syokota		}
17442421Syokota	}
17542421Syokota
17642421Syokota	return -1;
17742421Syokota}
17842421Syokota
17942421Syokotaint
18042421Syokotavid_unregister(video_adapter_t *adp)
18142421Syokota{
18242421Syokota	if ((adp->va_index < 0) || (adp->va_index >= adapters))
18342421Syokota		return ENOENT;
18442421Syokota	if (adapter[adp->va_index] != adp)
18542421Syokota		return ENOENT;
18642421Syokota
18742421Syokota	adapter[adp->va_index] = NULL;
18842421Syokota	vidsw[adp->va_index] = NULL;
18942421Syokota	return 0;
19042421Syokota}
19142421Syokota
19242421Syokota/* Get video I/O function table */
19342421Syokotavideo_switch_t
19442421Syokota*vid_get_switch(char *name)
19542421Syokota{
19648104Syokota	const video_driver_t **list;
19748104Syokota	const video_driver_t *p;
19842421Syokota
19978161Speter	SET_FOREACH(list, videodriver_set) {
20078161Speter		p = *list;
20142421Syokota		if (strcmp(p->name, name) == 0)
20242421Syokota			return p->vidsw;
20342421Syokota	}
20442421Syokota
20542421Syokota	return NULL;
20642421Syokota}
20742421Syokota
20842421Syokota/*
20942421Syokota * Video card client functions
21042421Syokota * Video card clients, such as the console driver `syscons' and the frame
21142421Syokota * buffer cdev driver, use these functions to claim and release a card for
21242421Syokota * exclusive use.
21342421Syokota */
21442421Syokota
21542421Syokota/* find the video card specified by a driver name and a unit number */
21642421Syokotaint
21742421Syokotavid_find_adapter(char *driver, int unit)
21842421Syokota{
21942421Syokota	int i;
22042421Syokota
22142421Syokota	for (i = 0; i < adapters; ++i) {
22242421Syokota		if (adapter[i] == NULL)
22342421Syokota			continue;
22442421Syokota		if (strcmp("*", driver) && strcmp(adapter[i]->va_name, driver))
22542421Syokota			continue;
22642421Syokota		if ((unit != -1) && (adapter[i]->va_unit != unit))
22742421Syokota			continue;
22842421Syokota		return i;
22942421Syokota	}
23042421Syokota	return -1;
23142421Syokota}
23242421Syokota
23342421Syokota/* allocate a video card */
23442421Syokotaint
23542421Syokotavid_allocate(char *driver, int unit, void *id)
23642421Syokota{
23742421Syokota	int index;
23842421Syokota	int s;
23942421Syokota
24042421Syokota	s = spltty();
24142421Syokota	index = vid_find_adapter(driver, unit);
24242421Syokota	if (index >= 0) {
24342421Syokota		if (adapter[index]->va_token) {
24442421Syokota			splx(s);
24542421Syokota			return -1;
24642421Syokota		}
24742421Syokota		adapter[index]->va_token = id;
24842421Syokota	}
24942421Syokota	splx(s);
25042421Syokota	return index;
25142421Syokota}
25242421Syokota
25342421Syokotaint
25442421Syokotavid_release(video_adapter_t *adp, void *id)
25542421Syokota{
25642421Syokota	int error;
25742421Syokota	int s;
25842421Syokota
25942421Syokota	s = spltty();
26042421Syokota	if (adp->va_token == NULL) {
26142421Syokota		error = EINVAL;
26242421Syokota	} else if (adp->va_token != id) {
26342421Syokota		error = EPERM;
26442421Syokota	} else {
26542421Syokota		adp->va_token = NULL;
26642421Syokota		error = 0;
26742421Syokota	}
26842421Syokota	splx(s);
26942421Syokota	return error;
27042421Syokota}
27142421Syokota
27242421Syokota/* Get a video adapter structure */
27342421Syokotavideo_adapter_t
27442421Syokota*vid_get_adapter(int index)
27542421Syokota{
27642421Syokota	if ((index < 0) || (index >= adapters))
27742421Syokota		return NULL;
27842421Syokota	return adapter[index];
27942421Syokota}
28042421Syokota
28142421Syokota/* Configure drivers: this is a backdoor for the console driver XXX */
28242421Syokotaint
28342421Syokotavid_configure(int flags)
28442421Syokota{
28548104Syokota	const video_driver_t **list;
28648104Syokota	const video_driver_t *p;
28742421Syokota
28878161Speter	SET_FOREACH(list, videodriver_set) {
28978161Speter		p = *list;
29042421Syokota		if (p->configure != NULL)
29142421Syokota			(*p->configure)(flags);
29242421Syokota	}
29342421Syokota
29442421Syokota	return 0;
29542421Syokota}
29642421Syokota
29742421Syokota/*
29842421Syokota * Virtual frame buffer cdev driver functions
29942421Syokota * The virtual frame buffer driver dispatches driver functions to
30042421Syokota * appropriate subdrivers.
30142421Syokota */
30242421Syokota
30348104Syokota#define FB_DRIVER_NAME	"fb"
30442421Syokota
30542421Syokota#ifdef FB_INSTALL_CDEV
30642421Syokota
30748104Syokota#if experimental
30848104Syokota
30948104Syokotastatic devclass_t	fb_devclass;
31048104Syokota
31148104Syokotastatic int		fbprobe(device_t dev);
31248104Syokotastatic int		fbattach(device_t dev);
31348104Syokota
31448104Syokotastatic device_method_t fb_methods[] = {
31548104Syokota	DEVMETHOD(device_probe,		fbprobe),
31648104Syokota	DEVMETHOD(device_attach,	fbattach),
31748104Syokota
31848104Syokota	DEVMETHOD(bus_print_child,	bus_generic_print_child),
31948104Syokota	{ 0, 0 }
32048104Syokota};
32148104Syokota
32248104Syokotastatic driver_t fb_driver = {
32348104Syokota	FB_DRIVER_NAME,
32448104Syokota	fb_methods,
32548104Syokota	0,
32648104Syokota};
32748104Syokota
32848104Syokotastatic int
32948104Syokotafbprobe(device_t dev)
33048104Syokota{
33148104Syokota	int unit;
33248104Syokota
33348104Syokota	unit = device_get_unit(dev);
33448104Syokota	if (unit >= adapters)
33548104Syokota		return ENXIO;
33648104Syokota	if (adapter[unit] == NULL)
33748104Syokota		return ENXIO;
33848104Syokota
33948104Syokota	device_set_desc(dev, "generic frame buffer");
34048104Syokota	return 0;
34148104Syokota}
34248104Syokota
34348104Syokotastatic int
34448104Syokotafbattach(device_t dev)
34548104Syokota{
34648104Syokota	printf("fbattach: about to attach children\n");
34748104Syokota	bus_generic_attach(dev);
34848104Syokota	return 0;
34948104Syokota}
35048104Syokota
35148104Syokota#endif /* experimental */
35248104Syokota
35342421Syokota#define FB_UNIT(dev)	minor(dev)
35442421Syokota#define FB_MKMINOR(unit) (u)
35542421Syokota
356111576Sphk#if experimental
35742421Syokotastatic d_open_t		fbopen;
35842421Syokotastatic d_close_t	fbclose;
35948104Syokotastatic d_read_t		fbread;
36048104Syokotastatic d_write_t	fbwrite;
36142421Syokotastatic d_ioctl_t	fbioctl;
36242421Syokotastatic d_mmap_t		fbmmap;
36342421Syokota
36442421Syokota
36542421Syokotastatic struct cdevsw fb_cdevsw = {
366126080Sphk	.d_version =	D_VERSION,
367126080Sphk	.d_flags =	D_NEEDGIANT,
368111815Sphk	.d_open =	fbopen,
369111815Sphk	.d_close =	fbclose,
370111815Sphk	.d_read =	fbread,
371111815Sphk	.d_write =	fbwrite,
372111815Sphk	.d_ioctl =	fbioctl,
373111815Sphk	.d_mmap =	fbmmap,
374111815Sphk	.d_name =	FB_DRIVER_NAME,
37542421Syokota};
376111576Sphk#endif
37742421Syokota
37842421Syokota
37971862Speterstatic int
38071862Speterfb_modevent(module_t mod, int type, void *data)
38171862Speter{
38271862Speter
38371862Speter	switch (type) {
38471862Speter	case MOD_LOAD:
38571862Speter		break;
38671862Speter	case MOD_UNLOAD:
38771862Speter		printf("fb module unload - not possible for this module type\n");
38871862Speter		return EINVAL;
389132199Sphk	default:
390132199Sphk		return EOPNOTSUPP;
39171862Speter	}
39271862Speter	return 0;
39371862Speter}
39442421Syokota
39571862Speterstatic moduledata_t fb_mod = {
39671862Speter	"fb",
39771862Speter	fb_modevent,
39871862Speter	NULL
39971862Speter};
40042421Syokota
40171862SpeterDECLARE_MODULE(fb, fb_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
40271862Speter
40342421Syokotaint
404120465Sphkfb_attach(int unit, video_adapter_t *adp, struct cdevsw *cdevsw)
40542421Syokota{
40642421Syokota	int s;
40742421Syokota
40842421Syokota	if (adp->va_index >= adapters)
40942421Syokota		return EINVAL;
41042421Syokota	if (adapter[adp->va_index] != adp)
41142421Syokota		return EINVAL;
41242421Syokota
41342421Syokota	s = spltty();
414120465Sphk	adp->va_minor = unit;
41542421Syokota	vidcdevsw[adp->va_index] = cdevsw;
41642421Syokota	splx(s);
41742421Syokota
41842421Syokota	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
41942421Syokota	return 0;
42042421Syokota}
42142421Syokota
42242421Syokotaint
423120465Sphkfb_detach(int unit, video_adapter_t *adp, struct cdevsw *cdevsw)
42442421Syokota{
42542421Syokota	int s;
42642421Syokota
42742421Syokota	if (adp->va_index >= adapters)
42842421Syokota		return EINVAL;
42942421Syokota	if (adapter[adp->va_index] != adp)
43042421Syokota		return EINVAL;
43142421Syokota	if (vidcdevsw[adp->va_index] != cdevsw)
43242421Syokota		return EINVAL;
43342421Syokota
43442421Syokota	s = spltty();
43542421Syokota	vidcdevsw[adp->va_index] = NULL;
43642421Syokota	splx(s);
43742421Syokota	return 0;
43842421Syokota}
43942421Syokota
44048104Syokota/*
44148104Syokota * Generic frame buffer cdev driver functions
44248104Syokota * Frame buffer subdrivers may call these functions to implement common
44348104Syokota * driver functions.
44448104Syokota */
44548104Syokota
44648104Syokotaint genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
44783366Sjulian	      struct thread *td)
44848104Syokota{
44948104Syokota	int s;
45048104Syokota
45148104Syokota	s = spltty();
45248104Syokota	if (!(sc->gfb_flags & FB_OPEN))
45348104Syokota		sc->gfb_flags |= FB_OPEN;
45448104Syokota	splx(s);
45548104Syokota	return 0;
45648104Syokota}
45748104Syokota
45848104Syokotaint genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
45983366Sjulian	       struct thread *td)
46048104Syokota{
46148104Syokota	int s;
46248104Syokota
46348104Syokota	s = spltty();
46448104Syokota	sc->gfb_flags &= ~FB_OPEN;
46548104Syokota	splx(s);
46648104Syokota	return 0;
46748104Syokota}
46848104Syokota
46948104Syokotaint genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
47048104Syokota	      int flag)
47148104Syokota{
47248104Syokota	int size;
47348104Syokota	int offset;
47448104Syokota	int error;
47548104Syokota	int len;
47648104Syokota
47748104Syokota	error = 0;
47848104Syokota	size = adp->va_buffer_size/adp->va_info.vi_planes;
47948104Syokota	while (uio->uio_resid > 0) {
48048104Syokota		if (uio->uio_offset >= size)
48148104Syokota			break;
48248104Syokota		offset = uio->uio_offset%adp->va_window_size;
48348104Syokota		len = imin(uio->uio_resid, size - uio->uio_offset);
48448104Syokota		len = imin(len, adp->va_window_size - offset);
48548104Syokota		if (len <= 0)
48648104Syokota			break;
48748104Syokota		(*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
48848104Syokota		error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
48948104Syokota		if (error)
49048104Syokota			break;
49148104Syokota	}
49248104Syokota	return error;
49348104Syokota}
49448104Syokota
49548104Syokotaint genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
49648104Syokota	       int flag)
49748104Syokota{
49848104Syokota	return ENODEV;
49948104Syokota}
50048104Syokota
50148104Syokotaint genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
50283366Sjulian	       caddr_t arg, int flag, struct thread *td)
50348104Syokota{
50448104Syokota	int error;
50548104Syokota
50648104Syokota	if (adp == NULL)	/* XXX */
50748104Syokota		return ENXIO;
50848104Syokota	error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
50948104Syokota	if (error == ENOIOCTL)
51048104Syokota		error = ENODEV;
51148104Syokota	return error;
51248104Syokota}
51348104Syokota
51448104Syokotaint genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
515111462Smux	      vm_offset_t *paddr, int prot)
51648104Syokota{
517111462Smux	return (*vidsw[adp->va_index]->mmap)(adp, offset, paddr, prot);
51848104Syokota}
51948104Syokota
52042421Syokota#endif /* FB_INSTALL_CDEV */
52142421Syokota
52242421Syokotastatic char
52342421Syokota*adapter_name(int type)
52442421Syokota{
52542421Syokota    static struct {
52642421Syokota	int type;
52742421Syokota	char *name;
52842421Syokota    } names[] = {
52942421Syokota	{ KD_MONO,	"MDA" },
53042421Syokota	{ KD_HERCULES,	"Hercules" },
53142421Syokota	{ KD_CGA,	"CGA" },
53242421Syokota	{ KD_EGA,	"EGA" },
53342421Syokota	{ KD_VGA,	"VGA" },
53442421Syokota	{ KD_PC98,	"PC-98x1" },
53548104Syokota	{ KD_TGA,	"TGA" },
53642421Syokota	{ -1,		"Unknown" },
53742421Syokota    };
53842421Syokota    int i;
53942421Syokota
54042421Syokota    for (i = 0; names[i].type != -1; ++i)
54142421Syokota	if (names[i].type == type)
54242421Syokota	    break;
54342421Syokota    return names[i].name;
54442421Syokota}
54542421Syokota
54648104Syokota/*
54748104Syokota * Generic low-level frame buffer functions
54848104Syokota * The low-level functions in the frame buffer subdriver may use these
54948104Syokota * functions.
55048104Syokota */
55148104Syokota
55242421Syokotavoid
55342421Syokotafb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
55442421Syokota{
55542421Syokota    if (level <= 0)
55642421Syokota	return;
55742421Syokota
55842421Syokota    printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
55948104Syokota	   FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
56042421Syokota	   adapter_name(adp->va_type), adp->va_type, adp->va_flags);
56194617Sobrien    printf("%s%d: port:0x%lx-0x%lx, crtc:0x%lx, mem:0x%lx 0x%x\n",
56294617Sobrien	   FB_DRIVER_NAME, adp->va_index, (u_long)adp->va_io_base,
56394617Sobrien	   (u_long)adp->va_io_base + adp->va_io_size - 1,
56494617Sobrien	   (u_long)adp->va_crtc_addr, (u_long)adp->va_mem_base,
56594617Sobrien	   adp->va_mem_size);
56642421Syokota    printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
56748104Syokota	   FB_DRIVER_NAME, adp->va_index,
56842421Syokota	   adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
56948104Syokota    printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
57048104Syokota	   FB_DRIVER_NAME, adp->va_index,
57148104Syokota	   (void *)adp->va_window, (int)adp->va_window_size/1024,
57248104Syokota	   (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
57342831Syokota	   (int)adp->va_buffer_size/1024);
57442421Syokota}
57542421Syokota
57642421Syokotavoid
57742421Syokotafb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
57842421Syokota		  int level)
57942421Syokota{
58042421Syokota    if (level <= 0)
58142421Syokota	return;
58242421Syokota
58342421Syokota    printf("%s%d: %s, mode:%d, flags:0x%x ",
58442421Syokota	   driver, adp->va_unit, adp->va_name, info->vi_mode, info->vi_flags);
58542421Syokota    if (info->vi_flags & V_INFO_GRAPHICS)
58642421Syokota	printf("G %dx%dx%d, %d plane(s), font:%dx%d, ",
58742421Syokota	       info->vi_width, info->vi_height,
58842421Syokota	       info->vi_depth, info->vi_planes,
58942421Syokota	       info->vi_cwidth, info->vi_cheight);
59042421Syokota    else
59142421Syokota	printf("T %dx%d, font:%dx%d, ",
59242421Syokota	       info->vi_width, info->vi_height,
59342421Syokota	       info->vi_cwidth, info->vi_cheight);
59494617Sobrien    printf("win:0x%lx\n", (u_long)info->vi_window);
59542421Syokota}
59648104Syokota
59748104Syokotaint
59848104Syokotafb_type(int adp_type)
59948104Syokota{
60048104Syokota	static struct {
60148104Syokota		int	fb_type;
60248104Syokota		int	va_type;
60348104Syokota	} types[] = {
60448104Syokota		{ FBTYPE_MDA,		KD_MONO },
60548104Syokota		{ FBTYPE_HERCULES,	KD_HERCULES },
60648104Syokota		{ FBTYPE_CGA,		KD_CGA },
60748104Syokota		{ FBTYPE_EGA,		KD_EGA },
60848104Syokota		{ FBTYPE_VGA,		KD_VGA },
60948104Syokota		{ FBTYPE_PC98,		KD_PC98 },
61048104Syokota		{ FBTYPE_TGA,		KD_TGA },
61148104Syokota	};
61248104Syokota	int i;
61348104Syokota
61448104Syokota	for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
61548104Syokota		if (types[i].va_type == adp_type)
61648104Syokota			return types[i].fb_type;
61748104Syokota	}
61848104Syokota	return -1;
61948104Syokota}
62048104Syokota
62148104Syokotaint
62248104Syokotafb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
62348104Syokota{
62448104Syokota	int error;
62548104Syokota	int s;
62648104Syokota
62748104Syokota	/* assert(adp != NULL) */
62848104Syokota
62948104Syokota	error = 0;
63048104Syokota	s = spltty();
63148104Syokota
63248104Syokota	switch (cmd) {
63348104Syokota
63448104Syokota	case FBIO_ADAPTER:	/* get video adapter index */
63548104Syokota		*(int *)arg = adp->va_index;
63648104Syokota		break;
63748104Syokota
63848104Syokota	case FBIO_ADPTYPE:	/* get video adapter type */
63948104Syokota		*(int *)arg = adp->va_type;
64048104Syokota		break;
64148104Syokota
64248104Syokota	case FBIO_ADPINFO:	/* get video adapter info */
64348104Syokota	        ((video_adapter_info_t *)arg)->va_index = adp->va_index;
64448104Syokota		((video_adapter_info_t *)arg)->va_type = adp->va_type;
64548104Syokota		bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
64648104Syokota		      imin(strlen(adp->va_name) + 1,
64748104Syokota			   sizeof(((video_adapter_info_t *)arg)->va_name)));
64848104Syokota		((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
64948104Syokota		((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
65048104Syokota		((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
65148104Syokota		((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
65248104Syokota		((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
65348104Syokota		((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
65448104Syokota		((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
65548104Syokota		((video_adapter_info_t *)arg)->va_window
65660742Sgallatin#ifdef __i386__
65748104Syokota			= vtophys(adp->va_window);
65860742Sgallatin#else
65960742Sgallatin			= adp->va_window;
66060742Sgallatin#endif
66148104Syokota		((video_adapter_info_t *)arg)->va_window_size
66248104Syokota			= adp->va_window_size;
66348104Syokota		((video_adapter_info_t *)arg)->va_window_gran
66448104Syokota			= adp->va_window_gran;
66548104Syokota		((video_adapter_info_t *)arg)->va_window_orig
66648104Syokota			= adp->va_window_orig;
66748104Syokota		((video_adapter_info_t *)arg)->va_unused0
66860742Sgallatin#ifdef __i386__
66948104Syokota			= (adp->va_buffer) ? vtophys(adp->va_buffer) : 0;
67060742Sgallatin#else
67160742Sgallatin			= adp->va_buffer;
67260742Sgallatin#endif
67348104Syokota		((video_adapter_info_t *)arg)->va_buffer_size
67448104Syokota			= adp->va_buffer_size;
67548104Syokota		((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
67648104Syokota		((video_adapter_info_t *)arg)->va_initial_mode
67748104Syokota			= adp->va_initial_mode;
67848104Syokota		((video_adapter_info_t *)arg)->va_initial_bios_mode
67948104Syokota			= adp->va_initial_bios_mode;
68048104Syokota		((video_adapter_info_t *)arg)->va_line_width
68148104Syokota			= adp->va_line_width;
68248104Syokota		((video_adapter_info_t *)arg)->va_disp_start.x
68348104Syokota			= adp->va_disp_start.x;
68448104Syokota		((video_adapter_info_t *)arg)->va_disp_start.y
68548104Syokota			= adp->va_disp_start.y;
68648104Syokota		break;
68748104Syokota
68848104Syokota	case FBIO_MODEINFO:	/* get mode information */
68948104Syokota		error = (*vidsw[adp->va_index]->get_info)(adp,
69048104Syokota				((video_info_t *)arg)->vi_mode,
69148104Syokota				(video_info_t *)arg);
69248104Syokota		if (error)
69348104Syokota			error = ENODEV;
69448104Syokota		break;
69548104Syokota
69648104Syokota	case FBIO_FINDMODE:	/* find a matching video mode */
69748104Syokota		error = (*vidsw[adp->va_index]->query_mode)(adp,
69848104Syokota				(video_info_t *)arg);
69948104Syokota		break;
70048104Syokota
70148104Syokota	case FBIO_GETMODE:	/* get video mode */
70248104Syokota		*(int *)arg = adp->va_mode;
70348104Syokota		break;
70448104Syokota
70548104Syokota	case FBIO_SETMODE:	/* set video mode */
70648104Syokota		error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg);
70748104Syokota		if (error)
70848104Syokota			error = ENODEV;	/* EINVAL? */
70948104Syokota		break;
71048104Syokota
71148104Syokota	case FBIO_GETWINORG:	/* get frame buffer window origin */
71248104Syokota		*(u_int *)arg = adp->va_window_orig;
71348104Syokota		break;
71448104Syokota
71548104Syokota	case FBIO_GETDISPSTART:	/* get display start address */
71648104Syokota		((video_display_start_t *)arg)->x = adp->va_disp_start.x;
71748104Syokota		((video_display_start_t *)arg)->y = adp->va_disp_start.y;
71848104Syokota		break;
71948104Syokota
72048104Syokota	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
72148104Syokota		*(u_int *)arg = adp->va_line_width;
72248104Syokota		break;
72348104Syokota
72481039Syokota	case FBIO_BLANK:	/* blank display */
72581039Syokota		error = (*vidsw[adp->va_index]->blank_display)(adp, *(int *)arg);
72681039Syokota		break;
72781039Syokota
72848104Syokota	case FBIO_GETPALETTE:	/* get color palette */
72948104Syokota	case FBIO_SETPALETTE:	/* set color palette */
73048104Syokota		/* XXX */
73148104Syokota
73248104Syokota	case FBIOPUTCMAP:
73348104Syokota	case FBIOGETCMAP:
73481039Syokota	case FBIOPUTCMAPI:
73581039Syokota	case FBIOGETCMAPI:
73648104Syokota		/* XXX */
73748104Syokota
73848104Syokota	case FBIO_SETWINORG:	/* set frame buffer window origin */
73948104Syokota	case FBIO_SETDISPSTART:	/* set display start address */
74048104Syokota	case FBIO_SETLINEWIDTH:	/* set scan line width in pixel */
74148104Syokota
74248104Syokota	case FBIOGTYPE:
74348104Syokota	case FBIOGATTR:
74448104Syokota	case FBIOSVIDEO:
74548104Syokota	case FBIOGVIDEO:
74681039Syokota	case FBIOVERTICAL:
74748104Syokota	case FBIOSCURSOR:
74848104Syokota	case FBIOGCURSOR:
74948104Syokota	case FBIOSCURPOS:
75048104Syokota	case FBIOGCURPOS:
75148104Syokota	case FBIOGCURMAX:
75281039Syokota	case FBIOMONINFO:
75381039Syokota	case FBIOGXINFO:
75448104Syokota
75548104Syokota	default:
75648104Syokota		error = ENODEV;
75748104Syokota		break;
75848104Syokota	}
75948104Syokota
76048104Syokota	splx(s);
76148104Syokota	return error;
76248104Syokota}
763