Commit cae61cef8976a819e590df66068f056e758c7429
1 parent
6411cfb6
bochs vbe: virtual screen support and bank switch (untested)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@605 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
67 additions
and
20 deletions
hw/vga.c
@@ -116,11 +116,13 @@ typedef struct VGAState { | @@ -116,11 +116,13 @@ typedef struct VGAState { | ||
116 | uint8_t dac_write_index; | 116 | uint8_t dac_write_index; |
117 | uint8_t dac_cache[3]; /* used when writing */ | 117 | uint8_t dac_cache[3]; /* used when writing */ |
118 | uint8_t palette[768]; | 118 | uint8_t palette[768]; |
119 | + uint32_t bank_offset; | ||
119 | #ifdef CONFIG_BOCHS_VBE | 120 | #ifdef CONFIG_BOCHS_VBE |
120 | uint16_t vbe_index; | 121 | uint16_t vbe_index; |
121 | uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; | 122 | uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; |
122 | uint32_t vbe_start_addr; | 123 | uint32_t vbe_start_addr; |
123 | uint32_t vbe_line_offset; | 124 | uint32_t vbe_line_offset; |
125 | + uint32_t vbe_bank_mask; | ||
124 | #endif | 126 | #endif |
125 | /* display refresh support */ | 127 | /* display refresh support */ |
126 | DisplayState *ds; | 128 | DisplayState *ds; |
@@ -537,28 +539,34 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | @@ -537,28 +539,34 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | ||
537 | #endif | 539 | #endif |
538 | switch(s->vbe_index) { | 540 | switch(s->vbe_index) { |
539 | case VBE_DISPI_INDEX_ID: | 541 | case VBE_DISPI_INDEX_ID: |
540 | - if (val != VBE_DISPI_ID0 && | ||
541 | - val != VBE_DISPI_ID1 && | ||
542 | - val != VBE_DISPI_ID2) | ||
543 | - return; | 542 | + if (val == VBE_DISPI_ID0 || |
543 | + val == VBE_DISPI_ID1 || | ||
544 | + val == VBE_DISPI_ID2) { | ||
545 | + s->vbe_regs[s->vbe_index] = val; | ||
546 | + } | ||
544 | break; | 547 | break; |
545 | case VBE_DISPI_INDEX_XRES: | 548 | case VBE_DISPI_INDEX_XRES: |
546 | - if ((val > VBE_DISPI_MAX_XRES) || ((val & 7) != 0)) | ||
547 | - return; | 549 | + if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) { |
550 | + s->vbe_regs[s->vbe_index] = val; | ||
551 | + } | ||
548 | break; | 552 | break; |
549 | case VBE_DISPI_INDEX_YRES: | 553 | case VBE_DISPI_INDEX_YRES: |
550 | - if (val > VBE_DISPI_MAX_YRES) | ||
551 | - return; | 554 | + if (val <= VBE_DISPI_MAX_YRES) { |
555 | + s->vbe_regs[s->vbe_index] = val; | ||
556 | + } | ||
552 | break; | 557 | break; |
553 | case VBE_DISPI_INDEX_BPP: | 558 | case VBE_DISPI_INDEX_BPP: |
554 | if (val == 0) | 559 | if (val == 0) |
555 | val = 8; | 560 | val = 8; |
556 | - if (val != 4 && val != 8 && val != 15 && | ||
557 | - val != 16 && val != 24 && val != 32) | ||
558 | - return; | 561 | + if (val == 4 || val == 8 || val == 15 || |
562 | + val == 16 || val == 24 || val == 32) { | ||
563 | + s->vbe_regs[s->vbe_index] = val; | ||
564 | + } | ||
559 | break; | 565 | break; |
560 | case VBE_DISPI_INDEX_BANK: | 566 | case VBE_DISPI_INDEX_BANK: |
561 | - val &= 0xff; | 567 | + val &= s->vbe_bank_mask; |
568 | + s->vbe_regs[s->vbe_index] = val; | ||
569 | + s->bank_offset = (val << 16) - 0xa0000; | ||
562 | break; | 570 | break; |
563 | case VBE_DISPI_INDEX_ENABLE: | 571 | case VBE_DISPI_INDEX_ENABLE: |
564 | if (val & VBE_DISPI_ENABLED) { | 572 | if (val & VBE_DISPI_ENABLED) { |
@@ -584,9 +592,9 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | @@ -584,9 +592,9 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | ||
584 | s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset); | 592 | s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset); |
585 | } | 593 | } |
586 | 594 | ||
587 | - /* we initialize graphic mode force graphic mode | ||
588 | - (should be done in BIOS) */ | ||
589 | - s->gr[6] |= 1; | 595 | + /* we initialize the VGA graphic mode (should be done |
596 | + in BIOS) */ | ||
597 | + s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */ | ||
590 | s->cr[0x17] |= 3; /* no CGA modes */ | 598 | s->cr[0x17] |= 3; /* no CGA modes */ |
591 | s->cr[0x13] = s->vbe_line_offset >> 3; | 599 | s->cr[0x13] = s->vbe_line_offset >> 3; |
592 | /* width */ | 600 | /* width */ |
@@ -609,12 +617,49 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | @@ -609,12 +617,49 @@ static void vbe_ioport_write(CPUState *env, uint32_t addr, uint32_t val) | ||
609 | } | 617 | } |
610 | s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5); | 618 | s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5); |
611 | s->cr[0x09] &= ~0x9f; /* no double scan */ | 619 | s->cr[0x09] &= ~0x9f; /* no double scan */ |
620 | + s->vbe_regs[s->vbe_index] = val; | ||
621 | + } else { | ||
622 | + /* XXX: the bios should do that */ | ||
623 | + s->bank_offset = -0xa0000; | ||
624 | + } | ||
625 | + break; | ||
626 | + case VBE_DISPI_INDEX_VIRT_WIDTH: | ||
627 | + { | ||
628 | + int w, h, line_offset; | ||
629 | + | ||
630 | + if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES]) | ||
631 | + return; | ||
632 | + w = val; | ||
633 | + if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) | ||
634 | + line_offset = w >> 1; | ||
635 | + else | ||
636 | + line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); | ||
637 | + h = s->vram_size / line_offset; | ||
638 | + /* XXX: support weird bochs semantics ? */ | ||
639 | + if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES]) | ||
640 | + return; | ||
641 | + s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w; | ||
642 | + s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h; | ||
643 | + s->vbe_line_offset = line_offset; | ||
644 | + } | ||
645 | + break; | ||
646 | + case VBE_DISPI_INDEX_X_OFFSET: | ||
647 | + case VBE_DISPI_INDEX_Y_OFFSET: | ||
648 | + { | ||
649 | + int x; | ||
650 | + s->vbe_regs[s->vbe_index] = val; | ||
651 | + s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET]; | ||
652 | + x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET]; | ||
653 | + if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) | ||
654 | + s->vbe_start_addr += x >> 1; | ||
655 | + else | ||
656 | + s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3); | ||
657 | + s->vbe_start_addr >>= 2; | ||
612 | } | 658 | } |
613 | break; | 659 | break; |
614 | default: | 660 | default: |
615 | break; | 661 | break; |
616 | } | 662 | } |
617 | - s->vbe_regs[s->vbe_index] = val; | ||
618 | } | 663 | } |
619 | } | 664 | } |
620 | #endif | 665 | #endif |
@@ -633,9 +678,9 @@ static uint32_t vga_mem_readb(uint32_t addr) | @@ -633,9 +678,9 @@ static uint32_t vga_mem_readb(uint32_t addr) | ||
633 | addr -= 0xa0000; | 678 | addr -= 0xa0000; |
634 | break; | 679 | break; |
635 | case 1: | 680 | case 1: |
636 | - addr -= 0xa0000; | ||
637 | - if (addr >= 0x10000) | 681 | + if (addr >= 0xb0000) |
638 | return 0xff; | 682 | return 0xff; |
683 | + addr += s->bank_offset; | ||
639 | break; | 684 | break; |
640 | case 2: | 685 | case 2: |
641 | addr -= 0xb0000; | 686 | addr -= 0xb0000; |
@@ -711,9 +756,9 @@ void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr) | @@ -711,9 +756,9 @@ void vga_mem_writeb(uint32_t addr, uint32_t val, uint32_t vaddr) | ||
711 | addr -= 0xa0000; | 756 | addr -= 0xa0000; |
712 | break; | 757 | break; |
713 | case 1: | 758 | case 1: |
714 | - addr -= 0xa0000; | ||
715 | - if (addr >= 0x10000) | 759 | + if (addr >= 0xb0000) |
716 | return; | 760 | return; |
761 | + addr += s->bank_offset; | ||
717 | break; | 762 | break; |
718 | case 2: | 763 | case 2: |
719 | addr -= 0xb0000; | 764 | addr -= 0xb0000; |
@@ -1611,9 +1656,11 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, | @@ -1611,9 +1656,11 @@ int vga_initialize(DisplayState *ds, uint8_t *vga_ram_base, | ||
1611 | register_ioport_read(0x3d4, 2, vga_ioport_read, 1); | 1656 | register_ioport_read(0x3d4, 2, vga_ioport_read, 1); |
1612 | register_ioport_read(0x3ba, 1, vga_ioport_read, 1); | 1657 | register_ioport_read(0x3ba, 1, vga_ioport_read, 1); |
1613 | register_ioport_read(0x3da, 1, vga_ioport_read, 1); | 1658 | register_ioport_read(0x3da, 1, vga_ioport_read, 1); |
1659 | + s->bank_offset = -0xa0000; | ||
1614 | 1660 | ||
1615 | #ifdef CONFIG_BOCHS_VBE | 1661 | #ifdef CONFIG_BOCHS_VBE |
1616 | s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0; | 1662 | s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0; |
1663 | + s->vbe_bank_mask = ((s->vram_size >> 16) - 1); | ||
1617 | register_ioport_read(0x1ce, 1, vbe_ioport_read, 2); | 1664 | register_ioport_read(0x1ce, 1, vbe_ioport_read, 2); |
1618 | register_ioport_read(0x1cf, 1, vbe_ioport_read, 2); | 1665 | register_ioport_read(0x1cf, 1, vbe_ioport_read, 2); |
1619 | 1666 |