vga_isa.c revision 46743
1138323Swollman/*- 22742Swollman * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 32742Swollman * Copyright (c) 1992-1998 S�ren Schmidt 42742Swollman * All rights reserved. 52742Swollman * 62742Swollman * Redistribution and use in source and binary forms, with or without 72742Swollman * modification, are permitted provided that the following conditions 858787Sru * are met: 92742Swollman * 1. Redistributions of source code must retain the above copyright 1058787Sru * notice, this list of conditions and the following disclaimer as 112742Swollman * the first lines of this file unmodified. 122742Swollman * 2. Redistributions in binary form must reproduce the above copyright 132742Swollman * notice, this list of conditions and the following disclaimer in the 142742Swollman * documentation and/or other materials provided with the distribution. 152742Swollman * 3. The name of the author may not be used to endorse or promote products 1658787Sru * derived from this software without specific prior written permission. 1758787Sru * 1858787Sru * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1958787Sru * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2058787Sru * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2158787Sru * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2258787Sru * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2358787Sru * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2458787Sru * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2558787Sru * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2658787Sru * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2714343Swollman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2814343Swollman * 2914343Swollman * $Id: vga_isa.c,v 1.6 1999/05/08 20:20:18 peter Exp $ 3014343Swollman */ 3114343Swollman 3214343Swollman#include "vga.h" 3314343Swollman#include "opt_vga.h" 3475267Swollman#include "opt_fb.h" 3517200Swollman#include "opt_syscons.h" /* should be removed in the future, XXX */ 3675267Swollman 3775267Swollman#if NVGA > 0 3817200Swollman 3917200Swollman#include <sys/param.h> 4017200Swollman#include <sys/systm.h> 4117200Swollman#include <sys/kernel.h> 4217200Swollman#include <sys/bus.h> 4317200Swollman#include <sys/malloc.h> 4417200Swollman 4517200Swollman#include <vm/vm.h> 4617200Swollman#include <vm/pmap.h> 4717200Swollman 4817200Swollman#include <machine/console.h> 4917200Swollman#include <machine/md_var.h> 5017200Swollman#include <machine/pc/bios.h> 5117200Swollman 5275267Swollman#include <dev/fb/fbreg.h> 5375267Swollman#include <dev/fb/vgareg.h> 5475267Swollman 5575267Swollman#if 1 5675267Swollman#include <isa/isareg.h> 5775267Swollman#include <isa/isavar.h> 5875267Swollman#else 5975267Swollman#include <i386/isa/isa.h> 6075267Swollman#include <i386/isa/isa_device.h> 6175267Swollman#endif 6217200Swollman 632742Swollman#define DRIVER_NAME "vga" 642742Swollman 6519878Swollman/* cdev driver declaration */ 6619878Swollman 672742Swollman#define ISAVGA_UNIT(dev) minor(dev) 682742Swollman#define ISAVGA_MKMINOR(unit) (unit) 692742Swollman 702742Swollmantypedef struct isavga_softc { 712742Swollman video_adapter_t *adp; 7267578Swollman} isavga_softc_t; 7367578Swollman 7467578Swollman#if 1 7567578Swollman 7667578Swollman#define ISAVGA_SOFTC(unit) \ 7767578Swollman ((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit)) 7867578Swollman 7967578Swollmandevclass_t isavga_devclass; 8067578Swollman 8167578Swollmanstatic int isavga_probe(device_t dev); 8267578Swollmanstatic int isavga_attach(device_t dev); 8367578Swollman 8486222Swollmanstatic device_method_t isavga_methods[] = { 8567578Swollman DEVMETHOD(device_probe, isavga_probe), 8667578Swollman DEVMETHOD(device_attach, isavga_attach), 8767578Swollman { 0, 0 } 8867578Swollman}; 8986222Swollman 9067578Swollmanstatic driver_t isavga_driver = { 91114173Swollman DRIVER_NAME, 92114173Swollman isavga_methods, 93114173Swollman sizeof(isavga_softc_t), 94114173Swollman}; 95114173Swollman 96114173SwollmanDRIVER_MODULE(vga, isa, isavga_driver, isavga_devclass, 0, 0); 97114173Swollman 98114173Swollman#else /* __i386__ */ 99114173Swollman 100114173Swollman#define ISAVGA_SOFTC(unit) (isavga_softc[unit]) 101114173Swollman 102114173Swollmanstatic isavga_softc_t *isavga_softc[NVGA]; 103114173Swollman 104114173Swollmanstatic int isavga_probe(struct isa_device *dev); 105114173Swollmanstatic int isavga_attach(struct isa_device *dev); 106114173Swollman 107114173Swollmanstruct isa_driver vgadriver = { 1082742Swollman isavga_probe, 10975267Swollman isavga_attach, 1102742Swollman DRIVER_NAME, 1112742Swollman 0, 11267578Swollman}; 1132742Swollman 1142742Swollman#endif /* __i386__ */ 1152742Swollman 1162742Swollmanstatic int isavga_probe_unit(int unit, isavga_softc_t *sc, 1172742Swollman int flags); 1182742Swollmanstatic int isavga_attach_unit(int unit, isavga_softc_t *sc, 1192742Swollman int flags); 12043543Swollman 12143543Swollman#ifdef FB_INSTALL_CDEV 12243543Swollman 1232742Swollmanstatic d_open_t isavgaopen; 12419878Swollmanstatic d_close_t isavgaclose; 1252742Swollmanstatic d_read_t isavgaread; 1262742Swollmanstatic d_ioctl_t isavgaioctl; 1272742Swollman 1282742Swollmanstatic struct cdevsw vga_cdevsw = { 1292742Swollman isavgaopen, isavgaclose, noread, nowrite, /* ?? */ 1302742Swollman isavgaioctl, nostop, nullreset, nodevtotty, 1312742Swollman seltrue, nommap, NULL, DRIVER_NAME, 1322742Swollman NULL, -1, nodump, nopsize, 1332742Swollman}; 1342742Swollman 1352742Swollman#endif /* FB_INSTALL_CDEV */ 13614343Swollman 13714343Swollman#if 1 13814343Swollman 13914343Swollmanstatic int 14019878Swollmanisavga_probe(device_t dev) 1412742Swollman{ 1422742Swollman isavga_softc_t *sc; 1432742Swollman 1442742Swollman device_set_desc(dev, "Generic ISA VGA"); 1452742Swollman sc = device_get_softc(dev); 1462742Swollman return isavga_probe_unit(device_get_unit(dev), sc, isa_get_flags(dev)); 1472742Swollman} 1482742Swollman 1492742Swollmanstatic int 1502742Swollmanisavga_attach(device_t dev) 1512742Swollman{ 1522742Swollman isavga_softc_t *sc; 1532742Swollman 1542742Swollman sc = device_get_softc(dev); 1552742Swollman return isavga_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev)); 15619878Swollman} 1572742Swollman 1582742Swollman#else /* __i386__ */ 1592742Swollman 1602742Swollmanstatic int 1612742Swollmanisavga_probe(struct isa_device *dev) 16219878Swollman{ 1632742Swollman isavga_softc_t *sc; 1642742Swollman int error; 16519878Swollman 1662742Swollman if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) 1672742Swollman return 0; 1682742Swollman sc = isavga_softc[dev->id_unit] 1692742Swollman = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); 1702742Swollman if (sc == NULL) 1712742Swollman return 0; 1722742Swollman 1732742Swollman error = isavga_probe_unit(dev->id_unit, sc, dev->id_flags); 1742742Swollman if (error) { 17519878Swollman isavga_softc[dev->id_unit] = NULL; 1762742Swollman free(sc, M_DEVBUF); 1772742Swollman return 0; 1782742Swollman } 1792742Swollman 1802742Swollman dev->id_iobase = sc->adp->va_io_base; 1812742Swollman dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base); 1822742Swollman dev->id_msize = sc->adp->va_mem_size; 1832742Swollman 1842742Swollman return sc->adp->va_io_size; 18519878Swollman} 1862742Swollman 1872742Swollmanstatic int 1882742Swollmanisavga_attach(struct isa_device *dev) 1892742Swollman{ 1902742Swollman isavga_softc_t *sc; 1912742Swollman 1922742Swollman if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) 1932742Swollman return 0; 1942742Swollman sc = isavga_softc[dev->id_unit]; 19514343Swollman if (sc == NULL) 19675267Swollman return 0; 19775267Swollman 19875267Swollman return ((isavga_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1); 19975267Swollman} 2002742Swollman 20186464Swollman#endif /* __i386__ */ 20286222Swollman 20375267Swollmanstatic int 20467578Swollmanisavga_probe_unit(int unit, isavga_softc_t *sc, int flags) 205114173Swollman{ 206114173Swollman video_switch_t *sw; 207114173Swollman 208114173Swollman bzero(sc, sizeof(*sc)); 209114173Swollman sw = vid_get_switch(DRIVER_NAME); 21067578Swollman if (sw == NULL) 21114343Swollman return 0; 21214343Swollman return (*sw->probe)(unit, &sc->adp, NULL, flags); 21314343Swollman} 21414343Swollman 21514343Swollmanstatic int 21614343Swollmanisavga_attach_unit(int unit, isavga_softc_t *sc, int flags) 21714343Swollman{ 21814343Swollman video_switch_t *sw; 21914343Swollman int error; 22014343Swollman 22114343Swollman sw = vid_get_switch(DRIVER_NAME); 22214343Swollman if (sw == NULL) 22314343Swollman return ENXIO; 2242742Swollman 22586222Swollman error = (*sw->init)(unit, sc->adp, flags); 22667578Swollman if (error) 227136638Swollman return ENXIO; 228136638Swollman 229136638Swollman#ifdef FB_INSTALL_CDEV 230114173Swollman /* attach a virtual frame buffer device */ 231114173Swollman error = fb_attach(makedev(0, ISAVGA_MKMINOR(unit)), scp->adp, 232114173Swollman &vga_cdevsw); 233114173Swollman if (error) 234114173Swollman return error; 23567578Swollman#endif /* FB_INSTALL_CDEV */ 23614343Swollman 23714343Swollman if (bootverbose) 23814343Swollman (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose); 23914343Swollman 24014343Swollman return 0; 24114343Swollman} 24214343Swollman 24314343Swollman/* LOW-LEVEL */ 24414343Swollman 24514343Swollman#include <machine/clock.h> 24614343Swollman#include <machine/pc/vesa.h> 24714343Swollman 24814343Swollman#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED) 24914343Swollman#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED) 25014343Swollman#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED) 25114343Swollman 25286222Swollman/* for compatibility with old kernel options */ 25386222Swollman#ifdef SC_ALT_SEQACCESS 25486222Swollman#undef SC_ALT_SEQACCESS 25586222Swollman#undef VGA_ALT_SEQACCESS 2562742Swollman#define VGA_ALT_SEQACCESS 1 25786222Swollman#endif 25867578Swollman 259136638Swollman#ifdef SLOW_VGA 26086222Swollman#undef SLOW_VGA 26186222Swollman#undef VGA_SLOW_IOACCESS 26275267Swollman#define VGA_SLOW_IOACCESS 1 26375267Swollman#endif 26467578Swollman 26514343Swollman/* architecture dependent option */ 26614343Swollman#ifdef __alpha__ 26714343Swollman#define VGA_NO_BIOS 1 26814343Swollman#endif 26914343Swollman 27014343Swollman/* this should really be in `rtc.h' */ 2712742Swollman#define RTC_EQUIPMENT 0x14 27214343Swollman 27315309Swollman/* various sizes */ 27415309Swollman#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1) 27515309Swollman#define V_MODE_PARAM_SIZE 64 27615309Swollman 27715309Swollman/* video adapter state buffer */ 2782742Swollmanstruct adp_state { 27914343Swollman int sig; 28067578Swollman#define V_STATE_SIG 0x736f6962 281136638Swollman u_char regs[V_MODE_PARAM_SIZE]; 282136638Swollman}; 283136638Swollmantypedef struct adp_state adp_state_t; 28467578Swollman 28514343Swollman/* video adapter information */ 28614343Swollman#define DCC_MONO 0 28714343Swollman#define DCC_CGA40 1 28814343Swollman#define DCC_CGA80 2 28914343Swollman#define DCC_EGAMONO 3 29014343Swollman#define DCC_EGA40 4 29114343Swollman#define DCC_EGA80 5 29214343Swollman 29314343Swollman/* 29414343Swollman * NOTE: `va_window' should have a virtual address, but is initialized 29514343Swollman * with a physical address in the following table, as verify_adapter() 2968029Swollman * will perform address conversion at run-time. 29714343Swollman */ 29814343Swollmanstatic video_adapter_t adapter_init_value[] = { 29914343Swollman /* DCC_MONO */ 30086222Swollman { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC, 30114343Swollman MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 30219878Swollman 0, 0, 0, 7, 0, }, 30375267Swollman /* DCC_CGA40 */ 30475267Swollman { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, 30575267Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 30675267Swollman 0, 0, 0, 3, 0, }, 30714343Swollman /* DCC_CGA80 */ 30886222Swollman { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, 30986222Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 31086222Swollman 0, 0, 0, 3, 0, }, 31186222Swollman /* DCC_EGAMONO */ 31286222Swollman { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC, 31386222Swollman EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 31486222Swollman 0, 0, 0, 7, 0, }, 31514343Swollman /* DCC_EGA40 */ 31675267Swollman { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, 31775267Swollman EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 31814343Swollman 0, 0, 0, 3, 0, }, 31914343Swollman /* DCC_EGA80 */ 32014343Swollman { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, 32114343Swollman EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 322136638Swollman 0, 0, 0, 3, 0, }, 32314343Swollman}; 32475267Swollman 32575267Swollmanstatic video_adapter_t biosadapter[2]; 32614343Swollmanstatic int biosadapters = 0; 32714343Swollman 32814343Swollman/* video driver declarations */ 329136638Swollmanstatic int vga_configure(int flags); 33014343Swollman int (*vga_sub_configure)(int flags); 33175267Swollmanstatic int vga_nop(void); 33275267Swollmanstatic vi_probe_t vga_probe; 33314343Swollmanstatic vi_init_t vga_init; 33414343Swollmanstatic vi_get_info_t vga_get_info; 33514343Swollmanstatic vi_query_mode_t vga_query_mode; 33614343Swollmanstatic vi_set_mode_t vga_set_mode; 33714343Swollmanstatic vi_save_font_t vga_save_font; 338136638Swollmanstatic vi_load_font_t vga_load_font; 33914343Swollmanstatic vi_show_font_t vga_show_font; 34075267Swollmanstatic vi_save_palette_t vga_save_palette; 34175267Swollmanstatic vi_load_palette_t vga_load_palette; 34214343Swollmanstatic vi_set_border_t vga_set_border; 34314343Swollmanstatic vi_save_state_t vga_save_state; 34414343Swollmanstatic vi_load_state_t vga_load_state; 34514343Swollmanstatic vi_set_win_org_t vga_set_origin; 34614343Swollmanstatic vi_read_hw_cursor_t vga_read_hw_cursor; 347136638Swollmanstatic vi_set_hw_cursor_t vga_set_hw_cursor; 34814343Swollmanstatic vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape; 34975267Swollmanstatic vi_mmap_t vga_mmap; 35075267Swollmanstatic vi_diag_t vga_diag; 35114343Swollman 35214343Swollmanstatic video_switch_t vgavidsw = { 35314343Swollman vga_probe, 35414343Swollman vga_init, 35514343Swollman vga_get_info, 356136638Swollman vga_query_mode, 35714343Swollman vga_set_mode, 35814343Swollman vga_save_font, 35914343Swollman vga_load_font, 36014343Swollman vga_show_font, 36114343Swollman vga_save_palette, 3622742Swollman vga_load_palette, 36314343Swollman vga_set_border, 36414343Swollman vga_save_state, 36514343Swollman vga_load_state, 36614343Swollman vga_set_origin, 36714343Swollman vga_read_hw_cursor, 36814343Swollman vga_set_hw_cursor, 36914343Swollman vga_set_hw_cursor_shape, 37014343Swollman (vi_blank_display_t *)vga_nop, 37114343Swollman vga_mmap, 37214343Swollman vga_diag, 37314343Swollman}; 37414343Swollman 37514343SwollmanVIDEO_DRIVER(mda, vgavidsw, NULL); 37614343SwollmanVIDEO_DRIVER(cga, vgavidsw, NULL); 37714343SwollmanVIDEO_DRIVER(ega, vgavidsw, NULL); 37814343SwollmanVIDEO_DRIVER(vga, vgavidsw, vga_configure); 3792742Swollman 38014343Swollman/* VGA BIOS standard video modes */ 38114343Swollman#define EOT (-1) 38214343Swollman#define NA (-2) 383114173Swollman 384114173Swollmanstatic video_info_t bios_vmode[] = { 385114173Swollman /* CGA */ 386114173Swollman { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1, 387114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 388114173Swollman { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1, 389114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 390114173Swollman { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1, 391114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 392114173Swollman { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1, 393114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 394114173Swollman /* EGA */ 395114173Swollman { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, 396114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 397114173Swollman { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, 398114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 399114173Swollman { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, 400114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 401114173Swollman { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, 402114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 40314343Swollman /* VGA */ 40414343Swollman { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, 405114173Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 40614343Swollman { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1, 40714343Swollman MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 408114173Swollman { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, 40914343Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 41019878Swollman /* MDA */ 41114343Swollman { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1, 412136638Swollman MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 4132742Swollman /* EGA */ 4142742Swollman { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1, 4152742Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 4162742Swollman { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1, 41714343Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 4182742Swollman /* VGA */ 419136638Swollman { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1, 420136638Swollman MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 421136638Swollman { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, 422136638Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 423136638Swollman { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1, 424136638Swollman MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 425136638Swollman { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1, 42614343Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 42714343Swollman { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1, 42814343Swollman MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, 42914343Swollman { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1, 43014343Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 43114343Swollman#ifndef VGA_NO_MODE_CHANGE 4322742Swollman /* CGA */ 43314343Swollman { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, 43414343Swollman CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 43558787Sru { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, 43658787Sru CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 43758787Sru { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1, 43858787Sru CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, 43958787Sru /* EGA */ 44014343Swollman { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4, 44114343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 44214343Swollman { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4, 44314343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 44414343Swollman { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 44514343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 }, 44614343Swollman { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 44714343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 44814343Swollman { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2, 44914343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45014343Swollman { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 45114343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45214343Swollman /* VGA */ 45314343Swollman { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, 45414343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45514343Swollman { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, 45614343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45714343Swollman { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1, 45814343Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 45975267Swollman { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 1, 46075267Swollman GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, 46175267Swollman#endif /* VGA_NO_MODE_CHANGE */ 46275267Swollman 46375267Swollman { EOT }, 46486222Swollman}; 46575267Swollman 46614343Swollmanstatic int init_done = FALSE; 46714343Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 46814343Swollmanstatic u_char *video_mode_ptr = NULL; /* EGA/VGA */ 46914343Swollmanstatic u_char *video_mode_ptr2 = NULL; /* CGA/MDA */ 47014343Swollman#endif 47114343Swollmanstatic u_char *mode_map[V_MODE_MAP_SIZE]; 47214343Swollmanstatic adp_state_t adpstate; 47314343Swollmanstatic adp_state_t adpstate2; 47414343Swollmanstatic int rows_offset = 1; 47514343Swollman 47614343Swollman/* local macros and functions */ 47714343Swollman#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) 47814343Swollman 47914343Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 48014343Swollmanstatic void map_mode_table(u_char *map[], u_char *table, int max); 48114343Swollman#endif 4822742Swollmanstatic void clear_mode_map(video_adapter_t *adp, u_char *map[], int max, 48314343Swollman int color); 48414343Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 48514343Swollmanstatic int map_mode_num(int mode); 48614343Swollman#endif 48714343Swollmanstatic int map_gen_mode_num(int type, int color, int mode); 48814343Swollmanstatic int map_bios_mode_num(int type, int color, int bios_mode); 48914343Swollmanstatic u_char *get_mode_param(int mode); 49014343Swollman#ifndef VGA_NO_BIOS 49114343Swollmanstatic void fill_adapter_param(int code, video_adapter_t *adp); 49214343Swollman#endif 49314343Swollmanstatic int verify_adapter(video_adapter_t *adp); 49414343Swollmanstatic void update_adapter_info(video_adapter_t *adp, video_info_t *info); 49514343Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 49614343Swollman#define COMP_IDENTICAL 0 49714343Swollman#define COMP_SIMILAR 1 49814343Swollman#define COMP_DIFFERENT 2 49914343Swollmanstatic int comp_adpregs(u_char *buf1, u_char *buf2); 50014343Swollman#endif 50119878Swollmanstatic int probe_adapters(void); 50219878Swollman 50314343Swollman#ifndef VGA_NO_FONT_LOADING 50419878Swollman#define PARAM_BUFSIZE 6 50514343Swollmanstatic void set_font_mode(video_adapter_t *adp, u_char *buf); 50614343Swollmanstatic void set_normal_mode(video_adapter_t *adp, u_char *buf); 50714343Swollman#endif 50814343Swollman 50914343Swollmanstatic void dump_buffer(u_char *buf, size_t len); 51014343Swollman 51114343Swollman#define ISMAPPED(pa, width) \ 51214343Swollman (((pa) <= (u_long)0x1000 - (width)) \ 51314343Swollman || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width))) 51414343Swollman 51514343Swollman#define prologue(adp, flag, err) \ 51614343Swollman if (!init_done || !((adp)->va_flags & (flag))) \ 51714343Swollman return (err) 51814343Swollman 51914343Swollman/* a backdoor for the console driver */ 52014343Swollmanstatic int 52114343Swollmanvga_configure(int flags) 52214343Swollman{ 52314343Swollman int i; 52414343Swollman 52514343Swollman probe_adapters(); 5262742Swollman for (i = 0; i < biosadapters; ++i) { 52714343Swollman if (!probe_done(&biosadapter[i])) 52867578Swollman continue; 52914343Swollman biosadapter[i].va_flags |= V_ADP_INITIALIZED; 53014343Swollman if (!config_done(&biosadapter[i])) { 53114343Swollman if (vid_register(&biosadapter[i]) < 0) 53214343Swollman continue; 53314343Swollman biosadapter[i].va_flags |= V_ADP_REGISTERED; 53414343Swollman } 53514343Swollman } 53614343Swollman if (vga_sub_configure != NULL) 53714343Swollman (*vga_sub_configure)(flags); 53814343Swollman 53914343Swollman return biosadapters; 54014343Swollman} 54114343Swollman 54214343Swollman/* local subroutines */ 54314343Swollman 54414343Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 54514343Swollman/* construct the mode parameter map */ 54614343Swollmanstatic void 54767578Swollmanmap_mode_table(u_char *map[], u_char *table, int max) 54867578Swollman{ 54958787Sru int i; 55058787Sru 55158787Sru for(i = 0; i < max; ++i) 55258787Sru map[i] = table + i*V_MODE_PARAM_SIZE; 55358787Sru for(; i < V_MODE_MAP_SIZE; ++i) 55458787Sru map[i] = NULL; 55558787Sru} 55658787Sru#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 55758787Sru 55858787Srustatic void 55958787Sruclear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color) 56058787Sru{ 56158787Sru video_info_t info; 56267578Swollman int i; 56367578Swollman 56467578Swollman /* 56567578Swollman * NOTE: we don't touch `bios_vmode[]' because it is shared 56675267Swollman * by all adapters. 56775267Swollman */ 56886222Swollman for(i = 0; i < max; ++i) { 56986222Swollman if (vga_get_info(adp, i, &info)) 57086222Swollman continue; 57186222Swollman if ((info.vi_flags & V_INFO_COLOR) != color) 57286222Swollman map[i] = NULL; 57386222Swollman } 574114173Swollman} 57567578Swollman 57667578Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 57767578Swollman/* map the non-standard video mode to a known mode number */ 57867578Swollmanstatic int 57967578Swollmanmap_mode_num(int mode) 5802742Swollman{ 58167578Swollman static struct { 58267578Swollman int from; 58367578Swollman int to; 58467578Swollman } mode_map[] = { 58567578Swollman { M_ENH_B80x43, M_ENH_B80x25 }, 58667578Swollman { M_ENH_C80x43, M_ENH_C80x25 }, 58767578Swollman { M_VGA_M80x30, M_VGA_M80x25 }, 58867578Swollman { M_VGA_C80x30, M_VGA_C80x25 }, 58967578Swollman { M_VGA_M80x50, M_VGA_M80x25 }, 59067578Swollman { M_VGA_C80x50, M_VGA_C80x25 }, 59186222Swollman { M_VGA_M80x60, M_VGA_M80x25 }, 59286222Swollman { M_VGA_C80x60, M_VGA_C80x25 }, 59386222Swollman { M_VGA_MODEX, M_VGA_CG320 }, 59486222Swollman }; 59586222Swollman int i; 59686222Swollman 59786222Swollman for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 59886222Swollman if (mode_map[i].from == mode) 59986222Swollman return mode_map[i].to; 60086222Swollman } 60186222Swollman return mode; 60286222Swollman} 60386222Swollman#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 60467578Swollman 60514343Swollman/* map a generic video mode to a known mode number */ 60614343Swollmanstatic int 60719878Swollmanmap_gen_mode_num(int type, int color, int mode) 60814343Swollman{ 60914343Swollman static struct { 61058787Sru int from; 61158787Sru int to_color; 61258787Sru int to_mono; 61358787Sru } mode_map[] = { 61414343Swollman { M_TEXT_80x30, M_VGA_C80x30, M_VGA_M80x30, }, 61514343Swollman { M_TEXT_80x43, M_ENH_C80x43, M_ENH_B80x43, }, 61614343Swollman { M_TEXT_80x50, M_VGA_C80x50, M_VGA_M80x50, }, 61714343Swollman { M_TEXT_80x60, M_VGA_C80x60, M_VGA_M80x60, }, 61814343Swollman }; 61914343Swollman int i; 62014343Swollman 62114343Swollman if (mode == M_TEXT_80x25) { 62214343Swollman switch (type) { 62314343Swollman 62414343Swollman case KD_VGA: 62575267Swollman if (color) 62675267Swollman return M_VGA_C80x25; 62775267Swollman else 62875267Swollman return M_VGA_M80x25; 62975267Swollman break; 63014343Swollman 63114343Swollman case KD_EGA: 63214343Swollman if (color) 63314343Swollman return M_ENH_C80x25; 63414343Swollman else 63514343Swollman return M_EGAMONO80x25; 63614343Swollman break; 63714343Swollman 63814343Swollman case KD_CGA: 63914343Swollman return M_C80x25; 64014343Swollman 64114343Swollman case KD_MONO: 64214343Swollman case KD_HERCULES: 64314343Swollman return M_EGAMONO80x25; /* XXX: this name is confusing */ 64414343Swollman 64514343Swollman default: 64614343Swollman return -1; 64714343Swollman } 64814343Swollman } 64914343Swollman 65014343Swollman for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 65114343Swollman if (mode_map[i].from == mode) 65214343Swollman return ((color) ? mode_map[i].to_color : mode_map[i].to_mono); 65314343Swollman } 65414343Swollman return mode; 65514343Swollman} 65614343Swollman 65714343Swollman/* turn the BIOS video number into our video mode number */ 65814343Swollmanstatic int 6592742Swollmanmap_bios_mode_num(int type, int color, int bios_mode) 66086222Swollman{ 66143543Swollman static int cga_modes[7] = { 66243543Swollman M_B40x25, M_C40x25, /* 0, 1 */ 66343543Swollman M_B80x25, M_C80x25, /* 2, 3 */ 66486222Swollman M_BG320, M_CG320, 66543543Swollman M_BG640, 66643543Swollman }; 66743543Swollman static int ega_modes[17] = { 66843543Swollman M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */ 66914343Swollman M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */ 67019878Swollman M_BG320, M_CG320, 67119878Swollman M_BG640, 67219878Swollman M_EGAMONO80x25, /* 7 */ 67319878Swollman 8, 9, 10, 11, 12, 67419878Swollman M_CG320_D, 67519878Swollman M_CG640_E, 67619878Swollman M_ENHMONOAPA2, /* XXX: video momery > 64K */ 67719878Swollman M_ENH_CG640, /* XXX: video momery > 64K */ 67819878Swollman }; 67919878Swollman static int vga_modes[20] = { 68019878Swollman M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */ 6812742Swollman M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */ 6822742Swollman M_BG320, M_CG320, 6832742Swollman M_BG640, 68458787Sru M_VGA_M80x25, /* 7 */ 68514343Swollman 8, 9, 10, 11, 12, 68658787Sru M_CG320_D, 68758787Sru M_CG640_E, 6882742Swollman M_ENHMONOAPA2, 68986222Swollman M_ENH_CG640, 69020094Swollman M_BG640x480, M_CG640x480, 69120094Swollman M_VGA_CG320, 69220094Swollman }; 69320094Swollman 69420094Swollman switch (type) { 69520094Swollman 69620094Swollman case KD_VGA: 69720094Swollman if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0])) 698121098Swollman return vga_modes[bios_mode]; 6992742Swollman else if (color) 700121098Swollman return M_VGA_C80x25; 701121098Swollman else 702121098Swollman return M_VGA_M80x25; 703121098Swollman break; 704121098Swollman 705121098Swollman case KD_EGA: 706121098Swollman if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0])) 707121098Swollman return ega_modes[bios_mode]; 7089908Swollman else if (color) 7092742Swollman return M_ENH_C80x25; 7102742Swollman else 7112742Swollman return M_EGAMONO80x25; 7129908Swollman break; 7139908Swollman 7149908Swollman case KD_CGA: 7159908Swollman if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0])) 7169908Swollman return cga_modes[bios_mode]; 7179908Swollman else 7189908Swollman return M_C80x25; 7199908Swollman break; 7209908Swollman 7219908Swollman case KD_MONO: 7229908Swollman case KD_HERCULES: 7239908Swollman return M_EGAMONO80x25; /* XXX: this name is confusing */ 7249908Swollman 7259908Swollman default: 7269908Swollman break; 7279908Swollman } 7289908Swollman return -1; 7299908Swollman} 7309908Swollman 7319908Swollman/* look up a parameter table entry */ 7329908Swollmanstatic u_char 7339908Swollman*get_mode_param(int mode) 7349908Swollman{ 7359908Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 7369908Swollman if (mode >= V_MODE_MAP_SIZE) 7379908Swollman mode = map_mode_num(mode); 7389908Swollman#endif 7399908Swollman if ((mode >= 0) && (mode < V_MODE_MAP_SIZE)) 7409908Swollman return mode_map[mode]; 7419908Swollman else 7429908Swollman return NULL; 7432742Swollman} 74467578Swollman 7459908Swollman#ifndef VGA_NO_BIOS 74667578Swollmanstatic void 74767578Swollmanfill_adapter_param(int code, video_adapter_t *adp) 74867578Swollman{ 74967578Swollman static struct { 75067578Swollman int primary; 75167578Swollman int secondary; 75267578Swollman } dcc[] = { 75367578Swollman { DCC_MONO, DCC_EGA40 /* CGA monitor */ }, 75467578Swollman { DCC_MONO, DCC_EGA80 /* CGA monitor */ }, 75567578Swollman { DCC_MONO, DCC_EGA80 /* CGA emulation */ }, 75667578Swollman { DCC_MONO, DCC_EGA80 }, 75767578Swollman { DCC_CGA40, DCC_EGAMONO }, 7589908Swollman { DCC_CGA80, DCC_EGAMONO }, 7592742Swollman { DCC_EGA40 /* CGA monitor */, DCC_MONO}, 76017200Swollman { DCC_EGA80 /* CGA monitor */, DCC_MONO}, 76117200Swollman { DCC_EGA80 /* CGA emulation */,DCC_MONO }, 762121098Swollman { DCC_EGA80, DCC_MONO }, 763121098Swollman { DCC_EGAMONO, DCC_CGA40 }, 76417200Swollman { DCC_EGAMONO, DCC_CGA40 }, 76517200Swollman }; 76617200Swollman 76717200Swollman if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) { 76817200Swollman adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; 76917200Swollman adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; 77067578Swollman } else { 77117200Swollman adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary]; 77267578Swollman adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary]; 77367578Swollman } 77467578Swollman} 77567578Swollman#endif /* VGA_NO_BIOS */ 77667578Swollman 77767578Swollmanstatic int 77817200Swollmanverify_adapter(video_adapter_t *adp) 779121098Swollman{ 7802742Swollman vm_offset_t buf; 7812742Swollman u_int16_t v; 7822742Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 7832742Swollman u_int32_t p; 7842742Swollman#endif 7852742Swollman 7862742Swollman buf = BIOS_PADDRTOVADDR(adp->va_window); 787121098Swollman v = readw(buf); 788121098Swollman writew(buf, 0xA55A); 789121098Swollman if (readw(buf) != 0xA55A) 790121098Swollman return 1; 791121098Swollman writew(buf, v); 792121098Swollman 7932742Swollman switch (adp->va_type) { 7942742Swollman 7952742Swollman case KD_EGA: 7962742Swollman outb(adp->va_crtc_addr, 7); 7972742Swollman if (inb(adp->va_crtc_addr) == 7) { 7982742Swollman adp->va_type = KD_VGA; 79967578Swollman adp->va_name = "vga"; 80067578Swollman adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE; 80167578Swollman } 80267578Swollman adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER; 80367578Swollman /* the color adapter may be in the 40x25 mode... XXX */ 80467578Swollman 80567578Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 80667578Swollman /* get the BIOS video mode pointer */ 8072742Swollman p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8); 8082742Swollman p = BIOS_SADDRTOLADDR(p); 8092742Swollman if (ISMAPPED(p, sizeof(u_int32_t))) { 810121098Swollman p = *(u_int32_t *)BIOS_PADDRTOVADDR(p); 811121098Swollman p = BIOS_SADDRTOLADDR(p); 81220094Swollman if (ISMAPPED(p, V_MODE_PARAM_SIZE)) 813121098Swollman video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p); 814121098Swollman } 8152742Swollman#endif 8162742Swollman break; 81767578Swollman 81817200Swollman case KD_CGA: 81920094Swollman adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER; 82020094Swollman /* may be in the 40x25 mode... XXX */ 82120094Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 822121098Swollman /* get the BIOS video mode pointer */ 823121098Swollman p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); 82420094Swollman p = BIOS_SADDRTOLADDR(p); 82520094Swollman video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); 826121098Swollman#endif 827121098Swollman break; 82820094Swollman 82920094Swollman case KD_MONO: 83020094Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 83120094Swollman /* get the BIOS video mode pointer */ 83220094Swollman p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); 83320094Swollman p = BIOS_SADDRTOLADDR(p); 83417200Swollman video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); 83517200Swollman#endif 83617200Swollman break; 83717200Swollman } 83817200Swollman 83917200Swollman return 0; 84017200Swollman} 84167578Swollman 84267578Swollmanstatic void 84367578Swollmanupdate_adapter_info(video_adapter_t *adp, video_info_t *info) 84467578Swollman{ 84567578Swollman adp->va_flags &= ~V_ADP_COLOR; 8462742Swollman adp->va_flags |= 8472742Swollman (info->vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; 8482742Swollman adp->va_crtc_addr = 8492742Swollman (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; 8502742Swollman adp->va_window = BIOS_PADDRTOVADDR(info->vi_window); 8512742Swollman adp->va_window_size = info->vi_window_size; 8522742Swollman adp->va_window_gran = info->vi_window_gran; 8532742Swollman if (info->vi_buffer_size == 0) { 8542742Swollman adp->va_buffer = 0; 8552742Swollman adp->va_buffer_size = 0; 8562742Swollman } else { 8572742Swollman adp->va_buffer = BIOS_PADDRTOVADDR(info->vi_buffer); 8582742Swollman adp->va_buffer_size = info->vi_buffer_size; 8592742Swollman } 8602742Swollman if (info->vi_flags & V_INFO_GRAPHICS) { 8612742Swollman switch (info->vi_depth/info->vi_planes) { 8622742Swollman case 1: 8632742Swollman adp->va_line_width = info->vi_width/8; 8642742Swollman break; 8652742Swollman case 2: 8662742Swollman adp->va_line_width = info->vi_width/4; 867121098Swollman break; 8682742Swollman case 4: 8692742Swollman adp->va_line_width = info->vi_width/2; 8702742Swollman break; 8712742Swollman case 8: 8722742Swollman default: /* shouldn't happen */ 8732742Swollman adp->va_line_width = info->vi_width; 8742742Swollman break; 8752742Swollman } 8762742Swollman } else { 8772742Swollman adp->va_line_width = info->vi_width; 8782742Swollman } 8792742Swollman bcopy(info, &adp->va_info, sizeof(adp->va_info)); 880121098Swollman} 881121098Swollman 882121098Swollman#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 883121098Swollman/* compare two parameter table entries */ 884121098Swollmanstatic int 885121098Swollmancomp_adpregs(u_char *buf1, u_char *buf2) 886121098Swollman{ 887121098Swollman static struct { 8882742Swollman u_char mask; 8892742Swollman } params[V_MODE_PARAM_SIZE] = { 890121098Swollman {0xff}, {0x00}, {0xff}, /* COLS, ROWS, POINTS */ 891121098Swollman {0x00}, {0x00}, /* page length */ 892121098Swollman {0xfe}, {0xff}, {0xff}, {0xff}, /* sequencer registers */ 893121098Swollman {0xf3}, /* misc register */ 894121098Swollman {0xff}, {0xff}, {0xff}, {0x7f}, {0xff}, /* CRTC */ 895121098Swollman {0xff}, {0xff}, {0xff}, {0x7f}, {0xff}, 89617200Swollman {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, 89717200Swollman {0x00}, {0xff}, {0x7f}, {0xff}, {0xff}, 89817200Swollman {0x7f}, {0xff}, {0xff}, {0xef}, {0xff}, 89917200Swollman {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* attribute controller regs */ 900121098Swollman {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, 901121098Swollman {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, 9022742Swollman {0xff}, {0xff}, {0xff}, {0xff}, {0xf0}, 9038029Swollman {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* GDC register */ 90417200Swollman {0xff}, {0xff}, {0xff}, {0xff}, 90517200Swollman }; 90617200Swollman int identical = TRUE; 907121098Swollman int i; 908121098Swollman 90917200Swollman if ((buf1 == NULL) || (buf2 == NULL)) 91017200Swollman return COMP_DIFFERENT; 91117200Swollman 91217200Swollman for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { 91317200Swollman if (params[i].mask == 0) /* don't care */ 914121098Swollman continue; 915121098Swollman if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) 916121098Swollman return COMP_DIFFERENT; 917121098Swollman if (buf1[i] != buf2[i]) 918121098Swollman identical = FALSE; 919121098Swollman } 920121098Swollman return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; 921121098Swollman} 922121098Swollman#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 923121098Swollman 924121098Swollman/* probe video adapters and return the number of detected adapters */ 925121098Swollmanstatic int 926121098Swollmanprobe_adapters(void) 92743014Swollman{ 928121098Swollman video_adapter_t *adp; 92943014Swollman video_info_t info; 93043014Swollman int i; 93143014Swollman 93243014Swollman /* do this test only once */ 93343014Swollman if (init_done) 93443014Swollman return biosadapters; 93543014Swollman init_done = TRUE; 93643014Swollman 93743014Swollman /* 93858787Sru * Locate display adapters. 93943014Swollman * The AT architecture supports upto two adapters. `syscons' allows 94043014Swollman * the following combinations of adapters: 94167578Swollman * 1) MDA + CGA 94267578Swollman * 2) MDA + EGA/VGA color 94367578Swollman * 3) CGA + EGA/VGA mono 94467578Swollman * Note that `syscons' doesn't bother with MCGA as it is only 94567578Swollman * avaiable for low end PS/2 models which has 80286 or earlier CPUs, 94667578Swollman * thus, they are not running FreeBSD! 94767578Swollman * When there are two adapaters in the system, one becomes `primary' 94867578Swollman * and the other `secondary'. The EGA adapter has a set of DIP 94967578Swollman * switches on board for this information and the EGA BIOS copies 95067578Swollman * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88). 95167578Swollman * The VGA BIOS has more sophisticated mechanism and has this 9522742Swollman * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains 9532742Swollman * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH. 9542742Swollman */ 9552742Swollman 9562742Swollman /* 9572742Swollman * Check rtc and BIOS data area. 958121098Swollman * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead 9592742Swollman * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are 9602742Swollman * zeros for EGA and VGA. However, the EGA/VGA BIOS sets 9612742Swollman * these bits in BIOSDATA_EQUIPMENT according to the monitor 9622742Swollman * type detected. 9632742Swollman */ 964136638Swollman#ifndef VGA_NO_BIOS 965136638Swollman switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ 966136638Swollman case 0: 967136638Swollman /* EGA/VGA */ 968136638Swollman fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f, 969136638Swollman biosadapter); 970136638Swollman break; 971136638Swollman case 1: 972136638Swollman /* CGA 40x25 */ 973136638Swollman /* FIXME: switch to the 80x25 mode? XXX */ 974136638Swollman biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40]; 975136638Swollman biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 976121098Swollman break; 9772742Swollman case 2: 9782742Swollman /* CGA 80x25 */ 9792742Swollman biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80]; 980121098Swollman biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 981121098Swollman break; 982121098Swollman case 3: 983121098Swollman /* MDA */ 984121098Swollman biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; 985121098Swollman biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; 986121098Swollman break; 987121098Swollman } 988121098Swollman#else 989121098Swollman /* assume EGA/VGA? XXX */ 990121098Swollman biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80]; 991121098Swollman biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 992136638Swollman#endif /* VGA_NO_BIOS */ 993136638Swollman 994136638Swollman biosadapters = 0; 995136638Swollman if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) { 996136638Swollman ++biosadapters; 997136638Swollman biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED; 998136638Swollman biosadapter[V_ADP_SECONDARY].va_mode = 999136638Swollman biosadapter[V_ADP_SECONDARY].va_initial_mode = 1000136638Swollman map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type, 1001136638Swollman biosadapter[V_ADP_SECONDARY].va_flags 1002136638Swollman & V_ADP_COLOR, 1003136638Swollman biosadapter[V_ADP_SECONDARY].va_initial_bios_mode); 1004136638Swollman } else { 1005121098Swollman biosadapter[V_ADP_SECONDARY].va_type = -1; 1006121098Swollman } 1007121098Swollman if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) { 1008121098Swollman ++biosadapters; 1009121098Swollman biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED; 1010121098Swollman#ifndef VGA_NO_BIOS 1011121098Swollman biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 1012121098Swollman readb(BIOS_PADDRTOVADDR(0x449)); 1013121098Swollman#else 1014121098Swollman biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */ 1015121098Swollman#endif 1016121098Swollman biosadapter[V_ADP_PRIMARY].va_mode = 1017121098Swollman biosadapter[V_ADP_PRIMARY].va_initial_mode = 1018121098Swollman map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type, 1019121098Swollman biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR, 1020121098Swollman biosadapter[V_ADP_PRIMARY].va_initial_bios_mode); 1021121098Swollman } else { 1022136638Swollman biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY]; 1023121098Swollman biosadapter[V_ADP_SECONDARY].va_type = -1; 1024136638Swollman } 1025136638Swollman if (biosadapters == 0) 1026136638Swollman return biosadapters; 1027136638Swollman biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY; 1028136638Swollman biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY; 1029136638Swollman 1030136638Swollman#if 0 /* we don't need these... */ 1031136638Swollman fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...); 1032136638Swollman fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...); 1033136638Swollman#endif 1034136638Swollman 1035136638Swollman#if 0 10362742Swollman /* 10372742Swollman * We cannot have two video adapter of the same type; there must be 1038121098Swollman * only one of color or mono adapter, or one each of them. 1039121098Swollman */ 1040121098Swollman if (biosadapters > 1) { 1041121098Swollman if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags) 1042121098Swollman & V_ADP_COLOR)) 1043121098Swollman /* we have two mono or color adapters!! */ 1044121098Swollman return (biosadapters = 0); 1045121098Swollman } 1046121098Swollman#endif 1047121098Swollman 1048121098Swollman /* 1049121098Swollman * Ensure a zero start address. This is mainly to recover after 105017200Swollman * switching from pcvt using userconfig(). The registers are w/o 1051136638Swollman * for old hardware so it's too hard to relocate the active screen 1052136638Swollman * memory. 105317200Swollman * This must be done before vga_save_state() for VGA. 105417200Swollman */ 105517200Swollman outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12); 105617200Swollman outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); 105717200Swollman outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13); 1058121098Swollman outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); 1059121098Swollman 106017200Swollman /* the video mode parameter table in EGA/VGA BIOS */ 106117200Swollman /* NOTE: there can be only one EGA/VGA, wheather color or mono, 1062121098Swollman * recognized by the video BIOS. 1063121098Swollman */ 106417200Swollman if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) || 10652742Swollman (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) { 10668029Swollman adp = &biosadapter[V_ADP_PRIMARY]; 106717200Swollman } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) || 106819878Swollman (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) { 10692742Swollman adp = &biosadapter[V_ADP_SECONDARY]; 10702742Swollman } else { 10712742Swollman adp = NULL; 10722742Swollman } 10732742Swollman bzero(mode_map, sizeof(mode_map)); 10742742Swollman if (adp != NULL) { 107514343Swollman if (adp->va_type == KD_VGA) { 1076121098Swollman vga_save_state(adp, &adpstate, sizeof(adpstate)); 1077121098Swollman#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) 10782742Swollman mode_map[adp->va_initial_mode] = adpstate.regs; 10792742Swollman rows_offset = 1; 10802742Swollman#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 10812742Swollman if (video_mode_ptr == NULL) { 108214343Swollman mode_map[adp->va_initial_mode] = adpstate.regs; 108314343Swollman rows_offset = 1; 108414343Swollman } else { 108514343Swollman /* discard the table if we are not familiar with it... */ 108614343Swollman u_char *mp; 10872742Swollman map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); 10882742Swollman mp = get_mode_param(adp->va_initial_mode); 10892742Swollman if (mp != NULL) 109014343Swollman bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs)); 10912742Swollman switch (comp_adpregs(adpstate.regs, mp)) { 109267578Swollman case COMP_IDENTICAL: 10932742Swollman /* 109467578Swollman * OK, this parameter table looks reasonably familiar 109567578Swollman * to us... 109667578Swollman */ 109767578Swollman /* 10982742Swollman * This is a kludge for Toshiba DynaBook SS433 10992742Swollman * whose BIOS video mode table entry has the actual # 11002742Swollman * of rows at the offset 1; BIOSes from other 11012742Swollman * manufacturers store the # of rows - 1 there. XXX 11028029Swollman */ 110317200Swollman rows_offset = adpstate.regs[1] + 1 - mp[1]; 110417200Swollman break; 1105121098Swollman 1106121098Swollman case COMP_SIMILAR: 1107121098Swollman /* 1108121098Swollman * Not exactly the same, but similar enough to be 1109121098Swollman * trusted. However, use the saved register values 1110121098Swollman * for the initial mode and other modes which are 1111121098Swollman * based on the initial mode. 1112121098Swollman */ 1113121098Swollman mode_map[adp->va_initial_mode] = adpstate.regs; 1114121098Swollman rows_offset = adpstate.regs[1] + 1 - mp[1]; 1115121098Swollman adpstate.regs[1] -= rows_offset - 1; 1116121098Swollman break; 1117121098Swollman 1118121098Swollman case COMP_DIFFERENT: 111967578Swollman default: 112017200Swollman /* 112117200Swollman * Don't use the paramter table in BIOS. It doesn't 112217200Swollman * look familiar to us. Video mode switching is allowed 112367578Swollman * only if the new mode is the same as or based on 112467578Swollman * the initial mode. 112517200Swollman */ 112619878Swollman video_mode_ptr = NULL; 112717200Swollman bzero(mode_map, sizeof(mode_map)); 112817200Swollman mode_map[adp->va_initial_mode] = adpstate.regs; 112917200Swollman rows_offset = 1; 113017200Swollman break; 113117200Swollman } 113217200Swollman } 113317200Swollman#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 113417200Swollman 113517200Swollman#ifndef VGA_NO_MODE_CHANGE 113617200Swollman adp->va_flags |= V_ADP_MODECHANGE; 113717200Swollman#endif 113817200Swollman#ifndef VGA_NO_FONT_LOADING 113917200Swollman adp->va_flags |= V_ADP_FONT; 114017200Swollman#endif 114117200Swollman } else if (adp->va_type == KD_EGA) { 114217200Swollman#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) 114317200Swollman rows_offset = 1; 114417200Swollman#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 114517200Swollman if (video_mode_ptr == NULL) { 114617200Swollman rows_offset = 1; 114717200Swollman } else { 114817200Swollman u_char *mp; 114917200Swollman map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1); 115017200Swollman /* XXX how can one validate the EGA table... */ 115117200Swollman mp = get_mode_param(adp->va_initial_mode); 11522742Swollman if (mp != NULL) { 11532742Swollman adp->va_flags |= V_ADP_MODECHANGE; 11542742Swollman#ifndef VGA_NO_FONT_LOADING 11552742Swollman adp->va_flags |= V_ADP_FONT; 11562742Swollman#endif 11572742Swollman rows_offset = 1; 11582742Swollman } else { 11592742Swollman /* 11602742Swollman * This is serious. We will not be able to switch video 1161121098Swollman * modes at all... 1162121098Swollman */ 11632742Swollman video_mode_ptr = NULL; 116417200Swollman bzero(mode_map, sizeof(mode_map)); 116517200Swollman rows_offset = 1; 1166121098Swollman } 1167121098Swollman } 1168121098Swollman#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 116917200Swollman } 117017200Swollman } 117117200Swollman 117217200Swollman /* remove conflicting modes if we have more than one adapter */ 117317200Swollman if (biosadapters > 1) { 117417200Swollman for (i = 0; i < biosadapters; ++i) { 117517200Swollman if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE)) 11762742Swollman continue; 117717200Swollman clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1, 117817200Swollman (biosadapter[i].va_flags & V_ADP_COLOR) ? 11792742Swollman V_INFO_COLOR : 0); 118017200Swollman if ((biosadapter[i].va_type == KD_VGA) 118117200Swollman || (biosadapter[i].va_type == KD_EGA)) { 118217200Swollman biosadapter[i].va_io_base = 118317200Swollman (biosadapter[i].va_flags & V_ADP_COLOR) ? 118417200Swollman IO_VGA : IO_MDA; 11852742Swollman biosadapter[i].va_io_size = 32; 11868029Swollman } 118717200Swollman } 118817200Swollman } 11892742Swollman 11902742Swollman /* buffer address */ 11912742Swollman vga_get_info(&biosadapter[V_ADP_PRIMARY], 11922742Swollman biosadapter[V_ADP_PRIMARY].va_initial_mode, &info); 11932742Swollman update_adapter_info(&biosadapter[V_ADP_PRIMARY], &info); 11942742Swollman 11952742Swollman if (biosadapters > 1) { 1196121098Swollman vga_get_info(&biosadapter[V_ADP_SECONDARY], 1197121098Swollman biosadapter[V_ADP_SECONDARY].va_initial_mode, &info); 11982742Swollman update_adapter_info(&biosadapter[V_ADP_SECONDARY], &info); 11992742Swollman } 12002742Swollman 12012742Swollman /* 12022742Swollman * XXX: we should verify the following values for the primary adapter... 12032742Swollman * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463); 12042742Swollman * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02) 12052742Swollman * ? 0 : V_ADP_COLOR; 12062742Swollman * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a); 12072742Swollman * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484); 12082742Swollman * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485); 12092742Swollman * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c); 12102742Swollman */ 12112742Swollman 12128029Swollman return biosadapters; 121317200Swollman} 121417200Swollman 121567578Swollman/* entry points */ 121617200Swollman 121758787Srustatic int 121867578Swollmanvga_nop(void) 121917200Swollman{ 12202742Swollman return 0; 12212742Swollman} 12222742Swollman 1223121098Swollmanstatic int 1224121098Swollmanvga_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 12252742Swollman{ 12262742Swollman probe_adapters(); 12272742Swollman if (unit >= biosadapters) 12282742Swollman return ENXIO; 12292742Swollman 12302742Swollman *adpp = &biosadapter[unit]; 12312742Swollman 12322742Swollman return 0; 12332742Swollman} 123417200Swollman 123517200Swollmanstatic int 123617200Swollmanvga_init(int unit, video_adapter_t *adp, int flags) 123717200Swollman{ 12382742Swollman if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp)) 12398029Swollman return ENXIO; 124058787Sru 124117200Swollman if (!init_done(adp)) { 124258787Sru /* nothing to do really... */ 124317200Swollman adp->va_flags |= V_ADP_INITIALIZED; 124420094Swollman } 124520094Swollman 124620094Swollman if (!config_done(adp)) { 124720094Swollman if (vid_register(adp) < 0) 124820094Swollman return ENXIO; 124920094Swollman adp->va_flags |= V_ADP_REGISTERED; 125020094Swollman } 125120094Swollman if (vga_sub_configure != NULL) 125217200Swollman (*vga_sub_configure)(0); 125358787Sru 125458787Sru return 0; 125558787Sru} 125658787Sru 125758787Sru/* 125858787Sru * get_info(): 125958787Sru * Return the video_info structure of the requested video mode. 126058787Sru * 126158787Sru * all adapters 126258787Sru */ 126358787Srustatic int 126458787Sruvga_get_info(video_adapter_t *adp, int mode, video_info_t *info) 126558787Sru{ 126686222Swollman int i; 126758787Sru 126886222Swollman if (!init_done) 126958787Sru return 1; 127058787Sru 127158787Sru mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); 127258787Sru#ifndef VGA_NO_MODE_CHANGE 127358787Sru if (adp->va_flags & V_ADP_MODECHANGE) { 127458787Sru /* 127558787Sru * If the parameter table entry for this mode is not found, 127658787Sru * the mode is not supported... 127758787Sru */ 127858787Sru if (get_mode_param(mode) == NULL) 127958787Sru return 1; 128058787Sru } else 128158787Sru#endif /* VGA_NO_MODE_CHANGE */ 128258787Sru { 128358787Sru /* 128458787Sru * Even if we don't support video mode switching on this adapter, 128558787Sru * the information on the initial (thus current) video mode 128658787Sru * should be made available. 128758787Sru */ 128858787Sru if (mode != adp->va_initial_mode) 128958787Sru return 1; 129058787Sru } 129158787Sru 129258787Sru for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 129358787Sru if (bios_vmode[i].vi_mode == NA) 129458787Sru continue; 129558787Sru if (mode == bios_vmode[i].vi_mode) { 129658787Sru *info = bios_vmode[i]; 129758787Sru return 0; 129858787Sru } 129958787Sru } 130058787Sru return 1; 130158787Sru} 130258787Sru 130367578Swollman/* 130467578Swollman * query_mode(): 130567578Swollman * Find a video mode matching the requested parameters. 130675267Swollman * Fields filled with 0 are considered "don't care" fields and 130767578Swollman * match any modes. 130867578Swollman * 130967578Swollman * all adapters 131067578Swollman */ 131167578Swollmanstatic int 131267578Swollmanvga_query_mode(video_adapter_t *adp, video_info_t *info) 131367578Swollman{ 131467578Swollman video_info_t buf; 131575267Swollman int i; 131675267Swollman 131775267Swollman if (!init_done) 131875267Swollman return -1; 131975267Swollman 132075267Swollman for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 132175267Swollman if (bios_vmode[i].vi_mode == NA) 132275267Swollman continue; 132375267Swollman 132475267Swollman if ((info->vi_width != 0) 132575267Swollman && (info->vi_width != bios_vmode[i].vi_width)) 132675267Swollman continue; 132775267Swollman if ((info->vi_height != 0) 132875267Swollman && (info->vi_height != bios_vmode[i].vi_height)) 132975267Swollman continue; 133075267Swollman if ((info->vi_cwidth != 0) 133175267Swollman && (info->vi_cwidth != bios_vmode[i].vi_cwidth)) 133275267Swollman continue; 133375267Swollman if ((info->vi_cheight != 0) 133475267Swollman && (info->vi_cheight != bios_vmode[i].vi_cheight)) 133575267Swollman continue; 133675267Swollman if ((info->vi_depth != 0) 133775267Swollman && (info->vi_depth != bios_vmode[i].vi_depth)) 133875267Swollman continue; 133975267Swollman if ((info->vi_planes != 0) 134075267Swollman && (info->vi_planes != bios_vmode[i].vi_planes)) 134175267Swollman continue; 134275267Swollman /* XXX: should check pixel format, memory model */ 134375267Swollman if ((info->vi_flags != 0) 134475267Swollman && (info->vi_flags != bios_vmode[i].vi_flags)) 13452742Swollman continue; 134617200Swollman 134717200Swollman /* verify if this mode is supported on this adapter */ 134817200Swollman if (vga_get_info(adp, bios_vmode[i].vi_mode, &buf)) 134917200Swollman continue; 1350121098Swollman return bios_vmode[i].vi_mode; 1351121098Swollman } 135217200Swollman return -1; 135317200Swollman} 135417200Swollman 135517200Swollman/* 135617200Swollman * set_mode(): 135717200Swollman * Change the video mode. 13582742Swollman * 135917200Swollman * EGA/VGA 136058787Sru */ 136158787Srustatic int 136275267Swollmanvga_set_mode(video_adapter_t *adp, int mode) 136375267Swollman{ 136458787Sru#ifndef VGA_NO_MODE_CHANGE 136558787Sru video_info_t info; 136675267Swollman adp_state_t params; 136775267Swollman 136875267Swollman prologue(adp, V_ADP_MODECHANGE, 1); 136975267Swollman 137075267Swollman mode = map_gen_mode_num(adp->va_type, 137158787Sru adp->va_flags & V_ADP_COLOR, mode); 137258787Sru if (vga_get_info(adp, mode, &info)) 137358787Sru return 1; 137475267Swollman params.sig = V_STATE_SIG; 137575267Swollman bcopy(get_mode_param(mode), params.regs, sizeof(params.regs)); 137675267Swollman 137775267Swollman switch (mode) { 137817200Swollman case M_VGA_C80x60: case M_VGA_M80x60: 137917200Swollman params.regs[2] = 0x08; 138017200Swollman params.regs[19] = 0x47; 138117200Swollman goto special_480l; 138217200Swollman 13832742Swollman case M_VGA_C80x30: case M_VGA_M80x30: 138417200Swollman params.regs[19] = 0x4f; 138517200Swollmanspecial_480l: 138617200Swollman params.regs[9] |= 0xc0; 138720094Swollman params.regs[16] = 0x08; 138817200Swollman params.regs[17] = 0x3e; 13892742Swollman params.regs[26] = 0xea; 13908029Swollman params.regs[28] = 0xdf; 13912742Swollman params.regs[31] = 0xe7; 13922742Swollman params.regs[32] = 0x04; 13932742Swollman goto setup_mode; 13942742Swollman 139575267Swollman case M_ENH_C80x43: case M_ENH_B80x43: 139675267Swollman params.regs[28] = 87; 139775267Swollman goto special_80x50; 139875267Swollman 139975267Swollman case M_VGA_C80x50: case M_VGA_M80x50: 140075267Swollmanspecial_80x50: 14012742Swollman params.regs[2] = 8; 140275267Swollman params.regs[19] = 7; 140375267Swollman goto setup_mode; 140475267Swollman 140575267Swollman case M_VGA_C40x25: case M_VGA_C80x25: 140675267Swollman case M_VGA_M80x25: 140775267Swollman case M_B40x25: case M_C40x25: 140875267Swollman case M_B80x25: case M_C80x25: 140975267Swollman case M_ENH_B40x25: case M_ENH_C40x25: 141075267Swollman case M_ENH_B80x25: case M_ENH_C80x25: 141175267Swollman case M_EGAMONO80x25: 14122742Swollman 141375267Swollmansetup_mode: 141475267Swollman vga_load_state(adp, ¶ms); 141575267Swollman break; 141675267Swollman 141775267Swollman case M_VGA_MODEX: 141875267Swollman /* "unchain" the VGA mode */ 141964499Swollman params.regs[5-1+0x04] &= 0xf7; 142064499Swollman params.regs[5-1+0x04] |= 0x04; 142164499Swollman /* turn off doubleword mode */ 14222742Swollman params.regs[10+0x14] &= 0xbf; 142317200Swollman /* turn off word adressing */ 142417200Swollman params.regs[10+0x17] |= 0x40; 142517200Swollman /* set logical screen width */ 142658787Sru params.regs[10+0x13] = 80; 142717200Swollman /* set 240 lines */ 142858787Sru params.regs[10+0x11] = 0x2c; 142917200Swollman params.regs[10+0x06] = 0x0d; 143017200Swollman params.regs[10+0x07] = 0x3e; 143158787Sru params.regs[10+0x10] = 0xea; 143217200Swollman params.regs[10+0x11] = 0xac; 143317200Swollman params.regs[10+0x12] = 0xdf; 143417200Swollman params.regs[10+0x15] = 0xe7; 143517200Swollman params.regs[10+0x16] = 0x06; 143658787Sru /* set vertical sync polarity to reflect aspect ratio */ 143717200Swollman params.regs[9] = 0xe3; 143817200Swollman goto setup_grmode; 143917200Swollman 144017200Swollman case M_BG320: case M_CG320: case M_BG640: 144117200Swollman case M_CG320_D: case M_CG640_E: 144258787Sru case M_CG640x350: case M_ENH_CG640: 144317200Swollman case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 144417200Swollman 144517200Swollmansetup_grmode: 144617200Swollman vga_load_state(adp, ¶ms); 144758787Sru break; 144817200Swollman 144958787Sru default: 145017200Swollman return 1; 145117200Swollman } 145243014Swollman 145343014Swollman adp->va_mode = mode; 145443014Swollman update_adapter_info(adp, &info); 145543014Swollman 145614343Swollman /* move hardware cursor out of the way */ 145743543Swollman (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1, -1); 145843543Swollman 145943543Swollman return 0; 146043543Swollman#else /* VGA_NO_MODE_CHANGE */ 146158787Sru return 1; 146258787Sru#endif /* VGA_NO_MODE_CHANGE */ 146358787Sru} 146458787Sru 146558787Sru#ifndef VGA_NO_FONT_LOADING 146658787Sru 146775267Swollmanstatic void 146875267Swollmanset_font_mode(video_adapter_t *adp, u_char *buf) 146975267Swollman{ 147075267Swollman u_char *mp; 147175267Swollman int s; 147275267Swollman 147375267Swollman s = splhigh(); 147475267Swollman 147575267Swollman /* save register values */ 147675267Swollman if (adp->va_type == KD_VGA) { 147775267Swollman outb(TSIDX, 0x02); buf[0] = inb(TSREG); 147875267Swollman outb(TSIDX, 0x04); buf[1] = inb(TSREG); 147975267Swollman outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); 148075267Swollman outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); 148175267Swollman outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); 148275267Swollman inb(adp->va_crtc_addr + 6); 148375267Swollman outb(ATC, 0x10); buf[5] = inb(ATC + 1); 148475267Swollman } else /* if (adp->va_type == KD_EGA) */ { 148575267Swollman /* 148675267Swollman * EGA cannot be read; copy parameters from the mode parameter 148775267Swollman * table. 148875267Swollman */ 148975267Swollman mp = get_mode_param(adp->va_mode); 149075267Swollman buf[0] = mp[5 + 0x02 - 1]; 149175267Swollman buf[1] = mp[5 + 0x04 - 1]; 149275267Swollman buf[2] = mp[55 + 0x04]; 149375267Swollman buf[3] = mp[55 + 0x05]; 149475267Swollman buf[4] = mp[55 + 0x06]; 149575267Swollman buf[5] = mp[35 + 0x10]; 149675267Swollman } 149775267Swollman 149875267Swollman /* setup vga for loading fonts */ 149975267Swollman inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 150075267Swollman outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01); 150175267Swollman inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 150275267Swollman outb(ATC, 0x20); /* enable palette */ 150375267Swollman 150475267Swollman#if VGA_SLOW_IOACCESS 150575267Swollman#ifdef VGA_ALT_SEQACCESS 150675267Swollman outb(TSIDX, 0x00); outb(TSREG, 0x01); 150775267Swollman#endif 150875267Swollman outb(TSIDX, 0x02); outb(TSREG, 0x04); 150975267Swollman outb(TSIDX, 0x04); outb(TSREG, 0x07); 151075267Swollman#ifdef VGA_ALT_SEQACCESS 151175267Swollman outb(TSIDX, 0x00); outb(TSREG, 0x03); 151275267Swollman#endif 151375267Swollman outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 151475267Swollman outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 151575267Swollman outb(GDCIDX, 0x06); outb(GDCREG, 0x04); 151675267Swollman#else /* VGA_SLOW_IOACCESS */ 151775267Swollman#ifdef VGA_ALT_SEQACCESS 151875267Swollman outw(TSIDX, 0x0100); 151975267Swollman#endif 152075267Swollman outw(TSIDX, 0x0402); 152175267Swollman outw(TSIDX, 0x0704); 152275267Swollman#ifdef VGA_ALT_SEQACCESS 152375267Swollman outw(TSIDX, 0x0300); 152486222Swollman#endif 152586222Swollman outw(GDCIDX, 0x0204); 152686222Swollman outw(GDCIDX, 0x0005); 152786222Swollman outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */ 152886222Swollman#endif /* VGA_SLOW_IOACCESS */ 152986222Swollman 153086222Swollman splx(s); 153186222Swollman} 153286222Swollman 153393799Swollmanstatic void 153493799Swollmanset_normal_mode(video_adapter_t *adp, u_char *buf) 153593799Swollman{ 153693799Swollman int s; 153793799Swollman 153893799Swollman s = splhigh(); 15392742Swollman 15402742Swollman /* setup vga for normal operation mode again */ 15412742Swollman inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 15422742Swollman outb(ATC, 0x10); outb(ATC, buf[5]); 15432742Swollman inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 1544121098Swollman outb(ATC, 0x20); /* enable palette */ 15452742Swollman 15462742Swollman#if VGA_SLOW_IOACCESS 15472742Swollman#ifdef VGA_ALT_SEQACCESS 154875267Swollman outb(TSIDX, 0x00); outb(TSREG, 0x01); 154975267Swollman#endif 155093799Swollman outb(TSIDX, 0x02); outb(TSREG, buf[0]); 155193799Swollman outb(TSIDX, 0x04); outb(TSREG, buf[1]); 155293799Swollman#ifdef VGA_ALT_SEQACCESS 155393799Swollman outb(TSIDX, 0x00); outb(TSREG, 0x03); 15542742Swollman#endif 155543014Swollman outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); 155658787Sru outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); 155775267Swollman if (adp->va_crtc_addr == MONO_CRTC) { 155843543Swollman outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); 155943543Swollman } else { 156064499Swollman outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); 156164499Swollman } 156275267Swollman#else /* VGA_SLOW_IOACCESS */ 156364499Swollman#ifdef VGA_ALT_SEQACCESS 156464499Swollman outw(TSIDX, 0x0100); 156564499Swollman#endif 156675267Swollman outw(TSIDX, 0x0002 | (buf[0] << 8)); 156764499Swollman outw(TSIDX, 0x0004 | (buf[1] << 8)); 156864499Swollman#ifdef VGA_ALT_SEQACCESS 156964499Swollman outw(TSIDX, 0x0300); 157043014Swollman#endif 15712742Swollman outw(GDCIDX, 0x0004 | (buf[2] << 8)); 15722742Swollman outw(GDCIDX, 0x0005 | (buf[3] << 8)); 15732742Swollman if (adp->va_crtc_addr == MONO_CRTC) 15742742Swollman outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); 15752742Swollman else 157675267Swollman outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); 157786222Swollman#endif /* VGA_SLOW_IOACCESS */ 157893799Swollman 157993799Swollman splx(s); 158043014Swollman} 158158787Sru 158243014Swollman#endif /* VGA_NO_FONT_LOADING */ 158343014Swollman 158443014Swollman/* 158543014Swollman * save_font(): 158675267Swollman * Read the font data in the requested font page from the video adapter. 158743014Swollman * 158843014Swollman * EGA/VGA 158943014Swollman */ 159043014Swollmanstatic int 159158787Sruvga_save_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 159258787Sru int ch, int count) 159358787Sru{ 159458787Sru#ifndef VGA_NO_FONT_LOADING 159558787Sru u_char buf[PARAM_BUFSIZE]; 159658787Sru u_int32_t segment; 159775267Swollman int c; 159864499Swollman#ifdef VGA_ALT_SEQACCESS 159958787Sru int s; 160058787Sru u_char val = 0; 160158787Sru#endif 160258787Sru 160364499Swollman prologue(adp, V_ADP_FONT, 1); 16042742Swollman 16052742Swollman if (fontsize < 14) { 16062742Swollman /* FONT_8 */ 16072742Swollman fontsize = 8; 16082742Swollman } else if (fontsize >= 32) { 160975267Swollman fontsize = 32; 161064499Swollman } else if (fontsize >= 16) { 16112742Swollman /* FONT_16 */ 16122742Swollman fontsize = 16; 161314343Swollman } else { 161458787Sru /* FONT_14 */ 16152742Swollman fontsize = 14; 161675267Swollman } 16172742Swollman 161875267Swollman if (page < 0 || page >= 8) 161975267Swollman return 1; 162075267Swollman segment = FONT_BUF + 0x4000*page; 162164499Swollman if (page > 3) 162275267Swollman segment -= 0xe000; 162375267Swollman 162475267Swollman#ifdef VGA_ALT_SEQACCESS 162575267Swollman if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ 162675267Swollman s = splhigh(); 162775267Swollman outb(TSIDX, 0x00); outb(TSREG, 0x01); 162814343Swollman outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 162975267Swollman outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 163093799Swollman outb(TSIDX, 0x00); outb(TSREG, 0x03); 163193799Swollman splx(s); 163275267Swollman } 163375267Swollman#endif 163475267Swollman 163575267Swollman set_font_mode(adp, buf); 163675267Swollman if (fontsize == 32) { 163775267Swollman bcopy_fromio(segment + ch*32, data, fontsize*count); 163875267Swollman } else { 163975267Swollman for (c = ch; count > 0; ++c, --count) { 164075267Swollman bcopy_fromio(segment + c*32, data, fontsize); 164175267Swollman data += fontsize; 16422742Swollman } 16432742Swollman } 16442742Swollman set_normal_mode(adp, buf); 16452742Swollman 16462742Swollman#ifdef VGA_ALT_SEQACCESS 16472742Swollman if (adp->va_type == KD_VGA) { 16482742Swollman s = splhigh(); 16492742Swollman outb(TSIDX, 0x00); outb(TSREG, 0x01); 16502742Swollman outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ 16512742Swollman outb(TSIDX, 0x00); outb(TSREG, 0x03); 16522742Swollman splx(s); 16532742Swollman } 16542742Swollman#endif 16552742Swollman 16562742Swollman return 0; 16572742Swollman#else /* VGA_NO_FONT_LOADING */ 16582742Swollman return 1; 16592742Swollman#endif /* VGA_NO_FONT_LOADING */ 16602742Swollman} 16612742Swollman 16622742Swollman/* 16632742Swollman * load_font(): 16642742Swollman * Set the font data in the requested font page. 16652742Swollman * NOTE: it appears that some recent video adapters do not support 16662742Swollman * the font page other than 0... XXX 16672742Swollman * 16682742Swollman * EGA/VGA 16692742Swollman */ 16702742Swollmanstatic int 16712742Swollmanvga_load_font(video_adapter_t *adp, int page, int fontsize, u_char *data, 16722742Swollman int ch, int count) 16732742Swollman{ 16742742Swollman#ifndef VGA_NO_FONT_LOADING 16752742Swollman u_char buf[PARAM_BUFSIZE]; 16762742Swollman u_int32_t segment; 167743014Swollman int c; 16782742Swollman#ifdef VGA_ALT_SEQACCESS 16792742Swollman int s; 16802742Swollman u_char val = 0; 16812742Swollman#endif 16822742Swollman 16832742Swollman prologue(adp, V_ADP_FONT, 1); 16842742Swollman 16852742Swollman if (fontsize < 14) { 16862742Swollman /* FONT_8 */ 16872742Swollman fontsize = 8; 16882742Swollman } else if (fontsize >= 32) { 16892742Swollman fontsize = 32; 16902742Swollman } else if (fontsize >= 16) { 16912742Swollman /* FONT_16 */ 16922742Swollman fontsize = 16; 16932742Swollman } else { 16942742Swollman /* FONT_14 */ 16952742Swollman fontsize = 14; 16962742Swollman } 16972742Swollman 16982742Swollman if (page < 0 || page >= 8) 16992742Swollman return 1; 17002742Swollman segment = FONT_BUF + 0x4000*page; 17012742Swollman if (page > 3) 170243014Swollman segment -= 0xe000; 17032742Swollman 17042742Swollman#ifdef VGA_ALT_SEQACCESS 17052742Swollman if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ 17062742Swollman s = splhigh(); 17072742Swollman outb(TSIDX, 0x00); outb(TSREG, 0x01); 17082742Swollman outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 170920094Swollman outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 171020094Swollman outb(TSIDX, 0x00); outb(TSREG, 0x03); 171120094Swollman splx(s); 171220094Swollman } 17132742Swollman#endif 17142742Swollman 17152742Swollman set_font_mode(adp, buf); 171658787Sru if (fontsize == 32) { 17172742Swollman bcopy_toio(data, segment + ch*32, fontsize*count); 17182742Swollman } else { 17192742Swollman for (c = ch; count > 0; ++c, --count) { 17202742Swollman bcopy_toio(data, segment + c*32, fontsize); 17212742Swollman data += fontsize; 17222742Swollman } 172358787Sru } 172458787Sru set_normal_mode(adp, buf); 172558787Sru 172658787Sru#ifdef VGA_ALT_SEQACCESS 172758787Sru if (adp->va_type == KD_VGA) { 172858787Sru s = splhigh(); 172958787Sru outb(TSIDX, 0x00); outb(TSREG, 0x01); 173058787Sru outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ 173158787Sru outb(TSIDX, 0x00); outb(TSREG, 0x03); 173258787Sru splx(s); 17332742Swollman } 1734138323Swollman#endif 1735138323Swollman 1736138323Swollman return 0; 1737138323Swollman#else /* VGA_NO_FONT_LOADING */ 1738138323Swollman return 1; 1739138323Swollman#endif /* VGA_NO_FONT_LOADING */ 1740138323Swollman} 1741138323Swollman 1742138323Swollman/* 17432742Swollman * show_font(): 17442742Swollman * Activate the requested font page. 17452742Swollman * NOTE: it appears that some recent video adapters do not support 17462742Swollman * the font page other than 0... XXX 17472742Swollman * 17482742Swollman * EGA/VGA 17492742Swollman */ 17502742Swollmanstatic int 17512742Swollmanvga_show_font(video_adapter_t *adp, int page) 17522742Swollman{ 17532742Swollman#ifndef VGA_NO_FONT_LOADING 17542742Swollman static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f }; 17552742Swollman int s; 17562742Swollman 17572742Swollman prologue(adp, V_ADP_FONT, 1); 17582742Swollman if (page < 0 || page >= 8) 17592742Swollman return 1; 17602742Swollman 17612742Swollman s = splhigh(); 176230711Swollman outb(TSIDX, 0x03); outb(TSREG, cg[page]); 17632742Swollman splx(s); 17642742Swollman 17652742Swollman return 0; 176643014Swollman#else /* VGA_NO_FONT_LOADING */ 176720094Swollman return 1; 176843014Swollman#endif /* VGA_NO_FONT_LOADING */ 176943014Swollman} 177058787Sru 1771138323Swollman/* 177258787Sru * save_palette(): 1773138323Swollman * Read DAC values. The values have expressed in 8 bits. 17742742Swollman * 17752742Swollman * VGA 17762742Swollman */ 177758787Srustatic int 17782742Swollmanvga_save_palette(video_adapter_t *adp, u_char *palette) 17792742Swollman{ 17802742Swollman int i; 17812742Swollman 17822742Swollman prologue(adp, V_ADP_PALETTE, 1); 17832742Swollman 17842742Swollman /* 17852742Swollman * We store 8 bit values in the palette buffer, while the standard 178675267Swollman * VGA has 6 bit DAC . 178775267Swollman */ 178875267Swollman outb(PALRADR, 0x00); 178975267Swollman for (i = 0; i < 256*3; ++i) 179075267Swollman palette[i] = inb(PALDATA) << 2; 179175267Swollman inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 179275267Swollman return 0; 179375267Swollman} 179475267Swollman 179575267Swollman/* 179675267Swollman * load_palette(): 179775267Swollman * Set DAC values. 179875267Swollman * 179975267Swollman * VGA 180075267Swollman */ 180175267Swollmanstatic int 180275267Swollmanvga_load_palette(video_adapter_t *adp, u_char *palette) 180375267Swollman{ 180475267Swollman int i; 18052742Swollman 18062742Swollman prologue(adp, V_ADP_PALETTE, 1); 18072742Swollman 18082742Swollman outb(PIXMASK, 0xff); /* no pixelmask */ 18092742Swollman outb(PALWADR, 0x00); 18102742Swollman for (i = 0; i < 256*3; ++i) 18112742Swollman outb(PALDATA, palette[i] >> 2); 18122742Swollman inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 18132742Swollman outb(ATC, 0x20); /* enable palette */ 18142742Swollman return 0; 18152742Swollman} 181675267Swollman 181775267Swollman/* 18182742Swollman * set_border(): 18192742Swollman * Change the border color. 18202742Swollman * 18212742Swollman * CGA/EGA/VGA 18222742Swollman */ 18232742Swollmanstatic int 1824121098Swollmanvga_set_border(video_adapter_t *adp, int color) 1825121098Swollman{ 18262742Swollman prologue(adp, V_ADP_BORDER, 1); 18272742Swollman 18282742Swollman switch (adp->va_type) { 18292742Swollman case KD_EGA: 18302742Swollman case KD_VGA: 18312742Swollman inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 183219878Swollman outb(ATC, 0x31); outb(ATC, color & 0xff); 18332742Swollman break; 18342742Swollman case KD_CGA: 18352742Swollman outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */ 18362742Swollman break; 18372742Swollman case KD_MONO: 18382742Swollman case KD_HERCULES: 18392742Swollman default: 18402742Swollman break; 18412742Swollman } 18422742Swollman return 0; 18432742Swollman} 18442742Swollman 18452742Swollman/* 184620094Swollman * save_state(): 184720094Swollman * Read video register values. 18482742Swollman * NOTE: this function only reads the standard EGA/VGA registers. 18492742Swollman * any extra/extended registers of SVGA adapters are not saved. 18502742Swollman * 18512742Swollman * VGA 18522742Swollman */ 18532742Swollmanstatic int 18542742Swollmanvga_save_state(video_adapter_t *adp, void *p, size_t size) 18552742Swollman{ 18562742Swollman video_info_t info; 185758787Sru u_char *buf; 185843014Swollman int crtc_addr; 185943014Swollman int i, j; 18602742Swollman int s; 18612742Swollman 18622742Swollman if (size == 0) { 18632742Swollman /* return the required buffer size */ 18642742Swollman prologue(adp, V_ADP_STATESAVE, 0); 18652742Swollman return sizeof(adp_state_t); 18662742Swollman } else { 18672742Swollman prologue(adp, V_ADP_STATESAVE, 1); 18682742Swollman if (size < sizeof(adp_state_t)) 18692742Swollman return 1; 187043543Swollman } 187143543Swollman 18722742Swollman ((adp_state_t *)p)->sig = V_STATE_SIG; 18732742Swollman buf = ((adp_state_t *)p)->regs; 18742742Swollman bzero(buf, V_MODE_PARAM_SIZE); 187519878Swollman crtc_addr = adp->va_crtc_addr; 18762742Swollman 18772742Swollman s = splhigh(); 187819878Swollman 18792742Swollman outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 18802742Swollman for (i = 0, j = 5; i < 4; i++) { 188158787Sru outb(TSIDX, i + 1); 18822742Swollman buf[j++] = inb(TSREG); 18832742Swollman } 188443014Swollman buf[9] = inb(MISC + 10); /* dot-clock */ 188558787Sru outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 188620094Swollman 188720094Swollman for (i = 0, j = 10; i < 25; i++) { /* crtc */ 18882742Swollman outb(crtc_addr, i); 18892742Swollman buf[j++] = inb(crtc_addr + 1); 18902742Swollman } 18912742Swollman for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */ 189286222Swollman inb(crtc_addr + 6); /* reset flip-flop */ 18932742Swollman outb(ATC, i); 18942742Swollman buf[j++] = inb(ATC + 1); 18952742Swollman } 18962742Swollman for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */ 18972742Swollman outb(GDCIDX, i); 189830711Swollman buf[j++] = inb(GDCREG); 189930711Swollman } 190030711Swollman inb(crtc_addr + 6); /* reset flip-flop */ 19012742Swollman outb(ATC, 0x20); /* enable palette */ 190230711Swollman 19032742Swollman splx(s); 19042742Swollman 19052742Swollman#if 1 190643543Swollman if (vga_get_info(adp, adp->va_mode, &info) == 0) { 190743543Swollman if (info.vi_flags & V_INFO_GRAPHICS) { 190843543Swollman buf[0] = info.vi_width/info.vi_cwidth; /* COLS */ 190943543Swollman buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */ 191043543Swollman } else { 19112742Swollman buf[0] = info.vi_width; /* COLS */ 19122742Swollman buf[1] = info.vi_height - 1; /* ROWS */ 19132742Swollman } 191420094Swollman buf[2] = info.vi_cheight; /* POINTS */ 191520094Swollman } else { 19162742Swollman /* XXX: shouldn't be happening... */ 19172742Swollman printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n", 191886222Swollman adp->va_unit, adp->va_name); 19192742Swollman } 19202742Swollman#else 192120094Swollman buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */ 192243543Swollman buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */ 192343543Swollman buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */ 19242742Swollman buf[3] = readb(BIOS_PADDRTOVADDR(0x44c)); 19252742Swollman buf[4] = readb(BIOS_PADDRTOVADDR(0x44d)); 19262742Swollman#endif 19272742Swollman 192886222Swollman return 0; 19292742Swollman} 19302742Swollman 19312742Swollman/* 19322742Swollman * load_state(): 19332742Swollman * Set video registers at once. 193414343Swollman * NOTE: this function only updates the standard EGA/VGA registers. 19352742Swollman * any extra/extended registers of SVGA adapters are not changed. 193614343Swollman * 19372742Swollman * EGA/VGA 19382742Swollman */ 19392742Swollmanstatic int 19402742Swollmanvga_load_state(video_adapter_t *adp, void *p) 19412742Swollman{ 19422742Swollman u_char *buf; 19432742Swollman int crtc_addr; 19442742Swollman int s; 19452742Swollman int i; 19462742Swollman 194786222Swollman prologue(adp, V_ADP_STATELOAD, 1); 19482742Swollman if (((adp_state_t *)p)->sig != V_STATE_SIG) 19492742Swollman return 1; 19502742Swollman 19512742Swollman buf = ((adp_state_t *)p)->regs; 19522742Swollman crtc_addr = adp->va_crtc_addr; 19532742Swollman 19542742Swollman s = splhigh(); 1955121098Swollman 1956121098Swollman outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 19572742Swollman for (i = 0; i < 4; ++i) { /* program sequencer */ 19582742Swollman outb(TSIDX, i + 1); 19592742Swollman outb(TSREG, buf[i + 5]); 19602742Swollman } 196143014Swollman outb(MISC, buf[9]); /* set dot-clock */ 19622742Swollman outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 19632742Swollman outb(crtc_addr, 0x11); 19642742Swollman outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F); 196543014Swollman for (i = 0; i < 25; ++i) { /* program crtc */ 196643014Swollman outb(crtc_addr, i); 196720094Swollman outb(crtc_addr + 1, buf[i + 10]); 196820094Swollman } 196920094Swollman inb(crtc_addr+6); /* reset flip-flop */ 197020094Swollman for (i = 0; i < 20; ++i) { /* program attribute ctrl */ 197120094Swollman outb(ATC, i); 19722742Swollman outb(ATC, buf[i + 35]); 19732742Swollman } 197443014Swollman for (i = 0; i < 9; ++i) { /* program graph data ctrl */ 197520094Swollman outb(GDCIDX, i); 19768029Swollman outb(GDCREG, buf[i + 55]); 197714343Swollman } 19782742Swollman inb(crtc_addr + 6); /* reset flip-flop */ 197914343Swollman outb(ATC, 0x20); /* enable palette */ 19802742Swollman 19818029Swollman#if notyet /* a temporary workaround for kernel panic, XXX */ 198214343Swollman#ifndef VGA_NO_BIOS 198314343Swollman if (adp->va_unit == V_ADP_PRIMARY) { 198414343Swollman writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */ 198514343Swollman writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */ 1986 writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */ 1987#if 0 1988 writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]); 1989 writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]); 1990#endif 1991 } 1992#endif /* VGA_NO_BIOS */ 1993#endif /* notyet */ 1994 1995 splx(s); 1996 return 0; 1997} 1998 1999/* 2000 * set_origin(): 2001 * Change the origin (window mapping) of the banked frame buffer. 2002 */ 2003static int 2004vga_set_origin(video_adapter_t *adp, off_t offset) 2005{ 2006 /* 2007 * The standard video modes do not require window mapping; 2008 * always return error. 2009 */ 2010 return 1; 2011} 2012 2013/* 2014 * read_hw_cursor(): 2015 * Read the position of the hardware text cursor. 2016 * 2017 * all adapters 2018 */ 2019static int 2020vga_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 2021{ 2022 u_int16_t off; 2023 int s; 2024 2025 if (!init_done) 2026 return 1; 2027 2028 if (adp->va_info.vi_flags & V_INFO_GRAPHICS) 2029 return 1; 2030 2031 s = spltty(); 2032 outb(adp->va_crtc_addr, 14); 2033 off = inb(adp->va_crtc_addr + 1); 2034 outb(adp->va_crtc_addr, 15); 2035 off = (off << 8) | inb(adp->va_crtc_addr + 1); 2036 splx(s); 2037 2038 *row = off / adp->va_info.vi_width; 2039 *col = off % adp->va_info.vi_width; 2040 2041 return 0; 2042} 2043 2044/* 2045 * set_hw_cursor(): 2046 * Move the hardware text cursor. If col and row are both -1, 2047 * the cursor won't be shown. 2048 * 2049 * all adapters 2050 */ 2051static int 2052vga_set_hw_cursor(video_adapter_t *adp, int col, int row) 2053{ 2054 u_int16_t off; 2055 int s; 2056 2057 if (!init_done) 2058 return 1; 2059 2060 if ((col == -1) && (row == -1)) { 2061 off = -1; 2062 } else { 2063 if (adp->va_info.vi_flags & V_INFO_GRAPHICS) 2064 return 1; 2065 off = row*adp->va_info.vi_width + col; 2066 } 2067 2068 s = spltty(); 2069 outb(adp->va_crtc_addr, 14); 2070 outb(adp->va_crtc_addr + 1, off >> 8); 2071 outb(adp->va_crtc_addr, 15); 2072 outb(adp->va_crtc_addr + 1, off & 0x00ff); 2073 splx(s); 2074 2075 return 0; 2076} 2077 2078/* 2079 * set_hw_cursor_shape(): 2080 * Change the shape of the hardware text cursor. If the height is 2081 * zero or negative, the cursor won't be shown. 2082 * 2083 * all adapters 2084 */ 2085static int 2086vga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 2087 int celsize, int blink) 2088{ 2089 int s; 2090 2091 if (!init_done) 2092 return 1; 2093 2094 s = spltty(); 2095 switch (adp->va_type) { 2096 case KD_VGA: 2097 case KD_CGA: 2098 case KD_MONO: 2099 case KD_HERCULES: 2100 default: 2101 if (height <= 0) { 2102 /* make the cursor invisible */ 2103 outb(adp->va_crtc_addr, 10); 2104 outb(adp->va_crtc_addr + 1, 32); 2105 outb(adp->va_crtc_addr, 11); 2106 outb(adp->va_crtc_addr + 1, 0); 2107 } else { 2108 outb(adp->va_crtc_addr, 10); 2109 outb(adp->va_crtc_addr + 1, celsize - base - height); 2110 outb(adp->va_crtc_addr, 11); 2111 outb(adp->va_crtc_addr + 1, celsize - base - 1); 2112 } 2113 break; 2114 case KD_EGA: 2115 if (height <= 0) { 2116 /* make the cursor invisible */ 2117 outb(adp->va_crtc_addr, 10); 2118 outb(adp->va_crtc_addr + 1, celsize); 2119 outb(adp->va_crtc_addr, 11); 2120 outb(adp->va_crtc_addr + 1, 0); 2121 } else { 2122 outb(adp->va_crtc_addr, 10); 2123 outb(adp->va_crtc_addr + 1, celsize - base - height); 2124 outb(adp->va_crtc_addr, 11); 2125 outb(adp->va_crtc_addr + 1, celsize - base); 2126 } 2127 break; 2128 } 2129 splx(s); 2130 2131 return 0; 2132} 2133 2134/* 2135 * mmap(): 2136 * Mmap frame buffer. 2137 * 2138 * all adapters 2139 */ 2140static int 2141vga_mmap(video_adapter_t *adp, vm_offset_t offset) 2142{ 2143 if (offset > 0x20000 - PAGE_SIZE) 2144 return -1; 2145#ifdef __i386__ 2146 return i386_btop((VIDEO_BUF_BASE + offset)); 2147#endif 2148#ifdef __alpha__ 2149 return alpha_btop((VIDEO_BUF_BASE + offset)); 2150#endif 2151} 2152 2153static void 2154dump_buffer(u_char *buf, size_t len) 2155{ 2156 int i; 2157 2158 for(i = 0; i < len;) { 2159 printf("%02x ", buf[i]); 2160 if ((++i % 16) == 0) 2161 printf("\n"); 2162 } 2163} 2164 2165/* 2166 * diag(): 2167 * Print some information about the video adapter and video modes, 2168 * with requested level of details. 2169 * 2170 * all adapters 2171 */ 2172static int 2173vga_diag(video_adapter_t *adp, int level) 2174{ 2175#if FB_DEBUG > 1 2176 video_info_t info; 2177#endif 2178 u_char *mp; 2179 2180 if (!init_done) 2181 return 1; 2182 2183#if FB_DEBUG > 1 2184#ifndef VGA_NO_BIOS 2185 printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n", 2186 rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488))); 2187 printf("vga: CRTC:0x%x, video option:0x%02x, ", 2188 readw(BIOS_PADDRTOVADDR(0x463)), 2189 readb(BIOS_PADDRTOVADDR(0x487))); 2190 printf("rows:%d, cols:%d, font height:%d\n", 2191 readb(BIOS_PADDRTOVADDR(0x44a)), 2192 readb(BIOS_PADDRTOVADDR(0x484)) + 1, 2193 readb(BIOS_PADDRTOVADDR(0x485))); 2194#endif /* VGA_NO_BIOS */ 2195#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 2196 printf("vga: param table EGA/VGA:%p", video_mode_ptr); 2197 printf(", CGA/MDA:%p\n", video_mode_ptr2); 2198#endif 2199 printf("vga: rows_offset:%d\n", rows_offset); 2200#endif /* FB_DEBUG > 1 */ 2201 2202 fb_dump_adp_info(DRIVER_NAME, adp, level); 2203 2204#if FB_DEBUG > 1 2205 if (adp->va_flags & V_ADP_MODECHANGE) { 2206 for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 2207 if (bios_vmode[i].vi_mode == NA) 2208 continue; 2209 if (get_mode_param(bios_vmode[i].vi_mode) == NULL) 2210 continue; 2211 fb_dump_mode_info(DRIVER_NAME, adp, &bios_vmode[i], level); 2212 } 2213 } else { 2214 vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */ 2215 fb_dump_mode_info(DRIVER_NAME, adp, &info, level); 2216 } 2217#endif /* FB_DEBUG > 1 */ 2218 2219 if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA)) 2220 return 0; 2221#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 2222 if (video_mode_ptr == NULL) 2223 printf("vga%d: %s: WARNING: video mode switching is not " 2224 "fully supported on this adapter\n", 2225 adp->va_unit, adp->va_name); 2226#endif 2227 if (level <= 0) 2228 return 0; 2229 2230 if (adp->va_type == KD_VGA) { 2231 printf("VGA parameters upon power-up\n"); 2232 dump_buffer(adpstate.regs, sizeof(adpstate.regs)); 2233 printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode); 2234 dump_buffer(adpstate2.regs, sizeof(adpstate2.regs)); 2235 } 2236 2237 mp = get_mode_param(adp->va_initial_mode); 2238 if (mp == NULL) /* this shouldn't be happening */ 2239 return 0; 2240 printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode); 2241 dump_buffer(mp, V_MODE_PARAM_SIZE); 2242 2243 return 0; 2244} 2245 2246#endif /* NVGA > 0 */ 2247