vga_isa.c revision 43105
143105Sdfr/*- 243105Sdfr * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 343105Sdfr * Copyright (c) 1992-1998 S�ren Schmidt 443105Sdfr * All rights reserved. 543105Sdfr * 643105Sdfr * Redistribution and use in source and binary forms, with or without 743105Sdfr * modification, are permitted provided that the following conditions 843105Sdfr * are met: 943105Sdfr * 1. Redistributions of source code must retain the above copyright 1043105Sdfr * notice, this list of conditions and the following disclaimer as 1143105Sdfr * the first lines of this file unmodified. 1243105Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1343105Sdfr * notice, this list of conditions and the following disclaimer in the 1443105Sdfr * documentation and/or other materials provided with the distribution. 1543105Sdfr * 3. The name of the author may not be used to endorse or promote products 1643105Sdfr * derived from this software without specific prior written permission. 1743105Sdfr * 1843105Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1943105Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2043105Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2143105Sdfr * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2243105Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2343105Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2443105Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2543105Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2643105Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2743105Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2843105Sdfr * 2943105Sdfr * $Id: vga_isa.c,v 1.1 1999/01/09 02:44:41 yokota Exp $ 3043105Sdfr */ 3143105Sdfr 3243105Sdfr#include "vga.h" 3343105Sdfr#include "opt_vga.h" 3443105Sdfr#include "opt_fb.h" 3543105Sdfr#include "opt_syscons.h" /* should be removed in the future, XXX */ 3643105Sdfr 3743105Sdfr#if NVGA > 0 3843105Sdfr 3943105Sdfr#include <sys/param.h> 4043105Sdfr#include <sys/systm.h> 4143105Sdfr#include <sys/kernel.h> 4243105Sdfr#include <sys/bus.h> 4343105Sdfr#include <sys/malloc.h> 4443105Sdfr 4543105Sdfr#include <vm/vm.h> 4643105Sdfr#include <vm/pmap.h> 4743105Sdfr 4843105Sdfr#include <machine/console.h> 4943105Sdfr#include <machine/md_var.h> 5043105Sdfr#include <machine/pc/bios.h> 5143105Sdfr 5243105Sdfr#include <dev/fb/fbreg.h> 5343105Sdfr#include <dev/fb/vgareg.h> 5443105Sdfr 5543105Sdfr#ifndef __i386__ 5643105Sdfr#include <isa/isareg.h> 5743105Sdfr#include <isa/isavar.h> 5843105Sdfr#else 5943105Sdfr#include <i386/isa/isa.h> 6043105Sdfr#include <i386/isa/isa_device.h> 6143105Sdfr#endif 6243105Sdfr 6343105Sdfr#define DRIVER_NAME "vga" 6443105Sdfr 6543105Sdfr/* cdev driver declaration */ 6643105Sdfr 6743105Sdfr#define ISAVGA_UNIT(dev) minor(dev) 6843105Sdfr#define ISAVGA_MKMINOR(unit) (unit) 6943105Sdfr 7043105Sdfrtypedef struct isavga_softc { 7143105Sdfr video_adapter_t *adp; 7243105Sdfr} isavga_softc_t; 7343105Sdfr 7443105Sdfr#ifndef __i386__ 7543105Sdfr 7643105Sdfr#define ISAVGA_SOFTC(unit) \ 7743105Sdfr ((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit)) 7843105Sdfr 7943105Sdfrdevclass_t isavga_devclass; 8043105Sdfr 8143105Sdfrstatic int isavga_probe(device_t dev); 8243105Sdfrstatic int isavga_attach(device_t dev); 8343105Sdfr 8443105Sdfrstatic device_method_t isavga_methods[] = { 8543105Sdfr DEVMETHOD(device_probe, isavga_probe), 8643105Sdfr DEVMETHOD(device_attach, isavga_attach), 8743105Sdfr { 0, 0 } 8843105Sdfr}; 8943105Sdfr 9043105Sdfrstatic driver_t isavga_driver = { 9143105Sdfr DRIVER_NAME, 9243105Sdfr isavga_methods, 9343105Sdfr DRIVER_TYPE_TTY, 9443105Sdfr sizeof(isavga_softc_t), 9543105Sdfr}; 9643105Sdfr 9743105SdfrDRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0); 9843105Sdfr 9943105Sdfr#else /* __i386__ */ 10043105Sdfr 10143105Sdfr#define ISAVGA_SOFTC(unit) (isavga_softc[unit]) 10243105Sdfr 10343105Sdfrstatic isavga_softc_t *isavga_softc[NVGA]; 10443105Sdfr 10543105Sdfrstatic int isavga_probe(struct isa_device *dev); 10643105Sdfrstatic int isavga_attach(struct isa_device *dev); 10743105Sdfr 10843105Sdfrstruct isa_driver vgadriver = { 10943105Sdfr isavga_probe, 11043105Sdfr isavga_attach, 11143105Sdfr DRIVER_NAME, 11243105Sdfr 0, 11343105Sdfr}; 11443105Sdfr 11543105Sdfr#endif /* __i386__ */ 11643105Sdfr 11743105Sdfrstatic int isavga_probe_unit(int unit, isavga_softc_t *sc, 11843105Sdfr int flags); 11943105Sdfrstatic int isavga_attach_unit(int unit, isavga_softc_t *sc, 12043105Sdfr int flags); 12143105Sdfr 12243105Sdfr#ifdef FB_INSTALL_CDEV 12343105Sdfr 12443105Sdfrstatic d_open_t isavgaopen; 12543105Sdfrstatic d_close_t isavgaclose; 12643105Sdfrstatic d_read_t isavgaread; 12743105Sdfrstatic d_ioctl_t isavgaioctl; 12843105Sdfr 12943105Sdfrstatic struct cdevsw vga_cdevsw = { 13043105Sdfr isavgaopen, isavgaclose, noread, nowrite, /* ?? */ 13143105Sdfr isavgaioctl, nostop, nullreset, nodevtotty, 13243105Sdfr seltrue, nommap, NULL, DRIVER_NAME, 13343105Sdfr NULL, -1, nodump, nopsize, 13443105Sdfr}; 13543105Sdfr 13643105Sdfr#endif /* FB_INSTALL_CDEV */ 13743105Sdfr 13843105Sdfr#ifndef __i386__ 13943105Sdfr 14043105Sdfrstatic int 14143105Sdfrisavga_probe(device_t dev) 14243105Sdfr{ 14343105Sdfr isavga_softc_t *sc; 14443105Sdfr 14543105Sdfr device_set_desc(dev, "Generic ISA VGA"); 14643105Sdfr sc = device_get_softc(dev); 14743105Sdfr return isavga_probe_unit(device_get_unit(dev), sc, isa_get_flags(dev)); 14843105Sdfr} 14943105Sdfr 15043105Sdfrstatic int 15143105Sdfrisavga_attach(device_t dev) 15243105Sdfr{ 15343105Sdfr isavga_softc_t *sc; 15443105Sdfr 15543105Sdfr sc = device_get_softc(dev); 15643105Sdfr return isavga_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev)); 15743105Sdfr} 15843105Sdfr 15943105Sdfr#else /* __i386__ */ 16043105Sdfr 16143105Sdfrstatic int 16243105Sdfrisavga_probe(struct isa_device *dev) 16343105Sdfr{ 16443105Sdfr isavga_softc_t *sc; 16543105Sdfr int error; 16643105Sdfr 16743105Sdfr if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) 16843105Sdfr return 0; 16943105Sdfr sc = isavga_softc[dev->id_unit] 17043105Sdfr = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); 17143105Sdfr if (sc == NULL) 17243105Sdfr return 0; 17343105Sdfr 17443105Sdfr error = isavga_probe_unit(dev->id_unit, sc, dev->id_flags); 17543105Sdfr if (error) { 17643105Sdfr isavga_softc[dev->id_unit] = NULL; 17743105Sdfr free(sc, M_DEVBUF); 17843105Sdfr return 0; 17943105Sdfr } 18043105Sdfr 18143105Sdfr dev->id_iobase = sc->adp->va_io_base; 18243105Sdfr dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base); 18343105Sdfr dev->id_msize = sc->adp->va_mem_size; 18443105Sdfr 18543105Sdfr return sc->adp->va_io_size; 18643105Sdfr} 18743105Sdfr 18843105Sdfrstatic int 18943105Sdfrisavga_attach(struct isa_device *dev) 19043105Sdfr{ 19143105Sdfr isavga_softc_t *sc; 19243105Sdfr 19343105Sdfr if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) 19443105Sdfr return 0; 19543105Sdfr sc = isavga_softc[dev->id_unit]; 19643105Sdfr if (sc == NULL) 19743105Sdfr return 0; 19843105Sdfr 19943105Sdfr return ((isavga_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1); 20043105Sdfr} 20143105Sdfr 20243105Sdfr#endif /* __i386__ */ 20343105Sdfr 20443105Sdfrstatic int 20543105Sdfrisavga_probe_unit(int unit, isavga_softc_t *sc, int flags) 20643105Sdfr{ 20743105Sdfr video_switch_t *sw; 20843105Sdfr 20943105Sdfr bzero(sc, sizeof(*sc)); 21043105Sdfr sw = vid_get_switch(DRIVER_NAME); 21143105Sdfr if (sw == NULL) 21243105Sdfr return 0; 21343105Sdfr return (*sw->probe)(unit, &sc->adp, NULL, flags); 21443105Sdfr} 21543105Sdfr 21643105Sdfrstatic int 21743105Sdfrisavga_attach_unit(int unit, isavga_softc_t *sc, int flags) 21843105Sdfr{ 21943105Sdfr video_switch_t *sw; 22043105Sdfr int error; 22143105Sdfr 22243105Sdfr sw = vid_get_switch(DRIVER_NAME); 22343105Sdfr if (sw == NULL) 22443105Sdfr return ENXIO; 22543105Sdfr 22643105Sdfr error = (*sw->init)(unit, sc->adp, flags); 22743105Sdfr if (error) 22843105Sdfr return ENXIO; 22943105Sdfr 23043105Sdfr#ifdef FB_INSTALL_CDEV 23143105Sdfr /* attach a virtual frame buffer device */ 23243105Sdfr error = fb_attach(makedev(0, ISAVGA_MKMINOR(unit)), scp->adp, 23343105Sdfr &vga_cdevsw); 23443105Sdfr if (error) 23543105Sdfr return error; 23643105Sdfr#endif /* FB_INSTALL_CDEV */ 23743105Sdfr 23843105Sdfr if (bootverbose) 23943105Sdfr (*sw->diag)(sc->adp, bootverbose); 24043105Sdfr 24143105Sdfr return 0; 24243105Sdfr} 24343105Sdfr 24443105Sdfr/* LOW-LEVEL */ 24543105Sdfr 24643105Sdfr#include <machine/clock.h> 24743105Sdfr#include <machine/pc/vesa.h> 24843105Sdfr 24943105Sdfr#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED) 25043105Sdfr#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED) 25143105Sdfr#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED) 25243105Sdfr 25343105Sdfr/* for compatibility with old kernel options */ 25443105Sdfr#ifdef SC_ALT_SEQACCESS 25543105Sdfr#undef SC_ALT_SEQACCESS 25643105Sdfr#undef VGA_ALT_SEQACCESS 25743105Sdfr#define VGA_ALT_SEQACCESS 1 25843105Sdfr#endif 25943105Sdfr 26043105Sdfr#ifdef SLOW_VGA 26143105Sdfr#undef SLOW_VGA 26243105Sdfr#undef VGA_SLOW_IOACCESS 26343105Sdfr#define VGA_SLOW_IOACCESS 1 26443105Sdfr#endif 26543105Sdfr 26643105Sdfr/* architecture dependent option */ 26743105Sdfr#ifdef __alpha__ 26843105Sdfr#define VGA_NO_BIOS 1 26943105Sdfr#endif 27043105Sdfr 27143105Sdfr/* this should really be in `rtc.h' */ 27243105Sdfr#define RTC_EQUIPMENT 0x14 27343105Sdfr 27443105Sdfr/* various sizes */ 27543105Sdfr#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1) 27643105Sdfr#define V_MODE_PARAM_SIZE 64 27743105Sdfr 27843105Sdfr/* video adapter state buffer */ 27943105Sdfrstruct adp_state { 28043105Sdfr int sig; 28143105Sdfr#define V_STATE_SIG 0x736f6962 28243105Sdfr u_char regs[V_MODE_PARAM_SIZE]; 28343105Sdfr}; 28443105Sdfrtypedef struct adp_state adp_state_t; 28543105Sdfr 28643105Sdfr/* video adapter information */ 28743105Sdfr#define DCC_MONO 0 28843105Sdfr#define DCC_CGA40 1 28943105Sdfr#define DCC_CGA80 2 29043105Sdfr#define DCC_EGAMONO 3 29143105Sdfr#define DCC_EGA40 4 29243105Sdfr#define DCC_EGA80 5 29343105Sdfr 29443105Sdfr/* 29543105Sdfr * NOTE: `va_window' should have a virtual address, but is initialized 29643105Sdfr * with a physical address in the following table, as verify_adapter() 29743105Sdfr * will perform address conversion at run-time. 29843105Sdfr */ 29943105Sdfrstatic video_adapter_t adapter_init_value[] = { 30043105Sdfr /* DCC_MONO */ 30143105Sdfr { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC, 30243105Sdfr MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 30343105Sdfr 0, 0, 0, 7, 0, 0, NULL }, 30443105Sdfr /* DCC_CGA40 */ 30543105Sdfr { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, 30643105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 30743105Sdfr 0, 0, 0, 3, 0, 0, NULL }, 30843105Sdfr /* DCC_CGA80 */ 30943105Sdfr { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, 31043105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 31143105Sdfr 0, 0, 0, 3, 0, 0, NULL }, 31243105Sdfr /* DCC_EGAMONO */ 31343105Sdfr { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC, 31443105Sdfr EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 31543105Sdfr 0, 0, 0, 7, 0, 0, NULL }, 31643105Sdfr /* DCC_EGA40 */ 31743105Sdfr { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, 31843105Sdfr EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 31943105Sdfr 0, 0, 0, 3, 0, 0, NULL }, 32043105Sdfr /* DCC_EGA80 */ 32143105Sdfr { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, 32243105Sdfr EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 32343105Sdfr 0, 0, 0, 3, 0, 0, NULL }, 32443105Sdfr}; 32543105Sdfr 32643105Sdfrstatic video_adapter_t biosadapter[2]; 32743105Sdfrstatic int biosadapters = 0; 32843105Sdfr 32943105Sdfr/* video driver declarations */ 33043105Sdfrstatic int vga_configure(int flags); 33143105Sdfr int (*vga_sub_configure)(int flags); 33243105Sdfrstatic int vga_nop(void); 33343105Sdfrstatic vi_probe_t vga_probe; 33443105Sdfrstatic vi_init_t vga_init; 33543105Sdfrstatic vi_get_info_t vga_get_info; 33643105Sdfrstatic vi_query_mode_t vga_query_mode; 33743105Sdfrstatic vi_set_mode_t vga_set_mode; 33843105Sdfrstatic vi_save_font_t vga_save_font; 33943105Sdfrstatic vi_load_font_t vga_load_font; 34043105Sdfrstatic vi_show_font_t vga_show_font; 34143105Sdfrstatic vi_save_palette_t vga_save_palette; 34243105Sdfrstatic vi_load_palette_t vga_load_palette; 34343105Sdfrstatic vi_set_border_t vga_set_border; 34443105Sdfrstatic vi_save_state_t vga_save_state; 34543105Sdfrstatic vi_load_state_t vga_load_state; 34643105Sdfrstatic vi_set_win_org_t vga_set_origin; 34743105Sdfrstatic vi_read_hw_cursor_t vga_read_hw_cursor; 34843105Sdfrstatic vi_set_hw_cursor_t vga_set_hw_cursor; 34943105Sdfrstatic vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape; 35043105Sdfrstatic vi_mmap_t vga_mmap; 35143105Sdfrstatic vi_diag_t vga_diag; 35243105Sdfr 35343105Sdfrstatic video_switch_t vgavidsw = { 35443105Sdfr vga_probe, 35543105Sdfr vga_init, 35643105Sdfr vga_get_info, 35743105Sdfr vga_query_mode, 35843105Sdfr vga_set_mode, 35943105Sdfr vga_save_font, 36043105Sdfr vga_load_font, 36143105Sdfr vga_show_font, 36243105Sdfr vga_save_palette, 36343105Sdfr vga_load_palette, 36443105Sdfr vga_set_border, 36543105Sdfr vga_save_state, 36643105Sdfr vga_load_state, 36743105Sdfr vga_set_origin, 36843105Sdfr vga_read_hw_cursor, 36943105Sdfr vga_set_hw_cursor, 37043105Sdfr vga_set_hw_cursor_shape, 37143105Sdfr (vi_blank_display_t *)vga_nop, 37243105Sdfr vga_mmap, 37343105Sdfr vga_diag, 37443105Sdfr}; 37543105Sdfr 37643105SdfrVIDEO_DRIVER(mda, vgavidsw, NULL); 37743105SdfrVIDEO_DRIVER(cga, vgavidsw, NULL); 37843105SdfrVIDEO_DRIVER(ega, vgavidsw, NULL); 37943105SdfrVIDEO_DRIVER(vga, vgavidsw, vga_configure); 38043105Sdfr 38143105Sdfr/* VGA BIOS standard video modes */ 38243105Sdfr#define EOT (-1) 38343105Sdfr#define NA (-2) 38443105Sdfr 38543105Sdfrstatic video_info_t bios_vmode[] = { 38643105Sdfr /* CGA */ 38743105Sdfr { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1, 38843105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 38943105Sdfr { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1, 39043105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 39143105Sdfr { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1, 39243105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 39343105Sdfr { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1, 39443105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 39543105Sdfr /* EGA */ 39643105Sdfr { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, 39743105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 39843105Sdfr { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, 39943105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 40043105Sdfr { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, 40143105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 40243105Sdfr { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, 40343105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 40443105Sdfr /* VGA */ 40543105Sdfr { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, 40643105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 40743105Sdfr { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1, 40843105Sdfr MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 40943105Sdfr { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, 41043105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 41143105Sdfr /* MDA */ 41243105Sdfr { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1, 41343105Sdfr MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 41443105Sdfr /* EGA */ 41543105Sdfr { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1, 41643105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 41743105Sdfr { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1, 41843105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 41943105Sdfr /* VGA */ 42043105Sdfr { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1, 42143105Sdfr MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 42243105Sdfr { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, 42343105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 42443105Sdfr { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1, 42543105Sdfr MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 42643105Sdfr { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1, 42743105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 42843105Sdfr { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1, 42943105Sdfr MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 43043105Sdfr { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1, 43143105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 43243105Sdfr#ifndef VGA_NO_MODE_CHANGE 43343105Sdfr /* CGA */ 43443105Sdfr { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, 43543105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 43643105Sdfr { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, 43743105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 43843105Sdfr { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1, 43943105Sdfr CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 44043105Sdfr /* EGA */ 44143105Sdfr { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4, 44243105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 44343105Sdfr { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4, 44443105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 44543105Sdfr { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 44643105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 }, 44743105Sdfr { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 44843105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 44943105Sdfr { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2, 45043105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45143105Sdfr { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 45243105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45343105Sdfr /* VGA */ 45443105Sdfr { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, 45543105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45643105Sdfr { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, 45743105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45843105Sdfr { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1, 45943105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 46043105Sdfr { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 1, 46143105Sdfr GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 46243105Sdfr#endif /* VGA_NO_MODE_CHANGE */ 46343105Sdfr 46443105Sdfr { EOT }, 46543105Sdfr}; 46643105Sdfr 46743105Sdfrstatic int init_done = FALSE; 46843105Sdfrstatic u_char *video_mode_ptr = NULL; /* EGA/VGA */ 46943105Sdfrstatic u_char *video_mode_ptr2 = NULL; /* CGA/MDA */ 47043105Sdfrstatic u_char *mode_map[V_MODE_MAP_SIZE]; 47143105Sdfrstatic adp_state_t adpstate; 47243105Sdfrstatic adp_state_t adpstate2; 47343105Sdfrstatic int rows_offset = 1; 47443105Sdfr 47543105Sdfr/* local macros and functions */ 47643105Sdfr#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) 47743105Sdfr 47843105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 47943105Sdfrstatic void map_mode_table(u_char *map[], u_char *table, int max); 48043105Sdfr#endif 48143105Sdfrstatic void clear_mode_map(video_adapter_t *adp, u_char *map[], int max, 48243105Sdfr int color); 48343105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 48443105Sdfrstatic int map_mode_num(int mode); 48543105Sdfr#endif 48643105Sdfrstatic int map_gen_mode_num(int type, int color, int mode); 48743105Sdfrstatic int map_bios_mode_num(int type, int color, int bios_mode); 48843105Sdfrstatic u_char *get_mode_param(int mode); 48943105Sdfr#ifndef VGA_NO_BIOS 49043105Sdfrstatic void fill_adapter_param(int code, video_adapter_t *adp); 49143105Sdfr#endif 49243105Sdfrstatic int verify_adapter(video_adapter_t *adp); 49343105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 49443105Sdfr#define COMP_IDENTICAL 0 49543105Sdfr#define COMP_SIMILAR 1 49643105Sdfr#define COMP_DIFFERENT 2 49743105Sdfrstatic int comp_adpregs(u_char *buf1, u_char *buf2); 49843105Sdfr#endif 49943105Sdfrstatic int probe_adapters(void); 50043105Sdfr 50143105Sdfr#define PARAM_BUFSIZE 6 50243105Sdfrstatic void set_font_mode(video_adapter_t *adp, u_char *buf); 50343105Sdfrstatic void set_normal_mode(video_adapter_t *adp, u_char *buf); 50443105Sdfr 50543105Sdfrstatic void dump_buffer(u_char *buf, size_t len); 50643105Sdfr 50743105Sdfr#define ISMAPPED(pa, width) \ 50843105Sdfr (((pa) <= (u_long)0x1000 - (width)) \ 50943105Sdfr || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width))) 51043105Sdfr 51143105Sdfr#define prologue(adp, flag, err) \ 51243105Sdfr if (!init_done || !((adp)->va_flags & (flag))) \ 51343105Sdfr return (err) 51443105Sdfr 51543105Sdfr/* a backdoor for the console driver */ 51643105Sdfrstatic int 51743105Sdfrvga_configure(int flags) 51843105Sdfr{ 51943105Sdfr int i; 52043105Sdfr 52143105Sdfr probe_adapters(); 52243105Sdfr for (i = 0; i < biosadapters; ++i) { 52343105Sdfr if (!probe_done(&biosadapter[i])) 52443105Sdfr continue; 52543105Sdfr biosadapter[i].va_flags |= V_ADP_INITIALIZED; 52643105Sdfr if (!config_done(&biosadapter[i])) { 52743105Sdfr if (vid_register(&biosadapter[i]) < 0) 52843105Sdfr continue; 52943105Sdfr biosadapter[i].va_flags |= V_ADP_REGISTERED; 53043105Sdfr } 53143105Sdfr } 53243105Sdfr if (vga_sub_configure != NULL) 53343105Sdfr (*vga_sub_configure)(flags); 53443105Sdfr 53543105Sdfr return biosadapters; 53643105Sdfr} 53743105Sdfr 53843105Sdfr/* local subroutines */ 53943105Sdfr 54043105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 54143105Sdfr/* construct the mode parameter map */ 54243105Sdfrstatic void 54343105Sdfrmap_mode_table(u_char *map[], u_char *table, int max) 54443105Sdfr{ 54543105Sdfr int i; 54643105Sdfr 54743105Sdfr for(i = 0; i < max; ++i) 54843105Sdfr map[i] = table + i*V_MODE_PARAM_SIZE; 54943105Sdfr for(; i < V_MODE_MAP_SIZE; ++i) 55043105Sdfr map[i] = NULL; 55143105Sdfr} 55243105Sdfr#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 55343105Sdfr 55443105Sdfrstatic void 55543105Sdfrclear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color) 55643105Sdfr{ 55743105Sdfr video_info_t info; 55843105Sdfr int i; 55943105Sdfr 56043105Sdfr /* 56143105Sdfr * NOTE: we don't touch `bios_vmode[]' because it is shared 56243105Sdfr * by all adapters. 56343105Sdfr */ 56443105Sdfr for(i = 0; i < max; ++i) { 56543105Sdfr if (vga_get_info(adp, i, &info)) 56643105Sdfr continue; 56743105Sdfr if ((info.vi_flags & V_INFO_COLOR) != color) 56843105Sdfr map[i] = NULL; 56943105Sdfr } 57043105Sdfr} 57143105Sdfr 57243105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 57343105Sdfr/* map the non-standard video mode to a known mode number */ 57443105Sdfrstatic int 57543105Sdfrmap_mode_num(int mode) 57643105Sdfr{ 57743105Sdfr static struct { 57843105Sdfr int from; 57943105Sdfr int to; 58043105Sdfr } mode_map[] = { 58143105Sdfr { M_ENH_B80x43, M_ENH_B80x25 }, 58243105Sdfr { M_ENH_C80x43, M_ENH_C80x25 }, 58343105Sdfr { M_VGA_M80x30, M_VGA_M80x25 }, 58443105Sdfr { M_VGA_C80x30, M_VGA_C80x25 }, 58543105Sdfr { M_VGA_M80x50, M_VGA_M80x25 }, 58643105Sdfr { M_VGA_C80x50, M_VGA_C80x25 }, 58743105Sdfr { M_VGA_M80x60, M_VGA_M80x25 }, 58843105Sdfr { M_VGA_C80x60, M_VGA_C80x25 }, 58943105Sdfr { M_VGA_MODEX, M_VGA_CG320 }, 59043105Sdfr }; 59143105Sdfr int i; 59243105Sdfr 59343105Sdfr for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 59443105Sdfr if (mode_map[i].from == mode) 59543105Sdfr return mode_map[i].to; 59643105Sdfr } 59743105Sdfr return mode; 59843105Sdfr} 59943105Sdfr#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 60043105Sdfr 60143105Sdfr/* map a generic video mode to a known mode number */ 60243105Sdfrstatic int 60343105Sdfrmap_gen_mode_num(int type, int color, int mode) 60443105Sdfr{ 60543105Sdfr static struct { 60643105Sdfr int from; 60743105Sdfr int to_color; 60843105Sdfr int to_mono; 60943105Sdfr } mode_map[] = { 61043105Sdfr { M_TEXT_80x30, M_VGA_C80x30, M_VGA_M80x30, }, 61143105Sdfr { M_TEXT_80x43, M_ENH_C80x43, M_ENH_B80x43, }, 61243105Sdfr { M_TEXT_80x50, M_VGA_C80x50, M_VGA_M80x50, }, 61343105Sdfr { M_TEXT_80x60, M_VGA_C80x60, M_VGA_M80x60, }, 61443105Sdfr }; 61543105Sdfr int i; 61643105Sdfr 61743105Sdfr if (mode == M_TEXT_80x25) { 61843105Sdfr switch (type) { 61943105Sdfr 62043105Sdfr case KD_VGA: 62143105Sdfr if (color) 62243105Sdfr return M_VGA_C80x25; 62343105Sdfr else 62443105Sdfr return M_VGA_M80x25; 62543105Sdfr break; 62643105Sdfr 62743105Sdfr case KD_EGA: 62843105Sdfr if (color) 62943105Sdfr return M_ENH_C80x25; 63043105Sdfr else 63143105Sdfr return M_EGAMONO80x25; 63243105Sdfr break; 63343105Sdfr 63443105Sdfr case KD_CGA: 63543105Sdfr return M_C80x25; 63643105Sdfr 63743105Sdfr case KD_MONO: 63843105Sdfr case KD_HERCULES: 63943105Sdfr return M_EGAMONO80x25; /* XXX: this name is confusing */ 64043105Sdfr 64143105Sdfr default: 64243105Sdfr return -1; 64343105Sdfr } 64443105Sdfr } 64543105Sdfr 64643105Sdfr for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 64743105Sdfr if (mode_map[i].from == mode) 64843105Sdfr return ((color) ? mode_map[i].to_color : mode_map[i].to_mono); 64943105Sdfr } 65043105Sdfr return mode; 65143105Sdfr} 65243105Sdfr 65343105Sdfr/* turn the BIOS video number into our video mode number */ 65443105Sdfrstatic int 65543105Sdfrmap_bios_mode_num(int type, int color, int bios_mode) 65643105Sdfr{ 65743105Sdfr static int cga_modes[7] = { 65843105Sdfr M_B40x25, M_C40x25, /* 0, 1 */ 65943105Sdfr M_B80x25, M_C80x25, /* 2, 3 */ 66043105Sdfr M_BG320, M_CG320, 66143105Sdfr M_BG640, 66243105Sdfr }; 66343105Sdfr static int ega_modes[17] = { 66443105Sdfr M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */ 66543105Sdfr M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */ 66643105Sdfr M_BG320, M_CG320, 66743105Sdfr M_BG640, 66843105Sdfr M_EGAMONO80x25, /* 7 */ 66943105Sdfr 8, 9, 10, 11, 12, 67043105Sdfr M_CG320_D, 67143105Sdfr M_CG640_E, 67243105Sdfr M_ENHMONOAPA2, /* XXX: video momery > 64K */ 67343105Sdfr M_ENH_CG640, /* XXX: video momery > 64K */ 67443105Sdfr }; 67543105Sdfr static int vga_modes[20] = { 67643105Sdfr M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */ 67743105Sdfr M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */ 67843105Sdfr M_BG320, M_CG320, 67943105Sdfr M_BG640, 68043105Sdfr M_VGA_M80x25, /* 7 */ 68143105Sdfr 8, 9, 10, 11, 12, 68243105Sdfr M_CG320_D, 68343105Sdfr M_CG640_E, 68443105Sdfr M_ENHMONOAPA2, 68543105Sdfr M_ENH_CG640, 68643105Sdfr M_BG640x480, M_CG640x480, 68743105Sdfr M_VGA_CG320, 68843105Sdfr }; 68943105Sdfr 69043105Sdfr switch (type) { 69143105Sdfr 69243105Sdfr case KD_VGA: 69343105Sdfr if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0])) 69443105Sdfr return vga_modes[bios_mode]; 69543105Sdfr else if (color) 69643105Sdfr return M_VGA_C80x25; 69743105Sdfr else 69843105Sdfr return M_VGA_M80x25; 69943105Sdfr break; 70043105Sdfr 70143105Sdfr case KD_EGA: 70243105Sdfr if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0])) 70343105Sdfr return ega_modes[bios_mode]; 70443105Sdfr else if (color) 70543105Sdfr return M_ENH_C80x25; 70643105Sdfr else 70743105Sdfr return M_EGAMONO80x25; 70843105Sdfr break; 70943105Sdfr 71043105Sdfr case KD_CGA: 71143105Sdfr if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0])) 71243105Sdfr return cga_modes[bios_mode]; 71343105Sdfr else 71443105Sdfr return M_C80x25; 71543105Sdfr break; 71643105Sdfr 71743105Sdfr case KD_MONO: 71843105Sdfr case KD_HERCULES: 71943105Sdfr return M_EGAMONO80x25; /* XXX: this name is confusing */ 72043105Sdfr 72143105Sdfr default: 72243105Sdfr break; 72343105Sdfr } 72443105Sdfr return -1; 72543105Sdfr} 72643105Sdfr 72743105Sdfr/* look up a parameter table entry */ 72843105Sdfrstatic u_char 72943105Sdfr*get_mode_param(int mode) 73043105Sdfr{ 73143105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 73243105Sdfr if (mode >= V_MODE_MAP_SIZE) 73343105Sdfr mode = map_mode_num(mode); 73443105Sdfr#endif 73543105Sdfr if ((mode >= 0) && (mode < V_MODE_MAP_SIZE)) 73643105Sdfr return mode_map[mode]; 73743105Sdfr else 73843105Sdfr return NULL; 73943105Sdfr} 74043105Sdfr 74143105Sdfr#ifndef VGA_NO_BIOS 74243105Sdfrstatic void 74343105Sdfrfill_adapter_param(int code, video_adapter_t *adp) 74443105Sdfr{ 74543105Sdfr static struct { 74643105Sdfr int primary; 74743105Sdfr int secondary; 74843105Sdfr } dcc[] = { 74943105Sdfr { DCC_MONO, DCC_EGA40 /* CGA monitor */ }, 75043105Sdfr { DCC_MONO, DCC_EGA80 /* CGA monitor */ }, 75143105Sdfr { DCC_MONO, DCC_EGA80 /* CGA emulation */ }, 75243105Sdfr { DCC_MONO, DCC_EGA80 }, 75343105Sdfr { DCC_CGA40, DCC_EGAMONO }, 75443105Sdfr { DCC_CGA80, DCC_EGAMONO }, 75543105Sdfr { DCC_EGA40 /* CGA monitor */, DCC_MONO}, 75643105Sdfr { DCC_EGA80 /* CGA monitor */, DCC_MONO}, 75743105Sdfr { DCC_EGA80 /* CGA emulation */,DCC_MONO }, 75843105Sdfr { DCC_EGA80, DCC_MONO }, 75943105Sdfr { DCC_EGAMONO, DCC_CGA40 }, 76043105Sdfr { DCC_EGAMONO, DCC_CGA40 }, 76143105Sdfr }; 76243105Sdfr 76343105Sdfr if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) { 76443105Sdfr adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; 76543105Sdfr adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; 76643105Sdfr } else { 76743105Sdfr adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary]; 76843105Sdfr adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary]; 76943105Sdfr } 77043105Sdfr} 77143105Sdfr#endif /* VGA_NO_BIOS */ 77243105Sdfr 77343105Sdfrstatic int 77443105Sdfrverify_adapter(video_adapter_t *adp) 77543105Sdfr{ 77643105Sdfr vm_offset_t buf; 77743105Sdfr u_int16_t v; 77843105Sdfr 77943105Sdfr buf = BIOS_PADDRTOVADDR(adp->va_window); 78043105Sdfr v = readw(buf); 78143105Sdfr writew(buf, 0xA55A); 78243105Sdfr if (readw(buf) != 0xA55A) 78343105Sdfr return 1; 78443105Sdfr writew(buf, v); 78543105Sdfr 78643105Sdfr switch (adp->va_type) { 78743105Sdfr 78843105Sdfr case KD_EGA: 78943105Sdfr outb(adp->va_crtc_addr, 7); 79043105Sdfr if (inb(adp->va_crtc_addr) == 7) { 79143105Sdfr adp->va_type = KD_VGA; 79243105Sdfr adp->va_name = "vga"; 79343105Sdfr adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE; 79443105Sdfr } 79543105Sdfr adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER; 79643105Sdfr /* the color adapter may be in the 40x25 mode... XXX */ 79743105Sdfr 79843105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 79943105Sdfr /* get the BIOS video mode pointer */ 80043105Sdfr p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8); 80143105Sdfr p = BIOS_SADDRTOLADDR(p); 80243105Sdfr if (ISMAPPED(p, sizeof(u_int32_t))) { 80343105Sdfr p = *(u_int32_t *)BIOS_PADDRTOVADDR(p); 80443105Sdfr p = BIOS_SADDRTOLADDR(p); 80543105Sdfr if (ISMAPPED(p, V_MODE_PARAM_SIZE)) 80643105Sdfr video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p); 80743105Sdfr } 80843105Sdfr#endif 80943105Sdfr break; 81043105Sdfr 81143105Sdfr case KD_CGA: 81243105Sdfr adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER; 81343105Sdfr /* may be in the 40x25 mode... XXX */ 81443105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 81543105Sdfr /* get the BIOS video mode pointer */ 81643105Sdfr p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); 81743105Sdfr p = BIOS_SADDRTOLADDR(p); 81843105Sdfr video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); 81943105Sdfr#endif 82043105Sdfr break; 82143105Sdfr 82243105Sdfr case KD_MONO: 82343105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 82443105Sdfr /* get the BIOS video mode pointer */ 82543105Sdfr p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); 82643105Sdfr p = BIOS_SADDRTOLADDR(p); 82743105Sdfr video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); 82843105Sdfr#endif 82943105Sdfr break; 83043105Sdfr } 83143105Sdfr 83243105Sdfr return 0; 83343105Sdfr} 83443105Sdfr 83543105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 83643105Sdfr/* compare two parameter table entries */ 83743105Sdfrstatic int 83843105Sdfrcomp_adpregs(u_char *buf1, u_char *buf2) 83943105Sdfr{ 84043105Sdfr static struct { 84143105Sdfr u_char mask; 84243105Sdfr } params[V_MODE_PARAM_SIZE] = { 84343105Sdfr 0xff, 0x00, 0xff, /* COLS, ROWS, POINTS */ 84443105Sdfr 0x00, 0x00, /* page length */ 84543105Sdfr 0xfe, 0xff, 0xff, 0xff, /* sequencer registers */ 84643105Sdfr 0xf3, /* misc register */ 84743105Sdfr 0xff, 0xff, 0xff, 0x7f, 0xff, /* CRTC */ 84843105Sdfr 0xff, 0xff, 0xff, 0x7f, 0xff, 84943105Sdfr 0x00, 0x00, 0x00, 0x00, 0x00, 85043105Sdfr 0x00, 0xff, 0x7f, 0xff, 0xff, 85143105Sdfr 0x7f, 0xff, 0xff, 0xef, 0xff, 85243105Sdfr 0xff, 0xff, 0xff, 0xff, 0xff, /* attribute controller registers */ 85343105Sdfr 0xff, 0xff, 0xff, 0xff, 0xff, 85443105Sdfr 0xff, 0xff, 0xff, 0xff, 0xff, 85543105Sdfr 0xff, 0xff, 0xff, 0xff, 0xf0, 85643105Sdfr 0xff, 0xff, 0xff, 0xff, 0xff, /* GDC register */ 85743105Sdfr 0xff, 0xff, 0xff, 0xff, 85843105Sdfr }; 85943105Sdfr int identical = TRUE; 86043105Sdfr int i; 86143105Sdfr 86243105Sdfr if ((buf1 == NULL) || (buf2 == NULL)) 86343105Sdfr return COMP_DIFFERENT; 86443105Sdfr 86543105Sdfr for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { 86643105Sdfr if (params[i].mask == 0) /* don't care */ 86743105Sdfr continue; 86843105Sdfr if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) 86943105Sdfr return COMP_DIFFERENT; 87043105Sdfr if (buf1[i] != buf2[i]) 87143105Sdfr identical = FALSE; 87243105Sdfr } 87343105Sdfr return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; 87443105Sdfr} 87543105Sdfr#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 87643105Sdfr 87743105Sdfr/* probe video adapters and return the number of detected adapters */ 87843105Sdfrstatic int 87943105Sdfrprobe_adapters(void) 88043105Sdfr{ 88143105Sdfr video_adapter_t *adp; 88243105Sdfr video_info_t info; 88343105Sdfr int i; 88443105Sdfr 88543105Sdfr /* do this test only once */ 88643105Sdfr if (init_done) 88743105Sdfr return biosadapters; 88843105Sdfr init_done = TRUE; 88943105Sdfr 89043105Sdfr /* 89143105Sdfr * Locate display adapters. 89243105Sdfr * The AT architecture supports upto two adapters. `syscons' allows 89343105Sdfr * the following combinations of adapters: 89443105Sdfr * 1) MDA + CGA 89543105Sdfr * 2) MDA + EGA/VGA color 89643105Sdfr * 3) CGA + EGA/VGA mono 89743105Sdfr * Note that `syscons' doesn't bother with MCGA as it is only 89843105Sdfr * avaiable for low end PS/2 models which has 80286 or earlier CPUs, 89943105Sdfr * thus, they are not running FreeBSD! 90043105Sdfr * When there are two adapaters in the system, one becomes `primary' 90143105Sdfr * and the other `secondary'. The EGA adapter has a set of DIP 90243105Sdfr * switches on board for this information and the EGA BIOS copies 90343105Sdfr * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88). 90443105Sdfr * The VGA BIOS has more sophisticated mechanism and has this 90543105Sdfr * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains 90643105Sdfr * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH. 90743105Sdfr */ 90843105Sdfr 90943105Sdfr /* 91043105Sdfr * Check rtc and BIOS data area. 91143105Sdfr * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead 91243105Sdfr * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are 91343105Sdfr * zeros for EGA and VGA. However, the EGA/VGA BIOS sets 91443105Sdfr * these bits in BIOSDATA_EQUIPMENT according to the monitor 91543105Sdfr * type detected. 91643105Sdfr */ 91743105Sdfr#ifndef VGA_NO_BIOS 91843105Sdfr switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ 91943105Sdfr case 0: 92043105Sdfr /* EGA/VGA */ 92143105Sdfr fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f, 92243105Sdfr biosadapter); 92343105Sdfr break; 92443105Sdfr case 1: 92543105Sdfr /* CGA 40x25 */ 92643105Sdfr /* FIXME: switch to the 80x25 mode? XXX */ 92743105Sdfr biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40]; 92843105Sdfr biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 92943105Sdfr break; 93043105Sdfr case 2: 93143105Sdfr /* CGA 80x25 */ 93243105Sdfr biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80]; 93343105Sdfr biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 93443105Sdfr break; 93543105Sdfr case 3: 93643105Sdfr /* MDA */ 93743105Sdfr biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; 93843105Sdfr biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; 93943105Sdfr break; 94043105Sdfr } 94143105Sdfr#else 94243105Sdfr /* assume EGA/VGA? XXX */ 94343105Sdfr biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80]; 94443105Sdfr biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 94543105Sdfr#endif /* VGA_NO_BIOS */ 94643105Sdfr 94743105Sdfr biosadapters = 0; 94843105Sdfr if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) { 94943105Sdfr ++biosadapters; 95043105Sdfr biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED; 95143105Sdfr biosadapter[V_ADP_SECONDARY].va_mode = 95243105Sdfr biosadapter[V_ADP_SECONDARY].va_initial_mode = 95343105Sdfr map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type, 95443105Sdfr biosadapter[V_ADP_SECONDARY].va_flags 95543105Sdfr & V_ADP_COLOR, 95643105Sdfr biosadapter[V_ADP_SECONDARY].va_initial_bios_mode); 95743105Sdfr } else { 95843105Sdfr biosadapter[V_ADP_SECONDARY].va_type = -1; 95943105Sdfr } 96043105Sdfr if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) { 96143105Sdfr ++biosadapters; 96243105Sdfr biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED; 96343105Sdfr#ifndef VGA_NO_BIOS 96443105Sdfr biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 96543105Sdfr readb(BIOS_PADDRTOVADDR(0x449)); 96643105Sdfr#else 96743105Sdfr biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */ 96843105Sdfr#endif 96943105Sdfr biosadapter[V_ADP_PRIMARY].va_mode = 97043105Sdfr biosadapter[V_ADP_PRIMARY].va_initial_mode = 97143105Sdfr map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type, 97243105Sdfr biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR, 97343105Sdfr biosadapter[V_ADP_PRIMARY].va_initial_bios_mode); 97443105Sdfr } else { 97543105Sdfr biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY]; 97643105Sdfr biosadapter[V_ADP_SECONDARY].va_type = -1; 97743105Sdfr } 97843105Sdfr if (biosadapters == 0) 97943105Sdfr return biosadapters; 98043105Sdfr#if 0 98143105Sdfr biosadapter[V_ADP_PRIMARY].va_index = V_ADP_PRIMARY; 98243105Sdfr biosadapter[V_ADP_SECONDARY].va_index = V_ADP_SECONDARY; 98343105Sdfr#endif 98443105Sdfr biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY; 98543105Sdfr biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY; 98643105Sdfr 98743105Sdfr#if 0 /* we don't need these... */ 98843105Sdfr fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...); 98943105Sdfr fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...); 99043105Sdfr#endif 99143105Sdfr 99243105Sdfr#if 0 99343105Sdfr /* 99443105Sdfr * We cannot have two video adapter of the same type; there must be 99543105Sdfr * only one of color or mono adapter, or one each of them. 99643105Sdfr */ 99743105Sdfr if (biosadapters > 1) { 99843105Sdfr if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags) 99943105Sdfr & V_ADP_COLOR)) 100043105Sdfr /* we have two mono or color adapters!! */ 100143105Sdfr return (biosadapters = 0); 100243105Sdfr } 100343105Sdfr#endif 100443105Sdfr 100543105Sdfr /* 100643105Sdfr * Ensure a zero start address. This is mainly to recover after 100743105Sdfr * switching from pcvt using userconfig(). The registers are w/o 100843105Sdfr * for old hardware so it's too hard to relocate the active screen 100943105Sdfr * memory. 101043105Sdfr * This must be done before vga_save_state() for VGA. 101143105Sdfr */ 101243105Sdfr outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12); 101343105Sdfr outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); 101443105Sdfr outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13); 101543105Sdfr outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); 101643105Sdfr 101743105Sdfr /* the video mode parameter table in EGA/VGA BIOS */ 101843105Sdfr /* NOTE: there can be only one EGA/VGA, wheather color or mono, 101943105Sdfr * recognized by the video BIOS. 102043105Sdfr */ 102143105Sdfr if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) || 102243105Sdfr (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) { 102343105Sdfr adp = &biosadapter[V_ADP_PRIMARY]; 102443105Sdfr } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) || 102543105Sdfr (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) { 102643105Sdfr adp = &biosadapter[V_ADP_SECONDARY]; 102743105Sdfr } else { 102843105Sdfr adp = NULL; 102943105Sdfr } 103043105Sdfr bzero(mode_map, sizeof(mode_map)); 103143105Sdfr if (adp != NULL) { 103243105Sdfr if (adp->va_type == KD_VGA) { 103343105Sdfr vga_save_state(adp, &adpstate, sizeof(adpstate)); 103443105Sdfr#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) 103543105Sdfr mode_map[adp->va_initial_mode] = adpstate.regs; 103643105Sdfr rows_offset = 1; 103743105Sdfr#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 103843105Sdfr if (video_mode_ptr == NULL) { 103943105Sdfr mode_map[adp->va_initial_mode] = adpstate.regs; 104043105Sdfr rows_offset = 1; 104143105Sdfr } else { 104243105Sdfr /* discard the table if we are not familiar with it... */ 104343105Sdfr map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); 104443105Sdfr mp = get_mode_param(adp->va_initial_mode); 104543105Sdfr if (mp != NULL) 104643105Sdfr bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs)); 104743105Sdfr switch (comp_adpregs(adpstate.regs, mp)) { 104843105Sdfr case COMP_IDENTICAL: 104943105Sdfr /* 105043105Sdfr * OK, this parameter table looks reasonably familiar 105143105Sdfr * to us... 105243105Sdfr */ 105343105Sdfr /* 105443105Sdfr * This is a kludge for Toshiba DynaBook SS433 105543105Sdfr * whose BIOS video mode table entry has the actual # 105643105Sdfr * of rows at the offset 1; BIOSes from other 105743105Sdfr * manufacturers store the # of rows - 1 there. XXX 105843105Sdfr */ 105943105Sdfr rows_offset = adpstate.regs[1] + 1 - mp[1]; 106043105Sdfr break; 106143105Sdfr 106243105Sdfr case COMP_SIMILAR: 106343105Sdfr /* 106443105Sdfr * Not exactly the same, but similar enough to be 106543105Sdfr * trusted. However, use the saved register values 106643105Sdfr * for the initial mode and other modes which are 106743105Sdfr * based on the initial mode. 106843105Sdfr */ 106943105Sdfr mode_map[adp->va_initial_mode] = adpstate.regs; 107043105Sdfr rows_offset = adpstate.regs[1] + 1 - mp[1]; 107143105Sdfr adpstate.regs[1] -= rows_offset - 1; 107243105Sdfr break; 107343105Sdfr 107443105Sdfr case COMP_DIFFERENT: 107543105Sdfr default: 107643105Sdfr /* 107743105Sdfr * Don't use the paramter table in BIOS. It doesn't 107843105Sdfr * look familiar to us. Video mode switching is allowed 107943105Sdfr * only if the new mode is the same as or based on 108043105Sdfr * the initial mode. 108143105Sdfr */ 108243105Sdfr video_mode_ptr = NULL; 108343105Sdfr bzero(mode_map, sizeof(mode_map)); 108443105Sdfr mode_map[adp->va_initial_mode] = adpstate.regs; 108543105Sdfr rows_offset = 1; 108643105Sdfr break; 108743105Sdfr } 108843105Sdfr } 108943105Sdfr#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 109043105Sdfr 109143105Sdfr#ifndef VGA_NO_MODE_CHANGE 109243105Sdfr adp->va_flags |= V_ADP_MODECHANGE; 109343105Sdfr#endif 109443105Sdfr#ifndef VGA_NO_FONT_LOADING 109543105Sdfr adp->va_flags |= V_ADP_FONT; 109643105Sdfr#endif 109743105Sdfr } else if (adp->va_type == KD_EGA) { 109843105Sdfr#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) 109943105Sdfr rows_offset = 1; 110043105Sdfr#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 110143105Sdfr if (video_mode_ptr == NULL) { 110243105Sdfr rows_offset = 1; 110343105Sdfr } else { 110443105Sdfr map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1); 110543105Sdfr /* XXX how can one validate the EGA table... */ 110643105Sdfr mp = get_mode_param(adp->va_initial_mode); 110743105Sdfr if (mp != NULL) { 110843105Sdfr adp->va_flags |= V_ADP_MODECHANGE; 110943105Sdfr#ifndef VGA_NO_FONT_LOADING 111043105Sdfr adp->va_flags |= V_ADP_FONT; 111143105Sdfr#endif 111243105Sdfr rows_offset = 1; 111343105Sdfr } else { 111443105Sdfr /* 111543105Sdfr * This is serious. We will not be able to switch video 111643105Sdfr * modes at all... 111743105Sdfr */ 111843105Sdfr video_mode_ptr = NULL; 111943105Sdfr bzero(mode_map, sizeof(mode_map)); 112043105Sdfr rows_offset = 1; 112143105Sdfr } 112243105Sdfr } 112343105Sdfr#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 112443105Sdfr } 112543105Sdfr } 112643105Sdfr 112743105Sdfr /* remove conflicting modes if we have more than one adapter */ 112843105Sdfr if (biosadapters > 1) { 112943105Sdfr for (i = 0; i < biosadapters; ++i) { 113043105Sdfr if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE)) 113143105Sdfr continue; 113243105Sdfr clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1, 113343105Sdfr (biosadapter[i].va_flags & V_ADP_COLOR) ? 113443105Sdfr V_INFO_COLOR : 0); 113543105Sdfr if ((biosadapter[i].va_type == KD_VGA) 113643105Sdfr || (biosadapter[i].va_type == KD_EGA)) { 113743105Sdfr biosadapter[i].va_io_base = 113843105Sdfr (biosadapter[i].va_flags & V_ADP_COLOR) ? 113943105Sdfr IO_VGA : IO_MDA; 114043105Sdfr biosadapter[i].va_io_size = 32; 114143105Sdfr } 114243105Sdfr } 114343105Sdfr } 114443105Sdfr 114543105Sdfr /* buffer address */ 114643105Sdfr vga_get_info(&biosadapter[V_ADP_PRIMARY], 114743105Sdfr biosadapter[V_ADP_PRIMARY].va_initial_mode, &info); 114843105Sdfr biosadapter[V_ADP_PRIMARY].va_mode_flags = info.vi_flags; 114943105Sdfr biosadapter[V_ADP_PRIMARY].va_window = BIOS_PADDRTOVADDR(info.vi_window); 115043105Sdfr biosadapter[V_ADP_PRIMARY].va_window_size = info.vi_window_size; 115143105Sdfr biosadapter[V_ADP_PRIMARY].va_window_gran = info.vi_window_gran; 115243105Sdfr if (info.vi_buffer_size == 0) { 115343105Sdfr biosadapter[V_ADP_PRIMARY].va_buffer = 0; 115443105Sdfr biosadapter[V_ADP_PRIMARY].va_buffer_size = 0; 115543105Sdfr } else { 115643105Sdfr biosadapter[V_ADP_PRIMARY].va_buffer 115743105Sdfr = BIOS_PADDRTOVADDR(info.vi_buffer); 115843105Sdfr biosadapter[V_ADP_PRIMARY].va_buffer_size = info.vi_buffer_size; 115943105Sdfr } 116043105Sdfr 116143105Sdfr if (biosadapters > 1) { 116243105Sdfr vga_get_info(&biosadapter[V_ADP_SECONDARY], 116343105Sdfr biosadapter[V_ADP_SECONDARY].va_initial_mode, &info); 116443105Sdfr biosadapter[V_ADP_SECONDARY].va_mode_flags = info.vi_flags; 116543105Sdfr biosadapter[V_ADP_SECONDARY].va_window = 116643105Sdfr BIOS_PADDRTOVADDR(info.vi_window); 116743105Sdfr biosadapter[V_ADP_SECONDARY].va_window_size = info.vi_window_size; 116843105Sdfr biosadapter[V_ADP_SECONDARY].va_window_gran = info.vi_window_gran; 116943105Sdfr if (info.vi_buffer_size == 0) { 117043105Sdfr biosadapter[V_ADP_SECONDARY].va_buffer = 0; 117143105Sdfr biosadapter[V_ADP_SECONDARY].va_buffer_size = 0; 117243105Sdfr } else { 117343105Sdfr biosadapter[V_ADP_SECONDARY].va_buffer = 117443105Sdfr BIOS_PADDRTOVADDR(info.vi_buffer); 117543105Sdfr biosadapter[V_ADP_SECONDARY].va_buffer_size = info.vi_buffer_size; 117643105Sdfr } 117743105Sdfr } 117843105Sdfr 117943105Sdfr /* 118043105Sdfr * XXX: we should verify the following values for the primary adapter... 118143105Sdfr * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463); 118243105Sdfr * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02) 118343105Sdfr * ? 0 : V_ADP_COLOR; 118443105Sdfr * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a); 118543105Sdfr * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484); 118643105Sdfr * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485); 118743105Sdfr * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c); 118843105Sdfr */ 118943105Sdfr 119043105Sdfr return biosadapters; 119143105Sdfr} 119243105Sdfr 119343105Sdfr/* entry points */ 119443105Sdfr 119543105Sdfrstatic int 119643105Sdfrvga_nop(void) 119743105Sdfr{ 119843105Sdfr return 0; 119943105Sdfr} 120043105Sdfr 120143105Sdfrstatic int 120243105Sdfrvga_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 120343105Sdfr{ 120443105Sdfr probe_adapters(); 120543105Sdfr if (unit >= biosadapters) 120643105Sdfr return ENXIO; 120743105Sdfr 120843105Sdfr *adpp = &biosadapter[unit]; 120943105Sdfr 121043105Sdfr return 0; 121143105Sdfr} 121243105Sdfr 121343105Sdfrstatic int 121443105Sdfrvga_init(int unit, video_adapter_t *adp, int flags) 121543105Sdfr{ 121643105Sdfr if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp)) 121743105Sdfr return ENXIO; 121843105Sdfr 121943105Sdfr if (!init_done(adp)) { 122043105Sdfr /* nothing to do really... */ 122143105Sdfr adp->va_flags |= V_ADP_INITIALIZED; 122243105Sdfr } 122343105Sdfr 122443105Sdfr if (!config_done(adp)) { 122543105Sdfr if (vid_register(adp) < 0) 122643105Sdfr return ENXIO; 122743105Sdfr adp->va_flags |= V_ADP_REGISTERED; 122843105Sdfr } 122943105Sdfr if (vga_sub_configure != NULL) 123043105Sdfr (*vga_sub_configure)(0); 123143105Sdfr 123243105Sdfr return 0; 123343105Sdfr} 123443105Sdfr 123543105Sdfr/* 123643105Sdfr * get_info(): 123743105Sdfr * Return the video_info structure of the requested video mode. 123843105Sdfr * 123943105Sdfr * all adapters 124043105Sdfr */ 124143105Sdfrstatic int 124243105Sdfrvga_get_info(video_adapter_t *adp, int mode, video_info_t *info) 124343105Sdfr{ 124443105Sdfr int i; 124543105Sdfr 124643105Sdfr if (!init_done) 124743105Sdfr return 1; 124843105Sdfr 124943105Sdfr mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); 125043105Sdfr#ifndef VGA_NO_MODE_CHANGE 125143105Sdfr if (adp->va_flags & V_ADP_MODECHANGE) { 125243105Sdfr /* 125343105Sdfr * If the parameter table entry for this mode is not found, 125443105Sdfr * the mode is not supported... 125543105Sdfr */ 125643105Sdfr if (get_mode_param(mode) == NULL) 125743105Sdfr return 1; 125843105Sdfr } else 125943105Sdfr#endif /* VGA_NO_MODE_CHANGE */ 126043105Sdfr { 126143105Sdfr /* 126243105Sdfr * Even if we don't support video mode switching on this adapter, 126343105Sdfr * the information on the initial (thus current) video mode 126443105Sdfr * should be made available. 126543105Sdfr */ 126643105Sdfr if (mode != adp->va_initial_mode) 126743105Sdfr return 1; 126843105Sdfr } 126943105Sdfr 127043105Sdfr for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 127143105Sdfr if (bios_vmode[i].vi_mode == NA) 127243105Sdfr continue; 127343105Sdfr if (mode == bios_vmode[i].vi_mode) { 127443105Sdfr *info = bios_vmode[i]; 127543105Sdfr return 0; 127643105Sdfr } 127743105Sdfr } 127843105Sdfr return 1; 127943105Sdfr} 128043105Sdfr 128143105Sdfr/* 128243105Sdfr * query_mode(): 128343105Sdfr * Find a video mode matching the requested parameters. 128443105Sdfr * Fields filled with 0 are considered "don't care" fields and 128543105Sdfr * match any modes. 128643105Sdfr * 128743105Sdfr * all adapters 128843105Sdfr */ 128943105Sdfrstatic int 129043105Sdfrvga_query_mode(video_adapter_t *adp, video_info_t *info) 129143105Sdfr{ 129243105Sdfr video_info_t buf; 129343105Sdfr int i; 129443105Sdfr 129543105Sdfr if (!init_done) 129643105Sdfr return -1; 129743105Sdfr 129843105Sdfr for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 129943105Sdfr if (bios_vmode[i].vi_mode == NA) 130043105Sdfr continue; 130143105Sdfr 130243105Sdfr if ((info->vi_width != 0) 130343105Sdfr && (info->vi_width != bios_vmode[i].vi_width)) 130443105Sdfr continue; 130543105Sdfr if ((info->vi_height != 0) 130643105Sdfr && (info->vi_height != bios_vmode[i].vi_height)) 130743105Sdfr continue; 130843105Sdfr if ((info->vi_cwidth != 0) 130943105Sdfr && (info->vi_cwidth != bios_vmode[i].vi_cwidth)) 131043105Sdfr continue; 131143105Sdfr if ((info->vi_cheight != 0) 131243105Sdfr && (info->vi_cheight != bios_vmode[i].vi_cheight)) 131343105Sdfr continue; 131443105Sdfr if ((info->vi_depth != 0) 131543105Sdfr && (info->vi_depth != bios_vmode[i].vi_depth)) 131643105Sdfr continue; 131743105Sdfr if ((info->vi_planes != 0) 131843105Sdfr && (info->vi_planes != bios_vmode[i].vi_planes)) 131943105Sdfr continue; 132043105Sdfr /* XXX: should check pixel format, memory model */ 132143105Sdfr if ((info->vi_flags != 0) 132243105Sdfr && (info->vi_flags != bios_vmode[i].vi_flags)) 132343105Sdfr continue; 132443105Sdfr 132543105Sdfr /* verify if this mode is supported on this adapter */ 132643105Sdfr if (vga_get_info(adp, bios_vmode[i].vi_mode, &buf)) 132743105Sdfr continue; 132843105Sdfr return bios_vmode[i].vi_mode; 132943105Sdfr } 133043105Sdfr return -1; 133143105Sdfr} 133243105Sdfr 133343105Sdfr/* 133443105Sdfr * set_mode(): 133543105Sdfr * Change the video mode. 133643105Sdfr * 133743105Sdfr * EGA/VGA 133843105Sdfr */ 133943105Sdfrstatic int 134043105Sdfrvga_set_mode(video_adapter_t *adp, int mode) 134143105Sdfr{ 134243105Sdfr#ifndef VGA_NO_MODE_CHANGE 134343105Sdfr video_info_t info; 134443105Sdfr adp_state_t params; 134543105Sdfr 134643105Sdfr prologue(adp, V_ADP_MODECHANGE, 1); 134743105Sdfr 134843105Sdfr mode = map_gen_mode_num(adp->va_type, 134943105Sdfr adp->va_flags & V_ADP_COLOR, mode); 135043105Sdfr if (vga_get_info(adp, mode, &info)) 135143105Sdfr return 1; 135243105Sdfr params.sig = V_STATE_SIG; 135343105Sdfr bcopy(get_mode_param(mode), params.regs, sizeof(params.regs)); 135443105Sdfr 135543105Sdfr switch (mode) { 135643105Sdfr case M_VGA_C80x60: case M_VGA_M80x60: 135743105Sdfr params.regs[2] = 0x08; 135843105Sdfr params.regs[19] = 0x47; 135943105Sdfr goto special_480l; 136043105Sdfr 136143105Sdfr case M_VGA_C80x30: case M_VGA_M80x30: 136243105Sdfr params.regs[19] = 0x4f; 136343105Sdfrspecial_480l: 136443105Sdfr params.regs[9] |= 0xc0; 136543105Sdfr params.regs[16] = 0x08; 136643105Sdfr params.regs[17] = 0x3e; 136743105Sdfr params.regs[26] = 0xea; 136843105Sdfr params.regs[28] = 0xdf; 136943105Sdfr params.regs[31] = 0xe7; 137043105Sdfr params.regs[32] = 0x04; 137143105Sdfr goto setup_mode; 137243105Sdfr 137343105Sdfr case M_ENH_C80x43: case M_ENH_B80x43: 137443105Sdfr params.regs[28] = 87; 137543105Sdfr goto special_80x50; 137643105Sdfr 137743105Sdfr case M_VGA_C80x50: case M_VGA_M80x50: 137843105Sdfrspecial_80x50: 137943105Sdfr params.regs[2] = 8; 138043105Sdfr params.regs[19] = 7; 138143105Sdfr goto setup_mode; 138243105Sdfr 138343105Sdfr case M_VGA_C40x25: case M_VGA_C80x25: 138443105Sdfr case M_VGA_M80x25: 138543105Sdfr case M_B40x25: case M_C40x25: 138643105Sdfr case M_B80x25: case M_C80x25: 138743105Sdfr case M_ENH_B40x25: case M_ENH_C40x25: 138843105Sdfr case M_ENH_B80x25: case M_ENH_C80x25: 138943105Sdfr case M_EGAMONO80x25: 139043105Sdfr 139143105Sdfrsetup_mode: 139243105Sdfr vga_load_state(adp, ¶ms); 139343105Sdfr break; 139443105Sdfr 139543105Sdfr case M_VGA_MODEX: 139643105Sdfr /* "unchain" the VGA mode */ 139743105Sdfr params.regs[5-1+0x04] &= 0xf7; 139843105Sdfr params.regs[5-1+0x04] |= 0x04; 139943105Sdfr /* turn off doubleword mode */ 140043105Sdfr params.regs[10+0x14] &= 0xbf; 140143105Sdfr /* turn off word adressing */ 140243105Sdfr params.regs[10+0x17] |= 0x40; 140343105Sdfr /* set logical screen width */ 140443105Sdfr params.regs[10+0x13] = 80; 140543105Sdfr /* set 240 lines */ 140643105Sdfr params.regs[10+0x11] = 0x2c; 140743105Sdfr params.regs[10+0x06] = 0x0d; 140843105Sdfr params.regs[10+0x07] = 0x3e; 140943105Sdfr params.regs[10+0x10] = 0xea; 141043105Sdfr params.regs[10+0x11] = 0xac; 141143105Sdfr params.regs[10+0x12] = 0xdf; 141243105Sdfr params.regs[10+0x15] = 0xe7; 141343105Sdfr params.regs[10+0x16] = 0x06; 141443105Sdfr /* set vertical sync polarity to reflect aspect ratio */ 141543105Sdfr params.regs[9] = 0xe3; 141643105Sdfr goto setup_grmode; 141743105Sdfr 141843105Sdfr case M_BG320: case M_CG320: case M_BG640: 141943105Sdfr case M_CG320_D: case M_CG640_E: 142043105Sdfr case M_CG640x350: case M_ENH_CG640: 142143105Sdfr case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 142243105Sdfr 142343105Sdfrsetup_grmode: 142443105Sdfr vga_load_state(adp, ¶ms); 142543105Sdfr break; 142643105Sdfr 142743105Sdfr default: 142843105Sdfr return 1; 142943105Sdfr } 143043105Sdfr 143143105Sdfr adp->va_mode = mode; 143243105Sdfr adp->va_mode_flags = info.vi_flags; 143343105Sdfr adp->va_flags &= ~V_ADP_COLOR; 143443105Sdfr adp->va_flags |= 143543105Sdfr (info.vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; 143643105Sdfr adp->va_crtc_addr = 143743105Sdfr (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; 143843105Sdfr adp->va_window = BIOS_PADDRTOVADDR(info.vi_window); 143943105Sdfr adp->va_window_size = info.vi_window_size; 144043105Sdfr adp->va_window_gran = info.vi_window_gran; 144143105Sdfr if (info.vi_buffer_size == 0) { 144243105Sdfr adp->va_buffer = 0; 144343105Sdfr adp->va_buffer_size = 0; 144443105Sdfr } else { 144543105Sdfr adp->va_buffer = BIOS_PADDRTOVADDR(info.vi_buffer); 144643105Sdfr adp->va_buffer_size = info.vi_buffer_size; 144743105Sdfr } 144843105Sdfr 144943105Sdfr /* move hardware cursor out of the way */ 145043105Sdfr (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1); 145143105Sdfr 145243105Sdfr return 0; 145343105Sdfr#else /* VGA_NO_MODE_CHANGE */ 145443105Sdfr return 1; 145543105Sdfr#endif /* VGA_NO_MODE_CHANGE */ 145643105Sdfr} 145743105Sdfr 145843105Sdfr#ifndef VGA_NO_FONT_LOADING 145943105Sdfr 146043105Sdfrstatic void 146143105Sdfrset_font_mode(video_adapter_t *adp, u_char *buf) 146243105Sdfr{ 146343105Sdfr u_char *mp; 146443105Sdfr int s; 146543105Sdfr 146643105Sdfr s = splhigh(); 146743105Sdfr 146843105Sdfr /* save register values */ 146943105Sdfr if (adp->va_type == KD_VGA) { 147043105Sdfr outb(TSIDX, 0x02); buf[0] = inb(TSREG); 147143105Sdfr outb(TSIDX, 0x04); buf[1] = inb(TSREG); 147243105Sdfr outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); 147343105Sdfr outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); 147443105Sdfr outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); 147543105Sdfr inb(adp->va_crtc_addr + 6); 147643105Sdfr outb(ATC, 0x10); buf[5] = inb(ATC + 1); 147743105Sdfr } else /* if (adp->va_type == KD_EGA) */ { 147843105Sdfr /* 147943105Sdfr * EGA cannot be read; copy parameters from the mode parameter 148043105Sdfr * table. 148143105Sdfr */ 148243105Sdfr mp = get_mode_param(adp->va_mode); 148343105Sdfr buf[0] = mp[5 + 0x02 - 1]; 148443105Sdfr buf[1] = mp[5 + 0x04 - 1]; 148543105Sdfr buf[2] = mp[55 + 0x04]; 148643105Sdfr buf[3] = mp[55 + 0x05]; 148743105Sdfr buf[4] = mp[55 + 0x06]; 148843105Sdfr buf[5] = mp[35 + 0x10]; 148943105Sdfr } 149043105Sdfr 149143105Sdfr /* setup vga for loading fonts */ 149243105Sdfr inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 149343105Sdfr outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01); 149443105Sdfr inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 149543105Sdfr outb(ATC, 0x20); /* enable palette */ 149643105Sdfr 149743105Sdfr#if VGA_SLOW_IOACCESS 149843105Sdfr#ifdef VGA_ALT_SEQACCESS 149943105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); 150043105Sdfr#endif 150143105Sdfr outb(TSIDX, 0x02); outb(TSREG, 0x04); 150243105Sdfr outb(TSIDX, 0x04); outb(TSREG, 0x07); 150343105Sdfr#ifdef VGA_ALT_SEQACCESS 150443105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); 150543105Sdfr#endif 150643105Sdfr outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 150743105Sdfr outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 150843105Sdfr outb(GDCIDX, 0x06); outb(GDCREG, 0x04); 150943105Sdfr#else /* VGA_SLOW_IOACCESS */ 151043105Sdfr#ifdef VGA_ALT_SEQACCESS 151143105Sdfr outw(TSIDX, 0x0100); 151243105Sdfr#endif 151343105Sdfr outw(TSIDX, 0x0402); 151443105Sdfr outw(TSIDX, 0x0704); 151543105Sdfr#ifdef VGA_ALT_SEQACCESS 151643105Sdfr outw(TSIDX, 0x0300); 151743105Sdfr#endif 151843105Sdfr outw(GDCIDX, 0x0204); 151943105Sdfr outw(GDCIDX, 0x0005); 152043105Sdfr outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */ 152143105Sdfr#endif /* VGA_SLOW_IOACCESS */ 152243105Sdfr 152343105Sdfr splx(s); 152443105Sdfr} 152543105Sdfr 152643105Sdfrstatic void 152743105Sdfrset_normal_mode(video_adapter_t *adp, u_char *buf) 152843105Sdfr{ 152943105Sdfr int s; 153043105Sdfr 153143105Sdfr s = splhigh(); 153243105Sdfr 153343105Sdfr /* setup vga for normal operation mode again */ 153443105Sdfr inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 153543105Sdfr outb(ATC, 0x10); outb(ATC, buf[5]); 153643105Sdfr inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 153743105Sdfr outb(ATC, 0x20); /* enable palette */ 153843105Sdfr 153943105Sdfr#if VGA_SLOW_IOACCESS 154043105Sdfr#ifdef VGA_ALT_SEQACCESS 154143105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); 154243105Sdfr#endif 154343105Sdfr outb(TSIDX, 0x02); outb(TSREG, buf[0]); 154443105Sdfr outb(TSIDX, 0x04); outb(TSREG, buf[1]); 154543105Sdfr#ifdef VGA_ALT_SEQACCESS 154643105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); 154743105Sdfr#endif 154843105Sdfr outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); 154943105Sdfr outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); 155043105Sdfr if (adp->va_crtc_addr == MONO_CRTC) { 155143105Sdfr outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); 155243105Sdfr } else { 155343105Sdfr outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); 155443105Sdfr } 155543105Sdfr#else /* VGA_SLOW_IOACCESS */ 155643105Sdfr#ifdef VGA_ALT_SEQACCESS 155743105Sdfr outw(TSIDX, 0x0100); 155843105Sdfr#endif 155943105Sdfr outw(TSIDX, 0x0002 | (buf[0] << 8)); 156043105Sdfr outw(TSIDX, 0x0004 | (buf[1] << 8)); 156143105Sdfr#ifdef VGA_ALT_SEQACCESS 156243105Sdfr outw(TSIDX, 0x0300); 156343105Sdfr#endif 156443105Sdfr outw(GDCIDX, 0x0004 | (buf[2] << 8)); 156543105Sdfr outw(GDCIDX, 0x0005 | (buf[3] << 8)); 156643105Sdfr if (adp->va_crtc_addr == MONO_CRTC) 156743105Sdfr outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); 156843105Sdfr else 156943105Sdfr outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); 157043105Sdfr#endif /* VGA_SLOW_IOACCESS */ 157143105Sdfr 157243105Sdfr splx(s); 157343105Sdfr} 157443105Sdfr 157543105Sdfr#endif /* VGA_NO_FONT_LOADING */ 157643105Sdfr 157743105Sdfr/* 157843105Sdfr * save_font(): 157943105Sdfr * Read the font data in the requested font page from the video adapter. 158043105Sdfr * 158143105Sdfr * EGA/VGA 158243105Sdfr */ 158343105Sdfrstatic int 158443105Sdfrvga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 158543105Sdfr int ch, int count) 158643105Sdfr{ 158743105Sdfr#ifndef VGA_NO_FONT_LOADING 158843105Sdfr u_char buf[PARAM_BUFSIZE]; 158943105Sdfr u_int32_t segment; 159043105Sdfr int c; 159143105Sdfr#ifdef VGA_ALT_SEQACCESS 159243105Sdfr int s; 159343105Sdfr u_char val = 0; 159443105Sdfr#endif 159543105Sdfr 159643105Sdfr prologue(adp, V_ADP_FONT, 1); 159743105Sdfr 159843105Sdfr if (fontsize < 14) { 159943105Sdfr /* FONT_8 */ 160043105Sdfr fontsize = 8; 160143105Sdfr } else if (fontsize >= 32) { 160243105Sdfr fontsize = 32; 160343105Sdfr } else if (fontsize >= 16) { 160443105Sdfr /* FONT_16 */ 160543105Sdfr fontsize = 16; 160643105Sdfr } else { 160743105Sdfr /* FONT_14 */ 160843105Sdfr fontsize = 14; 160943105Sdfr } 161043105Sdfr 161143105Sdfr if (page < 0 || page >= 8) 161243105Sdfr return 1; 161343105Sdfr segment = FONT_BUF + 0x4000*page; 161443105Sdfr if (page > 3) 161543105Sdfr segment -= 0xe000; 161643105Sdfr 161743105Sdfr#ifdef VGA_ALT_SEQACCESS 161843105Sdfr if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ 161943105Sdfr s = splhigh(); 162043105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); 162143105Sdfr outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 162243105Sdfr outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 162343105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); 162443105Sdfr splx(s); 162543105Sdfr } 162643105Sdfr#endif 162743105Sdfr 162843105Sdfr set_font_mode(adp, buf); 162943105Sdfr if (fontsize == 32) { 163043105Sdfr bcopy_fromio(segment + ch*32, data, fontsize*count); 163143105Sdfr } else { 163243105Sdfr for (c = ch; count > 0; ++c, --count) { 163343105Sdfr bcopy_fromio(segment + c*32, data, fontsize); 163443105Sdfr data += fontsize; 163543105Sdfr } 163643105Sdfr } 163743105Sdfr set_normal_mode(adp, buf); 163843105Sdfr 163943105Sdfr#ifdef VGA_ALT_SEQACCESS 164043105Sdfr if (adp->va_type == KD_VGA) { 164143105Sdfr s = splhigh(); 164243105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); 164343105Sdfr outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ 164443105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); 164543105Sdfr splx(s); 164643105Sdfr } 164743105Sdfr#endif 164843105Sdfr 164943105Sdfr return 0; 165043105Sdfr#else /* VGA_NO_FONT_LOADING */ 165143105Sdfr return 1; 165243105Sdfr#endif /* VGA_NO_FONT_LOADING */ 165343105Sdfr} 165443105Sdfr 165543105Sdfr/* 165643105Sdfr * load_font(): 165743105Sdfr * Set the font data in the requested font page. 165843105Sdfr * NOTE: it appears that some recent video adapters do not support 165943105Sdfr * the font page other than 0... XXX 166043105Sdfr * 166143105Sdfr * EGA/VGA 166243105Sdfr */ 166343105Sdfrstatic int 166443105Sdfrvga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 166543105Sdfr int ch, int count) 166643105Sdfr{ 166743105Sdfr#ifndef VGA_NO_FONT_LOADING 166843105Sdfr u_char buf[PARAM_BUFSIZE]; 166943105Sdfr u_int32_t segment; 167043105Sdfr int c; 167143105Sdfr#ifdef VGA_ALT_SEQACCESS 167243105Sdfr int s; 167343105Sdfr u_char val = 0; 167443105Sdfr#endif 167543105Sdfr 167643105Sdfr prologue(adp, V_ADP_FONT, 1); 167743105Sdfr 167843105Sdfr if (fontsize < 14) { 167943105Sdfr /* FONT_8 */ 168043105Sdfr fontsize = 8; 168143105Sdfr } else if (fontsize >= 32) { 168243105Sdfr fontsize = 32; 168343105Sdfr } else if (fontsize >= 16) { 168443105Sdfr /* FONT_16 */ 168543105Sdfr fontsize = 16; 168643105Sdfr } else { 168743105Sdfr /* FONT_14 */ 168843105Sdfr fontsize = 14; 168943105Sdfr } 169043105Sdfr 169143105Sdfr if (page < 0 || page >= 8) 169243105Sdfr return 1; 169343105Sdfr segment = FONT_BUF + 0x4000*page; 169443105Sdfr if (page > 3) 169543105Sdfr segment -= 0xe000; 169643105Sdfr 169743105Sdfr#ifdef VGA_ALT_SEQACCESS 169843105Sdfr if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ 169943105Sdfr s = splhigh(); 170043105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); 170143105Sdfr outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 170243105Sdfr outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 170343105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); 170443105Sdfr splx(s); 170543105Sdfr } 170643105Sdfr#endif 170743105Sdfr 170843105Sdfr set_font_mode(adp, buf); 170943105Sdfr if (fontsize == 32) { 171043105Sdfr bcopy_toio(data, segment + ch*32, fontsize*count); 171143105Sdfr } else { 171243105Sdfr for (c = ch; count > 0; ++c, --count) { 171343105Sdfr bcopy_toio(data, segment + c*32, fontsize); 171443105Sdfr data += fontsize; 171543105Sdfr } 171643105Sdfr } 171743105Sdfr set_normal_mode(adp, buf); 171843105Sdfr 171943105Sdfr#ifdef VGA_ALT_SEQACCESS 172043105Sdfr if (adp->va_type == KD_VGA) { 172143105Sdfr s = splhigh(); 172243105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); 172343105Sdfr outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ 172443105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); 172543105Sdfr splx(s); 172643105Sdfr } 172743105Sdfr#endif 172843105Sdfr 172943105Sdfr return 0; 173043105Sdfr#else /* VGA_NO_FONT_LOADING */ 173143105Sdfr return 1; 173243105Sdfr#endif /* VGA_NO_FONT_LOADING */ 173343105Sdfr} 173443105Sdfr 173543105Sdfr/* 173643105Sdfr * show_font(): 173743105Sdfr * Activate the requested font page. 173843105Sdfr * NOTE: it appears that some recent video adapters do not support 173943105Sdfr * the font page other than 0... XXX 174043105Sdfr * 174143105Sdfr * EGA/VGA 174243105Sdfr */ 174343105Sdfrstatic int 174443105Sdfrvga_show_font(video_adapter_t *adp, int page) 174543105Sdfr{ 174643105Sdfr#ifndef VGA_NO_FONT_LOADING 174743105Sdfr static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f }; 174843105Sdfr int s; 174943105Sdfr 175043105Sdfr prologue(adp, V_ADP_FONT, 1); 175143105Sdfr if (page < 0 || page >= 8) 175243105Sdfr return 1; 175343105Sdfr 175443105Sdfr s = splhigh(); 175543105Sdfr outb(TSIDX, 0x03); outb(TSREG, cg[page]); 175643105Sdfr splx(s); 175743105Sdfr 175843105Sdfr return 0; 175943105Sdfr#else /* VGA_NO_FONT_LOADING */ 176043105Sdfr return 1; 176143105Sdfr#endif /* VGA_NO_FONT_LOADING */ 176243105Sdfr} 176343105Sdfr 176443105Sdfr/* 176543105Sdfr * save_palette(): 176643105Sdfr * Read DAC values. The values have expressed in 8 bits. 176743105Sdfr * 176843105Sdfr * VGA 176943105Sdfr */ 177043105Sdfrstatic int 177143105Sdfrvga_save_palette(video_adapter_t *adp, u_char *palette) 177243105Sdfr{ 177343105Sdfr int i; 177443105Sdfr 177543105Sdfr prologue(adp, V_ADP_PALETTE, 1); 177643105Sdfr 177743105Sdfr /* 177843105Sdfr * We store 8 bit values in the palette buffer, while the standard 177943105Sdfr * VGA has 6 bit DAC . 178043105Sdfr */ 178143105Sdfr outb(PALRADR, 0x00); 178243105Sdfr for (i = 0; i < 256*3; ++i) 178343105Sdfr palette[i] = inb(PALDATA) << 2; 178443105Sdfr inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 178543105Sdfr return 0; 178643105Sdfr} 178743105Sdfr 178843105Sdfr/* 178943105Sdfr * load_palette(): 179043105Sdfr * Set DAC values. 179143105Sdfr * 179243105Sdfr * VGA 179343105Sdfr */ 179443105Sdfrstatic int 179543105Sdfrvga_load_palette(video_adapter_t *adp, u_char *palette) 179643105Sdfr{ 179743105Sdfr int i; 179843105Sdfr 179943105Sdfr prologue(adp, V_ADP_PALETTE, 1); 180043105Sdfr 180143105Sdfr outb(PIXMASK, 0xff); /* no pixelmask */ 180243105Sdfr outb(PALWADR, 0x00); 180343105Sdfr for (i = 0; i < 256*3; ++i) 180443105Sdfr outb(PALDATA, palette[i] >> 2); 180543105Sdfr inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 180643105Sdfr outb(ATC, 0x20); /* enable palette */ 180743105Sdfr return 0; 180843105Sdfr} 180943105Sdfr 181043105Sdfr/* 181143105Sdfr * set_border(): 181243105Sdfr * Change the border color. 181343105Sdfr * 181443105Sdfr * CGA/EGA/VGA 181543105Sdfr */ 181643105Sdfrstatic int 181743105Sdfrvga_set_border(video_adapter_t *adp, int color) 181843105Sdfr{ 181943105Sdfr prologue(adp, V_ADP_BORDER, 1); 182043105Sdfr 182143105Sdfr switch (adp->va_type) { 182243105Sdfr case KD_EGA: 182343105Sdfr case KD_VGA: 182443105Sdfr inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 182543105Sdfr outb(ATC, 0x31); outb(ATC, color & 0xff); 182643105Sdfr break; 182743105Sdfr case KD_CGA: 182843105Sdfr outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */ 182943105Sdfr break; 183043105Sdfr case KD_MONO: 183143105Sdfr case KD_HERCULES: 183243105Sdfr default: 183343105Sdfr break; 183443105Sdfr } 183543105Sdfr return 0; 183643105Sdfr} 183743105Sdfr 183843105Sdfr/* 183943105Sdfr * save_state(): 184043105Sdfr * Read video register values. 184143105Sdfr * NOTE: this function only reads the standard EGA/VGA registers. 184243105Sdfr * any extra/extended registers of SVGA adapters are not saved. 184343105Sdfr * 184443105Sdfr * VGA 184543105Sdfr */ 184643105Sdfrstatic int 184743105Sdfrvga_save_state(video_adapter_t *adp, void *p, size_t size) 184843105Sdfr{ 184943105Sdfr video_info_t info; 185043105Sdfr u_char *buf; 185143105Sdfr int crtc_addr; 185243105Sdfr int i, j; 185343105Sdfr int s; 185443105Sdfr 185543105Sdfr if (size == 0) { 185643105Sdfr /* return the required buffer size */ 185743105Sdfr prologue(adp, V_ADP_STATESAVE, 0); 185843105Sdfr return sizeof(adp_state_t); 185943105Sdfr } else { 186043105Sdfr prologue(adp, V_ADP_STATESAVE, 1); 186143105Sdfr if (size < sizeof(adp_state_t)) 186243105Sdfr return 1; 186343105Sdfr } 186443105Sdfr 186543105Sdfr ((adp_state_t *)p)->sig = V_STATE_SIG; 186643105Sdfr buf = ((adp_state_t *)p)->regs; 186743105Sdfr bzero(buf, V_MODE_PARAM_SIZE); 186843105Sdfr crtc_addr = adp->va_crtc_addr; 186943105Sdfr 187043105Sdfr s = splhigh(); 187143105Sdfr 187243105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 187343105Sdfr for (i = 0, j = 5; i < 4; i++) { 187443105Sdfr outb(TSIDX, i + 1); 187543105Sdfr buf[j++] = inb(TSREG); 187643105Sdfr } 187743105Sdfr buf[9] = inb(MISC + 10); /* dot-clock */ 187843105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 187943105Sdfr 188043105Sdfr for (i = 0, j = 10; i < 25; i++) { /* crtc */ 188143105Sdfr outb(crtc_addr, i); 188243105Sdfr buf[j++] = inb(crtc_addr + 1); 188343105Sdfr } 188443105Sdfr for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */ 188543105Sdfr inb(crtc_addr + 6); /* reset flip-flop */ 188643105Sdfr outb(ATC, i); 188743105Sdfr buf[j++] = inb(ATC + 1); 188843105Sdfr } 188943105Sdfr for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */ 189043105Sdfr outb(GDCIDX, i); 189143105Sdfr buf[j++] = inb(GDCREG); 189243105Sdfr } 189343105Sdfr inb(crtc_addr + 6); /* reset flip-flop */ 189443105Sdfr outb(ATC, 0x20); /* enable palette */ 189543105Sdfr 189643105Sdfr splx(s); 189743105Sdfr 189843105Sdfr#if 1 189943105Sdfr if (vga_get_info(adp, adp->va_mode, &info) == 0) { 190043105Sdfr if (info.vi_flags & V_INFO_GRAPHICS) { 190143105Sdfr buf[0] = info.vi_width/info.vi_cwidth; /* COLS */ 190243105Sdfr buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */ 190343105Sdfr } else { 190443105Sdfr buf[0] = info.vi_width; /* COLS */ 190543105Sdfr buf[1] = info.vi_height - 1; /* ROWS */ 190643105Sdfr } 190743105Sdfr buf[2] = info.vi_cheight; /* POINTS */ 190843105Sdfr } else { 190943105Sdfr /* XXX: shouldn't be happening... */ 191043105Sdfr printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n", 191143105Sdfr adp->va_unit, adp->va_name); 191243105Sdfr } 191343105Sdfr#else 191443105Sdfr buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */ 191543105Sdfr buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */ 191643105Sdfr buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */ 191743105Sdfr buf[3] = readb(BIOS_PADDRTOVADDR(0x44c)); 191843105Sdfr buf[4] = readb(BIOS_PADDRTOVADDR(0x44d)); 191943105Sdfr#endif 192043105Sdfr 192143105Sdfr return 0; 192243105Sdfr} 192343105Sdfr 192443105Sdfr/* 192543105Sdfr * load_state(): 192643105Sdfr * Set video registers at once. 192743105Sdfr * NOTE: this function only updates the standard EGA/VGA registers. 192843105Sdfr * any extra/extended registers of SVGA adapters are not changed. 192943105Sdfr * 193043105Sdfr * EGA/VGA 193143105Sdfr */ 193243105Sdfrstatic int 193343105Sdfrvga_load_state(video_adapter_t *adp, void *p) 193443105Sdfr{ 193543105Sdfr u_char *buf; 193643105Sdfr int crtc_addr; 193743105Sdfr int s; 193843105Sdfr int i; 193943105Sdfr 194043105Sdfr prologue(adp, V_ADP_STATELOAD, 1); 194143105Sdfr if (((adp_state_t *)p)->sig != V_STATE_SIG) 194243105Sdfr return 1; 194343105Sdfr 194443105Sdfr buf = ((adp_state_t *)p)->regs; 194543105Sdfr crtc_addr = adp->va_crtc_addr; 194643105Sdfr 194743105Sdfr s = splhigh(); 194843105Sdfr 194943105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 195043105Sdfr for (i = 0; i < 4; ++i) { /* program sequencer */ 195143105Sdfr outb(TSIDX, i + 1); 195243105Sdfr outb(TSREG, buf[i + 5]); 195343105Sdfr } 195443105Sdfr outb(MISC, buf[9]); /* set dot-clock */ 195543105Sdfr outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 195643105Sdfr outb(crtc_addr, 0x11); 195743105Sdfr outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F); 195843105Sdfr for (i = 0; i < 25; ++i) { /* program crtc */ 195943105Sdfr outb(crtc_addr, i); 196043105Sdfr outb(crtc_addr + 1, buf[i + 10]); 196143105Sdfr } 196243105Sdfr inb(crtc_addr+6); /* reset flip-flop */ 196343105Sdfr for (i = 0; i < 20; ++i) { /* program attribute ctrl */ 196443105Sdfr outb(ATC, i); 196543105Sdfr outb(ATC, buf[i + 35]); 196643105Sdfr } 196743105Sdfr for (i = 0; i < 9; ++i) { /* program graph data ctrl */ 196843105Sdfr outb(GDCIDX, i); 196943105Sdfr outb(GDCREG, buf[i + 55]); 197043105Sdfr } 197143105Sdfr inb(crtc_addr + 6); /* reset flip-flop */ 197243105Sdfr outb(ATC, 0x20); /* enable palette */ 197343105Sdfr 197443105Sdfr#ifndef VGA_NO_BIOS 197543105Sdfr if (adp->va_unit == V_ADP_PRIMARY) { 197643105Sdfr writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */ 197743105Sdfr writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */ 197843105Sdfr writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */ 197943105Sdfr#if 0 198043105Sdfr writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]); 198143105Sdfr writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]); 198243105Sdfr#endif 198343105Sdfr } 198443105Sdfr#endif /* VGA_NO_BIOS */ 198543105Sdfr 198643105Sdfr splx(s); 198743105Sdfr return 0; 198843105Sdfr} 198943105Sdfr 199043105Sdfr/* 199143105Sdfr * set_origin(): 199243105Sdfr * Change the origin (window mapping) of the banked frame buffer. 199343105Sdfr */ 199443105Sdfrstatic int 199543105Sdfrvga_set_origin(video_adapter_t *adp, off_t offset) 199643105Sdfr{ 199743105Sdfr /* 199843105Sdfr * The standard video modes do not require window mapping; 199943105Sdfr * always return error. 200043105Sdfr */ 200143105Sdfr return 1; 200243105Sdfr} 200343105Sdfr 200443105Sdfr/* 200543105Sdfr * read_hw_cursor(): 200643105Sdfr * Read the position of the hardware text cursor. 200743105Sdfr * 200843105Sdfr * all adapters 200943105Sdfr */ 201043105Sdfrstatic int 201143105Sdfrvga_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 201243105Sdfr{ 201343105Sdfr video_info_t info; 201443105Sdfr u_int16_t off; 201543105Sdfr int s; 201643105Sdfr 201743105Sdfr if (!init_done) 201843105Sdfr return 1; 201943105Sdfr 202043105Sdfr (*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info); 202143105Sdfr if (info.vi_flags & V_INFO_GRAPHICS) 202243105Sdfr return 1; 202343105Sdfr 202443105Sdfr s = spltty(); 202543105Sdfr outb(adp->va_crtc_addr, 14); 202643105Sdfr off = inb(adp->va_crtc_addr + 1); 202743105Sdfr outb(adp->va_crtc_addr, 15); 202843105Sdfr off = (off << 8) | inb(adp->va_crtc_addr + 1); 202943105Sdfr splx(s); 203043105Sdfr 203143105Sdfr *row = off / info.vi_width; 203243105Sdfr *col = off % info.vi_width; 203343105Sdfr 203443105Sdfr return 0; 203543105Sdfr} 203643105Sdfr 203743105Sdfr/* 203843105Sdfr * set_hw_cursor(): 203943105Sdfr * Move the hardware text cursor. If col and row are both -1, 204043105Sdfr * the cursor won't be shown. 204143105Sdfr * 204243105Sdfr * all adapters 204343105Sdfr */ 204443105Sdfrstatic int 204543105Sdfrvga_set_hw_cursor(video_adapter_t *adp, int col, int row) 204643105Sdfr{ 204743105Sdfr video_info_t info; 204843105Sdfr u_int16_t off; 204943105Sdfr int s; 205043105Sdfr 205143105Sdfr if (!init_done) 205243105Sdfr return 1; 205343105Sdfr 205443105Sdfr if ((col == -1) && (row == -1)) { 205543105Sdfr off = -1; 205643105Sdfr } else { 205743105Sdfr (*vidsw[adp->va_index]->get_info)(adp, adp->va_mode, &info); 205843105Sdfr if (info.vi_flags & V_INFO_GRAPHICS) 205943105Sdfr return 1; 206043105Sdfr off = row*info.vi_width + col; 206143105Sdfr } 206243105Sdfr 206343105Sdfr s = spltty(); 206443105Sdfr outb(adp->va_crtc_addr, 14); 206543105Sdfr outb(adp->va_crtc_addr + 1, off >> 8); 206643105Sdfr outb(adp->va_crtc_addr, 15); 206743105Sdfr outb(adp->va_crtc_addr + 1, off & 0x00ff); 206843105Sdfr splx(s); 206943105Sdfr 207043105Sdfr return 0; 207143105Sdfr} 207243105Sdfr 207343105Sdfr/* 207443105Sdfr * set_hw_cursor_shape(): 207543105Sdfr * Change the shape of the hardware text cursor. If the height is 207643105Sdfr * zero or negative, the cursor won't be shown. 207743105Sdfr * 207843105Sdfr * all adapters 207943105Sdfr */ 208043105Sdfrstatic int 208143105Sdfrvga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 208243105Sdfr int celsize, int blink) 208343105Sdfr{ 208443105Sdfr int s; 208543105Sdfr 208643105Sdfr if (!init_done) 208743105Sdfr return 1; 208843105Sdfr 208943105Sdfr s = spltty(); 209043105Sdfr switch (adp->va_type) { 209143105Sdfr case KD_VGA: 209243105Sdfr case KD_CGA: 209343105Sdfr case KD_MONO: 209443105Sdfr case KD_HERCULES: 209543105Sdfr default: 209643105Sdfr if (height <= 0) { 209743105Sdfr /* make the cursor invisible */ 209843105Sdfr outb(adp->va_crtc_addr, 10); 209943105Sdfr outb(adp->va_crtc_addr + 1, 32); 210043105Sdfr outb(adp->va_crtc_addr, 11); 210143105Sdfr outb(adp->va_crtc_addr + 1, 0); 210243105Sdfr } else { 210343105Sdfr outb(adp->va_crtc_addr, 10); 210443105Sdfr outb(adp->va_crtc_addr + 1, celsize - base - height); 210543105Sdfr outb(adp->va_crtc_addr, 11); 210643105Sdfr outb(adp->va_crtc_addr + 1, celsize - base - 1); 210743105Sdfr } 210843105Sdfr break; 210943105Sdfr case KD_EGA: 211043105Sdfr if (height <= 0) { 211143105Sdfr /* make the cursor invisible */ 211243105Sdfr outb(adp->va_crtc_addr, 10); 211343105Sdfr outb(adp->va_crtc_addr + 1, celsize); 211443105Sdfr outb(adp->va_crtc_addr, 11); 211543105Sdfr outb(adp->va_crtc_addr + 1, 0); 211643105Sdfr } else { 211743105Sdfr outb(adp->va_crtc_addr, 10); 211843105Sdfr outb(adp->va_crtc_addr + 1, celsize - base - height); 211943105Sdfr outb(adp->va_crtc_addr, 11); 212043105Sdfr outb(adp->va_crtc_addr + 1, celsize - base); 212143105Sdfr } 212243105Sdfr break; 212343105Sdfr } 212443105Sdfr splx(s); 212543105Sdfr 212643105Sdfr return 0; 212743105Sdfr} 212843105Sdfr 212943105Sdfr/* 213043105Sdfr * mmap(): 213143105Sdfr * Mmap frame buffer. 213243105Sdfr * 213343105Sdfr * all adapters 213443105Sdfr */ 213543105Sdfrstatic int 213643105Sdfrvga_mmap(video_adapter_t *adp, vm_offset_t offset) 213743105Sdfr{ 213843105Sdfr if (offset > 0x20000 - PAGE_SIZE) 213943105Sdfr return -1; 214043105Sdfr#ifdef __i386__ 214143105Sdfr return i386_btop((VIDEO_BUF_BASE + offset)); 214243105Sdfr#endif 214343105Sdfr#ifdef __alpha__ 214443105Sdfr return alpha_btop((VIDEO_BUF_BASE + offset)); 214543105Sdfr#endif 214643105Sdfr} 214743105Sdfr 214843105Sdfrstatic void 214943105Sdfrdump_buffer(u_char *buf, size_t len) 215043105Sdfr{ 215143105Sdfr int i; 215243105Sdfr 215343105Sdfr for(i = 0; i < len;) { 215443105Sdfr printf("%02x ", buf[i]); 215543105Sdfr if ((++i % 16) == 0) 215643105Sdfr printf("\n"); 215743105Sdfr } 215843105Sdfr} 215943105Sdfr 216043105Sdfr/* 216143105Sdfr * diag(): 216243105Sdfr * Print some information about the video adapter and video modes, 216343105Sdfr * with requested level of details. 216443105Sdfr * 216543105Sdfr * all adapters 216643105Sdfr */ 216743105Sdfrstatic int 216843105Sdfrvga_diag(video_adapter_t *adp, int level) 216943105Sdfr{ 217043105Sdfr#if FB_DEBUG > 1 217143105Sdfr video_info_t info; 217243105Sdfr#endif 217343105Sdfr u_char *mp; 217443105Sdfr 217543105Sdfr if (!init_done) 217643105Sdfr return 1; 217743105Sdfr 217843105Sdfr#if FB_DEBUG > 1 217943105Sdfr#ifndef VGA_NO_BIOS 218043105Sdfr printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n", 218143105Sdfr rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488))); 218243105Sdfr printf("vga: CRTC:0x%x, video option:0x%02x, ", 218343105Sdfr readw(BIOS_PADDRTOVADDR(0x463)), 218443105Sdfr readb(BIOS_PADDRTOVADDR(0x487))); 218543105Sdfr printf("rows:%d, cols:%d, font height:%d\n", 218643105Sdfr readb(BIOS_PADDRTOVADDR(0x44a)), 218743105Sdfr readb(BIOS_PADDRTOVADDR(0x484)) + 1, 218843105Sdfr readb(BIOS_PADDRTOVADDR(0x485))); 218943105Sdfr#endif /* VGA_NO_BIOS */ 219043105Sdfr printf("vga: param table EGA/VGA:%p", video_mode_ptr); 219143105Sdfr printf(", CGA/MDA:%p\n", video_mode_ptr2); 219243105Sdfr printf("vga: rows_offset:%d\n", rows_offset); 219343105Sdfr#endif /* FB_DEBUG > 1 */ 219443105Sdfr 219543105Sdfr fb_dump_adp_info(DRIVER_NAME, adp, level); 219643105Sdfr 219743105Sdfr#if FB_DEBUG > 1 219843105Sdfr if (adp->va_flags & V_ADP_MODECHANGE) { 219943105Sdfr for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 220043105Sdfr if (bios_vmode[i].vi_mode == NA) 220143105Sdfr continue; 220243105Sdfr if (get_mode_param(bios_vmode[i].vi_mode) == NULL) 220343105Sdfr continue; 220443105Sdfr fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level); 220543105Sdfr } 220643105Sdfr } else { 220743105Sdfr vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */ 220843105Sdfr fb_dump_mode_info(DRIVER_NAME, adp, &info, level); 220943105Sdfr } 221043105Sdfr#endif /* FB_DEBUG > 1 */ 221143105Sdfr 221243105Sdfr if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA)) 221343105Sdfr return 0; 221443105Sdfr#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 221543105Sdfr if (video_mode_ptr == NULL) 221643105Sdfr printf("vga%d: %s: WARNING: video mode switching is not " 221743105Sdfr "fully supported on this adapter\n", 221843105Sdfr adp->va_unit, adp->va_name); 221943105Sdfr#endif 222043105Sdfr if (level <= 0) 222143105Sdfr return 0; 222243105Sdfr 222343105Sdfr if (adp->va_type == KD_VGA) { 222443105Sdfr printf("VGA parameters upon power-up\n"); 222543105Sdfr dump_buffer(adpstate.regs, sizeof(adpstate.regs)); 222643105Sdfr printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode); 222743105Sdfr dump_buffer(adpstate2.regs, sizeof(adpstate2.regs)); 222843105Sdfr } 222943105Sdfr 223043105Sdfr mp = get_mode_param(adp->va_initial_mode); 223143105Sdfr if (mp == NULL) /* this shouldn't be happening */ 223243105Sdfr return 0; 223343105Sdfr printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode); 223443105Sdfr dump_buffer(mp, V_MODE_PARAM_SIZE); 223543105Sdfr 223643105Sdfr return 0; 223743105Sdfr} 223843105Sdfr 223943105Sdfr#endif /* NVGA > 0 */ 2240