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$");
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();
89298848Spfg	newsize = rounddown(adapters + 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
307153084Sru#if 0 /* 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
318227843Smarius	DEVMETHOD_END
31948104Syokota};
32048104Syokota
32148104Syokotastatic driver_t fb_driver = {
32248104Syokota	FB_DRIVER_NAME,
32348104Syokota	fb_methods,
32448104Syokota	0,
32548104Syokota};
32648104Syokota
32748104Syokotastatic int
32848104Syokotafbprobe(device_t dev)
32948104Syokota{
33048104Syokota	int unit;
33148104Syokota
33248104Syokota	unit = device_get_unit(dev);
33348104Syokota	if (unit >= adapters)
33448104Syokota		return ENXIO;
33548104Syokota	if (adapter[unit] == NULL)
33648104Syokota		return ENXIO;
33748104Syokota
33848104Syokota	device_set_desc(dev, "generic frame buffer");
33948104Syokota	return 0;
34048104Syokota}
34148104Syokota
34248104Syokotastatic int
34348104Syokotafbattach(device_t dev)
34448104Syokota{
34548104Syokota	printf("fbattach: about to attach children\n");
34648104Syokota	bus_generic_attach(dev);
34748104Syokota	return 0;
34848104Syokota}
34948104Syokota
350153084Sru#endif
35148104Syokota
352183397Sed#define FB_UNIT(dev)	dev2unit(dev)
35342421Syokota#define FB_MKMINOR(unit) (u)
35442421Syokota
355153084Sru#if 0 /* experimental */
35642421Syokotastatic d_open_t		fbopen;
35742421Syokotastatic d_close_t	fbclose;
35848104Syokotastatic d_read_t		fbread;
35948104Syokotastatic d_write_t	fbwrite;
36042421Syokotastatic d_ioctl_t	fbioctl;
36142421Syokotastatic d_mmap_t		fbmmap;
36242421Syokota
36342421Syokota
36442421Syokotastatic struct cdevsw fb_cdevsw = {
365126080Sphk	.d_version =	D_VERSION,
366126080Sphk	.d_flags =	D_NEEDGIANT,
367111815Sphk	.d_open =	fbopen,
368111815Sphk	.d_close =	fbclose,
369111815Sphk	.d_read =	fbread,
370111815Sphk	.d_write =	fbwrite,
371111815Sphk	.d_ioctl =	fbioctl,
372111815Sphk	.d_mmap =	fbmmap,
373111815Sphk	.d_name =	FB_DRIVER_NAME,
37442421Syokota};
375111576Sphk#endif
37642421Syokota
37742421Syokota
37871862Speterstatic int
37971862Speterfb_modevent(module_t mod, int type, void *data)
38071862Speter{
38171862Speter
38271862Speter	switch (type) {
38371862Speter	case MOD_LOAD:
38471862Speter		break;
38571862Speter	case MOD_UNLOAD:
38671862Speter		printf("fb module unload - not possible for this module type\n");
38771862Speter		return EINVAL;
388132199Sphk	default:
389132199Sphk		return EOPNOTSUPP;
39071862Speter	}
39171862Speter	return 0;
39271862Speter}
39342421Syokota
39471862Speterstatic moduledata_t fb_mod = {
39571862Speter	"fb",
39671862Speter	fb_modevent,
39771862Speter	NULL
39871862Speter};
39942421Syokota
40071862SpeterDECLARE_MODULE(fb, fb_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
40171862Speter
40242421Syokotaint
403120465Sphkfb_attach(int unit, video_adapter_t *adp, struct cdevsw *cdevsw)
40442421Syokota{
40542421Syokota	int s;
40642421Syokota
40742421Syokota	if (adp->va_index >= adapters)
40842421Syokota		return EINVAL;
40942421Syokota	if (adapter[adp->va_index] != adp)
41042421Syokota		return EINVAL;
41142421Syokota
41242421Syokota	s = spltty();
413120465Sphk	adp->va_minor = unit;
41442421Syokota	vidcdevsw[adp->va_index] = cdevsw;
41542421Syokota	splx(s);
41642421Syokota
41742421Syokota	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
41842421Syokota	return 0;
41942421Syokota}
42042421Syokota
42142421Syokotaint
422120465Sphkfb_detach(int unit, video_adapter_t *adp, struct cdevsw *cdevsw)
42342421Syokota{
42442421Syokota	int s;
42542421Syokota
42642421Syokota	if (adp->va_index >= adapters)
42742421Syokota		return EINVAL;
42842421Syokota	if (adapter[adp->va_index] != adp)
42942421Syokota		return EINVAL;
43042421Syokota	if (vidcdevsw[adp->va_index] != cdevsw)
43142421Syokota		return EINVAL;
43242421Syokota
43342421Syokota	s = spltty();
43442421Syokota	vidcdevsw[adp->va_index] = NULL;
43542421Syokota	splx(s);
43642421Syokota	return 0;
43742421Syokota}
43842421Syokota
43948104Syokota/*
44048104Syokota * Generic frame buffer cdev driver functions
44148104Syokota * Frame buffer subdrivers may call these functions to implement common
44248104Syokota * driver functions.
44348104Syokota */
44448104Syokota
44548104Syokotaint genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
44683366Sjulian	      struct thread *td)
44748104Syokota{
44848104Syokota	int s;
44948104Syokota
45048104Syokota	s = spltty();
45148104Syokota	if (!(sc->gfb_flags & FB_OPEN))
45248104Syokota		sc->gfb_flags |= FB_OPEN;
45348104Syokota	splx(s);
45448104Syokota	return 0;
45548104Syokota}
45648104Syokota
45748104Syokotaint genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
45883366Sjulian	       struct thread *td)
45948104Syokota{
46048104Syokota	int s;
46148104Syokota
46248104Syokota	s = spltty();
46348104Syokota	sc->gfb_flags &= ~FB_OPEN;
46448104Syokota	splx(s);
46548104Syokota	return 0;
46648104Syokota}
46748104Syokota
46848104Syokotaint genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
46948104Syokota	      int flag)
47048104Syokota{
47148104Syokota	int size;
47248104Syokota	int offset;
47348104Syokota	int error;
47448104Syokota	int len;
47548104Syokota
47648104Syokota	error = 0;
47748104Syokota	size = adp->va_buffer_size/adp->va_info.vi_planes;
47848104Syokota	while (uio->uio_resid > 0) {
47948104Syokota		if (uio->uio_offset >= size)
48048104Syokota			break;
48148104Syokota		offset = uio->uio_offset%adp->va_window_size;
48248104Syokota		len = imin(uio->uio_resid, size - uio->uio_offset);
48348104Syokota		len = imin(len, adp->va_window_size - offset);
48448104Syokota		if (len <= 0)
48548104Syokota			break;
486174985Swkoszek		vidd_set_win_org(adp, uio->uio_offset);
48748104Syokota		error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
48848104Syokota		if (error)
48948104Syokota			break;
49048104Syokota	}
49148104Syokota	return error;
49248104Syokota}
49348104Syokota
49448104Syokotaint genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
49548104Syokota	       int flag)
49648104Syokota{
49748104Syokota	return ENODEV;
49848104Syokota}
49948104Syokota
50048104Syokotaint genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
50183366Sjulian	       caddr_t arg, int flag, struct thread *td)
50248104Syokota{
50348104Syokota	int error;
50448104Syokota
50548104Syokota	if (adp == NULL)	/* XXX */
50648104Syokota		return ENXIO;
507174985Swkoszek	error = vidd_ioctl(adp, cmd, arg);
50848104Syokota	if (error == ENOIOCTL)
50948104Syokota		error = ENODEV;
51048104Syokota	return error;
51148104Syokota}
51248104Syokota
513201223Srnolandint genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_ooffset_t offset,
514201223Srnoland	      vm_offset_t *paddr, int prot, vm_memattr_t *memattr)
51548104Syokota{
516201223Srnoland	return vidd_mmap(adp, offset, paddr, prot, memattr);
51748104Syokota}
51848104Syokota
51942421Syokota#endif /* FB_INSTALL_CDEV */
52042421Syokota
52142421Syokotastatic char
52242421Syokota*adapter_name(int type)
52342421Syokota{
52442421Syokota    static struct {
52542421Syokota	int type;
52642421Syokota	char *name;
52742421Syokota    } names[] = {
52842421Syokota	{ KD_MONO,	"MDA" },
52942421Syokota	{ KD_HERCULES,	"Hercules" },
53042421Syokota	{ KD_CGA,	"CGA" },
53142421Syokota	{ KD_EGA,	"EGA" },
53242421Syokota	{ KD_VGA,	"VGA" },
53342421Syokota	{ KD_PC98,	"PC-98x1" },
53448104Syokota	{ KD_TGA,	"TGA" },
53542421Syokota	{ -1,		"Unknown" },
53642421Syokota    };
53742421Syokota    int i;
53842421Syokota
53942421Syokota    for (i = 0; names[i].type != -1; ++i)
54042421Syokota	if (names[i].type == type)
54142421Syokota	    break;
54242421Syokota    return names[i].name;
54342421Syokota}
54442421Syokota
54548104Syokota/*
54648104Syokota * Generic low-level frame buffer functions
54748104Syokota * The low-level functions in the frame buffer subdriver may use these
54848104Syokota * functions.
54948104Syokota */
55048104Syokota
55142421Syokotavoid
55242421Syokotafb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
55342421Syokota{
55442421Syokota    if (level <= 0)
55542421Syokota	return;
55642421Syokota
55742421Syokota    printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
55848104Syokota	   FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
55942421Syokota	   adapter_name(adp->va_type), adp->va_type, adp->va_flags);
56094617Sobrien    printf("%s%d: port:0x%lx-0x%lx, crtc:0x%lx, mem:0x%lx 0x%x\n",
56194617Sobrien	   FB_DRIVER_NAME, adp->va_index, (u_long)adp->va_io_base,
56294617Sobrien	   (u_long)adp->va_io_base + adp->va_io_size - 1,
56394617Sobrien	   (u_long)adp->va_crtc_addr, (u_long)adp->va_mem_base,
56494617Sobrien	   adp->va_mem_size);
56542421Syokota    printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
56648104Syokota	   FB_DRIVER_NAME, adp->va_index,
56742421Syokota	   adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
56848104Syokota    printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
56948104Syokota	   FB_DRIVER_NAME, adp->va_index,
57048104Syokota	   (void *)adp->va_window, (int)adp->va_window_size/1024,
57148104Syokota	   (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
57242831Syokota	   (int)adp->va_buffer_size/1024);
57342421Syokota}
57442421Syokota
57542421Syokotavoid
57642421Syokotafb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
57742421Syokota		  int level)
57842421Syokota{
57942421Syokota    if (level <= 0)
58042421Syokota	return;
58142421Syokota
58242421Syokota    printf("%s%d: %s, mode:%d, flags:0x%x ",
58342421Syokota	   driver, adp->va_unit, adp->va_name, info->vi_mode, info->vi_flags);
58442421Syokota    if (info->vi_flags & V_INFO_GRAPHICS)
58542421Syokota	printf("G %dx%dx%d, %d plane(s), font:%dx%d, ",
58642421Syokota	       info->vi_width, info->vi_height,
58742421Syokota	       info->vi_depth, info->vi_planes,
58842421Syokota	       info->vi_cwidth, info->vi_cheight);
58942421Syokota    else
59042421Syokota	printf("T %dx%d, font:%dx%d, ",
59142421Syokota	       info->vi_width, info->vi_height,
59242421Syokota	       info->vi_cwidth, info->vi_cheight);
59394617Sobrien    printf("win:0x%lx\n", (u_long)info->vi_window);
59442421Syokota}
59548104Syokota
59648104Syokotaint
59748104Syokotafb_type(int adp_type)
59848104Syokota{
59948104Syokota	static struct {
60048104Syokota		int	fb_type;
60148104Syokota		int	va_type;
60248104Syokota	} types[] = {
60348104Syokota		{ FBTYPE_MDA,		KD_MONO },
60448104Syokota		{ FBTYPE_HERCULES,	KD_HERCULES },
60548104Syokota		{ FBTYPE_CGA,		KD_CGA },
60648104Syokota		{ FBTYPE_EGA,		KD_EGA },
60748104Syokota		{ FBTYPE_VGA,		KD_VGA },
60848104Syokota		{ FBTYPE_PC98,		KD_PC98 },
60948104Syokota		{ FBTYPE_TGA,		KD_TGA },
61048104Syokota	};
61148104Syokota	int i;
61248104Syokota
613298431Spfg	for (i = 0; i < nitems(types); ++i) {
61448104Syokota		if (types[i].va_type == adp_type)
61548104Syokota			return types[i].fb_type;
61648104Syokota	}
61748104Syokota	return -1;
61848104Syokota}
61948104Syokota
62048104Syokotaint
62148104Syokotafb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
62248104Syokota{
62348104Syokota	int error;
62448104Syokota	int s;
62548104Syokota
62648104Syokota	/* assert(adp != NULL) */
62748104Syokota
62848104Syokota	error = 0;
62948104Syokota	s = spltty();
63048104Syokota
63148104Syokota	switch (cmd) {
63248104Syokota
63348104Syokota	case FBIO_ADAPTER:	/* get video adapter index */
63448104Syokota		*(int *)arg = adp->va_index;
63548104Syokota		break;
63648104Syokota
63748104Syokota	case FBIO_ADPTYPE:	/* get video adapter type */
63848104Syokota		*(int *)arg = adp->va_type;
63948104Syokota		break;
64048104Syokota
64148104Syokota	case FBIO_ADPINFO:	/* get video adapter info */
64248104Syokota	        ((video_adapter_info_t *)arg)->va_index = adp->va_index;
64348104Syokota		((video_adapter_info_t *)arg)->va_type = adp->va_type;
64448104Syokota		bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
64548104Syokota		      imin(strlen(adp->va_name) + 1,
64648104Syokota			   sizeof(((video_adapter_info_t *)arg)->va_name)));
64748104Syokota		((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
64848104Syokota		((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
64948104Syokota		((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
65048104Syokota		((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
65148104Syokota		((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
65248104Syokota		((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
65348104Syokota		((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
65448104Syokota		((video_adapter_info_t *)arg)->va_window
655204235Sjkim#if defined(__amd64__) || defined(__i386__)
65648104Syokota			= vtophys(adp->va_window);
65760742Sgallatin#else
65860742Sgallatin			= adp->va_window;
65960742Sgallatin#endif
66048104Syokota		((video_adapter_info_t *)arg)->va_window_size
66148104Syokota			= adp->va_window_size;
66248104Syokota		((video_adapter_info_t *)arg)->va_window_gran
66348104Syokota			= adp->va_window_gran;
66448104Syokota		((video_adapter_info_t *)arg)->va_window_orig
66548104Syokota			= adp->va_window_orig;
66648104Syokota		((video_adapter_info_t *)arg)->va_unused0
667204235Sjkim#if defined(__amd64__) || defined(__i386__)
668204235Sjkim			= adp->va_buffer != 0 ? vtophys(adp->va_buffer) : 0;
66960742Sgallatin#else
67060742Sgallatin			= adp->va_buffer;
67160742Sgallatin#endif
67248104Syokota		((video_adapter_info_t *)arg)->va_buffer_size
67348104Syokota			= adp->va_buffer_size;
67448104Syokota		((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
67548104Syokota		((video_adapter_info_t *)arg)->va_initial_mode
67648104Syokota			= adp->va_initial_mode;
67748104Syokota		((video_adapter_info_t *)arg)->va_initial_bios_mode
67848104Syokota			= adp->va_initial_bios_mode;
67948104Syokota		((video_adapter_info_t *)arg)->va_line_width
68048104Syokota			= adp->va_line_width;
68148104Syokota		((video_adapter_info_t *)arg)->va_disp_start.x
68248104Syokota			= adp->va_disp_start.x;
68348104Syokota		((video_adapter_info_t *)arg)->va_disp_start.y
68448104Syokota			= adp->va_disp_start.y;
68548104Syokota		break;
68648104Syokota
68748104Syokota	case FBIO_MODEINFO:	/* get mode information */
688174985Swkoszek		error = vidd_get_info(adp,
689174985Swkoszek		    ((video_info_t *)arg)->vi_mode,
690174985Swkoszek		    (video_info_t *)arg);
69148104Syokota		if (error)
69248104Syokota			error = ENODEV;
69348104Syokota		break;
69448104Syokota
69548104Syokota	case FBIO_FINDMODE:	/* find a matching video mode */
696174985Swkoszek		error = vidd_query_mode(adp, (video_info_t *)arg);
69748104Syokota		break;
69848104Syokota
69948104Syokota	case FBIO_GETMODE:	/* get video mode */
70048104Syokota		*(int *)arg = adp->va_mode;
70148104Syokota		break;
70248104Syokota
70348104Syokota	case FBIO_SETMODE:	/* set video mode */
704174985Swkoszek		error = vidd_set_mode(adp, *(int *)arg);
70548104Syokota		if (error)
70648104Syokota			error = ENODEV;	/* EINVAL? */
70748104Syokota		break;
70848104Syokota
70948104Syokota	case FBIO_GETWINORG:	/* get frame buffer window origin */
71048104Syokota		*(u_int *)arg = adp->va_window_orig;
71148104Syokota		break;
71248104Syokota
71348104Syokota	case FBIO_GETDISPSTART:	/* get display start address */
71448104Syokota		((video_display_start_t *)arg)->x = adp->va_disp_start.x;
71548104Syokota		((video_display_start_t *)arg)->y = adp->va_disp_start.y;
71648104Syokota		break;
71748104Syokota
71848104Syokota	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
71948104Syokota		*(u_int *)arg = adp->va_line_width;
72048104Syokota		break;
72148104Syokota
72281039Syokota	case FBIO_BLANK:	/* blank display */
723174985Swkoszek		error = vidd_blank_display(adp, *(int *)arg);
72481039Syokota		break;
72581039Syokota
72648104Syokota	case FBIO_GETPALETTE:	/* get color palette */
72748104Syokota	case FBIO_SETPALETTE:	/* set color palette */
72848104Syokota		/* XXX */
72948104Syokota
73048104Syokota	case FBIOPUTCMAP:
73148104Syokota	case FBIOGETCMAP:
73281039Syokota	case FBIOPUTCMAPI:
73381039Syokota	case FBIOGETCMAPI:
73448104Syokota		/* XXX */
73548104Syokota
73648104Syokota	case FBIO_SETWINORG:	/* set frame buffer window origin */
73748104Syokota	case FBIO_SETDISPSTART:	/* set display start address */
73848104Syokota	case FBIO_SETLINEWIDTH:	/* set scan line width in pixel */
73948104Syokota
74048104Syokota	case FBIOGTYPE:
74148104Syokota	case FBIOGATTR:
74248104Syokota	case FBIOSVIDEO:
74348104Syokota	case FBIOGVIDEO:
74481039Syokota	case FBIOVERTICAL:
74548104Syokota	case FBIOSCURSOR:
74648104Syokota	case FBIOGCURSOR:
74748104Syokota	case FBIOSCURPOS:
74848104Syokota	case FBIOGCURPOS:
74948104Syokota	case FBIOGCURMAX:
75081039Syokota	case FBIOMONINFO:
75181039Syokota	case FBIOGXINFO:
75248104Syokota
75348104Syokota	default:
75448104Syokota		error = ENODEV;
75548104Syokota		break;
75648104Syokota	}
75748104Syokota
75848104Syokota	splx(s);
75948104Syokota	return error;
76048104Syokota}
761