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 + -
显示快捷键?