X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fvideo%2Fconsole%2Ffbcon.c;fp=drivers%2Fvideo%2Fconsole%2Ffbcon.c;h=041d069878612052cddc875fba3094ed28d1c32c;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=6165fd9662d5a1194f3d843b09e1bd1c717ef6f2;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 6165fd966..041d06987 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -58,12 +58,14 @@ #undef FBCONDEBUG +#include #include #include #include #include #include #include /* MSch: for IRQ probe */ +#include #include #include #include @@ -123,8 +125,6 @@ static int softback_lines; static int first_fb_vc; static int last_fb_vc = MAX_NR_CONSOLES - 1; static int fbcon_is_default = 1; -static int fbcon_has_exited; - /* font data */ static char fontname[40]; @@ -140,6 +140,7 @@ static const struct consw fb_con; #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row) +static void fbcon_free_font(struct display *); static int fbcon_set_origin(struct vc_data *); #define CURSOR_DRAW_DELAY (1) @@ -193,9 +194,6 @@ static void fbcon_redraw_move(struct vc_data *vc, struct display *p, int line, int count, int dy); static void fbcon_modechanged(struct fb_info *info); static void fbcon_set_all_vcs(struct fb_info *info); -static void fbcon_start(void); -static void fbcon_exit(void); -static struct class_device *fbcon_class_device; #ifdef CONFIG_MAC /* @@ -254,7 +252,7 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate) if (!ops || ops->currcon < 0 || rotate > 3) return; - for (i = first_fb_vc; i <= last_fb_vc; i++) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { vc = vc_cons[i].d; if (!vc || vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[i]] != info) @@ -391,18 +389,15 @@ static void fb_flashcursor(void *private) int c; int mode; - acquire_console_sem(); - if (ops && ops->currcon != -1) + if (ops->currcon != -1) vc = vc_cons[ops->currcon].d; if (!vc || !CON_IS_VISIBLE(vc) || fbcon_is_inactive(vc, info) || registered_fb[con2fb_map[vc->vc_num]] != info || - vc_cons[ops->currcon].d->vc_deccm != 1) { - release_console_sem(); + vc_cons[ops->currcon].d->vc_deccm != 1) return; - } - + acquire_console_sem(); p = &fb_display[vc->vc_num]; c = scr_readw((u16 *) vc->vc_pos); mode = (!ops->cursor_flash || ops->cursor_state.enable) ? @@ -471,7 +466,7 @@ static int __init fb_console_setup(char *this_opt) int i, j; if (!this_opt || !*this_opt) - return 1; + return 0; while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) @@ -486,10 +481,10 @@ static int __init fb_console_setup(char *this_opt) options++; } if (*options != ',') - return 1; + return 0; options++; } else - return 1; + return 0; } if (!strncmp(options, "map:", 4)) { @@ -501,7 +496,7 @@ static int __init fb_console_setup(char *this_opt) con2fb_map_boot[i] = (options[j++]-'0') % FB_MAX; } - return 1; + return 0; } if (!strncmp(options, "vc:", 3)) { @@ -523,7 +518,7 @@ static int __init fb_console_setup(char *this_opt) rotate = 0; } } - return 1; + return 0; } __setup("fbcon=", fb_console_setup); @@ -533,7 +528,7 @@ static int search_fb_in_map(int idx) { int i, retval = 0; - for (i = first_fb_vc; i <= last_fb_vc; i++) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { if (con2fb_map[i] == idx) retval = 1; } @@ -544,7 +539,7 @@ static int search_for_mapped_con(void) { int i, retval = 0; - for (i = first_fb_vc; i <= last_fb_vc; i++) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { if (con2fb_map[i] != -1) retval = 1; } @@ -566,7 +561,6 @@ static int fbcon_takeover(int show_logo) err = take_over_console(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); - if (err) { for (i = first_fb_vc; i <= last_fb_vc; i++) { con2fb_map[i] = -1; @@ -801,8 +795,8 @@ static int set_con2fb_map(int unit, int newidx, int user) if (oldidx == newidx) return 0; - if (!info || fbcon_has_exited) - return -EINVAL; + if (!info) + err = -EINVAL; if (!err && !search_for_mapped_con()) { info_idx = newidx; @@ -838,9 +832,6 @@ static int set_con2fb_map(int unit, int newidx, int user) con2fb_init_display(vc, info, unit, show_logo); } - if (!search_fb_in_map(info_idx)) - info_idx = newidx; - release_console_sem(); return err; } @@ -1043,7 +1034,6 @@ static const char *fbcon_startup(void) #endif /* CONFIG_MAC */ fbcon_add_cursor_timer(info); - fbcon_has_exited = 0; return display_desc; } @@ -1071,36 +1061,17 @@ static void fbcon_init(struct vc_data *vc, int init) /* If we are not the first console on this fb, copy the font from that console */ - t = &fb_display[fg_console]; - if (!p->fontdata) { - if (t->fontdata) { - struct vc_data *fvc = vc_cons[fg_console].d; - - vc->vc_font.data = (void *)(p->fontdata = - fvc->vc_font.data); - vc->vc_font.width = fvc->vc_font.width; - vc->vc_font.height = fvc->vc_font.height; - p->userfont = t->userfont; - - if (p->userfont) - REFCOUNT(p->fontdata)++; - } else { - const struct font_desc *font = NULL; - - if (!fontname[0] || !(font = find_font(fontname))) - font = get_default_font(info->var.xres, - info->var.yres); - vc->vc_font.width = font->width; - vc->vc_font.height = font->height; - vc->vc_font.data = (void *)(p->fontdata = font->data); - vc->vc_font.charcount = 256; /* FIXME Need to - support more fonts */ - } + t = &fb_display[svc->vc_num]; + if (!vc->vc_font.data) { + vc->vc_font.data = (void *)(p->fontdata = t->fontdata); + vc->vc_font.width = (*default_mode)->vc_font.width; + vc->vc_font.height = (*default_mode)->vc_font.height; + p->userfont = t->userfont; + if (p->userfont) + REFCOUNT(p->fontdata)++; } - if (p->userfont) charcnt = FNTCHARCNT(p->fontdata); - vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { @@ -1171,50 +1142,15 @@ static void fbcon_init(struct vc_data *vc, int init) set_blitting_type(vc, info); } - ops->p = &fb_display[fg_console]; -} - -static void fbcon_free_font(struct display *p) -{ - if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) - kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); - p->fontdata = NULL; - p->userfont = 0; } static void fbcon_deinit(struct vc_data *vc) { struct display *p = &fb_display[vc->vc_num]; - struct fb_info *info; - struct fbcon_ops *ops; - int idx; + if (info_idx != -1) + return; fbcon_free_font(p); - idx = con2fb_map[vc->vc_num]; - - if (idx == -1) - goto finished; - - info = registered_fb[idx]; - - if (!info) - goto finished; - - ops = info->fbcon_par; - - if (!ops) - goto finished; - - if (CON_IS_VISIBLE(vc)) - fbcon_del_cursor_timer(info); - - ops->flags &= ~FBCON_FLAGS_INIT; -finished: - - if (!con_is_bound(&fb_con)) - fbcon_exit(); - - return; } /* ====================================================================== */ @@ -1808,7 +1744,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, fbcon_redraw_move(vc, p, 0, t, count); ypan_up_redraw(vc, t, count); if (vc->vc_rows - b > 0) - fbcon_redraw_move(vc, p, b, + fbcon_redraw_move(vc, p, b - count, vc->vc_rows - b, b); } else fbcon_redraw_move(vc, p, t + count, b - t - count, t); @@ -2162,11 +2098,12 @@ static int fbcon_switch(struct vc_data *vc) if (info->fbops->fb_set_par) info->fbops->fb_set_par(info); - if (old_info != info) + if (old_info != info) { fbcon_del_cursor_timer(old_info); + fbcon_add_cursor_timer(info); + } } - fbcon_add_cursor_timer(info); set_blitting_type(vc, info); ops->cursor_reset = 1; @@ -2284,6 +2221,14 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) return 0; } +static void fbcon_free_font(struct display *p) +{ + if (p->userfont && p->fontdata && (--REFCOUNT(p->fontdata) == 0)) + kfree(p->fontdata - FONT_EXTRA_WORDS * sizeof(int)); + p->fontdata = NULL; + p->userfont = 0; +} + static int fbcon_get_font(struct vc_data *vc, struct console_font *font) { u8 *fontdata = vc->vc_font.data; @@ -2497,7 +2442,7 @@ static int fbcon_set_font(struct vc_data *vc, struct console_font *font, unsigne FNTSUM(new_data) = csum; /* Check if the same font is on some other console already */ - for (i = first_fb_vc; i <= last_fb_vc; i++) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { struct vc_data *tmp = vc_cons[i].d; if (fb_display[i].userfont && @@ -2685,7 +2630,7 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) scr_memcpyw((u16 *) q, (u16 *) p, vc->vc_size_row); } - softback_in = softback_curr = p; + softback_in = p; update_region(vc, vc->vc_origin, logo_lines * vc->vc_cols); } @@ -2822,7 +2767,7 @@ static void fbcon_set_all_vcs(struct fb_info *info) if (!ops || ops->currcon < 0) return; - for (i = first_fb_vc; i <= last_fb_vc; i++) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { vc = vc_cons[i].d; if (!vc || vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[i]] != info) @@ -2884,57 +2829,22 @@ static int fbcon_mode_deleted(struct fb_info *info, return found; } -static int fbcon_fb_unregistered(int idx) -{ - int i; - - for (i = first_fb_vc; i <= last_fb_vc; i++) { - if (con2fb_map[i] == idx) - con2fb_map[i] = -1; - } - - if (idx == info_idx) { - info_idx = -1; - - for (i = 0; i < FB_MAX; i++) { - if (registered_fb[i] != NULL) { - info_idx = i; - break; - } - } - } - - if (info_idx != -1) { - for (i = first_fb_vc; i <= last_fb_vc; i++) { - if (con2fb_map[i] == -1) - con2fb_map[i] = info_idx; - } - } - - if (!num_registered_fb) - unregister_con_driver(&fb_con); - - return 0; -} - static int fbcon_fb_registered(int idx) { int ret = 0, i; if (info_idx == -1) { - for (i = first_fb_vc; i <= last_fb_vc; i++) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { if (con2fb_map_boot[i] == idx) { info_idx = idx; break; } } - if (info_idx != -1) ret = fbcon_takeover(1); } else { - for (i = first_fb_vc; i <= last_fb_vc; i++) { - if (con2fb_map_boot[i] == idx && - con2fb_map[i] == -1) + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (con2fb_map_boot[i] == idx) set_con2fb_map(i, idx, 0); } } @@ -2971,7 +2881,7 @@ static void fbcon_new_modelist(struct fb_info *info) struct fb_var_screeninfo var; struct fb_videomode *mode; - for (i = first_fb_vc; i <= last_fb_vc; i++) { + for (i = 0; i < MAX_NR_CONSOLES; i++) { if (registered_fb[con2fb_map[i]] != info) continue; if (!fb_display[i].mode) @@ -2999,14 +2909,6 @@ static int fbcon_event_notify(struct notifier_block *self, struct fb_con2fbmap *con2fb; int ret = 0; - /* - * ignore all events except driver registration and deregistration - * if fbcon is not active - */ - if (fbcon_has_exited && !(action == FB_EVENT_FB_REGISTERED || - action == FB_EVENT_FB_UNREGISTERED)) - goto done; - switch(action) { case FB_EVENT_SUSPEND: fbcon_suspended(info); @@ -3027,9 +2929,6 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_FB_REGISTERED: ret = fbcon_fb_registered(info->node); break; - case FB_EVENT_FB_UNREGISTERED: - ret = fbcon_fb_unregistered(info->node); - break; case FB_EVENT_SET_CONSOLE_MAP: con2fb = event->data; ret = set_con2fb_map(con2fb->console - 1, @@ -3045,9 +2944,16 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_NEW_MODELIST: fbcon_new_modelist(info); break; + case FB_EVENT_SET_CON_ROTATE: + fbcon_rotate(info, *(int *)event->data); + break; + case FB_EVENT_GET_CON_ROTATE: + ret = fbcon_get_rotate(info); + break; + case FB_EVENT_SET_CON_ROTATE_ALL: + fbcon_rotate_all(info, *(int *)event->data); } -done: return ret; } @@ -3085,184 +2991,27 @@ static struct notifier_block fbcon_event_notifier = { .notifier_call = fbcon_event_notify, }; -static ssize_t store_rotate(struct class_device *class_device, - const char *buf, size_t count) -{ - struct fb_info *info; - int rotate, idx; - char **last = NULL; - - if (fbcon_has_exited) - return count; - - acquire_console_sem(); - idx = con2fb_map[fg_console]; - - if (idx == -1 || registered_fb[idx] == NULL) - goto err; - - info = registered_fb[idx]; - rotate = simple_strtoul(buf, last, 0); - fbcon_rotate(info, rotate); -err: - release_console_sem(); - return count; -} - -static ssize_t store_rotate_all(struct class_device *class_device, - const char *buf, size_t count) -{ - struct fb_info *info; - int rotate, idx; - char **last = NULL; - - if (fbcon_has_exited) - return count; - - acquire_console_sem(); - idx = con2fb_map[fg_console]; - - if (idx == -1 || registered_fb[idx] == NULL) - goto err; - - info = registered_fb[idx]; - rotate = simple_strtoul(buf, last, 0); - fbcon_rotate_all(info, rotate); -err: - release_console_sem(); - return count; -} - -static ssize_t show_rotate(struct class_device *class_device, char *buf) +static int __init fb_console_init(void) { - struct fb_info *info; - int rotate = 0, idx; - - if (fbcon_has_exited) - return 0; + int i; acquire_console_sem(); - idx = con2fb_map[fg_console]; - - if (idx == -1 || registered_fb[idx] == NULL) - goto err; - - info = registered_fb[idx]; - rotate = fbcon_get_rotate(info); -err: + fb_register_client(&fbcon_event_notifier); release_console_sem(); - return snprintf(buf, PAGE_SIZE, "%d\n", rotate); -} - -static struct class_device_attribute class_device_attrs[] = { - __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), - __ATTR(rotate_all, S_IWUSR, NULL, store_rotate_all), -}; - -static int fbcon_init_class_device(void) -{ - int i; - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_create_file(fbcon_class_device, - &class_device_attrs[i]); - return 0; -} + for (i = 0; i < MAX_NR_CONSOLES; i++) + con2fb_map[i] = -1; -static void fbcon_start(void) -{ if (num_registered_fb) { - int i; - - acquire_console_sem(); - for (i = 0; i < FB_MAX; i++) { if (registered_fb[i] != NULL) { info_idx = i; break; } } - - release_console_sem(); fbcon_takeover(0); } -} - -static void fbcon_exit(void) -{ - struct fb_info *info; - int i, j, mapped; - - if (fbcon_has_exited) - return; - -#ifdef CONFIG_ATARI - free_irq(IRQ_AUTO_4, fbcon_vbl_handler); -#endif -#ifdef CONFIG_MAC - if (MACH_IS_MAC && vbl_detected) - free_irq(IRQ_MAC_VBL, fbcon_vbl_handler); -#endif - - kfree((void *)softback_buf); - softback_buf = 0UL; - - for (i = 0; i < FB_MAX; i++) { - mapped = 0; - info = registered_fb[i]; - - if (info == NULL) - continue; - - for (j = first_fb_vc; j <= last_fb_vc; j++) { - if (con2fb_map[j] == i) - mapped = 1; - } - - if (mapped) { - if (info->fbops->fb_release) - info->fbops->fb_release(info, 0); - module_put(info->fbops->owner); - - if (info->fbcon_par) { - struct fbcon_ops *ops = info->fbcon_par; - - fbcon_del_cursor_timer(info); - kfree(ops->cursor_src); - kfree(info->fbcon_par); - info->fbcon_par = NULL; - } - - if (info->queue.func == fb_flashcursor) - info->queue.func = NULL; - } - } - - fbcon_has_exited = 1; -} -static int __init fb_console_init(void) -{ - int i; - - acquire_console_sem(); - fb_register_client(&fbcon_event_notifier); - fbcon_class_device = - class_device_create(fb_class, NULL, MKDEV(0, 0), NULL, "fbcon"); - - if (IS_ERR(fbcon_class_device)) { - printk(KERN_WARNING "Unable to create class_device " - "for fbcon; errno = %ld\n", - PTR_ERR(fbcon_class_device)); - fbcon_class_device = NULL; - } else - fbcon_init_class_device(); - - for (i = 0; i < MAX_NR_CONSOLES; i++) - con2fb_map[i] = -1; - - release_console_sem(); - fbcon_start(); return 0; } @@ -3270,24 +3019,12 @@ module_init(fb_console_init); #ifdef MODULE -static void __exit fbcon_deinit_class_device(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++) - class_device_remove_file(fbcon_class_device, - &class_device_attrs[i]); -} - static void __exit fb_console_exit(void) { acquire_console_sem(); fb_unregister_client(&fbcon_event_notifier); - fbcon_deinit_class_device(); - class_device_destroy(fb_class, MKDEV(0, 0)); - fbcon_exit(); release_console_sem(); - unregister_con_driver(&fb_con); + give_up_console(&fb_con); } module_exit(fb_console_exit);