xref: /freebsd/sys/isa/vga_isa.c (revision f7f2df54)
18a997770SDoug Rabson /*-
28a997770SDoug Rabson  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
38a997770SDoug Rabson  * Copyright (c) 1992-1998 S�ren Schmidt
48a997770SDoug Rabson  * All rights reserved.
58a997770SDoug Rabson  *
68a997770SDoug Rabson  * Redistribution and use in source and binary forms, with or without
78a997770SDoug Rabson  * modification, are permitted provided that the following conditions
88a997770SDoug Rabson  * are met:
98a997770SDoug Rabson  * 1. Redistributions of source code must retain the above copyright
108a997770SDoug Rabson  *    notice, this list of conditions and the following disclaimer as
118a997770SDoug Rabson  *    the first lines of this file unmodified.
128a997770SDoug Rabson  * 2. Redistributions in binary form must reproduce the above copyright
138a997770SDoug Rabson  *    notice, this list of conditions and the following disclaimer in the
148a997770SDoug Rabson  *    documentation and/or other materials provided with the distribution.
158a997770SDoug Rabson  * 3. The name of the author may not be used to endorse or promote products
168a997770SDoug Rabson  *    derived from this software without specific prior written permission.
178a997770SDoug Rabson  *
188a997770SDoug Rabson  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
198a997770SDoug Rabson  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
208a997770SDoug Rabson  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
218a997770SDoug Rabson  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
228a997770SDoug Rabson  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
238a997770SDoug Rabson  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
248a997770SDoug Rabson  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258a997770SDoug Rabson  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
268a997770SDoug Rabson  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
278a997770SDoug Rabson  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
288a997770SDoug Rabson  *
29f7f2df54SDoug Rabson  * $Id: vga_isa.c,v 1.8 1999/05/09 16:39:24 peter Exp $
308a997770SDoug Rabson  */
318a997770SDoug Rabson 
328a997770SDoug Rabson #include "vga.h"
338a997770SDoug Rabson #include "opt_vga.h"
348a997770SDoug Rabson #include "opt_fb.h"
358a997770SDoug Rabson #include "opt_syscons.h"	/* should be removed in the future, XXX */
368a997770SDoug Rabson 
378a997770SDoug Rabson #if NVGA > 0
388a997770SDoug Rabson 
398a997770SDoug Rabson #include <sys/param.h>
408a997770SDoug Rabson #include <sys/systm.h>
418a997770SDoug Rabson #include <sys/kernel.h>
428a997770SDoug Rabson #include <sys/bus.h>
438a997770SDoug Rabson #include <sys/malloc.h>
448a997770SDoug Rabson 
458a997770SDoug Rabson #include <vm/vm.h>
468a997770SDoug Rabson #include <vm/pmap.h>
478a997770SDoug Rabson 
488a997770SDoug Rabson #include <machine/console.h>
498a997770SDoug Rabson #include <machine/md_var.h>
508a997770SDoug Rabson #include <machine/pc/bios.h>
518a997770SDoug Rabson 
528a997770SDoug Rabson #include <dev/fb/fbreg.h>
538a997770SDoug Rabson #include <dev/fb/vgareg.h>
548a997770SDoug Rabson 
558a997770SDoug Rabson #include <isa/isareg.h>
568a997770SDoug Rabson #include <isa/isavar.h>
578a997770SDoug Rabson 
588a997770SDoug Rabson #define DRIVER_NAME		"vga"
598a997770SDoug Rabson 
608a997770SDoug Rabson /* cdev driver declaration */
618a997770SDoug Rabson 
628a997770SDoug Rabson #define ISAVGA_UNIT(dev)	minor(dev)
638a997770SDoug Rabson #define ISAVGA_MKMINOR(unit)	(unit)
648a997770SDoug Rabson 
658a997770SDoug Rabson typedef struct isavga_softc {
668a997770SDoug Rabson 	video_adapter_t	*adp;
678a997770SDoug Rabson } isavga_softc_t;
688a997770SDoug Rabson 
698a997770SDoug Rabson #define ISAVGA_SOFTC(unit)		\
708a997770SDoug Rabson 	((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit))
718a997770SDoug Rabson 
728a997770SDoug Rabson devclass_t		isavga_devclass;
738a997770SDoug Rabson 
748a997770SDoug Rabson static int		isavga_probe(device_t dev);
758a997770SDoug Rabson static int		isavga_attach(device_t dev);
768a997770SDoug Rabson 
778a997770SDoug Rabson static device_method_t isavga_methods[] = {
788a997770SDoug Rabson 	DEVMETHOD(device_probe,		isavga_probe),
798a997770SDoug Rabson 	DEVMETHOD(device_attach,	isavga_attach),
808a997770SDoug Rabson 	{ 0, 0 }
818a997770SDoug Rabson };
828a997770SDoug Rabson 
838a997770SDoug Rabson static driver_t isavga_driver = {
848a997770SDoug Rabson 	DRIVER_NAME,
858a997770SDoug Rabson 	isavga_methods,
868a997770SDoug Rabson 	sizeof(isavga_softc_t),
878a997770SDoug Rabson };
888a997770SDoug Rabson 
898a997770SDoug Rabson DRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0);
908a997770SDoug Rabson 
918a997770SDoug Rabson static int		isavga_probe_unit(int unit, isavga_softc_t *sc,
928a997770SDoug Rabson 					  int flags);
938a997770SDoug Rabson static int		isavga_attach_unit(int unit, isavga_softc_t *sc,
948a997770SDoug Rabson 					   int flags);
958a997770SDoug Rabson 
968a997770SDoug Rabson #ifdef FB_INSTALL_CDEV
978a997770SDoug Rabson 
988a997770SDoug Rabson static d_open_t		isavgaopen;
998a997770SDoug Rabson static d_close_t	isavgaclose;
1008a997770SDoug Rabson static d_read_t		isavgaread;
1018a997770SDoug Rabson static d_ioctl_t	isavgaioctl;
1028a997770SDoug Rabson 
1038a997770SDoug Rabson static struct  cdevsw vga_cdevsw = {
1048a997770SDoug Rabson 	isavgaopen,	isavgaclose,	noread,		nowrite,	/* ?? */
1058a997770SDoug Rabson 	isavgaioctl,	nostop,		nullreset,	nodevtotty,
1068a997770SDoug Rabson 	seltrue,	nommap,		NULL,		DRIVER_NAME,
1078a997770SDoug Rabson 	NULL,		-1,		nodump,		nopsize,
1088a997770SDoug Rabson };
1098a997770SDoug Rabson 
1108a997770SDoug Rabson #endif /* FB_INSTALL_CDEV */
1118a997770SDoug Rabson 
1128a997770SDoug Rabson static int
1138a997770SDoug Rabson isavga_probe(device_t dev)
1148a997770SDoug Rabson {
1158a997770SDoug Rabson 	isavga_softc_t *sc;
1168a997770SDoug Rabson 
117f7f2df54SDoug Rabson 	/* No pnp support */
118f7f2df54SDoug Rabson 	if (isa_get_vendorid(dev))
119f7f2df54SDoug Rabson 		return (ENXIO);
120f7f2df54SDoug Rabson 
1218a997770SDoug Rabson 	device_set_desc(dev, "Generic ISA VGA");
1228a997770SDoug Rabson 	sc = device_get_softc(dev);
1238a997770SDoug Rabson 	return isavga_probe_unit(device_get_unit(dev), sc, isa_get_flags(dev));
1248a997770SDoug Rabson }
1258a997770SDoug Rabson 
1268a997770SDoug Rabson static int
1278a997770SDoug Rabson isavga_attach(device_t dev)
1288a997770SDoug Rabson {
1298a997770SDoug Rabson 	isavga_softc_t *sc;
1308a997770SDoug Rabson 
1318a997770SDoug Rabson 	sc = device_get_softc(dev);
1328a997770SDoug Rabson 	return isavga_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev));
1338a997770SDoug Rabson }
1348a997770SDoug Rabson 
1358a997770SDoug Rabson static int
1368a997770SDoug Rabson isavga_probe_unit(int unit, isavga_softc_t *sc, int flags)
1378a997770SDoug Rabson {
1388a997770SDoug Rabson 	video_switch_t *sw;
1398a997770SDoug Rabson 
1408a997770SDoug Rabson 	bzero(sc, sizeof(*sc));
1418a997770SDoug Rabson 	sw = vid_get_switch(DRIVER_NAME);
1428a997770SDoug Rabson 	if (sw == NULL)
1438a997770SDoug Rabson 		return 0;
1448a997770SDoug Rabson 	return (*sw->probe)(unit, &sc->adp, NULL, flags);
1458a997770SDoug Rabson }
1468a997770SDoug Rabson 
1478a997770SDoug Rabson static int
1488a997770SDoug Rabson isavga_attach_unit(int unit, isavga_softc_t *sc, int flags)
1498a997770SDoug Rabson {
1508a997770SDoug Rabson 	video_switch_t *sw;
1518a997770SDoug Rabson 	int error;
1528a997770SDoug Rabson 
1538a997770SDoug Rabson 	sw = vid_get_switch(DRIVER_NAME);
1548a997770SDoug Rabson 	if (sw == NULL)
1558a997770SDoug Rabson 		return ENXIO;
1568a997770SDoug Rabson 
1578a997770SDoug Rabson 	error = (*sw->init)(unit, sc->adp, flags);
1588a997770SDoug Rabson 	if (error)
1598a997770SDoug Rabson 		return ENXIO;
1608a997770SDoug Rabson 
1618a997770SDoug Rabson #ifdef FB_INSTALL_CDEV
1628a997770SDoug Rabson 	/* attach a virtual frame buffer device */
1638a997770SDoug Rabson 	error = fb_attach(makedev(0, ISAVGA_MKMINOR(unit)), scp->adp,
1648a997770SDoug Rabson 			  &vga_cdevsw);
1658a997770SDoug Rabson 	if (error)
1668a997770SDoug Rabson 		return error;
1678a997770SDoug Rabson #endif /* FB_INSTALL_CDEV */
1688a997770SDoug Rabson 
1698a997770SDoug Rabson 	if (bootverbose)
1701c27745fSKazutaka YOKOTA 		(*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose);
1718a997770SDoug Rabson 
1728a997770SDoug Rabson 	return 0;
1738a997770SDoug Rabson }
1748a997770SDoug Rabson 
1758a997770SDoug Rabson /* LOW-LEVEL */
1768a997770SDoug Rabson 
1778a997770SDoug Rabson #include <machine/clock.h>
1788a997770SDoug Rabson #include <machine/pc/vesa.h>
1798a997770SDoug Rabson 
1808a997770SDoug Rabson #define probe_done(adp)		((adp)->va_flags & V_ADP_PROBED)
1818a997770SDoug Rabson #define init_done(adp)		((adp)->va_flags & V_ADP_INITIALIZED)
1828a997770SDoug Rabson #define config_done(adp)	((adp)->va_flags & V_ADP_REGISTERED)
1838a997770SDoug Rabson 
1848a997770SDoug Rabson /* for compatibility with old kernel options */
1858a997770SDoug Rabson #ifdef SC_ALT_SEQACCESS
1868a997770SDoug Rabson #undef SC_ALT_SEQACCESS
1878a997770SDoug Rabson #undef VGA_ALT_SEQACCESS
1888a997770SDoug Rabson #define VGA_ALT_SEQACCESS	1
1898a997770SDoug Rabson #endif
1908a997770SDoug Rabson 
1918a997770SDoug Rabson #ifdef SLOW_VGA
1928a997770SDoug Rabson #undef SLOW_VGA
1938a997770SDoug Rabson #undef VGA_SLOW_IOACCESS
1948a997770SDoug Rabson #define VGA_SLOW_IOACCESS	1
1958a997770SDoug Rabson #endif
1968a997770SDoug Rabson 
1978a997770SDoug Rabson /* architecture dependent option */
1988a997770SDoug Rabson #ifdef __alpha__
1998a997770SDoug Rabson #define VGA_NO_BIOS		1
2008a997770SDoug Rabson #endif
2018a997770SDoug Rabson 
2028a997770SDoug Rabson /* this should really be in `rtc.h' */
2038a997770SDoug Rabson #define RTC_EQUIPMENT           0x14
2048a997770SDoug Rabson 
2058a997770SDoug Rabson /* various sizes */
2068a997770SDoug Rabson #define V_MODE_MAP_SIZE		(M_VGA_CG320 + 1)
2078a997770SDoug Rabson #define V_MODE_PARAM_SIZE	64
2088a997770SDoug Rabson 
2098a997770SDoug Rabson /* video adapter state buffer */
2108a997770SDoug Rabson struct adp_state {
2118a997770SDoug Rabson     int			sig;
2128a997770SDoug Rabson #define V_STATE_SIG	0x736f6962
2138a997770SDoug Rabson     u_char		regs[V_MODE_PARAM_SIZE];
2148a997770SDoug Rabson };
2158a997770SDoug Rabson typedef struct adp_state adp_state_t;
2168a997770SDoug Rabson 
2178a997770SDoug Rabson /* video adapter information */
2188a997770SDoug Rabson #define DCC_MONO	0
2198a997770SDoug Rabson #define DCC_CGA40	1
2208a997770SDoug Rabson #define DCC_CGA80	2
2218a997770SDoug Rabson #define DCC_EGAMONO	3
2228a997770SDoug Rabson #define DCC_EGA40	4
2238a997770SDoug Rabson #define DCC_EGA80	5
2248a997770SDoug Rabson 
2258a997770SDoug Rabson /*
2268a997770SDoug Rabson  * NOTE: `va_window' should have a virtual address, but is initialized
2278a997770SDoug Rabson  * with a physical address in the following table, as verify_adapter()
2288a997770SDoug Rabson  * will perform address conversion at run-time.
2298a997770SDoug Rabson  */
2308a997770SDoug Rabson static video_adapter_t adapter_init_value[] = {
2318a997770SDoug Rabson     /* DCC_MONO */
2328a997770SDoug Rabson     { 0, KD_MONO, "mda", 0, 0, 0, 	    IO_MDA, IO_MDASIZE, MONO_CRTC,
2338a997770SDoug Rabson       MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
2341c27745fSKazutaka YOKOTA       0, 0, 0, 7, 0, },
2358a997770SDoug Rabson     /* DCC_CGA40 */
2368a997770SDoug Rabson     { 0, KD_CGA,  "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
2378a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
2381c27745fSKazutaka YOKOTA       0, 0, 0, 3, 0, },
2398a997770SDoug Rabson     /* DCC_CGA80 */
2408a997770SDoug Rabson     { 0, KD_CGA,  "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC,
2418a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
2421c27745fSKazutaka YOKOTA       0, 0, 0, 3, 0, },
2438a997770SDoug Rabson     /* DCC_EGAMONO */
2448a997770SDoug Rabson     { 0, KD_EGA,  "ega", 0, 0, 0,	    IO_MDA, 48,	  MONO_CRTC,
2458a997770SDoug Rabson       EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE,
2461c27745fSKazutaka YOKOTA       0, 0, 0, 7, 0, },
2478a997770SDoug Rabson     /* DCC_EGA40 */
2488a997770SDoug Rabson     { 0, KD_EGA,  "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48,	  COLOR_CRTC,
2498a997770SDoug Rabson       EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
2501c27745fSKazutaka YOKOTA       0, 0, 0, 3, 0, },
2518a997770SDoug Rabson     /* DCC_EGA80 */
2528a997770SDoug Rabson     { 0, KD_EGA,  "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48,	  COLOR_CRTC,
2538a997770SDoug Rabson       EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE,
2541c27745fSKazutaka YOKOTA       0, 0, 0, 3, 0, },
2558a997770SDoug Rabson };
2568a997770SDoug Rabson 
2578a997770SDoug Rabson static video_adapter_t	biosadapter[2];
2588a997770SDoug Rabson static int		biosadapters = 0;
2598a997770SDoug Rabson 
2608a997770SDoug Rabson /* video driver declarations */
2618a997770SDoug Rabson static int			vga_configure(int flags);
2628a997770SDoug Rabson        int			(*vga_sub_configure)(int flags);
2638a997770SDoug Rabson static int			vga_nop(void);
2648a997770SDoug Rabson static vi_probe_t		vga_probe;
2658a997770SDoug Rabson static vi_init_t		vga_init;
2668a997770SDoug Rabson static vi_get_info_t		vga_get_info;
2678a997770SDoug Rabson static vi_query_mode_t		vga_query_mode;
2688a997770SDoug Rabson static vi_set_mode_t		vga_set_mode;
2698a997770SDoug Rabson static vi_save_font_t		vga_save_font;
2708a997770SDoug Rabson static vi_load_font_t		vga_load_font;
2718a997770SDoug Rabson static vi_show_font_t		vga_show_font;
2728a997770SDoug Rabson static vi_save_palette_t	vga_save_palette;
2738a997770SDoug Rabson static vi_load_palette_t	vga_load_palette;
2748a997770SDoug Rabson static vi_set_border_t		vga_set_border;
2758a997770SDoug Rabson static vi_save_state_t		vga_save_state;
2768a997770SDoug Rabson static vi_load_state_t		vga_load_state;
2778a997770SDoug Rabson static vi_set_win_org_t		vga_set_origin;
2788a997770SDoug Rabson static vi_read_hw_cursor_t	vga_read_hw_cursor;
2798a997770SDoug Rabson static vi_set_hw_cursor_t	vga_set_hw_cursor;
2808a997770SDoug Rabson static vi_set_hw_cursor_shape_t	vga_set_hw_cursor_shape;
2818a997770SDoug Rabson static vi_mmap_t		vga_mmap;
2828a997770SDoug Rabson static vi_diag_t		vga_diag;
2838a997770SDoug Rabson 
2848a997770SDoug Rabson static video_switch_t vgavidsw = {
2858a997770SDoug Rabson 	vga_probe,
2868a997770SDoug Rabson 	vga_init,
2878a997770SDoug Rabson 	vga_get_info,
2888a997770SDoug Rabson 	vga_query_mode,
2898a997770SDoug Rabson 	vga_set_mode,
2908a997770SDoug Rabson 	vga_save_font,
2918a997770SDoug Rabson 	vga_load_font,
2928a997770SDoug Rabson 	vga_show_font,
2938a997770SDoug Rabson 	vga_save_palette,
2948a997770SDoug Rabson 	vga_load_palette,
2958a997770SDoug Rabson 	vga_set_border,
2968a997770SDoug Rabson 	vga_save_state,
2978a997770SDoug Rabson 	vga_load_state,
2988a997770SDoug Rabson 	vga_set_origin,
2998a997770SDoug Rabson 	vga_read_hw_cursor,
3008a997770SDoug Rabson 	vga_set_hw_cursor,
3018a997770SDoug Rabson 	vga_set_hw_cursor_shape,
3028a997770SDoug Rabson 	(vi_blank_display_t *)vga_nop,
3038a997770SDoug Rabson 	vga_mmap,
3048a997770SDoug Rabson 	vga_diag,
3058a997770SDoug Rabson };
3068a997770SDoug Rabson 
3078a997770SDoug Rabson VIDEO_DRIVER(mda, vgavidsw, NULL);
3088a997770SDoug Rabson VIDEO_DRIVER(cga, vgavidsw, NULL);
3098a997770SDoug Rabson VIDEO_DRIVER(ega, vgavidsw, NULL);
3108a997770SDoug Rabson VIDEO_DRIVER(vga, vgavidsw, vga_configure);
3118a997770SDoug Rabson 
3128a997770SDoug Rabson /* VGA BIOS standard video modes */
3138a997770SDoug Rabson #define EOT		(-1)
3148a997770SDoug Rabson #define NA		(-2)
3158a997770SDoug Rabson 
3168a997770SDoug Rabson static video_info_t bios_vmode[] = {
3178a997770SDoug Rabson     /* CGA */
3188a997770SDoug Rabson     { M_B40x25,     V_INFO_COLOR, 40, 25, 8,  8, 2, 1,
3198a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3208a997770SDoug Rabson     { M_C40x25,     V_INFO_COLOR, 40, 25, 8,  8, 4, 1,
3218a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3228a997770SDoug Rabson     { M_B80x25,     V_INFO_COLOR, 80, 25, 8,  8, 2, 1,
3238a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3248a997770SDoug Rabson     { M_C80x25,     V_INFO_COLOR, 80, 25, 8,  8, 4, 1,
3258a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3268a997770SDoug Rabson     /* EGA */
3278a997770SDoug Rabson     { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1,
3288a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3298a997770SDoug Rabson     { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1,
3308a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3318a997770SDoug Rabson     { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1,
3328a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3338a997770SDoug Rabson     { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1,
3348a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3358a997770SDoug Rabson     /* VGA */
3368a997770SDoug Rabson     { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1,
3378a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3388a997770SDoug Rabson     { M_VGA_M80x25, 0,            80, 25, 8, 16, 2, 1,
3398a997770SDoug Rabson       MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
3408a997770SDoug Rabson     { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1,
3418a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3428a997770SDoug Rabson     /* MDA */
3438a997770SDoug Rabson     { M_EGAMONO80x25, 0,          80, 25, 8, 14, 2, 1,
3448a997770SDoug Rabson       MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
3458a997770SDoug Rabson     /* EGA */
3468a997770SDoug Rabson     { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8,  8, 2, 1,
3478a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3488a997770SDoug Rabson     { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8,  8, 4, 1,
3498a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3508a997770SDoug Rabson     /* VGA */
3518a997770SDoug Rabson     { M_VGA_M80x30, 0,            80, 30, 8, 16, 2, 1,
3528a997770SDoug Rabson       MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
3538a997770SDoug Rabson     { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1,
3548a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3558a997770SDoug Rabson     { M_VGA_M80x50, 0,            80, 50, 8,  8, 2, 1,
3568a997770SDoug Rabson       MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
3578a997770SDoug Rabson     { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8,  8, 4, 1,
3588a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3598a997770SDoug Rabson     { M_VGA_M80x60, 0,            80, 60, 8,  8, 2, 1,
3608a997770SDoug Rabson       MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 },
3618a997770SDoug Rabson     { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8,  8, 4, 1,
3628a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3638a997770SDoug Rabson #ifndef VGA_NO_MODE_CHANGE
3648a997770SDoug Rabson     /* CGA */
3658a997770SDoug Rabson     { M_BG320,      V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8,  8, 2, 1,
3668a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3678a997770SDoug Rabson     { M_CG320,      V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8,  8, 2, 1,
3688a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3698a997770SDoug Rabson     { M_BG640,      V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8,  8, 1, 1,
3708a997770SDoug Rabson       CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },
3718a997770SDoug Rabson     /* EGA */
3728a997770SDoug Rabson     { M_CG320_D,    V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8,  8, 4, 4,
3738a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3748a997770SDoug Rabson     { M_CG640_E,    V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8,  8, 4, 4,
3758a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3768a997770SDoug Rabson     { M_EGAMONOAPA, V_INFO_GRAPHICS,                640, 350, 8, 14, 4, 4,
3778a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 },
3788a997770SDoug Rabson     { M_ENHMONOAPA2,V_INFO_GRAPHICS,                640, 350, 8, 14, 4, 4,
3798a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3808a997770SDoug Rabson     { M_CG640x350,  V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2,
3818a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3828a997770SDoug Rabson     { M_ENH_CG640,  V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4,
3838a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3848a997770SDoug Rabson     /* VGA */
3858a997770SDoug Rabson     { M_BG640x480,  V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
3868a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3878a997770SDoug Rabson     { M_CG640x480,  V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4,
3888a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3898a997770SDoug Rabson     { M_VGA_CG320,  V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8,  8, 8, 1,
3908a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3918a997770SDoug Rabson     { M_VGA_MODEX,  V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8,  8, 8, 1,
3928a997770SDoug Rabson       GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },
3938a997770SDoug Rabson #endif /* VGA_NO_MODE_CHANGE */
3948a997770SDoug Rabson 
3958a997770SDoug Rabson     { EOT },
3968a997770SDoug Rabson };
3978a997770SDoug Rabson 
3988a997770SDoug Rabson static int		init_done = FALSE;
3996e694ebbSPeter Wemm #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
4008a997770SDoug Rabson static u_char		*video_mode_ptr = NULL;		/* EGA/VGA */
4018a997770SDoug Rabson static u_char		*video_mode_ptr2 = NULL;	/* CGA/MDA */
4026e694ebbSPeter Wemm #endif
4038a997770SDoug Rabson static u_char		*mode_map[V_MODE_MAP_SIZE];
4048a997770SDoug Rabson static adp_state_t	adpstate;
4058a997770SDoug Rabson static adp_state_t	adpstate2;
4068a997770SDoug Rabson static int		rows_offset = 1;
4078a997770SDoug Rabson 
4088a997770SDoug Rabson /* local macros and functions */
4098a997770SDoug Rabson #define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))
4108a997770SDoug Rabson 
4118a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
4128a997770SDoug Rabson static void map_mode_table(u_char *map[], u_char *table, int max);
4138a997770SDoug Rabson #endif
4148a997770SDoug Rabson static void clear_mode_map(video_adapter_t *adp, u_char *map[], int max,
4158a997770SDoug Rabson 			   int color);
4168a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
4178a997770SDoug Rabson static int map_mode_num(int mode);
4188a997770SDoug Rabson #endif
4198a997770SDoug Rabson static int map_gen_mode_num(int type, int color, int mode);
4208a997770SDoug Rabson static int map_bios_mode_num(int type, int color, int bios_mode);
4218a997770SDoug Rabson static u_char *get_mode_param(int mode);
4228a997770SDoug Rabson #ifndef VGA_NO_BIOS
4238a997770SDoug Rabson static void fill_adapter_param(int code, video_adapter_t *adp);
4248a997770SDoug Rabson #endif
4258a997770SDoug Rabson static int verify_adapter(video_adapter_t *adp);
4261c27745fSKazutaka YOKOTA static void update_adapter_info(video_adapter_t *adp, video_info_t *info);
4278a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
4288a997770SDoug Rabson #define COMP_IDENTICAL	0
4298a997770SDoug Rabson #define COMP_SIMILAR	1
4308a997770SDoug Rabson #define COMP_DIFFERENT	2
4318a997770SDoug Rabson static int comp_adpregs(u_char *buf1, u_char *buf2);
4328a997770SDoug Rabson #endif
4338a997770SDoug Rabson static int probe_adapters(void);
4348a997770SDoug Rabson 
4356e694ebbSPeter Wemm #ifndef VGA_NO_FONT_LOADING
4368a997770SDoug Rabson #define PARAM_BUFSIZE	6
4378a997770SDoug Rabson static void set_font_mode(video_adapter_t *adp, u_char *buf);
4388a997770SDoug Rabson static void set_normal_mode(video_adapter_t *adp, u_char *buf);
4396e694ebbSPeter Wemm #endif
4408a997770SDoug Rabson 
4418a997770SDoug Rabson static void dump_buffer(u_char *buf, size_t len);
4428a997770SDoug Rabson 
4438a997770SDoug Rabson #define	ISMAPPED(pa, width)				\
4448a997770SDoug Rabson 	(((pa) <= (u_long)0x1000 - (width)) 		\
4458a997770SDoug Rabson 	 || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width)))
4468a997770SDoug Rabson 
4478a997770SDoug Rabson #define	prologue(adp, flag, err)			\
4488a997770SDoug Rabson 	if (!init_done || !((adp)->va_flags & (flag)))	\
4498a997770SDoug Rabson 	    return (err)
4508a997770SDoug Rabson 
4518a997770SDoug Rabson /* a backdoor for the console driver */
4528a997770SDoug Rabson static int
4538a997770SDoug Rabson vga_configure(int flags)
4548a997770SDoug Rabson {
4558a997770SDoug Rabson     int i;
4568a997770SDoug Rabson 
4578a997770SDoug Rabson     probe_adapters();
4588a997770SDoug Rabson     for (i = 0; i < biosadapters; ++i) {
4598a997770SDoug Rabson 	if (!probe_done(&biosadapter[i]))
4608a997770SDoug Rabson 	    continue;
4618a997770SDoug Rabson 	biosadapter[i].va_flags |= V_ADP_INITIALIZED;
4628a997770SDoug Rabson 	if (!config_done(&biosadapter[i])) {
4638a997770SDoug Rabson 	    if (vid_register(&biosadapter[i]) < 0)
4648a997770SDoug Rabson 		continue;
4658a997770SDoug Rabson 	    biosadapter[i].va_flags |= V_ADP_REGISTERED;
4668a997770SDoug Rabson 	}
4678a997770SDoug Rabson     }
4688a997770SDoug Rabson     if (vga_sub_configure != NULL)
4698a997770SDoug Rabson 	(*vga_sub_configure)(flags);
4708a997770SDoug Rabson 
4718a997770SDoug Rabson     return biosadapters;
4728a997770SDoug Rabson }
4738a997770SDoug Rabson 
4748a997770SDoug Rabson /* local subroutines */
4758a997770SDoug Rabson 
4768a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
4778a997770SDoug Rabson /* construct the mode parameter map */
4788a997770SDoug Rabson static void
4798a997770SDoug Rabson map_mode_table(u_char *map[], u_char *table, int max)
4808a997770SDoug Rabson {
4818a997770SDoug Rabson     int i;
4828a997770SDoug Rabson 
4838a997770SDoug Rabson     for(i = 0; i < max; ++i)
4848a997770SDoug Rabson 	map[i] = table + i*V_MODE_PARAM_SIZE;
4858a997770SDoug Rabson     for(; i < V_MODE_MAP_SIZE; ++i)
4868a997770SDoug Rabson 	map[i] = NULL;
4878a997770SDoug Rabson }
4888a997770SDoug Rabson #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
4898a997770SDoug Rabson 
4908a997770SDoug Rabson static void
4918a997770SDoug Rabson clear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color)
4928a997770SDoug Rabson {
4938a997770SDoug Rabson     video_info_t info;
4948a997770SDoug Rabson     int i;
4958a997770SDoug Rabson 
4968a997770SDoug Rabson     /*
4978a997770SDoug Rabson      * NOTE: we don't touch `bios_vmode[]' because it is shared
4988a997770SDoug Rabson      * by all adapters.
4998a997770SDoug Rabson      */
5008a997770SDoug Rabson     for(i = 0; i < max; ++i) {
5018a997770SDoug Rabson 	if (vga_get_info(adp, i, &info))
5028a997770SDoug Rabson 	    continue;
5038a997770SDoug Rabson 	if ((info.vi_flags & V_INFO_COLOR) != color)
5048a997770SDoug Rabson 	    map[i] = NULL;
5058a997770SDoug Rabson     }
5068a997770SDoug Rabson }
5078a997770SDoug Rabson 
5088a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
5098a997770SDoug Rabson /* map the non-standard video mode to a known mode number */
5108a997770SDoug Rabson static int
5118a997770SDoug Rabson map_mode_num(int mode)
5128a997770SDoug Rabson {
5138a997770SDoug Rabson     static struct {
5148a997770SDoug Rabson         int from;
5158a997770SDoug Rabson         int to;
5168a997770SDoug Rabson     } mode_map[] = {
5178a997770SDoug Rabson         { M_ENH_B80x43, M_ENH_B80x25 },
5188a997770SDoug Rabson         { M_ENH_C80x43, M_ENH_C80x25 },
5198a997770SDoug Rabson         { M_VGA_M80x30, M_VGA_M80x25 },
5208a997770SDoug Rabson         { M_VGA_C80x30, M_VGA_C80x25 },
5218a997770SDoug Rabson         { M_VGA_M80x50, M_VGA_M80x25 },
5228a997770SDoug Rabson         { M_VGA_C80x50, M_VGA_C80x25 },
5238a997770SDoug Rabson         { M_VGA_M80x60, M_VGA_M80x25 },
5248a997770SDoug Rabson         { M_VGA_C80x60, M_VGA_C80x25 },
5258a997770SDoug Rabson         { M_VGA_MODEX,  M_VGA_CG320 },
5268a997770SDoug Rabson     };
5278a997770SDoug Rabson     int i;
5288a997770SDoug Rabson 
5298a997770SDoug Rabson     for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
5308a997770SDoug Rabson         if (mode_map[i].from == mode)
5318a997770SDoug Rabson             return mode_map[i].to;
5328a997770SDoug Rabson     }
5338a997770SDoug Rabson     return mode;
5348a997770SDoug Rabson }
5358a997770SDoug Rabson #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
5368a997770SDoug Rabson 
5378a997770SDoug Rabson /* map a generic video mode to a known mode number */
5388a997770SDoug Rabson static int
5398a997770SDoug Rabson map_gen_mode_num(int type, int color, int mode)
5408a997770SDoug Rabson {
5418a997770SDoug Rabson     static struct {
5428a997770SDoug Rabson 	int from;
5438a997770SDoug Rabson 	int to_color;
5448a997770SDoug Rabson 	int to_mono;
5458a997770SDoug Rabson     } mode_map[] = {
5468a997770SDoug Rabson 	{ M_TEXT_80x30,	M_VGA_C80x30, M_VGA_M80x30, },
5478a997770SDoug Rabson 	{ M_TEXT_80x43,	M_ENH_C80x43, M_ENH_B80x43, },
5488a997770SDoug Rabson 	{ M_TEXT_80x50,	M_VGA_C80x50, M_VGA_M80x50, },
5498a997770SDoug Rabson 	{ M_TEXT_80x60,	M_VGA_C80x60, M_VGA_M80x60, },
5508a997770SDoug Rabson     };
5518a997770SDoug Rabson     int i;
5528a997770SDoug Rabson 
5538a997770SDoug Rabson     if (mode == M_TEXT_80x25) {
5548a997770SDoug Rabson 	switch (type) {
5558a997770SDoug Rabson 
5568a997770SDoug Rabson 	case KD_VGA:
5578a997770SDoug Rabson 	    if (color)
5588a997770SDoug Rabson 		return M_VGA_C80x25;
5598a997770SDoug Rabson 	    else
5608a997770SDoug Rabson 		return M_VGA_M80x25;
5618a997770SDoug Rabson 	    break;
5628a997770SDoug Rabson 
5638a997770SDoug Rabson 	case KD_EGA:
5648a997770SDoug Rabson 	    if (color)
5658a997770SDoug Rabson 		return M_ENH_C80x25;
5668a997770SDoug Rabson 	    else
5678a997770SDoug Rabson 		return M_EGAMONO80x25;
5688a997770SDoug Rabson 	    break;
5698a997770SDoug Rabson 
5708a997770SDoug Rabson 	case KD_CGA:
5718a997770SDoug Rabson 	    return M_C80x25;
5728a997770SDoug Rabson 
5738a997770SDoug Rabson 	case KD_MONO:
5748a997770SDoug Rabson 	case KD_HERCULES:
5758a997770SDoug Rabson 	    return M_EGAMONO80x25;	/* XXX: this name is confusing */
5768a997770SDoug Rabson 
5778a997770SDoug Rabson  	default:
5788a997770SDoug Rabson 	    return -1;
5798a997770SDoug Rabson 	}
5808a997770SDoug Rabson     }
5818a997770SDoug Rabson 
5828a997770SDoug Rabson     for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {
5838a997770SDoug Rabson         if (mode_map[i].from == mode)
5848a997770SDoug Rabson             return ((color) ? mode_map[i].to_color : mode_map[i].to_mono);
5858a997770SDoug Rabson     }
5868a997770SDoug Rabson     return mode;
5878a997770SDoug Rabson }
5888a997770SDoug Rabson 
5898a997770SDoug Rabson /* turn the BIOS video number into our video mode number */
5908a997770SDoug Rabson static int
5918a997770SDoug Rabson map_bios_mode_num(int type, int color, int bios_mode)
5928a997770SDoug Rabson {
5938a997770SDoug Rabson     static int cga_modes[7] = {
5948a997770SDoug Rabson 	M_B40x25, M_C40x25,		/* 0, 1 */
5958a997770SDoug Rabson 	M_B80x25, M_C80x25,		/* 2, 3 */
5968a997770SDoug Rabson 	M_BG320, M_CG320,
5978a997770SDoug Rabson 	M_BG640,
5988a997770SDoug Rabson     };
5998a997770SDoug Rabson     static int ega_modes[17] = {
6008a997770SDoug Rabson 	M_ENH_B40x25, M_ENH_C40x25,	/* 0, 1 */
6018a997770SDoug Rabson 	M_ENH_B80x25, M_ENH_C80x25,	/* 2, 3 */
6028a997770SDoug Rabson 	M_BG320, M_CG320,
6038a997770SDoug Rabson 	M_BG640,
6048a997770SDoug Rabson 	M_EGAMONO80x25,			/* 7 */
6058a997770SDoug Rabson 	8, 9, 10, 11, 12,
6068a997770SDoug Rabson 	M_CG320_D,
6078a997770SDoug Rabson 	M_CG640_E,
6088a997770SDoug Rabson 	M_ENHMONOAPA2,			/* XXX: video momery > 64K */
6098a997770SDoug Rabson 	M_ENH_CG640,			/* XXX: video momery > 64K */
6108a997770SDoug Rabson     };
6118a997770SDoug Rabson     static int vga_modes[20] = {
6128a997770SDoug Rabson 	M_VGA_C40x25, M_VGA_C40x25,	/* 0, 1 */
6138a997770SDoug Rabson 	M_VGA_C80x25, M_VGA_C80x25,	/* 2, 3 */
6148a997770SDoug Rabson 	M_BG320, M_CG320,
6158a997770SDoug Rabson 	M_BG640,
6168a997770SDoug Rabson 	M_VGA_M80x25,			/* 7 */
6178a997770SDoug Rabson 	8, 9, 10, 11, 12,
6188a997770SDoug Rabson 	M_CG320_D,
6198a997770SDoug Rabson 	M_CG640_E,
6208a997770SDoug Rabson 	M_ENHMONOAPA2,
6218a997770SDoug Rabson 	M_ENH_CG640,
6228a997770SDoug Rabson 	M_BG640x480, M_CG640x480,
6238a997770SDoug Rabson 	M_VGA_CG320,
6248a997770SDoug Rabson     };
6258a997770SDoug Rabson 
6268a997770SDoug Rabson     switch (type) {
6278a997770SDoug Rabson 
6288a997770SDoug Rabson     case KD_VGA:
6298a997770SDoug Rabson 	if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0]))
6308a997770SDoug Rabson 	    return vga_modes[bios_mode];
6318a997770SDoug Rabson 	else if (color)
6328a997770SDoug Rabson 	    return M_VGA_C80x25;
6338a997770SDoug Rabson 	else
6348a997770SDoug Rabson 	    return M_VGA_M80x25;
6358a997770SDoug Rabson 	break;
6368a997770SDoug Rabson 
6378a997770SDoug Rabson     case KD_EGA:
6388a997770SDoug Rabson 	if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0]))
6398a997770SDoug Rabson 	    return ega_modes[bios_mode];
6408a997770SDoug Rabson 	else if (color)
6418a997770SDoug Rabson 	    return M_ENH_C80x25;
6428a997770SDoug Rabson 	else
6438a997770SDoug Rabson 	    return M_EGAMONO80x25;
6448a997770SDoug Rabson 	break;
6458a997770SDoug Rabson 
6468a997770SDoug Rabson     case KD_CGA:
6478a997770SDoug Rabson 	if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0]))
6488a997770SDoug Rabson 	    return cga_modes[bios_mode];
6498a997770SDoug Rabson 	else
6508a997770SDoug Rabson 	    return M_C80x25;
6518a997770SDoug Rabson 	break;
6528a997770SDoug Rabson 
6538a997770SDoug Rabson     case KD_MONO:
6548a997770SDoug Rabson     case KD_HERCULES:
6558a997770SDoug Rabson 	return M_EGAMONO80x25;		/* XXX: this name is confusing */
6568a997770SDoug Rabson 
6578a997770SDoug Rabson     default:
6588a997770SDoug Rabson 	break;
6598a997770SDoug Rabson     }
6608a997770SDoug Rabson     return -1;
6618a997770SDoug Rabson }
6628a997770SDoug Rabson 
6638a997770SDoug Rabson /* look up a parameter table entry */
6648a997770SDoug Rabson static u_char
6658a997770SDoug Rabson *get_mode_param(int mode)
6668a997770SDoug Rabson {
6678a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
6688a997770SDoug Rabson     if (mode >= V_MODE_MAP_SIZE)
6698a997770SDoug Rabson 	mode = map_mode_num(mode);
6708a997770SDoug Rabson #endif
6718a997770SDoug Rabson     if ((mode >= 0) && (mode < V_MODE_MAP_SIZE))
6728a997770SDoug Rabson 	return mode_map[mode];
6738a997770SDoug Rabson     else
6748a997770SDoug Rabson 	return NULL;
6758a997770SDoug Rabson }
6768a997770SDoug Rabson 
6778a997770SDoug Rabson #ifndef VGA_NO_BIOS
6788a997770SDoug Rabson static void
6798a997770SDoug Rabson fill_adapter_param(int code, video_adapter_t *adp)
6808a997770SDoug Rabson {
6818a997770SDoug Rabson     static struct {
6828a997770SDoug Rabson 	int primary;
6838a997770SDoug Rabson 	int secondary;
6848a997770SDoug Rabson     } dcc[] = {
6858a997770SDoug Rabson 	{ DCC_MONO, 			DCC_EGA40 /* CGA monitor */ },
6868a997770SDoug Rabson 	{ DCC_MONO, 			DCC_EGA80 /* CGA monitor */ },
6878a997770SDoug Rabson 	{ DCC_MONO, 			DCC_EGA80 /* CGA emulation */ },
6888a997770SDoug Rabson 	{ DCC_MONO, 			DCC_EGA80 },
6898a997770SDoug Rabson 	{ DCC_CGA40, 			DCC_EGAMONO },
6908a997770SDoug Rabson 	{ DCC_CGA80, 			DCC_EGAMONO },
6918a997770SDoug Rabson 	{ DCC_EGA40 /* CGA monitor */, 	DCC_MONO},
6928a997770SDoug Rabson 	{ DCC_EGA80 /* CGA monitor */, 	DCC_MONO},
6938a997770SDoug Rabson 	{ DCC_EGA80 /* CGA emulation */,DCC_MONO },
6948a997770SDoug Rabson 	{ DCC_EGA80, 			DCC_MONO },
6958a997770SDoug Rabson 	{ DCC_EGAMONO, 			DCC_CGA40 },
6968a997770SDoug Rabson 	{ DCC_EGAMONO, 			DCC_CGA40 },
6978a997770SDoug Rabson     };
6988a997770SDoug Rabson 
6998a997770SDoug Rabson     if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) {
7008a997770SDoug Rabson 	adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
7018a997770SDoug Rabson 	adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
7028a997770SDoug Rabson     } else {
7038a997770SDoug Rabson 	adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary];
7048a997770SDoug Rabson 	adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary];
7058a997770SDoug Rabson     }
7068a997770SDoug Rabson }
7078a997770SDoug Rabson #endif /* VGA_NO_BIOS */
7088a997770SDoug Rabson 
7098a997770SDoug Rabson static int
7108a997770SDoug Rabson verify_adapter(video_adapter_t *adp)
7118a997770SDoug Rabson {
7128a997770SDoug Rabson     vm_offset_t buf;
7138a997770SDoug Rabson     u_int16_t v;
7146182fdbdSPeter Wemm #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
7156182fdbdSPeter Wemm     u_int32_t p;
7166182fdbdSPeter Wemm #endif
7178a997770SDoug Rabson 
7188a997770SDoug Rabson     buf = BIOS_PADDRTOVADDR(adp->va_window);
7198a997770SDoug Rabson     v = readw(buf);
7208a997770SDoug Rabson     writew(buf, 0xA55A);
7218a997770SDoug Rabson     if (readw(buf) != 0xA55A)
7228a997770SDoug Rabson 	return 1;
7238a997770SDoug Rabson     writew(buf, v);
7248a997770SDoug Rabson 
7258a997770SDoug Rabson     switch (adp->va_type) {
7268a997770SDoug Rabson 
7278a997770SDoug Rabson     case KD_EGA:
7288a997770SDoug Rabson 	outb(adp->va_crtc_addr, 7);
7298a997770SDoug Rabson 	if (inb(adp->va_crtc_addr) == 7) {
7308a997770SDoug Rabson 	    adp->va_type = KD_VGA;
7318a997770SDoug Rabson 	    adp->va_name = "vga";
7328a997770SDoug Rabson 	    adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE;
7338a997770SDoug Rabson 	}
7348a997770SDoug Rabson 	adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER;
7358a997770SDoug Rabson 	/* the color adapter may be in the 40x25 mode... XXX */
7368a997770SDoug Rabson 
7378a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
7388a997770SDoug Rabson 	/* get the BIOS video mode pointer */
7398a997770SDoug Rabson 	p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8);
7408a997770SDoug Rabson 	p = BIOS_SADDRTOLADDR(p);
7418a997770SDoug Rabson 	if (ISMAPPED(p, sizeof(u_int32_t))) {
7428a997770SDoug Rabson 	    p = *(u_int32_t *)BIOS_PADDRTOVADDR(p);
7438a997770SDoug Rabson 	    p = BIOS_SADDRTOLADDR(p);
7448a997770SDoug Rabson 	    if (ISMAPPED(p, V_MODE_PARAM_SIZE))
7458a997770SDoug Rabson 		video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p);
7468a997770SDoug Rabson 	}
7478a997770SDoug Rabson #endif
7488a997770SDoug Rabson 	break;
7498a997770SDoug Rabson 
7508a997770SDoug Rabson     case KD_CGA:
7518a997770SDoug Rabson 	adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER;
7528a997770SDoug Rabson 	/* may be in the 40x25 mode... XXX */
7538a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
7548a997770SDoug Rabson 	/* get the BIOS video mode pointer */
7558a997770SDoug Rabson 	p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
7568a997770SDoug Rabson 	p = BIOS_SADDRTOLADDR(p);
7578a997770SDoug Rabson 	video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
7588a997770SDoug Rabson #endif
7598a997770SDoug Rabson 	break;
7608a997770SDoug Rabson 
7618a997770SDoug Rabson     case KD_MONO:
7628a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
7638a997770SDoug Rabson 	/* get the BIOS video mode pointer */
7648a997770SDoug Rabson 	p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4);
7658a997770SDoug Rabson 	p = BIOS_SADDRTOLADDR(p);
7668a997770SDoug Rabson 	video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p);
7678a997770SDoug Rabson #endif
7688a997770SDoug Rabson 	break;
7698a997770SDoug Rabson     }
7708a997770SDoug Rabson 
7718a997770SDoug Rabson     return 0;
7728a997770SDoug Rabson }
7738a997770SDoug Rabson 
7741c27745fSKazutaka YOKOTA static void
7751c27745fSKazutaka YOKOTA update_adapter_info(video_adapter_t *adp, video_info_t *info)
7761c27745fSKazutaka YOKOTA {
7771c27745fSKazutaka YOKOTA     adp->va_flags &= ~V_ADP_COLOR;
7781c27745fSKazutaka YOKOTA     adp->va_flags |=
7791c27745fSKazutaka YOKOTA 	(info->vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0;
7801c27745fSKazutaka YOKOTA     adp->va_crtc_addr =
7811c27745fSKazutaka YOKOTA 	(adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC;
7821c27745fSKazutaka YOKOTA     adp->va_window = BIOS_PADDRTOVADDR(info->vi_window);
7831c27745fSKazutaka YOKOTA     adp->va_window_size = info->vi_window_size;
7841c27745fSKazutaka YOKOTA     adp->va_window_gran = info->vi_window_gran;
7851c27745fSKazutaka YOKOTA     if (info->vi_buffer_size == 0) {
7861c27745fSKazutaka YOKOTA     	adp->va_buffer = 0;
7871c27745fSKazutaka YOKOTA     	adp->va_buffer_size = 0;
7881c27745fSKazutaka YOKOTA     } else {
7891c27745fSKazutaka YOKOTA     	adp->va_buffer = BIOS_PADDRTOVADDR(info->vi_buffer);
7901c27745fSKazutaka YOKOTA     	adp->va_buffer_size = info->vi_buffer_size;
7911c27745fSKazutaka YOKOTA     }
7923dec8614SKazutaka YOKOTA     if (info->vi_flags & V_INFO_GRAPHICS) {
7933dec8614SKazutaka YOKOTA 	switch (info->vi_depth/info->vi_planes) {
7943dec8614SKazutaka YOKOTA 	case 1:
7951c27745fSKazutaka YOKOTA 	    adp->va_line_width = info->vi_width/8;
7963dec8614SKazutaka YOKOTA 	    break;
7973dec8614SKazutaka YOKOTA 	case 2:
7983dec8614SKazutaka YOKOTA 	    adp->va_line_width = info->vi_width/4;
7993dec8614SKazutaka YOKOTA 	    break;
8003dec8614SKazutaka YOKOTA 	case 4:
8013dec8614SKazutaka YOKOTA 	    adp->va_line_width = info->vi_width/2;
8023dec8614SKazutaka YOKOTA 	    break;
8033dec8614SKazutaka YOKOTA 	case 8:
8043dec8614SKazutaka YOKOTA 	default: /* shouldn't happen */
8051c27745fSKazutaka YOKOTA 	    adp->va_line_width = info->vi_width;
8063dec8614SKazutaka YOKOTA 	    break;
8073dec8614SKazutaka YOKOTA 	}
8083dec8614SKazutaka YOKOTA     } else {
8093dec8614SKazutaka YOKOTA 	adp->va_line_width = info->vi_width;
8103dec8614SKazutaka YOKOTA     }
8111c27745fSKazutaka YOKOTA     bcopy(info, &adp->va_info, sizeof(adp->va_info));
8121c27745fSKazutaka YOKOTA }
8131c27745fSKazutaka YOKOTA 
8148a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
8158a997770SDoug Rabson /* compare two parameter table entries */
8168a997770SDoug Rabson static int
8178a997770SDoug Rabson comp_adpregs(u_char *buf1, u_char *buf2)
8188a997770SDoug Rabson {
8198a997770SDoug Rabson     static struct {
8208a997770SDoug Rabson         u_char mask;
8218a997770SDoug Rabson     } params[V_MODE_PARAM_SIZE] = {
82205170bddSPeter Wemm 	{0xff}, {0x00}, {0xff}, 		/* COLS, ROWS, POINTS */
82305170bddSPeter Wemm 	{0x00}, {0x00}, 			/* page length */
82405170bddSPeter Wemm 	{0xfe}, {0xff}, {0xff}, {0xff},		/* sequencer registers */
82505170bddSPeter Wemm 	{0xf3},					/* misc register */
82605170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0x7f}, {0xff},	/* CRTC */
82705170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0x7f}, {0xff},
82805170bddSPeter Wemm 	{0x00}, {0x00}, {0x00}, {0x00}, {0x00},
82905170bddSPeter Wemm 	{0x00}, {0xff}, {0x7f}, {0xff}, {0xff},
83005170bddSPeter Wemm 	{0x7f}, {0xff}, {0xff}, {0xef}, {0xff},
83105170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0xff}, {0xff},	/* attribute controller regs */
83205170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0xff}, {0xff},
83305170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0xff}, {0xff},
83405170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0xff}, {0xf0},
83505170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0xff}, {0xff},	/* GDC register */
83605170bddSPeter Wemm 	{0xff}, {0xff}, {0xff}, {0xff},
8378a997770SDoug Rabson     };
8388a997770SDoug Rabson     int identical = TRUE;
8398a997770SDoug Rabson     int i;
8408a997770SDoug Rabson 
8418a997770SDoug Rabson     if ((buf1 == NULL) || (buf2 == NULL))
8428a997770SDoug Rabson 	return COMP_DIFFERENT;
8438a997770SDoug Rabson 
8448a997770SDoug Rabson     for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) {
8458a997770SDoug Rabson 	if (params[i].mask == 0)	/* don't care */
8468a997770SDoug Rabson 	    continue;
8478a997770SDoug Rabson 	if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask))
8488a997770SDoug Rabson 	    return COMP_DIFFERENT;
8498a997770SDoug Rabson 	if (buf1[i] != buf2[i])
8508a997770SDoug Rabson 	    identical = FALSE;
8518a997770SDoug Rabson     }
8528a997770SDoug Rabson     return (identical) ? COMP_IDENTICAL : COMP_SIMILAR;
8538a997770SDoug Rabson }
8548a997770SDoug Rabson #endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */
8558a997770SDoug Rabson 
8568a997770SDoug Rabson /* probe video adapters and return the number of detected adapters */
8578a997770SDoug Rabson static int
8588a997770SDoug Rabson probe_adapters(void)
8598a997770SDoug Rabson {
8608a997770SDoug Rabson     video_adapter_t *adp;
8618a997770SDoug Rabson     video_info_t info;
8628a997770SDoug Rabson     int i;
8638a997770SDoug Rabson 
8648a997770SDoug Rabson     /* do this test only once */
8658a997770SDoug Rabson     if (init_done)
8668a997770SDoug Rabson 	return biosadapters;
8678a997770SDoug Rabson     init_done = TRUE;
8688a997770SDoug Rabson 
8698a997770SDoug Rabson     /*
8708a997770SDoug Rabson      * Locate display adapters.
8718a997770SDoug Rabson      * The AT architecture supports upto two adapters. `syscons' allows
8728a997770SDoug Rabson      * the following combinations of adapters:
8738a997770SDoug Rabson      *     1) MDA + CGA
8748a997770SDoug Rabson      *     2) MDA + EGA/VGA color
8758a997770SDoug Rabson      *     3) CGA + EGA/VGA mono
8768a997770SDoug Rabson      * Note that `syscons' doesn't bother with MCGA as it is only
8778a997770SDoug Rabson      * avaiable for low end PS/2 models which has 80286 or earlier CPUs,
8788a997770SDoug Rabson      * thus, they are not running FreeBSD!
8798a997770SDoug Rabson      * When there are two adapaters in the system, one becomes `primary'
8808a997770SDoug Rabson      * and the other `secondary'. The EGA adapter has a set of DIP
8818a997770SDoug Rabson      * switches on board for this information and the EGA BIOS copies
8828a997770SDoug Rabson      * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88).
8838a997770SDoug Rabson      * The VGA BIOS has more sophisticated mechanism and has this
8848a997770SDoug Rabson      * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains
8858a997770SDoug Rabson      * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH.
8868a997770SDoug Rabson      */
8878a997770SDoug Rabson 
8888a997770SDoug Rabson     /*
8898a997770SDoug Rabson      * Check rtc and BIOS data area.
8908a997770SDoug Rabson      * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead
8918a997770SDoug Rabson      * copy of RTC_EQUIPMENT.  Bits 4 and 5 of ETC_EQUIPMENT are
8928a997770SDoug Rabson      * zeros for EGA and VGA.  However, the EGA/VGA BIOS sets
8938a997770SDoug Rabson      * these bits in BIOSDATA_EQUIPMENT according to the monitor
8948a997770SDoug Rabson      * type detected.
8958a997770SDoug Rabson      */
8968a997770SDoug Rabson #ifndef VGA_NO_BIOS
8978a997770SDoug Rabson     switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) {	/* bit 4 and 5 */
8988a997770SDoug Rabson     case 0:
8998a997770SDoug Rabson 	/* EGA/VGA */
9008a997770SDoug Rabson 	fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f,
9018a997770SDoug Rabson 			   biosadapter);
9028a997770SDoug Rabson 	break;
9038a997770SDoug Rabson     case 1:
9048a997770SDoug Rabson 	/* CGA 40x25 */
9058a997770SDoug Rabson 	/* FIXME: switch to the 80x25 mode? XXX */
9068a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40];
9078a997770SDoug Rabson 	biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
9088a997770SDoug Rabson 	break;
9098a997770SDoug Rabson     case 2:
9108a997770SDoug Rabson 	/* CGA 80x25 */
9118a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80];
9128a997770SDoug Rabson 	biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
9138a997770SDoug Rabson 	break;
9148a997770SDoug Rabson     case 3:
9158a997770SDoug Rabson 	/* MDA */
9168a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO];
9178a997770SDoug Rabson 	biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80];
9188a997770SDoug Rabson 	break;
9198a997770SDoug Rabson     }
9208a997770SDoug Rabson #else
9218a997770SDoug Rabson     /* assume EGA/VGA? XXX */
9228a997770SDoug Rabson     biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80];
9238a997770SDoug Rabson     biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO];
9248a997770SDoug Rabson #endif /* VGA_NO_BIOS */
9258a997770SDoug Rabson 
9268a997770SDoug Rabson     biosadapters = 0;
9278a997770SDoug Rabson     if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) {
9288a997770SDoug Rabson 	++biosadapters;
9298a997770SDoug Rabson 	biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED;
9308a997770SDoug Rabson 	biosadapter[V_ADP_SECONDARY].va_mode =
9318a997770SDoug Rabson 	    biosadapter[V_ADP_SECONDARY].va_initial_mode =
9328a997770SDoug Rabson 	    map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type,
9338a997770SDoug Rabson 			      biosadapter[V_ADP_SECONDARY].va_flags
9348a997770SDoug Rabson 				  & V_ADP_COLOR,
9358a997770SDoug Rabson 			      biosadapter[V_ADP_SECONDARY].va_initial_bios_mode);
9368a997770SDoug Rabson     } else {
9378a997770SDoug Rabson 	biosadapter[V_ADP_SECONDARY].va_type = -1;
9388a997770SDoug Rabson     }
9398a997770SDoug Rabson     if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) {
9408a997770SDoug Rabson 	++biosadapters;
9418a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED;
9428a997770SDoug Rabson #ifndef VGA_NO_BIOS
9438a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY].va_initial_bios_mode =
9448a997770SDoug Rabson 	    readb(BIOS_PADDRTOVADDR(0x449));
9458a997770SDoug Rabson #else
9468a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3;	/* XXX */
9478a997770SDoug Rabson #endif
9488a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY].va_mode =
9498a997770SDoug Rabson 	    biosadapter[V_ADP_PRIMARY].va_initial_mode =
9508a997770SDoug Rabson 	    map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type,
9518a997770SDoug Rabson 			      biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR,
9528a997770SDoug Rabson 			      biosadapter[V_ADP_PRIMARY].va_initial_bios_mode);
9538a997770SDoug Rabson     } else {
9548a997770SDoug Rabson 	biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY];
9558a997770SDoug Rabson 	biosadapter[V_ADP_SECONDARY].va_type = -1;
9568a997770SDoug Rabson     }
9578a997770SDoug Rabson     if (biosadapters == 0)
9588a997770SDoug Rabson 	return biosadapters;
9598a997770SDoug Rabson     biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY;
9608a997770SDoug Rabson     biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY;
9618a997770SDoug Rabson 
9628a997770SDoug Rabson #if 0 /* we don't need these... */
9638a997770SDoug Rabson     fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...);
9648a997770SDoug Rabson     fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...);
9658a997770SDoug Rabson #endif
9668a997770SDoug Rabson 
9678a997770SDoug Rabson #if 0
9688a997770SDoug Rabson     /*
9698a997770SDoug Rabson      * We cannot have two video adapter of the same type; there must be
9708a997770SDoug Rabson      * only one of color or mono adapter, or one each of them.
9718a997770SDoug Rabson      */
9728a997770SDoug Rabson     if (biosadapters > 1) {
9738a997770SDoug Rabson 	if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags)
9748a997770SDoug Rabson 	      & V_ADP_COLOR))
9758a997770SDoug Rabson 	    /* we have two mono or color adapters!! */
9768a997770SDoug Rabson 	    return (biosadapters = 0);
9778a997770SDoug Rabson     }
9788a997770SDoug Rabson #endif
9798a997770SDoug Rabson 
9808a997770SDoug Rabson     /*
9818a997770SDoug Rabson      * Ensure a zero start address.  This is mainly to recover after
9828a997770SDoug Rabson      * switching from pcvt using userconfig().  The registers are w/o
9838a997770SDoug Rabson      * for old hardware so it's too hard to relocate the active screen
9848a997770SDoug Rabson      * memory.
9858a997770SDoug Rabson      * This must be done before vga_save_state() for VGA.
9868a997770SDoug Rabson      */
9878a997770SDoug Rabson     outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12);
9888a997770SDoug Rabson     outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
9898a997770SDoug Rabson     outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13);
9908a997770SDoug Rabson     outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0);
9918a997770SDoug Rabson 
9928a997770SDoug Rabson     /* the video mode parameter table in EGA/VGA BIOS */
9938a997770SDoug Rabson     /* NOTE: there can be only one EGA/VGA, wheather color or mono,
9948a997770SDoug Rabson      * recognized by the video BIOS.
9958a997770SDoug Rabson      */
9968a997770SDoug Rabson     if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) ||
9978a997770SDoug Rabson 	(biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) {
9988a997770SDoug Rabson 	adp = &biosadapter[V_ADP_PRIMARY];
9998a997770SDoug Rabson     } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) ||
10008a997770SDoug Rabson 	       (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) {
10018a997770SDoug Rabson 	adp = &biosadapter[V_ADP_SECONDARY];
10028a997770SDoug Rabson     } else {
10038a997770SDoug Rabson 	adp = NULL;
10048a997770SDoug Rabson     }
10058a997770SDoug Rabson     bzero(mode_map, sizeof(mode_map));
10068a997770SDoug Rabson     if (adp != NULL) {
10078a997770SDoug Rabson 	if (adp->va_type == KD_VGA) {
10088a997770SDoug Rabson 	    vga_save_state(adp, &adpstate, sizeof(adpstate));
10098a997770SDoug Rabson #if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
10108a997770SDoug Rabson 	    mode_map[adp->va_initial_mode] = adpstate.regs;
10118a997770SDoug Rabson 	    rows_offset = 1;
10128a997770SDoug Rabson #else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
10138a997770SDoug Rabson 	    if (video_mode_ptr == NULL) {
10148a997770SDoug Rabson 		mode_map[adp->va_initial_mode] = adpstate.regs;
10158a997770SDoug Rabson 		rows_offset = 1;
10168a997770SDoug Rabson 	    } else {
10178a997770SDoug Rabson 		/* discard the table if we are not familiar with it... */
10186182fdbdSPeter Wemm 		u_char *mp;
10198a997770SDoug Rabson 		map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1);
10208a997770SDoug Rabson 		mp = get_mode_param(adp->va_initial_mode);
10218a997770SDoug Rabson 		if (mp != NULL)
10228a997770SDoug Rabson 		    bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs));
10238a997770SDoug Rabson 		switch (comp_adpregs(adpstate.regs, mp)) {
10248a997770SDoug Rabson 		case COMP_IDENTICAL:
10258a997770SDoug Rabson 		    /*
10268a997770SDoug Rabson 		     * OK, this parameter table looks reasonably familiar
10278a997770SDoug Rabson 		     * to us...
10288a997770SDoug Rabson 		     */
10298a997770SDoug Rabson 		    /*
10308a997770SDoug Rabson 		     * This is a kludge for Toshiba DynaBook SS433
10318a997770SDoug Rabson 		     * whose BIOS video mode table entry has the actual #
10328a997770SDoug Rabson 		     * of rows at the offset 1; BIOSes from other
10338a997770SDoug Rabson 		     * manufacturers store the # of rows - 1 there. XXX
10348a997770SDoug Rabson 		     */
10358a997770SDoug Rabson 		    rows_offset = adpstate.regs[1] + 1 - mp[1];
10368a997770SDoug Rabson 		    break;
10378a997770SDoug Rabson 
10388a997770SDoug Rabson 		case COMP_SIMILAR:
10398a997770SDoug Rabson 		    /*
10408a997770SDoug Rabson 		     * Not exactly the same, but similar enough to be
10418a997770SDoug Rabson 		     * trusted. However, use the saved register values
10428a997770SDoug Rabson 		     * for the initial mode and other modes which are
10438a997770SDoug Rabson 		     * based on the initial mode.
10448a997770SDoug Rabson 		     */
10458a997770SDoug Rabson 		    mode_map[adp->va_initial_mode] = adpstate.regs;
10468a997770SDoug Rabson 		    rows_offset = adpstate.regs[1] + 1 - mp[1];
10478a997770SDoug Rabson 		    adpstate.regs[1] -= rows_offset - 1;
10488a997770SDoug Rabson 		    break;
10498a997770SDoug Rabson 
10508a997770SDoug Rabson 		case COMP_DIFFERENT:
10518a997770SDoug Rabson 		default:
10528a997770SDoug Rabson 		    /*
10538a997770SDoug Rabson 		     * Don't use the paramter table in BIOS. It doesn't
10548a997770SDoug Rabson 		     * look familiar to us. Video mode switching is allowed
10558a997770SDoug Rabson 		     * only if the new mode is the same as or based on
10568a997770SDoug Rabson 		     * the initial mode.
10578a997770SDoug Rabson 		     */
10588a997770SDoug Rabson 		    video_mode_ptr = NULL;
10598a997770SDoug Rabson 		    bzero(mode_map, sizeof(mode_map));
10608a997770SDoug Rabson 		    mode_map[adp->va_initial_mode] = adpstate.regs;
10618a997770SDoug Rabson 		    rows_offset = 1;
10628a997770SDoug Rabson 		    break;
10638a997770SDoug Rabson 		}
10648a997770SDoug Rabson 	    }
10658a997770SDoug Rabson #endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
10668a997770SDoug Rabson 
10678a997770SDoug Rabson #ifndef VGA_NO_MODE_CHANGE
10688a997770SDoug Rabson 	    adp->va_flags |= V_ADP_MODECHANGE;
10698a997770SDoug Rabson #endif
10708a997770SDoug Rabson #ifndef VGA_NO_FONT_LOADING
10718a997770SDoug Rabson 	    adp->va_flags |= V_ADP_FONT;
10728a997770SDoug Rabson #endif
10738a997770SDoug Rabson 	} else if (adp->va_type == KD_EGA) {
10748a997770SDoug Rabson #if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE)
10758a997770SDoug Rabson 	    rows_offset = 1;
10768a997770SDoug Rabson #else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
10778a997770SDoug Rabson 	    if (video_mode_ptr == NULL) {
10788a997770SDoug Rabson 		rows_offset = 1;
10798a997770SDoug Rabson 	    } else {
10806182fdbdSPeter Wemm 		u_char *mp;
10818a997770SDoug Rabson 		map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1);
10828a997770SDoug Rabson 		/* XXX how can one validate the EGA table... */
10838a997770SDoug Rabson 		mp = get_mode_param(adp->va_initial_mode);
10848a997770SDoug Rabson 		if (mp != NULL) {
10858a997770SDoug Rabson 		    adp->va_flags |= V_ADP_MODECHANGE;
10868a997770SDoug Rabson #ifndef VGA_NO_FONT_LOADING
10878a997770SDoug Rabson 		    adp->va_flags |= V_ADP_FONT;
10888a997770SDoug Rabson #endif
10898a997770SDoug Rabson 		    rows_offset = 1;
10908a997770SDoug Rabson 		} else {
10918a997770SDoug Rabson 		    /*
10928a997770SDoug Rabson 		     * This is serious. We will not be able to switch video
10938a997770SDoug Rabson 		     * modes at all...
10948a997770SDoug Rabson 		     */
10958a997770SDoug Rabson 		    video_mode_ptr = NULL;
10968a997770SDoug Rabson 		    bzero(mode_map, sizeof(mode_map));
10978a997770SDoug Rabson 		    rows_offset = 1;
10988a997770SDoug Rabson                 }
10998a997770SDoug Rabson 	    }
11008a997770SDoug Rabson #endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */
11018a997770SDoug Rabson 	}
11028a997770SDoug Rabson     }
11038a997770SDoug Rabson 
11048a997770SDoug Rabson     /* remove conflicting modes if we have more than one adapter */
11058a997770SDoug Rabson     if (biosadapters > 1) {
11068a997770SDoug Rabson 	for (i = 0; i < biosadapters; ++i) {
11078a997770SDoug Rabson 	    if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE))
11088a997770SDoug Rabson 		continue;
11098a997770SDoug Rabson 	    clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1,
11108a997770SDoug Rabson 			   (biosadapter[i].va_flags & V_ADP_COLOR) ?
11118a997770SDoug Rabson 			       V_INFO_COLOR : 0);
11128a997770SDoug Rabson 	    if ((biosadapter[i].va_type == KD_VGA)
11138a997770SDoug Rabson 		|| (biosadapter[i].va_type == KD_EGA)) {
11148a997770SDoug Rabson 		biosadapter[i].va_io_base =
11158a997770SDoug Rabson 		    (biosadapter[i].va_flags & V_ADP_COLOR) ?
11168a997770SDoug Rabson 			IO_VGA : IO_MDA;
11178a997770SDoug Rabson 		biosadapter[i].va_io_size = 32;
11188a997770SDoug Rabson 	    }
11198a997770SDoug Rabson 	}
11208a997770SDoug Rabson     }
11218a997770SDoug Rabson 
11228a997770SDoug Rabson     /* buffer address */
11238a997770SDoug Rabson     vga_get_info(&biosadapter[V_ADP_PRIMARY],
11248a997770SDoug Rabson 		 biosadapter[V_ADP_PRIMARY].va_initial_mode, &info);
11251c27745fSKazutaka YOKOTA     update_adapter_info(&biosadapter[V_ADP_PRIMARY], &info);
11268a997770SDoug Rabson 
11278a997770SDoug Rabson     if (biosadapters > 1) {
11288a997770SDoug Rabson 	vga_get_info(&biosadapter[V_ADP_SECONDARY],
11298a997770SDoug Rabson 		     biosadapter[V_ADP_SECONDARY].va_initial_mode, &info);
11301c27745fSKazutaka YOKOTA 	update_adapter_info(&biosadapter[V_ADP_SECONDARY], &info);
11318a997770SDoug Rabson     }
11328a997770SDoug Rabson 
11338a997770SDoug Rabson     /*
11348a997770SDoug Rabson      * XXX: we should verify the following values for the primary adapter...
11358a997770SDoug Rabson      * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463);
11368a997770SDoug Rabson      * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02)
11378a997770SDoug Rabson      *                     ? 0 : V_ADP_COLOR;
11388a997770SDoug Rabson      * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a);
11398a997770SDoug Rabson      * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484);
11408a997770SDoug Rabson      * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485);
11418a997770SDoug Rabson      * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c);
11428a997770SDoug Rabson      */
11438a997770SDoug Rabson 
11448a997770SDoug Rabson     return biosadapters;
11458a997770SDoug Rabson }
11468a997770SDoug Rabson 
11478a997770SDoug Rabson /* entry points */
11488a997770SDoug Rabson 
11498a997770SDoug Rabson static int
11508a997770SDoug Rabson vga_nop(void)
11518a997770SDoug Rabson {
11528a997770SDoug Rabson     return 0;
11538a997770SDoug Rabson }
11548a997770SDoug Rabson 
11558a997770SDoug Rabson static int
11568a997770SDoug Rabson vga_probe(int unit, video_adapter_t **adpp, void *arg, int flags)
11578a997770SDoug Rabson {
11588a997770SDoug Rabson     probe_adapters();
11598a997770SDoug Rabson     if (unit >= biosadapters)
11608a997770SDoug Rabson 	return ENXIO;
11618a997770SDoug Rabson 
11628a997770SDoug Rabson     *adpp = &biosadapter[unit];
11638a997770SDoug Rabson 
11648a997770SDoug Rabson     return 0;
11658a997770SDoug Rabson }
11668a997770SDoug Rabson 
11678a997770SDoug Rabson static int
11688a997770SDoug Rabson vga_init(int unit, video_adapter_t *adp, int flags)
11698a997770SDoug Rabson {
11708a997770SDoug Rabson     if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp))
11718a997770SDoug Rabson 	return ENXIO;
11728a997770SDoug Rabson 
11738a997770SDoug Rabson     if (!init_done(adp)) {
11748a997770SDoug Rabson 	/* nothing to do really... */
11758a997770SDoug Rabson 	adp->va_flags |= V_ADP_INITIALIZED;
11768a997770SDoug Rabson     }
11778a997770SDoug Rabson 
11788a997770SDoug Rabson     if (!config_done(adp)) {
11798a997770SDoug Rabson 	if (vid_register(adp) < 0)
11808a997770SDoug Rabson 		return ENXIO;
11818a997770SDoug Rabson 	adp->va_flags |= V_ADP_REGISTERED;
11828a997770SDoug Rabson     }
11838a997770SDoug Rabson     if (vga_sub_configure != NULL)
11848a997770SDoug Rabson 	(*vga_sub_configure)(0);
11858a997770SDoug Rabson 
11868a997770SDoug Rabson     return 0;
11878a997770SDoug Rabson }
11888a997770SDoug Rabson 
11898a997770SDoug Rabson /*
11908a997770SDoug Rabson  * get_info():
11918a997770SDoug Rabson  * Return the video_info structure of the requested video mode.
11928a997770SDoug Rabson  *
11938a997770SDoug Rabson  * all adapters
11948a997770SDoug Rabson  */
11958a997770SDoug Rabson static int
11968a997770SDoug Rabson vga_get_info(video_adapter_t *adp, int mode, video_info_t *info)
11978a997770SDoug Rabson {
11988a997770SDoug Rabson     int i;
11998a997770SDoug Rabson 
12008a997770SDoug Rabson     if (!init_done)
12018a997770SDoug Rabson 	return 1;
12028a997770SDoug Rabson 
12038a997770SDoug Rabson     mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode);
12048a997770SDoug Rabson #ifndef VGA_NO_MODE_CHANGE
12058a997770SDoug Rabson     if (adp->va_flags & V_ADP_MODECHANGE) {
12068a997770SDoug Rabson 	/*
12078a997770SDoug Rabson 	 * If the parameter table entry for this mode is not found,
12088a997770SDoug Rabson 	 * the mode is not supported...
12098a997770SDoug Rabson 	 */
12108a997770SDoug Rabson 	if (get_mode_param(mode) == NULL)
12118a997770SDoug Rabson 	    return 1;
12128a997770SDoug Rabson     } else
12138a997770SDoug Rabson #endif /* VGA_NO_MODE_CHANGE */
12148a997770SDoug Rabson     {
12158a997770SDoug Rabson 	/*
12168a997770SDoug Rabson 	 * Even if we don't support video mode switching on this adapter,
12178a997770SDoug Rabson 	 * the information on the initial (thus current) video mode
12188a997770SDoug Rabson 	 * should be made available.
12198a997770SDoug Rabson 	 */
12208a997770SDoug Rabson 	if (mode != adp->va_initial_mode)
12218a997770SDoug Rabson 	    return 1;
12228a997770SDoug Rabson     }
12238a997770SDoug Rabson 
12248a997770SDoug Rabson     for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
12258a997770SDoug Rabson 	if (bios_vmode[i].vi_mode == NA)
12268a997770SDoug Rabson 	    continue;
12278a997770SDoug Rabson 	if (mode == bios_vmode[i].vi_mode) {
12288a997770SDoug Rabson 	    *info = bios_vmode[i];
12298a997770SDoug Rabson 	    return 0;
12308a997770SDoug Rabson 	}
12318a997770SDoug Rabson     }
12328a997770SDoug Rabson     return 1;
12338a997770SDoug Rabson }
12348a997770SDoug Rabson 
12358a997770SDoug Rabson /*
12368a997770SDoug Rabson  * query_mode():
12378a997770SDoug Rabson  * Find a video mode matching the requested parameters.
12388a997770SDoug Rabson  * Fields filled with 0 are considered "don't care" fields and
12398a997770SDoug Rabson  * match any modes.
12408a997770SDoug Rabson  *
12418a997770SDoug Rabson  * all adapters
12428a997770SDoug Rabson  */
12438a997770SDoug Rabson static int
12448a997770SDoug Rabson vga_query_mode(video_adapter_t *adp, video_info_t *info)
12458a997770SDoug Rabson {
12468a997770SDoug Rabson     video_info_t buf;
12478a997770SDoug Rabson     int i;
12488a997770SDoug Rabson 
12498a997770SDoug Rabson     if (!init_done)
12508a997770SDoug Rabson 	return -1;
12518a997770SDoug Rabson 
12528a997770SDoug Rabson     for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
12538a997770SDoug Rabson 	if (bios_vmode[i].vi_mode == NA)
12548a997770SDoug Rabson 	    continue;
12558a997770SDoug Rabson 
12568a997770SDoug Rabson 	if ((info->vi_width != 0)
12578a997770SDoug Rabson 	    && (info->vi_width != bios_vmode[i].vi_width))
12588a997770SDoug Rabson 		continue;
12598a997770SDoug Rabson 	if ((info->vi_height != 0)
12608a997770SDoug Rabson 	    && (info->vi_height != bios_vmode[i].vi_height))
12618a997770SDoug Rabson 		continue;
12628a997770SDoug Rabson 	if ((info->vi_cwidth != 0)
12638a997770SDoug Rabson 	    && (info->vi_cwidth != bios_vmode[i].vi_cwidth))
12648a997770SDoug Rabson 		continue;
12658a997770SDoug Rabson 	if ((info->vi_cheight != 0)
12668a997770SDoug Rabson 	    && (info->vi_cheight != bios_vmode[i].vi_cheight))
12678a997770SDoug Rabson 		continue;
12688a997770SDoug Rabson 	if ((info->vi_depth != 0)
12698a997770SDoug Rabson 	    && (info->vi_depth != bios_vmode[i].vi_depth))
12708a997770SDoug Rabson 		continue;
12718a997770SDoug Rabson 	if ((info->vi_planes != 0)
12728a997770SDoug Rabson 	    && (info->vi_planes != bios_vmode[i].vi_planes))
12738a997770SDoug Rabson 		continue;
12748a997770SDoug Rabson 	/* XXX: should check pixel format, memory model */
12758a997770SDoug Rabson 	if ((info->vi_flags != 0)
12768a997770SDoug Rabson 	    && (info->vi_flags != bios_vmode[i].vi_flags))
12778a997770SDoug Rabson 		continue;
12788a997770SDoug Rabson 
12798a997770SDoug Rabson 	/* verify if this mode is supported on this adapter */
12808a997770SDoug Rabson 	if (vga_get_info(adp, bios_vmode[i].vi_mode, &buf))
12818a997770SDoug Rabson 		continue;
12828a997770SDoug Rabson 	return bios_vmode[i].vi_mode;
12838a997770SDoug Rabson     }
12848a997770SDoug Rabson     return -1;
12858a997770SDoug Rabson }
12868a997770SDoug Rabson 
12878a997770SDoug Rabson /*
12888a997770SDoug Rabson  * set_mode():
12898a997770SDoug Rabson  * Change the video mode.
12908a997770SDoug Rabson  *
12918a997770SDoug Rabson  * EGA/VGA
12928a997770SDoug Rabson  */
12938a997770SDoug Rabson static int
12948a997770SDoug Rabson vga_set_mode(video_adapter_t *adp, int mode)
12958a997770SDoug Rabson {
12968a997770SDoug Rabson #ifndef VGA_NO_MODE_CHANGE
12978a997770SDoug Rabson     video_info_t info;
12988a997770SDoug Rabson     adp_state_t params;
12998a997770SDoug Rabson 
13008a997770SDoug Rabson     prologue(adp, V_ADP_MODECHANGE, 1);
13018a997770SDoug Rabson 
13028a997770SDoug Rabson     mode = map_gen_mode_num(adp->va_type,
13038a997770SDoug Rabson 			    adp->va_flags & V_ADP_COLOR, mode);
13048a997770SDoug Rabson     if (vga_get_info(adp, mode, &info))
13058a997770SDoug Rabson 	return 1;
13068a997770SDoug Rabson     params.sig = V_STATE_SIG;
13078a997770SDoug Rabson     bcopy(get_mode_param(mode), params.regs, sizeof(params.regs));
13088a997770SDoug Rabson 
13098a997770SDoug Rabson     switch (mode) {
13108a997770SDoug Rabson     case M_VGA_C80x60: case M_VGA_M80x60:
13118a997770SDoug Rabson 	params.regs[2]  = 0x08;
13128a997770SDoug Rabson 	params.regs[19] = 0x47;
13138a997770SDoug Rabson 	goto special_480l;
13148a997770SDoug Rabson 
13158a997770SDoug Rabson     case M_VGA_C80x30: case M_VGA_M80x30:
13168a997770SDoug Rabson 	params.regs[19] = 0x4f;
13178a997770SDoug Rabson special_480l:
13188a997770SDoug Rabson 	params.regs[9] |= 0xc0;
13198a997770SDoug Rabson 	params.regs[16] = 0x08;
13208a997770SDoug Rabson 	params.regs[17] = 0x3e;
13218a997770SDoug Rabson 	params.regs[26] = 0xea;
13228a997770SDoug Rabson 	params.regs[28] = 0xdf;
13238a997770SDoug Rabson 	params.regs[31] = 0xe7;
13248a997770SDoug Rabson 	params.regs[32] = 0x04;
13258a997770SDoug Rabson 	goto setup_mode;
13268a997770SDoug Rabson 
13278a997770SDoug Rabson     case M_ENH_C80x43: case M_ENH_B80x43:
13288a997770SDoug Rabson 	params.regs[28] = 87;
13298a997770SDoug Rabson 	goto special_80x50;
13308a997770SDoug Rabson 
13318a997770SDoug Rabson     case M_VGA_C80x50: case M_VGA_M80x50:
13328a997770SDoug Rabson special_80x50:
13338a997770SDoug Rabson 	params.regs[2] = 8;
13348a997770SDoug Rabson 	params.regs[19] = 7;
13358a997770SDoug Rabson 	goto setup_mode;
13368a997770SDoug Rabson 
13378a997770SDoug Rabson     case M_VGA_C40x25: case M_VGA_C80x25:
13388a997770SDoug Rabson     case M_VGA_M80x25:
13398a997770SDoug Rabson     case M_B40x25:     case M_C40x25:
13408a997770SDoug Rabson     case M_B80x25:     case M_C80x25:
13418a997770SDoug Rabson     case M_ENH_B40x25: case M_ENH_C40x25:
13428a997770SDoug Rabson     case M_ENH_B80x25: case M_ENH_C80x25:
13438a997770SDoug Rabson     case M_EGAMONO80x25:
13448a997770SDoug Rabson 
13458a997770SDoug Rabson setup_mode:
13468a997770SDoug Rabson 	vga_load_state(adp, &params);
13478a997770SDoug Rabson 	break;
13488a997770SDoug Rabson 
13498a997770SDoug Rabson     case M_VGA_MODEX:
13508a997770SDoug Rabson 	/* "unchain" the VGA mode */
13518a997770SDoug Rabson 	params.regs[5-1+0x04] &= 0xf7;
13528a997770SDoug Rabson 	params.regs[5-1+0x04] |= 0x04;
13538a997770SDoug Rabson 	/* turn off doubleword mode */
13548a997770SDoug Rabson 	params.regs[10+0x14] &= 0xbf;
13558a997770SDoug Rabson 	/* turn off word adressing */
13568a997770SDoug Rabson 	params.regs[10+0x17] |= 0x40;
13578a997770SDoug Rabson 	/* set logical screen width */
13588a997770SDoug Rabson 	params.regs[10+0x13] = 80;
13598a997770SDoug Rabson 	/* set 240 lines */
13608a997770SDoug Rabson 	params.regs[10+0x11] = 0x2c;
13618a997770SDoug Rabson 	params.regs[10+0x06] = 0x0d;
13628a997770SDoug Rabson 	params.regs[10+0x07] = 0x3e;
13638a997770SDoug Rabson 	params.regs[10+0x10] = 0xea;
13648a997770SDoug Rabson 	params.regs[10+0x11] = 0xac;
13658a997770SDoug Rabson 	params.regs[10+0x12] = 0xdf;
13668a997770SDoug Rabson 	params.regs[10+0x15] = 0xe7;
13678a997770SDoug Rabson 	params.regs[10+0x16] = 0x06;
13688a997770SDoug Rabson 	/* set vertical sync polarity to reflect aspect ratio */
13698a997770SDoug Rabson 	params.regs[9] = 0xe3;
13708a997770SDoug Rabson 	goto setup_grmode;
13718a997770SDoug Rabson 
13728a997770SDoug Rabson     case M_BG320:     case M_CG320:     case M_BG640:
13738a997770SDoug Rabson     case M_CG320_D:   case M_CG640_E:
13748a997770SDoug Rabson     case M_CG640x350: case M_ENH_CG640:
13758a997770SDoug Rabson     case M_BG640x480: case M_CG640x480: case M_VGA_CG320:
13768a997770SDoug Rabson 
13778a997770SDoug Rabson setup_grmode:
13788a997770SDoug Rabson 	vga_load_state(adp, &params);
13798a997770SDoug Rabson 	break;
13808a997770SDoug Rabson 
13818a997770SDoug Rabson     default:
13828a997770SDoug Rabson 	return 1;
13838a997770SDoug Rabson     }
13848a997770SDoug Rabson 
13858a997770SDoug Rabson     adp->va_mode = mode;
13861c27745fSKazutaka YOKOTA     update_adapter_info(adp, &info);
13878a997770SDoug Rabson 
13888a997770SDoug Rabson     /* move hardware cursor out of the way */
13898a997770SDoug Rabson     (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1);
13908a997770SDoug Rabson 
13918a997770SDoug Rabson     return 0;
13928a997770SDoug Rabson #else /* VGA_NO_MODE_CHANGE */
13938a997770SDoug Rabson     return 1;
13948a997770SDoug Rabson #endif /* VGA_NO_MODE_CHANGE */
13958a997770SDoug Rabson }
13968a997770SDoug Rabson 
13978a997770SDoug Rabson #ifndef VGA_NO_FONT_LOADING
13988a997770SDoug Rabson 
13998a997770SDoug Rabson static void
14008a997770SDoug Rabson set_font_mode(video_adapter_t *adp, u_char *buf)
14018a997770SDoug Rabson {
14028a997770SDoug Rabson     u_char *mp;
14038a997770SDoug Rabson     int s;
14048a997770SDoug Rabson 
14058a997770SDoug Rabson     s = splhigh();
14068a997770SDoug Rabson 
14078a997770SDoug Rabson     /* save register values */
14088a997770SDoug Rabson     if (adp->va_type == KD_VGA) {
14098a997770SDoug Rabson 	outb(TSIDX, 0x02); buf[0] = inb(TSREG);
14108a997770SDoug Rabson 	outb(TSIDX, 0x04); buf[1] = inb(TSREG);
14118a997770SDoug Rabson 	outb(GDCIDX, 0x04); buf[2] = inb(GDCREG);
14128a997770SDoug Rabson 	outb(GDCIDX, 0x05); buf[3] = inb(GDCREG);
14138a997770SDoug Rabson 	outb(GDCIDX, 0x06); buf[4] = inb(GDCREG);
14148a997770SDoug Rabson 	inb(adp->va_crtc_addr + 6);
14158a997770SDoug Rabson 	outb(ATC, 0x10); buf[5] = inb(ATC + 1);
14168a997770SDoug Rabson     } else /* if (adp->va_type == KD_EGA) */ {
14178a997770SDoug Rabson 	/*
14188a997770SDoug Rabson 	 * EGA cannot be read; copy parameters from the mode parameter
14198a997770SDoug Rabson 	 * table.
14208a997770SDoug Rabson 	 */
14218a997770SDoug Rabson 	mp = get_mode_param(adp->va_mode);
14228a997770SDoug Rabson 	buf[0] = mp[5 + 0x02 - 1];
14238a997770SDoug Rabson 	buf[1] = mp[5 + 0x04 - 1];
14248a997770SDoug Rabson 	buf[2] = mp[55 + 0x04];
14258a997770SDoug Rabson 	buf[3] = mp[55 + 0x05];
14268a997770SDoug Rabson 	buf[4] = mp[55 + 0x06];
14278a997770SDoug Rabson 	buf[5] = mp[35 + 0x10];
14288a997770SDoug Rabson     }
14298a997770SDoug Rabson 
14308a997770SDoug Rabson     /* setup vga for loading fonts */
14318a997770SDoug Rabson     inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
14328a997770SDoug Rabson     outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01);
14338a997770SDoug Rabson     inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
14348a997770SDoug Rabson     outb(ATC, 0x20);				/* enable palette */
14358a997770SDoug Rabson 
14368a997770SDoug Rabson #if VGA_SLOW_IOACCESS
14378a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
14388a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x01);
14398a997770SDoug Rabson #endif
14408a997770SDoug Rabson     outb(TSIDX, 0x02); outb(TSREG, 0x04);
14418a997770SDoug Rabson     outb(TSIDX, 0x04); outb(TSREG, 0x07);
14428a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
14438a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x03);
14448a997770SDoug Rabson #endif
14458a997770SDoug Rabson     outb(GDCIDX, 0x04); outb(GDCREG, 0x02);
14468a997770SDoug Rabson     outb(GDCIDX, 0x05); outb(GDCREG, 0x00);
14478a997770SDoug Rabson     outb(GDCIDX, 0x06); outb(GDCREG, 0x04);
14488a997770SDoug Rabson #else /* VGA_SLOW_IOACCESS */
14498a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
14508a997770SDoug Rabson     outw(TSIDX, 0x0100);
14518a997770SDoug Rabson #endif
14528a997770SDoug Rabson     outw(TSIDX, 0x0402);
14538a997770SDoug Rabson     outw(TSIDX, 0x0704);
14548a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
14558a997770SDoug Rabson     outw(TSIDX, 0x0300);
14568a997770SDoug Rabson #endif
14578a997770SDoug Rabson     outw(GDCIDX, 0x0204);
14588a997770SDoug Rabson     outw(GDCIDX, 0x0005);
14598a997770SDoug Rabson     outw(GDCIDX, 0x0406);               /* addr = a0000, 64kb */
14608a997770SDoug Rabson #endif /* VGA_SLOW_IOACCESS */
14618a997770SDoug Rabson 
14628a997770SDoug Rabson     splx(s);
14638a997770SDoug Rabson }
14648a997770SDoug Rabson 
14658a997770SDoug Rabson static void
14668a997770SDoug Rabson set_normal_mode(video_adapter_t *adp, u_char *buf)
14678a997770SDoug Rabson {
14688a997770SDoug Rabson     int s;
14698a997770SDoug Rabson 
14708a997770SDoug Rabson     s = splhigh();
14718a997770SDoug Rabson 
14728a997770SDoug Rabson     /* setup vga for normal operation mode again */
14738a997770SDoug Rabson     inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
14748a997770SDoug Rabson     outb(ATC, 0x10); outb(ATC, buf[5]);
14758a997770SDoug Rabson     inb(adp->va_crtc_addr + 6);			/* reset flip-flop */
14768a997770SDoug Rabson     outb(ATC, 0x20);				/* enable palette */
14778a997770SDoug Rabson 
14788a997770SDoug Rabson #if VGA_SLOW_IOACCESS
14798a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
14808a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x01);
14818a997770SDoug Rabson #endif
14828a997770SDoug Rabson     outb(TSIDX, 0x02); outb(TSREG, buf[0]);
14838a997770SDoug Rabson     outb(TSIDX, 0x04); outb(TSREG, buf[1]);
14848a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
14858a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x03);
14868a997770SDoug Rabson #endif
14878a997770SDoug Rabson     outb(GDCIDX, 0x04); outb(GDCREG, buf[2]);
14888a997770SDoug Rabson     outb(GDCIDX, 0x05); outb(GDCREG, buf[3]);
14898a997770SDoug Rabson     if (adp->va_crtc_addr == MONO_CRTC) {
14908a997770SDoug Rabson 	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08);
14918a997770SDoug Rabson     } else {
14928a997770SDoug Rabson 	outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c);
14938a997770SDoug Rabson     }
14948a997770SDoug Rabson #else /* VGA_SLOW_IOACCESS */
14958a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
14968a997770SDoug Rabson     outw(TSIDX, 0x0100);
14978a997770SDoug Rabson #endif
14988a997770SDoug Rabson     outw(TSIDX, 0x0002 | (buf[0] << 8));
14998a997770SDoug Rabson     outw(TSIDX, 0x0004 | (buf[1] << 8));
15008a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
15018a997770SDoug Rabson     outw(TSIDX, 0x0300);
15028a997770SDoug Rabson #endif
15038a997770SDoug Rabson     outw(GDCIDX, 0x0004 | (buf[2] << 8));
15048a997770SDoug Rabson     outw(GDCIDX, 0x0005 | (buf[3] << 8));
15058a997770SDoug Rabson     if (adp->va_crtc_addr == MONO_CRTC)
15068a997770SDoug Rabson         outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8));
15078a997770SDoug Rabson     else
15088a997770SDoug Rabson         outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8));
15098a997770SDoug Rabson #endif /* VGA_SLOW_IOACCESS */
15108a997770SDoug Rabson 
15118a997770SDoug Rabson     splx(s);
15128a997770SDoug Rabson }
15138a997770SDoug Rabson 
15148a997770SDoug Rabson #endif /* VGA_NO_FONT_LOADING */
15158a997770SDoug Rabson 
15168a997770SDoug Rabson /*
15178a997770SDoug Rabson  * save_font():
15188a997770SDoug Rabson  * Read the font data in the requested font page from the video adapter.
15198a997770SDoug Rabson  *
15208a997770SDoug Rabson  * EGA/VGA
15218a997770SDoug Rabson  */
15228a997770SDoug Rabson static int
15238a997770SDoug Rabson vga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
15248a997770SDoug Rabson 	      int ch, int count)
15258a997770SDoug Rabson {
15268a997770SDoug Rabson #ifndef VGA_NO_FONT_LOADING
15278a997770SDoug Rabson     u_char buf[PARAM_BUFSIZE];
15288a997770SDoug Rabson     u_int32_t segment;
15298a997770SDoug Rabson     int c;
15308a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
15318a997770SDoug Rabson     int s;
15328a997770SDoug Rabson     u_char val = 0;
15338a997770SDoug Rabson #endif
15348a997770SDoug Rabson 
15358a997770SDoug Rabson     prologue(adp, V_ADP_FONT, 1);
15368a997770SDoug Rabson 
15378a997770SDoug Rabson     if (fontsize < 14) {
15388a997770SDoug Rabson 	/* FONT_8 */
15398a997770SDoug Rabson 	fontsize = 8;
15408a997770SDoug Rabson     } else if (fontsize >= 32) {
15418a997770SDoug Rabson 	fontsize = 32;
15428a997770SDoug Rabson     } else if (fontsize >= 16) {
15438a997770SDoug Rabson 	/* FONT_16 */
15448a997770SDoug Rabson 	fontsize = 16;
15458a997770SDoug Rabson     } else {
15468a997770SDoug Rabson 	/* FONT_14 */
15478a997770SDoug Rabson 	fontsize = 14;
15488a997770SDoug Rabson     }
15498a997770SDoug Rabson 
15508a997770SDoug Rabson     if (page < 0 || page >= 8)
15518a997770SDoug Rabson 	return 1;
15528a997770SDoug Rabson     segment = FONT_BUF + 0x4000*page;
15538a997770SDoug Rabson     if (page > 3)
15548a997770SDoug Rabson 	segment -= 0xe000;
15558a997770SDoug Rabson 
15568a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
15578a997770SDoug Rabson     if (adp->va_type == KD_VGA) {	/* what about EGA? XXX */
15588a997770SDoug Rabson 	s = splhigh();
15598a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x01);
15608a997770SDoug Rabson 	outb(TSIDX, 0x01); val = inb(TSREG);	/* disable screen */
15618a997770SDoug Rabson 	outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
15628a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x03);
15638a997770SDoug Rabson 	splx(s);
15648a997770SDoug Rabson     }
15658a997770SDoug Rabson #endif
15668a997770SDoug Rabson 
15678a997770SDoug Rabson     set_font_mode(adp, buf);
15688a997770SDoug Rabson     if (fontsize == 32) {
15698a997770SDoug Rabson 	bcopy_fromio(segment + ch*32, data, fontsize*count);
15708a997770SDoug Rabson     } else {
15718a997770SDoug Rabson 	for (c = ch; count > 0; ++c, --count) {
15728a997770SDoug Rabson 	    bcopy_fromio(segment + c*32, data, fontsize);
15738a997770SDoug Rabson 	    data += fontsize;
15748a997770SDoug Rabson 	}
15758a997770SDoug Rabson     }
15768a997770SDoug Rabson     set_normal_mode(adp, buf);
15778a997770SDoug Rabson 
15788a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
15798a997770SDoug Rabson     if (adp->va_type == KD_VGA) {
15808a997770SDoug Rabson 	s = splhigh();
15818a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x01);
15828a997770SDoug Rabson 	outb(TSIDX, 0x01); outb(TSREG, val & 0xdf);	/* enable screen */
15838a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x03);
15848a997770SDoug Rabson 	splx(s);
15858a997770SDoug Rabson     }
15868a997770SDoug Rabson #endif
15878a997770SDoug Rabson 
15888a997770SDoug Rabson     return 0;
15898a997770SDoug Rabson #else /* VGA_NO_FONT_LOADING */
15908a997770SDoug Rabson     return 1;
15918a997770SDoug Rabson #endif /* VGA_NO_FONT_LOADING */
15928a997770SDoug Rabson }
15938a997770SDoug Rabson 
15948a997770SDoug Rabson /*
15958a997770SDoug Rabson  * load_font():
15968a997770SDoug Rabson  * Set the font data in the requested font page.
15978a997770SDoug Rabson  * NOTE: it appears that some recent video adapters do not support
15988a997770SDoug Rabson  * the font page other than 0... XXX
15998a997770SDoug Rabson  *
16008a997770SDoug Rabson  * EGA/VGA
16018a997770SDoug Rabson  */
16028a997770SDoug Rabson static int
16038a997770SDoug Rabson vga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data,
16048a997770SDoug Rabson 	      int ch, int count)
16058a997770SDoug Rabson {
16068a997770SDoug Rabson #ifndef VGA_NO_FONT_LOADING
16078a997770SDoug Rabson     u_char buf[PARAM_BUFSIZE];
16088a997770SDoug Rabson     u_int32_t segment;
16098a997770SDoug Rabson     int c;
16108a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
16118a997770SDoug Rabson     int s;
16128a997770SDoug Rabson     u_char val = 0;
16138a997770SDoug Rabson #endif
16148a997770SDoug Rabson 
16158a997770SDoug Rabson     prologue(adp, V_ADP_FONT, 1);
16168a997770SDoug Rabson 
16178a997770SDoug Rabson     if (fontsize < 14) {
16188a997770SDoug Rabson 	/* FONT_8 */
16198a997770SDoug Rabson 	fontsize = 8;
16208a997770SDoug Rabson     } else if (fontsize >= 32) {
16218a997770SDoug Rabson 	fontsize = 32;
16228a997770SDoug Rabson     } else if (fontsize >= 16) {
16238a997770SDoug Rabson 	/* FONT_16 */
16248a997770SDoug Rabson 	fontsize = 16;
16258a997770SDoug Rabson     } else {
16268a997770SDoug Rabson 	/* FONT_14 */
16278a997770SDoug Rabson 	fontsize = 14;
16288a997770SDoug Rabson     }
16298a997770SDoug Rabson 
16308a997770SDoug Rabson     if (page < 0 || page >= 8)
16318a997770SDoug Rabson 	return 1;
16328a997770SDoug Rabson     segment = FONT_BUF + 0x4000*page;
16338a997770SDoug Rabson     if (page > 3)
16348a997770SDoug Rabson 	segment -= 0xe000;
16358a997770SDoug Rabson 
16368a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
16378a997770SDoug Rabson     if (adp->va_type == KD_VGA) {	/* what about EGA? XXX */
16388a997770SDoug Rabson 	s = splhigh();
16398a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x01);
16408a997770SDoug Rabson 	outb(TSIDX, 0x01); val = inb(TSREG);	/* disable screen */
16418a997770SDoug Rabson 	outb(TSIDX, 0x01); outb(TSREG, val | 0x20);
16428a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x03);
16438a997770SDoug Rabson 	splx(s);
16448a997770SDoug Rabson     }
16458a997770SDoug Rabson #endif
16468a997770SDoug Rabson 
16478a997770SDoug Rabson     set_font_mode(adp, buf);
16488a997770SDoug Rabson     if (fontsize == 32) {
16498a997770SDoug Rabson 	bcopy_toio(data, segment + ch*32, fontsize*count);
16508a997770SDoug Rabson     } else {
16518a997770SDoug Rabson 	for (c = ch; count > 0; ++c, --count) {
16528a997770SDoug Rabson 	    bcopy_toio(data, segment + c*32, fontsize);
16538a997770SDoug Rabson 	    data += fontsize;
16548a997770SDoug Rabson 	}
16558a997770SDoug Rabson     }
16568a997770SDoug Rabson     set_normal_mode(adp, buf);
16578a997770SDoug Rabson 
16588a997770SDoug Rabson #ifdef VGA_ALT_SEQACCESS
16598a997770SDoug Rabson     if (adp->va_type == KD_VGA) {
16608a997770SDoug Rabson 	s = splhigh();
16618a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x01);
16628a997770SDoug Rabson 	outb(TSIDX, 0x01); outb(TSREG, val & 0xdf);	/* enable screen */
16638a997770SDoug Rabson 	outb(TSIDX, 0x00); outb(TSREG, 0x03);
16648a997770SDoug Rabson 	splx(s);
16658a997770SDoug Rabson     }
16668a997770SDoug Rabson #endif
16678a997770SDoug Rabson 
16688a997770SDoug Rabson     return 0;
16698a997770SDoug Rabson #else /* VGA_NO_FONT_LOADING */
16708a997770SDoug Rabson     return 1;
16718a997770SDoug Rabson #endif /* VGA_NO_FONT_LOADING */
16728a997770SDoug Rabson }
16738a997770SDoug Rabson 
16748a997770SDoug Rabson /*
16758a997770SDoug Rabson  * show_font():
16768a997770SDoug Rabson  * Activate the requested font page.
16778a997770SDoug Rabson  * NOTE: it appears that some recent video adapters do not support
16788a997770SDoug Rabson  * the font page other than 0... XXX
16798a997770SDoug Rabson  *
16808a997770SDoug Rabson  * EGA/VGA
16818a997770SDoug Rabson  */
16828a997770SDoug Rabson static int
16838a997770SDoug Rabson vga_show_font(video_adapter_t *adp, int page)
16848a997770SDoug Rabson {
16858a997770SDoug Rabson #ifndef VGA_NO_FONT_LOADING
16868a997770SDoug Rabson     static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f };
16878a997770SDoug Rabson     int s;
16888a997770SDoug Rabson 
16898a997770SDoug Rabson     prologue(adp, V_ADP_FONT, 1);
16908a997770SDoug Rabson     if (page < 0 || page >= 8)
16918a997770SDoug Rabson 	return 1;
16928a997770SDoug Rabson 
16938a997770SDoug Rabson     s = splhigh();
16948a997770SDoug Rabson     outb(TSIDX, 0x03); outb(TSREG, cg[page]);
16958a997770SDoug Rabson     splx(s);
16968a997770SDoug Rabson 
16978a997770SDoug Rabson     return 0;
16988a997770SDoug Rabson #else /* VGA_NO_FONT_LOADING */
16998a997770SDoug Rabson     return 1;
17008a997770SDoug Rabson #endif /* VGA_NO_FONT_LOADING */
17018a997770SDoug Rabson }
17028a997770SDoug Rabson 
17038a997770SDoug Rabson /*
17048a997770SDoug Rabson  * save_palette():
17058a997770SDoug Rabson  * Read DAC values. The values have expressed in 8 bits.
17068a997770SDoug Rabson  *
17078a997770SDoug Rabson  * VGA
17088a997770SDoug Rabson  */
17098a997770SDoug Rabson static int
17108a997770SDoug Rabson vga_save_palette(video_adapter_t *adp, u_char *palette)
17118a997770SDoug Rabson {
17128a997770SDoug Rabson     int i;
17138a997770SDoug Rabson 
17148a997770SDoug Rabson     prologue(adp, V_ADP_PALETTE, 1);
17158a997770SDoug Rabson 
17168a997770SDoug Rabson     /*
17178a997770SDoug Rabson      * We store 8 bit values in the palette buffer, while the standard
17188a997770SDoug Rabson      * VGA has 6 bit DAC .
17198a997770SDoug Rabson      */
17208a997770SDoug Rabson     outb(PALRADR, 0x00);
17218a997770SDoug Rabson     for (i = 0; i < 256*3; ++i)
17228a997770SDoug Rabson 	palette[i] = inb(PALDATA) << 2;
17238a997770SDoug Rabson     inb(adp->va_crtc_addr + 6);	/* reset flip/flop */
17248a997770SDoug Rabson     return 0;
17258a997770SDoug Rabson }
17268a997770SDoug Rabson 
17278a997770SDoug Rabson /*
17288a997770SDoug Rabson  * load_palette():
17298a997770SDoug Rabson  * Set DAC values.
17308a997770SDoug Rabson  *
17318a997770SDoug Rabson  * VGA
17328a997770SDoug Rabson  */
17338a997770SDoug Rabson static int
17348a997770SDoug Rabson vga_load_palette(video_adapter_t *adp, u_char *palette)
17358a997770SDoug Rabson {
17368a997770SDoug Rabson     int i;
17378a997770SDoug Rabson 
17388a997770SDoug Rabson     prologue(adp, V_ADP_PALETTE, 1);
17398a997770SDoug Rabson 
17408a997770SDoug Rabson     outb(PIXMASK, 0xff);		/* no pixelmask */
17418a997770SDoug Rabson     outb(PALWADR, 0x00);
17428a997770SDoug Rabson     for (i = 0; i < 256*3; ++i)
17438a997770SDoug Rabson 	outb(PALDATA, palette[i] >> 2);
17448a997770SDoug Rabson     inb(adp->va_crtc_addr + 6);	/* reset flip/flop */
17458a997770SDoug Rabson     outb(ATC, 0x20);			/* enable palette */
17468a997770SDoug Rabson     return 0;
17478a997770SDoug Rabson }
17488a997770SDoug Rabson 
17498a997770SDoug Rabson /*
17508a997770SDoug Rabson  * set_border():
17518a997770SDoug Rabson  * Change the border color.
17528a997770SDoug Rabson  *
17538a997770SDoug Rabson  * CGA/EGA/VGA
17548a997770SDoug Rabson  */
17558a997770SDoug Rabson static int
17568a997770SDoug Rabson vga_set_border(video_adapter_t *adp, int color)
17578a997770SDoug Rabson {
17588a997770SDoug Rabson     prologue(adp, V_ADP_BORDER, 1);
17598a997770SDoug Rabson 
17608a997770SDoug Rabson     switch (adp->va_type) {
17618a997770SDoug Rabson     case KD_EGA:
17628a997770SDoug Rabson     case KD_VGA:
17638a997770SDoug Rabson 	inb(adp->va_crtc_addr + 6);	/* reset flip-flop */
17648a997770SDoug Rabson 	outb(ATC, 0x31); outb(ATC, color & 0xff);
17658a997770SDoug Rabson 	break;
17668a997770SDoug Rabson     case KD_CGA:
17678a997770SDoug Rabson 	outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */
17688a997770SDoug Rabson 	break;
17698a997770SDoug Rabson     case KD_MONO:
17708a997770SDoug Rabson     case KD_HERCULES:
17718a997770SDoug Rabson     default:
17728a997770SDoug Rabson 	break;
17738a997770SDoug Rabson     }
17748a997770SDoug Rabson     return 0;
17758a997770SDoug Rabson }
17768a997770SDoug Rabson 
17778a997770SDoug Rabson /*
17788a997770SDoug Rabson  * save_state():
17798a997770SDoug Rabson  * Read video register values.
17808a997770SDoug Rabson  * NOTE: this function only reads the standard EGA/VGA registers.
17818a997770SDoug Rabson  * any extra/extended registers of SVGA adapters are not saved.
17828a997770SDoug Rabson  *
17838a997770SDoug Rabson  * VGA
17848a997770SDoug Rabson  */
17858a997770SDoug Rabson static int
17868a997770SDoug Rabson vga_save_state(video_adapter_t *adp, void *p, size_t size)
17878a997770SDoug Rabson {
17888a997770SDoug Rabson     video_info_t info;
17898a997770SDoug Rabson     u_char *buf;
17908a997770SDoug Rabson     int crtc_addr;
17918a997770SDoug Rabson     int i, j;
17928a997770SDoug Rabson     int s;
17938a997770SDoug Rabson 
17948a997770SDoug Rabson     if (size == 0) {
17958a997770SDoug Rabson 	/* return the required buffer size */
17968a997770SDoug Rabson 	prologue(adp, V_ADP_STATESAVE, 0);
17978a997770SDoug Rabson 	return sizeof(adp_state_t);
17988a997770SDoug Rabson     } else {
17998a997770SDoug Rabson 	prologue(adp, V_ADP_STATESAVE, 1);
18008a997770SDoug Rabson 	if (size < sizeof(adp_state_t))
18018a997770SDoug Rabson 	    return 1;
18028a997770SDoug Rabson     }
18038a997770SDoug Rabson 
18048a997770SDoug Rabson     ((adp_state_t *)p)->sig = V_STATE_SIG;
18058a997770SDoug Rabson     buf = ((adp_state_t *)p)->regs;
18068a997770SDoug Rabson     bzero(buf, V_MODE_PARAM_SIZE);
18078a997770SDoug Rabson     crtc_addr = adp->va_crtc_addr;
18088a997770SDoug Rabson 
18098a997770SDoug Rabson     s = splhigh();
18108a997770SDoug Rabson 
18118a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x01);	/* stop sequencer */
18128a997770SDoug Rabson     for (i = 0, j = 5; i < 4; i++) {
18138a997770SDoug Rabson 	outb(TSIDX, i + 1);
18148a997770SDoug Rabson 	buf[j++]  =  inb(TSREG);
18158a997770SDoug Rabson     }
18168a997770SDoug Rabson     buf[9]  =  inb(MISC + 10);			/* dot-clock */
18178a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x03);	/* start sequencer */
18188a997770SDoug Rabson 
18198a997770SDoug Rabson     for (i = 0, j = 10; i < 25; i++) {		/* crtc */
18208a997770SDoug Rabson 	outb(crtc_addr, i);
18218a997770SDoug Rabson 	buf[j++]  =  inb(crtc_addr + 1);
18228a997770SDoug Rabson     }
18238a997770SDoug Rabson     for (i = 0, j = 35; i < 20; i++) {		/* attribute ctrl */
18248a997770SDoug Rabson         inb(crtc_addr + 6);			/* reset flip-flop */
18258a997770SDoug Rabson 	outb(ATC, i);
18268a997770SDoug Rabson 	buf[j++]  =  inb(ATC + 1);
18278a997770SDoug Rabson     }
18288a997770SDoug Rabson     for (i = 0, j = 55; i < 9; i++) {		/* graph data ctrl */
18298a997770SDoug Rabson 	outb(GDCIDX, i);
18308a997770SDoug Rabson 	buf[j++]  =  inb(GDCREG);
18318a997770SDoug Rabson     }
18328a997770SDoug Rabson     inb(crtc_addr + 6);				/* reset flip-flop */
18338a997770SDoug Rabson     outb(ATC, 0x20);				/* enable palette */
18348a997770SDoug Rabson 
18358a997770SDoug Rabson     splx(s);
18368a997770SDoug Rabson 
18378a997770SDoug Rabson #if 1
18388a997770SDoug Rabson     if (vga_get_info(adp, adp->va_mode, &info) == 0) {
18398a997770SDoug Rabson 	if (info.vi_flags & V_INFO_GRAPHICS) {
18408a997770SDoug Rabson 	    buf[0] = info.vi_width/info.vi_cwidth; /* COLS */
18418a997770SDoug Rabson 	    buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */
18428a997770SDoug Rabson 	} else {
18438a997770SDoug Rabson 	    buf[0] = info.vi_width;		/* COLS */
18448a997770SDoug Rabson 	    buf[1] = info.vi_height - 1;	/* ROWS */
18458a997770SDoug Rabson 	}
18468a997770SDoug Rabson 	buf[2] = info.vi_cheight;		/* POINTS */
18478a997770SDoug Rabson     } else {
18488a997770SDoug Rabson 	/* XXX: shouldn't be happening... */
18498a997770SDoug Rabson 	printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n",
18508a997770SDoug Rabson 	       adp->va_unit, adp->va_name);
18518a997770SDoug Rabson     }
18528a997770SDoug Rabson #else
18538a997770SDoug Rabson     buf[0] = readb(BIOS_PADDRTOVADDR(0x44a));	/* COLS */
18548a997770SDoug Rabson     buf[1] = readb(BIOS_PADDRTOVADDR(0x484));	/* ROWS */
18558a997770SDoug Rabson     buf[2] = readb(BIOS_PADDRTOVADDR(0x485));	/* POINTS */
18568a997770SDoug Rabson     buf[3] = readb(BIOS_PADDRTOVADDR(0x44c));
18578a997770SDoug Rabson     buf[4] = readb(BIOS_PADDRTOVADDR(0x44d));
18588a997770SDoug Rabson #endif
18598a997770SDoug Rabson 
18608a997770SDoug Rabson     return 0;
18618a997770SDoug Rabson }
18628a997770SDoug Rabson 
18638a997770SDoug Rabson /*
18648a997770SDoug Rabson  * load_state():
18658a997770SDoug Rabson  * Set video registers at once.
18668a997770SDoug Rabson  * NOTE: this function only updates the standard EGA/VGA registers.
18678a997770SDoug Rabson  * any extra/extended registers of SVGA adapters are not changed.
18688a997770SDoug Rabson  *
18698a997770SDoug Rabson  * EGA/VGA
18708a997770SDoug Rabson  */
18718a997770SDoug Rabson static int
18728a997770SDoug Rabson vga_load_state(video_adapter_t *adp, void *p)
18738a997770SDoug Rabson {
18748a997770SDoug Rabson     u_char *buf;
18758a997770SDoug Rabson     int crtc_addr;
18768a997770SDoug Rabson     int s;
18778a997770SDoug Rabson     int i;
18788a997770SDoug Rabson 
18798a997770SDoug Rabson     prologue(adp, V_ADP_STATELOAD, 1);
18808a997770SDoug Rabson     if (((adp_state_t *)p)->sig != V_STATE_SIG)
18818a997770SDoug Rabson 	return 1;
18828a997770SDoug Rabson 
18838a997770SDoug Rabson     buf = ((adp_state_t *)p)->regs;
18848a997770SDoug Rabson     crtc_addr = adp->va_crtc_addr;
18858a997770SDoug Rabson 
18868a997770SDoug Rabson     s = splhigh();
18878a997770SDoug Rabson 
18888a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x01);	/* stop sequencer */
18898a997770SDoug Rabson     for (i = 0; i < 4; ++i) {			/* program sequencer */
18908a997770SDoug Rabson 	outb(TSIDX, i + 1);
18918a997770SDoug Rabson 	outb(TSREG, buf[i + 5]);
18928a997770SDoug Rabson     }
18938a997770SDoug Rabson     outb(MISC, buf[9]);				/* set dot-clock */
18948a997770SDoug Rabson     outb(TSIDX, 0x00); outb(TSREG, 0x03);	/* start sequencer */
18958a997770SDoug Rabson     outb(crtc_addr, 0x11);
18968a997770SDoug Rabson     outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F);
18978a997770SDoug Rabson     for (i = 0; i < 25; ++i) {			/* program crtc */
18988a997770SDoug Rabson 	outb(crtc_addr, i);
18998a997770SDoug Rabson 	outb(crtc_addr + 1, buf[i + 10]);
19008a997770SDoug Rabson     }
19018a997770SDoug Rabson     inb(crtc_addr+6);				/* reset flip-flop */
19028a997770SDoug Rabson     for (i = 0; i < 20; ++i) {			/* program attribute ctrl */
19038a997770SDoug Rabson 	outb(ATC, i);
19048a997770SDoug Rabson 	outb(ATC, buf[i + 35]);
19058a997770SDoug Rabson     }
19068a997770SDoug Rabson     for (i = 0; i < 9; ++i) {			/* program graph data ctrl */
19078a997770SDoug Rabson 	outb(GDCIDX, i);
19088a997770SDoug Rabson 	outb(GDCREG, buf[i + 55]);
19098a997770SDoug Rabson     }
19108a997770SDoug Rabson     inb(crtc_addr + 6);				/* reset flip-flop */
19118a997770SDoug Rabson     outb(ATC, 0x20);				/* enable palette */
19128a997770SDoug Rabson 
19136e694ebbSPeter Wemm #if notyet /* a temporary workaround for kernel panic, XXX */
19148a997770SDoug Rabson #ifndef VGA_NO_BIOS
19158a997770SDoug Rabson     if (adp->va_unit == V_ADP_PRIMARY) {
19168a997770SDoug Rabson 	writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]);	/* COLS */
19178a997770SDoug Rabson 	writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */
19188a997770SDoug Rabson 	writeb(BIOS_PADDRTOVADDR(0x485), buf[2]);	/* POINTS */
19198a997770SDoug Rabson #if 0
19208a997770SDoug Rabson 	writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]);
19218a997770SDoug Rabson 	writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]);
19228a997770SDoug Rabson #endif
19238a997770SDoug Rabson     }
19248a997770SDoug Rabson #endif /* VGA_NO_BIOS */
19256e694ebbSPeter Wemm #endif /* notyet */
19268a997770SDoug Rabson 
19278a997770SDoug Rabson     splx(s);
19288a997770SDoug Rabson     return 0;
19298a997770SDoug Rabson }
19308a997770SDoug Rabson 
19318a997770SDoug Rabson /*
19328a997770SDoug Rabson  * set_origin():
19338a997770SDoug Rabson  * Change the origin (window mapping) of the banked frame buffer.
19348a997770SDoug Rabson  */
19358a997770SDoug Rabson static int
19368a997770SDoug Rabson vga_set_origin(video_adapter_t *adp, off_t offset)
19378a997770SDoug Rabson {
19388a997770SDoug Rabson     /*
19398a997770SDoug Rabson      * The standard video modes do not require window mapping;
19408a997770SDoug Rabson      * always return error.
19418a997770SDoug Rabson      */
19428a997770SDoug Rabson     return 1;
19438a997770SDoug Rabson }
19448a997770SDoug Rabson 
19458a997770SDoug Rabson /*
19468a997770SDoug Rabson  * read_hw_cursor():
19478a997770SDoug Rabson  * Read the position of the hardware text cursor.
19488a997770SDoug Rabson  *
19498a997770SDoug Rabson  * all adapters
19508a997770SDoug Rabson  */
19518a997770SDoug Rabson static int
19528a997770SDoug Rabson vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
19538a997770SDoug Rabson {
19548a997770SDoug Rabson     u_int16_t off;
19558a997770SDoug Rabson     int s;
19568a997770SDoug Rabson 
19578a997770SDoug Rabson     if (!init_done)
19588a997770SDoug Rabson 	return 1;
19598a997770SDoug Rabson 
19601c27745fSKazutaka YOKOTA     if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
19618a997770SDoug Rabson 	return 1;
19628a997770SDoug Rabson 
19638a997770SDoug Rabson     s = spltty();
19648a997770SDoug Rabson     outb(adp->va_crtc_addr, 14);
19658a997770SDoug Rabson     off = inb(adp->va_crtc_addr + 1);
19668a997770SDoug Rabson     outb(adp->va_crtc_addr, 15);
19678a997770SDoug Rabson     off = (off << 8) | inb(adp->va_crtc_addr + 1);
19688a997770SDoug Rabson     splx(s);
19698a997770SDoug Rabson 
19701c27745fSKazutaka YOKOTA     *row = off / adp->va_info.vi_width;
19711c27745fSKazutaka YOKOTA     *col = off % adp->va_info.vi_width;
19728a997770SDoug Rabson 
19738a997770SDoug Rabson     return 0;
19748a997770SDoug Rabson }
19758a997770SDoug Rabson 
19768a997770SDoug Rabson /*
19778a997770SDoug Rabson  * set_hw_cursor():
19788a997770SDoug Rabson  * Move the hardware text cursor.  If col and row are both -1,
19798a997770SDoug Rabson  * the cursor won't be shown.
19808a997770SDoug Rabson  *
19818a997770SDoug Rabson  * all adapters
19828a997770SDoug Rabson  */
19838a997770SDoug Rabson static int
19848a997770SDoug Rabson vga_set_hw_cursor(video_adapter_t *adp, int col, int row)
19858a997770SDoug Rabson {
19868a997770SDoug Rabson     u_int16_t off;
19878a997770SDoug Rabson     int s;
19888a997770SDoug Rabson 
19898a997770SDoug Rabson     if (!init_done)
19908a997770SDoug Rabson 	return 1;
19918a997770SDoug Rabson 
19928a997770SDoug Rabson     if ((col == -1) && (row == -1)) {
19938a997770SDoug Rabson 	off = -1;
19948a997770SDoug Rabson     } else {
19951c27745fSKazutaka YOKOTA 	if (adp->va_info.vi_flags & V_INFO_GRAPHICS)
19968a997770SDoug Rabson 	    return 1;
19971c27745fSKazutaka YOKOTA 	off = row*adp->va_info.vi_width + col;
19988a997770SDoug Rabson     }
19998a997770SDoug Rabson 
20008a997770SDoug Rabson     s = spltty();
20018a997770SDoug Rabson     outb(adp->va_crtc_addr, 14);
20028a997770SDoug Rabson     outb(adp->va_crtc_addr + 1, off >> 8);
20038a997770SDoug Rabson     outb(adp->va_crtc_addr, 15);
20048a997770SDoug Rabson     outb(adp->va_crtc_addr + 1, off & 0x00ff);
20058a997770SDoug Rabson     splx(s);
20068a997770SDoug Rabson 
20078a997770SDoug Rabson     return 0;
20088a997770SDoug Rabson }
20098a997770SDoug Rabson 
20108a997770SDoug Rabson /*
20118a997770SDoug Rabson  * set_hw_cursor_shape():
20128a997770SDoug Rabson  * Change the shape of the hardware text cursor. If the height is
20138a997770SDoug Rabson  * zero or negative, the cursor won't be shown.
20148a997770SDoug Rabson  *
20158a997770SDoug Rabson  * all adapters
20168a997770SDoug Rabson  */
20178a997770SDoug Rabson static int
20188a997770SDoug Rabson vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
20198a997770SDoug Rabson 			int celsize, int blink)
20208a997770SDoug Rabson {
20218a997770SDoug Rabson     int s;
20228a997770SDoug Rabson 
20238a997770SDoug Rabson     if (!init_done)
20248a997770SDoug Rabson 	return 1;
20258a997770SDoug Rabson 
20268a997770SDoug Rabson     s = spltty();
20278a997770SDoug Rabson     switch (adp->va_type) {
20288a997770SDoug Rabson     case KD_VGA:
20298a997770SDoug Rabson     case KD_CGA:
20308a997770SDoug Rabson     case KD_MONO:
20318a997770SDoug Rabson     case KD_HERCULES:
20328a997770SDoug Rabson     default:
20338a997770SDoug Rabson 	if (height <= 0) {
20348a997770SDoug Rabson 	    /* make the cursor invisible */
20358a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 10);
20368a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, 32);
20378a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 11);
20388a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, 0);
20398a997770SDoug Rabson 	} else {
20408a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 10);
20418a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, celsize - base - height);
20428a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 11);
20438a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, celsize - base - 1);
20448a997770SDoug Rabson 	}
20458a997770SDoug Rabson 	break;
20468a997770SDoug Rabson     case KD_EGA:
20478a997770SDoug Rabson 	if (height <= 0) {
20488a997770SDoug Rabson 	    /* make the cursor invisible */
20498a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 10);
20508a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, celsize);
20518a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 11);
20528a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, 0);
20538a997770SDoug Rabson 	} else {
20548a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 10);
20558a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, celsize - base - height);
20568a997770SDoug Rabson 	    outb(adp->va_crtc_addr, 11);
20578a997770SDoug Rabson 	    outb(adp->va_crtc_addr + 1, celsize - base);
20588a997770SDoug Rabson 	}
20598a997770SDoug Rabson 	break;
20608a997770SDoug Rabson     }
20618a997770SDoug Rabson     splx(s);
20628a997770SDoug Rabson 
20638a997770SDoug Rabson     return 0;
20648a997770SDoug Rabson }
20658a997770SDoug Rabson 
20668a997770SDoug Rabson /*
20678a997770SDoug Rabson  * mmap():
20688a997770SDoug Rabson  * Mmap frame buffer.
20698a997770SDoug Rabson  *
20708a997770SDoug Rabson  * all adapters
20718a997770SDoug Rabson  */
20728a997770SDoug Rabson static int
20738a997770SDoug Rabson vga_mmap(video_adapter_t *adp, vm_offset_t offset)
20748a997770SDoug Rabson {
20758a997770SDoug Rabson     if (offset > 0x20000 - PAGE_SIZE)
20768a997770SDoug Rabson 	return -1;
20778a997770SDoug Rabson #ifdef __i386__
20788a997770SDoug Rabson     return i386_btop((VIDEO_BUF_BASE + offset));
20798a997770SDoug Rabson #endif
20808a997770SDoug Rabson #ifdef __alpha__
20818a997770SDoug Rabson     return alpha_btop((VIDEO_BUF_BASE + offset));
20828a997770SDoug Rabson #endif
20838a997770SDoug Rabson }
20848a997770SDoug Rabson 
20858a997770SDoug Rabson static void
20868a997770SDoug Rabson dump_buffer(u_char *buf, size_t len)
20878a997770SDoug Rabson {
20888a997770SDoug Rabson     int i;
20898a997770SDoug Rabson 
20908a997770SDoug Rabson     for(i = 0; i < len;) {
20918a997770SDoug Rabson 	printf("%02x ", buf[i]);
20928a997770SDoug Rabson 	if ((++i % 16) == 0)
20938a997770SDoug Rabson 	    printf("\n");
20948a997770SDoug Rabson     }
20958a997770SDoug Rabson }
20968a997770SDoug Rabson 
20978a997770SDoug Rabson /*
20988a997770SDoug Rabson  * diag():
20998a997770SDoug Rabson  * Print some information about the video adapter and video modes,
21008a997770SDoug Rabson  * with requested level of details.
21018a997770SDoug Rabson  *
21028a997770SDoug Rabson  * all adapters
21038a997770SDoug Rabson  */
21048a997770SDoug Rabson static int
21058a997770SDoug Rabson vga_diag(video_adapter_t *adp, int level)
21068a997770SDoug Rabson {
21078a997770SDoug Rabson #if FB_DEBUG > 1
21088a997770SDoug Rabson     video_info_t info;
21098a997770SDoug Rabson #endif
21108a997770SDoug Rabson     u_char *mp;
21118a997770SDoug Rabson 
21128a997770SDoug Rabson     if (!init_done)
21138a997770SDoug Rabson 	return 1;
21148a997770SDoug Rabson 
21158a997770SDoug Rabson #if FB_DEBUG > 1
21168a997770SDoug Rabson #ifndef VGA_NO_BIOS
21178a997770SDoug Rabson     printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n",
21188a997770SDoug Rabson 	   rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488)));
21198a997770SDoug Rabson     printf("vga: CRTC:0x%x, video option:0x%02x, ",
21208a997770SDoug Rabson 	   readw(BIOS_PADDRTOVADDR(0x463)),
21218a997770SDoug Rabson 	   readb(BIOS_PADDRTOVADDR(0x487)));
21228a997770SDoug Rabson     printf("rows:%d, cols:%d, font height:%d\n",
21238a997770SDoug Rabson 	   readb(BIOS_PADDRTOVADDR(0x44a)),
21248a997770SDoug Rabson 	   readb(BIOS_PADDRTOVADDR(0x484)) + 1,
21258a997770SDoug Rabson 	   readb(BIOS_PADDRTOVADDR(0x485)));
21268a997770SDoug Rabson #endif /* VGA_NO_BIOS */
21276e694ebbSPeter Wemm #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
21288a997770SDoug Rabson     printf("vga: param table EGA/VGA:%p", video_mode_ptr);
21298a997770SDoug Rabson     printf(", CGA/MDA:%p\n", video_mode_ptr2);
21306e694ebbSPeter Wemm #endif
21318a997770SDoug Rabson     printf("vga: rows_offset:%d\n", rows_offset);
21328a997770SDoug Rabson #endif /* FB_DEBUG > 1 */
21338a997770SDoug Rabson 
21348a997770SDoug Rabson     fb_dump_adp_info(DRIVER_NAME, adp, level);
21358a997770SDoug Rabson 
21368a997770SDoug Rabson #if FB_DEBUG > 1
21378a997770SDoug Rabson     if (adp->va_flags & V_ADP_MODECHANGE) {
21388a997770SDoug Rabson 	for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) {
21398a997770SDoug Rabson 	    if (bios_vmode[i].vi_mode == NA)
21408a997770SDoug Rabson 		continue;
21418a997770SDoug Rabson 	    if (get_mode_param(bios_vmode[i].vi_mode) == NULL)
21428a997770SDoug Rabson 		continue;
21438a997770SDoug Rabson 	    fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level);
21448a997770SDoug Rabson 	}
21458a997770SDoug Rabson     } else {
21468a997770SDoug Rabson 	vga_get_info(adp, adp->va_initial_mode, &info);	/* shouldn't fail */
21478a997770SDoug Rabson 	fb_dump_mode_info(DRIVER_NAME, adp, &info, level);
21488a997770SDoug Rabson     }
21498a997770SDoug Rabson #endif /* FB_DEBUG > 1 */
21508a997770SDoug Rabson 
21518a997770SDoug Rabson     if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA))
21528a997770SDoug Rabson 	return 0;
21538a997770SDoug Rabson #if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)
21548a997770SDoug Rabson     if (video_mode_ptr == NULL)
21558a997770SDoug Rabson 	printf("vga%d: %s: WARNING: video mode switching is not "
21568a997770SDoug Rabson 	       "fully supported on this adapter\n",
21578a997770SDoug Rabson 	       adp->va_unit, adp->va_name);
21588a997770SDoug Rabson #endif
21598a997770SDoug Rabson     if (level <= 0)
21608a997770SDoug Rabson 	return 0;
21618a997770SDoug Rabson 
21628a997770SDoug Rabson     if (adp->va_type == KD_VGA) {
21638a997770SDoug Rabson 	printf("VGA parameters upon power-up\n");
21648a997770SDoug Rabson 	dump_buffer(adpstate.regs, sizeof(adpstate.regs));
21658a997770SDoug Rabson 	printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode);
21668a997770SDoug Rabson 	dump_buffer(adpstate2.regs, sizeof(adpstate2.regs));
21678a997770SDoug Rabson     }
21688a997770SDoug Rabson 
21698a997770SDoug Rabson     mp = get_mode_param(adp->va_initial_mode);
21708a997770SDoug Rabson     if (mp == NULL)	/* this shouldn't be happening */
21718a997770SDoug Rabson 	return 0;
21728a997770SDoug Rabson     printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode);
21738a997770SDoug Rabson     dump_buffer(mp, V_MODE_PARAM_SIZE);
21748a997770SDoug Rabson 
21758a997770SDoug Rabson     return 0;
21768a997770SDoug Rabson }
21778a997770SDoug Rabson 
21788a997770SDoug Rabson #endif /* NVGA > 0 */
2179