vga_isa.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 2,236 行 · 第 1/4 页
C
2,236 行
/*- * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> * Copyright (c) 1992-1998 S鴕en Schmidt * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer as * the first lines of this file unmodified. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $Id: vga_isa.c,v 1.1.2.2 1999/03/15 00:20:56 yokota Exp $ */#include "vga.h"#include "opt_vga.h"#include "opt_fb.h"#include "opt_syscons.h" /* should be removed in the future, XXX */#if NVGA > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/bus.h>#include <sys/malloc.h>#include <vm/vm.h>#include <vm/pmap.h>#include <machine/console.h>#include <machine/md_var.h>#include <machine/pc/bios.h>#include <dev/fb/fbreg.h>#include <dev/fb/vgareg.h>#ifndef __i386__#include <isa/isareg.h>#include <isa/isavar.h>#else#include <i386/isa/isa.h>#include <i386/isa/isa_device.h>#endif#define DRIVER_NAME "vga"/* cdev driver declaration */#define ISAVGA_UNIT(dev) minor(dev)#define ISAVGA_MKMINOR(unit) (unit)typedef struct isavga_softc { video_adapter_t *adp;} isavga_softc_t;#ifndef __i386__#define ISAVGA_SOFTC(unit) \ ((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit))devclass_t isavga_devclass;static int isavga_probe(device_t dev);static int isavga_attach(device_t dev);static device_method_t isavga_methods[] = { DEVMETHOD(device_probe, isavga_probe), DEVMETHOD(device_attach, isavga_attach), { 0, 0 }};static driver_t isavga_driver = { DRIVER_NAME, isavga_methods, DRIVER_TYPE_TTY, sizeof(isavga_softc_t),};#else /* __i386__ */#define ISAVGA_SOFTC(unit) (isavga_softc[unit])static isavga_softc_t *isavga_softc[NVGA];static int isavga_probe(struct isa_device *dev);static int isavga_attach(struct isa_device *dev);struct isa_driver vgadriver = { isavga_probe, isavga_attach, DRIVER_NAME, 0,};#endif /* __i386__ */static int isavga_probe_unit(int unit, isavga_softc_t *sc, int flags);static int isavga_attach_unit(int unit, isavga_softc_t *sc, int flags);#ifdef FB_INSTALL_CDEVstatic d_open_t isavgaopen;static d_close_t isavgaclose;static d_read_t isavgaread;static d_ioctl_t isavgaioctl;static struct cdevsw vga_cdevsw = { isavgaopen, isavgaclose, noread, nowrite, /* ?? */ isavgaioctl, nostop, nullreset, nodevtotty, seltrue, nommap, NULL, DRIVER_NAME, NULL, -1, nodump, nopsize,};#endif /* FB_INSTALL_CDEV */#ifndef __i386__static intisavga_probe(device_t dev){ isavga_softc_t *sc; sc = device_get_softc(dev); return isavga_probe_unit(device_get_unit(dev), sc, isa_get_flags(dev));}static intisavga_attach(device_t dev){ isavga_softc_t *sc; sc = device_get_softc(dev); return isavga_attach_unit(device_get_unit(dev), sc, isa_get_flags(dev));}#else /* __i386__ */static intisavga_probe(struct isa_device *dev){ isavga_softc_t *sc; int error; if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) return 0; sc = isavga_softc[dev->id_unit] = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); if (sc == NULL) return 0; error = isavga_probe_unit(dev->id_unit, sc, dev->id_flags); if (error) { isavga_softc[dev->id_unit] = NULL; free(sc, M_DEVBUF); return 0; } dev->id_iobase = sc->adp->va_io_base; dev->id_maddr = (caddr_t)BIOS_PADDRTOVADDR(sc->adp->va_mem_base); dev->id_msize = sc->adp->va_mem_size; return sc->adp->va_io_size;}static intisavga_attach(struct isa_device *dev){ isavga_softc_t *sc; if (dev->id_unit >= sizeof(isavga_softc)/sizeof(isavga_softc[0])) return 0; sc = isavga_softc[dev->id_unit]; if (sc == NULL) return 0; return ((isavga_attach_unit(dev->id_unit, sc, dev->id_flags)) ? 0 : 1);}#endif /* __i386__ */static intisavga_probe_unit(int unit, isavga_softc_t *sc, int flags){ video_switch_t *sw; bzero(sc, sizeof(*sc)); sw = vid_get_switch(DRIVER_NAME); if (sw == NULL) return 0; return (*sw->probe)(unit, &sc->adp, NULL, flags);}static intisavga_attach_unit(int unit, isavga_softc_t *sc, int flags){ video_switch_t *sw; int error; sw = vid_get_switch(DRIVER_NAME); if (sw == NULL) return ENXIO; error = (*sw->init)(unit, sc->adp, flags); if (error) return ENXIO;#ifdef FB_INSTALL_CDEV /* attach a virtual frame buffer device */ error = fb_attach(makedev(0, ISAVGA_MKMINOR(unit)), scp->adp, &vga_cdevsw); if (error) return error;#endif /* FB_INSTALL_CDEV */ if (bootverbose) (*vidsw[sc->adp->va_index]->diag)(sc->adp, bootverbose); return 0;}/* LOW-LEVEL */#include <machine/clock.h>#include <machine/pc/vesa.h>#define probe_done(adp) ((adp)->va_flags & V_ADP_PROBED)#define init_done(adp) ((adp)->va_flags & V_ADP_INITIALIZED)#define config_done(adp) ((adp)->va_flags & V_ADP_REGISTERED)/* for compatibility with old kernel options */#ifdef SC_ALT_SEQACCESS#undef SC_ALT_SEQACCESS#undef VGA_ALT_SEQACCESS#define VGA_ALT_SEQACCESS 1#endif#ifdef SLOW_VGA#undef SLOW_VGA#undef VGA_SLOW_IOACCESS#define VGA_SLOW_IOACCESS 1#endif/* architecture dependent option */#ifdef __alpha__#define VGA_NO_BIOS 1#endif/* this should really be in `rtc.h' */#define RTC_EQUIPMENT 0x14/* various sizes */#define V_MODE_MAP_SIZE (M_VGA_CG320 + 1)#define V_MODE_PARAM_SIZE 64/* video adapter state buffer */struct adp_state { int sig;#define V_STATE_SIG 0x736f6962 u_char regs[V_MODE_PARAM_SIZE];};typedef struct adp_state adp_state_t;/* video adapter information */#define DCC_MONO 0#define DCC_CGA40 1#define DCC_CGA80 2#define DCC_EGAMONO 3#define DCC_EGA40 4#define DCC_EGA80 5/* * NOTE: `va_window' should have a virtual address, but is initialized * with a physical address in the following table, as verify_adapter() * will perform address conversion at run-time. */static video_adapter_t adapter_init_value[] = { /* DCC_MONO */ { 0, KD_MONO, "mda", 0, 0, 0, IO_MDA, IO_MDASIZE, MONO_CRTC, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, 0, 7, 0, }, /* DCC_CGA40 */ { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, 0, 3, 0, }, /* DCC_CGA80 */ { 0, KD_CGA, "cga", 0, 0, V_ADP_COLOR, IO_CGA, IO_CGASIZE, COLOR_CRTC, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, 0, 3, 0, }, /* DCC_EGAMONO */ { 0, KD_EGA, "ega", 0, 0, 0, IO_MDA, 48, MONO_CRTC, EGA_BUF_BASE, EGA_BUF_SIZE, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0, 0, 7, 0, }, /* DCC_EGA40 */ { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, 0, 3, 0, }, /* DCC_EGA80 */ { 0, KD_EGA, "ega", 0, 0, V_ADP_COLOR, IO_MDA, 48, COLOR_CRTC, EGA_BUF_BASE, EGA_BUF_SIZE, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0, 0, 3, 0, },};static video_adapter_t biosadapter[2];static int biosadapters = 0;/* video driver declarations */static int vga_configure(int flags); int (*vga_sub_configure)(int flags);static int vga_nop(void);static vi_probe_t vga_probe;static vi_init_t vga_init;static vi_get_info_t vga_get_info;static vi_query_mode_t vga_query_mode;static vi_set_mode_t vga_set_mode;static vi_save_font_t vga_save_font;static vi_load_font_t vga_load_font;static vi_show_font_t vga_show_font;static vi_save_palette_t vga_save_palette;static vi_load_palette_t vga_load_palette;static vi_set_border_t vga_set_border;static vi_save_state_t vga_save_state;static vi_load_state_t vga_load_state;static vi_set_win_org_t vga_set_origin;static vi_read_hw_cursor_t vga_read_hw_cursor;static vi_set_hw_cursor_t vga_set_hw_cursor;static vi_set_hw_cursor_shape_t vga_set_hw_cursor_shape;static vi_mmap_t vga_mmap;static vi_diag_t vga_diag;static video_switch_t vgavidsw = { vga_probe, vga_init, vga_get_info, vga_query_mode, vga_set_mode, vga_save_font, vga_load_font, vga_show_font, vga_save_palette, vga_load_palette, vga_set_border, vga_save_state, vga_load_state, vga_set_origin, vga_read_hw_cursor, vga_set_hw_cursor, vga_set_hw_cursor_shape, (vi_blank_display_t *)vga_nop, vga_mmap, vga_diag,};VIDEO_DRIVER(mda, vgavidsw, NULL);VIDEO_DRIVER(cga, vgavidsw, NULL);VIDEO_DRIVER(ega, vgavidsw, NULL);VIDEO_DRIVER(vga, vgavidsw, vga_configure);/* VGA BIOS standard video modes */#define EOT (-1)#define NA (-2)static video_info_t bios_vmode[] = { /* CGA */ { M_B40x25, V_INFO_COLOR, 40, 25, 8, 8, 2, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_C40x25, V_INFO_COLOR, 40, 25, 8, 8, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_B80x25, V_INFO_COLOR, 80, 25, 8, 8, 2, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_C80x25, V_INFO_COLOR, 80, 25, 8, 8, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, /* EGA */ { M_ENH_B40x25, V_INFO_COLOR, 40, 25, 8, 14, 2, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_ENH_C40x25, V_INFO_COLOR, 40, 25, 8, 14, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_ENH_B80x25, V_INFO_COLOR, 80, 25, 8, 14, 2, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_ENH_C80x25, V_INFO_COLOR, 80, 25, 8, 14, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, /* VGA */ { M_VGA_C40x25, V_INFO_COLOR, 40, 25, 8, 16, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_VGA_M80x25, 0, 80, 25, 8, 16, 2, 1, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, { M_VGA_C80x25, V_INFO_COLOR, 80, 25, 8, 16, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, /* MDA */ { M_EGAMONO80x25, 0, 80, 25, 8, 14, 2, 1, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, /* EGA */ { M_ENH_B80x43, V_INFO_COLOR, 80, 43, 8, 8, 2, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_ENH_C80x43, V_INFO_COLOR, 80, 43, 8, 8, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, /* VGA */ { M_VGA_M80x30, 0, 80, 30, 8, 16, 2, 1, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, { M_VGA_C80x30, V_INFO_COLOR, 80, 30, 8, 16, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_VGA_M80x50, 0, 80, 50, 8, 8, 2, 1, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, { M_VGA_C80x50, V_INFO_COLOR, 80, 50, 8, 8, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_VGA_M80x60, 0, 80, 60, 8, 8, 2, 1, MDA_BUF_BASE, MDA_BUF_SIZE, MDA_BUF_SIZE, 0, 0 }, { M_VGA_C80x60, V_INFO_COLOR, 80, 60, 8, 8, 4, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 },#ifndef VGA_NO_MODE_CHANGE /* CGA */ { M_BG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 2, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, { M_BG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 1, 1, CGA_BUF_BASE, CGA_BUF_SIZE, CGA_BUF_SIZE, 0, 0 }, /* EGA */ { M_CG320_D, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 4, 4, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, { M_CG640_E, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 200, 8, 8, 4, 4, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, { M_EGAMONOAPA, V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, 64*1024, 0, 0 }, { M_ENHMONOAPA2,V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, { M_CG640x350, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 2, 2, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, { M_ENH_CG640, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 350, 8, 14, 4, 4, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, /* VGA */ { M_BG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, { M_CG640x480, V_INFO_COLOR | V_INFO_GRAPHICS, 640, 480, 8, 16, 4, 4, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, { M_VGA_CG320, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 200, 8, 8, 8, 1, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 }, { M_VGA_MODEX, V_INFO_COLOR | V_INFO_GRAPHICS, 320, 240, 8, 8, 8, 1, GRAPHICS_BUF_BASE, GRAPHICS_BUF_SIZE, GRAPHICS_BUF_SIZE, 0, 0 },#endif /* VGA_NO_MODE_CHANGE */ { EOT },};static int init_done = FALSE;static u_char *video_mode_ptr = NULL; /* EGA/VGA */static u_char *video_mode_ptr2 = NULL; /* CGA/MDA */static u_char *mode_map[V_MODE_MAP_SIZE];static adp_state_t adpstate;static adp_state_t adpstate2;static int rows_offset = 1;/* local macros and functions */#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)static void map_mode_table(u_char *map[], u_char *table, int max);#endifstatic void clear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color);#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)static int map_mode_num(int mode);#endifstatic int map_gen_mode_num(int type, int color, int mode);static int map_bios_mode_num(int type, int color, int bios_mode);static u_char *get_mode_param(int mode);#ifndef VGA_NO_BIOSstatic void fill_adapter_param(int code, video_adapter_t *adp);#endifstatic int verify_adapter(video_adapter_t *adp);static void update_adapter_info(video_adapter_t *adp, video_info_t *info);#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)#define COMP_IDENTICAL 0#define COMP_SIMILAR 1#define COMP_DIFFERENT 2static int comp_adpregs(u_char *buf1, u_char *buf2);#endifstatic int probe_adapters(void);#define PARAM_BUFSIZE 6static void set_font_mode(video_adapter_t *adp, u_char *buf);static void set_normal_mode(video_adapter_t *adp, u_char *buf);static void dump_buffer(u_char *buf, size_t len);#define ISMAPPED(pa, width) \ (((pa) <= (u_long)0x1000 - (width)) \ || ((pa) >= ISA_HOLE_START && (pa) <= 0x100000 - (width)))#define prologue(adp, flag, err) \ if (!init_done || !((adp)->va_flags & (flag))) \ return (err)/* a backdoor for the console driver */static intvga_configure(int flags){ int i; probe_adapters(); for (i = 0; i < biosadapters; ++i) { if (!probe_done(&biosadapter[i])) continue; biosadapter[i].va_flags |= V_ADP_INITIALIZED; if (!config_done(&biosadapter[i])) { if (vid_register(&biosadapter[i]) < 0) continue; biosadapter[i].va_flags |= V_ADP_REGISTERED; } } if (vga_sub_configure != NULL) (*vga_sub_configure)(flags); return biosadapters;}/* local subroutines */#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE)/* construct the mode parameter map */static voidmap_mode_table(u_char *map[], u_char *table, int max){ int i; for(i = 0; i < max; ++i) map[i] = table + i*V_MODE_PARAM_SIZE; for(; i < V_MODE_MAP_SIZE; ++i) map[i] = NULL;}#endif /* !VGA_NO_BIOS && !VGA_NO_MODE_CHANGE */static voidclear_mode_map(video_adapter_t *adp, u_char *map[], int max, int color){ video_info_t info; int i; /* * NOTE: we don't touch `bios_vmode[]' because it is shared
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?