aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntonino A. Daplas <adaplas@gmail.com>2006-06-26 03:27:02 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 12:58:32 -0400
commit50ec42edd9784fad6a37b05be03064ea24098db6 (patch)
treed4f145507e36bf52a5f26a8aad10af46392f36fc
parent9dac73a4ec2c0a791bbfc6630dc4629ce11e68b9 (diff)
[PATCH] Detaching fbcon: fix vgacon to allow retaking of the console
One of the limitations of the framebuffer console system is its inablity to unload or detach itself from the console layer. And once it loads, it also locks in framebuffer drivers preventing their unload. Although the con2fbmap utility does provide a means to unload individual drivers, it requires that at least one framebuffer driver is loaded for use by fbcon. With this change, it is possible to detach fbcon from the console layer. If it is detached, it will reattach the boot console driver (which is permanently loaded) back to the console layer so the system can continue to work. As a consequence, fbcon will also decrement its reference count of individual framebuffer drivers, allowing all of these drivers to be unloaded even if fbcon is still loaded. Unless you use drivers that restores the display to text mode (rivafb and i810fb, for example), detaching fbcon does require assistance from userspace tools (ie, vbetools) for text mode to be restored completely. Without the help of these tools, fbcon will leave the VGA console corrupted. The methods that can be used will be described in Documentation/fb/fbcon.txt. Because the vt layer also increments the module reference count for each console driver, fbcon cannot be directly unloaded. It must be detached first prior to unload. Similarly, fbcon can be reattached to the console layer without having to reload the module. A nice feature if fbcon is compiled statically. Attaching and detaching fbcon is done via sysfs attributes. A class device entry for fbcon is created in /sys/class/graphics. The two attributes that controls this feature are detach and attach. Two other attributes that are piggybacked under /sys/class/graphics/fb[n] that are fbcon-specific, 'con_rotate' and 'con_rotate_all' are moved to fbcon. They are renamed as 'rotate' and 'rotate_all' respectively. Overall, this feature is a great help for developers working in the framebuffer or console layer. There is not need to continually reboot the kernel for every small change. It is also useful for regular users who wants to choose between a graphical console or a text console without having to reboot. Example usage for x86: /* start in text mode */ modprobe xxxfb modprobe fbcon /* graphical mode with fbcon using xxxfb */ echo 1 > /sys/class/graphics/fbcon/detach /* back to text mode, will produce corrupt display unless vbetool is used */ rmmod xxxfb modprobe yyyfb /* back to graphical mode with fbcon using yyyfb */ Before trying out this feature, please read Documentation/fb/fbcon.txt. This patch: In order for fbcon to detach itself from the console layer, vgacon, which is a boot console driver, must be fixed so it can retake the console multiple times, not just during init. The following needs to be done: - remove __init from the vgacon_startup, this is called again by take_over_console(). - vc->rows and vc->cols are set manually by vgacon during init. After init, vc_resize() can be used - make sure the scrollback_buffer is not reallocated Signed-off-by: Antonino Daplas <adaplas@pol.net> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--drivers/video/console/vgacon.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c
index e64d42e2449e..f32b590730f2 100644
--- a/drivers/video/console/vgacon.c
+++ b/drivers/video/console/vgacon.c
@@ -114,6 +114,7 @@ static int vga_512_chars;
114static int vga_video_font_height; 114static int vga_video_font_height;
115static int vga_scan_lines; 115static int vga_scan_lines;
116static unsigned int vga_rolled_over = 0; 116static unsigned int vga_rolled_over = 0;
117static int vga_init_done;
117 118
118static int __init no_scroll(char *str) 119static int __init no_scroll(char *str)
119{ 120{
@@ -190,7 +191,7 @@ static void vgacon_scrollback_init(int pitch)
190 } 191 }
191} 192}
192 193
193static void __init vgacon_scrollback_startup(void) 194static void vgacon_scrollback_startup(void)
194{ 195{
195 vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE 196 vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE
196 * 1024); 197 * 1024);
@@ -355,7 +356,7 @@ static int vgacon_scrolldelta(struct vc_data *c, int lines)
355} 356}
356#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */ 357#endif /* CONFIG_VGACON_SOFT_SCROLLBACK */
357 358
358static const char __init *vgacon_startup(void) 359static const char *vgacon_startup(void)
359{ 360{
360 const char *display_desc = NULL; 361 const char *display_desc = NULL;
361 u16 saved1, saved2; 362 u16 saved1, saved2;
@@ -523,7 +524,12 @@ static const char __init *vgacon_startup(void)
523 524
524 vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH; 525 vgacon_xres = ORIG_VIDEO_COLS * VGA_FONTWIDTH;
525 vgacon_yres = vga_scan_lines; 526 vgacon_yres = vga_scan_lines;
526 vgacon_scrollback_startup(); 527
528 if (!vga_init_done) {
529 vgacon_scrollback_startup();
530 vga_init_done = 1;
531 }
532
527 return display_desc; 533 return display_desc;
528} 534}
529 535
@@ -531,10 +537,20 @@ static void vgacon_init(struct vc_data *c, int init)
531{ 537{
532 unsigned long p; 538 unsigned long p;
533 539
534 /* We cannot be loaded as a module, therefore init is always 1 */ 540 /*
541 * We cannot be loaded as a module, therefore init is always 1,
542 * but vgacon_init can be called more than once, and init will
543 * not be 1.
544 */
535 c->vc_can_do_color = vga_can_do_color; 545 c->vc_can_do_color = vga_can_do_color;
536 c->vc_cols = vga_video_num_columns; 546
537 c->vc_rows = vga_video_num_lines; 547 /* set dimensions manually if init != 0 since vc_resize() will fail */
548 if (init) {
549 c->vc_cols = vga_video_num_columns;
550 c->vc_rows = vga_video_num_lines;
551 } else
552 vc_resize(c, vga_video_num_columns, vga_video_num_lines);
553
538 c->vc_scan_lines = vga_scan_lines; 554 c->vc_scan_lines = vga_scan_lines;
539 c->vc_font.height = vga_video_font_height; 555 c->vc_font.height = vga_video_font_height;
540 c->vc_complement_mask = 0x7700; 556 c->vc_complement_mask = 0x7700;