[PATCH 1/2] i386/pc386/VESA framebuffer driver: modified and extended initialization options

Jan Dolezal dolezj21 at fel.cvut.cz
Sat May 23 17:32:34 UTC 2015


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

diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am
index 1da40f2..56272e2 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 0000000..948ffee
--- /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:
+ * "<resX>x<resY>[-<bpp>]" - 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 d6fd174..33dfc35 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=<resX>x<resY>[-<bpp>]"
- * 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 at gmail.com)
  */
 
 #include <bsp.h>
 
+#include <bsp/fb_default_mode.h>
 #include <bsp/fb_vesa.h>
 #include <bsp/realmode_int.h>
 
@@ -53,6 +60,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:
+ * "<resX>x<resY>[-<bpp>]" - 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.
  *
  * utilizes switches to real mode interrupts and therefore must be
@@ -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=<resX>x<resY>[-<bpp>]
+ *  <resX>x<resY>[-<bpp>]
  *  numbers <resX>, <resY> and <bpp> 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=<resX>x<resY>[-<bpp>]
+ *  numbers <resX>, <resY> and <bpp> 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 5305fbe..fa7bb69 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
-- 
1.9.1



More information about the devel mailing list