A mechanism to allow (local) debuggers to learn about changes to the console layout, to adapt their internal state. Signed-Off-By: Jan Beulich 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 #include +#include #include #ifndef CONFIG_AMIGA #include @@ -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__ */