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
/*
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) ?
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;
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);
}
}
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);
}
return ret;
.notifier_call = fbcon_event_notify,
};
-static int __init fb_console_init(void)
+static ssize_t store_rotate(struct class_device *class_device,
+ const char *buf, size_t count)
{
- int i;
+ struct fb_info *info;
+ int rotate, idx;
+ char **last = NULL;
acquire_console_sem();
- fb_register_client(&fbcon_event_notifier);
+ 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;
+}
- for (i = 0; i < MAX_NR_CONSOLES; i++)
- con2fb_map[i] = -1;
+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;
+
+ 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)
+{
+ struct fb_info *info;
+ int rotate = 0, idx;
+
+ 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:
+ release_console_sem();
+ 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)
+{
+ 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;
+}
+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;
+
+ acquire_console_sem();
+#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 = 0; j < MAX_NR_CONSOLES; j++) {
+ if (con2fb_map[j] == i) {
+ con2fb_map[j] = -1;
+ mapped = 1;
+ }
+ }
+
+ if (mapped) {
+ if (info->fbops->fb_release)
+ info->fbops->fb_release(info, 0);
+ module_put(info->fbops->owner);
+
+ 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;
+
+ }
+ }
+
+ 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;
}
#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_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);