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, ¶ms); 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, ¶ms); 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