⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vga.c

📁 qemu虚拟机代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * QEMU VGA Emulator. *  * Copyright (c) 2003 Fabrice Bellard *  * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */#include "vl.h"#include "vga_int.h"//#define DEBUG_VGA//#define DEBUG_VGA_MEM//#define DEBUG_VGA_REG//#define DEBUG_BOCHS_VBE/* force some bits to zero */const uint8_t sr_mask[8] = {    (uint8_t)~0xfc,    (uint8_t)~0xc2,    (uint8_t)~0xf0,    (uint8_t)~0xc0,    (uint8_t)~0xf1,    (uint8_t)~0xff,    (uint8_t)~0xff,    (uint8_t)~0x00,};const uint8_t gr_mask[16] = {    (uint8_t)~0xf0, /* 0x00 */    (uint8_t)~0xf0, /* 0x01 */    (uint8_t)~0xf0, /* 0x02 */    (uint8_t)~0xe0, /* 0x03 */    (uint8_t)~0xfc, /* 0x04 */    (uint8_t)~0x84, /* 0x05 */    (uint8_t)~0xf0, /* 0x06 */    (uint8_t)~0xf0, /* 0x07 */    (uint8_t)~0x00, /* 0x08 */    (uint8_t)~0xff, /* 0x09 */    (uint8_t)~0xff, /* 0x0a */    (uint8_t)~0xff, /* 0x0b */    (uint8_t)~0xff, /* 0x0c */    (uint8_t)~0xff, /* 0x0d */    (uint8_t)~0xff, /* 0x0e */    (uint8_t)~0xff, /* 0x0f */};#define cbswap_32(__x) \((uint32_t)( \		(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \		(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \		(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \		(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))#ifdef WORDS_BIGENDIAN#define PAT(x) cbswap_32(x)#else#define PAT(x) (x)#endif#ifdef WORDS_BIGENDIAN#define BIG 1#else#define BIG 0#endif#ifdef WORDS_BIGENDIAN#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)#else#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)#endifstatic const uint32_t mask16[16] = {    PAT(0x00000000),    PAT(0x000000ff),    PAT(0x0000ff00),    PAT(0x0000ffff),    PAT(0x00ff0000),    PAT(0x00ff00ff),    PAT(0x00ffff00),    PAT(0x00ffffff),    PAT(0xff000000),    PAT(0xff0000ff),    PAT(0xff00ff00),    PAT(0xff00ffff),    PAT(0xffff0000),    PAT(0xffff00ff),    PAT(0xffffff00),    PAT(0xffffffff),};#undef PAT#ifdef WORDS_BIGENDIAN#define PAT(x) (x)#else#define PAT(x) cbswap_32(x)#endifstatic const uint32_t dmask16[16] = {    PAT(0x00000000),    PAT(0x000000ff),    PAT(0x0000ff00),    PAT(0x0000ffff),    PAT(0x00ff0000),    PAT(0x00ff00ff),    PAT(0x00ffff00),    PAT(0x00ffffff),    PAT(0xff000000),    PAT(0xff0000ff),    PAT(0xff00ff00),    PAT(0xff00ffff),    PAT(0xffff0000),    PAT(0xffff00ff),    PAT(0xffffff00),    PAT(0xffffffff),};static const uint32_t dmask4[4] = {    PAT(0x00000000),    PAT(0x0000ffff),    PAT(0xffff0000),    PAT(0xffffffff),};static uint32_t expand4[256];static uint16_t expand2[256];static uint8_t expand4to8[16];VGAState *vga_state;int vga_io_memory;static void vga_screen_dump(void *opaque, const char *filename);static uint32_t vga_ioport_read(void *opaque, uint32_t addr){    VGAState *s = opaque;    int val, index;    /* check port range access depending on color/monochrome mode */    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {        val = 0xff;    } else {        switch(addr) {        case 0x3c0:            if (s->ar_flip_flop == 0) {                val = s->ar_index;            } else {                val = 0;            }            break;        case 0x3c1:            index = s->ar_index & 0x1f;            if (index < 21)                 val = s->ar[index];            else                val = 0;            break;        case 0x3c2:            val = s->st00;            break;        case 0x3c4:            val = s->sr_index;            break;        case 0x3c5:            val = s->sr[s->sr_index];#ifdef DEBUG_VGA_REG            printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);#endif            break;        case 0x3c7:            val = s->dac_state;            break;	case 0x3c8:	    val = s->dac_write_index;	    break;        case 0x3c9:            val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];            if (++s->dac_sub_index == 3) {                s->dac_sub_index = 0;                s->dac_read_index++;            }            break;        case 0x3ca:            val = s->fcr;            break;        case 0x3cc:            val = s->msr;            break;        case 0x3ce:            val = s->gr_index;            break;        case 0x3cf:            val = s->gr[s->gr_index];#ifdef DEBUG_VGA_REG            printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);#endif            break;        case 0x3b4:        case 0x3d4:            val = s->cr_index;            break;        case 0x3b5:        case 0x3d5:            val = s->cr[s->cr_index];#ifdef DEBUG_VGA_REG            printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);#endif            break;        case 0x3ba:        case 0x3da:            /* just toggle to fool polling */            s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;            val = s->st01;            s->ar_flip_flop = 0;            break;        default:            val = 0x00;            break;        }    }#if defined(DEBUG_VGA)    printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);#endif    return val;}static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val){    VGAState *s = opaque;    int index;    /* check port range access depending on color/monochrome mode */    if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||        (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))        return;#ifdef DEBUG_VGA    printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);#endif    switch(addr) {    case 0x3c0:        if (s->ar_flip_flop == 0) {            val &= 0x3f;            s->ar_index = val;        } else {            index = s->ar_index & 0x1f;            switch(index) {            case 0x00 ... 0x0f:                s->ar[index] = val & 0x3f;                break;            case 0x10:                s->ar[index] = val & ~0x10;                break;            case 0x11:                s->ar[index] = val;                break;            case 0x12:                s->ar[index] = val & ~0xc0;                break;            case 0x13:                s->ar[index] = val & ~0xf0;                break;            case 0x14:                s->ar[index] = val & ~0xf0;                break;            default:                break;            }        }        s->ar_flip_flop ^= 1;        break;    case 0x3c2:        s->msr = val & ~0x10;        break;    case 0x3c4:        s->sr_index = val & 7;        break;    case 0x3c5:#ifdef DEBUG_VGA_REG        printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);#endif        s->sr[s->sr_index] = val & sr_mask[s->sr_index];        break;    case 0x3c7:        s->dac_read_index = val;        s->dac_sub_index = 0;        s->dac_state = 3;        break;    case 0x3c8:        s->dac_write_index = val;        s->dac_sub_index = 0;        s->dac_state = 0;        break;    case 0x3c9:        s->dac_cache[s->dac_sub_index] = val;        if (++s->dac_sub_index == 3) {            memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);            s->dac_sub_index = 0;            s->dac_write_index++;        }        break;    case 0x3ce:        s->gr_index = val & 0x0f;        break;    case 0x3cf:#ifdef DEBUG_VGA_REG        printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);#endif        s->gr[s->gr_index] = val & gr_mask[s->gr_index];        break;    case 0x3b4:    case 0x3d4:        s->cr_index = val;        break;    case 0x3b5:    case 0x3d5:#ifdef DEBUG_VGA_REG        printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);#endif        /* handle CR0-7 protection */        if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {            /* can always write bit 4 of CR7 */            if (s->cr_index == 7)                s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);            return;        }        switch(s->cr_index) {        case 0x01: /* horizontal display end */        case 0x07:        case 0x09:        case 0x0c:        case 0x0d:        case 0x12: /* veritcal display end */            s->cr[s->cr_index] = val;            break;        default:            s->cr[s->cr_index] = val;            break;        }        break;    case 0x3ba:    case 0x3da:        s->fcr = val & 0x10;        break;    }}#ifdef CONFIG_BOCHS_VBEstatic uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr){    VGAState *s = opaque;    uint32_t val;    val = s->vbe_index;    return val;}static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr){    VGAState *s = opaque;    uint32_t val;    if (s->vbe_index <= VBE_DISPI_INDEX_NB)        val = s->vbe_regs[s->vbe_index];    else        val = 0;#ifdef DEBUG_BOCHS_VBE    printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);#endif    return val;}static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val){    VGAState *s = opaque;    s->vbe_index = val;}static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val){    VGAState *s = opaque;    if (s->vbe_index <= VBE_DISPI_INDEX_NB) {#ifdef DEBUG_BOCHS_VBE        printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);#endif        switch(s->vbe_index) {        case VBE_DISPI_INDEX_ID:            if (val == VBE_DISPI_ID0 ||                val == VBE_DISPI_ID1 ||                val == VBE_DISPI_ID2) {                s->vbe_regs[s->vbe_index] = val;            }            break;        case VBE_DISPI_INDEX_XRES:            if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {                s->vbe_regs[s->vbe_index] = val;            }            break;        case VBE_DISPI_INDEX_YRES:            if (val <= VBE_DISPI_MAX_YRES) {                s->vbe_regs[s->vbe_index] = val;            }            break;        case VBE_DISPI_INDEX_BPP:            if (val == 0)                val = 8;            if (val == 4 || val == 8 || val == 15 ||                 val == 16 || val == 24 || val == 32) {                s->vbe_regs[s->vbe_index] = val;            }            break;        case VBE_DISPI_INDEX_BANK:            val &= s->vbe_bank_mask;            s->vbe_regs[s->vbe_index] = val;            s->bank_offset = (val << 16);            break;        case VBE_DISPI_INDEX_ENABLE:            if (val & VBE_DISPI_ENABLED) {                int h, shift_control;                s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =                     s->vbe_regs[VBE_DISPI_INDEX_XRES];                s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =                     s->vbe_regs[VBE_DISPI_INDEX_YRES];                s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;                s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;                                if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;                else                    s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *                         ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);                s->vbe_start_addr = 0;                                /* clear the screen (should be done in BIOS) */                if (!(val & VBE_DISPI_NOCLEARMEM)) {                    memset(s->vram_ptr, 0,                            s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);                }                                /* we initialize the VGA graphic mode (should be done                   in BIOS) */                s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */                s->cr[0x17] |= 3; /* no CGA modes */                s->cr[0x13] = s->vbe_line_offset >> 3;                /* width */                s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;                /* height */                h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;                s->cr[0x12] = h;                s->cr[0x07] = (s->cr[0x07] & ~0x42) |                     ((h >> 7) & 0x02) | ((h >> 3) & 0x40);                /* line compare to 1023 */

⌨️ 快捷键说明

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