X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=vgasrc%2Fstdvga.c;h=0345a813f03d38cb1f2ef9866461be0f5c981c2d;hb=3471fdbe63f9e982ae979094b6b3e7562dae1021;hp=1727fcaafe4ae3f27b1e9376906c4d0e7f9fc9c0;hpb=ed68e5b601ad283b48ced1f5b25b58c1b8d00815;p=seabios.git diff --git a/vgasrc/stdvga.c b/vgasrc/stdvga.c index 1727fca..0345a81 100644 --- a/vgasrc/stdvga.c +++ b/vgasrc/stdvga.c @@ -1,15 +1,16 @@ -// VGA io port access +// Standard VGA driver code // // Copyright (C) 2009 Kevin O'Connor // Copyright (C) 2001-2008 the LGPL VGABios developers Team // // This file may be distributed under the terms of the GNU LGPLv3 license. -#include "stdvga.h" // vgahw_init +#include "stdvga.h" // stdvga_init #include "ioport.h" // outb #include "farptr.h" // SET_FARVAR -#include "biosvar.h" // GET_BDA -#include "vgabios.h" // VGAREG_* +#include "biosvar.h" // GET_GLOBAL +#include "util.h" // memcpy_far +#include "vbe.h" // VBE_RETURN_STATUS_FAILED // TODO // * replace direct in/out calls with wrapper functions @@ -19,22 +20,22 @@ * Attribute control ****************************************************************/ -void -vgahw_screen_disable(void) +static void +stdvga_screen_disable(void) { inb(VGAREG_ACTL_RESET); outb(0x00, VGAREG_ACTL_ADDRESS); } -void -vgahw_screen_enable(void) +static void +stdvga_screen_enable(void) { inb(VGAREG_ACTL_RESET); outb(0x20, VGAREG_ACTL_ADDRESS); } void -vgahw_set_border_color(u8 color) +stdvga_set_border_color(u8 color) { inb(VGAREG_ACTL_RESET); outb(0x00, VGAREG_ACTL_ADDRESS); @@ -57,7 +58,7 @@ vgahw_set_border_color(u8 color) } void -vgahw_set_overscan_border_color(u8 color) +stdvga_set_overscan_border_color(u8 color) { inb(VGAREG_ACTL_RESET); outb(0x11, VGAREG_ACTL_ADDRESS); @@ -66,7 +67,7 @@ vgahw_set_overscan_border_color(u8 color) } u8 -vgahw_get_overscan_border_color(void) +stdvga_get_overscan_border_color(void) { inb(VGAREG_ACTL_RESET); outb(0x11, VGAREG_ACTL_ADDRESS); @@ -77,7 +78,7 @@ vgahw_get_overscan_border_color(void) } void -vgahw_set_palette(u8 palid) +stdvga_set_palette(u8 palid) { inb(VGAREG_ACTL_RESET); palid &= 0x01; @@ -94,27 +95,7 @@ vgahw_set_palette(u8 palid) } void -vgahw_set_single_palette_reg(u8 reg, u8 val) -{ - inb(VGAREG_ACTL_RESET); - outb(reg, VGAREG_ACTL_ADDRESS); - outb(val, VGAREG_ACTL_WRITE_DATA); - outb(0x20, VGAREG_ACTL_ADDRESS); -} - -u8 -vgahw_get_single_palette_reg(u8 reg) -{ - inb(VGAREG_ACTL_RESET); - outb(reg, VGAREG_ACTL_ADDRESS); - u8 v = inb(VGAREG_ACTL_READ_DATA); - inb(VGAREG_ACTL_RESET); - outb(0x20, VGAREG_ACTL_ADDRESS); - return v; -} - -void -vgahw_set_all_palette_reg(u16 seg, u8 *data_far) +stdvga_set_all_palette_reg(u16 seg, u8 *data_far) { inb(VGAREG_ACTL_RESET); int i; @@ -130,7 +111,7 @@ vgahw_set_all_palette_reg(u16 seg, u8 *data_far) } void -vgahw_get_all_palette_reg(u16 seg, u8 *data_far) +stdvga_get_all_palette_reg(u16 seg, u8 *data_far) { int i; for (i = 0; i < 0x10; i++) { @@ -147,7 +128,7 @@ vgahw_get_all_palette_reg(u16 seg, u8 *data_far) } void -vgahw_toggle_intensity(u8 flag) +stdvga_toggle_intensity(u8 flag) { inb(VGAREG_ACTL_RESET); outb(0x10, VGAREG_ACTL_ADDRESS); @@ -157,7 +138,7 @@ vgahw_toggle_intensity(u8 flag) } void -vgahw_select_video_dac_color_page(u8 flag, u8 data) +stdvga_select_video_dac_color_page(u8 flag, u8 data) { inb(VGAREG_ACTL_RESET); outb(0x10, VGAREG_ACTL_ADDRESS); @@ -180,7 +161,7 @@ vgahw_select_video_dac_color_page(u8 flag, u8 data) } void -vgahw_read_video_dac_state(u8 *pmode, u8 *curpage) +stdvga_read_video_dac_state(u8 *pmode, u8 *curpage) { inb(VGAREG_ACTL_RESET); outb(0x10, VGAREG_ACTL_ADDRESS); @@ -205,90 +186,60 @@ vgahw_read_video_dac_state(u8 *pmode, u8 *curpage) ****************************************************************/ void -vgahw_set_dac_regs(u16 seg, u8 *data_far, u8 start, int count) -{ - outb(start, VGAREG_DAC_WRITE_ADDRESS); - while (count) { - outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA); - data_far++; - outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA); - data_far++; - outb(GET_FARVAR(seg, *data_far), VGAREG_DAC_DATA); - data_far++; - count--; - } -} - -void -vgahw_get_dac_regs(u16 seg, u8 *data_far, u8 start, int count) -{ - outb(start, VGAREG_DAC_READ_ADDRESS); - while (count) { - SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA)); - data_far++; - SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA)); - data_far++; - SET_FARVAR(seg, *data_far, inb(VGAREG_DAC_DATA)); - data_far++; - count--; - } -} - -void -vgahw_set_pel_mask(u8 val) -{ - outb(val, VGAREG_PEL_MASK); -} - -u8 -vgahw_get_pel_mask(void) -{ - return inb(VGAREG_PEL_MASK); -} - -void -vgahw_save_dac_state(u16 seg, struct saveDACcolors *info) +stdvga_save_dac_state(u16 seg, struct saveDACcolors *info) { /* XXX: check this */ SET_FARVAR(seg, info->rwmode, inb(VGAREG_DAC_STATE)); SET_FARVAR(seg, info->peladdr, inb(VGAREG_DAC_WRITE_ADDRESS)); SET_FARVAR(seg, info->pelmask, inb(VGAREG_PEL_MASK)); - vgahw_get_dac_regs(seg, info->dac, 0, 256); + stdvga_dac_read(seg, info->dac, 0, 256); SET_FARVAR(seg, info->color_select, 0); } void -vgahw_restore_dac_state(u16 seg, struct saveDACcolors *info) +stdvga_restore_dac_state(u16 seg, struct saveDACcolors *info) { outb(GET_FARVAR(seg, info->pelmask), VGAREG_PEL_MASK); - vgahw_set_dac_regs(seg, info->dac, 0, 256); + stdvga_dac_write(seg, info->dac, 0, 256); outb(GET_FARVAR(seg, info->peladdr), VGAREG_DAC_WRITE_ADDRESS); } +void +stdvga_perform_gray_scale_summing(u16 start, u16 count) +{ + stdvga_screen_disable(); + int i; + for (i = start; i < start+count; i++) { + u8 rgb[3]; + stdvga_dac_read(GET_SEG(SS), rgb, i, 1); + + // intensity = ( 0.3 * Red ) + ( 0.59 * Green ) + ( 0.11 * Blue ) + u16 intensity = ((77 * rgb[0] + 151 * rgb[1] + 28 * rgb[2]) + 0x80) >> 8; + if (intensity > 0x3f) + intensity = 0x3f; + + stdvga_dac_write(GET_SEG(SS), rgb, i, 1); + } + stdvga_screen_enable(); +} + /**************************************************************** * Memory control ****************************************************************/ void -vgahw_sequ_write(u8 index, u8 value) +stdvga_set_text_block_specifier(u8 spec) { - outw((value<<8) | index, VGAREG_SEQU_ADDRESS); + outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS); } -void -vgahw_grdc_write(u8 index, u8 value) -{ - outw((value<<8) | index, VGAREG_GRDC_ADDRESS); -} -void -vgahw_set_text_block_specifier(u8 spec) -{ - outw((spec << 8) | 0x03, VGAREG_SEQU_ADDRESS); -} +/**************************************************************** + * Font loading + ****************************************************************/ -void +static void get_font_access(void) { outw(0x0100, VGAREG_SEQU_ADDRESS); @@ -300,34 +251,50 @@ get_font_access(void) outw(0x0406, VGAREG_GRDC_ADDRESS); } -void +static void release_font_access(void) { outw(0x0100, VGAREG_SEQU_ADDRESS); outw(0x0302, VGAREG_SEQU_ADDRESS); outw(0x0304, VGAREG_SEQU_ADDRESS); outw(0x0300, VGAREG_SEQU_ADDRESS); - u16 v = (inw(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a; + u16 v = (inb(VGAREG_READ_MISC_OUTPUT) & 0x01) ? 0x0e : 0x0a; outw((v << 8) | 0x06, VGAREG_GRDC_ADDRESS); outw(0x0004, VGAREG_GRDC_ADDRESS); outw(0x1005, VGAREG_GRDC_ADDRESS); } +void +stdvga_load_font(u16 seg, void *src_far, u16 count + , u16 start, u8 destflags, u8 fontsize) +{ + get_font_access(); + u16 blockaddr = ((destflags & 0x03) << 14) + ((destflags & 0x04) << 11); + void *dest_far = (void*)(blockaddr + start*32); + u16 i; + for (i = 0; i < count; i++) + memcpy_far(SEG_GRAPH, dest_far + i*32 + , seg, src_far + i*fontsize, fontsize); + release_font_access(); +} + /**************************************************************** * CRTC registers ****************************************************************/ -static u16 -get_crtc(void) +u16 +stdvga_get_crtc(void) { - return GET_BDA(crtc_address); + if (stdvga_misc_read() & 1) + return VGAREG_VGA_CRTC_ADDRESS; + return VGAREG_MDA_CRTC_ADDRESS; } void -vgahw_set_cursor_shape(u8 start, u8 end) +stdvga_set_cursor_shape(u8 start, u8 end) { - u16 crtc_addr = get_crtc(); + u16 crtc_addr = stdvga_get_crtc(); outb(0x0a, crtc_addr); outb(start, crtc_addr + 1); outb(0x0b, crtc_addr); @@ -335,9 +302,9 @@ vgahw_set_cursor_shape(u8 start, u8 end) } void -vgahw_set_active_page(u16 address) +stdvga_set_active_page(u16 address) { - u16 crtc_addr = get_crtc(); + u16 crtc_addr = stdvga_get_crtc(); outb(0x0c, crtc_addr); outb((address & 0xff00) >> 8, crtc_addr + 1); outb(0x0d, crtc_addr); @@ -345,9 +312,9 @@ vgahw_set_active_page(u16 address) } void -vgahw_set_cursor_pos(u16 address) +stdvga_set_cursor_pos(u16 address) { - u16 crtc_addr = get_crtc(); + u16 crtc_addr = stdvga_get_crtc(); outb(0x0e, crtc_addr); outb((address & 0xff00) >> 8, crtc_addr + 1); outb(0x0f, crtc_addr); @@ -355,9 +322,9 @@ vgahw_set_cursor_pos(u16 address) } void -vgahw_set_scan_lines(u8 lines) +stdvga_set_scan_lines(u8 lines) { - u16 crtc_addr = get_crtc(); + u16 crtc_addr = stdvga_get_crtc(); outb(0x09, crtc_addr); u8 crtc_r9 = inb(crtc_addr + 1); crtc_r9 = (crtc_r9 & 0xe0) | (lines - 1); @@ -366,9 +333,9 @@ vgahw_set_scan_lines(u8 lines) // Get vertical display end u16 -vgahw_get_vde(void) +stdvga_get_vde(void) { - u16 crtc_addr = get_crtc(); + u16 crtc_addr = stdvga_get_crtc(); outb(0x12, crtc_addr); u16 vde = inb(crtc_addr + 1); outb(0x07, crtc_addr); @@ -383,9 +350,9 @@ vgahw_get_vde(void) ****************************************************************/ void -vgahw_save_state(u16 seg, struct saveVideoHardware *info) +stdvga_save_state(u16 seg, struct saveVideoHardware *info) { - u16 crtc_addr = get_crtc(); + u16 crtc_addr = stdvga_get_crtc(); SET_FARVAR(seg, info->sequ_index, inb(VGAREG_SEQU_ADDRESS)); SET_FARVAR(seg, info->crtc_index, inb(crtc_addr)); SET_FARVAR(seg, info->grdc_index, inb(VGAREG_GRDC_ADDRESS)); @@ -427,7 +394,7 @@ vgahw_save_state(u16 seg, struct saveVideoHardware *info) } void -vgahw_restore_state(u16 seg, struct saveVideoHardware *info) +stdvga_restore_state(u16 seg, struct saveVideoHardware *info) { // Reset Attribute Ctl flip-flop inb(VGAREG_ACTL_RESET); @@ -481,14 +448,59 @@ vgahw_restore_state(u16 seg, struct saveVideoHardware *info) outb(GET_FARVAR(seg, info->feature), crtc_addr - 0x4 + 0xa); } -void -vgahw_set_mode(struct vgamode_s *vmode_g) +static void +clear_screen(struct vgamode_s *vmode_g) +{ + switch (GET_GLOBAL(vmode_g->memmodel)) { + case MM_TEXT: + memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0720, 32*1024); + break; + case MM_CGA: + memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 32*1024); + break; + default: + // XXX - old code gets/sets/restores sequ register 2 to 0xf - + // but it should always be 0xf anyway. + memset16_far(GET_GLOBAL(vmode_g->sstart), 0, 0x0000, 64*1024); + } +} + +int +stdvga_set_mode(int mode, int flags) { + // find the entry in the video modes + struct vgamode_s *vmode_g = stdvga_find_mode(mode); + dprintf(1, "mode search %02x found %p\n", mode, vmode_g); + if (!vmode_g) + return VBE_RETURN_STATUS_FAILED; + struct stdvga_mode_s *stdmode_g = container_of( + vmode_g, struct stdvga_mode_s, info); + + // if palette loading (bit 3 of modeset ctl = 0) + if (!(flags & MF_NOPALETTE)) { // Set the PEL mask + stdvga_pelmask_write(GET_GLOBAL(stdmode_g->pelmask)); + + // From which palette + u8 *palette_g = GET_GLOBAL(stdmode_g->dac); + u16 palsize = GET_GLOBAL(stdmode_g->dacsize) / 3; + + // Always 256*3 values + stdvga_dac_write(get_global_seg(), palette_g, 0, palsize); + u16 i; + for (i = palsize; i < 0x0100; i++) { + static u8 rgb[3] VAR16; + stdvga_dac_write(get_global_seg(), rgb, i, 1); + } + + if (flags & MF_GRAYSUM) + stdvga_perform_gray_scale_summing(0x00, 0x100); + } + // Reset Attribute Ctl flip-flop inb(VGAREG_ACTL_RESET); // Set Attribute Ctl - u8 *regs = GET_GLOBAL(vmode_g->actl_regs); + u8 *regs = GET_GLOBAL(stdmode_g->actl_regs); u16 i; for (i = 0; i <= 0x13; i++) { outb(i, VGAREG_ACTL_ADDRESS); @@ -500,21 +512,21 @@ vgahw_set_mode(struct vgamode_s *vmode_g) // Set Sequencer Ctl outb(0, VGAREG_SEQU_ADDRESS); outb(0x03, VGAREG_SEQU_DATA); - regs = GET_GLOBAL(vmode_g->sequ_regs); + regs = GET_GLOBAL(stdmode_g->sequ_regs); for (i = 1; i <= 4; i++) { outb(i, VGAREG_SEQU_ADDRESS); outb(GET_GLOBAL(regs[i - 1]), VGAREG_SEQU_DATA); } // Set Grafx Ctl - regs = GET_GLOBAL(vmode_g->grdc_regs); + regs = GET_GLOBAL(stdmode_g->grdc_regs); for (i = 0; i <= 8; i++) { outb(i, VGAREG_GRDC_ADDRESS); outb(GET_GLOBAL(regs[i]), VGAREG_GRDC_DATA); } // Set CRTC address VGA or MDA - u8 miscreg = GET_GLOBAL(vmode_g->miscreg); + u8 miscreg = GET_GLOBAL(stdmode_g->miscreg); u16 crtc_addr = VGAREG_VGA_CRTC_ADDRESS; if (!(miscreg & 1)) crtc_addr = VGAREG_MDA_CRTC_ADDRESS; @@ -522,7 +534,7 @@ vgahw_set_mode(struct vgamode_s *vmode_g) // Disable CRTC write protection outw(0x0011, crtc_addr); // Set CRTC regs - regs = GET_GLOBAL(vmode_g->crtc_regs); + regs = GET_GLOBAL(stdmode_g->crtc_regs); for (i = 0; i <= 0x18; i++) { outb(i, crtc_addr); outb(GET_GLOBAL(regs[i]), crtc_addr + 1); @@ -534,6 +546,20 @@ vgahw_set_mode(struct vgamode_s *vmode_g) // Enable video outb(0x20, VGAREG_ACTL_ADDRESS); inb(VGAREG_ACTL_RESET); + + // Clear screen + if (!(flags & MF_NOCLEARMEM)) + clear_screen(vmode_g); + + // Write the fonts in memory + u8 memmodel = GET_GLOBAL(vmode_g->memmodel); + if (memmodel == MM_TEXT) + stdvga_load_font(get_global_seg(), vgafont16, 0x100, 0, 0, 16); + + // Setup BDA variables + modeswitch_set_bda(mode, flags, vmode_g); + + return 0; } @@ -542,19 +568,27 @@ vgahw_set_mode(struct vgamode_s *vmode_g) ****************************************************************/ void -vgahw_enable_video_addressing(u8 disable) +stdvga_list_modes(u16 seg, u16 *dest, u16 *last) +{ + SET_FARVAR(seg, *dest, 0xffff); +} + +void +stdvga_enable_video_addressing(u8 disable) { u8 v = (disable & 1) ? 0x00 : 0x02; u8 v2 = inb(VGAREG_READ_MISC_OUTPUT) & ~0x02; outb(v | v2, VGAREG_WRITE_MISC_OUTPUT); } -void -vgahw_init(void) +int +stdvga_init(void) { // switch to color mode and enable CPU access 480 lines outb(0xc3, VGAREG_WRITE_MISC_OUTPUT); // more than 64k 3C4/04 outb(0x04, VGAREG_SEQU_ADDRESS); outb(0x02, VGAREG_SEQU_DATA); + + return 0; }