📄 vgaemu.c
字号:
/* $Id: vgaemu.c,v 1.2 2003/05/21 10:17:24 pefo Exp $ *//* * Copyright (c) 2002 Opsycon AB (www.opsycon.se) * * 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. * 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Opsycon AB. * 4. 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 AUTHOR ``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 AUTHOR 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. * */#include "biosemui.h"#include <string.h>#include <stdlib.h>#include <stdarg.h>#include <termio.h>#include <dev/pci/pcireg.h>#include <dev/pci/pcivar.h>#include <pmon.h>void vga_bios_init (void);void vga_putc(char c);void vga_puts(char *s);void vga_setmode(char mode);void vga_doint10(int ax, int bx);BE_sysEnv _BE_env;static X86EMU_memFuncs _BE_mem = { BE_rdb, BE_rdw, BE_rdl, BE_wrb, BE_wrw, BE_wrl,};static X86EMU_pioFuncs _BE_pio = { BE_inb, BE_inw, BE_inl, BE_outb, BE_outw, BE_outl,};static int vga_done = 0;#define OFF(addr) (((addr) >> 0) & 0xffff)#define SEG(addr) (((addr) >> 4) & 0xf000)#define MEM_SIZE (64*1024) /* should be plenty for now */static voidvga_sys_init (void *rom_addr, u32 rom_size, void *busmem_addr, u32 busmem_size){ extern int memorysize; memset(&M, 0, sizeof(M)); /* grab some memory from the top of memory */ memorysize = (memorysize - (5*MEM_SIZE)) & ~3; /* Setup the RAM buffer access */ M.mem_base = (memorysize & 0x3fffffff) + (CLIENTPC & 0xc0000000); M.mem_size = MEM_SIZE; memset((void *)M.mem_base, 0, MEM_SIZE); /* Shadow the VGA ROM to memory */ _BE_env.biosmem_base = M.mem_base + MEM_SIZE; memcpy((void *)_BE_env.biosmem_base, rom_addr, rom_size); _BE_env.biosmem_limit = _BE_env.biosmem_base + 4*MEM_SIZE - 1; /* Fill all entrys with hlt (note area starts at 0xc0000) */ memset((char *)_BE_env.biosmem_base + 0x30000, 0xf4, 0x10000); /* set bios date */ strcpy((char *)_BE_env.biosmem_base + 0x3fff5, "06/01/99"); /* set up eisa ident string */ strcpy((char *)_BE_env.biosmem_base + 0x3ffd9, "PCI/ISA"); /* write system model id for IBM-AT */ *((char *)_BE_env.biosmem_base + 0x3fffe) = 0xfc; /* Setup the video memory access */ _BE_env.busmem_base = (u32) busmem_addr; _BE_env.busmem_limit = _BE_env.busmem_base + busmem_size - 1; /* Initialize the System BIOS */ _BE_bios_init(); X86EMU_setupMemFuncs(&_BE_mem); X86EMU_setupPioFuncs(&_BE_pio);}voidvga_bios_init(){extern pcitag_t have_vga; pcireg_t rom_addr; pcireg_t rom_size; void *busmem_addr = (void *)0xc00a0000; int busmem_size = 0x20000; int bus = (have_vga >> 16) & 0xff; int dev_fn = (have_vga >> 8) & 0xff; if (vga_done || have_vga == 0) { return; } rom_addr = _pci_conf_read(have_vga, PCI_MAPREG_ROM); _pci_conf_write(have_vga, PCI_MAPREG_ROM, PCI_MAPREG_MEM_ADDR_MASK); rom_size = -_pci_conf_read(have_vga, PCI_MAPREG_ROM); _pci_conf_write(have_vga, PCI_MAPREG_ROM, rom_addr); rom_addr &= PCI_MAPREG_MEM_ADDR_MASK; rom_addr += 0xc0000000; vga_sys_init((void *)rom_addr, rom_size, busmem_addr, busmem_size); if (BE_rdw(0xc0000) != 0xaa55) { printf("vga: No VGA BIOS ROM found!\n"); return; } /* Setup the emulator to run the VGA BIOS */ M.x86.R_CS = SEG(0xc0003); M.x86.R_IP = OFF(0xc0003); /* Set the PCI bus, device and function numbers */ M.x86.R_AL = dev_fn; M.x86.R_AH = bus; /* Setup the emulator exit */ BE_wrb(0x8000, 0xf4); /* HALT opcode */ /* Setup the stack to point to the emulator exit */ M.x86.R_SS = SEG(M.mem_size - 4); M.x86.R_SP = OFF(M.mem_size - 4); BE_wrw(0xfffc, 0x8000); /* IP */ BE_wrw(0xfffe, 0x0000); /* CS */ X86EMU_exec(); vga_done = 1; return;}static intvga_bios_call (X86EMU_regs *inregs, X86EMU_regs *outregs){ if (!vga_done) { return 0; } /* Setup the stack */ M.x86.R_SS = SEG(M.mem_size - 4); M.x86.R_SP = OFF(M.mem_size - 4); /* Set the entry registers */ M.x86.R_AX = inregs->R_AX; M.x86.R_BX = inregs->R_BX; M.x86.R_CX = inregs->R_CX; M.x86.R_DX = inregs->R_DX; M.x86.R_SI = inregs->R_SI; M.x86.R_DI = inregs->R_DI; M.x86.R_DS = inregs->R_DS; M.x86.R_ES = inregs->R_ES; M.x86.R_FLG = inregs->R_FLG; /* Setup to run the VGA BIOS interrupt call */ M.x86.R_CS = SEG(0x8000); M.x86.R_IP = OFF(0x8000); BE_wrb(0x8000, 0xcd); /* INT 10 */ BE_wrb(0x8001, 0x10); /* Setup the emulator exit */ BE_wrb(0x8002, 0xf4); /* HALT opcode */ /* Run the emulator */ X86EMU_exec(); /* Set the return registers */ outregs->R_AX = M.x86.R_AX; outregs->R_BX = M.x86.R_BX; outregs->R_CX = M.x86.R_CX; outregs->R_DX = M.x86.R_DX; outregs->R_SI = M.x86.R_SI; outregs->R_DI = M.x86.R_DI; outregs->R_DS = M.x86.R_DS; outregs->R_ES = M.x86.R_ES; outregs->R_FLG = M.x86.R_FLG; return 1;}void vga_putc(char c){ X86EMU_regs regs; if (!vga_done || c == 7) { return; } regs.R_AH = 0x0E; /* Function number */ regs.R_AL = c; /* ASCII code */ regs.R_BH = 0; /* Page number */ regs.R_BL = 15; /* Color (graphics mode only */ vga_bios_call(®s, ®s);}void vga_puts(char *s){ if (!vga_done) { return; } while (*s != '\0') vga_putc(*s++); vga_putc('\r'); vga_putc('\n');}void vga_setmode(char mode){ X86EMU_regs regs; regs.R_AH = 0x0; /* Function number */ regs.R_AL = mode; /* Video Mode */ vga_bios_call(®s, ®s);}void vga_doint10(int ax, int bx){ X86EMU_regs regs; regs.R_AX = ax; regs.R_BX = bx; vga_bios_call(®s, ®s);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -