|
@@ -194,7 +194,8 @@ 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
|
|
@@ -391,15 +392,18 @@ static void fb_flashcursor(void *private)
|
|
|
int c;
|
|
|
int mode;
|
|
|
|
|
|
- if (ops->currcon != -1)
|
|
|
+ acquire_console_sem();
|
|
|
+ if (ops && 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)
|
|
|
+ vc_cons[ops->currcon].d->vc_deccm != 1) {
|
|
|
+ release_console_sem();
|
|
|
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) ?
|
|
@@ -2101,12 +2105,11 @@ 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;
|
|
|
|
|
@@ -2847,7 +2850,8 @@ static int fbcon_fb_registered(int idx)
|
|
|
ret = fbcon_takeover(1);
|
|
|
} else {
|
|
|
for (i = 0; i < MAX_NR_CONSOLES; i++) {
|
|
|
- if (con2fb_map_boot[i] == idx)
|
|
|
+ if (con2fb_map_boot[i] == idx &&
|
|
|
+ con2fb_map[i] == -1)
|
|
|
set_con2fb_map(i, idx, 0);
|
|
|
}
|
|
|
}
|
|
@@ -3046,9 +3050,32 @@ err:
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", rotate);
|
|
|
}
|
|
|
|
|
|
+static ssize_t store_attach(struct class_device *class_device,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ if (info_idx == -1)
|
|
|
+ fbcon_start();
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t store_detach(struct class_device *class_device,
|
|
|
+ const char *buf, size_t count)
|
|
|
+{
|
|
|
+ if (info_idx != -1) {
|
|
|
+ fbcon_exit();
|
|
|
+ give_up_console(&fb_con);
|
|
|
+ }
|
|
|
+
|
|
|
+ info_idx = -1;
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
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),
|
|
|
+ __ATTR(attach, S_IWUSR, NULL, store_attach),
|
|
|
+ __ATTR(detach, S_IWUSR, NULL, store_detach),
|
|
|
};
|
|
|
|
|
|
static int fbcon_init_class_device(void)
|
|
@@ -3061,67 +3088,31 @@ static int fbcon_init_class_device(void)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int __init fb_console_init(void)
|
|
|
+static void fbcon_start(void)
|
|
|
{
|
|
|
- int i;
|
|
|
-
|
|
|
- acquire_console_sem();
|
|
|
- fb_register_client(&fbcon_event_notifier);
|
|
|
- release_console_sem();
|
|
|
-
|
|
|
- fbcon_class_device =
|
|
|
- class_device_create(fb_class, NULL,
|
|
|
- MKDEV(FB_MAJOR, FB_MAX), 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();
|
|
|
+ if (num_registered_fb) {
|
|
|
+ int i;
|
|
|
|
|
|
- for (i = 0; i < MAX_NR_CONSOLES; i++)
|
|
|
- con2fb_map[i] = -1;
|
|
|
+ acquire_console_sem();
|
|
|
|
|
|
- if (num_registered_fb) {
|
|
|
for (i = 0; i < FB_MAX; i++) {
|
|
|
if (registered_fb[i] != NULL) {
|
|
|
info_idx = i;
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ release_console_sem();
|
|
|
fbcon_takeover(0);
|
|
|
}
|
|
|
-
|
|
|
- return 0;
|
|
|
-}
|
|
|
-
|
|
|
-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 fbcon_exit(void)
|
|
|
+static void fbcon_exit(void)
|
|
|
{
|
|
|
struct fb_info *info;
|
|
|
int i, j, mapped;
|
|
|
|
|
|
- for (i = 0; i < FB_MAX; i++) {
|
|
|
- info = registered_fb[i];
|
|
|
-
|
|
|
- if (info && info->fbcon_par)
|
|
|
- fbcon_del_cursor_timer(info);
|
|
|
- }
|
|
|
-
|
|
|
+ acquire_console_sem();
|
|
|
#ifdef CONFIG_ATARI
|
|
|
free_irq(IRQ_AUTO_4, fbcon_vbl_handler);
|
|
|
#endif
|
|
@@ -3131,6 +3122,7 @@ static void __exit fbcon_exit(void)
|
|
|
#endif
|
|
|
|
|
|
kfree((void *)softback_buf);
|
|
|
+ softback_buf = 0UL;
|
|
|
|
|
|
for (i = 0; i < FB_MAX; i++) {
|
|
|
mapped = 0;
|
|
@@ -3150,22 +3142,69 @@ static void __exit fbcon_exit(void)
|
|
|
if (info->fbops->fb_release)
|
|
|
info->fbops->fb_release(info, 0);
|
|
|
module_put(info->fbops->owner);
|
|
|
- kfree(info->fbcon_par);
|
|
|
- info->fbcon_par = NULL;
|
|
|
+
|
|
|
+ if (info->fbcon_par) {
|
|
|
+ fbcon_del_cursor_timer(info);
|
|
|
+ kfree(info->fbcon_par);
|
|
|
+ info->fbcon_par = NULL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (info->queue.func == fb_flashcursor)
|
|
|
+ info->queue.func = NULL;
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- fbcon_deinit_class_device();
|
|
|
- class_device_destroy(fb_class, MKDEV(FB_MAJOR, FB_MAX));
|
|
|
+ release_console_sem();
|
|
|
+}
|
|
|
+
|
|
|
+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(FB_MAJOR, FB_MAX), 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;
|
|
|
+}
|
|
|
+
|
|
|
+module_init(fb_console_init);
|
|
|
+
|
|
|
+#ifdef MODULE
|
|
|
+
|
|
|
+static void 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_exit();
|
|
|
+ fbcon_deinit_class_device();
|
|
|
+ class_device_destroy(fb_class, MKDEV(FB_MAJOR, FB_MAX));
|
|
|
release_console_sem();
|
|
|
- give_up_console(&fb_con);
|
|
|
}
|
|
|
|
|
|
module_exit(fb_console_exit);
|