fb.c revision 111576
1243791Sdim/*-
2243791Sdim * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3353358Sdim * All rights reserved.
4353358Sdim *
5353358Sdim * Redistribution and use in source and binary forms, with or without
6243791Sdim * modification, are permitted provided that the following conditions
7243791Sdim * are met:
8243791Sdim * 1. Redistributions of source code must retain the above copyright
9243791Sdim *    notice, this list of conditions and the following disclaimer as
10243791Sdim *    the first lines of this file unmodified.
11243791Sdim * 2. Redistributions in binary form must reproduce the above copyright
12243791Sdim *    notice, this list of conditions and the following disclaimer in the
13243791Sdim *    documentation and/or other materials provided with the distribution.
14243791Sdim * 3. The name of the author may not be used to endorse or promote products
15243791Sdim *    derived from this software without specific prior written permission.
16243791Sdim *
17243791Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18360784Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19360784Sdim * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20341825Sdim * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21243791Sdim * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22243791Sdim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23243791Sdim * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24243791Sdim * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25243791Sdim * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26243791Sdim * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27243791Sdim *
28243791Sdim * $FreeBSD: head/sys/dev/fb/fb.c 111576 2003-02-26 21:14:39Z phk $
29243791Sdim */
30243791Sdim
31243791Sdim#include "opt_fb.h"
32341825Sdim
33243791Sdim#include <sys/param.h>
34243791Sdim#include <sys/systm.h>
35243791Sdim#include <sys/conf.h>
36243791Sdim#include <sys/bus.h>
37243791Sdim#include <sys/kernel.h>
38243791Sdim#include <sys/malloc.h>
39243791Sdim#include <sys/module.h>
40243791Sdim#include <sys/uio.h>
41243791Sdim#include <sys/fbio.h>
42243791Sdim#include <sys/linker_set.h>
43243791Sdim
44243791Sdim#include <vm/vm.h>
45243791Sdim#include <vm/pmap.h>
46243791Sdim
47243791Sdim#include <dev/fb/fbreg.h>
48276479Sdim
49243791SdimSET_DECLARE(videodriver_set, const video_driver_t);
50243791Sdim
51276479Sdim/* local arrays */
52276479Sdim
53276479Sdim/*
54276479Sdim * We need at least one entry each in order to initialize a video card
55276479Sdim * for the kernel console.  The arrays will be increased dynamically
56243791Sdim * when necessary.
57243791Sdim */
58243791Sdim
59243791Sdimstatic int		vid_malloc;
60243791Sdimstatic int		adapters = 1;
61243791Sdimstatic video_adapter_t	*adp_ini;
62243791Sdimstatic video_adapter_t	**adapter = &adp_ini;
63243791Sdimstatic video_switch_t	*vidsw_ini;
64243791Sdim       video_switch_t	**vidsw = &vidsw_ini;
65243791Sdim
66243791Sdim#ifdef FB_INSTALL_CDEV
67243791Sdimstatic struct cdevsw	*vidcdevsw_ini;
68243791Sdimstatic struct cdevsw	**vidcdevsw = &vidcdevsw_ini;
69243791Sdim#endif
70243791Sdim
71243791Sdim#define ARRAY_DELTA	4
72243791Sdim
73243791Sdimstatic int
74243791Sdimvid_realloc_array(void)
75243791Sdim{
76243791Sdim	video_adapter_t **new_adp;
77276479Sdim	video_switch_t **new_vidsw;
78243791Sdim#ifdef FB_INSTALL_CDEV
79243791Sdim	struct cdevsw **new_cdevsw;
80243791Sdim#endif
81243791Sdim	int newsize;
82243791Sdim	int s;
83243791Sdim
84243791Sdim	if (!vid_malloc)
85276479Sdim		return ENOMEM;
86243791Sdim
87243791Sdim	s = spltty();
88288943Sdim	newsize = ((adapters + ARRAY_DELTA)/ARRAY_DELTA)*ARRAY_DELTA;
89288943Sdim	new_adp = malloc(sizeof(*new_adp)*newsize, M_DEVBUF, M_WAITOK | M_ZERO);
90288943Sdim	new_vidsw = malloc(sizeof(*new_vidsw)*newsize, M_DEVBUF,
91288943Sdim	    M_WAITOK | M_ZERO);
92288943Sdim#ifdef FB_INSTALL_CDEV
93288943Sdim	new_cdevsw = malloc(sizeof(*new_cdevsw)*newsize, M_DEVBUF,
94288943Sdim	    M_WAITOK | M_ZERO);
95288943Sdim#endif
96321369Sdim	bcopy(adapter, new_adp, sizeof(*adapter)*adapters);
97321369Sdim	bcopy(vidsw, new_vidsw, sizeof(*vidsw)*adapters);
98321369Sdim#ifdef FB_INSTALL_CDEV
99321369Sdim	bcopy(vidcdevsw, new_cdevsw, sizeof(*vidcdevsw)*adapters);
100321369Sdim#endif
101321369Sdim	if (adapters > 1) {
102321369Sdim		free(adapter, M_DEVBUF);
103321369Sdim		free(vidsw, M_DEVBUF);
104321369Sdim#ifdef FB_INSTALL_CDEV
105249423Sdim		free(vidcdevsw, M_DEVBUF);
106243791Sdim#endif
107249423Sdim	}
108249423Sdim	adapter = new_adp;
109249423Sdim	vidsw = new_vidsw;
110249423Sdim#ifdef FB_INSTALL_CDEV
111243791Sdim	vidcdevsw = new_cdevsw;
112243791Sdim#endif
113243791Sdim	adapters = newsize;
114243791Sdim	splx(s);
115243791Sdim
116243791Sdim	if (bootverbose)
117243791Sdim		printf("fb: new array size %d\n", adapters);
118296417Sdim
119296417Sdim	return 0;
120296417Sdim}
121243791Sdim
122296417Sdimstatic void
123243791Sdimvid_malloc_init(void *arg)
124243791Sdim{
125341825Sdim	vid_malloc = TRUE;
126243791Sdim}
127243791Sdim
128243791SdimSYSINIT(vid_mem, SI_SUB_KMEM, SI_ORDER_ANY, vid_malloc_init, NULL);
129243791Sdim
130243791Sdim/*
131243791Sdim * Low-level frame buffer driver functions
132243791Sdim * frame buffer subdrivers, such as the VGA driver, call these functions
133243791Sdim * to initialize the video_adapter structure and register it to the virtual
134243791Sdim * frame buffer driver `fb'.
135243791Sdim */
136243791Sdim
137243791Sdim/* initialize the video_adapter_t structure */
138243791Sdimvoid
139243791Sdimvid_init_struct(video_adapter_t *adp, char *name, int type, int unit)
140243791Sdim{
141243791Sdim	adp->va_flags = 0;
142243791Sdim	adp->va_name = name;
143243791Sdim	adp->va_type = type;
144243791Sdim	adp->va_unit = unit;
145243791Sdim}
146243791Sdim
147243791Sdim/* Register a video adapter */
148243791Sdimint
149243791Sdimvid_register(video_adapter_t *adp)
150243791Sdim{
151243791Sdim	const video_driver_t **list;
152243791Sdim	const video_driver_t *p;
153243791Sdim	int index;
154243791Sdim
155243791Sdim	for (index = 0; index < adapters; ++index) {
156243791Sdim		if (adapter[index] == NULL)
157243791Sdim			break;
158243791Sdim	}
159243791Sdim	if (index >= adapters) {
160243791Sdim		if (vid_realloc_array())
161243791Sdim			return -1;
162243791Sdim	}
163243791Sdim
164243791Sdim	adp->va_index = index;
165243791Sdim	adp->va_token = NULL;
166243791Sdim	SET_FOREACH(list, videodriver_set) {
167243791Sdim		p = *list;
168341825Sdim		if (strcmp(p->name, adp->va_name) == 0) {
169341825Sdim			adapter[index] = adp;
170341825Sdim			vidsw[index] = p->vidsw;
171341825Sdim			return index;
172341825Sdim		}
173341825Sdim	}
174341825Sdim
175341825Sdim	return -1;
176341825Sdim}
177341825Sdim
178341825Sdimint
179341825Sdimvid_unregister(video_adapter_t *adp)
180341825Sdim{
181341825Sdim	if ((adp->va_index < 0) || (adp->va_index >= adapters))
182243791Sdim		return ENOENT;
183341825Sdim	if (adapter[adp->va_index] != adp)
184243791Sdim		return ENOENT;
185243791Sdim
186243791Sdim	adapter[adp->va_index] = NULL;
187243791Sdim	vidsw[adp->va_index] = NULL;
188243791Sdim	return 0;
189341825Sdim}
190243791Sdim
191243791Sdim/* Get video I/O function table */
192243791Sdimvideo_switch_t
193243791Sdim*vid_get_switch(char *name)
194243791Sdim{
195243791Sdim	const video_driver_t **list;
196243791Sdim	const video_driver_t *p;
197243791Sdim
198243791Sdim	SET_FOREACH(list, videodriver_set) {
199243791Sdim		p = *list;
200243791Sdim		if (strcmp(p->name, name) == 0)
201243791Sdim			return p->vidsw;
202243791Sdim	}
203243791Sdim
204243791Sdim	return NULL;
205243791Sdim}
206243791Sdim
207243791Sdim/*
208243791Sdim * Video card client functions
209243791Sdim * Video card clients, such as the console driver `syscons' and the frame
210243791Sdim * buffer cdev driver, use these functions to claim and release a card for
211243791Sdim * exclusive use.
212243791Sdim */
213243791Sdim
214243791Sdim/* find the video card specified by a driver name and a unit number */
215243791Sdimint
216243791Sdimvid_find_adapter(char *driver, int unit)
217243791Sdim{
218243791Sdim	int i;
219243791Sdim
220243791Sdim	for (i = 0; i < adapters; ++i) {
221243791Sdim		if (adapter[i] == NULL)
222309124Sdim			continue;
223309124Sdim		if (strcmp("*", driver) && strcmp(adapter[i]->va_name, driver))
224309124Sdim			continue;
225309124Sdim		if ((unit != -1) && (adapter[i]->va_unit != unit))
226309124Sdim			continue;
227243791Sdim		return i;
228243791Sdim	}
229243791Sdim	return -1;
230243791Sdim}
231243791Sdim
232249423Sdim/* allocate a video card */
233249423Sdimint
234309124Sdimvid_allocate(char *driver, int unit, void *id)
235249423Sdim{
236249423Sdim	int index;
237249423Sdim	int s;
238288943Sdim
239288943Sdim	s = spltty();
240288943Sdim	index = vid_find_adapter(driver, unit);
241288943Sdim	if (index >= 0) {
242288943Sdim		if (adapter[index]->va_token) {
243288943Sdim			splx(s);
244288943Sdim			return -1;
245288943Sdim		}
246288943Sdim		adapter[index]->va_token = id;
247341825Sdim	}
248243791Sdim	splx(s);
249243791Sdim	return index;
250341825Sdim}
251243791Sdim
252243791Sdimint
253243791Sdimvid_release(video_adapter_t *adp, void *id)
254243791Sdim{
255243791Sdim	int error;
256243791Sdim	int s;
257243791Sdim
258243791Sdim	s = spltty();
259341825Sdim	if (adp->va_token == NULL) {
260243791Sdim		error = EINVAL;
261243791Sdim	} else if (adp->va_token != id) {
262243791Sdim		error = EPERM;
263243791Sdim	} else {
264243791Sdim		adp->va_token = NULL;
265341825Sdim		error = 0;
266243791Sdim	}
267243791Sdim	splx(s);
268243791Sdim	return error;
269243791Sdim}
270243791Sdim
271243791Sdim/* Get a video adapter structure */
272243791Sdimvideo_adapter_t
273243791Sdim*vid_get_adapter(int index)
274243791Sdim{
275243791Sdim	if ((index < 0) || (index >= adapters))
276243791Sdim		return NULL;
277243791Sdim	return adapter[index];
278280031Sdim}
279280031Sdim
280280031Sdim/* Configure drivers: this is a backdoor for the console driver XXX */
281280031Sdimint
282280031Sdimvid_configure(int flags)
283280031Sdim{
284243791Sdim	const video_driver_t **list;
285243791Sdim	const video_driver_t *p;
286243791Sdim
287243791Sdim	SET_FOREACH(list, videodriver_set) {
288243791Sdim		p = *list;
289243791Sdim		if (p->configure != NULL)
290243791Sdim			(*p->configure)(flags);
291243791Sdim	}
292243791Sdim
293243791Sdim	return 0;
294243791Sdim}
295243791Sdim
296243791Sdim/*
297243791Sdim * Virtual frame buffer cdev driver functions
298243791Sdim * The virtual frame buffer driver dispatches driver functions to
299243791Sdim * appropriate subdrivers.
300243791Sdim */
301243791Sdim
302243791Sdim#define FB_DRIVER_NAME	"fb"
303243791Sdim
304243791Sdim#ifdef FB_INSTALL_CDEV
305243791Sdim
306243791Sdim#if experimental
307243791Sdim
308261991Sdimstatic devclass_t	fb_devclass;
309261991Sdim
310314564Sdimstatic int		fbprobe(device_t dev);
311314564Sdimstatic int		fbattach(device_t dev);
312261991Sdim
313261991Sdimstatic device_method_t fb_methods[] = {
314261991Sdim	DEVMETHOD(device_probe,		fbprobe),
315261991Sdim	DEVMETHOD(device_attach,	fbattach),
316261991Sdim
317261991Sdim	DEVMETHOD(bus_print_child,	bus_generic_print_child),
318261991Sdim	{ 0, 0 }
319261991Sdim};
320261991Sdim
321261991Sdimstatic driver_t fb_driver = {
322261991Sdim	FB_DRIVER_NAME,
323261991Sdim	fb_methods,
324261991Sdim	0,
325261991Sdim};
326261991Sdim
327261991Sdimstatic int
328261991Sdimfbprobe(device_t dev)
329261991Sdim{
330261991Sdim	int unit;
331261991Sdim
332261991Sdim	unit = device_get_unit(dev);
333261991Sdim	if (unit >= adapters)
334261991Sdim		return ENXIO;
335261991Sdim	if (adapter[unit] == NULL)
336261991Sdim		return ENXIO;
337261991Sdim
338261991Sdim	device_set_desc(dev, "generic frame buffer");
339261991Sdim	return 0;
340}
341
342static int
343fbattach(device_t dev)
344{
345	printf("fbattach: about to attach children\n");
346	bus_generic_attach(dev);
347	return 0;
348}
349
350#endif /* experimental */
351
352#define FB_UNIT(dev)	minor(dev)
353#define FB_MKMINOR(unit) (u)
354
355#if experimental
356static d_open_t		fbopen;
357static d_close_t	fbclose;
358static d_read_t		fbread;
359static d_write_t	fbwrite;
360static d_ioctl_t	fbioctl;
361static d_mmap_t		fbmmap;
362
363#define CDEV_MAJOR	123	/* XXX */
364
365static struct cdevsw fb_cdevsw = {
366	/* open */	fbopen,
367	/* close */	fbclose,
368	/* read */	fbread,
369	/* write */	fbwrite,
370	/* ioctl */	fbioctl,
371	/* poll */	nopoll,
372	/* mmap */	fbmmap,
373	/* strategy */	nostrategy,
374	/* name */	FB_DRIVER_NAME,
375	/* maj */	CDEV_MAJOR,
376	/* dump */	nodump,
377	/* psize */	nopsize,
378	/* flags */	0,
379};
380#endif
381
382
383static int
384fb_modevent(module_t mod, int type, void *data)
385{
386
387	switch (type) {
388	case MOD_LOAD:
389		break;
390	case MOD_UNLOAD:
391		printf("fb module unload - not possible for this module type\n");
392		return EINVAL;
393	}
394	return 0;
395}
396
397static moduledata_t fb_mod = {
398	"fb",
399	fb_modevent,
400	NULL
401};
402
403DECLARE_MODULE(fb, fb_mod, SI_SUB_PSEUDO, SI_ORDER_ANY);
404
405int
406fb_attach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
407{
408	int s;
409
410	if (adp->va_index >= adapters)
411		return EINVAL;
412	if (adapter[adp->va_index] != adp)
413		return EINVAL;
414
415	s = spltty();
416	adp->va_minor = minor(dev);
417	vidcdevsw[adp->va_index] = cdevsw;
418	splx(s);
419
420	printf("fb%d at %s%d\n", adp->va_index, adp->va_name, adp->va_unit);
421	return 0;
422}
423
424int
425fb_detach(dev_t dev, video_adapter_t *adp, struct cdevsw *cdevsw)
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] != cdevsw)
434		return EINVAL;
435
436	s = spltty();
437	vidcdevsw[adp->va_index] = NULL;
438	splx(s);
439	return 0;
440}
441
442#if experimental
443static int
444fbopen(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 (*vidcdevsw[unit]->d_open)(makedev(0, adapter[unit]->va_minor),
454					  flag, mode, td);
455}
456
457static int
458fbclose(dev_t dev, int flag, int mode, struct thread *td)
459{
460	int unit;
461
462	unit = FB_UNIT(dev);
463	if (vidcdevsw[unit] == NULL)
464		return ENXIO;
465	return (*vidcdevsw[unit]->d_close)(makedev(0, adapter[unit]->va_minor),
466					   flag, mode, td);
467}
468
469static int
470fbread(dev_t dev, struct uio *uio, int flag)
471{
472	int unit;
473
474	unit = FB_UNIT(dev);
475	if (vidcdevsw[unit] == NULL)
476		return ENXIO;
477	return (*vidcdevsw[unit]->d_read)(makedev(0, adapter[unit]->va_minor),
478					  uio, flag);
479}
480
481static int
482fbwrite(dev_t dev, struct uio *uio, int flag)
483{
484	int unit;
485
486	unit = FB_UNIT(dev);
487	if (vidcdevsw[unit] == NULL)
488		return ENXIO;
489	return (*vidcdevsw[unit]->d_write)(makedev(0, adapter[unit]->va_minor),
490					   uio, flag);
491}
492
493static int
494fbioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
495{
496	int unit;
497
498	unit = FB_UNIT(dev);
499	if (vidcdevsw[unit] == NULL)
500		return ENXIO;
501	return (*vidcdevsw[unit]->d_ioctl)(makedev(0, adapter[unit]->va_minor),
502					   cmd, arg, flag, td);
503}
504
505static int
506fbmmap(dev_t dev, vm_offset_t offset, vm_offset_t *paddr, int nprot)
507{
508	int unit;
509
510	unit = FB_UNIT(dev);
511	if (vidcdevsw[unit] == NULL)
512		return ENXIO;
513	return (*vidcdevsw[unit]->d_mmap)(makedev(0, adapter[unit]->va_minor),
514					  offset, paddr, nprot);
515}
516
517DEV_DRIVER_MODULE(fb, ???, fb_driver, fb_devclass, fb_cdevsw, 0, 0);
518#endif
519
520/*
521 * Generic frame buffer cdev driver functions
522 * Frame buffer subdrivers may call these functions to implement common
523 * driver functions.
524 */
525
526int genfbopen(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
527	      struct thread *td)
528{
529	int s;
530
531	s = spltty();
532	if (!(sc->gfb_flags & FB_OPEN))
533		sc->gfb_flags |= FB_OPEN;
534	splx(s);
535	return 0;
536}
537
538int genfbclose(genfb_softc_t *sc, video_adapter_t *adp, int flag, int mode,
539	       struct thread *td)
540{
541	int s;
542
543	s = spltty();
544	sc->gfb_flags &= ~FB_OPEN;
545	splx(s);
546	return 0;
547}
548
549int genfbread(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
550	      int flag)
551{
552	int size;
553	int offset;
554	int error;
555	int len;
556
557	error = 0;
558	size = adp->va_buffer_size/adp->va_info.vi_planes;
559	while (uio->uio_resid > 0) {
560		if (uio->uio_offset >= size)
561			break;
562		offset = uio->uio_offset%adp->va_window_size;
563		len = imin(uio->uio_resid, size - uio->uio_offset);
564		len = imin(len, adp->va_window_size - offset);
565		if (len <= 0)
566			break;
567		(*vidsw[adp->va_index]->set_win_org)(adp, uio->uio_offset);
568		error = uiomove((caddr_t)(adp->va_window + offset), len, uio);
569		if (error)
570			break;
571	}
572	return error;
573}
574
575int genfbwrite(genfb_softc_t *sc, video_adapter_t *adp, struct uio *uio,
576	       int flag)
577{
578	return ENODEV;
579}
580
581int genfbioctl(genfb_softc_t *sc, video_adapter_t *adp, u_long cmd,
582	       caddr_t arg, int flag, struct thread *td)
583{
584	int error;
585
586	if (adp == NULL)	/* XXX */
587		return ENXIO;
588	error = (*vidsw[adp->va_index]->ioctl)(adp, cmd, arg);
589	if (error == ENOIOCTL)
590		error = ENODEV;
591	return error;
592}
593
594int genfbmmap(genfb_softc_t *sc, video_adapter_t *adp, vm_offset_t offset,
595	      vm_offset_t *paddr, int prot)
596{
597	return (*vidsw[adp->va_index]->mmap)(adp, offset, paddr, prot);
598}
599
600#endif /* FB_INSTALL_CDEV */
601
602static char
603*adapter_name(int type)
604{
605    static struct {
606	int type;
607	char *name;
608    } names[] = {
609	{ KD_MONO,	"MDA" },
610	{ KD_HERCULES,	"Hercules" },
611	{ KD_CGA,	"CGA" },
612	{ KD_EGA,	"EGA" },
613	{ KD_VGA,	"VGA" },
614	{ KD_PC98,	"PC-98x1" },
615	{ KD_TGA,	"TGA" },
616	{ -1,		"Unknown" },
617    };
618    int i;
619
620    for (i = 0; names[i].type != -1; ++i)
621	if (names[i].type == type)
622	    break;
623    return names[i].name;
624}
625
626/*
627 * Generic low-level frame buffer functions
628 * The low-level functions in the frame buffer subdriver may use these
629 * functions.
630 */
631
632void
633fb_dump_adp_info(char *driver, video_adapter_t *adp, int level)
634{
635    if (level <= 0)
636	return;
637
638    printf("%s%d: %s%d, %s, type:%s (%d), flags:0x%x\n",
639	   FB_DRIVER_NAME, adp->va_index, driver, adp->va_unit, adp->va_name,
640	   adapter_name(adp->va_type), adp->va_type, adp->va_flags);
641    printf("%s%d: port:0x%lx-0x%lx, crtc:0x%lx, mem:0x%lx 0x%x\n",
642	   FB_DRIVER_NAME, adp->va_index, (u_long)adp->va_io_base,
643	   (u_long)adp->va_io_base + adp->va_io_size - 1,
644	   (u_long)adp->va_crtc_addr, (u_long)adp->va_mem_base,
645	   adp->va_mem_size);
646    printf("%s%d: init mode:%d, bios mode:%d, current mode:%d\n",
647	   FB_DRIVER_NAME, adp->va_index,
648	   adp->va_initial_mode, adp->va_initial_bios_mode, adp->va_mode);
649    printf("%s%d: window:%p size:%dk gran:%dk, buf:%p size:%dk\n",
650	   FB_DRIVER_NAME, adp->va_index,
651	   (void *)adp->va_window, (int)adp->va_window_size/1024,
652	   (int)adp->va_window_gran/1024, (void *)adp->va_buffer,
653	   (int)adp->va_buffer_size/1024);
654}
655
656void
657fb_dump_mode_info(char *driver, video_adapter_t *adp, video_info_t *info,
658		  int level)
659{
660    if (level <= 0)
661	return;
662
663    printf("%s%d: %s, mode:%d, flags:0x%x ",
664	   driver, adp->va_unit, adp->va_name, info->vi_mode, info->vi_flags);
665    if (info->vi_flags & V_INFO_GRAPHICS)
666	printf("G %dx%dx%d, %d plane(s), font:%dx%d, ",
667	       info->vi_width, info->vi_height,
668	       info->vi_depth, info->vi_planes,
669	       info->vi_cwidth, info->vi_cheight);
670    else
671	printf("T %dx%d, font:%dx%d, ",
672	       info->vi_width, info->vi_height,
673	       info->vi_cwidth, info->vi_cheight);
674    printf("win:0x%lx\n", (u_long)info->vi_window);
675}
676
677int
678fb_type(int adp_type)
679{
680	static struct {
681		int	fb_type;
682		int	va_type;
683	} types[] = {
684		{ FBTYPE_MDA,		KD_MONO },
685		{ FBTYPE_HERCULES,	KD_HERCULES },
686		{ FBTYPE_CGA,		KD_CGA },
687		{ FBTYPE_EGA,		KD_EGA },
688		{ FBTYPE_VGA,		KD_VGA },
689		{ FBTYPE_PC98,		KD_PC98 },
690		{ FBTYPE_TGA,		KD_TGA },
691	};
692	int i;
693
694	for (i = 0; i < sizeof(types)/sizeof(types[0]); ++i) {
695		if (types[i].va_type == adp_type)
696			return types[i].fb_type;
697	}
698	return -1;
699}
700
701int
702fb_commonioctl(video_adapter_t *adp, u_long cmd, caddr_t arg)
703{
704	int error;
705	int s;
706
707	/* assert(adp != NULL) */
708
709	error = 0;
710	s = spltty();
711
712	switch (cmd) {
713
714	case FBIO_ADAPTER:	/* get video adapter index */
715		*(int *)arg = adp->va_index;
716		break;
717
718	case FBIO_ADPTYPE:	/* get video adapter type */
719		*(int *)arg = adp->va_type;
720		break;
721
722	case FBIO_ADPINFO:	/* get video adapter info */
723	        ((video_adapter_info_t *)arg)->va_index = adp->va_index;
724		((video_adapter_info_t *)arg)->va_type = adp->va_type;
725		bcopy(adp->va_name, ((video_adapter_info_t *)arg)->va_name,
726		      imin(strlen(adp->va_name) + 1,
727			   sizeof(((video_adapter_info_t *)arg)->va_name)));
728		((video_adapter_info_t *)arg)->va_unit = adp->va_unit;
729		((video_adapter_info_t *)arg)->va_flags = adp->va_flags;
730		((video_adapter_info_t *)arg)->va_io_base = adp->va_io_base;
731		((video_adapter_info_t *)arg)->va_io_size = adp->va_io_size;
732		((video_adapter_info_t *)arg)->va_crtc_addr = adp->va_crtc_addr;
733		((video_adapter_info_t *)arg)->va_mem_base = adp->va_mem_base;
734		((video_adapter_info_t *)arg)->va_mem_size = adp->va_mem_size;
735		((video_adapter_info_t *)arg)->va_window
736#ifdef __i386__
737			= vtophys(adp->va_window);
738#else
739			= adp->va_window;
740#endif
741		((video_adapter_info_t *)arg)->va_window_size
742			= adp->va_window_size;
743		((video_adapter_info_t *)arg)->va_window_gran
744			= adp->va_window_gran;
745		((video_adapter_info_t *)arg)->va_window_orig
746			= adp->va_window_orig;
747		((video_adapter_info_t *)arg)->va_unused0
748#ifdef __i386__
749			= (adp->va_buffer) ? vtophys(adp->va_buffer) : 0;
750#else
751			= adp->va_buffer;
752#endif
753		((video_adapter_info_t *)arg)->va_buffer_size
754			= adp->va_buffer_size;
755		((video_adapter_info_t *)arg)->va_mode = adp->va_mode;
756		((video_adapter_info_t *)arg)->va_initial_mode
757			= adp->va_initial_mode;
758		((video_adapter_info_t *)arg)->va_initial_bios_mode
759			= adp->va_initial_bios_mode;
760		((video_adapter_info_t *)arg)->va_line_width
761			= adp->va_line_width;
762		((video_adapter_info_t *)arg)->va_disp_start.x
763			= adp->va_disp_start.x;
764		((video_adapter_info_t *)arg)->va_disp_start.y
765			= adp->va_disp_start.y;
766		break;
767
768	case FBIO_MODEINFO:	/* get mode information */
769		error = (*vidsw[adp->va_index]->get_info)(adp,
770				((video_info_t *)arg)->vi_mode,
771				(video_info_t *)arg);
772		if (error)
773			error = ENODEV;
774		break;
775
776	case FBIO_FINDMODE:	/* find a matching video mode */
777		error = (*vidsw[adp->va_index]->query_mode)(adp,
778				(video_info_t *)arg);
779		break;
780
781	case FBIO_GETMODE:	/* get video mode */
782		*(int *)arg = adp->va_mode;
783		break;
784
785	case FBIO_SETMODE:	/* set video mode */
786		error = (*vidsw[adp->va_index]->set_mode)(adp, *(int *)arg);
787		if (error)
788			error = ENODEV;	/* EINVAL? */
789		break;
790
791	case FBIO_GETWINORG:	/* get frame buffer window origin */
792		*(u_int *)arg = adp->va_window_orig;
793		break;
794
795	case FBIO_GETDISPSTART:	/* get display start address */
796		((video_display_start_t *)arg)->x = adp->va_disp_start.x;
797		((video_display_start_t *)arg)->y = adp->va_disp_start.y;
798		break;
799
800	case FBIO_GETLINEWIDTH:	/* get scan line width in bytes */
801		*(u_int *)arg = adp->va_line_width;
802		break;
803
804	case FBIO_BLANK:	/* blank display */
805		error = (*vidsw[adp->va_index]->blank_display)(adp, *(int *)arg);
806		break;
807
808	case FBIO_GETPALETTE:	/* get color palette */
809	case FBIO_SETPALETTE:	/* set color palette */
810		/* XXX */
811
812	case FBIOPUTCMAP:
813	case FBIOGETCMAP:
814	case FBIOPUTCMAPI:
815	case FBIOGETCMAPI:
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 FBIOVERTICAL:
827	case FBIOSCURSOR:
828	case FBIOGCURSOR:
829	case FBIOSCURPOS:
830	case FBIOGCURPOS:
831	case FBIOGCURMAX:
832	case FBIOMONINFO:
833	case FBIOGXINFO:
834
835	default:
836		error = ENODEV;
837		break;
838	}
839
840	splx(s);
841	return error;
842}
843