X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=vgasrc%2Fclext.c;h=39f3b2a99362941c223366378aa5058dfcc7163e;hb=5e1694c71d43bf6fdf6ba02bc225e2022e6eee70;hp=277246b0369ee888388a9df9b58ed22dbb10081e;hpb=3c06536954c7683af75090566732f855552f7e16;p=seabios.git diff --git a/vgasrc/clext.c b/vgasrc/clext.c index 277246b..39f3b2a 100644 --- a/vgasrc/clext.c +++ b/vgasrc/clext.c @@ -5,41 +5,21 @@ // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "vgatables.h" // cirrus_init +#include "clext.h" // clext_init +#include "vgabios.h" // VBE_VENDOR_STRING #include "biosvar.h" // GET_GLOBAL #include "util.h" // dprintf #include "bregs.h" // struct bregs +#include "vbe.h" // struct vbe_info +#include "stdvga.h" // VGAREG_SEQU_ADDRESS +#include "pci.h" // pci_config_readl +#include "pci_regs.h" // PCI_BASE_ADDRESS_0 /**************************************************************** * tables ****************************************************************/ -struct cirrus_mode_s { - /* + 0 */ - u16 mode; - u16 width; - u16 height; - u16 depth; - /* + 8 */ - u16 hidden_dac; /* 0x3c6 */ - u16 *seq; /* 0x3c4 */ - u16 *graph; /* 0x3ce */ - u16 *crtc; /* 0x3d4 */ - /* +16 */ - u8 bitsperpixel; - u8 vesacolortype; - u8 vesaredmask; - u8 vesaredpos; - u8 vesagreenmask; - u8 vesagreenpos; - u8 vesabluemask; - u8 vesabluepos; - /* +24 */ - u8 vesareservedmask; - u8 vesareservedpos; -}; - /* VGA */ static u16 cseq_vga[] VAR16 = {0x0007,0xffff}; static u16 cgraph_vga[] VAR16 = {0x0009,0x000a,0x000b,0xffff}; @@ -95,8 +75,8 @@ static u16 ccrtc_640x480x24[] VAR16 = { 0x2c11, 0x5f00,0x4f01,0x4f02,0x8003,0x5204,0x1e05,0x0b06,0x3e07, 0x4009,0x000c,0x000d, - 0xea10,0xdf12,0x0013,0x4014,0xdf15,0x0b16,0xc317,0xff18, - 0x001a,0x321b,0x001d, + 0xea10,0xdf12,0xf013,0x4014,0xdf15,0x0b16,0xc317,0xff18, + 0x001a,0x221b,0x001d, 0xffff }; /* 800x600x8 */ @@ -231,68 +211,97 @@ static u16 cseq_1600x1200x8[] VAR16 = { static u16 ccrtc_1600x1200x8[] VAR16 = { 0x2911,0xc300,0x9f01,0x9f02,0x8603,0x8304,0x9405,0x2406,0xf707, 0x6009,0x000c,0x000d, - 0x0310,0xff12,0xa013,0x4014,0xff15,0x2416,0xc317,0xff18, + 0x0310,0xff12,0xc813,0x4014,0xff15,0x2416,0xc317,0xff18, 0x001a,0x221b,0x001d, 0xffff }; +struct cirrus_mode_s { + u16 mode; + struct vgamode_s info; + + u16 hidden_dac; /* 0x3c6 */ + u16 *seq; /* 0x3c4 */ + u16 *graph; /* 0x3ce */ + u16 *crtc; /* 0x3d4 */ +}; + static struct cirrus_mode_s cirrus_modes[] VAR16 = { - {0x5f,640,480,8,0x00, - cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8,8, - 4,0,0,0,0,0,0,0,0}, - {0x64,640,480,16,0xe1, - cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16, - 6,5,11,6,5,5,0,0,0}, - {0x66,640,480,15,0xf0, - cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16,16, - 6,5,10,5,5,5,0,1,15}, - {0x71,640,480,24,0xe5, - cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24,24, - 6,8,16,8,8,8,0,0,0}, - - {0x5c,800,600,8,0x00, - cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8,8, - 4,0,0,0,0,0,0,0,0}, - {0x65,800,600,16,0xe1, - cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16, - 6,5,11,6,5,5,0,0,0}, - {0x67,800,600,15,0xf0, - cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16,16, - 6,5,10,5,5,5,0,1,15}, - - {0x60,1024,768,8,0x00, - cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8,8, - 4,0,0,0,0,0,0,0,0}, - {0x74,1024,768,16,0xe1, - cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16, - 6,5,11,6,5,5,0,0,0}, - {0x68,1024,768,15,0xf0, - cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16,16, - 6,5,10,5,5,5,0,1,15}, - - {0x78,800,600,24,0xe5, - cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24,24, - 6,8,16,8,8,8,0,0,0}, - {0x79,1024,768,24,0xe5, - cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24,24, - 6,8,16,8,8,8,0,0,0}, - - {0x6d,1280,1024,8,0x00, - cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8,8, - 4,0,0,0,0,0,0,0,0}, - {0x69,1280,1024,15,0xf0, - cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16, - 6,5,10,5,5,5,0,1,15}, - {0x75,1280,1024,16,0xe1, - cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16,16, - 6,5,11,6,5,5,0,0,0}, - - {0x7b,1600,1200,8,0x00, - cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8,8, - 4,0,0,0,0,0,0,0,0}, - - {0xfe,0,0,0,0,cseq_vga,cgraph_vga,ccrtc_vga,0, - 0xff,0,0,0,0,0,0,0,0}, + {0x5f,{MM_PACKED,640,480,8},0x00, + cseq_640x480x8,cgraph_svgacolor,ccrtc_640x480x8}, + {0x64,{MM_DIRECT,640,480,16},0xe1, + cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16}, + {0x66,{MM_DIRECT,640,480,15},0xf0, + cseq_640x480x16,cgraph_svgacolor,ccrtc_640x480x16}, + {0x71,{MM_DIRECT,640,480,24},0xe5, + cseq_640x480x24,cgraph_svgacolor,ccrtc_640x480x24}, + + {0x5c,{MM_PACKED,800,600,8},0x00, + cseq_800x600x8,cgraph_svgacolor,ccrtc_800x600x8}, + {0x65,{MM_DIRECT,800,600,16},0xe1, + cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16}, + {0x67,{MM_DIRECT,800,600,15},0xf0, + cseq_800x600x16,cgraph_svgacolor,ccrtc_800x600x16}, + + {0x60,{MM_PACKED,1024,768,8},0x00, + cseq_1024x768x8,cgraph_svgacolor,ccrtc_1024x768x8}, + {0x74,{MM_DIRECT,1024,768,16},0xe1, + cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16}, + {0x68,{MM_DIRECT,1024,768,15},0xf0, + cseq_1024x768x16,cgraph_svgacolor,ccrtc_1024x768x16}, + + {0x78,{MM_DIRECT,800,600,24},0xe5, + cseq_800x600x24,cgraph_svgacolor,ccrtc_800x600x24}, + {0x79,{MM_DIRECT,1024,768,24},0xe5, + cseq_1024x768x24,cgraph_svgacolor,ccrtc_1024x768x24}, + + {0x6d,{MM_PACKED,1280,1024,8},0x00, + cseq_1280x1024x8,cgraph_svgacolor,ccrtc_1280x1024x8}, + {0x69,{MM_DIRECT,1280,1024,15},0xf0, + cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16}, + {0x75,{MM_DIRECT,1280,1024,16},0xe1, + cseq_1280x1024x16,cgraph_svgacolor,ccrtc_1280x1024x16}, + + {0x7b,{MM_PACKED,1600,1200,8},0x00, + cseq_1600x1200x8,cgraph_svgacolor,ccrtc_1600x1200x8}, +}; + +static struct cirrus_mode_s mode_switchback VAR16 = + {0xfe,{0xff},0,cseq_vga,cgraph_vga,ccrtc_vga}; + +static struct { + u16 vesamode, mode; +} cirrus_vesa_modelist[] VAR16 = { + // 640x480x8 + { 0x101, 0x5f }, + // 640x480x15 + { 0x110, 0x66 }, + // 640x480x16 + { 0x111, 0x64 }, + // 640x480x24 + { 0x112, 0x71 }, + // 800x600x8 + { 0x103, 0x5c }, + // 800x600x15 + { 0x113, 0x67 }, + // 800x600x16 + { 0x114, 0x65 }, + // 800x600x24 + { 0x115, 0x78 }, + // 1024x768x8 + { 0x105, 0x60 }, + // 1024x768x15 + { 0x116, 0x68 }, + // 1024x768x16 + { 0x117, 0x74 }, + // 1024x768x24 + { 0x118, 0x79 }, + // 1280x1024x8 + { 0x107, 0x6d }, + // 1280x1024x15 + { 0x119, 0x69 }, + // 1280x1024x16 + { 0x11a, 0x75 }, }; @@ -300,9 +309,22 @@ static struct cirrus_mode_s cirrus_modes[] VAR16 = { * helper functions ****************************************************************/ +static u16 +cirrus_vesamode_to_mode(u16 vesamode) +{ + int i; + for (i=0; imode); @@ -313,6 +335,15 @@ cirrus_get_modeentry(u8 mode) return NULL; } +struct vgamode_s * +clext_find_mode(int mode) +{ + struct cirrus_mode_s *table_g = cirrus_get_modeentry(mode); + if (table_g) + return &table_g->info; + return stdvga_find_mode(mode); +} + static void cirrus_switch_mode_setregs(u16 *data, u16 port) { @@ -325,102 +356,89 @@ cirrus_switch_mode_setregs(u16 *data, u16 port) } } -static u16 -cirrus_get_crtc(void) -{ - if (inb(VGAREG_READ_MISC_OUTPUT) & 1) - return VGAREG_VGA_CRTC_ADDRESS; - return VGAREG_MDA_CRTC_ADDRESS; -} - static void cirrus_switch_mode(struct cirrus_mode_s *table) { // Unlock cirrus special - outw(0x1206, VGAREG_SEQU_ADDRESS); + stdvga_sequ_write(0x06, 0x12); cirrus_switch_mode_setregs(GET_GLOBAL(table->seq), VGAREG_SEQU_ADDRESS); cirrus_switch_mode_setregs(GET_GLOBAL(table->graph), VGAREG_GRDC_ADDRESS); - cirrus_switch_mode_setregs(GET_GLOBAL(table->crtc), cirrus_get_crtc()); + cirrus_switch_mode_setregs(GET_GLOBAL(table->crtc), stdvga_get_crtc()); - outb(0x00, VGAREG_PEL_MASK); - inb(VGAREG_PEL_MASK); - inb(VGAREG_PEL_MASK); - inb(VGAREG_PEL_MASK); - inb(VGAREG_PEL_MASK); - outb(GET_GLOBAL(table->hidden_dac), VGAREG_PEL_MASK); - outb(0xff, VGAREG_PEL_MASK); + stdvga_pelmask_write(0x00); + stdvga_pelmask_read(); + stdvga_pelmask_read(); + stdvga_pelmask_read(); + stdvga_pelmask_read(); + stdvga_pelmask_write(GET_GLOBAL(table->hidden_dac)); + stdvga_pelmask_write(0xff); - u8 vesacolortype = GET_GLOBAL(table->vesacolortype); - u8 v = vgahw_get_single_palette_reg(0x10) & 0xfe; - if (vesacolortype == 3) - v |= 0x41; - else if (vesacolortype) - v |= 0x01; - vgahw_set_single_palette_reg(0x10, v); + u8 memmodel = GET_GLOBAL(table->info.memmodel); + u8 on = 0; + if (memmodel == MM_PLANAR) + on = 0x41; + else if (memmodel != MM_TEXT) + on = 0x01; + stdvga_attr_mask(0x10, 0x01, on); } static u8 cirrus_get_memsize(void) { // get DRAM band width - outb(0x0f, VGAREG_SEQU_ADDRESS); - u8 v = inb(VGAREG_SEQU_DATA); + u8 v = stdvga_sequ_read(0x0f); u8 x = (v >> 3) & 0x03; - if (x == 0x03) { - if (v & 0x80) - // 4MB - return 0x40; - // 2MB - return 0x20; - } + if (x == 0x03 && v & 0x80) + // 4MB + return 0x40; return 0x04 << x; } static void cirrus_enable_16k_granularity(void) { - outb(0x0b, VGAREG_GRDC_ADDRESS); - u8 v = inb(VGAREG_GRDC_DATA); - outb(v | 0x20, VGAREG_GRDC_DATA); + stdvga_grdc_mask(0x0b, 0x00, 0x20); } static void cirrus_clear_vram(u16 param) { cirrus_enable_16k_granularity(); - u8 count = cirrus_get_memsize() * 4; + u8 count = GET_GLOBAL(VBE_total_memory) / (16 * 1024); u8 i; for (i=0; iax = 0x0032; @@ -447,29 +463,27 @@ cirrus_extbios_80h(struct bregs *regs) } static void -cirrus_extbios_81h(struct bregs *regs) +clext_101281(struct bregs *regs) { // XXX regs->ax = 0x0100; } static void -cirrus_extbios_82h(struct bregs *regs) +clext_101282(struct bregs *regs) { - u16 crtc_addr = cirrus_get_crtc(); - outb(0x27, crtc_addr); - regs->al = inb(crtc_addr + 1) & 0x03; + regs->al = stdvga_crtc_read(stdvga_get_crtc(), 0x27) & 0x03; regs->ah = 0xAF; } static void -cirrus_extbios_85h(struct bregs *regs) +clext_101285(struct bregs *regs) { - regs->al = cirrus_get_memsize(); + regs->al = GET_GLOBAL(VBE_total_memory) / (64*1024); } static void -cirrus_extbios_9Ah(struct bregs *regs) +clext_10129a(struct bregs *regs) { regs->ax = 0x4060; regs->cx = 0x1132; @@ -484,7 +498,7 @@ ASM16( "retf"); static void -cirrus_extbios_A0h(struct bregs *regs) +clext_1012a0(struct bregs *regs) { struct cirrus_mode_s *table_g = cirrus_get_modeentry(regs->al & 0x7f); regs->ah = (table_g ? 1 : 0); @@ -493,38 +507,43 @@ cirrus_extbios_A0h(struct bregs *regs) } static void -cirrus_extbios_A1h(struct bregs *regs) +clext_1012a1(struct bregs *regs) { regs->bx = 0x0e00; // IBM 8512/8513, color } static void -cirrus_extbios_A2h(struct bregs *regs) +clext_1012a2(struct bregs *regs) { regs->al = 0x07; // HSync 31.5 - 64.0 kHz } static void -cirrus_extbios_AEh(struct bregs *regs) +clext_1012ae(struct bregs *regs) { regs->al = 0x01; // High Refresh 75Hz } +static void +clext_1012XX(struct bregs *regs) +{ + debug_stub(regs); +} + void -cirrus_extbios(struct bregs *regs) +clext_1012(struct bregs *regs) { - // XXX - regs->bl < 0x80 or > 0xaf call regular handlers. switch (regs->bl) { - case 0x80: cirrus_extbios_80h(regs); break; - case 0x81: cirrus_extbios_81h(regs); break; - case 0x82: cirrus_extbios_82h(regs); break; - case 0x85: cirrus_extbios_85h(regs); break; - case 0x9a: cirrus_extbios_9Ah(regs); break; - case 0xa0: cirrus_extbios_A0h(regs); break; - case 0xa1: cirrus_extbios_A1h(regs); break; - case 0xa2: cirrus_extbios_A2h(regs); break; - case 0xae: cirrus_extbios_AEh(regs); break; - default: break; + case 0x80: clext_101280(regs); break; + case 0x81: clext_101281(regs); break; + case 0x82: clext_101282(regs); break; + case 0x85: clext_101285(regs); break; + case 0x9a: clext_10129a(regs); break; + case 0xa0: clext_1012a0(regs); break; + case 0xa1: clext_1012a1(regs); break; + case 0xa2: clext_1012a2(regs); break; + case 0xae: clext_1012ae(regs); break; + default: clext_1012XX(regs); break; } } @@ -533,103 +552,152 @@ cirrus_extbios(struct bregs *regs) * vesa calls ****************************************************************/ -#if 0 -static u16 -cirrus_vesamode_to_mode(u16 vesamode) +void +clext_list_modes(u16 seg, u16 *dest, u16 *last) { - // XXX - convert assembler - return 0; + int i; + for (i=0; i>= 1; + if (v != 0x04) + v++; + return v; } static void cirrus_set_line_offset(u16 new_line_offset) { - // XXX - convert assembler + new_line_offset /= 8; + u16 crtc_addr = stdvga_get_crtc(); + stdvga_crtc_write(crtc_addr, 0x13, new_line_offset); + stdvga_crtc_mask(crtc_addr, 0x1b, 0x10, (new_line_offset & 0x100) >> 4); } static u16 cirrus_get_line_offset(void) { - // XXX - convert assembler - return 0; -} - -static u16 -cirrus_get_line_offset_entry(void *table) -{ - // XXX - convert assembler - return 0; + u16 crtc_addr = stdvga_get_crtc(); + u8 reg13 = stdvga_crtc_read(crtc_addr, 0x13); + u8 reg1b = stdvga_crtc_read(crtc_addr, 0x1b); + return (((reg1b & 0x10) << 4) + reg13) * 8; } static void -cirrus_set_start_addr(void *addr) +cirrus_set_start_addr(u32 addr) { - // XXX - convert assembler + u16 crtc_addr = stdvga_get_crtc(); + stdvga_crtc_write(crtc_addr, 0x0d, addr); + stdvga_crtc_write(crtc_addr, 0x0c, addr >> 8); + stdvga_crtc_mask(crtc_addr, 0x1d, 0x80, (addr & 0x0800) >> 4); + stdvga_crtc_mask(crtc_addr, 0x1b, 0x0d + , ((addr & 0x0100) >> 8) | ((addr & 0x0600) >> 7)); } -static void * +static u32 cirrus_get_start_addr(void) { - // XXX - convert assembler - return NULL; -} -#endif - -static void -cirrus_vesa_00h(struct bregs *regs) -{ - // XXX - convert assembler -} - -static void -cirrus_vesa_01h(struct bregs *regs) -{ - // XXX - convert assembler -} - -static void -cirrus_vesa_02h(struct bregs *regs) -{ - // XXX - convert assembler -} - -static void -cirrus_vesa_03h(struct bregs *regs) -{ - // XXX - convert assembler + u16 crtc_addr = stdvga_get_crtc(); + u8 b2 = stdvga_crtc_read(crtc_addr, 0x0c); + u8 b1 = stdvga_crtc_read(crtc_addr, 0x0d); + u8 b3 = stdvga_crtc_read(crtc_addr, 0x1b); + u8 b4 = stdvga_crtc_read(crtc_addr, 0x1d); + return (b1 | (b2<<8) | ((b3 & 0x01) << 16) | ((b3 & 0x0c) << 15) + | ((b4 & 0x80) << 12)); } -// XXX - add cirrus_vesa_05h_farentry to vgaentry.S - static void cirrus_vesa_05h(struct bregs *regs) { - // XXX - convert assembler + if (regs->bl > 1) + goto fail; + if (regs->bh == 0) { + // set mempage + if (regs->dx >= 0x100) + goto fail; + stdvga_grdc_write(regs->bl + 9, regs->dx); + } else if (regs->bh == 1) { + // get mempage + regs->dx = stdvga_grdc_read(regs->bl + 9); + } else + goto fail; + + regs->ax = 0x004f; + return; +fail: + regs->ax = 0x014f; } static void cirrus_vesa_06h(struct bregs *regs) { - // XXX - convert assembler + if (regs->bl > 2) { + regs->ax = 0x0100; + return; + } + + if (regs->bl == 0x00) { + cirrus_set_line_offset(cirrus_get_bpp_bytes() * regs->cx); + } else if (regs->bl == 0x02) { + cirrus_set_line_offset(regs->cx); + } + + u32 v = cirrus_get_line_offset(); + regs->cx = v / cirrus_get_bpp_bytes(); + regs->bx = v; + regs->dx = GET_GLOBAL(VBE_total_memory) / v; + regs->ax = 0x004f; } static void cirrus_vesa_07h(struct bregs *regs) { - // XXX - convert assembler + if (regs->bl == 0x80 || regs->bl == 0x00) { + u32 addr = (cirrus_get_bpp_bytes() * regs->cx + + cirrus_get_line_offset() * regs->dx); + cirrus_set_start_addr(addr / 4); + } else if (regs->bl == 0x01) { + u32 addr = cirrus_get_start_addr() * 4; + u32 linelength = cirrus_get_line_offset(); + regs->dx = addr / linelength; + regs->cx = (addr % linelength) / cirrus_get_bpp_bytes(); + } else { + regs->ax = 0x0100; + return; + } + + regs->ax = 0x004f; } static void cirrus_vesa_10h(struct bregs *regs) { - // XXX - convert assembler + if (regs->bl == 0x00) { + regs->bx = 0x0f30; + regs->ax = 0x004f; + return; + } + if (regs->bl == 0x01) { + SET_BDA(vbe_flag, regs->bh); + regs->ax = 0x004f; + return; + } + if (regs->bl == 0x02) { + regs->bh = GET_BDA(vbe_flag); + regs->ax = 0x004f; + return; + } + regs->ax = 0x014f; } static void @@ -643,10 +711,6 @@ void cirrus_vesa(struct bregs *regs) { switch (regs->al) { - case 0x00: cirrus_vesa_00h(regs); break; - case 0x01: cirrus_vesa_01h(regs); break; - case 0x02: cirrus_vesa_02h(regs); break; - case 0x03: cirrus_vesa_03h(regs); break; case 0x05: cirrus_vesa_05h(regs); break; case 0x06: cirrus_vesa_06h(regs); break; case 0x07: cirrus_vesa_07h(regs); break; @@ -660,21 +724,35 @@ cirrus_vesa(struct bregs *regs) * init ****************************************************************/ -void -cirrus_init(void) +int +clext_init(void) { + int ret = stdvga_init(); + if (ret) + return ret; + dprintf(1, "cirrus init\n"); if (! cirrus_check()) - return; + return -1; dprintf(1, "cirrus init 2\n"); + u32 lfb_addr = 0; + int bdf = GET_GLOBAL(VgaBDF); + if (CONFIG_VGA_PCI && bdf >= 0) + lfb_addr = (pci_config_readl(bdf, PCI_BASE_ADDRESS_0) + & PCI_BASE_ADDRESS_MEM_MASK); + SET_VGA(VBE_framebuffer, lfb_addr); + u16 totalmem = cirrus_get_memsize(); + SET_VGA(VBE_total_memory, totalmem * 64 * 1024); + SET_VGA(VBE_win_granularity, 16); + // memory setup - outb(0x0f, VGAREG_SEQU_ADDRESS); - u8 v = inb(VGAREG_SEQU_DATA); - outb(((v & 0x18) << 8) | 0x0a, VGAREG_SEQU_ADDRESS); + stdvga_sequ_write(0x0a, stdvga_sequ_read(0x0f) & 0x18); // set vga mode - outw(0x0007, VGAREG_SEQU_ADDRESS); + stdvga_sequ_write(0x07, 0x00); // reset bitblt - outw(0x0431, VGAREG_GRDC_ADDRESS); - outw(0x0031, VGAREG_GRDC_ADDRESS); + stdvga_grdc_write(0x31, 0x04); + stdvga_grdc_write(0x31, 0x00); + + return 0; }