148104Syokota/*- 248104Syokota * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 348104Syokota * Copyright (c) 1992-1998 S�ren Schmidt 448104Syokota * All rights reserved. 548104Syokota * 648104Syokota * Redistribution and use in source and binary forms, with or without 748104Syokota * modification, are permitted provided that the following conditions 848104Syokota * are met: 948104Syokota * 1. Redistributions of source code must retain the above copyright 1048104Syokota * notice, this list of conditions and the following disclaimer as 1148104Syokota * the first lines of this file unmodified. 1248104Syokota * 2. Redistributions in binary form must reproduce the above copyright 1348104Syokota * notice, this list of conditions and the following disclaimer in the 1448104Syokota * documentation and/or other materials provided with the distribution. 1548104Syokota * 3. The name of the author may not be used to endorse or promote products 1648104Syokota * derived from this software without specific prior written permission. 1748104Syokota * 1848104Syokota * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 1948104Syokota * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2048104Syokota * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2148104Syokota * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 2248104Syokota * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2348104Syokota * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2448104Syokota * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2548104Syokota * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2648104Syokota * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2748104Syokota * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2848104Syokota * 2948104Syokota */ 3048104Syokota 31119418Sobrien#include <sys/cdefs.h> 32119418Sobrien__FBSDID("$FreeBSD$"); 33119418Sobrien 3448104Syokota#include "opt_vga.h" 3548104Syokota#include "opt_fb.h" 36153072Sru#ifndef FB_DEBUG 37153072Sru#define FB_DEBUG 0 38153072Sru#endif 3948104Syokota#include "opt_syscons.h" /* should be removed in the future, XXX */ 4048104Syokota 4148104Syokota#include <sys/param.h> 4248104Syokota#include <sys/systm.h> 4348104Syokota#include <sys/kernel.h> 4448104Syokota#include <sys/conf.h> 4548104Syokota#include <sys/fcntl.h> 4648104Syokota#include <sys/malloc.h> 4748104Syokota#include <sys/fbio.h> 4848104Syokota 4948104Syokota#include <vm/vm.h> 5048104Syokota#include <vm/vm_param.h> 5148104Syokota#include <vm/pmap.h> 5248104Syokota 5348104Syokota#include <machine/md_var.h> 54135690Speter#if defined(__i386__) || defined(__amd64__) 5548104Syokota#include <machine/pc/bios.h> 56114383Speter#endif 5765176Sdfr#include <machine/bus.h> 5848104Syokota 5948104Syokota#include <dev/fb/fbreg.h> 6048104Syokota#include <dev/fb/vgareg.h> 6148104Syokota 6248104Syokota#include <isa/isareg.h> 6348104Syokota 6448104Syokota#ifndef VGA_DEBUG 6548104Syokota#define VGA_DEBUG 0 6648104Syokota#endif 6748104Syokota 68114485Smarcel/* XXX machine/pc/bios.h has got too much i386-specific stuff in it */ 69114383Speter#ifndef BIOS_PADDRTOVADDR 70114485Smarcel#define BIOS_PADDRTOVADDR(x) (x) 71114383Speter#endif 72114485Smarcel 7348104Syokotaint 7448104Syokotavga_probe_unit(int unit, video_adapter_t *buf, int flags) 7548104Syokota{ 7648104Syokota video_adapter_t *adp; 7748104Syokota video_switch_t *sw; 7848104Syokota int error; 7948104Syokota 8048104Syokota sw = vid_get_switch(VGA_DRIVER_NAME); 8148104Syokota if (sw == NULL) 8248104Syokota return 0; 8348104Syokota error = (*sw->probe)(unit, &adp, NULL, flags); 8448104Syokota if (error) 8548104Syokota return error; 8648104Syokota bcopy(adp, buf, sizeof(*buf)); 8748104Syokota return 0; 8848104Syokota} 8948104Syokota 9048104Syokotaint 9148104Syokotavga_attach_unit(int unit, vga_softc_t *sc, int flags) 9248104Syokota{ 9348104Syokota video_switch_t *sw; 9448104Syokota int error; 9548104Syokota 9648104Syokota sw = vid_get_switch(VGA_DRIVER_NAME); 9748104Syokota if (sw == NULL) 9848104Syokota return ENXIO; 9948104Syokota 10048104Syokota error = (*sw->probe)(unit, &sc->adp, NULL, flags); 10148104Syokota if (error) 10248104Syokota return error; 10348104Syokota return (*sw->init)(unit, sc->adp, flags); 10448104Syokota} 10548104Syokota 10648104Syokota/* cdev driver functions */ 10748104Syokota 10848104Syokota#ifdef FB_INSTALL_CDEV 10948104Syokota 11048104Syokotaint 111130585Sphkvga_open(struct cdev *dev, vga_softc_t *sc, int flag, int mode, struct thread *td) 11248104Syokota{ 11348104Syokota if (sc == NULL) 11448104Syokota return ENXIO; 11548104Syokota if (mode & (O_CREAT | O_APPEND | O_TRUNC)) 11648104Syokota return ENODEV; 11748104Syokota 11883366Sjulian return genfbopen(&sc->gensc, sc->adp, flag, mode, td); 11948104Syokota} 12048104Syokota 12148104Syokotaint 122130585Sphkvga_close(struct cdev *dev, vga_softc_t *sc, int flag, int mode, struct thread *td) 12348104Syokota{ 12483366Sjulian return genfbclose(&sc->gensc, sc->adp, flag, mode, td); 12548104Syokota} 12648104Syokota 12748104Syokotaint 128130585Sphkvga_read(struct cdev *dev, vga_softc_t *sc, struct uio *uio, int flag) 12948104Syokota{ 13048104Syokota return genfbread(&sc->gensc, sc->adp, uio, flag); 13148104Syokota} 13248104Syokota 13348104Syokotaint 134130585Sphkvga_write(struct cdev *dev, vga_softc_t *sc, struct uio *uio, int flag) 13548104Syokota{ 13648104Syokota return genfbread(&sc->gensc, sc->adp, uio, flag); 13748104Syokota} 13848104Syokota 13948104Syokotaint 140130585Sphkvga_ioctl(struct cdev *dev, vga_softc_t *sc, u_long cmd, caddr_t arg, int flag, 14183366Sjulian struct thread *td) 14248104Syokota{ 14383366Sjulian return genfbioctl(&sc->gensc, sc->adp, cmd, arg, flag, td); 14448104Syokota} 14548104Syokota 14648104Syokotaint 147201223Srnolandvga_mmap(struct cdev *dev, vga_softc_t *sc, vm_ooffset_t offset, 148201223Srnoland vm_offset_t *paddr, int prot, vm_memattr_t *memattr) 14948104Syokota{ 150201223Srnoland return genfbmmap(&sc->gensc, sc->adp, offset, paddr, prot, memattr); 15148104Syokota} 15248104Syokota 15348104Syokota#endif /* FB_INSTALL_CDEV */ 15448104Syokota 15548104Syokota/* LOW-LEVEL */ 15648104Syokota 157178193Sphk#include <isa/rtc.h> 158114383Speter#ifdef __i386__ 159197025Sdelphij#include <dev/fb/vesa.h> 160114383Speter#endif 16148104Syokota 16248104Syokota#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED) 16348104Syokota#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED) 16448104Syokota#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED) 16548104Syokota 16648104Syokota/* for compatibility with old kernel options */ 16748104Syokota#ifdef SC_ALT_SEQACCESS 16848104Syokota#undef SC_ALT_SEQACCESS 16948104Syokota#undef VGA_ALT_SEQACCESS 17048104Syokota#define VGA_ALT_SEQACCESS 1 17148104Syokota#endif 17248104Syokota 17348104Syokota#ifdef SLOW_VGA 17448104Syokota#undef SLOW_VGA 17548104Syokota#undef VGA_SLOW_IOACCESS 176153072Sru#define VGA_SLOW_IOACCESS 17748104Syokota#endif 17848104Syokota 17948104Syokota/* architecture dependent option */ 180197185Sdelphij#if !defined(__i386__) && !defined(__amd64__) 18148104Syokota#define VGA_NO_BIOS 1 18248104Syokota#endif 18348104Syokota 18448104Syokota/* this should really be in `rtc.h' */ 18548104Syokota#define RTC_EQUIPMENT 0x14 18648104Syokota 18748104Syokota/* various sizes */ 18848104Syokota#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1) 18948104Syokota#define V_MODE_PARAM_SIZE 64 19048104Syokota 19148104Syokota/* video adapter state buffer */ 19248104Syokotastruct adp_state { 19348104Syokota int sig; 19448104Syokota#define V_STATE_SIG 0x736f6962 19548104Syokota u_char regs[V_MODE_PARAM_SIZE]; 19648104Syokota}; 19748104Syokotatypedef struct adp_state adp_state_t; 19848104Syokota 19948104Syokota/* video adapter information */ 20048104Syokota#define DCC_MONO 0 20148104Syokota#define DCC_CGA40 1 20248104Syokota#define DCC_CGA80 2 20348104Syokota#define DCC_EGAMONO 3 20448104Syokota#define DCC_EGA40 4 20548104Syokota#define DCC_EGA80 5 20648104Syokota 20748104Syokota/* 20848104Syokota * NOTE: `va_window' should have a virtual address, but is initialized 20948104Syokota * with a physical address in the following table, as verify_adapter() 21048104Syokota * will perform address conversion at run-time. 21148104Syokota */ 21248104Syokotastatic video_adapter_t adapter_init_value[] = { 21348104Syokota /* DCC_MONO */ 21448104Syokota { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC, 21548104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 21648104Syokota 0, 0, 0, 0, 7, 0, }, 21748104Syokota /* DCC_CGA40 */ 21848104Syokota { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, 21948104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 22048104Syokota 0, 0, 0, 0, 3, 0, }, 22148104Syokota /* DCC_CGA80 */ 22248104Syokota { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, 22348104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 22448104Syokota 0, 0, 0, 0, 3, 0, }, 22548104Syokota /* DCC_EGAMONO */ 22648104Syokota { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC, 22748104Syokota EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 22848104Syokota 0, 0, 0, 0, 7, 0, }, 22948104Syokota /* DCC_EGA40 */ 23048104Syokota { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, 23148104Syokota EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 23248104Syokota 0, 0, 0, 0, 3, 0, }, 23348104Syokota /* DCC_EGA80 */ 23448104Syokota { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, 23548104Syokota EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 23648104Syokota 0, 0, 0, 0, 3, 0, }, 23748104Syokota}; 23848104Syokota 23948104Syokotastatic video_adapter_t biosadapter[2]; 24048104Syokotastatic int biosadapters = 0; 24148104Syokota 24248104Syokota/* video driver declarations */ 24348104Syokotastatic int vga_configure(int flags); 24448104Syokota int (*vga_sub_configure)(int flags); 24548238Speter#if 0 24648104Syokotastatic int vga_nop(void); 24748238Speter#endif 24848104Syokotastatic int vga_error(void); 24948104Syokotastatic vi_probe_t vga_probe; 25048104Syokotastatic vi_init_t vga_init; 25148104Syokotastatic vi_get_info_t vga_get_info; 25248104Syokotastatic vi_query_mode_t vga_query_mode; 25348104Syokotastatic vi_set_mode_t vga_set_mode; 25448104Syokotastatic vi_save_font_t vga_save_font; 25548104Syokotastatic vi_load_font_t vga_load_font; 25648104Syokotastatic vi_show_font_t vga_show_font; 25748104Syokotastatic vi_save_palette_t vga_save_palette; 25848104Syokotastatic vi_load_palette_t vga_load_palette; 25948104Syokotastatic vi_set_border_t vga_set_border; 26048104Syokotastatic vi_save_state_t vga_save_state; 26148104Syokotastatic vi_load_state_t vga_load_state; 26248104Syokotastatic vi_set_win_org_t vga_set_origin; 26348104Syokotastatic vi_read_hw_cursor_t vga_read_hw_cursor; 26448104Syokotastatic vi_set_hw_cursor_t vga_set_hw_cursor; 26548104Syokotastatic vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape; 26648104Syokotastatic vi_blank_display_t vga_blank_display; 26748104Syokotastatic vi_mmap_t vga_mmap_buf; 26848104Syokotastatic vi_ioctl_t vga_dev_ioctl; 26948104Syokota#ifndef VGA_NO_MODE_CHANGE 27048104Syokotastatic vi_clear_t vga_clear; 27148104Syokotastatic vi_fill_rect_t vga_fill_rect; 27248104Syokotastatic vi_bitblt_t vga_bitblt; 27348104Syokota#else /* VGA_NO_MODE_CHANGE */ 27448104Syokota#define vga_clear (vi_clear_t *)vga_error 27548104Syokota#define vga_fill_rect (vi_fill_rect_t *)vga_error 27648104Syokota#define vga_bitblt (vi_bitblt_t *)vga_error 27748104Syokota#endif 27848104Syokotastatic vi_diag_t vga_diag; 27948104Syokota 28048104Syokotastatic video_switch_t vgavidsw = { 28148104Syokota vga_probe, 28248104Syokota vga_init, 28348104Syokota vga_get_info, 28448104Syokota vga_query_mode, 28548104Syokota vga_set_mode, 28648104Syokota vga_save_font, 28748104Syokota vga_load_font, 28848104Syokota vga_show_font, 28948104Syokota vga_save_palette, 29048104Syokota vga_load_palette, 29148104Syokota vga_set_border, 29248104Syokota vga_save_state, 29348104Syokota vga_load_state, 29448104Syokota vga_set_origin, 29548104Syokota vga_read_hw_cursor, 29648104Syokota vga_set_hw_cursor, 29748104Syokota vga_set_hw_cursor_shape, 29848104Syokota vga_blank_display, 29948104Syokota vga_mmap_buf, 30048104Syokota vga_dev_ioctl, 30148104Syokota vga_clear, 30248104Syokota vga_fill_rect, 30348104Syokota vga_bitblt, 30448104Syokota vga_error, 30548104Syokota vga_error, 30648104Syokota vga_diag, 30748104Syokota}; 30848104Syokota 30948104SyokotaVIDEO_DRIVER(mda, vgavidsw, NULL); 31048104SyokotaVIDEO_DRIVER(cga, vgavidsw, NULL); 31148104SyokotaVIDEO_DRIVER(ega, vgavidsw, NULL); 31248104SyokotaVIDEO_DRIVER(vga, vgavidsw, vga_configure); 31348104Syokota 31448104Syokota/* VGA BIOS standard video modes */ 31548104Syokota#define EOT (-1) 31648104Syokota#define NA (-2) 31748104Syokota 31848104Syokotastatic video_info_t bios_vmode[] = { 31948104Syokota /* CGA */ 32048104Syokota { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1, 32148104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 32248104Syokota { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1, 32348104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 32448104Syokota { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1, 32548104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 32648104Syokota { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1, 32748104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 32848104Syokota /* EGA */ 32948104Syokota { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, 33048104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 33148104Syokota { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, 33248104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 33348104Syokota { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, 33448104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 33548104Syokota { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, 33648104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 33748104Syokota /* VGA */ 33848104Syokota { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, 33948104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 34048104Syokota { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1, 34148104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 34248104Syokota { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, 34348104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 34448104Syokota /* MDA */ 34548104Syokota { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1, 34648104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 34748104Syokota /* EGA */ 34848104Syokota { M_ENH_B80x43, 0, 80, 43, 8, 8, 2, 1, 34948104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 35048104Syokota { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1, 35148104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 35248104Syokota /* VGA */ 35348104Syokota { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1, 35448104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 35548104Syokota { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, 35648104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 35748104Syokota { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1, 35848104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 35948104Syokota { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1, 36048104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 36148104Syokota { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1, 36248104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 36348104Syokota { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1, 36448104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 36548104Syokota 36648104Syokota#ifndef VGA_NO_MODE_CHANGE 36748104Syokota 36848104Syokota#ifdef VGA_WIDTH90 36948104Syokota { M_VGA_M90x25, 0, 90, 25, 8, 16, 2, 1, 37048104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 37148104Syokota { M_VGA_C90x25, V_INFO_COLOR, 90, 25, 8, 16, 4, 1, 37248104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 37348104Syokota { M_VGA_M90x30, 0, 90, 30, 8, 16, 2, 1, 37448104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 37548104Syokota { M_VGA_C90x30, V_INFO_COLOR, 90, 30, 8, 16, 4, 1, 37648104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 37748104Syokota { M_VGA_M90x43, 0, 90, 43, 8, 8, 2, 1, 37848104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 37948104Syokota { M_VGA_C90x43, V_INFO_COLOR, 90, 43, 8, 8, 4, 1, 38048104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 38148104Syokota { M_VGA_M90x50, 0, 90, 50, 8, 8, 2, 1, 38248104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 38348104Syokota { M_VGA_C90x50, V_INFO_COLOR, 90, 50, 8, 8, 4, 1, 38448104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 38548104Syokota { M_VGA_M90x60, 0, 90, 60, 8, 8, 2, 1, 38648104Syokota MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 38748104Syokota { M_VGA_C90x60, V_INFO_COLOR, 90, 60, 8, 8, 4, 1, 38848104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_TEXT }, 38948104Syokota#endif /* VGA_WIDTH90 */ 39048104Syokota 39148104Syokota /* CGA */ 39248104Syokota { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, 39348104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA }, 39448104Syokota { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, 39548104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA }, 39648104Syokota { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1, 39748104Syokota CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, V_INFO_MM_CGA }, 39848104Syokota /* EGA */ 39948104Syokota { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4, 40048104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0, 40148104Syokota V_INFO_MM_PLANAR }, 40248104Syokota { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4, 40348104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 , 40448104Syokota V_INFO_MM_PLANAR }, 40548104Syokota { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 40648104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 , 40748104Syokota V_INFO_MM_PLANAR }, 40848104Syokota { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 40948104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 , 41048104Syokota V_INFO_MM_PLANAR }, 41148104Syokota { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2, 41248104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 , 41348104Syokota V_INFO_MM_PLANAR }, 41448104Syokota { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, 41548104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 , 41648104Syokota V_INFO_MM_PLANAR }, 41748104Syokota /* VGA */ 41848104Syokota { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, 41948104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 , 42048104Syokota V_INFO_MM_PLANAR }, 42148104Syokota { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, 42248104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 , 42348104Syokota V_INFO_MM_PLANAR }, 42448104Syokota { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1, 42548104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0, 42648104Syokota V_INFO_MM_PACKED, 1 }, 42750299Syokota { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 4, 42848104Syokota GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0, 42950299Syokota V_INFO_MM_VGAX, 1 }, 43048104Syokota#endif /* VGA_NO_MODE_CHANGE */ 43148104Syokota 43248104Syokota { EOT }, 43348104Syokota}; 43448104Syokota 43548104Syokotastatic int vga_init_done = FALSE; 43648104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 43748104Syokotastatic u_char *video_mode_ptr = NULL; /* EGA/VGA */ 43848104Syokotastatic u_char *video_mode_ptr2 = NULL; /* CGA/MDA */ 43948104Syokota#endif 44048104Syokotastatic u_char *mode_map[V_MODE_MAP_SIZE]; 44148104Syokotastatic adp_state_t adpstate; 44248104Syokotastatic adp_state_t adpstate2; 44348104Syokotastatic int rows_offset = 1; 44448104Syokota 44548104Syokota/* local macros and functions */ 44648104Syokota#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff)) 44748104Syokota 44848104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 44948104Syokotastatic void map_mode_table(u_char *map[], u_char *table, int max); 45048104Syokota#endif 45148104Syokotastatic void clear_mode_map(video_adapter_t *adp, u_char *map[], int max, 45248104Syokota int color); 45348104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 45448104Syokotastatic int map_mode_num(int mode); 45548104Syokota#endif 45648104Syokotastatic int map_gen_mode_num(int type, int color, int mode); 45748104Syokotastatic int map_bios_mode_num(int type, int color, int bios_mode); 45848104Syokotastatic u_char *get_mode_param(int mode); 45948104Syokota#ifndef VGA_NO_BIOS 46048104Syokotastatic void fill_adapter_param(int code, video_adapter_t *adp); 46148104Syokota#endif 46248104Syokotastatic int verify_adapter(video_adapter_t *adp); 46348104Syokotastatic void update_adapter_info(video_adapter_t *adp, video_info_t *info); 46448104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 46548104Syokota#define COMP_IDENTICAL 0 46648104Syokota#define COMP_SIMILAR 1 46748104Syokota#define COMP_DIFFERENT 2 46848104Syokotastatic int comp_adpregs(u_char *buf1, u_char *buf2); 46948104Syokota#endif 47048104Syokotastatic int probe_adapters(void); 47148104Syokotastatic int set_line_length(video_adapter_t *adp, int pixel); 47248104Syokotastatic int set_display_start(video_adapter_t *adp, int x, int y); 47348104Syokota 47448104Syokota#ifndef VGA_NO_MODE_CHANGE 47548104Syokota#ifdef VGA_WIDTH90 47648104Syokotastatic void set_width90(adp_state_t *params); 47748104Syokota#endif 47848104Syokota#endif /* !VGA_NO_MODE_CHANGE */ 47948104Syokota 48048104Syokota#ifndef VGA_NO_FONT_LOADING 48148104Syokota#define PARAM_BUFSIZE 6 48248104Syokotastatic void set_font_mode(video_adapter_t *adp, u_char *buf); 48348104Syokotastatic void set_normal_mode(video_adapter_t *adp, u_char *buf); 48448104Syokota#endif 48548104Syokota 48648104Syokota#ifndef VGA_NO_MODE_CHANGE 487138891Srustatic void filll_io(int val, vm_offset_t d, size_t size); 48848104Syokotastatic void planar_fill(video_adapter_t *adp, int val); 48948104Syokotastatic void packed_fill(video_adapter_t *adp, int val); 49048104Syokotastatic void direct_fill(video_adapter_t *adp, int val); 49148104Syokota#ifdef notyet 49248104Syokotastatic void planar_fill_rect(video_adapter_t *adp, int val, int x, int y, 49348104Syokota int cx, int cy); 49448104Syokotastatic void packed_fill_rect(video_adapter_t *adp, int val, int x, int y, 49548104Syokota int cx, int cy); 49648104Syokotastatic void direct_fill_rect16(video_adapter_t *adp, int val, int x, int y, 49748104Syokota int cx, int cy); 49848104Syokotastatic void direct_fill_rect24(video_adapter_t *adp, int val, int x, int y, 49948104Syokota int cx, int cy); 50048104Syokotastatic void direct_fill_rect32(video_adapter_t *adp, int val, int x, int y, 50148104Syokota int cx, int cy); 50248104Syokota#endif /* notyet */ 50348104Syokota#endif /* !VGA_NO_MODE_CHANGE */ 50448104Syokota 50548104Syokotastatic void dump_buffer(u_char *buf, size_t len); 50648104Syokota 50748104Syokota#define ISMAPPED(pa, width) \ 50848104Syokota (((pa) <= (u_long)0x1000 - (width)) \ 50948104Syokota || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width))) 51048104Syokota 51148104Syokota#define prologue(adp, flag, err) \ 51248104Syokota if (!vga_init_done || !((adp)->va_flags & (flag))) \ 51348104Syokota return (err) 51448104Syokota 51548104Syokota/* a backdoor for the console driver */ 51648104Syokotastatic int 51748104Syokotavga_configure(int flags) 51848104Syokota{ 51948104Syokota int i; 52048104Syokota 52148104Syokota probe_adapters(); 52248104Syokota for (i = 0; i < biosadapters; ++i) { 52348104Syokota if (!probe_done(&biosadapter[i])) 52448104Syokota continue; 52548104Syokota biosadapter[i].va_flags |= V_ADP_INITIALIZED; 52648104Syokota if (!config_done(&biosadapter[i])) { 52748104Syokota if (vid_register(&biosadapter[i]) < 0) 52848104Syokota continue; 52948104Syokota biosadapter[i].va_flags |= V_ADP_REGISTERED; 53048104Syokota } 53148104Syokota } 53248104Syokota if (vga_sub_configure != NULL) 53348104Syokota (*vga_sub_configure)(flags); 53448104Syokota 53548104Syokota return biosadapters; 53648104Syokota} 53748104Syokota 53848104Syokota/* local subroutines */ 53948104Syokota 54048104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 54148104Syokota/* construct the mode parameter map */ 54248104Syokotastatic void 54348104Syokotamap_mode_table(u_char *map[], u_char *table, int max) 54448104Syokota{ 54548104Syokota int i; 54648104Syokota 54748104Syokota for(i = 0; i < max; ++i) 54848104Syokota map[i] = table + i*V_MODE_PARAM_SIZE; 54948104Syokota for(; i < V_MODE_MAP_SIZE; ++i) 55048104Syokota map[i] = NULL; 55148104Syokota} 55248104Syokota#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 55348104Syokota 55448104Syokotastatic void 55548104Syokotaclear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color) 55648104Syokota{ 55748104Syokota video_info_t info; 55848104Syokota int i; 55948104Syokota 56048104Syokota /* 56148104Syokota * NOTE: we don't touch `bios_vmode[]' because it is shared 56248104Syokota * by all adapters. 56348104Syokota */ 56448104Syokota for(i = 0; i < max; ++i) { 56548104Syokota if (vga_get_info(adp, i, &info)) 56648104Syokota continue; 56748104Syokota if ((info.vi_flags & V_INFO_COLOR) != color) 56848104Syokota map[i] = NULL; 56948104Syokota } 57048104Syokota} 57148104Syokota 57248104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 57348104Syokota/* map the non-standard video mode to a known mode number */ 57448104Syokotastatic int 57548104Syokotamap_mode_num(int mode) 57648104Syokota{ 57748104Syokota static struct { 57848104Syokota int from; 57948104Syokota int to; 58048104Syokota } mode_map[] = { 58148104Syokota { M_ENH_B80x43, M_ENH_B80x25 }, 58248104Syokota { M_ENH_C80x43, M_ENH_C80x25 }, 58348104Syokota { M_VGA_M80x30, M_VGA_M80x25 }, 58448104Syokota { M_VGA_C80x30, M_VGA_C80x25 }, 58548104Syokota { M_VGA_M80x50, M_VGA_M80x25 }, 58648104Syokota { M_VGA_C80x50, M_VGA_C80x25 }, 58748104Syokota { M_VGA_M80x60, M_VGA_M80x25 }, 58848104Syokota { M_VGA_C80x60, M_VGA_C80x25 }, 58948104Syokota#ifdef VGA_WIDTH90 59048104Syokota { M_VGA_M90x25, M_VGA_M80x25 }, 59148104Syokota { M_VGA_C90x25, M_VGA_C80x25 }, 59248104Syokota { M_VGA_M90x30, M_VGA_M80x25 }, 59348104Syokota { M_VGA_C90x30, M_VGA_C80x25 }, 59448104Syokota { M_VGA_M90x43, M_ENH_B80x25 }, 59548104Syokota { M_VGA_C90x43, M_ENH_C80x25 }, 59648104Syokota { M_VGA_M90x50, M_VGA_M80x25 }, 59748104Syokota { M_VGA_C90x50, M_VGA_C80x25 }, 59848104Syokota { M_VGA_M90x60, M_VGA_M80x25 }, 59948104Syokota { M_VGA_C90x60, M_VGA_C80x25 }, 60048104Syokota#endif 60148104Syokota { M_VGA_MODEX, M_VGA_CG320 }, 60248104Syokota }; 60348104Syokota int i; 60448104Syokota 60548104Syokota for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 60648104Syokota if (mode_map[i].from == mode) 60748104Syokota return mode_map[i].to; 60848104Syokota } 60948104Syokota return mode; 61048104Syokota} 61148104Syokota#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 61248104Syokota 61348104Syokota/* map a generic video mode to a known mode number */ 61448104Syokotastatic int 61548104Syokotamap_gen_mode_num(int type, int color, int mode) 61648104Syokota{ 61748104Syokota static struct { 61848104Syokota int from; 61948104Syokota int to_color; 62048104Syokota int to_mono; 62148104Syokota } mode_map[] = { 62248104Syokota { M_TEXT_80x30, M_VGA_C80x30, M_VGA_M80x30, }, 62348104Syokota { M_TEXT_80x43, M_ENH_C80x43, M_ENH_B80x43, }, 62448104Syokota { M_TEXT_80x50, M_VGA_C80x50, M_VGA_M80x50, }, 62548104Syokota { M_TEXT_80x60, M_VGA_C80x60, M_VGA_M80x60, }, 62648104Syokota }; 62748104Syokota int i; 62848104Syokota 62948104Syokota if (mode == M_TEXT_80x25) { 63048104Syokota switch (type) { 63148104Syokota 63248104Syokota case KD_VGA: 63348104Syokota if (color) 63448104Syokota return M_VGA_C80x25; 63548104Syokota else 63648104Syokota return M_VGA_M80x25; 63748104Syokota break; 63848104Syokota 63948104Syokota case KD_EGA: 64048104Syokota if (color) 64148104Syokota return M_ENH_C80x25; 64248104Syokota else 64348104Syokota return M_EGAMONO80x25; 64448104Syokota break; 64548104Syokota 64648104Syokota case KD_CGA: 64748104Syokota return M_C80x25; 64848104Syokota 64948104Syokota case KD_MONO: 65048104Syokota case KD_HERCULES: 65148104Syokota return M_EGAMONO80x25; /* XXX: this name is confusing */ 65248104Syokota 65348104Syokota default: 65448104Syokota return -1; 65548104Syokota } 65648104Syokota } 65748104Syokota 65848104Syokota for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) { 65948104Syokota if (mode_map[i].from == mode) 66048104Syokota return ((color) ? mode_map[i].to_color : mode_map[i].to_mono); 66148104Syokota } 66248104Syokota return mode; 66348104Syokota} 66448104Syokota 66548104Syokota/* turn the BIOS video number into our video mode number */ 66648104Syokotastatic int 66748104Syokotamap_bios_mode_num(int type, int color, int bios_mode) 66848104Syokota{ 66948104Syokota static int cga_modes[7] = { 67048104Syokota M_B40x25, M_C40x25, /* 0, 1 */ 67148104Syokota M_B80x25, M_C80x25, /* 2, 3 */ 67248104Syokota M_BG320, M_CG320, 67348104Syokota M_BG640, 67448104Syokota }; 67548104Syokota static int ega_modes[17] = { 67648104Syokota M_ENH_B40x25, M_ENH_C40x25, /* 0, 1 */ 67748104Syokota M_ENH_B80x25, M_ENH_C80x25, /* 2, 3 */ 67848104Syokota M_BG320, M_CG320, 67948104Syokota M_BG640, 68048104Syokota M_EGAMONO80x25, /* 7 */ 68148104Syokota 8, 9, 10, 11, 12, 68248104Syokota M_CG320_D, 68348104Syokota M_CG640_E, 68448104Syokota M_ENHMONOAPA2, /* XXX: video momery > 64K */ 68548104Syokota M_ENH_CG640, /* XXX: video momery > 64K */ 68648104Syokota }; 68748104Syokota static int vga_modes[20] = { 68848104Syokota M_VGA_C40x25, M_VGA_C40x25, /* 0, 1 */ 68948104Syokota M_VGA_C80x25, M_VGA_C80x25, /* 2, 3 */ 69048104Syokota M_BG320, M_CG320, 69148104Syokota M_BG640, 69248104Syokota M_VGA_M80x25, /* 7 */ 69348104Syokota 8, 9, 10, 11, 12, 69448104Syokota M_CG320_D, 69548104Syokota M_CG640_E, 69648104Syokota M_ENHMONOAPA2, 69748104Syokota M_ENH_CG640, 69848104Syokota M_BG640x480, M_CG640x480, 69948104Syokota M_VGA_CG320, 70048104Syokota }; 70148104Syokota 70248104Syokota switch (type) { 70348104Syokota 70448104Syokota case KD_VGA: 70548104Syokota if (bios_mode < sizeof(vga_modes)/sizeof(vga_modes[0])) 70648104Syokota return vga_modes[bios_mode]; 70748104Syokota else if (color) 70848104Syokota return M_VGA_C80x25; 70948104Syokota else 71048104Syokota return M_VGA_M80x25; 71148104Syokota break; 71248104Syokota 71348104Syokota case KD_EGA: 71448104Syokota if (bios_mode < sizeof(ega_modes)/sizeof(ega_modes[0])) 71548104Syokota return ega_modes[bios_mode]; 71648104Syokota else if (color) 71748104Syokota return M_ENH_C80x25; 71848104Syokota else 71948104Syokota return M_EGAMONO80x25; 72048104Syokota break; 72148104Syokota 72248104Syokota case KD_CGA: 72348104Syokota if (bios_mode < sizeof(cga_modes)/sizeof(cga_modes[0])) 72448104Syokota return cga_modes[bios_mode]; 72548104Syokota else 72648104Syokota return M_C80x25; 72748104Syokota break; 72848104Syokota 72948104Syokota case KD_MONO: 73048104Syokota case KD_HERCULES: 73148104Syokota return M_EGAMONO80x25; /* XXX: this name is confusing */ 73248104Syokota 73348104Syokota default: 73448104Syokota break; 73548104Syokota } 73648104Syokota return -1; 73748104Syokota} 73848104Syokota 73948104Syokota/* look up a parameter table entry */ 74048104Syokotastatic u_char 74148104Syokota*get_mode_param(int mode) 74248104Syokota{ 74348104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 74448104Syokota if (mode >= V_MODE_MAP_SIZE) 74548104Syokota mode = map_mode_num(mode); 74648104Syokota#endif 74748104Syokota if ((mode >= 0) && (mode < V_MODE_MAP_SIZE)) 74848104Syokota return mode_map[mode]; 74948104Syokota else 75048104Syokota return NULL; 75148104Syokota} 75248104Syokota 75348104Syokota#ifndef VGA_NO_BIOS 75448104Syokotastatic void 75548104Syokotafill_adapter_param(int code, video_adapter_t *adp) 75648104Syokota{ 75748104Syokota static struct { 75848104Syokota int primary; 75948104Syokota int secondary; 76048104Syokota } dcc[] = { 76148104Syokota { DCC_MONO, DCC_EGA40 /* CGA monitor */ }, 76248104Syokota { DCC_MONO, DCC_EGA80 /* CGA monitor */ }, 76348104Syokota { DCC_MONO, DCC_EGA80 }, 76455727Syokota { DCC_MONO, DCC_EGA80 }, 76548104Syokota { DCC_CGA40, DCC_EGAMONO }, 76648104Syokota { DCC_CGA80, DCC_EGAMONO }, 76748104Syokota { DCC_EGA40 /* CGA monitor */, DCC_MONO}, 76848104Syokota { DCC_EGA80 /* CGA monitor */, DCC_MONO}, 76955727Syokota { DCC_EGA80, DCC_MONO }, 77048104Syokota { DCC_EGA80, DCC_MONO }, 77148104Syokota { DCC_EGAMONO, DCC_CGA40 }, 77255727Syokota { DCC_EGAMONO, DCC_CGA80 }, 77348104Syokota }; 77448104Syokota 77548104Syokota if ((code < 0) || (code >= sizeof(dcc)/sizeof(dcc[0]))) { 77648104Syokota adp[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; 77748104Syokota adp[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; 77848104Syokota } else { 77948104Syokota adp[V_ADP_PRIMARY] = adapter_init_value[dcc[code].primary]; 78048104Syokota adp[V_ADP_SECONDARY] = adapter_init_value[dcc[code].secondary]; 78148104Syokota } 78248104Syokota} 78348104Syokota#endif /* VGA_NO_BIOS */ 78448104Syokota 78548104Syokotastatic int 78648104Syokotaverify_adapter(video_adapter_t *adp) 78748104Syokota{ 78848104Syokota vm_offset_t buf; 78948104Syokota u_int16_t v; 79048104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 79148104Syokota u_int32_t p; 79248104Syokota#endif 79348104Syokota 79448104Syokota buf = BIOS_PADDRTOVADDR(adp->va_window); 79548104Syokota v = readw(buf); 79648104Syokota writew(buf, 0xA55A); 79748104Syokota if (readw(buf) != 0xA55A) 79848104Syokota return ENXIO; 79948104Syokota writew(buf, v); 80048104Syokota 80148104Syokota switch (adp->va_type) { 80248104Syokota 80348104Syokota case KD_EGA: 80448104Syokota outb(adp->va_crtc_addr, 7); 80548104Syokota if (inb(adp->va_crtc_addr) == 7) { 80648104Syokota adp->va_type = KD_VGA; 80748104Syokota adp->va_name = "vga"; 80848104Syokota adp->va_flags |= V_ADP_STATESAVE | V_ADP_PALETTE; 80948104Syokota } 81048104Syokota adp->va_flags |= V_ADP_STATELOAD | V_ADP_BORDER; 81148104Syokota /* the color adapter may be in the 40x25 mode... XXX */ 81248104Syokota 81348104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 81448104Syokota /* get the BIOS video mode pointer */ 81548104Syokota p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8); 81648104Syokota p = BIOS_SADDRTOLADDR(p); 81748104Syokota if (ISMAPPED(p, sizeof(u_int32_t))) { 81848104Syokota p = *(u_int32_t *)BIOS_PADDRTOVADDR(p); 81948104Syokota p = BIOS_SADDRTOLADDR(p); 82048104Syokota if (ISMAPPED(p, V_MODE_PARAM_SIZE)) 82148104Syokota video_mode_ptr = (u_char *)BIOS_PADDRTOVADDR(p); 82248104Syokota } 82348104Syokota#endif 82448104Syokota break; 82548104Syokota 82648104Syokota case KD_CGA: 82748104Syokota adp->va_flags |= V_ADP_COLOR | V_ADP_BORDER; 82848104Syokota /* may be in the 40x25 mode... XXX */ 82948104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 83048104Syokota /* get the BIOS video mode pointer */ 83148104Syokota p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); 83248104Syokota p = BIOS_SADDRTOLADDR(p); 83348104Syokota video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); 83448104Syokota#endif 83548104Syokota break; 83648104Syokota 83748104Syokota case KD_MONO: 83848104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 83948104Syokota /* get the BIOS video mode pointer */ 84048104Syokota p = *(u_int32_t *)BIOS_PADDRTOVADDR(0x1d*4); 84148104Syokota p = BIOS_SADDRTOLADDR(p); 84248104Syokota video_mode_ptr2 = (u_char *)BIOS_PADDRTOVADDR(p); 84348104Syokota#endif 84448104Syokota break; 84548104Syokota } 84648104Syokota 84748104Syokota return 0; 84848104Syokota} 84948104Syokota 85048104Syokotastatic void 85148104Syokotaupdate_adapter_info(video_adapter_t *adp, video_info_t *info) 85248104Syokota{ 85348104Syokota adp->va_flags &= ~V_ADP_COLOR; 85448104Syokota adp->va_flags |= 85548104Syokota (info->vi_flags & V_INFO_COLOR) ? V_ADP_COLOR : 0; 85648104Syokota adp->va_crtc_addr = 85748104Syokota (adp->va_flags & V_ADP_COLOR) ? COLOR_CRTC : MONO_CRTC; 85848104Syokota adp->va_window = BIOS_PADDRTOVADDR(info->vi_window); 85948104Syokota adp->va_window_size = info->vi_window_size; 86048104Syokota adp->va_window_gran = info->vi_window_gran; 86148104Syokota adp->va_window_orig = 0; 86248104Syokota /* XXX */ 86348104Syokota adp->va_buffer = info->vi_buffer; 86448104Syokota adp->va_buffer_size = info->vi_buffer_size; 86550299Syokota if (info->vi_mem_model == V_INFO_MM_VGAX) { 86650299Syokota adp->va_line_width = info->vi_width/2; 86750299Syokota } else if (info->vi_flags & V_INFO_GRAPHICS) { 86848104Syokota switch (info->vi_depth/info->vi_planes) { 86948104Syokota case 1: 87048104Syokota adp->va_line_width = info->vi_width/8; 87148104Syokota break; 87248104Syokota case 2: 87348104Syokota adp->va_line_width = info->vi_width/4; 87448104Syokota break; 87548104Syokota case 4: 87648104Syokota adp->va_line_width = info->vi_width/2; 87748104Syokota break; 87848104Syokota case 8: 87948104Syokota default: /* shouldn't happen */ 88048104Syokota adp->va_line_width = info->vi_width; 88148104Syokota break; 88248104Syokota } 88348104Syokota } else { 88448104Syokota adp->va_line_width = info->vi_width; 88548104Syokota } 88648104Syokota adp->va_disp_start.x = 0; 88748104Syokota adp->va_disp_start.y = 0; 88848104Syokota bcopy(info, &adp->va_info, sizeof(adp->va_info)); 88948104Syokota} 89048104Syokota 89148104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 89248104Syokota/* compare two parameter table entries */ 89348104Syokotastatic int 89448104Syokotacomp_adpregs(u_char *buf1, u_char *buf2) 89548104Syokota{ 89648104Syokota static struct { 89748104Syokota u_char mask; 89848104Syokota } params[V_MODE_PARAM_SIZE] = { 89948104Syokota {0xff}, {0x00}, {0xff}, /* COLS}, ROWS}, POINTS */ 90048104Syokota {0x00}, {0x00}, /* page length */ 90148104Syokota {0xfe}, {0xff}, {0xff}, {0xff}, /* sequencer registers */ 90248104Syokota {0xf3}, /* misc register */ 90348104Syokota {0xff}, {0xff}, {0xff}, {0x7f}, {0xff}, /* CRTC */ 90448104Syokota {0xff}, {0xff}, {0xff}, {0x7f}, {0xff}, 90548104Syokota {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, 90648104Syokota {0x00}, {0xff}, {0x7f}, {0xff}, {0xff}, 90748104Syokota {0x7f}, {0xff}, {0xff}, {0xef}, {0xff}, 90848104Syokota {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* attribute controller regs */ 90948104Syokota {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, 91048104Syokota {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, 91148104Syokota {0xff}, {0xff}, {0xff}, {0xff}, {0xf0}, 91248104Syokota {0xff}, {0xff}, {0xff}, {0xff}, {0xff}, /* GDC register */ 91348104Syokota {0xff}, {0xff}, {0xff}, {0xff}, 91448104Syokota }; 91548104Syokota int identical = TRUE; 91648104Syokota int i; 91748104Syokota 91848104Syokota if ((buf1 == NULL) || (buf2 == NULL)) 91948104Syokota return COMP_DIFFERENT; 92048104Syokota 92148104Syokota for (i = 0; i < sizeof(params)/sizeof(params[0]); ++i) { 92248104Syokota if (params[i].mask == 0) /* don't care */ 92348104Syokota continue; 92448104Syokota if ((buf1[i] & params[i].mask) != (buf2[i] & params[i].mask)) 92548104Syokota return COMP_DIFFERENT; 92648104Syokota if (buf1[i] != buf2[i]) 92748104Syokota identical = FALSE; 92848104Syokota } 92948104Syokota return (identical) ? COMP_IDENTICAL : COMP_SIMILAR; 93048104Syokota} 93148104Syokota#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */ 93248104Syokota 93348104Syokota/* probe video adapters and return the number of detected adapters */ 93448104Syokotastatic int 93548104Syokotaprobe_adapters(void) 93648104Syokota{ 93748104Syokota video_adapter_t *adp; 93848104Syokota video_info_t info; 93948104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 94048104Syokota u_char *mp; 94148104Syokota#endif 94248104Syokota int i; 94348104Syokota 94448104Syokota /* do this test only once */ 94548104Syokota if (vga_init_done) 94648104Syokota return biosadapters; 94748104Syokota vga_init_done = TRUE; 94848104Syokota 94948104Syokota /* 95048104Syokota * Locate display adapters. 95148104Syokota * The AT architecture supports upto two adapters. `syscons' allows 95248104Syokota * the following combinations of adapters: 95348104Syokota * 1) MDA + CGA 95448104Syokota * 2) MDA + EGA/VGA color 95548104Syokota * 3) CGA + EGA/VGA mono 95648104Syokota * Note that `syscons' doesn't bother with MCGA as it is only 95748104Syokota * avaiable for low end PS/2 models which has 80286 or earlier CPUs, 95848104Syokota * thus, they are not running FreeBSD! 95948104Syokota * When there are two adapaters in the system, one becomes `primary' 96048104Syokota * and the other `secondary'. The EGA adapter has a set of DIP 96148104Syokota * switches on board for this information and the EGA BIOS copies 96248104Syokota * it in the BIOS data area BIOSDATA_VIDEOSWITCH (40:88). 96348104Syokota * The VGA BIOS has more sophisticated mechanism and has this 96448104Syokota * information in BIOSDATA_DCCINDEX (40:8a), but it also maintains 96548104Syokota * compatibility with the EGA BIOS by updating BIOSDATA_VIDEOSWITCH. 96648104Syokota */ 96748104Syokota 96848104Syokota /* 96948104Syokota * Check rtc and BIOS data area. 97048104Syokota * XXX: we don't use BIOSDATA_EQUIPMENT, since it is not a dead 97148104Syokota * copy of RTC_EQUIPMENT. Bits 4 and 5 of ETC_EQUIPMENT are 97248104Syokota * zeros for EGA and VGA. However, the EGA/VGA BIOS sets 97348104Syokota * these bits in BIOSDATA_EQUIPMENT according to the monitor 97448104Syokota * type detected. 97548104Syokota */ 97648104Syokota#ifndef VGA_NO_BIOS 97755729Syokota if (*(u_int32_t *)BIOS_PADDRTOVADDR(0x4a8)) { 97855729Syokota /* EGA/VGA BIOS is present */ 97948104Syokota fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f, 98048104Syokota biosadapter); 98155729Syokota } else { 98255729Syokota switch ((rtcin(RTC_EQUIPMENT) >> 4) & 3) { /* bit 4 and 5 */ 98355729Syokota case 0: 98455729Syokota /* EGA/VGA: shouldn't be happening */ 98555729Syokota fill_adapter_param(readb(BIOS_PADDRTOVADDR(0x488)) & 0x0f, 98655729Syokota biosadapter); 98755729Syokota break; 98855729Syokota case 1: 98955729Syokota /* CGA 40x25 */ 99055729Syokota /* FIXME: switch to the 80x25 mode? XXX */ 99155729Syokota biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA40]; 99255729Syokota biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 99355729Syokota break; 99455729Syokota case 2: 99555729Syokota /* CGA 80x25 */ 99655729Syokota biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_CGA80]; 99755729Syokota biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 99855729Syokota break; 99955729Syokota case 3: 100055729Syokota /* MDA */ 100155729Syokota biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_MONO]; 100255729Syokota biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_CGA80]; 100355729Syokota break; 100455729Syokota } 100548104Syokota } 100648104Syokota#else 100748104Syokota /* assume EGA/VGA? XXX */ 100848104Syokota biosadapter[V_ADP_PRIMARY] = adapter_init_value[DCC_EGA80]; 100948104Syokota biosadapter[V_ADP_SECONDARY] = adapter_init_value[DCC_MONO]; 101048104Syokota#endif /* VGA_NO_BIOS */ 101148104Syokota 101248104Syokota biosadapters = 0; 101348104Syokota if (verify_adapter(&biosadapter[V_ADP_SECONDARY]) == 0) { 101448104Syokota ++biosadapters; 101548104Syokota biosadapter[V_ADP_SECONDARY].va_flags |= V_ADP_PROBED; 101648104Syokota biosadapter[V_ADP_SECONDARY].va_mode = 101748104Syokota biosadapter[V_ADP_SECONDARY].va_initial_mode = 101848104Syokota map_bios_mode_num(biosadapter[V_ADP_SECONDARY].va_type, 101948104Syokota biosadapter[V_ADP_SECONDARY].va_flags 102048104Syokota & V_ADP_COLOR, 102148104Syokota biosadapter[V_ADP_SECONDARY].va_initial_bios_mode); 102248104Syokota } else { 102348104Syokota biosadapter[V_ADP_SECONDARY].va_type = -1; 102448104Syokota } 102548104Syokota if (verify_adapter(&biosadapter[V_ADP_PRIMARY]) == 0) { 102648104Syokota ++biosadapters; 102748104Syokota biosadapter[V_ADP_PRIMARY].va_flags |= V_ADP_PROBED; 102848104Syokota#ifndef VGA_NO_BIOS 102948104Syokota biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 103048104Syokota readb(BIOS_PADDRTOVADDR(0x449)); 103148104Syokota#else 103248104Syokota biosadapter[V_ADP_PRIMARY].va_initial_bios_mode = 3; /* XXX */ 103348104Syokota#endif 103448104Syokota biosadapter[V_ADP_PRIMARY].va_mode = 103548104Syokota biosadapter[V_ADP_PRIMARY].va_initial_mode = 103648104Syokota map_bios_mode_num(biosadapter[V_ADP_PRIMARY].va_type, 103748104Syokota biosadapter[V_ADP_PRIMARY].va_flags & V_ADP_COLOR, 103848104Syokota biosadapter[V_ADP_PRIMARY].va_initial_bios_mode); 103948104Syokota } else { 104048104Syokota biosadapter[V_ADP_PRIMARY] = biosadapter[V_ADP_SECONDARY]; 104148104Syokota biosadapter[V_ADP_SECONDARY].va_type = -1; 104248104Syokota } 104348104Syokota if (biosadapters == 0) 104448104Syokota return biosadapters; 104548104Syokota biosadapter[V_ADP_PRIMARY].va_unit = V_ADP_PRIMARY; 104648104Syokota biosadapter[V_ADP_SECONDARY].va_unit = V_ADP_SECONDARY; 104748104Syokota 104848104Syokota#if 0 /* we don't need these... */ 104948104Syokota fb_init_struct(&biosadapter[V_ADP_PRIMARY], ...); 105048104Syokota fb_init_struct(&biosadapter[V_ADP_SECONDARY], ...); 105148104Syokota#endif 105248104Syokota 1053153072Sru#ifdef notyet 105448104Syokota /* 105548104Syokota * We cannot have two video adapter of the same type; there must be 105648104Syokota * only one of color or mono adapter, or one each of them. 105748104Syokota */ 105848104Syokota if (biosadapters > 1) { 105948104Syokota if (!((biosadapter[0].va_flags ^ biosadapter[1].va_flags) 106048104Syokota & V_ADP_COLOR)) 106148104Syokota /* we have two mono or color adapters!! */ 106248104Syokota return (biosadapters = 0); 106348104Syokota } 106448104Syokota#endif 106548104Syokota 106648104Syokota /* 106794275Sphk * Ensure a zero start address. The registers are w/o 106848104Syokota * for old hardware so it's too hard to relocate the active screen 106948104Syokota * memory. 107048104Syokota * This must be done before vga_save_state() for VGA. 107148104Syokota */ 107248104Syokota outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 12); 107348104Syokota outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); 107448104Syokota outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr, 13); 107548104Syokota outb(biosadapter[V_ADP_PRIMARY].va_crtc_addr + 1, 0); 107648104Syokota 107748104Syokota /* the video mode parameter table in EGA/VGA BIOS */ 107848104Syokota /* NOTE: there can be only one EGA/VGA, wheather color or mono, 107948104Syokota * recognized by the video BIOS. 108048104Syokota */ 108148104Syokota if ((biosadapter[V_ADP_PRIMARY].va_type == KD_EGA) || 108248104Syokota (biosadapter[V_ADP_PRIMARY].va_type == KD_VGA)) { 108348104Syokota adp = &biosadapter[V_ADP_PRIMARY]; 108448104Syokota } else if ((biosadapter[V_ADP_SECONDARY].va_type == KD_EGA) || 108548104Syokota (biosadapter[V_ADP_SECONDARY].va_type == KD_VGA)) { 108648104Syokota adp = &biosadapter[V_ADP_SECONDARY]; 108748104Syokota } else { 108848104Syokota adp = NULL; 108948104Syokota } 109048104Syokota bzero(mode_map, sizeof(mode_map)); 109148104Syokota if (adp != NULL) { 109248104Syokota if (adp->va_type == KD_VGA) { 109348104Syokota vga_save_state(adp, &adpstate, sizeof(adpstate)); 109448104Syokota#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) 109548104Syokota mode_map[adp->va_initial_mode] = adpstate.regs; 109648104Syokota rows_offset = 1; 109748104Syokota#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 109848104Syokota if (video_mode_ptr == NULL) { 109948104Syokota mode_map[adp->va_initial_mode] = adpstate.regs; 110048104Syokota rows_offset = 1; 110148104Syokota } else { 110248104Syokota /* discard the table if we are not familiar with it... */ 110348104Syokota map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); 110448104Syokota mp = get_mode_param(adp->va_initial_mode); 110548104Syokota if (mp != NULL) 110648104Syokota bcopy(mp, adpstate2.regs, sizeof(adpstate2.regs)); 110748104Syokota switch (comp_adpregs(adpstate.regs, mp)) { 110848104Syokota case COMP_IDENTICAL: 110948104Syokota /* 111048104Syokota * OK, this parameter table looks reasonably familiar 111148104Syokota * to us... 111248104Syokota */ 111348104Syokota /* 111448104Syokota * This is a kludge for Toshiba DynaBook SS433 111548104Syokota * whose BIOS video mode table entry has the actual # 111648104Syokota * of rows at the offset 1; BIOSes from other 111748104Syokota * manufacturers store the # of rows - 1 there. XXX 111848104Syokota */ 111948104Syokota rows_offset = adpstate.regs[1] + 1 - mp[1]; 112048104Syokota break; 112148104Syokota 112248104Syokota case COMP_SIMILAR: 112348104Syokota /* 112448104Syokota * Not exactly the same, but similar enough to be 112548104Syokota * trusted. However, use the saved register values 112648104Syokota * for the initial mode and other modes which are 112748104Syokota * based on the initial mode. 112848104Syokota */ 112948104Syokota mode_map[adp->va_initial_mode] = adpstate.regs; 113048104Syokota rows_offset = adpstate.regs[1] + 1 - mp[1]; 113148104Syokota adpstate.regs[1] -= rows_offset - 1; 113248104Syokota break; 113348104Syokota 113448104Syokota case COMP_DIFFERENT: 113548104Syokota default: 113648104Syokota /* 113748104Syokota * Don't use the paramter table in BIOS. It doesn't 113848104Syokota * look familiar to us. Video mode switching is allowed 113948104Syokota * only if the new mode is the same as or based on 114048104Syokota * the initial mode. 114148104Syokota */ 114248104Syokota video_mode_ptr = NULL; 114348104Syokota bzero(mode_map, sizeof(mode_map)); 114448104Syokota mode_map[adp->va_initial_mode] = adpstate.regs; 114548104Syokota rows_offset = 1; 114648104Syokota break; 114748104Syokota } 114848104Syokota } 114948104Syokota#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 115048104Syokota 115148104Syokota#ifndef VGA_NO_MODE_CHANGE 115248104Syokota adp->va_flags |= V_ADP_MODECHANGE; 115348104Syokota#endif 115448104Syokota#ifndef VGA_NO_FONT_LOADING 115548104Syokota adp->va_flags |= V_ADP_FONT; 115648104Syokota#endif 115748104Syokota } else if (adp->va_type == KD_EGA) { 115848104Syokota#if defined(VGA_NO_BIOS) || defined(VGA_NO_MODE_CHANGE) 115948104Syokota rows_offset = 1; 116048104Syokota#else /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 116148104Syokota if (video_mode_ptr == NULL) { 116248104Syokota rows_offset = 1; 116348104Syokota } else { 116448104Syokota map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1); 116548104Syokota /* XXX how can one validate the EGA table... */ 116648104Syokota mp = get_mode_param(adp->va_initial_mode); 116748104Syokota if (mp != NULL) { 116848104Syokota adp->va_flags |= V_ADP_MODECHANGE; 116948104Syokota#ifndef VGA_NO_FONT_LOADING 117048104Syokota adp->va_flags |= V_ADP_FONT; 117148104Syokota#endif 117248104Syokota rows_offset = 1; 117348104Syokota } else { 117448104Syokota /* 117548104Syokota * This is serious. We will not be able to switch video 117648104Syokota * modes at all... 117748104Syokota */ 117848104Syokota video_mode_ptr = NULL; 117948104Syokota bzero(mode_map, sizeof(mode_map)); 118048104Syokota rows_offset = 1; 118148104Syokota } 118248104Syokota } 118348104Syokota#endif /* VGA_NO_BIOS || VGA_NO_MODE_CHANGE */ 118448104Syokota } 118548104Syokota } 118648104Syokota 118748104Syokota /* remove conflicting modes if we have more than one adapter */ 118856522Sdfr if (biosadapters > 0) { 118948104Syokota for (i = 0; i < biosadapters; ++i) { 119048104Syokota if (!(biosadapter[i].va_flags & V_ADP_MODECHANGE)) 119148104Syokota continue; 119248104Syokota clear_mode_map(&biosadapter[i], mode_map, M_VGA_CG320 + 1, 119348104Syokota (biosadapter[i].va_flags & V_ADP_COLOR) ? 119448104Syokota V_INFO_COLOR : 0); 119548104Syokota if ((biosadapter[i].va_type == KD_VGA) 119648104Syokota || (biosadapter[i].va_type == KD_EGA)) { 119748104Syokota biosadapter[i].va_io_base = 119848104Syokota (biosadapter[i].va_flags & V_ADP_COLOR) ? 119948104Syokota IO_VGA : IO_MDA; 120048104Syokota biosadapter[i].va_io_size = 32; 120148104Syokota } 120248104Syokota } 120348104Syokota } 120448104Syokota 120548104Syokota /* buffer address */ 120648104Syokota vga_get_info(&biosadapter[V_ADP_PRIMARY], 120748104Syokota biosadapter[V_ADP_PRIMARY].va_initial_mode, &info); 120848104Syokota info.vi_flags &= ~V_INFO_LINEAR; /* XXX */ 120948104Syokota update_adapter_info(&biosadapter[V_ADP_PRIMARY], &info); 121048104Syokota 121148104Syokota if (biosadapters > 1) { 121248104Syokota vga_get_info(&biosadapter[V_ADP_SECONDARY], 121348104Syokota biosadapter[V_ADP_SECONDARY].va_initial_mode, &info); 121448104Syokota info.vi_flags &= ~V_INFO_LINEAR; /* XXX */ 121548104Syokota update_adapter_info(&biosadapter[V_ADP_SECONDARY], &info); 121648104Syokota } 121748104Syokota 121848104Syokota /* 121948104Syokota * XXX: we should verify the following values for the primary adapter... 122048104Syokota * crtc I/O port address: *(u_int16_t *)BIOS_PADDRTOVADDR(0x463); 122148104Syokota * color/mono display: (*(u_int8_t *)BIOS_PADDRTOVADDR(0x487) & 0x02) 122248104Syokota * ? 0 : V_ADP_COLOR; 122348104Syokota * columns: *(u_int8_t *)BIOS_PADDRTOVADDR(0x44a); 122448104Syokota * rows: *(u_int8_t *)BIOS_PADDRTOVADDR(0x484); 122548104Syokota * font size: *(u_int8_t *)BIOS_PADDRTOVADDR(0x485); 122648104Syokota * buffer size: *(u_int16_t *)BIOS_PADDRTOVADDR(0x44c); 122748104Syokota */ 122848104Syokota 122948104Syokota return biosadapters; 123048104Syokota} 123148104Syokota 123248104Syokota/* set the scan line length in pixel */ 123348104Syokotastatic int 123448104Syokotaset_line_length(video_adapter_t *adp, int pixel) 123548104Syokota{ 123648104Syokota u_char *mp; 123748104Syokota int ppw; /* pixels per word */ 123848104Syokota int bpl; /* bytes per line */ 123948104Syokota int count; 124048104Syokota 124148104Syokota if ((adp->va_type != KD_VGA) && (adp->va_type != KD_EGA)) 124248104Syokota return ENODEV; 124348104Syokota mp = get_mode_param(adp->va_mode); 124448104Syokota if (mp == NULL) 124548104Syokota return EINVAL; 124648104Syokota 124748104Syokota switch (adp->va_info.vi_mem_model) { 124848104Syokota case V_INFO_MM_PLANAR: 124948104Syokota ppw = 16/(adp->va_info.vi_depth/adp->va_info.vi_planes); 125048104Syokota count = (pixel + ppw - 1)/ppw/2; 125148104Syokota bpl = ((pixel + ppw - 1)/ppw/2)*4; 125248104Syokota break; 125348104Syokota case V_INFO_MM_PACKED: 125448104Syokota count = (pixel + 7)/8; 125548104Syokota bpl = ((pixel + 7)/8)*8; 125648104Syokota break; 125748104Syokota case V_INFO_MM_TEXT: 125848104Syokota count = (pixel + 7)/8; /* columns */ 125948104Syokota bpl = (pixel + 7)/8; /* columns */ 126048104Syokota break; 126148104Syokota default: 126248104Syokota return ENODEV; 126348104Syokota } 126448104Syokota 126548104Syokota if (mp[10 + 0x17] & 0x40) /* CRTC mode control reg */ 126648104Syokota count *= 2; /* byte mode */ 126748104Syokota outb(adp->va_crtc_addr, 0x13); 126848104Syokota outb(adp->va_crtc_addr + 1, count); 126948104Syokota adp->va_line_width = bpl; 127048104Syokota 127148104Syokota return 0; 127248104Syokota} 127348104Syokota 127448104Syokotastatic int 127548104Syokotaset_display_start(video_adapter_t *adp, int x, int y) 127648104Syokota{ 127748104Syokota int off; /* byte offset (graphics mode)/word offset (text mode) */ 127848104Syokota int poff; /* pixel offset */ 127948104Syokota int roff; /* row offset */ 128048104Syokota int ppb; /* pixels per byte */ 128148104Syokota 128248104Syokota if ((adp->va_type != KD_VGA) && (adp->va_type != KD_EGA)) 128348104Syokota x &= ~7; 128448104Syokota if (adp->va_info.vi_flags & V_INFO_GRAPHICS) { 128548104Syokota ppb = 8/(adp->va_info.vi_depth/adp->va_info.vi_planes); 128648104Syokota off = y*adp->va_line_width + x/ppb; 128748104Syokota roff = 0; 128848104Syokota poff = x%ppb; 128948104Syokota } else { 129048104Syokota if ((adp->va_type == KD_VGA) || (adp->va_type == KD_EGA)) { 129148104Syokota outb(TSIDX, 1); 129248104Syokota if (inb(TSREG) & 1) 129348104Syokota ppb = 9; 129448104Syokota else 129548104Syokota ppb = 8; 129648104Syokota } else { 129748104Syokota ppb = 8; 129848104Syokota } 129948104Syokota off = y/adp->va_info.vi_cheight*adp->va_line_width + x/ppb; 130048104Syokota roff = y%adp->va_info.vi_cheight; 130148104Syokota /* FIXME: is this correct? XXX */ 130248104Syokota if (ppb == 8) 130348104Syokota poff = x%ppb; 130448104Syokota else 130548104Syokota poff = (x + 8)%ppb; 130648104Syokota } 130748104Syokota 130848104Syokota /* start address */ 130948104Syokota outb(adp->va_crtc_addr, 0xc); /* high */ 131048104Syokota outb(adp->va_crtc_addr + 1, off >> 8); 131148104Syokota outb(adp->va_crtc_addr, 0xd); /* low */ 131248104Syokota outb(adp->va_crtc_addr + 1, off & 0xff); 131348104Syokota 131448104Syokota /* horizontal pel pan */ 131548104Syokota if ((adp->va_type == KD_VGA) || (adp->va_type == KD_EGA)) { 131648104Syokota inb(adp->va_crtc_addr + 6); 131748104Syokota outb(ATC, 0x13 | 0x20); 131848104Syokota outb(ATC, poff); 131948104Syokota inb(adp->va_crtc_addr + 6); 132048104Syokota outb(ATC, 0x20); 132148104Syokota } 132248104Syokota 132348104Syokota /* preset raw scan */ 132448104Syokota outb(adp->va_crtc_addr, 8); 132548104Syokota outb(adp->va_crtc_addr + 1, roff); 132648104Syokota 132748104Syokota adp->va_disp_start.x = x; 132848104Syokota adp->va_disp_start.y = y; 132948104Syokota return 0; 133048104Syokota} 133148104Syokota 1332138891Sru#ifndef VGA_NO_MODE_CHANGE 1333114383Speter#if defined(__i386__) || defined(__amd64__) /* XXX */ 133448104Syokotastatic void 133548104Syokotafill(int val, void *d, size_t size) 133648104Syokota{ 133748104Syokota u_char *p = d; 133848104Syokota 133948104Syokota while (size-- > 0) 134048104Syokota *p++ = val; 134148104Syokota} 134248104Syokota#endif /* __i386__ */ 134348104Syokota 134448104Syokotastatic void 134548104Syokotafilll_io(int val, vm_offset_t d, size_t size) 134648104Syokota{ 134748104Syokota while (size-- > 0) { 134848104Syokota writel(d, val); 134948104Syokota d += sizeof(u_int32_t); 135048104Syokota } 135148104Syokota} 1352138891Sru#endif /* !VGA_NO_MODE_CHANGE */ 135348104Syokota 135448104Syokota/* entry points */ 135548104Syokota 135648238Speter#if 0 135748104Syokotastatic int 135848104Syokotavga_nop(void) 135948104Syokota{ 136048104Syokota return 0; 136148104Syokota} 136248238Speter#endif 136348104Syokota 136448104Syokotastatic int 136548104Syokotavga_error(void) 136648104Syokota{ 136748104Syokota return ENODEV; 136848104Syokota} 136948104Syokota 137048104Syokotastatic int 137148104Syokotavga_probe(int unit, video_adapter_t **adpp, void *arg, int flags) 137248104Syokota{ 137348104Syokota probe_adapters(); 137448104Syokota if (unit >= biosadapters) 137548104Syokota return ENXIO; 137648104Syokota 137748104Syokota *adpp = &biosadapter[unit]; 137848104Syokota 137948104Syokota return 0; 138048104Syokota} 138148104Syokota 138248104Syokotastatic int 138348104Syokotavga_init(int unit, video_adapter_t *adp, int flags) 138448104Syokota{ 138548104Syokota if ((unit >= biosadapters) || (adp == NULL) || !probe_done(adp)) 138648104Syokota return ENXIO; 138748104Syokota 138848104Syokota if (!init_done(adp)) { 138948104Syokota /* nothing to do really... */ 139048104Syokota adp->va_flags |= V_ADP_INITIALIZED; 139148104Syokota } 139248104Syokota 139348104Syokota if (!config_done(adp)) { 139448104Syokota if (vid_register(adp) < 0) 139548104Syokota return ENXIO; 139648104Syokota adp->va_flags |= V_ADP_REGISTERED; 139748104Syokota } 139848104Syokota if (vga_sub_configure != NULL) 139948104Syokota (*vga_sub_configure)(0); 140048104Syokota 140148104Syokota return 0; 140248104Syokota} 140348104Syokota 140448104Syokota/* 140548104Syokota * get_info(): 140648104Syokota * Return the video_info structure of the requested video mode. 140748104Syokota * 140848104Syokota * all adapters 140948104Syokota */ 141048104Syokotastatic int 141148104Syokotavga_get_info(video_adapter_t *adp, int mode, video_info_t *info) 141248104Syokota{ 141348104Syokota int i; 141448104Syokota 141548104Syokota if (!vga_init_done) 141648104Syokota return ENXIO; 141748104Syokota 141848104Syokota mode = map_gen_mode_num(adp->va_type, adp->va_flags & V_ADP_COLOR, mode); 141948104Syokota#ifndef VGA_NO_MODE_CHANGE 142048104Syokota if (adp->va_flags & V_ADP_MODECHANGE) { 142148104Syokota /* 142248104Syokota * If the parameter table entry for this mode is not found, 142348104Syokota * the mode is not supported... 142448104Syokota */ 142548104Syokota if (get_mode_param(mode) == NULL) 142648104Syokota return EINVAL; 142748104Syokota } else 142848104Syokota#endif /* VGA_NO_MODE_CHANGE */ 142948104Syokota { 143048104Syokota /* 143148104Syokota * Even if we don't support video mode switching on this adapter, 143248104Syokota * the information on the initial (thus current) video mode 143348104Syokota * should be made available. 143448104Syokota */ 143548104Syokota if (mode != adp->va_initial_mode) 143648104Syokota return EINVAL; 143748104Syokota } 143848104Syokota 143948104Syokota for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 144048104Syokota if (bios_vmode[i].vi_mode == NA) 144148104Syokota continue; 144248104Syokota if (mode == bios_vmode[i].vi_mode) { 144348104Syokota *info = bios_vmode[i]; 144448104Syokota /* XXX */ 144548104Syokota info->vi_buffer_size = info->vi_window_size*info->vi_planes; 144648104Syokota return 0; 144748104Syokota } 144848104Syokota } 144948104Syokota return EINVAL; 145048104Syokota} 145148104Syokota 145248104Syokota/* 145348104Syokota * query_mode(): 145448104Syokota * Find a video mode matching the requested parameters. 145548104Syokota * Fields filled with 0 are considered "don't care" fields and 145648104Syokota * match any modes. 145748104Syokota * 145848104Syokota * all adapters 145948104Syokota */ 146048104Syokotastatic int 146148104Syokotavga_query_mode(video_adapter_t *adp, video_info_t *info) 146248104Syokota{ 146348104Syokota int i; 146448104Syokota 146548104Syokota if (!vga_init_done) 146654258Syokota return ENXIO; 146748104Syokota 146848104Syokota for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 146948104Syokota if (bios_vmode[i].vi_mode == NA) 147048104Syokota continue; 147148104Syokota 147248104Syokota if ((info->vi_width != 0) 147348104Syokota && (info->vi_width != bios_vmode[i].vi_width)) 147448104Syokota continue; 147548104Syokota if ((info->vi_height != 0) 147648104Syokota && (info->vi_height != bios_vmode[i].vi_height)) 147748104Syokota continue; 147848104Syokota if ((info->vi_cwidth != 0) 147948104Syokota && (info->vi_cwidth != bios_vmode[i].vi_cwidth)) 148048104Syokota continue; 148148104Syokota if ((info->vi_cheight != 0) 148248104Syokota && (info->vi_cheight != bios_vmode[i].vi_cheight)) 148348104Syokota continue; 148448104Syokota if ((info->vi_depth != 0) 148548104Syokota && (info->vi_depth != bios_vmode[i].vi_depth)) 148648104Syokota continue; 148748104Syokota if ((info->vi_planes != 0) 148848104Syokota && (info->vi_planes != bios_vmode[i].vi_planes)) 148948104Syokota continue; 149048104Syokota /* XXX: should check pixel format, memory model */ 149148104Syokota if ((info->vi_flags != 0) 149248104Syokota && (info->vi_flags != bios_vmode[i].vi_flags)) 149348104Syokota continue; 149448104Syokota 149548104Syokota /* verify if this mode is supported on this adapter */ 149654258Syokota if (vga_get_info(adp, bios_vmode[i].vi_mode, info)) 149748104Syokota continue; 149854258Syokota return 0; 149948104Syokota } 150054258Syokota return ENODEV; 150148104Syokota} 150248104Syokota 150348104Syokota/* 150448104Syokota * set_mode(): 150548104Syokota * Change the video mode. 150648104Syokota * 150748104Syokota * EGA/VGA 150848104Syokota */ 150948104Syokota 151048104Syokota#ifndef VGA_NO_MODE_CHANGE 151148104Syokota#ifdef VGA_WIDTH90 151248104Syokotastatic void 151348104Syokotaset_width90(adp_state_t *params) 151448104Syokota{ 151548104Syokota /* 151648104Syokota * Based on code submitted by Kelly Yancey (kbyanc@freedomnet.com) 151748104Syokota * and alexv@sui.gda.itesm.mx. 151848104Syokota */ 151948104Syokota params->regs[5] |= 1; /* toggle 8 pixel wide fonts */ 152048104Syokota params->regs[10+0x0] = 0x6b; 152148104Syokota params->regs[10+0x1] = 0x59; 152248104Syokota params->regs[10+0x2] = 0x5a; 152348104Syokota params->regs[10+0x3] = 0x8e; 152448104Syokota params->regs[10+0x4] = 0x5e; 152548104Syokota params->regs[10+0x5] = 0x8a; 152648104Syokota params->regs[10+0x13] = 45; 152748104Syokota params->regs[35+0x13] = 0; 152848104Syokota} 152948104Syokota#endif /* VGA_WIDTH90 */ 153048104Syokota#endif /* !VGA_NO_MODE_CHANGE */ 153148104Syokota 153248104Syokotastatic int 153348104Syokotavga_set_mode(video_adapter_t *adp, int mode) 153448104Syokota{ 153548104Syokota#ifndef VGA_NO_MODE_CHANGE 153648104Syokota video_info_t info; 153748104Syokota adp_state_t params; 153848104Syokota 153948104Syokota prologue(adp, V_ADP_MODECHANGE, ENODEV); 154048104Syokota 154148104Syokota mode = map_gen_mode_num(adp->va_type, 154248104Syokota adp->va_flags & V_ADP_COLOR, mode); 154348104Syokota if (vga_get_info(adp, mode, &info)) 154448104Syokota return EINVAL; 154548104Syokota 154648104Syokota#if VGA_DEBUG > 1 154748104Syokota printf("vga_set_mode(): setting mode %d\n", mode); 154848104Syokota#endif 154948104Syokota 155048104Syokota params.sig = V_STATE_SIG; 155148104Syokota bcopy(get_mode_param(mode), params.regs, sizeof(params.regs)); 155248104Syokota 155348104Syokota switch (mode) { 155448104Syokota#ifdef VGA_WIDTH90 155548104Syokota case M_VGA_C90x60: case M_VGA_M90x60: 155648104Syokota set_width90(¶ms); 1557102412Scharnier /* FALLTHROUGH */ 155848104Syokota#endif 155948104Syokota case M_VGA_C80x60: case M_VGA_M80x60: 156048104Syokota params.regs[2] = 0x08; 156148104Syokota params.regs[19] = 0x47; 156248104Syokota goto special_480l; 156348104Syokota 156448104Syokota#ifdef VGA_WIDTH90 156548104Syokota case M_VGA_C90x30: case M_VGA_M90x30: 156648104Syokota set_width90(¶ms); 1567102412Scharnier /* FALLTHROUGH */ 156848104Syokota#endif 156948104Syokota case M_VGA_C80x30: case M_VGA_M80x30: 157048104Syokota params.regs[19] = 0x4f; 157148104Syokotaspecial_480l: 157248104Syokota params.regs[9] |= 0xc0; 157348104Syokota params.regs[16] = 0x08; 157448104Syokota params.regs[17] = 0x3e; 157548104Syokota params.regs[26] = 0xea; 157648104Syokota params.regs[28] = 0xdf; 157748104Syokota params.regs[31] = 0xe7; 157848104Syokota params.regs[32] = 0x04; 157948104Syokota goto setup_mode; 158048104Syokota 158148104Syokota#ifdef VGA_WIDTH90 158248104Syokota case M_VGA_C90x43: case M_VGA_M90x43: 158348104Syokota set_width90(¶ms); 1584102412Scharnier /* FALLTHROUGH */ 158548104Syokota#endif 158648104Syokota case M_ENH_C80x43: case M_ENH_B80x43: 158748104Syokota params.regs[28] = 87; 158848104Syokota goto special_80x50; 158948104Syokota 159048104Syokota#ifdef VGA_WIDTH90 159148104Syokota case M_VGA_C90x50: case M_VGA_M90x50: 159248104Syokota set_width90(¶ms); 1593102412Scharnier /* FALLTHROUGH */ 159448104Syokota#endif 159548104Syokota case M_VGA_C80x50: case M_VGA_M80x50: 159648104Syokotaspecial_80x50: 159748104Syokota params.regs[2] = 8; 159848104Syokota params.regs[19] = 7; 159948104Syokota goto setup_mode; 160048104Syokota 160148104Syokota#ifdef VGA_WIDTH90 160248104Syokota case M_VGA_C90x25: case M_VGA_M90x25: 160348104Syokota set_width90(¶ms); 1604102412Scharnier /* FALLTHROUGH */ 160548104Syokota#endif 160648104Syokota case M_VGA_C40x25: case M_VGA_C80x25: 160748104Syokota case M_VGA_M80x25: 160848104Syokota case M_B40x25: case M_C40x25: 160948104Syokota case M_B80x25: case M_C80x25: 161048104Syokota case M_ENH_B40x25: case M_ENH_C40x25: 161148104Syokota case M_ENH_B80x25: case M_ENH_C80x25: 161248104Syokota case M_EGAMONO80x25: 161348104Syokota 161448104Syokotasetup_mode: 161548104Syokota vga_load_state(adp, ¶ms); 161648104Syokota break; 161748104Syokota 161848104Syokota case M_VGA_MODEX: 161948104Syokota /* "unchain" the VGA mode */ 162048104Syokota params.regs[5-1+0x04] &= 0xf7; 162148104Syokota params.regs[5-1+0x04] |= 0x04; 162248104Syokota /* turn off doubleword mode */ 162348104Syokota params.regs[10+0x14] &= 0xbf; 162480203Skris /* turn off word addressing */ 162548104Syokota params.regs[10+0x17] |= 0x40; 162648104Syokota /* set logical screen width */ 162748104Syokota params.regs[10+0x13] = 80; 162848104Syokota /* set 240 lines */ 162948104Syokota params.regs[10+0x11] = 0x2c; 163048104Syokota params.regs[10+0x06] = 0x0d; 163148104Syokota params.regs[10+0x07] = 0x3e; 163248104Syokota params.regs[10+0x10] = 0xea; 163348104Syokota params.regs[10+0x11] = 0xac; 163448104Syokota params.regs[10+0x12] = 0xdf; 163548104Syokota params.regs[10+0x15] = 0xe7; 163648104Syokota params.regs[10+0x16] = 0x06; 163748104Syokota /* set vertical sync polarity to reflect aspect ratio */ 163848104Syokota params.regs[9] = 0xe3; 163948104Syokota goto setup_grmode; 164048104Syokota 164148104Syokota case M_BG320: case M_CG320: case M_BG640: 164248104Syokota case M_CG320_D: case M_CG640_E: 164348104Syokota case M_CG640x350: case M_ENH_CG640: 164448104Syokota case M_BG640x480: case M_CG640x480: case M_VGA_CG320: 164548104Syokota 164648104Syokotasetup_grmode: 164748104Syokota vga_load_state(adp, ¶ms); 164848104Syokota break; 164948104Syokota 165048104Syokota default: 165148104Syokota return EINVAL; 165248104Syokota } 165348104Syokota 165448104Syokota adp->va_mode = mode; 165548104Syokota info.vi_flags &= ~V_INFO_LINEAR; /* XXX */ 165648104Syokota update_adapter_info(adp, &info); 165748104Syokota 165848104Syokota /* move hardware cursor out of the way */ 1659174985Swkoszek vidd_set_hw_cursor(adp, -1, -1); 166048104Syokota 166148104Syokota return 0; 166248104Syokota#else /* VGA_NO_MODE_CHANGE */ 166348104Syokota return ENODEV; 166448104Syokota#endif /* VGA_NO_MODE_CHANGE */ 166548104Syokota} 166648104Syokota 166748104Syokota#ifndef VGA_NO_FONT_LOADING 166848104Syokota 166948104Syokotastatic void 167048104Syokotaset_font_mode(video_adapter_t *adp, u_char *buf) 167148104Syokota{ 167248104Syokota u_char *mp; 167348104Syokota int s; 167448104Syokota 167548104Syokota s = splhigh(); 167648104Syokota 167748104Syokota /* save register values */ 167848104Syokota if (adp->va_type == KD_VGA) { 167948104Syokota outb(TSIDX, 0x02); buf[0] = inb(TSREG); 168048104Syokota outb(TSIDX, 0x04); buf[1] = inb(TSREG); 168148104Syokota outb(GDCIDX, 0x04); buf[2] = inb(GDCREG); 168248104Syokota outb(GDCIDX, 0x05); buf[3] = inb(GDCREG); 168348104Syokota outb(GDCIDX, 0x06); buf[4] = inb(GDCREG); 168448104Syokota inb(adp->va_crtc_addr + 6); 168548104Syokota outb(ATC, 0x10); buf[5] = inb(ATC + 1); 168648104Syokota } else /* if (adp->va_type == KD_EGA) */ { 168748104Syokota /* 168848104Syokota * EGA cannot be read; copy parameters from the mode parameter 168948104Syokota * table. 169048104Syokota */ 169148104Syokota mp = get_mode_param(adp->va_mode); 169248104Syokota buf[0] = mp[5 + 0x02 - 1]; 169348104Syokota buf[1] = mp[5 + 0x04 - 1]; 169448104Syokota buf[2] = mp[55 + 0x04]; 169548104Syokota buf[3] = mp[55 + 0x05]; 169648104Syokota buf[4] = mp[55 + 0x06]; 169748104Syokota buf[5] = mp[35 + 0x10]; 169848104Syokota } 169948104Syokota 170048104Syokota /* setup vga for loading fonts */ 170148104Syokota inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 170248104Syokota outb(ATC, 0x10); outb(ATC, buf[5] & ~0x01); 170348104Syokota inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 170448104Syokota outb(ATC, 0x20); /* enable palette */ 170548104Syokota 1706153072Sru#ifdef VGA_SLOW_IOACCESS 170748104Syokota#ifdef VGA_ALT_SEQACCESS 170848104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); 170948104Syokota#endif 171048104Syokota outb(TSIDX, 0x02); outb(TSREG, 0x04); 171148104Syokota outb(TSIDX, 0x04); outb(TSREG, 0x07); 171248104Syokota#ifdef VGA_ALT_SEQACCESS 171348104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); 171448104Syokota#endif 171548104Syokota outb(GDCIDX, 0x04); outb(GDCREG, 0x02); 171648104Syokota outb(GDCIDX, 0x05); outb(GDCREG, 0x00); 171748104Syokota outb(GDCIDX, 0x06); outb(GDCREG, 0x04); 171848104Syokota#else /* VGA_SLOW_IOACCESS */ 171948104Syokota#ifdef VGA_ALT_SEQACCESS 172048104Syokota outw(TSIDX, 0x0100); 172148104Syokota#endif 172248104Syokota outw(TSIDX, 0x0402); 172348104Syokota outw(TSIDX, 0x0704); 172448104Syokota#ifdef VGA_ALT_SEQACCESS 172548104Syokota outw(TSIDX, 0x0300); 172648104Syokota#endif 172748104Syokota outw(GDCIDX, 0x0204); 172848104Syokota outw(GDCIDX, 0x0005); 172948104Syokota outw(GDCIDX, 0x0406); /* addr = a0000, 64kb */ 173048104Syokota#endif /* VGA_SLOW_IOACCESS */ 173148104Syokota 173248104Syokota splx(s); 173348104Syokota} 173448104Syokota 173548104Syokotastatic void 173648104Syokotaset_normal_mode(video_adapter_t *adp, u_char *buf) 173748104Syokota{ 173848104Syokota int s; 173948104Syokota 174048104Syokota s = splhigh(); 174148104Syokota 174248104Syokota /* setup vga for normal operation mode again */ 174348104Syokota inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 174448104Syokota outb(ATC, 0x10); outb(ATC, buf[5]); 174548104Syokota inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 174648104Syokota outb(ATC, 0x20); /* enable palette */ 174748104Syokota 1748153072Sru#ifdef VGA_SLOW_IOACCESS 174948104Syokota#ifdef VGA_ALT_SEQACCESS 175048104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); 175148104Syokota#endif 175248104Syokota outb(TSIDX, 0x02); outb(TSREG, buf[0]); 175348104Syokota outb(TSIDX, 0x04); outb(TSREG, buf[1]); 175448104Syokota#ifdef VGA_ALT_SEQACCESS 175548104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); 175648104Syokota#endif 175748104Syokota outb(GDCIDX, 0x04); outb(GDCREG, buf[2]); 175848104Syokota outb(GDCIDX, 0x05); outb(GDCREG, buf[3]); 175948104Syokota if (adp->va_crtc_addr == MONO_CRTC) { 176048104Syokota outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x08); 176148104Syokota } else { 176248104Syokota outb(GDCIDX, 0x06); outb(GDCREG,(buf[4] & 0x03) | 0x0c); 176348104Syokota } 176448104Syokota#else /* VGA_SLOW_IOACCESS */ 176548104Syokota#ifdef VGA_ALT_SEQACCESS 176648104Syokota outw(TSIDX, 0x0100); 176748104Syokota#endif 176848104Syokota outw(TSIDX, 0x0002 | (buf[0] << 8)); 176948104Syokota outw(TSIDX, 0x0004 | (buf[1] << 8)); 177048104Syokota#ifdef VGA_ALT_SEQACCESS 177148104Syokota outw(TSIDX, 0x0300); 177248104Syokota#endif 177348104Syokota outw(GDCIDX, 0x0004 | (buf[2] << 8)); 177448104Syokota outw(GDCIDX, 0x0005 | (buf[3] << 8)); 177548104Syokota if (adp->va_crtc_addr == MONO_CRTC) 177648104Syokota outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x08)<<8)); 177748104Syokota else 177848104Syokota outw(GDCIDX, 0x0006 | (((buf[4] & 0x03) | 0x0c)<<8)); 177948104Syokota#endif /* VGA_SLOW_IOACCESS */ 178048104Syokota 178148104Syokota splx(s); 178248104Syokota} 178348104Syokota 178448104Syokota#endif /* VGA_NO_FONT_LOADING */ 178548104Syokota 178648104Syokota/* 178748104Syokota * save_font(): 178848104Syokota * Read the font data in the requested font page from the video adapter. 178948104Syokota * 179048104Syokota * EGA/VGA 179148104Syokota */ 179248104Syokotastatic int 1793150686Smariusvga_save_font(video_adapter_t *adp, int page, int fontsize, int fontwidth, 1794150686Smarius u_char *data, int ch, int count) 179548104Syokota{ 179648104Syokota#ifndef VGA_NO_FONT_LOADING 179748104Syokota u_char buf[PARAM_BUFSIZE]; 1798115253Speter vm_offset_t segment; 179948104Syokota int c; 180048104Syokota#ifdef VGA_ALT_SEQACCESS 180148104Syokota int s; 180248104Syokota u_char val = 0; 180348104Syokota#endif 180448104Syokota 180548104Syokota prologue(adp, V_ADP_FONT, ENODEV); 180648104Syokota 180748104Syokota if (fontsize < 14) { 180848104Syokota /* FONT_8 */ 180948104Syokota fontsize = 8; 181048104Syokota } else if (fontsize >= 32) { 181148104Syokota fontsize = 32; 181248104Syokota } else if (fontsize >= 16) { 181348104Syokota /* FONT_16 */ 181448104Syokota fontsize = 16; 181548104Syokota } else { 181648104Syokota /* FONT_14 */ 181748104Syokota fontsize = 14; 181848104Syokota } 181948104Syokota 1820150686Smarius if (page < 0 || page >= 8 || fontwidth != 8) 182148104Syokota return EINVAL; 182248104Syokota segment = FONT_BUF + 0x4000*page; 182348104Syokota if (page > 3) 182448104Syokota segment -= 0xe000; 182548104Syokota 182648104Syokota#ifdef VGA_ALT_SEQACCESS 182748104Syokota if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ 182848104Syokota s = splhigh(); 182948104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); 183048104Syokota outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 183148104Syokota outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 183248104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); 183348104Syokota splx(s); 183448104Syokota } 183548104Syokota#endif 183648104Syokota 183748104Syokota set_font_mode(adp, buf); 183848104Syokota if (fontsize == 32) { 1839114383Speter bcopy_fromio((uintptr_t)segment + ch*32, data, fontsize*count); 184048104Syokota } else { 184148104Syokota for (c = ch; count > 0; ++c, --count) { 1842114383Speter bcopy_fromio((uintptr_t)segment + c*32, data, fontsize); 184348104Syokota data += fontsize; 184448104Syokota } 184548104Syokota } 184648104Syokota set_normal_mode(adp, buf); 184748104Syokota 184848104Syokota#ifdef VGA_ALT_SEQACCESS 184948104Syokota if (adp->va_type == KD_VGA) { 185048104Syokota s = splhigh(); 185148104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); 185248104Syokota outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ 185348104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); 185448104Syokota splx(s); 185548104Syokota } 185648104Syokota#endif 185748104Syokota 185848104Syokota return 0; 185948104Syokota#else /* VGA_NO_FONT_LOADING */ 186048104Syokota return ENODEV; 186148104Syokota#endif /* VGA_NO_FONT_LOADING */ 186248104Syokota} 186348104Syokota 186448104Syokota/* 186548104Syokota * load_font(): 186648104Syokota * Set the font data in the requested font page. 186748104Syokota * NOTE: it appears that some recent video adapters do not support 186848104Syokota * the font page other than 0... XXX 186948104Syokota * 187048104Syokota * EGA/VGA 187148104Syokota */ 187248104Syokotastatic int 1873150686Smariusvga_load_font(video_adapter_t *adp, int page, int fontsize, int fontwidth, 1874150686Smarius u_char *data, int ch, int count) 187548104Syokota{ 187648104Syokota#ifndef VGA_NO_FONT_LOADING 187748104Syokota u_char buf[PARAM_BUFSIZE]; 1878115253Speter vm_offset_t segment; 187948104Syokota int c; 188048104Syokota#ifdef VGA_ALT_SEQACCESS 188148104Syokota int s; 188248104Syokota u_char val = 0; 188348104Syokota#endif 188448104Syokota 188548104Syokota prologue(adp, V_ADP_FONT, ENODEV); 188648104Syokota 188748104Syokota if (fontsize < 14) { 188848104Syokota /* FONT_8 */ 188948104Syokota fontsize = 8; 189048104Syokota } else if (fontsize >= 32) { 189148104Syokota fontsize = 32; 189248104Syokota } else if (fontsize >= 16) { 189348104Syokota /* FONT_16 */ 189448104Syokota fontsize = 16; 189548104Syokota } else { 189648104Syokota /* FONT_14 */ 189748104Syokota fontsize = 14; 189848104Syokota } 189948104Syokota 1900150686Smarius if (page < 0 || page >= 8 || fontwidth != 8) 190148104Syokota return EINVAL; 190248104Syokota segment = FONT_BUF + 0x4000*page; 190348104Syokota if (page > 3) 190448104Syokota segment -= 0xe000; 190548104Syokota 190648104Syokota#ifdef VGA_ALT_SEQACCESS 190748104Syokota if (adp->va_type == KD_VGA) { /* what about EGA? XXX */ 190848104Syokota s = splhigh(); 190948104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); 191048104Syokota outb(TSIDX, 0x01); val = inb(TSREG); /* disable screen */ 191148104Syokota outb(TSIDX, 0x01); outb(TSREG, val | 0x20); 191248104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); 191348104Syokota splx(s); 191448104Syokota } 191548104Syokota#endif 191648104Syokota 191748104Syokota set_font_mode(adp, buf); 191848104Syokota if (fontsize == 32) { 1919114383Speter bcopy_toio(data, (uintptr_t)segment + ch*32, fontsize*count); 192048104Syokota } else { 192148104Syokota for (c = ch; count > 0; ++c, --count) { 1922114383Speter bcopy_toio(data, (uintptr_t)segment + c*32, fontsize); 192348104Syokota data += fontsize; 192448104Syokota } 192548104Syokota } 192648104Syokota set_normal_mode(adp, buf); 192748104Syokota 192848104Syokota#ifdef VGA_ALT_SEQACCESS 192948104Syokota if (adp->va_type == KD_VGA) { 193048104Syokota s = splhigh(); 193148104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); 193248104Syokota outb(TSIDX, 0x01); outb(TSREG, val & 0xdf); /* enable screen */ 193348104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); 193448104Syokota splx(s); 193548104Syokota } 193648104Syokota#endif 193748104Syokota 193848104Syokota return 0; 193948104Syokota#else /* VGA_NO_FONT_LOADING */ 194048104Syokota return ENODEV; 194148104Syokota#endif /* VGA_NO_FONT_LOADING */ 194248104Syokota} 194348104Syokota 194448104Syokota/* 194548104Syokota * show_font(): 194648104Syokota * Activate the requested font page. 194748104Syokota * NOTE: it appears that some recent video adapters do not support 194848104Syokota * the font page other than 0... XXX 194948104Syokota * 195048104Syokota * EGA/VGA 195148104Syokota */ 195248104Syokotastatic int 195348104Syokotavga_show_font(video_adapter_t *adp, int page) 195448104Syokota{ 195548104Syokota#ifndef VGA_NO_FONT_LOADING 195648104Syokota static u_char cg[] = { 0x00, 0x05, 0x0a, 0x0f, 0x30, 0x35, 0x3a, 0x3f }; 195748104Syokota int s; 195848104Syokota 195948104Syokota prologue(adp, V_ADP_FONT, ENODEV); 196048104Syokota if (page < 0 || page >= 8) 196148104Syokota return EINVAL; 196248104Syokota 196348104Syokota s = splhigh(); 196448104Syokota outb(TSIDX, 0x03); outb(TSREG, cg[page]); 196548104Syokota splx(s); 196648104Syokota 196748104Syokota return 0; 196848104Syokota#else /* VGA_NO_FONT_LOADING */ 196948104Syokota return ENODEV; 197048104Syokota#endif /* VGA_NO_FONT_LOADING */ 197148104Syokota} 197248104Syokota 197348104Syokota/* 197448104Syokota * save_palette(): 197548104Syokota * Read DAC values. The values have expressed in 8 bits. 197648104Syokota * 197748104Syokota * VGA 197848104Syokota */ 197948104Syokotastatic int 198048104Syokotavga_save_palette(video_adapter_t *adp, u_char *palette) 198148104Syokota{ 1982205604Sjkim int bits; 198348104Syokota int i; 198448104Syokota 198548104Syokota prologue(adp, V_ADP_PALETTE, ENODEV); 198648104Syokota 198748104Syokota /* 198848104Syokota * We store 8 bit values in the palette buffer, while the standard 198948104Syokota * VGA has 6 bit DAC . 199048104Syokota */ 199148104Syokota outb(PALRADR, 0x00); 1992205604Sjkim bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; 199348104Syokota for (i = 0; i < 256*3; ++i) 1994205604Sjkim palette[i] = inb(PALDATA) << bits; 199548104Syokota inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 199648104Syokota return 0; 199748104Syokota} 199848104Syokota 199948104Syokotastatic int 200048104Syokotavga_save_palette2(video_adapter_t *adp, int base, int count, 200148104Syokota u_char *r, u_char *g, u_char *b) 200248104Syokota{ 2003205604Sjkim int bits; 200448104Syokota int i; 200548104Syokota 200648104Syokota prologue(adp, V_ADP_PALETTE, ENODEV); 200748104Syokota 200848104Syokota outb(PALRADR, base); 2009205604Sjkim bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; 201048104Syokota for (i = 0; i < count; ++i) { 2011205604Sjkim r[i] = inb(PALDATA) << bits; 2012205604Sjkim g[i] = inb(PALDATA) << bits; 2013205604Sjkim b[i] = inb(PALDATA) << bits; 201448104Syokota } 201548104Syokota inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 201648104Syokota return 0; 201748104Syokota} 201848104Syokota 201948104Syokota/* 202048104Syokota * load_palette(): 202148104Syokota * Set DAC values. 202248104Syokota * 202348104Syokota * VGA 202448104Syokota */ 202548104Syokotastatic int 202648104Syokotavga_load_palette(video_adapter_t *adp, u_char *palette) 202748104Syokota{ 2028205604Sjkim int bits; 202948104Syokota int i; 203048104Syokota 203148104Syokota prologue(adp, V_ADP_PALETTE, ENODEV); 203248104Syokota 203348104Syokota outb(PIXMASK, 0xff); /* no pixelmask */ 203448104Syokota outb(PALWADR, 0x00); 2035205604Sjkim bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; 203648104Syokota for (i = 0; i < 256*3; ++i) 2037205604Sjkim outb(PALDATA, palette[i] >> bits); 203848104Syokota inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 203948104Syokota outb(ATC, 0x20); /* enable palette */ 204048104Syokota return 0; 204148104Syokota} 204248104Syokota 204348104Syokotastatic int 204448104Syokotavga_load_palette2(video_adapter_t *adp, int base, int count, 204548104Syokota u_char *r, u_char *g, u_char *b) 204648104Syokota{ 2047205604Sjkim int bits; 204848104Syokota int i; 204948104Syokota 205048104Syokota prologue(adp, V_ADP_PALETTE, ENODEV); 205148104Syokota 205248104Syokota outb(PIXMASK, 0xff); /* no pixelmask */ 205348104Syokota outb(PALWADR, base); 2054205604Sjkim bits = (adp->va_flags & V_ADP_DAC8) != 0 ? 0 : 2; 205548104Syokota for (i = 0; i < count; ++i) { 2056205604Sjkim outb(PALDATA, r[i] >> bits); 2057205604Sjkim outb(PALDATA, g[i] >> bits); 2058205604Sjkim outb(PALDATA, b[i] >> bits); 205948104Syokota } 206048104Syokota inb(adp->va_crtc_addr + 6); /* reset flip/flop */ 206148104Syokota outb(ATC, 0x20); /* enable palette */ 206248104Syokota return 0; 206348104Syokota} 206448104Syokota 206548104Syokota/* 206648104Syokota * set_border(): 206748104Syokota * Change the border color. 206848104Syokota * 206948104Syokota * CGA/EGA/VGA 207048104Syokota */ 207148104Syokotastatic int 207248104Syokotavga_set_border(video_adapter_t *adp, int color) 207348104Syokota{ 207448104Syokota prologue(adp, V_ADP_BORDER, ENODEV); 207548104Syokota 207648104Syokota switch (adp->va_type) { 207748104Syokota case KD_EGA: 207848104Syokota case KD_VGA: 207948104Syokota inb(adp->va_crtc_addr + 6); /* reset flip-flop */ 208048104Syokota outb(ATC, 0x31); outb(ATC, color & 0xff); 208148104Syokota break; 208248104Syokota case KD_CGA: 208348104Syokota outb(adp->va_crtc_addr + 5, color & 0x0f); /* color select register */ 208448104Syokota break; 208548104Syokota case KD_MONO: 208648104Syokota case KD_HERCULES: 208748104Syokota default: 208848104Syokota break; 208948104Syokota } 209048104Syokota return 0; 209148104Syokota} 209248104Syokota 209348104Syokota/* 209448104Syokota * save_state(): 209548104Syokota * Read video register values. 209648104Syokota * NOTE: this function only reads the standard EGA/VGA registers. 209748104Syokota * any extra/extended registers of SVGA adapters are not saved. 209848104Syokota * 209948104Syokota * VGA 210048104Syokota */ 210148104Syokotastatic int 210248104Syokotavga_save_state(video_adapter_t *adp, void *p, size_t size) 210348104Syokota{ 210448104Syokota video_info_t info; 210548104Syokota u_char *buf; 210648104Syokota int crtc_addr; 210748104Syokota int i, j; 210848104Syokota int s; 210948104Syokota 211048104Syokota if (size == 0) { 211148104Syokota /* return the required buffer size */ 211248104Syokota prologue(adp, V_ADP_STATESAVE, 0); 211348104Syokota return sizeof(adp_state_t); 211448104Syokota } else { 211548104Syokota prologue(adp, V_ADP_STATESAVE, ENODEV); 211648104Syokota if (size < sizeof(adp_state_t)) 211748104Syokota return EINVAL; 211848104Syokota } 211948104Syokota 212048104Syokota ((adp_state_t *)p)->sig = V_STATE_SIG; 212148104Syokota buf = ((adp_state_t *)p)->regs; 212248104Syokota bzero(buf, V_MODE_PARAM_SIZE); 212348104Syokota crtc_addr = adp->va_crtc_addr; 212448104Syokota 212548104Syokota s = splhigh(); 212648104Syokota 212748104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 212848104Syokota for (i = 0, j = 5; i < 4; i++) { 212948104Syokota outb(TSIDX, i + 1); 213048104Syokota buf[j++] = inb(TSREG); 213148104Syokota } 213248104Syokota buf[9] = inb(MISC + 10); /* dot-clock */ 213348104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 213448104Syokota 213548104Syokota for (i = 0, j = 10; i < 25; i++) { /* crtc */ 213648104Syokota outb(crtc_addr, i); 213748104Syokota buf[j++] = inb(crtc_addr + 1); 213848104Syokota } 213948104Syokota for (i = 0, j = 35; i < 20; i++) { /* attribute ctrl */ 214048104Syokota inb(crtc_addr + 6); /* reset flip-flop */ 214148104Syokota outb(ATC, i); 214248104Syokota buf[j++] = inb(ATC + 1); 214348104Syokota } 214448104Syokota for (i = 0, j = 55; i < 9; i++) { /* graph data ctrl */ 214548104Syokota outb(GDCIDX, i); 214648104Syokota buf[j++] = inb(GDCREG); 214748104Syokota } 214848104Syokota inb(crtc_addr + 6); /* reset flip-flop */ 214948104Syokota outb(ATC, 0x20); /* enable palette */ 215048104Syokota 215148104Syokota splx(s); 215248104Syokota 215348104Syokota#if 1 215448104Syokota if (vga_get_info(adp, adp->va_mode, &info) == 0) { 215548104Syokota if (info.vi_flags & V_INFO_GRAPHICS) { 215648104Syokota buf[0] = info.vi_width/info.vi_cwidth; /* COLS */ 215748104Syokota buf[1] = info.vi_height/info.vi_cheight - 1; /* ROWS */ 215848104Syokota } else { 215948104Syokota buf[0] = info.vi_width; /* COLS */ 216048104Syokota buf[1] = info.vi_height - 1; /* ROWS */ 216148104Syokota } 216248104Syokota buf[2] = info.vi_cheight; /* POINTS */ 216348104Syokota } else { 216448104Syokota /* XXX: shouldn't be happening... */ 216548104Syokota printf("vga%d: %s: failed to obtain mode info. (vga_save_state())\n", 216648104Syokota adp->va_unit, adp->va_name); 216748104Syokota } 216848104Syokota#else 216948104Syokota buf[0] = readb(BIOS_PADDRTOVADDR(0x44a)); /* COLS */ 217048104Syokota buf[1] = readb(BIOS_PADDRTOVADDR(0x484)); /* ROWS */ 217148104Syokota buf[2] = readb(BIOS_PADDRTOVADDR(0x485)); /* POINTS */ 217248104Syokota buf[3] = readb(BIOS_PADDRTOVADDR(0x44c)); 217348104Syokota buf[4] = readb(BIOS_PADDRTOVADDR(0x44d)); 217448104Syokota#endif 217548104Syokota 217648104Syokota return 0; 217748104Syokota} 217848104Syokota 217948104Syokota/* 218048104Syokota * load_state(): 218148104Syokota * Set video registers at once. 218248104Syokota * NOTE: this function only updates the standard EGA/VGA registers. 218348104Syokota * any extra/extended registers of SVGA adapters are not changed. 218448104Syokota * 218548104Syokota * EGA/VGA 218648104Syokota */ 218748104Syokotastatic int 218848104Syokotavga_load_state(video_adapter_t *adp, void *p) 218948104Syokota{ 219048104Syokota u_char *buf; 219148104Syokota int crtc_addr; 219248104Syokota int s; 219348104Syokota int i; 219448104Syokota 219548104Syokota prologue(adp, V_ADP_STATELOAD, ENODEV); 219648104Syokota if (((adp_state_t *)p)->sig != V_STATE_SIG) 219748104Syokota return EINVAL; 219848104Syokota 219948104Syokota buf = ((adp_state_t *)p)->regs; 220048104Syokota crtc_addr = adp->va_crtc_addr; 220148104Syokota 220248104Syokota#if VGA_DEBUG > 1 220348104Syokota dump_buffer(buf, V_MODE_PARAM_SIZE); 220448104Syokota#endif 220548104Syokota 220648104Syokota s = splhigh(); 220748104Syokota 220848104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x01); /* stop sequencer */ 220948104Syokota for (i = 0; i < 4; ++i) { /* program sequencer */ 221048104Syokota outb(TSIDX, i + 1); 221148104Syokota outb(TSREG, buf[i + 5]); 221248104Syokota } 221348104Syokota outb(MISC, buf[9]); /* set dot-clock */ 221448104Syokota outb(TSIDX, 0x00); outb(TSREG, 0x03); /* start sequencer */ 221548104Syokota outb(crtc_addr, 0x11); 221648104Syokota outb(crtc_addr + 1, inb(crtc_addr + 1) & 0x7F); 221748104Syokota for (i = 0; i < 25; ++i) { /* program crtc */ 221848104Syokota outb(crtc_addr, i); 221948104Syokota outb(crtc_addr + 1, buf[i + 10]); 222048104Syokota } 222148104Syokota inb(crtc_addr+6); /* reset flip-flop */ 222248104Syokota for (i = 0; i < 20; ++i) { /* program attribute ctrl */ 222348104Syokota outb(ATC, i); 222448104Syokota outb(ATC, buf[i + 35]); 222548104Syokota } 222648104Syokota for (i = 0; i < 9; ++i) { /* program graph data ctrl */ 222748104Syokota outb(GDCIDX, i); 222848104Syokota outb(GDCREG, buf[i + 55]); 222948104Syokota } 223048104Syokota inb(crtc_addr + 6); /* reset flip-flop */ 223148104Syokota outb(ATC, 0x20); /* enable palette */ 223248104Syokota 2233153072Sru#ifdef notyet /* a temporary workaround for kernel panic, XXX */ 223448104Syokota#ifndef VGA_NO_BIOS 223548104Syokota if (adp->va_unit == V_ADP_PRIMARY) { 223648104Syokota writeb(BIOS_PADDRTOVADDR(0x44a), buf[0]); /* COLS */ 223748104Syokota writeb(BIOS_PADDRTOVADDR(0x484), buf[1] + rows_offset - 1); /* ROWS */ 223848104Syokota writeb(BIOS_PADDRTOVADDR(0x485), buf[2]); /* POINTS */ 223948104Syokota#if 0 224048104Syokota writeb(BIOS_PADDRTOVADDR(0x44c), buf[3]); 224148104Syokota writeb(BIOS_PADDRTOVADDR(0x44d), buf[4]); 224248104Syokota#endif 224348104Syokota } 224448104Syokota#endif /* VGA_NO_BIOS */ 224548104Syokota#endif /* notyet */ 224648104Syokota 224748104Syokota splx(s); 224848104Syokota return 0; 224948104Syokota} 225048104Syokota 225148104Syokota/* 225248104Syokota * set_origin(): 225348104Syokota * Change the origin (window mapping) of the banked frame buffer. 225448104Syokota */ 225548104Syokotastatic int 225648104Syokotavga_set_origin(video_adapter_t *adp, off_t offset) 225748104Syokota{ 225848104Syokota /* 225948104Syokota * The standard video modes do not require window mapping; 226048104Syokota * always return error. 226148104Syokota */ 226248104Syokota return ENODEV; 226348104Syokota} 226448104Syokota 226548104Syokota/* 226648104Syokota * read_hw_cursor(): 226748104Syokota * Read the position of the hardware text cursor. 226848104Syokota * 226948104Syokota * all adapters 227048104Syokota */ 227148104Syokotastatic int 227248104Syokotavga_read_hw_cursor(video_adapter_t *adp, int *col, int *row) 227348104Syokota{ 227448104Syokota u_int16_t off; 227548104Syokota int s; 227648104Syokota 227748104Syokota if (!vga_init_done) 227848104Syokota return ENXIO; 227948104Syokota 228048104Syokota if (adp->va_info.vi_flags & V_INFO_GRAPHICS) 228148104Syokota return ENODEV; 228248104Syokota 228348104Syokota s = spltty(); 228448104Syokota outb(adp->va_crtc_addr, 14); 228548104Syokota off = inb(adp->va_crtc_addr + 1); 228648104Syokota outb(adp->va_crtc_addr, 15); 228748104Syokota off = (off << 8) | inb(adp->va_crtc_addr + 1); 228848104Syokota splx(s); 228948104Syokota 229048104Syokota *row = off / adp->va_info.vi_width; 229148104Syokota *col = off % adp->va_info.vi_width; 229248104Syokota 229348104Syokota return 0; 229448104Syokota} 229548104Syokota 229648104Syokota/* 229748104Syokota * set_hw_cursor(): 229848104Syokota * Move the hardware text cursor. If col and row are both -1, 229948104Syokota * the cursor won't be shown. 230048104Syokota * 230148104Syokota * all adapters 230248104Syokota */ 230348104Syokotastatic int 230448104Syokotavga_set_hw_cursor(video_adapter_t *adp, int col, int row) 230548104Syokota{ 230648104Syokota u_int16_t off; 230748104Syokota int s; 230848104Syokota 230948104Syokota if (!vga_init_done) 231048104Syokota return ENXIO; 231148104Syokota 231248104Syokota if ((col == -1) && (row == -1)) { 231348104Syokota off = -1; 231448104Syokota } else { 231548104Syokota if (adp->va_info.vi_flags & V_INFO_GRAPHICS) 231648104Syokota return ENODEV; 231748104Syokota off = row*adp->va_info.vi_width + col; 231848104Syokota } 231948104Syokota 232048104Syokota s = spltty(); 232148104Syokota outb(adp->va_crtc_addr, 14); 232248104Syokota outb(adp->va_crtc_addr + 1, off >> 8); 232348104Syokota outb(adp->va_crtc_addr, 15); 232448104Syokota outb(adp->va_crtc_addr + 1, off & 0x00ff); 232548104Syokota splx(s); 232648104Syokota 232748104Syokota return 0; 232848104Syokota} 232948104Syokota 233048104Syokota/* 233148104Syokota * set_hw_cursor_shape(): 233248104Syokota * Change the shape of the hardware text cursor. If the height is 233348104Syokota * zero or negative, the cursor won't be shown. 233448104Syokota * 233548104Syokota * all adapters 233648104Syokota */ 233748104Syokotastatic int 233848104Syokotavga_set_hw_cursor_shape(video_adapter_t *adp, int base, int height, 233948104Syokota int celsize, int blink) 234048104Syokota{ 234148104Syokota int s; 234248104Syokota 234348104Syokota if (!vga_init_done) 234448104Syokota return ENXIO; 234548104Syokota 234648104Syokota s = spltty(); 234748104Syokota switch (adp->va_type) { 234848104Syokota case KD_VGA: 234948104Syokota case KD_CGA: 235048104Syokota case KD_MONO: 235148104Syokota case KD_HERCULES: 235248104Syokota default: 235348104Syokota if (height <= 0) { 235448104Syokota /* make the cursor invisible */ 235548104Syokota outb(adp->va_crtc_addr, 10); 235648104Syokota outb(adp->va_crtc_addr + 1, 32); 235748104Syokota outb(adp->va_crtc_addr, 11); 235848104Syokota outb(adp->va_crtc_addr + 1, 0); 235948104Syokota } else { 236048104Syokota outb(adp->va_crtc_addr, 10); 236148104Syokota outb(adp->va_crtc_addr + 1, celsize - base - height); 236248104Syokota outb(adp->va_crtc_addr, 11); 236348104Syokota outb(adp->va_crtc_addr + 1, celsize - base - 1); 236448104Syokota } 236548104Syokota break; 236648104Syokota case KD_EGA: 236748104Syokota if (height <= 0) { 236848104Syokota /* make the cursor invisible */ 236948104Syokota outb(adp->va_crtc_addr, 10); 237048104Syokota outb(adp->va_crtc_addr + 1, celsize); 237148104Syokota outb(adp->va_crtc_addr, 11); 237248104Syokota outb(adp->va_crtc_addr + 1, 0); 237348104Syokota } else { 237448104Syokota outb(adp->va_crtc_addr, 10); 237548104Syokota outb(adp->va_crtc_addr + 1, celsize - base - height); 237648104Syokota outb(adp->va_crtc_addr, 11); 237748104Syokota outb(adp->va_crtc_addr + 1, celsize - base); 237848104Syokota } 237948104Syokota break; 238048104Syokota } 238148104Syokota splx(s); 238248104Syokota 238348104Syokota return 0; 238448104Syokota} 238548104Syokota 238648104Syokota/* 238748104Syokota * blank_display() 238848104Syokota * Put the display in power save/power off mode. 238948104Syokota * 239048104Syokota * all adapters 239148104Syokota */ 239248104Syokotastatic int 239348104Syokotavga_blank_display(video_adapter_t *adp, int mode) 239448104Syokota{ 239548104Syokota u_char val; 239648104Syokota int s; 239748104Syokota 239848104Syokota s = splhigh(); 239948104Syokota switch (adp->va_type) { 240048104Syokota case KD_VGA: 240148104Syokota switch (mode) { 240248104Syokota case V_DISPLAY_SUSPEND: 240348104Syokota case V_DISPLAY_STAND_BY: 240448104Syokota outb(TSIDX, 0x01); 240548104Syokota val = inb(TSREG); 240648104Syokota outb(TSIDX, 0x01); 240748104Syokota outb(TSREG, val | 0x20); 240848104Syokota outb(adp->va_crtc_addr, 0x17); 240948104Syokota val = inb(adp->va_crtc_addr + 1); 241048104Syokota outb(adp->va_crtc_addr + 1, val & ~0x80); 241148104Syokota break; 241248104Syokota case V_DISPLAY_BLANK: 241348104Syokota outb(TSIDX, 0x01); 241448104Syokota val = inb(TSREG); 241548104Syokota outb(TSIDX, 0x01); 241648104Syokota outb(TSREG, val | 0x20); 241748104Syokota break; 241848104Syokota case V_DISPLAY_ON: 241948104Syokota outb(TSIDX, 0x01); 242048104Syokota val = inb(TSREG); 242148104Syokota outb(TSIDX, 0x01); 242248104Syokota outb(TSREG, val & 0xDF); 242348104Syokota outb(adp->va_crtc_addr, 0x17); 242448104Syokota val = inb(adp->va_crtc_addr + 1); 242548104Syokota outb(adp->va_crtc_addr + 1, val | 0x80); 242648104Syokota break; 242748104Syokota } 242848104Syokota break; 242948104Syokota 243048104Syokota case KD_EGA: 243148104Syokota /* no support yet */ 243281455Syokota splx(s); 243348104Syokota return ENODEV; 243448104Syokota 243548104Syokota case KD_CGA: 243648104Syokota switch (mode) { 243748104Syokota case V_DISPLAY_SUSPEND: 243848104Syokota case V_DISPLAY_STAND_BY: 243948104Syokota case V_DISPLAY_BLANK: 244048104Syokota outb(adp->va_crtc_addr + 4, 0x25); 244148104Syokota break; 244248104Syokota case V_DISPLAY_ON: 244348104Syokota outb(adp->va_crtc_addr + 4, 0x2d); 244448104Syokota break; 244548104Syokota } 244648104Syokota break; 244748104Syokota 244848104Syokota case KD_MONO: 244948104Syokota case KD_HERCULES: 245048104Syokota switch (mode) { 245148104Syokota case V_DISPLAY_SUSPEND: 245248104Syokota case V_DISPLAY_STAND_BY: 245348104Syokota case V_DISPLAY_BLANK: 245448104Syokota outb(adp->va_crtc_addr + 4, 0x21); 245548104Syokota break; 245648104Syokota case V_DISPLAY_ON: 245748104Syokota outb(adp->va_crtc_addr + 4, 0x29); 245848104Syokota break; 245948104Syokota } 246048104Syokota break; 246148104Syokota default: 246248104Syokota break; 246348104Syokota } 246448104Syokota splx(s); 246548104Syokota 246648104Syokota return 0; 246748104Syokota} 246848104Syokota 246948104Syokota/* 247048104Syokota * mmap(): 247148104Syokota * Mmap frame buffer. 247248104Syokota * 247348104Syokota * all adapters 247448104Syokota */ 247548104Syokotastatic int 2476201223Srnolandvga_mmap_buf(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr, 2477201223Srnoland int prot, vm_memattr_t *memattr) 247848104Syokota{ 247948104Syokota if (adp->va_info.vi_flags & V_INFO_LINEAR) 248048104Syokota return -1; 248148104Syokota 248248104Syokota#if VGA_DEBUG > 0 2483106662Sjhb printf("vga_mmap_buf(): window:0x%jx, offset:0x%jx\n", 2484106662Sjhb (uintmax_t)adp->va_info.vi_window, (uintmax_t)offset); 248548104Syokota#endif 248648104Syokota 248748104Syokota /* XXX: is this correct? */ 248848104Syokota if (offset > adp->va_window_size - PAGE_SIZE) 248948104Syokota return -1; 249048104Syokota 2491111462Smux *paddr = adp->va_info.vi_window + offset; 2492111462Smux return 0; 249348104Syokota} 249448104Syokota 249548104Syokota#ifndef VGA_NO_MODE_CHANGE 249648104Syokota 249748104Syokotastatic void 249848104Syokotaplanar_fill(video_adapter_t *adp, int val) 249948104Syokota{ 250048104Syokota int length; 250148104Syokota int at; /* position in the frame buffer */ 250248104Syokota int l; 250348104Syokota 250448104Syokota outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 250548104Syokota outw(GDCIDX, 0x0003); /* data rotate/function select */ 250648104Syokota outw(GDCIDX, 0x0f01); /* set/reset enable */ 250748104Syokota outw(GDCIDX, 0xff08); /* bit mask */ 250848104Syokota outw(GDCIDX, (val << 8) | 0x00); /* set/reset */ 250948104Syokota at = 0; 251048104Syokota length = adp->va_line_width*adp->va_info.vi_height; 251148104Syokota while (length > 0) { 251248104Syokota l = imin(length, adp->va_window_size); 2513174985Swkoszek vidd_set_win_org(adp, at); 251448104Syokota bzero_io(adp->va_window, l); 251548104Syokota length -= l; 251648104Syokota at += l; 251748104Syokota } 251848104Syokota outw(GDCIDX, 0x0000); /* set/reset */ 251948104Syokota outw(GDCIDX, 0x0001); /* set/reset enable */ 252048104Syokota} 252148104Syokota 252248104Syokotastatic void 252348104Syokotapacked_fill(video_adapter_t *adp, int val) 252448104Syokota{ 252548104Syokota int length; 252648104Syokota int at; /* position in the frame buffer */ 252748104Syokota int l; 252848104Syokota 252948104Syokota at = 0; 253048104Syokota length = adp->va_line_width*adp->va_info.vi_height; 253148104Syokota while (length > 0) { 253248104Syokota l = imin(length, adp->va_window_size); 2533174985Swkoszek vidd_set_win_org(adp, at); 253448104Syokota fill_io(val, adp->va_window, l); 253548104Syokota length -= l; 253648104Syokota at += l; 253748104Syokota } 253848104Syokota} 253948104Syokota 254048104Syokotastatic void 254148104Syokotadirect_fill(video_adapter_t *adp, int val) 254248104Syokota{ 254348104Syokota int length; 254448104Syokota int at; /* position in the frame buffer */ 254548104Syokota int l; 254648104Syokota 254748104Syokota at = 0; 254848104Syokota length = adp->va_line_width*adp->va_info.vi_height; 254948104Syokota while (length > 0) { 255048104Syokota l = imin(length, adp->va_window_size); 2551174985Swkoszek vidd_set_win_org(adp, at); 255248104Syokota switch (adp->va_info.vi_pixel_size) { 255348104Syokota case sizeof(u_int16_t): 255448104Syokota fillw_io(val, adp->va_window, l/sizeof(u_int16_t)); 255548104Syokota break; 255648104Syokota case 3: 255748104Syokota /* FIXME */ 255848104Syokota break; 255948104Syokota case sizeof(u_int32_t): 256048104Syokota filll_io(val, adp->va_window, l/sizeof(u_int32_t)); 256148104Syokota break; 256248104Syokota } 256348104Syokota length -= l; 256448104Syokota at += l; 256548104Syokota } 256648104Syokota} 256748104Syokota 256848104Syokotastatic int 256948104Syokotavga_clear(video_adapter_t *adp) 257048104Syokota{ 257148104Syokota switch (adp->va_info.vi_mem_model) { 257248104Syokota case V_INFO_MM_TEXT: 257348104Syokota /* do nothing? XXX */ 257448104Syokota break; 257548104Syokota case V_INFO_MM_PLANAR: 257648104Syokota planar_fill(adp, 0); 257748104Syokota break; 257848104Syokota case V_INFO_MM_PACKED: 257948104Syokota packed_fill(adp, 0); 258048104Syokota break; 258148104Syokota case V_INFO_MM_DIRECT: 258248104Syokota direct_fill(adp, 0); 258348104Syokota break; 258448104Syokota } 258548104Syokota return 0; 258648104Syokota} 258748104Syokota 258848104Syokota#ifdef notyet 258948104Syokotastatic void 259048104Syokotaplanar_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 259148104Syokota{ 259248104Syokota int banksize; 259348104Syokota int bank; 259448104Syokota int pos; 259548104Syokota int offset; /* offset within window */ 259648104Syokota int bx; 259748104Syokota int l; 259848104Syokota 259948104Syokota outw(GDCIDX, 0x0005); /* read mode 0, write mode 0 */ 260048104Syokota outw(GDCIDX, 0x0003); /* data rotate/function select */ 260148104Syokota outw(GDCIDX, 0x0f01); /* set/reset enable */ 260248104Syokota outw(GDCIDX, 0xff08); /* bit mask */ 260348104Syokota outw(GDCIDX, (val << 8) | 0x00); /* set/reset */ 260448104Syokota 260548104Syokota banksize = adp->va_window_size; 260648104Syokota bank = -1; 260748104Syokota while (cy > 0) { 260848104Syokota pos = adp->va_line_width*y + x/8; 260948104Syokota if (bank != pos/banksize) { 2610174985Swkoszek vidd_set_win_org(adp, pos); 261148104Syokota bank = pos/banksize; 261248104Syokota } 261348104Syokota offset = pos%banksize; 261448104Syokota bx = (x + cx)/8 - x/8; 261548104Syokota if (x % 8) { 261648104Syokota outw(GDCIDX, ((0xff00 >> (x % 8)) & 0xff00) | 0x08); 261748104Syokota writeb(adp->va_window + offset, 0); 261848104Syokota ++offset; 261948104Syokota --bx; 262048104Syokota if (offset >= banksize) { 262148104Syokota offset = 0; 262248104Syokota ++bank; /* next bank */ 2623174985Swkoszek vidd_set_win_org(adp, bank*banksize); 262448104Syokota } 262548104Syokota outw(GDCIDX, 0xff08); /* bit mask */ 262648104Syokota } 262748104Syokota while (bx > 0) { 262848104Syokota l = imin(bx, banksize); 262948104Syokota bzero_io(adp->va_window + offset, l); 263048104Syokota offset += l; 263148104Syokota bx -= l; 263248104Syokota if (offset >= banksize) { 263348104Syokota offset = 0; 263448104Syokota ++bank; /* next bank */ 2635174985Swkoszek vidd_set_win_org(adp, bank*banksize); 263648104Syokota } 263748104Syokota } 263848104Syokota if ((x + cx) % 8) { 263948104Syokota outw(GDCIDX, (~(0xff00 >> ((x + cx) % 8)) & 0xff00) | 0x08); 264048104Syokota writeb(adp->va_window + offset, 0); 264148104Syokota ++offset; 264248104Syokota if (offset >= banksize) { 264348104Syokota offset = 0; 264448104Syokota ++bank; /* next bank */ 2645174985Swkoszek vidd_set_win_org(adp, bank*banksize); 264648104Syokota } 264748104Syokota outw(GDCIDX, 0xff08); /* bit mask */ 264848104Syokota } 264948104Syokota ++y; 265048104Syokota --cy; 265148104Syokota } 265248104Syokota 265348104Syokota outw(GDCIDX, 0xff08); /* bit mask */ 265448104Syokota outw(GDCIDX, 0x0000); /* set/reset */ 265548104Syokota outw(GDCIDX, 0x0001); /* set/reset enable */ 265648104Syokota} 265748104Syokota 265848104Syokotastatic void 265948104Syokotapacked_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 266048104Syokota{ 266148104Syokota int banksize; 266248104Syokota int bank; 266348104Syokota int pos; 266448104Syokota int offset; /* offset within window */ 266548104Syokota int end; 266648104Syokota 266748104Syokota banksize = adp->va_window_size; 266848104Syokota bank = -1; 266948104Syokota cx *= adp->va_info.vi_pixel_size; 267048104Syokota while (cy > 0) { 267148104Syokota pos = adp->va_line_width*y + x*adp->va_info.vi_pixel_size; 267248104Syokota if (bank != pos/banksize) { 2673174985Swkoszek vidd_set_win_org(adp, pos); 267448104Syokota bank = pos/banksize; 267548104Syokota } 267648104Syokota offset = pos%banksize; 267748104Syokota end = imin(offset + cx, banksize); 267848104Syokota fill_io(val, adp->va_window + offset, 267948104Syokota (end - offset)/adp->va_info.vi_pixel_size); 268048104Syokota /* the line may cross the window boundary */ 268148104Syokota if (offset + cx > banksize) { 268248104Syokota ++bank; /* next bank */ 2683174985Swkoszek vidd_set_win_org(adp, bank*banksize); 268448104Syokota end = offset + cx - banksize; 268548104Syokota fill_io(val, adp->va_window, end/adp->va_info.vi_pixel_size); 268648104Syokota } 268748104Syokota ++y; 268848104Syokota --cy; 268948104Syokota } 269048104Syokota} 269148104Syokota 269248104Syokotastatic void 269348104Syokotadirect_fill_rect16(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 269448104Syokota{ 269548104Syokota int banksize; 269648104Syokota int bank; 269748104Syokota int pos; 269848104Syokota int offset; /* offset within window */ 269948104Syokota int end; 270048104Syokota 270148104Syokota /* 270248104Syokota * XXX: the function assumes that banksize is a muliple of 270348104Syokota * sizeof(u_int16_t). 270448104Syokota */ 270548104Syokota banksize = adp->va_window_size; 270648104Syokota bank = -1; 270748104Syokota cx *= sizeof(u_int16_t); 270848104Syokota while (cy > 0) { 270948104Syokota pos = adp->va_line_width*y + x*sizeof(u_int16_t); 271048104Syokota if (bank != pos/banksize) { 2711174985Swkoszek vidd_set_win_org(adp, pos); 271248104Syokota bank = pos/banksize; 271348104Syokota } 271448104Syokota offset = pos%banksize; 271548104Syokota end = imin(offset + cx, banksize); 271648104Syokota fillw_io(val, adp->va_window + offset, 271748104Syokota (end - offset)/sizeof(u_int16_t)); 271848104Syokota /* the line may cross the window boundary */ 271948104Syokota if (offset + cx > banksize) { 272048104Syokota ++bank; /* next bank */ 2721174985Swkoszek vidd_set_win_org(adp, bank*banksize); 272248104Syokota end = offset + cx - banksize; 272348104Syokota fillw_io(val, adp->va_window, end/sizeof(u_int16_t)); 272448104Syokota } 272548104Syokota ++y; 272648104Syokota --cy; 272748104Syokota } 272848104Syokota} 272948104Syokota 273048104Syokotastatic void 273148104Syokotadirect_fill_rect24(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 273248104Syokota{ 273348104Syokota int banksize; 273448104Syokota int bank; 273548104Syokota int pos; 273648104Syokota int offset; /* offset within window */ 273748104Syokota int end; 273848104Syokota int i; 273948104Syokota int j; 274048104Syokota u_int8_t b[3]; 274148104Syokota 274248104Syokota b[0] = val & 0x0000ff; 274348104Syokota b[1] = (val >> 8) & 0x0000ff; 274448104Syokota b[2] = (val >> 16) & 0x0000ff; 274548104Syokota banksize = adp->va_window_size; 274648104Syokota bank = -1; 274748104Syokota cx *= 3; 274848104Syokota while (cy > 0) { 274948104Syokota pos = adp->va_line_width*y + x*3; 275048104Syokota if (bank != pos/banksize) { 2751174985Swkoszek vidd_set_win_org(adp, pos); 275248104Syokota bank = pos/banksize; 275348104Syokota } 275448104Syokota offset = pos%banksize; 275548104Syokota end = imin(offset + cx, banksize); 275648104Syokota for (i = 0, j = offset; j < end; i = (++i)%3, ++j) { 275748104Syokota writeb(adp->va_window + j, b[i]); 275848104Syokota } 275948104Syokota /* the line may cross the window boundary */ 276048104Syokota if (offset + cx >= banksize) { 276148104Syokota ++bank; /* next bank */ 2762174985Swkoszek vidd_set_win_org(adp, bank*banksize); 276348104Syokota j = 0; 276448104Syokota end = offset + cx - banksize; 276548104Syokota for (; j < end; i = (++i)%3, ++j) { 276648104Syokota writeb(adp->va_window + j, b[i]); 276748104Syokota } 276848104Syokota } 276948104Syokota ++y; 277048104Syokota --cy; 277148104Syokota } 277248104Syokota} 277348104Syokota 277448104Syokotastatic void 277548104Syokotadirect_fill_rect32(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 277648104Syokota{ 277748104Syokota int banksize; 277848104Syokota int bank; 277948104Syokota int pos; 278048104Syokota int offset; /* offset within window */ 278148104Syokota int end; 278248104Syokota 278348104Syokota /* 278448104Syokota * XXX: the function assumes that banksize is a muliple of 278548104Syokota * sizeof(u_int32_t). 278648104Syokota */ 278748104Syokota banksize = adp->va_window_size; 278848104Syokota bank = -1; 278948104Syokota cx *= sizeof(u_int32_t); 279048104Syokota while (cy > 0) { 279148104Syokota pos = adp->va_line_width*y + x*sizeof(u_int32_t); 279248104Syokota if (bank != pos/banksize) { 2793174985Swkoszek vidd_set_win_org(adp, pos); 279448104Syokota bank = pos/banksize; 279548104Syokota } 279648104Syokota offset = pos%banksize; 279748104Syokota end = imin(offset + cx, banksize); 279848104Syokota filll_io(val, adp->va_window + offset, 279948104Syokota (end - offset)/sizeof(u_int32_t)); 280048104Syokota /* the line may cross the window boundary */ 280148104Syokota if (offset + cx > banksize) { 280248104Syokota ++bank; /* next bank */ 2803174985Swkoszek vidd_set_win_org(adp, bank*banksize); 280448104Syokota end = offset + cx - banksize; 280548104Syokota filll_io(val, adp->va_window, end/sizeof(u_int32_t)); 280648104Syokota } 280748104Syokota ++y; 280848104Syokota --cy; 280948104Syokota } 281048104Syokota} 281148104Syokota 281248104Syokotastatic int 281348104Syokotavga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 281448104Syokota{ 281548104Syokota switch (adp->va_info.vi_mem_model) { 281648104Syokota case V_INFO_MM_TEXT: 281748104Syokota /* do nothing? XXX */ 281848104Syokota break; 281948104Syokota case V_INFO_MM_PLANAR: 282048104Syokota planar_fill_rect(adp, val, x, y, cx, cy); 282148104Syokota break; 282248104Syokota case V_INFO_MM_PACKED: 282348104Syokota packed_fill_rect(adp, val, x, y, cx, cy); 282448104Syokota break; 282548104Syokota case V_INFO_MM_DIRECT: 282648104Syokota switch (adp->va_info.vi_pixel_size) { 282748104Syokota case sizeof(u_int16_t): 282848104Syokota direct_fill_rect16(adp, val, x, y, cx, cy); 282948104Syokota break; 283048104Syokota case 3: 283148104Syokota direct_fill_rect24(adp, val, x, y, cx, cy); 283248104Syokota break; 283348104Syokota case sizeof(u_int32_t): 283448104Syokota direct_fill_rect32(adp, val, x, y, cx, cy); 283548104Syokota break; 283648104Syokota } 283748104Syokota break; 283848104Syokota } 283948104Syokota return 0; 284048104Syokota} 284148104Syokota#else /* !notyet */ 284248104Syokotastatic int 284348104Syokotavga_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy) 284448104Syokota{ 284548104Syokota return ENODEV; 284648104Syokota} 284748104Syokota#endif /* notyet */ 284848104Syokota 284948104Syokotastatic int 285048104Syokotavga_bitblt(video_adapter_t *adp,...) 285148104Syokota{ 285248104Syokota /* FIXME */ 285348104Syokota return ENODEV; 285448104Syokota} 285548104Syokota 285648104Syokota#endif /* !VGA_NO_MODE_CHANGE */ 285748104Syokota 285848104Syokotastatic int 285948104Syokotaget_palette(video_adapter_t *adp, int base, int count, 286048104Syokota u_char *red, u_char *green, u_char *blue, u_char *trans) 286148104Syokota{ 286248104Syokota u_char *r; 286348104Syokota u_char *g; 286448104Syokota u_char *b; 286548104Syokota 2866127792Snectar if (count < 0 || base < 0 || count > 256 || base > 256 || 2867127792Snectar base + count > 256) 286848104Syokota return EINVAL; 286948104Syokota 2870111119Simp r = malloc(count*3, M_DEVBUF, M_WAITOK); 287148104Syokota g = r + count; 287248104Syokota b = g + count; 2873104389Sphk if (vga_save_palette2(adp, base, count, r, g, b)) { 2874104389Sphk free(r, M_DEVBUF); 287548104Syokota return ENODEV; 2876104389Sphk } 287748104Syokota copyout(r, red, count); 287848104Syokota copyout(g, green, count); 287948104Syokota copyout(b, blue, count); 288048104Syokota if (trans != NULL) { 288148104Syokota bzero(r, count); 288248104Syokota copyout(r, trans, count); 288348104Syokota } 288448104Syokota free(r, M_DEVBUF); 288548104Syokota 288648104Syokota return 0; 288748104Syokota} 288848104Syokota 288948104Syokotastatic int 289048104Syokotaset_palette(video_adapter_t *adp, int base, int count, 289148104Syokota u_char *red, u_char *green, u_char *blue, u_char *trans) 289248104Syokota{ 289348104Syokota u_char *r; 289448104Syokota u_char *g; 289548104Syokota u_char *b; 289648104Syokota int err; 289748104Syokota 2898127792Snectar if (count < 0 || base < 0 || count > 256 || base > 256 || 2899127792Snectar base + count > 256) 290048104Syokota return EINVAL; 290148104Syokota 2902111119Simp r = malloc(count*3, M_DEVBUF, M_WAITOK); 290348104Syokota g = r + count; 290448104Syokota b = g + count; 2905144146Ssam err = copyin(red, r, count); 2906144146Ssam if (!err) 2907144146Ssam err = copyin(green, g, count); 2908144146Ssam if (!err) 2909144146Ssam err = copyin(blue, b, count); 2910144146Ssam if (!err) 2911144146Ssam err = vga_load_palette2(adp, base, count, r, g, b); 291248104Syokota free(r, M_DEVBUF); 291348104Syokota 291448104Syokota return (err ? ENODEV : 0); 291548104Syokota} 291648104Syokota 291748104Syokotastatic int 291848104Syokotavga_dev_ioctl(video_adapter_t *adp, u_long cmd, caddr_t arg) 291948104Syokota{ 292048104Syokota switch (cmd) { 292148104Syokota case FBIO_GETWINORG: /* get frame buffer window origin */ 292248104Syokota *(u_int *)arg = 0; 292348104Syokota return 0; 292448104Syokota 292548104Syokota case FBIO_SETWINORG: /* set frame buffer window origin */ 292648104Syokota return ENODEV; 292748104Syokota 292848104Syokota case FBIO_SETDISPSTART: /* set display start address */ 292948104Syokota return (set_display_start(adp, 293048104Syokota ((video_display_start_t *)arg)->x, 293148104Syokota ((video_display_start_t *)arg)->y) 293248104Syokota ? ENODEV : 0); 293348104Syokota 293448104Syokota case FBIO_SETLINEWIDTH: /* set scan line length in pixel */ 293548104Syokota return (set_line_length(adp, *(u_int *)arg) ? ENODEV : 0); 293648104Syokota 293748104Syokota case FBIO_GETPALETTE: /* get color palette */ 293848104Syokota return get_palette(adp, ((video_color_palette_t *)arg)->index, 293948104Syokota ((video_color_palette_t *)arg)->count, 294048104Syokota ((video_color_palette_t *)arg)->red, 294148104Syokota ((video_color_palette_t *)arg)->green, 294248104Syokota ((video_color_palette_t *)arg)->blue, 294348104Syokota ((video_color_palette_t *)arg)->transparent); 294448104Syokota 294548104Syokota case FBIO_SETPALETTE: /* set color palette */ 294648104Syokota return set_palette(adp, ((video_color_palette_t *)arg)->index, 294748104Syokota ((video_color_palette_t *)arg)->count, 294848104Syokota ((video_color_palette_t *)arg)->red, 294948104Syokota ((video_color_palette_t *)arg)->green, 295048104Syokota ((video_color_palette_t *)arg)->blue, 295148104Syokota ((video_color_palette_t *)arg)->transparent); 295248104Syokota 295348104Syokota case FBIOGTYPE: /* get frame buffer type info. */ 295448104Syokota ((struct fbtype *)arg)->fb_type = fb_type(adp->va_type); 295548104Syokota ((struct fbtype *)arg)->fb_height = adp->va_info.vi_height; 295648104Syokota ((struct fbtype *)arg)->fb_width = adp->va_info.vi_width; 295748104Syokota ((struct fbtype *)arg)->fb_depth = adp->va_info.vi_depth; 295848104Syokota if ((adp->va_info.vi_depth <= 1) || (adp->va_info.vi_depth > 8)) 295948104Syokota ((struct fbtype *)arg)->fb_cmsize = 0; 296048104Syokota else 296148104Syokota ((struct fbtype *)arg)->fb_cmsize = 1 << adp->va_info.vi_depth; 296248104Syokota ((struct fbtype *)arg)->fb_size = adp->va_buffer_size; 296348104Syokota return 0; 296448104Syokota 296548104Syokota case FBIOGETCMAP: /* get color palette */ 296648104Syokota return get_palette(adp, ((struct fbcmap *)arg)->index, 296748104Syokota ((struct fbcmap *)arg)->count, 296848104Syokota ((struct fbcmap *)arg)->red, 296948104Syokota ((struct fbcmap *)arg)->green, 297048104Syokota ((struct fbcmap *)arg)->blue, NULL); 297148104Syokota 297248104Syokota case FBIOPUTCMAP: /* set color palette */ 297348104Syokota return set_palette(adp, ((struct fbcmap *)arg)->index, 297448104Syokota ((struct fbcmap *)arg)->count, 297548104Syokota ((struct fbcmap *)arg)->red, 297648104Syokota ((struct fbcmap *)arg)->green, 297748104Syokota ((struct fbcmap *)arg)->blue, NULL); 297848104Syokota 297948104Syokota default: 298048104Syokota return fb_commonioctl(adp, cmd, arg); 298148104Syokota } 298248104Syokota} 298348104Syokota 298448104Syokotastatic void 298548104Syokotadump_buffer(u_char *buf, size_t len) 298648104Syokota{ 298748104Syokota int i; 298848104Syokota 298948104Syokota for(i = 0; i < len;) { 299048104Syokota printf("%02x ", buf[i]); 299148104Syokota if ((++i % 16) == 0) 299248104Syokota printf("\n"); 299348104Syokota } 299448104Syokota} 299548104Syokota 299648104Syokota/* 299748104Syokota * diag(): 299848104Syokota * Print some information about the video adapter and video modes, 299948104Syokota * with requested level of details. 300048104Syokota * 300148104Syokota * all adapters 300248104Syokota */ 300348104Syokotastatic int 300448104Syokotavga_diag(video_adapter_t *adp, int level) 300548104Syokota{ 300648104Syokota u_char *mp; 300748104Syokota#if FB_DEBUG > 1 300848104Syokota video_info_t info; 300948104Syokota int i; 301048104Syokota#endif 301148104Syokota 301248104Syokota if (!vga_init_done) 301348104Syokota return ENXIO; 301448104Syokota 301548104Syokota#if FB_DEBUG > 1 301648104Syokota#ifndef VGA_NO_BIOS 301748104Syokota printf("vga: RTC equip. code:0x%02x, DCC code:0x%02x\n", 301848104Syokota rtcin(RTC_EQUIPMENT), readb(BIOS_PADDRTOVADDR(0x488))); 301948104Syokota printf("vga: CRTC:0x%x, video option:0x%02x, ", 302048104Syokota readw(BIOS_PADDRTOVADDR(0x463)), 302148104Syokota readb(BIOS_PADDRTOVADDR(0x487))); 302248104Syokota printf("rows:%d, cols:%d, font height:%d\n", 302348104Syokota readb(BIOS_PADDRTOVADDR(0x44a)), 302448104Syokota readb(BIOS_PADDRTOVADDR(0x484)) + 1, 302548104Syokota readb(BIOS_PADDRTOVADDR(0x485))); 302648104Syokota#endif /* VGA_NO_BIOS */ 302748104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 302848104Syokota printf("vga: param table EGA/VGA:%p", video_mode_ptr); 302948104Syokota printf(", CGA/MDA:%p\n", video_mode_ptr2); 303048104Syokota printf("vga: rows_offset:%d\n", rows_offset); 303148104Syokota#endif 303248104Syokota#endif /* FB_DEBUG > 1 */ 303348104Syokota 303448104Syokota fb_dump_adp_info(VGA_DRIVER_NAME, adp, level); 303548104Syokota 303648104Syokota#if FB_DEBUG > 1 303748104Syokota if (adp->va_flags & V_ADP_MODECHANGE) { 303848104Syokota for (i = 0; bios_vmode[i].vi_mode != EOT; ++i) { 303948104Syokota if (bios_vmode[i].vi_mode == NA) 304048104Syokota continue; 304148104Syokota if (get_mode_param(bios_vmode[i].vi_mode) == NULL) 304248104Syokota continue; 304348104Syokota fb_dump_mode_info(VGA_DRIVER_NAME, adp, &bios_vmode[i], level); 304448104Syokota } 304548104Syokota } else { 304648104Syokota vga_get_info(adp, adp->va_initial_mode, &info); /* shouldn't fail */ 304748104Syokota fb_dump_mode_info(VGA_DRIVER_NAME, adp, &info, level); 304848104Syokota } 304948104Syokota#endif /* FB_DEBUG > 1 */ 305048104Syokota 305148104Syokota if ((adp->va_type != KD_EGA) && (adp->va_type != KD_VGA)) 305248104Syokota return 0; 305348104Syokota#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) 305448104Syokota if (video_mode_ptr == NULL) 305548104Syokota printf("vga%d: %s: WARNING: video mode switching is not " 305648104Syokota "fully supported on this adapter\n", 305748104Syokota adp->va_unit, adp->va_name); 305848104Syokota#endif 305948104Syokota if (level <= 0) 306048104Syokota return 0; 306148104Syokota 306248104Syokota if (adp->va_type == KD_VGA) { 306348104Syokota printf("VGA parameters upon power-up\n"); 306448104Syokota dump_buffer(adpstate.regs, sizeof(adpstate.regs)); 306548104Syokota printf("VGA parameters in BIOS for mode %d\n", adp->va_initial_mode); 306648104Syokota dump_buffer(adpstate2.regs, sizeof(adpstate2.regs)); 306748104Syokota } 306848104Syokota 306948104Syokota mp = get_mode_param(adp->va_initial_mode); 307048104Syokota if (mp == NULL) /* this shouldn't be happening */ 307148104Syokota return 0; 307248104Syokota printf("EGA/VGA parameters to be used for mode %d\n", adp->va_initial_mode); 307348104Syokota dump_buffer(mp, V_MODE_PARAM_SIZE); 307448104Syokota 307548104Syokota return 0; 307648104Syokota} 3077