From 56399c3bc8b924b5e9266fd73b5b4eed0746adf3 Mon Sep 17 00:00:00 2001 From: Jan Dolezal Date: Sat, 23 May 2015 12:32:00 -0500 Subject: i386/pc386/VESA framebuffer driver: modified and extended initialization options driver is not initialized by default initialization is possible through multiboot command line option or through the string variable (see fb_default_mode.h) set in user's module allowing the driver to evaluate this variable after the two modules are linked together --- c/src/lib/libbsp/i386/pc386/Makefile.am | 1 + .../libbsp/i386/pc386/console/fb_default_mode.h | 25 +++ c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c | 182 ++++++++++++++++----- c/src/lib/libbsp/i386/pc386/preinstall.am | 4 + 4 files changed, 172 insertions(+), 40 deletions(-) create mode 100644 c/src/lib/libbsp/i386/pc386/console/fb_default_mode.h (limited to 'c/src/lib') diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am index 1da40f2e32..56272e26bf 100644 --- a/c/src/lib/libbsp/i386/pc386/Makefile.am +++ b/c/src/lib/libbsp/i386/pc386/Makefile.am @@ -96,6 +96,7 @@ libbsp_a_SOURCES += console/vt.c libbsp_a_SOURCES += console/videoAsm.S libbsp_a_SOURCES += console/kbd_parser.c libbsp_a_SOURCES += console/vgacons.c +include_bsp_HEADERS += console/fb_default_mode.h if USE_VBE_RM include_bsp_HEADERS += include/vbe3.h include_HEADERS += include/edid.h diff --git a/c/src/lib/libbsp/i386/pc386/console/fb_default_mode.h b/c/src/lib/libbsp/i386/pc386/console/fb_default_mode.h new file mode 100644 index 0000000000..948ffee5b6 --- /dev/null +++ b/c/src/lib/libbsp/i386/pc386/console/fb_default_mode.h @@ -0,0 +1,25 @@ +/** + * @file fb_default_mode.h + * + * @ingroup i386_pc386 + * + * @brief Variable for the definition of the default graphical mode to be + * initialized. + */ + +/* + * @brief Allows to enable initialization of specific framebuffer driver (e.g. + * VESA real mode) from an application by setting the value of this variable + * to non null value in user's module. The value of this variable will be then + * updated when linked with an application's object. + * + * Further the value should point to string in the following format: + * "x[-]" - e.g. "1024x768-32" + * "auto" - select the graphic mode automatically + * "none" / "off" - do not initialize the driver + * the given parameters are used if applicable. + * + * Command line argument "--video=" has priority over this string if + * it is read/implemented by the driver. + */ +extern const char * const rtems_fb_default_mode; diff --git a/c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c b/c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c index d6fd174c04..33dfc354c4 100644 --- a/c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c +++ b/c/src/lib/libbsp/i386/pc386/console/fb_vesa_rm.c @@ -19,8 +19,14 @@ * * Driver reads parameter from multiboot command line to setup video: * "--video=x[-]" - * If cmdline parameter is not specified an attempt for obtaining - * resolution from display attached is made. + * "--video=auto" - try EDID to find mode that fits the display attached best + * "--video=none" / "--video=off" - do not initialize the driver + * If cmdline parameter is not specified the rtems_fb_default_mode + * variable content is tested (see doc below). + * Command line option has higher priority. rtems_fb_default_mode is probed + * only if cmdline "--video=" is not specified at all. + * + * If neither of the above options is specified the driver is not initialized. */ /* @@ -31,13 +37,14 @@ * found in the file LICENSE in this distribution or at * http://www.rtems.org/license/LICENSE. * - * The code for rtems_buffer_* functions were greatly + * The code for rtems_buffer_* functions was greatly * inspired or coppied from: * - RTEMS fb_cirrus.c - Alexandru-Sever Horin (alex.sever.h@gmail.com) */ #include +#include #include #include @@ -52,6 +59,22 @@ #define FB_VESA_NAME "FB_VESA_RM" +/** + * @brief Allows to enable initialization of VESA real mode driver from + * an application by setting the value of this variable to non null value in + * user's module. The value of this variable will be then updated + * when linked with application's object. + * + * Further the value should point to string in the following format: + * "x[-]" - e.g. "1024x768-32" + * "auto" - try EDID to find mode that fits the display attached best + * "none" / "off" - do not initialize the driver + * the given parameters are used if applicable. + * + * Command line argument "--video=" has priority over this string. + */ +const char * const rtems_fb_default_mode; + /** * @brief Initializes VBE framebuffer during bootup. * @@ -70,7 +93,7 @@ static pthread_mutex_t vesa_mutex = PTHREAD_MUTEX_INITIALIZER; static struct fb_var_screeninfo fb_var; static struct fb_fix_screeninfo fb_fix; -static uint16_t vbe_used_mode; +static int32_t vbe_used_mode; uint32_t VBE_controller_information( VBE_vbe_info_block *info_block, uint16_t queried_VBE_Version) @@ -212,6 +235,14 @@ typedef struct { uint8_t bpp; } Mode_params; +typedef enum { + NO_SUITABLE_MODE = -1, + BAD_FORMAT = -2, + AUTO_SELECT = -3, + DONT_INIT = -4, + NO_MODE_REQ = -5, +} mode_err_ret_val; + /** * @brief Find mode by resolution in the given list of modes * @@ -229,7 +260,7 @@ typedef struct { * @retval mode number satisfying given parameters * @retval -1 no suitable mode found */ -static uint16_t find_mode_by_resolution(Mode_params *mode_list, +static int32_t find_mode_by_resolution(Mode_params *mode_list, uint8_t list_length, Mode_params *searched_resolution) { @@ -249,37 +280,48 @@ static uint16_t find_mode_by_resolution(Mode_params *mode_list, } i++; } - return -1; + return NO_SUITABLE_MODE; } /** - * @brief Find mode given within command line. + * @brief Find mode given in string format. * - * Parse command line option "--video=" if available. * expected format - * --video=x[-] + * x[-] * numbers , and are decadic * * @param[in] mode_list list of modes to be searched * @param[in] list_length number of modes in the list + * @param[in] video_string string to be parsed * @retval video mode number to be set - * @retval -1 on parsing error or when no suitable mode found + * @retval -1 no suitable mode found + * @retval -2 bad format of the video_string + * @retval -3 automatic mode selection requested + * @retval -4 request to not initialize graphics + * @retval -5 no mode requested/empty video string */ -static uint16_t find_mode_using_cmdline(Mode_params *mode_list, - uint8_t list_length) +static int32_t find_mode_from_string(Mode_params *mode_list, + uint8_t list_length, + const char *video_string) { const char* opt; Mode_params cmdline_mode; char* endptr; - cmdline_mode.bpp = 0; - opt = bsp_cmdline_arg("--video="); + cmdline_mode.bpp = 16; /* default bpp */ + opt = video_string; if (opt) { - opt += sizeof("--video=")-1; + if (strncmp(opt, "auto", 4) == 0) + return AUTO_SELECT; + if (strncmp(opt, "none", 4) == 0 || + strncmp(opt, "off", 3) == 0) + { + return DONT_INIT; + } cmdline_mode.resX = strtol(opt, &endptr, 10); if (*endptr != 'x') { - return -1; + return BAD_FORMAT; } opt = endptr+1; cmdline_mode.resY = strtol(opt, &endptr, 10); @@ -294,21 +336,49 @@ static uint16_t find_mode_using_cmdline(Mode_params *mode_list, cmdline_mode.bpp = strtol(opt, &endptr, 10); if (*endptr != ' ') { - return -1; + return BAD_FORMAT; } } case ' ': case 0: break; default: - return -1; + return BAD_FORMAT; } - if (find_mode_by_resolution(mode_list, list_length, &cmdline_mode) != - (uint16_t)-1) - return cmdline_mode.mode_number; + return find_mode_by_resolution(mode_list, list_length, &cmdline_mode); } - return -1; + return NO_MODE_REQ; +} + +/** + * @brief Find mode given within command line. + * + * Parse command line option "--video=" if available. + * expected format + * --video=x[-] + * numbers , and are decadic + * + * @param[in] mode_list list of modes to be searched + * @param[in] list_length number of modes in the list + * @retval video mode number to be set + * @retval -1 no suitable mode found + * @retval -2 bad format of the video_string + * @retval -3 automatic mode selection requested + * @retval -4 request to not initialize graphics + * @retval -5 no mode requested/empty video string + */ +static int32_t find_mode_using_cmdline(Mode_params *mode_list, + uint8_t list_length) +{ + const char* opt; + opt = bsp_cmdline_arg("--video="); + if (opt) + { + opt += sizeof("--video=")-1; + return find_mode_from_string(mode_list, list_length, opt); + } + return NO_MODE_REQ; } /** @@ -319,7 +389,7 @@ static uint16_t find_mode_using_cmdline(Mode_params *mode_list, * @retval video mode number to be set * @retval -1 on parsing error or when no suitable mode found */ -static uint16_t find_mode_using_EDID( Mode_params *mode_list, +static int32_t find_mode_using_EDID( Mode_params *mode_list, uint8_t list_length) { EDID_edid1 edid; @@ -363,7 +433,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resX = DTD_horizontal_active(&edid.dtd_md[0].dtd); EDIDmode.resY = DTD_vertical_active(&edid.dtd_md[0].dtd); if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; index++; @@ -410,7 +480,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, } EDIDmode.resX = (EDIDmode.resX/8)*8; if (find_mode_by_resolution( - mode_list, list_length, &EDIDmode) != (uint16_t)-1) + mode_list, list_length, &EDIDmode) != -1) return EDIDmode.mode_number; j++; @@ -450,7 +520,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, break; } if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; index++; @@ -465,7 +535,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resY = 1024; EDIDmode.bpp = 0; if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; } if (edid1_established_tim(&edid, EST_1152x870_75Hz)) @@ -474,7 +544,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resY = 870; EDIDmode.bpp = 0; if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; } if (edid1_established_tim(&edid, EST_1024x768_75Hz) || @@ -486,7 +556,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resY = 768; EDIDmode.bpp = 0; if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; } if (edid1_established_tim(&edid, EST_832x624_75Hz)) @@ -495,7 +565,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resY = 624; EDIDmode.bpp = 0; if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; } if (edid1_established_tim(&edid, EST_800x600_60Hz) || @@ -507,7 +577,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resY = 600; EDIDmode.bpp = 0; if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; } if (edid1_established_tim(&edid, EST_720x400_88Hz) || @@ -517,7 +587,7 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resY = 400; EDIDmode.bpp = 0; if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; } if (edid1_established_tim(&edid, EST_640x480_75Hz) || @@ -529,13 +599,13 @@ static uint16_t find_mode_using_EDID( Mode_params *mode_list, EDIDmode.resY = 480; EDIDmode.bpp = 0; if (find_mode_by_resolution(mode_list, list_length, &EDIDmode) != - (uint16_t)-1) + -1) return EDIDmode.mode_number; } } else printk(FB_VESA_NAME " error reading EDID: unsupported version\n"); - return (uint16_t)-1; + return -1; } void vesa_realmode_bootup_init(void) @@ -569,6 +639,7 @@ void vesa_realmode_bootup_init(void) uint16_t *modeNOPtr = (uint16_t*) i386_Real_to_physical(*(vmpSegOff+1), *vmpSegOff); uint16_t iterator = 0; + if (*(uint16_t*)vib->VideoModePtr == VBE_STUB_VideoModeList) { printk(FB_VESA_NAME " VBE Core not implemented!\n"); @@ -618,6 +689,40 @@ void vesa_realmode_bootup_init(void) sorted_mode_params[nextFilteredMode].mode_number = 0; uint8_t number_of_modes = nextFilteredMode; + + /* first search for video argument in multiboot options */ + vbe_used_mode = find_mode_using_cmdline(sorted_mode_params, + number_of_modes); + + if (vbe_used_mode == NO_MODE_REQ) { + vbe_used_mode = find_mode_from_string(sorted_mode_params, + number_of_modes, rtems_fb_default_mode); + if (vbe_used_mode != NO_MODE_REQ) { + printk(FB_VESA_NAME " using application option to select" + " video mode\n"); + } + } + else + { + printk(FB_VESA_NAME " using command line option '--video='" + "to select video mode\n"); + } + + switch (vbe_used_mode) { + case NO_SUITABLE_MODE: + printk(FB_VESA_NAME " requested mode not found\n"); + return; + case BAD_FORMAT: + printk(FB_VESA_NAME " bad format of video requested\n"); + return; + case DONT_INIT: + printk(FB_VESA_NAME " selected not to initialize graphics\n"); + return; + case NO_MODE_REQ: + printk(FB_VESA_NAME " not initialized, no video selected\n"); + return; + } + /* sort filtered modes */ Mode_params modeXchgPlace; iterator = 0; @@ -657,17 +762,14 @@ void vesa_realmode_bootup_init(void) iterator++; } - /* first search for video argument in multiboot options */ - vbe_used_mode = find_mode_using_cmdline(sorted_mode_params, - number_of_modes); - if (vbe_used_mode == (uint16_t)-1) + if (vbe_used_mode == AUTO_SELECT) { - printk(FB_VESA_NAME " video on command line not provided" + printk(FB_VESA_NAME " auto video mode selected" "\n\ttrying EDID ...\n"); /* second search monitor for good resolution */ vbe_used_mode = find_mode_using_EDID(sorted_mode_params, number_of_modes); - if (vbe_used_mode == (uint16_t)-1) + if (vbe_used_mode == -1) { printk(FB_VESA_NAME" monitor's EDID video parameters not supported" "\n\tusing mode with highest resolution, bpp\n"); diff --git a/c/src/lib/libbsp/i386/pc386/preinstall.am b/c/src/lib/libbsp/i386/pc386/preinstall.am index 5305fbeb90..fa7bb6972c 100644 --- a/c/src/lib/libbsp/i386/pc386/preinstall.am +++ b/c/src/lib/libbsp/i386/pc386/preinstall.am @@ -140,6 +140,10 @@ $(PROJECT_INCLUDE)/rtems/vgacons.h: console/vgacons.h $(PROJECT_INCLUDE)/rtems/$ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/vgacons.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/vgacons.h +$(PROJECT_INCLUDE)/bsp/fb_default_mode.h: console/fb_default_mode.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/fb_default_mode.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/fb_default_mode.h + if USE_VBE_RM $(PROJECT_INCLUDE)/bsp/vbe3.h: include/vbe3.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/vbe3.h -- cgit v1.2.3