summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVolker Ruppert <info@vruppert.de>2006-06-18 15:22:43 +0000
committerVolker Ruppert <info@vruppert.de>2006-06-18 15:22:43 +0000
commit72c270d8091fb0f09e8291cc0e7154b075b921a9 (patch)
tree833a5d7c6bb7638e67d4dbf682cb5c3c3ea646d1
parent819d1f4cd637f34ca314ac38b165e772703df90d (diff)
- applied patch from the qemu project (Fabrice Bellard)
* Cirrus SVGA now supports the "no clear" bit when switching to Cirrus or VESA mode * Bochs VBE protected mode interface improved * save/restore video state support for Bochs VBE and standard VGA added * Bochs VBE prepared for more modi
-rw-r--r--clext.c46
-rw-r--r--vbe.c207
-rw-r--r--vbe.h18
-rw-r--r--vbetables.h6
-rw-r--r--vgabios.c227
5 files changed, 468 insertions, 36 deletions
diff --git a/clext.c b/clext.c
index a86a4ec..26b7228 100644
--- a/clext.c
+++ b/clext.c
@@ -544,6 +544,13 @@ cirrus_debug_dump:
cirrus_set_video_mode_extended:
call cirrus_switch_mode
pop ax ;; mode
+ test al, #0x80
+ jnz cirrus_set_video_mode_extended_1
+ push ax
+ mov ax, #0xffff ; set to 0xff to keep win 2K happy
+ call cirrus_clear_vram
+ pop ax
+cirrus_set_video_mode_extended_1:
and al, #0x7f
push ds
@@ -1011,6 +1018,13 @@ cirrus_vesa_02h_1:
jnz cirrus_vesa_02h_3
call cirrus_enable_16k_granularity
cirrus_vesa_02h_3:
+ test bx, #0x8000 ;; no clear
+ jnz cirrus_vesa_02h_4
+ push ax
+ xor ax,ax
+ call cirrus_clear_vram
+ pop ax
+cirrus_vesa_02h_4:
pop ax
push ds
#ifdef CIRRUS_VESA3_PMINFO
@@ -1479,6 +1493,38 @@ cirrus_get_start_addr:
pop bx
ret
+cirrus_clear_vram:
+ pusha
+ push es
+ mov si, ax
+
+ call cirrus_enable_16k_granularity
+ call cirrus_extbios_85h
+ shl al, #2
+ mov bl, al
+ xor ah,ah
+cirrus_clear_vram_1:
+ mov al, #0x09
+ mov dx, #0x3ce
+ out dx, ax
+ push ax
+ mov cx, #0xa000
+ mov es, cx
+ xor di, di
+ mov ax, si
+ mov cx, #8192
+ cld
+ rep
+ stosw
+ pop ax
+ inc ah
+ cmp ah, bl
+ jne cirrus_clear_vram_1
+
+ pop es
+ popa
+ ret
+
cirrus_extbios_handlers:
;; 80h
dw cirrus_extbios_80h
diff --git a/vbe.c b/vbe.c
index d0eb2af..d4becd3 100644
--- a/vbe.c
+++ b/vbe.c
@@ -118,21 +118,114 @@ _vbebios_mode_list:
.word VBE_VESA_MODE_END_OF_LIST
#endif
+ .align 2
vesa_pm_start:
dw vesa_pm_set_window - vesa_pm_start
- dw vesa_pm_set_display_strt - vesa_pm_start
+ dw vesa_pm_set_display_start - vesa_pm_start
dw vesa_pm_unimplemented - vesa_pm_start
- dw 0
+ dw vesa_pm_io_ports_table - vesa_pm_start
+vesa_pm_io_ports_table:
+ dw VBE_DISPI_IOPORT_INDEX
+ dw VBE_DISPI_IOPORT_INDEX + 1
+ dw VBE_DISPI_IOPORT_DATA
+ dw VBE_DISPI_IOPORT_DATA + 1
+ dw 0xffff
+ dw 0xffff
USE32
vesa_pm_set_window:
- mov ax, #0x4f05
- int #0x10
+ cmp bx, #0x00
+ je vesa_pm_set_display_window1
+ mov ax, #0x0100
+ ret
+vesa_pm_set_display_window1:
+ mov ax, dx
+ push dx
+ push ax
+ mov dx, # VBE_DISPI_IOPORT_INDEX
+ mov ax, # VBE_DISPI_INDEX_BANK
+ out dx, ax
+ pop ax
+ mov dx, # VBE_DISPI_IOPORT_DATA
+ out dx, ax
+ pop dx
+ mov ax, #0x004f
ret
vesa_pm_set_display_start:
- mov ax, #0x4f07
- int #0x10
+ cmp bl, #0x80
+ je vesa_pm_set_display_start1
+ cmp bl, #0x00
+ je vesa_pm_set_display_start1
+ mov ax, #0x0100
+ ret
+vesa_pm_set_display_start1:
+; convert offset to (X, Y) coordinate
+; (would be simpler to change Bochs VBE API...)
+ push eax
+ push ecx
+ push edx
+ push esi
+ push edi
+ shl edx, #16
+ and ecx, #0xffff
+ or ecx, edx
+ shl ecx, #2
+ mov eax, ecx
+
+ push eax
+ mov dx, # VBE_DISPI_IOPORT_INDEX
+ mov ax, # VBE_DISPI_INDEX_VIRT_WIDTH
+ out dx, ax
+ mov dx, # VBE_DISPI_IOPORT_DATA
+ in ax, dx
+ movzx ecx, ax
+
+ mov dx, # VBE_DISPI_IOPORT_INDEX
+ mov ax, # VBE_DISPI_INDEX_BPP
+ out dx, ax
+ mov dx, # VBE_DISPI_IOPORT_DATA
+ in ax, dx
+ movzx esi, ax
+ pop eax
+
+ add esi, #7
+ shr esi, #3
+ imul ecx, esi
+ xor edx, edx
+ div ecx
+ mov edi, eax
+ mov eax, edx
+ xor edx, edx
+ div esi
+
+ push dx
+ push ax
+ mov dx, # VBE_DISPI_IOPORT_INDEX
+ mov ax, # VBE_DISPI_INDEX_X_OFFSET
+ out dx, ax
+ pop ax
+ mov dx, # VBE_DISPI_IOPORT_DATA
+ out dx, ax
+ pop dx
+
+ mov ax, di
+ push dx
+ push ax
+ mov dx, # VBE_DISPI_IOPORT_INDEX
+ mov ax, # VBE_DISPI_INDEX_Y_OFFSET
+ out dx, ax
+ pop ax
+ mov dx, # VBE_DISPI_IOPORT_DATA
+ out dx, ax
+ pop dx
+
+ pop edi
+ pop esi
+ pop edx
+ pop ecx
+ pop eax
+ mov ax, #0x004f
ret
vesa_pm_unimplemented:
@@ -835,6 +928,64 @@ vbe_03_ok:
ASM_END
+Bit16u vbe_biosfn_read_video_state_size()
+{
+ return 9 * 2;
+}
+
+void vbe_biosfn_save_video_state(ES, BX)
+ Bit16u ES; Bit16u BX;
+{
+ Bit16u enable, i;
+
+ outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
+ enable = inw(VBE_DISPI_IOPORT_DATA);
+ write_word(ES, BX, enable);
+ BX += 2;
+ if (!(enable & VBE_DISPI_ENABLED))
+ return;
+ for(i = VBE_DISPI_INDEX_XRES; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
+ if (i != VBE_DISPI_INDEX_ENABLE) {
+ outw(VBE_DISPI_IOPORT_INDEX, i);
+ write_word(ES, BX, inw(VBE_DISPI_IOPORT_DATA));
+ BX += 2;
+ }
+ }
+}
+
+
+void vbe_biosfn_restore_video_state(ES, BX)
+ Bit16u ES; Bit16u BX;
+{
+ Bit16u enable, i;
+
+ enable = read_word(ES, BX);
+ BX += 2;
+
+ if (!(enable & VBE_DISPI_ENABLED)) {
+ outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
+ outw(VBE_DISPI_IOPORT_DATA, enable);
+ } else {
+ outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_XRES);
+ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
+ BX += 2;
+ outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_YRES);
+ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
+ BX += 2;
+ outw(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_BPP);
+ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
+ BX += 2;
+ outw(VBE_DISPI_IOPORT_INDEX,VBE_DISPI_INDEX_ENABLE);
+ outw(VBE_DISPI_IOPORT_DATA, enable);
+
+ for(i = VBE_DISPI_INDEX_BANK; i <= VBE_DISPI_INDEX_Y_OFFSET; i++) {
+ outw(VBE_DISPI_IOPORT_INDEX, i);
+ outw(VBE_DISPI_IOPORT_DATA, read_word(ES, BX));
+ BX += 2;
+ }
+ }
+}
+
/** Function 04h - Save/Restore State
*
* Input:
@@ -849,10 +1000,48 @@ ASM_END
* BX = Number of 64-byte blocks to hold the state buffer (if DL=00h)
*
*/
-void vbe_biosfn_save_restore_state(AX, DL, CX, ES, BX)
+void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX)
+Bit16u *AX; Bit16u CX; Bit16u DX; Bit16u ES; Bit16u *BX;
{
-}
+ Bit16u ss=get_SS();
+ Bit16u result, val;
+ result = 0x4f;
+ switch(GET_DL()) {
+ case 0x00:
+ val = biosfn_read_video_state_size2(CX);
+#ifdef DEBUG
+ printf("VGA state size=%x\n", val);
+#endif
+ if (CX & 8)
+ val += vbe_biosfn_read_video_state_size();
+ write_word(ss, BX, val);
+ break;
+ case 0x01:
+ val = read_word(ss, BX);
+ val = biosfn_save_video_state(CX, ES, val);
+#ifdef DEBUG
+ printf("VGA save_state offset=%x\n", val);
+#endif
+ if (CX & 8)
+ vbe_biosfn_save_video_state(ES, val);
+ break;
+ case 0x02:
+ val = read_word(ss, BX);
+ val = biosfn_restore_video_state(CX, ES, val);
+#ifdef DEBUG
+ printf("VGA restore_state offset=%x\n", val);
+#endif
+ if (CX & 8)
+ vbe_biosfn_restore_video_state(ES, val);
+ break;
+ default:
+ // function failed
+ result = 0x100;
+ break;
+ }
+ write_word(ss, AX, result);
+}
/** Function 05h - Display Window Control
*
@@ -1090,7 +1279,7 @@ void vbe_biosfn_set_get_palette_data(AX)
*/
ASM_START
vbe_biosfn_return_protected_mode_interface:
- test bx, bx
+ test bl, bl
jnz _fail
mov di, #0xc000
mov es, di
diff --git a/vbe.h b/vbe.h
index 621048a..14ec69f 100644
--- a/vbe.h
+++ b/vbe.h
@@ -14,7 +14,7 @@ Boolean vbe_has_vbe_display();
void vbe_biosfn_return_controller_information(AX, ES, DI);
void vbe_biosfn_return_mode_information(AX, CX, ES, DI);
void vbe_biosfn_set_mode(AX, BX, ES, DI);
-void vbe_biosfn_save_restore_state(AX, DL, CX, ES, BX);
+void vbe_biosfn_save_restore_state(AX, CX, DX, ES, BX);
void vbe_biosfn_set_get_palette_data(AX);
void vbe_biosfn_return_protected_mode_interface(AX);
@@ -151,6 +151,12 @@ typedef struct ModeInfoBlock
Bit8u Reserved[189];
} ModeInfoBlock;
+typedef struct ModeInfoListItem
+{
+ Bit16u mode;
+ ModeInfoBlockCompact info;
+} ModeInfoListItem;
+
// VBE Return Status Info
// AL
#define VBE_RETURN_STATUS_SUPPORTED 0x4F
@@ -193,6 +199,10 @@ typedef struct ModeInfoBlock
#define VBE_VESA_MODE_1280X1024X1555 0x119
#define VBE_VESA_MODE_1280X1024X565 0x11A
#define VBE_VESA_MODE_1280X1024X888 0x11B
+#define VBE_VESA_MODE_1600X1200X8 0x11C
+#define VBE_VESA_MODE_1600X1200X1555 0x11D
+#define VBE_VESA_MODE_1600X1200X565 0x11E
+#define VBE_VESA_MODE_1600X1200X888 0x11F
// BOCHS/PLEX86 'own' mode numbers
#define VBE_OWN_MODE_320X200X8888 0x140
@@ -202,6 +212,12 @@ typedef struct ModeInfoBlock
#define VBE_OWN_MODE_1024X768X8888 0x144
#define VBE_OWN_MODE_1280X1024X8888 0x145
#define VBE_OWN_MODE_320X200X8 0x146
+#define VBE_OWN_MODE_1600X1200X8888 0x147
+#define VBE_OWN_MODE_1152X864X8 0x148
+#define VBE_OWN_MODE_1152X864X1555 0x149
+#define VBE_OWN_MODE_1152X864X565 0x14a
+#define VBE_OWN_MODE_1152X864X888 0x14b
+#define VBE_OWN_MODE_1152X864X8888 0x14c
#define VBE_VESA_MODE_END_OF_LIST 0xFFFF
diff --git a/vbetables.h b/vbetables.h
index a742ac7..a62d464 100644
--- a/vbetables.h
+++ b/vbetables.h
@@ -8,12 +8,6 @@
*/
-typedef struct ModeInfoListItem
-{
- Bit16u mode;
- ModeInfoBlockCompact info;
-} ModeInfoListItem;
-
// FIXME: check all member variables to be correct for the different modi
// FIXME: add more modi
static ModeInfoListItem mode_info_list[]=
diff --git a/vgabios.c b/vgabios.c
index a0e6c71..7190c0e 100644
--- a/vgabios.c
+++ b/vgabios.c
@@ -109,8 +109,8 @@ static void biosfn_enable_video_refresh_control();
static void biosfn_write_string();
static void biosfn_read_state_info();
static void biosfn_read_video_state_size();
-static void biosfn_save_video_state();
-static void biosfn_restore_video_state();
+static Bit16u biosfn_save_video_state();
+static Bit16u biosfn_restore_video_state();
extern Bit8u video_save_pointer_table[];
// This is for compiling with gcc2 and gcc3
@@ -748,12 +748,7 @@ static void int10_func(DI, SI, BP, SP, BX, DX, CX, AX, DS, ES, FLAGS)
vbe_biosfn_set_mode(&AX,BX,ES,DI);
break;
case 0x04:
- //FIXME
-#ifdef DEBUG
- unimplemented();
-#endif
- // function failed
- AX=0x100;
+ vbe_biosfn_save_restore_state(&AX, CX, DX, ES, &BX);
break;
case 0x09:
//FIXME
@@ -3138,23 +3133,215 @@ Bit16u BX;Bit16u ES;Bit16u DI;
}
// --------------------------------------------------------------------------------------------
-static void biosfn_read_video_state_size (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
+// --------------------------------------------------------------------------------------------
+static Bit16u biosfn_read_video_state_size2 (CX)
+ Bit16u CX;
{
-#ifdef DEBUG
- unimplemented();
-#endif
+ Bit16u size;
+ size = 0;
+ if (CX & 1) {
+ size += 0x46;
+ }
+ if (CX & 2) {
+ size += (5 + 8 + 5) * 2 + 6;
+ }
+ if (CX & 4) {
+ size += 3 + 256 * 3 + 1;
}
-static void biosfn_save_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
+ return size;
+}
+
+static void biosfn_read_video_state_size (CX, BX)
+ Bit16u CX; Bit16u *BX;
{
-#ifdef DEBUG
- unimplemented();
-#endif
+ Bit16u ss=get_SS();
+ write_word(ss, BX, biosfn_read_video_state_size2(CX));
}
-static void biosfn_restore_video_state (CX,ES,BX) Bit16u CX;Bit16u ES;Bit16u BX;
+
+static Bit16u biosfn_save_video_state (CX,ES,BX)
+ Bit16u CX;Bit16u ES;Bit16u BX;
{
-#ifdef DEBUG
- unimplemented();
-#endif
+ Bit16u i, v, crtc_addr, ar_index;
+
+ crtc_addr = read_word(BIOSMEM_SEG, BIOSMEM_CRTC_ADDRESS);
+ if (CX & 1) {
+ write_byte(ES, BX, inb(VGAREG_SEQU_ADDRESS)); BX++;
+ write_byte(ES, BX, inb(crtc_addr)); BX++;
+ write_byte(ES, BX, inb(VGAREG_GRDC_ADDRESS)); BX++;
+ inb(VGAREG_ACTL_RESET);
+ ar_index = inb(VGAREG_ACTL_ADDRESS);
+ write_byte(ES, BX, ar_index); BX++;
+ write_byte(ES, BX, inb(VGAREG_READ_FEATURE_CTL)); BX++;
+
+ for(i=1;i<=4;i++){
+ outb(VGAREG_SEQU_ADDRESS, i);
+ write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
+ }
+ outb(VGAREG_SEQU_ADDRESS, 0);
+ write_byte(ES, BX, inb(VGAREG_SEQU_DATA)); BX++;
+
+ for(i=0;i<=0x18;i++) {
+ outb(crtc_addr,i);
+ write_byte(ES, BX, inb(crtc_addr+1)); BX++;
+ }
+
+ for(i=0;i<=0x13;i++) {
+ inb(VGAREG_ACTL_RESET);
+ outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
+ write_byte(ES, BX, inb(VGAREG_ACTL_READ_DATA)); BX++;
+ }
+ inb(VGAREG_ACTL_RESET);
+
+ for(i=0;i<=8;i++) {
+ outb(VGAREG_GRDC_ADDRESS,i);
+ write_byte(ES, BX, inb(VGAREG_GRDC_DATA)); BX++;
+ }
+
+ write_word(ES, BX, crtc_addr); BX+= 2;
+
+ /* XXX: read plane latches */
+ write_byte(ES, BX, 0); BX++;
+ write_byte(ES, BX, 0); BX++;
+ write_byte(ES, BX, 0); BX++;
+ write_byte(ES, BX, 0); BX++;
+ }
+ if (CX & 2) {
+ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE)); BX++;
+ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_NB_COLS)); BX += 2;
+ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE)); BX += 2;
+ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)); BX += 2;
+ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS)); BX++;
+ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT)); BX += 2;
+ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL)); BX++;
+ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES)); BX++;
+ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL)); BX++;
+ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE)); BX += 2;
+ for(i=0;i<8;i++) {
+ write_word(ES, BX, read_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i));
+ BX += 2;
+ }
+ write_word(ES, BX, read_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START)); BX += 2;
+ write_byte(ES, BX, read_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE)); BX++;
+ /* current font */
+ write_word(ES, BX, read_word(0, 0x1f * 4)); BX += 2;
+ write_word(ES, BX, read_word(0, 0x1f * 4 + 2)); BX += 2;
+ write_word(ES, BX, read_word(0, 0x43 * 4)); BX += 2;
+ write_word(ES, BX, read_word(0, 0x43 * 4 + 2)); BX += 2;
+ }
+ if (CX & 4) {
+ /* XXX: check this */
+ write_byte(ES, BX, inb(VGAREG_DAC_STATE)); BX++; /* read/write mode dac */
+ write_byte(ES, BX, inb(VGAREG_DAC_WRITE_ADDRESS)); BX++; /* pix address */
+ write_byte(ES, BX, inb(VGAREG_PEL_MASK)); BX++;
+ // Set the whole dac always, from 0
+ outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
+ for(i=0;i<256*3;i++) {
+ write_byte(ES, BX, inb(VGAREG_DAC_DATA)); BX++;
+ }
+ write_byte(ES, BX, 0); BX++; /* color select register */
+ }
+ return BX;
+}
+
+static Bit16u biosfn_restore_video_state (CX,ES,BX)
+ Bit16u CX;Bit16u ES;Bit16u BX;
+{
+ Bit16u i, crtc_addr, v, addr1, ar_index;
+
+ if (CX & 1) {
+ // Reset Attribute Ctl flip-flop
+ inb(VGAREG_ACTL_RESET);
+
+ crtc_addr = read_word(ES, BX + 0x40);
+ addr1 = BX;
+ BX += 5;
+
+ for(i=1;i<=4;i++){
+ outb(VGAREG_SEQU_ADDRESS, i);
+ outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
+ }
+ outb(VGAREG_SEQU_ADDRESS, 0);
+ outb(VGAREG_SEQU_DATA, read_byte(ES, BX)); BX++;
+
+ // Disable CRTC write protection
+ outw(crtc_addr,0x0011);
+ // Set CRTC regs
+ for(i=0;i<=0x18;i++) {
+ if (i != 0x11) {
+ outb(crtc_addr,i);
+ outb(crtc_addr+1, read_byte(ES, BX));
+ }
+ BX++;
+ }
+ // select crtc base address
+ v = inb(VGAREG_READ_MISC_OUTPUT) & ~0x01;
+ if (crtc_addr = 0x3d4)
+ v |= 0x01;
+ outb(VGAREG_WRITE_MISC_OUTPUT, v);
+
+ // enable write protection if needed
+ outb(crtc_addr, 0x11);
+ outb(crtc_addr+1, read_byte(ES, BX - 0x18 + 0x11));
+
+ // Set Attribute Ctl
+ ar_index = read_byte(ES, addr1 + 0x03);
+ inb(VGAREG_ACTL_RESET);
+ for(i=0;i<=0x13;i++) {
+ outb(VGAREG_ACTL_ADDRESS, i | (ar_index & 0x20));
+ outb(VGAREG_ACTL_WRITE_DATA, read_byte(ES, BX)); BX++;
+ }
+ outb(VGAREG_ACTL_ADDRESS, ar_index);
+ inb(VGAREG_ACTL_RESET);
+
+ for(i=0;i<=8;i++) {
+ outb(VGAREG_GRDC_ADDRESS,i);
+ outb(VGAREG_GRDC_DATA, read_byte(ES, BX)); BX++;
+ }
+ BX += 2; /* crtc_addr */
+ BX += 4; /* plane latches */
+
+ outb(VGAREG_SEQU_ADDRESS, read_byte(ES, addr1)); addr1++;
+ outb(crtc_addr, read_byte(ES, addr1)); addr1++;
+ outb(VGAREG_GRDC_ADDRESS, read_byte(ES, addr1)); addr1++;
+ addr1++;
+ outb(crtc_addr - 0x4 + 0xa, read_byte(ES, addr1)); addr1++;
+ }
+ if (CX & 2) {
+ write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_MODE, read_byte(ES, BX)); BX++;
+ write_word(BIOSMEM_SEG,BIOSMEM_NB_COLS, read_word(ES, BX)); BX += 2;
+ write_word(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE, read_word(ES, BX)); BX += 2;
+ write_word(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS, read_word(ES, BX)); BX += 2;
+ write_byte(BIOSMEM_SEG,BIOSMEM_NB_ROWS, read_byte(ES, BX)); BX++;
+ write_word(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT, read_word(ES, BX)); BX += 2;
+ write_byte(BIOSMEM_SEG,BIOSMEM_VIDEO_CTL, read_byte(ES, BX)); BX++;
+ write_byte(BIOSMEM_SEG,BIOSMEM_SWITCHES, read_byte(ES, BX)); BX++;
+ write_byte(BIOSMEM_SEG,BIOSMEM_MODESET_CTL, read_byte(ES, BX)); BX++;
+ write_word(BIOSMEM_SEG,BIOSMEM_CURSOR_TYPE, read_word(ES, BX)); BX += 2;
+ for(i=0;i<8;i++) {
+ write_word(BIOSMEM_SEG, BIOSMEM_CURSOR_POS+2*i, read_word(ES, BX));
+ BX += 2;
+ }
+ write_word(BIOSMEM_SEG,BIOSMEM_CURRENT_START, read_word(ES, BX)); BX += 2;
+ write_byte(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE, read_byte(ES, BX)); BX++;
+ /* current font */
+ write_word(0, 0x1f * 4, read_word(ES, BX)); BX += 2;
+ write_word(0, 0x1f * 4 + 2, read_word(ES, BX)); BX += 2;
+ write_word(0, 0x43 * 4, read_word(ES, BX)); BX += 2;
+ write_word(0, 0x43 * 4 + 2, read_word(ES, BX)); BX += 2;
+ }
+ if (CX & 4) {
+ BX++;
+ v = read_byte(ES, BX); BX++;
+ outb(VGAREG_PEL_MASK, read_byte(ES, BX)); BX++;
+ // Set the whole dac always, from 0
+ outb(VGAREG_DAC_WRITE_ADDRESS,0x00);
+ for(i=0;i<256*3;i++) {
+ outb(VGAREG_DAC_DATA, read_byte(ES, BX)); BX++;
+ }
+ BX++;
+ outb(VGAREG_DAC_WRITE_ADDRESS, v);
+ }
+ return BX;
}
// ============================================================================================