A mechanism to allow (local) debuggers to learn about changes to the
console layout, to adapt their internal state.

Signed-Off-By: Jan Beulich <jbeulich@novell.com>

Index: 2.6.14-nlkd/drivers/video/console/fbcon.c
===================================================================
--- 2.6.14-nlkd.orig/drivers/video/console/fbcon.c	2005-11-09 10:40:17.000000000 +0100
+++ 2.6.14-nlkd/drivers/video/console/fbcon.c	2005-11-07 12:09:42.000000000 +0100
@@ -107,7 +107,7 @@ enum {
 };
 
 struct display fb_display[MAX_NR_CONSOLES];
-static signed char con2fb_map[MAX_NR_CONSOLES];
+signed char con2fb_map[MAX_NR_CONSOLES];
 static signed char con2fb_map_boot[MAX_NR_CONSOLES];
 static int logo_height;
 static int logo_lines;
@@ -211,6 +211,16 @@ static inline int fbcon_is_inactive(stru
 		vc->vc_mode != KD_TEXT || ops->graphics);
 }
 
+static inline int fbcon_set_par(struct fb_info *info)
+{
+	if (info->fbops->fb_set_par) {
+		if (fb_notify_clients(FB_EVENT_PRE_MODE_CHANGE, info, &info->var) == NOTIFY_BAD)
+			return -EINVAL;
+		info->fbops->fb_set_par(info);
+	}
+	return 0;
+}
+
 static inline int get_color(struct vc_data *vc, struct fb_info *info,
 	      u16 c, int is_fg)
 {
@@ -623,15 +633,19 @@ static int con2fb_release_oldinfo(struct
 	return err;
 }
 
-static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
+static int con2fb_init_display(struct vc_data *vc, struct fb_info *info,
 				int unit, int show_logo)
 {
 	struct fbcon_ops *ops = info->fbcon_par;
 
 	ops->currcon = fg_console;
 
-	if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT))
-		info->fbops->fb_set_par(info);
+	if (!(ops->flags & FBCON_FLAGS_INIT)) {
+		int err = fbcon_set_par(info);
+
+		if (err)
+			return err;
+	}
 
 	ops->flags |= FBCON_FLAGS_INIT;
 	ops->graphics = 0;
@@ -652,6 +666,7 @@ static void con2fb_init_display(struct v
 	}
 
 	update_screen(vc_cons[fg_console].d);
+	return 0;
 }
 
 /**
@@ -708,7 +723,7 @@ static int set_con2fb_map(int unit, int 
  		if (!found)
  			fbcon_add_cursor_timer(info);
  		con2fb_map_boot[unit] = newidx;
- 		con2fb_init_display(vc, info, unit, show_logo);
+ 		err = con2fb_init_display(vc, info, unit, show_logo);
 	}
 
 	release_console_sem();
@@ -980,9 +995,8 @@ static void fbcon_init(struct vc_data *v
 	 * We need to do it in fbcon_init() to prevent screen corruption.
 	 */
 	if (CON_IS_VISIBLE(vc)) {
-		if (info->fbops->fb_set_par &&
-		    !(ops->flags & FBCON_FLAGS_INIT))
-			info->fbops->fb_set_par(info);
+		if (!(ops->flags & FBCON_FLAGS_INIT) && fbcon_set_par(info) != 0)
+			return;
 		ops->flags |= FBCON_FLAGS_INIT;
 	}
 
@@ -1988,8 +2002,8 @@ static int fbcon_switch(struct vc_data *
 	fb_set_var(info, &var);
 
 	if (old_info != NULL && old_info != info) {
-		if (info->fbops->fb_set_par)
-			info->fbops->fb_set_par(info);
+		if (fbcon_set_par(info) != 0)
+			return 0;
 		fbcon_del_cursor_timer(old_info);
 		fbcon_add_cursor_timer(info);
 	}
@@ -2848,6 +2862,12 @@ static const struct consw fb_con = {
 	.con_resize             = fbcon_resize,
 };
 
+int is_fb_con(const struct consw *con)
+{
+	return con == &fb_con;
+}
+EXPORT_SYMBOL(is_fb_con);
+
 static struct notifier_block fbcon_event_notifier = {
 	.notifier_call	= fbcon_event_notify,
 };
@@ -2892,4 +2912,6 @@ module_exit(fb_console_exit);
 
 #endif
 
+EXPORT_SYMBOL(con2fb_map);
+
 MODULE_LICENSE("GPL");
Index: 2.6.14-nlkd/drivers/video/console/fbcon.h
===================================================================
--- 2.6.14-nlkd.orig/drivers/video/console/fbcon.h	2005-11-09 10:40:17.000000000 +0100
+++ 2.6.14-nlkd/drivers/video/console/fbcon.h	2005-11-07 10:07:01.000000000 +0100
@@ -168,4 +168,7 @@ extern void fbcon_set_tileops(struct vc_
 #endif
 extern void fbcon_set_bitops(struct fbcon_ops *ops);
 
+extern int is_fb_con(const struct consw *);
+extern signed char con2fb_map[];
+
 #endif /* _VIDEO_FBCON_H */
Index: 2.6.14-nlkd/drivers/video/console/vgacon.c
===================================================================
--- 2.6.14-nlkd.orig/drivers/video/console/vgacon.c	2005-11-09 10:40:17.000000000 +0100
+++ 2.6.14-nlkd/drivers/video/console/vgacon.c	2005-11-04 16:19:34.000000000 +0100
@@ -114,6 +114,8 @@ static int 		vga_video_font_height;
 static int 		vga_scan_lines;
 static unsigned int 	vga_rolled_over = 0;
 
+static struct notifier_block *vga_notifier_list;
+
 static int __init no_scroll(char *str)
 {
 	/*
@@ -962,6 +964,9 @@ static int vgacon_adjust_height(struct v
 	outb_p(fsr, vga_video_port_val);
 	outb_p(0x12, vga_video_port_reg);	/* Vertical display limit */
 	outb_p(vde, vga_video_port_val);
+	notifier_call_chain(&vga_notifier_list,
+			    VGACON_EVENT_PRE_ADJUST_HEIGHT | (vga_font_is_default ? VGACON_MC_DEFAULT_FONT : 0),
+			    (void*)(long)rows);
 	spin_unlock_irq(&vga_lock);
 
 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
@@ -1185,4 +1190,16 @@ const struct consw vga_con = {
 	.con_invert_region = vgacon_invert_region,
 };
 
+int vgacon_register_client(struct notifier_block *nb)
+{
+	return notifier_chain_register(&vga_notifier_list, nb);
+}
+EXPORT_SYMBOL(vgacon_register_client);
+
+int vgacon_unregister_client(struct notifier_block *nb)
+{
+	return notifier_chain_unregister(&vga_notifier_list, nb);
+}
+EXPORT_SYMBOL(vgacon_unregister_client);
+
 MODULE_LICENSE("GPL");
Index: 2.6.14-nlkd/drivers/video/fbmem.c
===================================================================
--- 2.6.14-nlkd.orig/drivers/video/fbmem.c	2005-11-09 10:40:17.000000000 +0100
+++ 2.6.14-nlkd/drivers/video/fbmem.c	2005-11-07 10:11:34.000000000 +0100
@@ -673,8 +673,17 @@ fb_set_var(struct fb_info *info, struct 
 
 		if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW) {
 			struct fb_videomode mode;
+			struct fb_event event;
 			int err = 0;
 
+			event.info = info;
+			event.data = var;
+			if (notifier_call_chain(&fb_notifier_list,
+						FB_EVENT_PRE_MODE_CHANGE,
+						&event) == NOTIFY_BAD)
+				return -EINVAL;
+
+
 			info->var = *var;
 			if (info->fbops->fb_set_par)
 				info->fbops->fb_set_par(info);
@@ -690,7 +699,6 @@ fb_set_var(struct fb_info *info, struct 
 				err = fb_add_videomode(&mode, &info->modelist);
 
 			if (!err && (flags & FBINFO_MISC_USEREVENT)) {
-				struct fb_event event;
 				int evnt = (var->activate & FB_ACTIVATE_ALL) ?
 					FB_EVENT_MODE_CHANGE_ALL :
 					FB_EVENT_MODE_CHANGE;
@@ -1117,6 +1125,21 @@ int fb_unregister_client(struct notifier
 }
 
 /**
+ *	fb_notify_clients - notify all clients
+ *	@what: event type
+ *	@info: framebuffer affected
+ *	@data: event specific data
+ */
+int fb_notify_clients(unsigned long what, struct fb_info *info, void *data)
+{
+	struct fb_event event;
+
+	event.info = info;
+	event.data = data;
+	return notifier_call_chain(&fb_notifier_list, what, &event);
+}
+
+/**
  *	fb_set_suspend - low level driver signals suspend
  *	@info: framebuffer affected
  *	@state: 0 = resuming, !=0 = suspending
@@ -1321,6 +1344,7 @@ EXPORT_SYMBOL(fb_get_buffer_offset);
 EXPORT_SYMBOL(fb_set_suspend);
 EXPORT_SYMBOL(fb_register_client);
 EXPORT_SYMBOL(fb_unregister_client);
+EXPORT_SYMBOL(fb_notify_clients);
 EXPORT_SYMBOL(fb_get_options);
 EXPORT_SYMBOL(fb_new_modelist);
 
Index: 2.6.14-nlkd/include/linux/fb.h
===================================================================
--- 2.6.14-nlkd.orig/include/linux/fb.h	2005-11-09 10:40:17.000000000 +0100
+++ 2.6.14-nlkd/include/linux/fb.h	2005-11-09 10:28:14.000000000 +0100
@@ -475,6 +475,8 @@ struct fb_cursor_user {
  * Register/unregister for framebuffer events
  */
 
+/*	The resolution of the passed in fb_info is about to change */
+#define FB_EVENT_PRE_MODE_CHANGE	0x00
 /*	The resolution of the passed in fb_info about to change */ 
 #define FB_EVENT_MODE_CHANGE		0x01
 /*	The display on this fb_info is beeing suspended, no access to the
@@ -509,6 +511,7 @@ struct fb_event {
 
 extern int fb_register_client(struct notifier_block *nb);
 extern int fb_unregister_client(struct notifier_block *nb);
+extern int fb_notify_clients(unsigned long, struct fb_info *, void *);
 
 /*
  * Pixmap structure definition
Index: 2.6.14-nlkd/include/video/vga.h
===================================================================
--- 2.6.14-nlkd.orig/include/video/vga.h	2005-11-09 10:40:17.000000000 +0100
+++ 2.6.14-nlkd/include/video/vga.h	2005-11-04 16:19:34.000000000 +0100
@@ -19,6 +19,7 @@
 
 #include <linux/config.h>
 #include <linux/types.h>
+#include <linux/notifier.h>
 #include <asm/io.h>
 #ifndef CONFIG_AMIGA
 #include <asm/vga.h>
@@ -479,4 +480,12 @@ static inline void vga_mm_wattr (void __
         vga_mm_w (regbase, VGA_ATT_W, val);
 }
 
+#define VGACON_EVENT_PRE_ADJUST_HEIGHT 0x01
+
+#define VGACON_EVENT_FLAGS_MASK 0xff000000
+#define VGACON_MC_DEFAULT_FONT 0x80000000
+
+int vgacon_register_client(struct notifier_block *);
+int vgacon_unregister_client(struct notifier_block *);
+
 #endif /* __linux_video_vga_h__ */
