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