vesa.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,166 行 · 第 1/2 页

C
1,166
字号
/*- * Copyright (c) 1998 Kazutaka YOKOTA and Michael Smith * 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. * * 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: vesa.c,v 1.15.2.5 1999/04/16 15:58:21 jlemon Exp $ */#include "vga.h"#include "opt_vga.h"#include "opt_vesa.h"#include "opt_vm86.h"#include "opt_fb.h"#ifdef VGA_NO_MODE_CHANGE#undef VESA#endif#if (NVGA > 0 && defined(VESA) && defined(VM86)) || defined(KLD_MODULE)#include <sys/param.h>#include <sys/systm.h>#include <sys/kernel.h>#include <sys/module.h>#include <sys/malloc.h>#include <vm/vm.h>#include <vm/pmap.h>#include <machine/console.h>#include <machine/md_var.h>#include <machine/vm86.h>#include <machine/pc/bios.h>#include <machine/pc/vesa.h>#include <dev/fb/fbreg.h>#include <dev/fb/vgareg.h>#ifndef __i386__#include <isa/isareg.h>#else#include <i386/isa/isa.h>#endif#ifndef VESA_DEBUG#define VESA_DEBUG	0#endif/* VESA video adapter state buffer stub */struct adp_state {	int		sig;#define V_STATE_SIG	0x61736576	u_char		regs[1];};typedef struct adp_state adp_state_t;/* VESA video adapter */static video_adapter_t *vesa_adp = NULL;static int vesa_state_buf_size = 0;#if 0static void *vesa_state_buf = NULL;#endif/* VESA functions */static int			vesa_nop(void);static vi_probe_t		vesa_probe;static vi_init_t		vesa_init;static vi_get_info_t		vesa_get_info;static vi_query_mode_t		vesa_query_mode;static vi_set_mode_t		vesa_set_mode;static vi_save_font_t		vesa_save_font;static vi_load_font_t		vesa_load_font;static vi_show_font_t		vesa_show_font;static vi_save_palette_t	vesa_save_palette;static vi_load_palette_t	vesa_load_palette;static vi_set_border_t		vesa_set_border;static vi_save_state_t		vesa_save_state;static vi_load_state_t		vesa_load_state;static vi_set_win_org_t		vesa_set_origin;static vi_read_hw_cursor_t	vesa_read_hw_cursor;static vi_set_hw_cursor_t	vesa_set_hw_cursor;static vi_set_hw_cursor_shape_t	vesa_set_hw_cursor_shape;static vi_mmap_t		vesa_mmap;static vi_diag_t		vesa_diag;static struct vm86context	vesa_vmcontext;static video_switch_t vesavidsw = {	vesa_probe,	vesa_init,	vesa_get_info,	vesa_query_mode,	vesa_set_mode,	vesa_save_font,	vesa_load_font,	vesa_show_font,	vesa_save_palette,	vesa_load_palette,	vesa_set_border,	vesa_save_state,	vesa_load_state,	vesa_set_origin,	vesa_read_hw_cursor,	vesa_set_hw_cursor,	vesa_set_hw_cursor_shape,	(vi_blank_display_t *)vesa_nop,	vesa_mmap,	vesa_diag,};static video_switch_t *prevvidsw;/* VESA BIOS video modes */#define VESA_MAXMODES	64#define EOT		(-1)#define NA		(-2)static video_info_t vesa_vmode[VESA_MAXMODES + 1] = {	{ EOT, },};static int vesa_init_done = FALSE;static int has_vesa_bios = FALSE;static struct vesa_info *vesa_adp_info = NULL;static u_int16_t *vesa_vmodetab = NULL;static char *vesa_oemstr = NULL;static char *vesa_venderstr = NULL;static char *vesa_prodstr = NULL;static char *vesa_revstr = NULL;/* local macros and functions */#define BIOS_SADDRTOLADDR(p) ((((p) & 0xffff0000) >> 12) + ((p) & 0x0000ffff))static int int10_set_mode(int mode);static int vesa_bios_get_mode(int mode, struct vesa_mode *vmode);static int vesa_bios_set_mode(int mode);static int vesa_bios_get_dac(void);static int vesa_bios_set_dac(int bits);static int vesa_bios_save_palette(int start, int colors, u_char *palette,				  int bits);static int vesa_bios_load_palette(int start, int colors, u_char *palette,				  int bits);#define STATE_SIZE	0#define STATE_SAVE	1#define STATE_LOAD	2#define STATE_HW	(1<<0)#define STATE_DATA	(1<<1)#define STATE_DAC	(1<<2)#define STATE_REG	(1<<3)#define STATE_MOST	(STATE_HW | STATE_DATA | STATE_REG)#define STATE_ALL	(STATE_HW | STATE_DATA | STATE_DAC | STATE_REG)static int vesa_bios_state_buf_size(void);static int vesa_bios_save_restore(int code, void *p, size_t size);static int vesa_bios_get_line_length(void);static int vesa_map_gen_mode_num(int type, int color, int mode);static int vesa_translate_flags(u_int16_t vflags);static void *vesa_fix_ptr(u_int32_t p, u_int16_t seg, u_int16_t off, 			  u_char *buf);static int vesa_bios_init(void);static void vesa_clear_modes(video_info_t *info, int color);static voiddump_buffer(u_char *buf, size_t len){    int i;    for(i = 0; i < len;) {	printf("%02x ", buf[i]);	if ((++i % 16) == 0)	    printf("\n");    }}/* INT 10 BIOS calls */static intint10_set_mode(int mode){	struct vm86frame vmf;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x0000 | mode;	vm86_intcall(0x10, &vmf);	return 0;}/* VESA BIOS calls */static intvesa_bios_get_mode(int mode, struct vesa_mode *vmode){	struct vm86frame vmf;	u_char *buf;	int err;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f01; 	vmf.vmf_ecx = mode;	buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);	vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_di);	err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);	if ((err != 0) || (vmf.vmf_eax != 0x4f))		return 1;	bcopy(buf, vmode, sizeof(*vmode));	return 0;}static intvesa_bios_set_mode(int mode){	struct vm86frame vmf;	int err;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f02;	vmf.vmf_ebx = mode;	err = vm86_intcall(0x10, &vmf);	return ((err != 0) || (vmf.vmf_eax != 0x4f));}static intvesa_bios_get_dac(void){	struct vm86frame vmf;	int err;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f08;	vmf.vmf_ebx = 1;	/* get DAC width */	err = vm86_intcall(0x10, &vmf);	if ((err != 0) || (vmf.vmf_eax != 0x4f))		return 6;	/* XXX */	return ((vmf.vmf_ebx >> 8) & 0x00ff);}static intvesa_bios_set_dac(int bits){	struct vm86frame vmf;	int err;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f08;	vmf.vmf_ebx = (bits << 8);	err = vm86_intcall(0x10, &vmf);	if ((err != 0) || (vmf.vmf_eax != 0x4f))		return 6;	/* XXX */	return ((vmf.vmf_ebx >> 8) & 0x00ff);}static intvesa_bios_save_palette(int start, int colors, u_char *palette, int bits){	struct vm86frame vmf;	u_char *p;	int err;	int i;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f09;	vmf.vmf_ebx = 1;	/* get primary palette data */	vmf.vmf_ecx = colors;	vmf.vmf_edx = start;	p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);	vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);	err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);	if ((err != 0) || (vmf.vmf_eax != 0x4f))		return 1;	bits = 8 - bits;	for (i = 0; i < colors; ++i) {		palette[i*3]     = p[i*4 + 2] << bits;		palette[i*3 + 1] = p[i*4 + 1] << bits;		palette[i*3 + 2] = p[i*4] << bits;	}	return 0;}static intvesa_bios_load_palette(int start, int colors, u_char *palette, int bits){	struct vm86frame vmf;	u_char *p;	int err;	int i;	p = (u_char *)vm86_getpage(&vesa_vmcontext, 1);	bits = 8 - bits;	for (i = 0; i < colors; ++i) {		p[i*4]	   = palette[i*3 + 2] >> bits;		p[i*4 + 1] = palette[i*3 + 1] >> bits;		p[i*4 + 2] = palette[i*3] >> bits;		p[i*4 + 3] = 0;	}	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f09;	vmf.vmf_ebx = 0;	/* set primary palette data */	vmf.vmf_ecx = colors;	vmf.vmf_edx = start;	vm86_getptr(&vesa_vmcontext, (vm_offset_t)p, &vmf.vmf_es, &vmf.vmf_di);	err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);	return ((err != 0) || (vmf.vmf_eax != 0x4f));}static intvesa_bios_state_buf_size(void){	struct vm86frame vmf;	int err;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f04; 	vmf.vmf_ecx = STATE_MOST;	vmf.vmf_edx = STATE_SIZE;	err = vm86_intcall(0x10, &vmf);	if ((err != 0) || (vmf.vmf_eax != 0x4f))		return 0;	return vmf.vmf_ebx*64;}static intvesa_bios_save_restore(int code, void *p, size_t size){	struct vm86frame vmf;	u_char *buf;	int err;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f04; 	vmf.vmf_ecx = STATE_MOST;	vmf.vmf_edx = code;	/* STATE_SAVE/STATE_LOAD */	buf = (u_char *)vm86_getpage(&vesa_vmcontext, 1);	vm86_getptr(&vesa_vmcontext, (vm_offset_t)buf, &vmf.vmf_es, &vmf.vmf_di);	bcopy(p, buf, size);	err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);	return ((err != 0) || (vmf.vmf_eax != 0x4f));}static intvesa_bios_get_line_length(void){	struct vm86frame vmf;	int err;	bzero(&vmf, sizeof(vmf));	vmf.vmf_eax = 0x4f06; 	vmf.vmf_ebx = 1;	/* get scan line length */	err = vm86_intcall(0x10, &vmf);	if ((err != 0) || (vmf.vmf_eax != 0x4f))		return -1;	return vmf.vmf_bx;	/* line length in bytes */}/* map a generic video mode to a known mode */static intvesa_map_gen_mode_num(int type, int color, int mode){    static struct {	int from;	int to;    } mode_map[] = {	{ M_TEXT_132x25, M_VESA_C132x25 },	{ M_TEXT_132x43, M_VESA_C132x43 },	{ M_TEXT_132x50, M_VESA_C132x50 },	{ M_TEXT_132x60, M_VESA_C132x60 },    };    int i;    for (i = 0; i < sizeof(mode_map)/sizeof(mode_map[0]); ++i) {        if (mode_map[i].from == mode)            return mode_map[i].to;    }    return mode;}static intvesa_translate_flags(u_int16_t vflags){	static struct {		u_int16_t mask;		int set;		int reset;	} ftable[] = {		{ V_MODECOLOR, V_INFO_COLOR, 0 },		{ V_MODEGRAPHICS, V_INFO_GRAPHICS, 0 },		{ V_MODELFB, V_INFO_LINEAR, 0 },	};	int flags;	int i;	for (flags = 0, i = 0; i < sizeof(ftable)/sizeof(ftable[0]); ++i) {		flags |= (vflags & ftable[i].mask) ? 			 ftable[i].set : ftable[i].reset;	}	return flags;}static void*vesa_fix_ptr(u_int32_t p, u_int16_t seg, u_int16_t off, u_char *buf){	if (p == 0)		return NULL;	if (((p >> 16) == seg) && ((p & 0xffff) >= off))		return (void *)(buf + ((p & 0xffff) - off));	else {		p = BIOS_SADDRTOLADDR(p);		return (void *)BIOS_PADDRTOVADDR(p);	}}static intvesa_bios_init(void){	static u_char buf[512];	struct vm86frame vmf;	struct vesa_mode vmode;	u_char *vmbuf;	int modes;	int err;	int i;	if (vesa_init_done)		return 0;	has_vesa_bios = FALSE;	vesa_adp_info = NULL;	vesa_vmode[0].vi_mode = EOT;	vmbuf = (u_char *)vm86_addpage(&vesa_vmcontext, 1, 0);	bzero(&vmf, sizeof(vmf));	/* paranoia */	bcopy("VBE2", vmbuf, 4);	/* try for VBE2 data */	vmf.vmf_eax = 0x4f00;	vm86_getptr(&vesa_vmcontext, (vm_offset_t)vmbuf, &vmf.vmf_es, &vmf.vmf_di);	err = vm86_datacall(0x10, &vmf, &vesa_vmcontext);	if ((err != 0) || (vmf.vmf_eax != 0x4f) || bcmp("VESA", vmbuf, 4))		return 1;	bcopy(vmbuf, buf, sizeof(buf));	vesa_adp_info = (struct vesa_info *)buf;	if (bootverbose) {		printf("VESA: information block\n");		dump_buffer(buf, 64);	}	if (vesa_adp_info->v_flags & V_NONVGA)		return 1;	/* fix string ptrs */	vesa_oemstr = (char *)vesa_fix_ptr(vesa_adp_info->v_oemstr,					   vmf.vmf_es, vmf.vmf_di, buf);	if (vesa_adp_info->v_version >= 0x0200) {		vesa_venderstr = 		    (char *)vesa_fix_ptr(vesa_adp_info->v_venderstr,					 vmf.vmf_es, vmf.vmf_di, buf);		vesa_prodstr = 		    (char *)vesa_fix_ptr(vesa_adp_info->v_prodstr,					 vmf.vmf_es, vmf.vmf_di, buf);		vesa_revstr = 		    (char *)vesa_fix_ptr(vesa_adp_info->v_revstr,					 vmf.vmf_es, vmf.vmf_di, buf);	}	/* obtain video mode information */	vesa_vmode[0].vi_mode = EOT;	vesa_vmodetab = (u_int16_t *)vesa_fix_ptr(vesa_adp_info->v_modetable,						  vmf.vmf_es, vmf.vmf_di, buf);	if (vesa_vmodetab == NULL)		return 1;	for (i = 0, modes = 0; 		(i < (M_VESA_MODE_MAX - M_VESA_BASE + 1))		&& (vesa_vmodetab[i] != 0xffff); ++i) {		if (modes >= VESA_MAXMODES)			break;		if (vesa_bios_get_mode(vesa_vmodetab[i], &vmode))			continue;		/* reject unsupported modes */#if 0		if ((vmode.v_modeattr & (V_MODESUPP | V_MODEOPTINFO 					| V_MODENONVGA))		    != (V_MODESUPP | V_MODEOPTINFO))			continue;#else		if ((vmode.v_modeattr & (V_MODEOPTINFO | V_MODENONVGA))		    != (V_MODEOPTINFO))			continue;#endif		/* copy some fields */		bzero(&vesa_vmode[modes], sizeof(vesa_vmode[modes]));		vesa_vmode[modes].vi_mode = vesa_vmodetab[i];		vesa_vmode[modes].vi_width = vmode.v_width;		vesa_vmode[modes].vi_height = vmode.v_height;		vesa_vmode[modes].vi_depth = vmode.v_bpp;		vesa_vmode[modes].vi_planes = vmode.v_planes;		vesa_vmode[modes].vi_cwidth = vmode.v_cwidth;		vesa_vmode[modes].vi_cheight = vmode.v_cheight;		vesa_vmode[modes].vi_window = (u_int)vmode.v_waseg << 4;		/* XXX window B */		vesa_vmode[modes].vi_window_size = vmode.v_wsize*1024;		vesa_vmode[modes].vi_window_gran = vmode.v_wgran*1024;		vesa_vmode[modes].vi_buffer = vmode.v_lfb;		/* XXX */		if (vmode.v_offscreen > vmode.v_lfb)			vesa_vmode[modes].vi_buffer_size				= vmode.v_offscreen - vmode.v_lfb;		else			vesa_vmode[modes].vi_buffer_size = vmode.v_offscreen;		/* pixel format, memory model... */		vesa_vmode[modes].vi_flags 			= vesa_translate_flags(vmode.v_modeattr) | V_INFO_VESA;		++modes;	}	vesa_vmode[modes].vi_mode = EOT;	if (bootverbose)		printf("VESA: %d mode(s) found\n", modes);	has_vesa_bios = (modes > 0);	return (has_vesa_bios ? 0 : 1);}static voidvesa_clear_modes(video_info_t *info, int color){	while (info->vi_mode != EOT) {		if ((info->vi_flags & V_INFO_COLOR) != color)			info->vi_mode = NA;		++info;	}}/* entry points */static intvesa_configure(int flags){	video_adapter_t *adp;	int adapters;	int error;	int i;	if (vesa_init_done)		return 0;	if (flags & VIO_PROBE_ONLY)		return 0;		/* XXX */	/*	 * If the VESA module has already been loaded, abort loading 	 * the module this time.	 */	for (i = 0; (adp = vid_get_adapter(i)) != NULL; ++i) {		if (adp->va_flags & V_ADP_VESA)			return ENXIO;		if (adp->va_type == KD_VGA)			break;	}	/*	 * The VGA adapter is not found.  This is because either 	 * 1) the VGA driver has not been initialized, or 2) the VGA card	 * is not present.  If 1) is the case, we shall defer	 * initialization for now and try again later.	 */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?