File:  [DragonFly] / src / sys / dev / video / fb / fb.c
Revision 1.8: download - view: text, annotated - select for diffs
Thu May 13 23:49:22 2004 UTC (10 years, 3 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*-
    2:  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions and the following disclaimer as
   10:  *    the first lines of this file unmodified.
   11:  * 2. Redistributions in binary form must reproduce the above copyright
   12:  *    notice, this list of conditions and the following disclaimer in the
   13:  *    documentation and/or other materials provided with the distribution.
   14:  * 3. The name of the author may not be used to endorse or promote products
   15:  *    derived from this software without specific prior written permission.
   16:  *
   17:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
   18:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   19:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   20:  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   21:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   22:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   23:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   24:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   25:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   26:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   27:  *
   28:  * $FreeBSD: src/sys/dev/fb/fb.c,v 1.11.2.2 2000/08/02 22:35:22 peter Exp $
   29:  * $DragonFly: src/sys/dev/video/fb/fb.c,v 1.8 2004/05/13 23:49:22 dillon Exp $
   30:  */
   31: 
   32: #include "opt_fb.h"
   33: 
   34: #include <sys/param.h>
   35: #include <sys/systm.h>
   36: #include <sys/conf.h>
   37: #include <sys/bus.h>
   38: #include <sys/kernel.h>
   39: #include <sys/malloc.h>
   40: #include <sys/uio.h>
   41: #include <sys/fbio.h>
   42: #include <sys/linker_set.h>
   43: #include <sys/device.h>
   44: 
   45: #include <vm/vm.h>
   46: #include <vm/pmap.h>
   47: 
   48: #include "fbreg.h"
   49: 
   50: SET_DECLARE(videodriver_set, const video_driver_t);
   51: 
   52: /* local arrays */
   53: 
   54: /*
   55:  * We need at least one entry each in order to initialize a video card
   56:  * for the kernel console.  The arrays will be increased dynamically
   57:  * when necessary.
   58:  */
   59: 
   60: static int		vid_malloc;
   61: static int		adapters = 1;
   62: static video_adapter_t	*adp_ini;
   63: static video_adapter_t	**adapter = &adp_ini;
   64: static video_switch_t	*vidsw_ini;
   65:        video_switch_t	**vidsw = &vidsw_ini;
   66: 
   67: #ifdef FB_INSTALL_CDEV
   68: static struct lwkt_port	*vidcdevsw_ini;
   69: static struct lwkt_port	**vidcdevsw = &vidcdevsw_ini;
   70: #endif
   71: 
   72: #define ARRAY_DELTA	4
   73: 
   74: static int
   75: vid_realloc_array(void)
   76: {
   77: 	video_adapter_t **new_adp;
   78: 	video_switch_t **new_vidsw;
   79: #ifdef FB_INSTALL_CDEV
   80: 	struct lwkt_port **new_cdevsw;
   81: #endif
   82: 	int newsize;
   83: 	int s;
   84: 
   85: 	if (!vid_malloc)
   86: 		return ENOMEM;
   87: 
   88: 	s = spltty();
   89: 	newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
   90: 	new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK);
   91: 	new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF, M_WAITOK);
   92: #ifdef FB_INSTALL_CDEV
   93: 	new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF, M_WAITOK);
   94: #endif
   95: 	bzero(new_adp, sizeof(*new_adp)*newsize);
   96: 	bzero(new_vidsw, sizeof(*new_vidsw)*newsize);
   97: 	bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
   98: 	bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
   99: #ifdef FB_INSTALL_CDEV
  100: 	bzero(new_cdevsw, sizeof(*new_cdevsw)*newsize);
  101: 	bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
  102: #endif
  103: 	if (adapters > 1) {
  104: 		free(adapter, M_DEVBUF);
  105: 		free(vidsw, M_DEVBUF);
  106: #ifdef FB_INSTALL_CDEV
  107: 		free(vidcdevsw, M_DEVBUF);
  108: #endif
  109: 	}
  110: 	adapter = new_adp;
  111: 	vidsw = new_vidsw;
  112: #ifdef FB_INSTALL_CDEV
  113: 	vidcdevsw = new_cdevsw;
  114: #endif
  115: 	adapters = newsize;
  116: 	splx(s);
  117: 
  118: 	if (bootverbose)
  119: 		printf("fb: new array size %d\n", adapters);
  120: 
  121: 	return 0;
  122: }
  123: 
  124: static void
  125: vid_malloc_init(void *arg)
  126: {
  127: 	vid_malloc = TRUE;
  128: }
  129: 
  130: SYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
  131: 
  132: /*
  133:  * Low-level frame buffer driver functions
  134:  * frame buffer subdrivers, such as the VGA driver, call these functions
  135:  * to initialize the video_adapter structure and register it to the virtual
  136:  * frame buffer driver `fb'.
  137:  */
  138: 
  139: /* initialize the video_adapter_t structure */
  140: void
  141: vid_init_struct(video_adapter_t *adp, char *name, int type, int unit)
  142: {
  143: 	adp->va_flags = 0;
  144: 	adp->va_name = name;
  145: 	adp->va_type = type;
  146: 	adp->va_unit = unit;
  147: }
  148: 
  149: /* Register a video adapter */
  150: int
  151: vid_register(video_adapter_t *adp)
  152: {
  153: 	const video_driver_t **list;
  154: 	const video_driver_t *p;
  155: 	int index;
  156: 
  157: 	for (index = 0; index < adapters; ++index) {
  158: 		if (adapter[index] == NULL)
  159: 			break;
  160: 	}
  161: 	if (index >= adapters) {
  162: 		if (vid_realloc_array())
  163: 			return -1;
  164: 	}
  165: 
  166: 	adp->va_index = index;
  167: 	adp->va_token = NULL;
  168: 	SET_FOREACH(list, videodriver_set) {
  169: 		p = *list;
  170: 		if (strcmp(p->name, adp->va_name) == 0) {
  171: 			adapter[index] = adp;
  172: 			vidsw[index] = p->vidsw;
  173: 			return index;
  174: 		}
  175: 	}
  176: 
  177: 	return -1;
  178: }
  179: 
  180: int
  181: vid_unregister(video_adapter_t *adp)
  182: {
  183: 	if ((adp->va_index < 0) || (adp->va_index >= adapters))
  184: 		return ENOENT;
  185: 	if (adapter[adp->va_index] != adp)
  186: 		return ENOENT;
  187: 
  188: 	adapter[adp->va_index] = NULL;
  189: 	vidsw[adp->va_index] = NULL;
  190: 	return 0;
  191: }
  192: 
  193: /* Get video I/O function table */
  194: video_switch_t
  195: *vid_get_switch(char *name)
  196: {
  197: 	const video_driver_t **list;
  198: 	const video_driver_t *p;
  199: 
  200: 	SET_FOREACH(list, videodriver_set) {
  201: 		p = *list;
  202: 		if (strcmp(p->name, name) == 0)
  203: 			return p->vidsw;
  204: 	}
  205: 
  206: 	return NULL;
  207: }
  208: 
  209: /*
  210:  * Video card client functions
  211:  * Video card clients, such as the console driver `syscons' and the frame
  212:  * buffer cdev driver, use these functions to claim and release a card for
  213:  * exclusive use.
  214:  */
  215: 
  216: /* find the video card specified by a driver name and a unit number */
  217: int
  218: vid_find_adapter(char *driver, int unit)
  219: {
  220: 	int i;
  221: 
  222: 	for (i = 0; i < adapters; ++i) {
  223: 		if (adapter[i] == NULL)
  224: 			continue;
  225: 		if (strcmp("*", driver) && strcmp(adapter[i]->va_name, driver))
  226: 			continue;
  227: 		if ((unit != -1) && (adapter[i]->va_unit != unit))
  228: 			continue;
  229: 		return i;
  230: 	}
  231: 	return -1;
  232: }
  233: 
  234: /* allocate a video card */
  235: int
  236: vid_allocate(char *driver, int unit, void *id)
  237: {
  238: 	int index;
  239: 	int s;
  240: 
  241: 	s = spltty();
  242: 	index = vid_find_adapter(driver, unit);
  243: 	if (index >= 0) {
  244: 		if (adapter[index]->va_token) {
  245: 			splx(s);
  246: 			return -1;
  247: 		}
  248: 		adapter[index]->va_token = id;
  249: 	}
  250: 	splx(s);
  251: 	return index;
  252: }
  253: 
  254: int
  255: vid_release(video_adapter_t *adp, void *id)
  256: {
  257: 	int error;
  258: 	int s;
  259: 
  260: 	s = spltty();
  261: 	if (adp->va_token == NULL) {
  262: 		error = EINVAL;
  263: 	} else if (adp->va_token != id) {
  264: 		error = EPERM;
  265: 	} else {
  266: 		adp->va_token = NULL;
  267: 		error = 0;
  268: 	}
  269: 	splx(s);
  270: 	return error;
  271: }
  272: 
  273: /* Get a video adapter structure */
  274: video_adapter_t
  275: *vid_get_adapter(int index)
  276: {
  277: 	if ((index < 0) || (index >= adapters))
  278: 		return NULL;
  279: 	return adapter[index];
  280: }
  281: 
  282: /* Configure drivers: this is a backdoor for the console driver XXX */
  283: int
  284: vid_configure(int flags)
  285: {
  286: 	const video_driver_t **list;
  287: 	const video_driver_t *p;
  288: 
  289: 	SET_FOREACH(list, videodriver_set) {
  290: 		p = *list;
  291: 		if (p->configure != NULL)
  292: 			(*p->configure)(flags);
  293: 	}
  294: 
  295: 	return 0;
  296: }
  297: 
  298: /*
  299:  * Virtual frame buffer cdev driver functions
  300:  * The virtual frame buffer driver dispatches driver functions to
  301:  * appropriate subdrivers.
  302:  */
  303: 
  304: #define FB_DRIVER_NAME	"fb"
  305: 
  306: #ifdef FB_INSTALL_CDEV
  307: 
  308: #if experimental
  309: 
  310: static devclass_t	fb_devclass;
  311: 
  312: static int		fbprobe(device_t dev);
  313: static int		fbattach(device_t dev);
  314: 
  315: static device_method_t fb_methods[] = {
  316: 	DEVMETHOD(device_probe,		fbprobe),
  317: 	DEVMETHOD(device_attach,	fbattach),
  318: 
  319: 	DEVMETHOD(bus_print_child,	bus_generic_print_child),
  320: 	{ 0, 0 }
  321: };
  322: 
  323: static driver_t fb_driver = {
  324: 	FB_DRIVER_NAME,
  325: 	fb_methods,
  326: 	0,
  327: };
  328: 
  329: static int
  330: fbprobe(device_t dev)
  331: {
  332: 	int unit;
  333: 
  334: 	unit = device_get_unit(dev);
  335: 	if (unit >= adapters)
  336: 		return ENXIO;
  337: 	if (adapter[unit] == NULL)
  338: 		return ENXIO;
  339: 
  340: 	device_set_desc(dev, "generic frame buffer");
  341: 	return 0;
  342: }
  343: 
  344: static int
  345: fbattach(device_t dev)
  346: {
  347: 	printf("fbattach: about to attach children\n");
  348: 	bus_generic_attach(dev);
  349: 	return 0;
  350: }
  351: 
  352: #endif /* experimental */
  353: 
  354: #define FB_UNIT(dev)	minor(dev)
  355: #define FB_MKMINOR(unit) (u)
  356: 
  357: static d_open_t		fbopen;
  358: static d_close_t	fbclose;
  359: static d_read_t		fbread;
  360: static d_write_t	fbwrite;
  361: static d_ioctl_t	fbioctl;
  362: static d_mmap_t		fbmmap;
  363: 
  364: #define CDEV_MAJOR	123	/* XXX */
  365: 
  366: static struct cdevsw fb_cdevsw = {
  367: 	/* name */	FB_DRIVER_NAME,
  368: 	/* maj */	CDEV_MAJOR,
  369: 	/* flags */	0,
  370: 	/* port */      NULL,
  371: 	/* clone */	NULL,
  372: 
  373: 	/* open */	fbopen,
  374: 	/* close */	fbclose,
  375: 	/* read */	fbread,
  376: 	/* write */	fbwrite,
  377: 	/* ioctl */	fbioctl,
  378: 	/* poll */	nopoll,
  379: 	/* mmap */	fbmmap,
  380: 	/* strategy */	nostrategy,
  381: 	/* dump */	nodump,
  382: 	/* psize */	nopsize
  383: };
  384: 
  385: static void
  386: vfbattach(void *arg)
  387: {
  388: 	static int fb_devsw_installed = FALSE;
  389: 
  390: 	if (!fb_devsw_installed) {
  391: 		cdevsw_add(&fb_cdevsw);
  392: 		fb_devsw_installed = TRUE;
  393: 	}
  394: }
  395: 
  396: PSEUDO_SET(vfbattach, fb);
  397: 
  398: /*
  399:  *  Note: dev represents the actual video device, not the frame buffer
  400:  */
  401: int
  402: fb_attach(dev_t dev, video_adapter_t *adp)
  403: {
  404: 	int s;
  405: 
  406: 	if (adp->va_index >= adapters)
  407: 		return EINVAL;
  408: 	if (adapter[adp->va_index] != adp)
  409: 		return EINVAL;
  410: 
  411: 	s = spltty();
  412: 	adp->va_minor = minor(dev);
  413: 	vidcdevsw[adp->va_index] = dev_dport(dev);
  414: 	splx(s);
  415: 
  416: 	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
  417: 	return 0;
  418: }
  419: 
  420: #if 0	/* never seems to be called */
  421: /*
  422:  *  Note: dev represents the actual video device, not the frame buffer
  423:  */
  424: int
  425: fb_detach(dev_t dev, video_adapter_t *adp)
  426: {
  427: 	int s;
  428: 
  429: 	if (adp->va_index >= adapters)
  430: 		return EINVAL;
  431: 	if (adapter[adp->va_index] != adp)
  432: 		return EINVAL;
  433: 	if (vidcdevsw[adp->va_index] != port)
  434: 		return EINVAL;
  435: 
  436: 	s = spltty();
  437: 	vidcdevsw[adp->va_index] = NULL;
  438: 	splx(s);
  439: 	return 0;
  440: }
  441: #endif
  442: 
  443: static int
  444: fbopen(dev_t dev, int flag, int mode, struct thread *td)
  445: {
  446: 	int unit;
  447: 
  448: 	unit = FB_UNIT(dev);
  449: 	if (unit >= adapters)
  450: 		return ENXIO;
  451: 	if (vidcdevsw[unit] == NULL)
  452: 		return ENXIO;
  453: 	return dev_port_dopen(vidcdevsw[unit], 
  454: 			makedev(0, adapter[unit]->va_minor),
  455: 			flag, mode, td);
  456: }
  457: 
  458: static int
  459: fbclose(dev_t dev, int flag, int mode, struct thread *td)
  460: {
  461: 	int unit;
  462: 
  463: 	unit = FB_UNIT(dev);
  464: 	if (vidcdevsw[unit] == NULL)
  465: 		return ENXIO;
  466: 	return dev_port_dclose(vidcdevsw[unit],
  467: 			makedev(0, adapter[unit]->va_minor),
  468: 			flag, mode, td);
  469: }
  470: 
  471: static int
  472: fbread(dev_t dev, struct uio *uio, int flag)
  473: {
  474: 	int unit;
  475: 
  476: 	unit = FB_UNIT(dev);
  477: 	if (vidcdevsw[unit] == NULL)
  478: 		return ENXIO;
  479: 	return dev_port_dread(vidcdevsw[unit],
  480: 			makedev(0, adapter[unit]->va_minor),
  481: 			uio, flag);
  482: }
  483: 
  484: static int
  485: fbwrite(dev_t dev, struct uio *uio, int flag)
  486: {
  487: 	int unit;
  488: 
  489: 	unit = FB_UNIT(dev);
  490: 	if (vidcdevsw[unit] == NULL)
  491: 		return ENXIO;
  492: 	return dev_port_dwrite(vidcdevsw[unit],
  493: 			makedev(0, adapter[unit]->va_minor),
  494: 			uio, flag);
  495: }
  496: 
  497: static int
  498: fbioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
  499: {
  500: 	int unit;
  501: 
  502: 	unit = FB_UNIT(dev);
  503: 	if (vidcdevsw[unit] == NULL)
  504: 		return ENXIO;
  505: 	return dev_port_dioctl(vidcdevsw[unit],
  506: 			makedev(0, adapter[unit]->va_minor),
  507: 			cmd, arg, flag, td);
  508: }
  509: 
  510: static int
  511: fbmmap(dev_t dev, vm_offset_t offset, int nprot)
  512: {
  513: 	int unit;
  514: 
  515: 	unit = FB_UNIT(dev);
  516: 	if (vidcdevsw[unit] == NULL)
  517: 		return ENXIO;
  518: 	return (dev_port_dmmap(vidcdevsw[unit],
  519: 			makedev(0, adapter[unit]->va_minor),
  520: 			offset, nprot));
  521: }
  522: 
  523: #if experimental
  524: DEV_DRIVER_MODULE(fb, ???, fb_driver, fb_devclass, fb_cdevsw, 0, 0);
  525: #endif
  526: 
  527: /*
  528:  * Generic frame buffer cdev driver functions
  529:  * Frame buffer subdrivers may call these functions to implement common
  530:  * driver functions.
  531:  */
  532: 
  533: int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
  534: 	      struct thread *td)
  535: {
  536: 	int s;
  537: 
  538: 	s = spltty();
  539: 	if (!(sc->gfb_flags & FB_OPEN))
  540: 		sc->gfb_flags |= FB_OPEN;
  541: 	splx(s);
  542: 	return 0;
  543: }
  544: 
  545: int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
  546: 	       struct thread *td)
  547: {
  548: 	int s;
  549: 
  550: 	s = spltty();
  551: 	sc->gfb_flags &= ~FB_OPEN;
  552: 	splx(s);
  553: 	return 0;
  554: }
  555: 
  556: int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
  557: 	      int flag)
  558: {
  559: 	int size;
  560: 	int offset;
  561: 	int error;
  562: 	int len;
  563: 
  564: 	error = 0;
  565: 	size = adp->va_buffer_size/adp->va_info.vi_planes;
  566: 	while (uio->uio_resid > 0) {
  567: 		if (uio->uio_offset >= size)
  568: 			break;
  569: 		offset = uio->uio_offset%adp->va_window_size;
  570: 		len = imin(uio->uio_resid, size - uio->uio_offset);
  571: 		len = imin(len, adp->va_window_size - offset);
  572: 		if (len <= 0)
  573: 			break;
  574: 		(*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
  575: 		error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
  576: 		if (error)
  577: 			break;
  578: 	}
  579: 	return error;
  580: }
  581: 
  582: int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
  583: 	       int flag)
  584: {
  585: 	return ENODEV;
  586: }
  587: 
  588: int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
  589: 	       caddr_t arg, int flag, struct thread *td)
  590: {
  591: 	int error;
  592: 
  593: 	if (adp == NULL)	/* XXX */
  594: 		return ENXIO;
  595: 	error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
  596: 	if (error == ENOIOCTL)
  597: 		error = ENODEV;
  598: 	return error;
  599: }
  600: 
  601: int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
  602: 	      int prot)
  603: {
  604: 	return (*vidsw[adp->va_index]->mmap)(adp, offset, prot);
  605: }
  606: 
  607: #endif /* FB_INSTALL_CDEV */
  608: 
  609: static char
  610: *adapter_name(int type)
  611: {
  612:     static struct {
  613: 	int type;
  614: 	char *name;
  615:     } names[] = {
  616: 	{ KD_MONO,	"MDA" },
  617: 	{ KD_HERCULES,	"Hercules" },
  618: 	{ KD_CGA,	"CGA" },
  619: 	{ KD_EGA,	"EGA" },
  620: 	{ KD_VGA,	"VGA" },
  621: 	{ KD_PC98,	"PC-98x1" },
  622: 	{ KD_TGA,	"TGA" },
  623: 	{ -1,		"Unknown" },
  624:     };
  625:     int i;
  626: 
  627:     for (i = 0; names[i].type != -1; ++i)
  628: 	if (names[i].type == type)
  629: 	    break;
  630:     return names[i].name;
  631: }
  632: 
  633: /*
  634:  * Generic low-level frame buffer functions
  635:  * The low-level functions in the frame buffer subdriver may use these
  636:  * functions.
  637:  */
  638: 
  639: void
  640: fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
  641: {
  642:     if (level <= 0)
  643: 	return;
  644: 
  645:     printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n", 
  646: 	   FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
  647: 	   adapter_name(adp->va_type), adp->va_type, adp->va_flags);
  648:     printf("%s%d: port:0x%x-0x%x, crtc:0x%x, mem:0x%x 0x%x\n",
  649: 	   FB_DRIVER_NAME, adp->va_index,
  650: 	   adp->va_io_base, adp->va_io_base + adp->va_io_size - 1,
  651: 	   adp->va_crtc_addr, adp->va_mem_base, adp->va_mem_size);
  652:     printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
  653: 	   FB_DRIVER_NAME, adp->va_index,
  654: 	   adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
  655:     printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
  656: 	   FB_DRIVER_NAME, adp->va_index, 
  657: 	   (void *)adp->va_window, (int)adp->va_window_size/1024,
  658: 	   (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
  659: 	   (int)adp->va_buffer_size/1024);
  660: }
  661: 
  662: void
  663: fb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
  664: 		  int level)
  665: {
  666:     if (level <= 0)
  667: 	return;
  668: 
  669:     printf("%s%d: %s, mode:%d, flags:0x%x ", 
  670: 	   driver, adp->va_unit, adp->va_name, info->vi_mode, info->vi_flags);
  671:     if (info->vi_flags & V_INFO_GRAPHICS)
  672: 	printf("G %dx%dx%d, %d plane(s), font:%dx%d, ",
  673: 	       info->vi_width, info->vi_height, 
  674: 	       info->vi_depth, info->vi_planes, 
  675: 	       info->vi_cwidth, info->vi_cheight); 
  676:     else
  677: 	printf("T %dx%d, font:%dx%d, ",
  678: 	       info->vi_width, info->vi_height, 
  679: 	       info->vi_cwidth, info->vi_cheight); 
  680:     printf("win:0x%x\n", info->vi_window);
  681: }
  682: 
  683: int
  684: fb_type(int adp_type)
  685: {
  686: 	static struct {
  687: 		int	fb_type;
  688: 		int	va_type;
  689: 	} types[] = {
  690: 		{ FBTYPE_MDA,		KD_MONO },
  691: 		{ FBTYPE_HERCULES,	KD_HERCULES },
  692: 		{ FBTYPE_CGA,		KD_CGA },
  693: 		{ FBTYPE_EGA,		KD_EGA },
  694: 		{ FBTYPE_VGA,		KD_VGA },
  695: 		{ FBTYPE_PC98,		KD_PC98 },
  696: 		{ FBTYPE_TGA,		KD_TGA },
  697: 	};
  698: 	int i;
  699: 
  700: 	for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
  701: 		if (types[i].va_type == adp_type)
  702: 			return types[i].fb_type;
  703: 	}
  704: 	return -1;
  705: }
  706: 
  707: int
  708: fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
  709: {
  710: 	int error;
  711: 	int s;
  712: 
  713: 	/* assert(adp != NULL) */
  714: 
  715: 	error = 0;
  716: 	s = spltty();
  717: 
  718: 	switch (cmd) {
  719: 
  720: 	case FBIO_ADAPTER:	/* get video adapter index */
  721: 		*(int *)arg = adp->va_index;
  722: 		break;
  723: 
  724: 	case FBIO_ADPTYPE:	/* get video adapter type */
  725: 		*(int *)arg = adp->va_type;
  726: 		break;
  727: 
  728: 	case FBIO_ADPINFO:	/* get video adapter info */
  729: 	        ((video_adapter_info_t *)arg)->va_index = adp->va_index;
  730: 		((video_adapter_info_t *)arg)->va_type = adp->va_type;
  731: 		bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
  732: 		      imin(strlen(adp->va_name) + 1,
  733: 			   sizeof(((video_adapter_info_t *)arg)->va_name))); 
  734: 		((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
  735: 		((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
  736: 		((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
  737: 		((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
  738: 		((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
  739: 		((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
  740: 		((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
  741: 		((video_adapter_info_t *)arg)->va_window
  742: #ifdef __i386__
  743: 			= vtophys(adp->va_window);
  744: #else
  745: 			= adp->va_window;
  746: #endif
  747: 		((video_adapter_info_t *)arg)->va_window_size
  748: 			= adp->va_window_size;
  749: 		((video_adapter_info_t *)arg)->va_window_gran
  750: 			= adp->va_window_gran;
  751: 		((video_adapter_info_t *)arg)->va_window_orig
  752: 			= adp->va_window_orig;
  753: 		((video_adapter_info_t *)arg)->va_unused0
  754: #ifdef __i386__
  755: 			= (adp->va_buffer) ? vtophys(adp->va_buffer) : 0;
  756: #else
  757: 			= adp->va_buffer;
  758: #endif
  759: 		((video_adapter_info_t *)arg)->va_buffer_size
  760: 			= adp->va_buffer_size;
  761: 		((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
  762: 		((video_adapter_info_t *)arg)->va_initial_mode
  763: 			= adp->va_initial_mode;
  764: 		((video_adapter_info_t *)arg)->va_initial_bios_mode
  765: 			= adp->va_initial_bios_mode;
  766: 		((video_adapter_info_t *)arg)->va_line_width
  767: 			= adp->va_line_width;
  768: 		((video_adapter_info_t *)arg)->va_disp_start.x
  769: 			= adp->va_disp_start.x;
  770: 		((video_adapter_info_t *)arg)->va_disp_start.y
  771: 			= adp->va_disp_start.y;
  772: 		break;
  773: 
  774: 	case FBIO_MODEINFO:	/* get mode information */
  775: 		error = (*vidsw[adp->va_index]->get_info)(adp, 
  776: 				((video_info_t *)arg)->vi_mode,
  777: 				(video_info_t *)arg); 
  778: 		if (error)
  779: 			error = ENODEV;
  780: 		break;
  781: 
  782: 	case FBIO_FINDMODE:	/* find a matching video mode */
  783: 		error = (*vidsw[adp->va_index]->query_mode)(adp, 
  784: 				(video_info_t *)arg); 
  785: 		break;
  786: 
  787: 	case FBIO_GETMODE:	/* get video mode */
  788: 		*(int *)arg = adp->va_mode;
  789: 		break;
  790: 
  791: 	case FBIO_SETMODE:	/* set video mode */
  792: 		error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg);
  793: 		if (error)
  794: 			error = ENODEV;	/* EINVAL? */
  795: 		break;
  796: 
  797: 	case FBIO_GETWINORG:	/* get frame buffer window origin */
  798: 		*(u_int *)arg = adp->va_window_orig;
  799: 		break;
  800: 
  801: 	case FBIO_GETDISPSTART:	/* get display start address */
  802: 		((video_display_start_t *)arg)->x = adp->va_disp_start.x;
  803: 		((video_display_start_t *)arg)->y = adp->va_disp_start.y;
  804: 		break;
  805: 
  806: 	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
  807: 		*(u_int *)arg = adp->va_line_width;
  808: 		break;
  809: 
  810: 	case FBIO_GETPALETTE:	/* get color palette */
  811: 	case FBIO_SETPALETTE:	/* set color palette */
  812: 		/* XXX */
  813: 
  814: 	case FBIOPUTCMAP:
  815: 	case FBIOGETCMAP:
  816: 		/* XXX */
  817: 
  818: 	case FBIO_SETWINORG:	/* set frame buffer window origin */
  819: 	case FBIO_SETDISPSTART:	/* set display start address */
  820: 	case FBIO_SETLINEWIDTH:	/* set scan line width in pixel */
  821: 
  822: 	case FBIOGTYPE:
  823: 	case FBIOGATTR:
  824: 	case FBIOSVIDEO:
  825: 	case FBIOGVIDEO:
  826: 	case FBIOSCURSOR:
  827: 	case FBIOGCURSOR:
  828: 	case FBIOSCURPOS:
  829: 	case FBIOGCURPOS:
  830: 	case FBIOGCURMAX:
  831: 
  832: 	default:
  833: 		error = ENODEV;
  834: 		break;
  835: 	}
  836: 
  837: 	splx(s);
  838: 	return error;
  839: }