X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fchar%2Fvt.c;h=367be917506117b08d2407b7f74beb55432701d4;hb=d870ec7281d8429ab17d2e0324f4d8ca3f3de62d;hp=0d56f8fc105c9314fb9b9e73b539d8acbb7ddfe1;hpb=5cae826e9e54a31f06b4c11b73f4af29e2ea4932;p=linux-2.6-omap-h63xx.git diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 0d56f8fc105..367be917506 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -99,6 +99,7 @@ #include #include #include +#include #include #include @@ -158,7 +159,7 @@ static void blank_screen_t(unsigned long dummy); static void set_palette(struct vc_data *vc); static int printable; /* Is console ready for printing? */ -static int default_utf8; +int default_utf8 = true; module_param(default_utf8, int, S_IRUGO | S_IWUSR); /* @@ -222,6 +223,35 @@ enum { blank_vesa_wait, }; +/* + * Notifier list for console events. + */ +static ATOMIC_NOTIFIER_HEAD(vt_notifier_list); + +int register_vt_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&vt_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(register_vt_notifier); + +int unregister_vt_notifier(struct notifier_block *nb) +{ + return atomic_notifier_chain_unregister(&vt_notifier_list, nb); +} +EXPORT_SYMBOL_GPL(unregister_vt_notifier); + +static void notify_write(struct vc_data *vc, unsigned int unicode) +{ + struct vt_notifier_param param = { .vc = vc, unicode = unicode }; + atomic_notifier_call_chain(&vt_notifier_list, VT_WRITE, ¶m); +} + +static void notify_update(struct vc_data *vc) +{ + struct vt_notifier_param param = { .vc = vc }; + atomic_notifier_call_chain(&vt_notifier_list, VT_UPDATE, ¶m); +} + /* * Low-Level Functions */ @@ -718,6 +748,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ return -ENXIO; if (!vc_cons[currcons].d) { struct vc_data *vc; + struct vt_notifier_param param; /* prevent users from taking too much memory */ if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE)) @@ -729,7 +760,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ /* although the numbers above are not valid since long ago, the point is still up-to-date and the comment still has its value even if only as a historical artifact. --mj, July 1998 */ - vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL); + param.vc = vc = kzalloc(sizeof(struct vc_data), GFP_KERNEL); if (!vc) return -ENOMEM; vc_cons[currcons].d = vc; @@ -746,6 +777,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ } vc->vc_kmalloced = 1; vc_init(vc, vc->vc_rows, vc->vc_cols, 1); + atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); } return 0; } @@ -907,6 +939,8 @@ void vc_deallocate(unsigned int currcons) if (vc_cons_allocated(currcons)) { struct vc_data *vc = vc_cons[currcons].d; + struct vt_notifier_param param = { .vc = vc }; + atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); vc->vc_sw->con_deinit(vc); put_pid(vc->vt_pid); module_put(vc->vc_sw->owner); @@ -1019,6 +1053,7 @@ static void lf(struct vc_data *vc) vc->vc_pos += vc->vc_size_row; } vc->vc_need_wrap = 0; + notify_write(vc, '\n'); } static void ri(struct vc_data *vc) @@ -1039,6 +1074,7 @@ static inline void cr(struct vc_data *vc) { vc->vc_pos -= vc->vc_x << 1; vc->vc_need_wrap = vc->vc_x = 0; + notify_write(vc, '\r'); } static inline void bs(struct vc_data *vc) @@ -1047,6 +1083,7 @@ static inline void bs(struct vc_data *vc) vc->vc_pos -= 2; vc->vc_x--; vc->vc_need_wrap = 0; + notify_write(vc, '\b'); } } @@ -1593,6 +1630,7 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c) break; } vc->vc_pos += (vc->vc_x << 1); + notify_write(vc, '\t'); return; case 10: case 11: case 12: lf(vc); @@ -2252,6 +2290,7 @@ rescan_last_byte: tc = conv_uni_to_pc(vc, ' '); /* A space is printed in the second column */ if (tc < 0) tc = ' '; } + notify_write(vc, c); if (inverse) { FLUSH @@ -2274,6 +2313,7 @@ rescan_last_byte: release_console_sem(); out: + notify_update(vc); return n; #undef FLUSH } @@ -2317,6 +2357,7 @@ static void console_callback(struct work_struct *ignored) do_blank_screen(0); blank_timer_expired = 0; } + notify_update(vc_cons[fg_console].d); release_console_sem(); } @@ -2359,13 +2400,15 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) { struct vc_data *vc = vc_cons[fg_console].d; unsigned char c; - static unsigned long printing; + static DEFINE_SPINLOCK(printing_lock); const ushort *start; ushort cnt = 0; ushort myx; /* console busy or not yet initialized */ - if (!printable || test_and_set_bit(0, &printing)) + if (!printable) + return; + if (!spin_trylock(&printing_lock)) return; if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) @@ -2418,6 +2461,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) continue; } scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos); + notify_write(vc, c); cnt++; if (myx == vc->vc_cols - 1) { vc->vc_need_wrap = 1; @@ -2436,9 +2480,10 @@ static void vt_console_print(struct console *co, const char *b, unsigned count) } } set_cursor(vc); + notify_update(vc); quit: - clear_bit(0, &printing); + spin_unlock(&printing_lock); } static struct tty_driver *vt_console_device(struct console *c, int *index)