1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77#include <linux/module.h>
78#include <linux/sched.h>
79#include <linux/tty.h>
80#include <linux/tty_flip.h>
81#include <linux/kernel.h>
82#include <linux/string.h>
83#include <linux/errno.h>
84#include <linux/kd.h>
85#include <linux/slab.h>
86#include <linux/major.h>
87#include <linux/mm.h>
88#include <linux/console.h>
89#include <linux/init.h>
90#include <linux/devfs_fs_kernel.h>
91#include <linux/vt_kern.h>
92#include <linux/selection.h>
93#include <linux/console_struct.h>
94#include <linux/kbd_kern.h>
95#include <linux/consolemap.h>
96#include <linux/timer.h>
97#include <linux/interrupt.h>
98#include <linux/config.h>
99#include <linux/version.h>
100#include <linux/tqueue.h>
101#include <linux/bootmem.h>
102#include <linux/pm.h>
103#include <linux/smp_lock.h>
104
105#include <asm/io.h>
106#include <asm/system.h>
107#include <asm/uaccess.h>
108#include <asm/bitops.h>
109
110#include "console_macros.h"
111
112
113const struct consw *conswitchp;
114
115static void __console_callback(void);
116
117
118
119
120
121
122#define CTRL_ACTION 0x0d00ff81
123#define CTRL_ALWAYS 0x0800f501
124
125
126
127
128#define DEFAULT_BELL_PITCH 750
129#define DEFAULT_BELL_DURATION (HZ/8)
130
131extern void vcs_make_devfs (unsigned int index, int unregister);
132
133#ifndef MIN
134#define MIN(a,b) ((a) < (b) ? (a) : (b))
135#endif
136
137static struct tty_struct *console_table[MAX_NR_CONSOLES];
138static struct termios *console_termios[MAX_NR_CONSOLES];
139static struct termios *console_termios_locked[MAX_NR_CONSOLES];
140struct vc vc_cons [MAX_NR_CONSOLES];
141
142#ifndef VT_SINGLE_DRIVER
143static const struct consw *con_driver_map[MAX_NR_CONSOLES];
144#endif
145
146static int con_open(struct tty_struct *, struct file *);
147static void vc_init(unsigned int console, unsigned int rows,
148 unsigned int cols, int do_clear);
149static void blank_screen(unsigned long dummy);
150static void gotoxy(int currcons, int new_x, int new_y);
151static void save_cur(int currcons);
152static void reset_terminal(int currcons, int do_clear);
153static void con_flush_chars(struct tty_struct *tty);
154static void set_vesa_blanking(unsigned long arg);
155static void set_cursor(int currcons);
156static void hide_cursor(int currcons);
157static void unblank_screen_t(unsigned long dummy);
158static void console_callback(void *ignored);
159
160static int printable;
161
162int do_poke_blanked_console;
163int console_blanked;
164
165static int vesa_blank_mode;
166static int blankinterval = 10*60*HZ;
167static int vesa_off_interval;
168
169static struct tq_struct console_callback_tq = {
170 routine: console_callback,
171};
172
173
174
175
176
177
178
179int fg_console;
180int last_console;
181int want_console = -1;
182int kmsg_redirect;
183
184
185
186
187
188
189
190static struct vc_data *master_display_fg;
191
192
193
194
195
196
197
198
199
200
201
202static int scrollback_delta;
203
204
205
206
207
208int (*console_blank_hook)(int);
209
210static struct timer_list console_timer;
211
212
213
214
215
216#define IS_FG (currcons == fg_console)
217#define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)
218
219#ifdef VT_BUF_VRAM_ONLY
220#define DO_UPDATE 0
221#else
222#define DO_UPDATE IS_VISIBLE
223#endif
224
225static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data);
226static struct pm_dev *pm_con;
227
228static inline unsigned short *screenpos(int currcons, int offset, int viewed)
229{
230 unsigned short *p;
231
232 if (!viewed)
233 p = (unsigned short *)(origin + offset);
234 else if (!sw->con_screen_pos)
235 p = (unsigned short *)(visible_origin + offset);
236 else
237 p = sw->con_screen_pos(vc_cons[currcons].d, offset);
238 return p;
239}
240
241static inline void scrolldelta(int lines)
242{
243 scrollback_delta += lines;
244 schedule_console_callback();
245}
246
247extern int machine_paniced;
248
249void schedule_console_callback(void)
250{
251
252
253 if (machine_paniced)
254 __console_callback();
255 else
256 schedule_task(&console_callback_tq);
257}
258
259static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
260{
261 unsigned short *d, *s;
262
263 if (t+nr >= b)
264 nr = b - t - 1;
265 if (b > video_num_lines || t >= b || nr < 1)
266 return;
267 if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
268 return;
269 d = (unsigned short *) (origin+video_size_row*t);
270 s = (unsigned short *) (origin+video_size_row*(t+nr));
271 scr_memcpyw(d, s, (b-t-nr) * video_size_row);
272 scr_memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
273}
274
275static void
276scrdown(int currcons, unsigned int t, unsigned int b, int nr)
277{
278 unsigned short *s;
279 unsigned int step;
280
281 if (t+nr >= b)
282 nr = b - t - 1;
283 if (b > video_num_lines || t >= b || nr < 1)
284 return;
285 if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
286 return;
287 s = (unsigned short *) (origin+video_size_row*t);
288 step = video_num_columns * nr;
289 scr_memmovew(s + step, s, (b-t-nr)*video_size_row);
290 scr_memsetw(s, video_erase_char, 2*step);
291}
292
293static void do_update_region(int currcons, unsigned long start, int count)
294{
295#ifndef VT_BUF_VRAM_ONLY
296 unsigned int xx, yy, offset;
297 u16 *p;
298
299 p = (u16 *) start;
300 if (!sw->con_getxy) {
301 offset = (start - origin) / 2;
302 xx = offset % video_num_columns;
303 yy = offset / video_num_columns;
304 } else {
305 int nxx, nyy;
306 start = sw->con_getxy(vc_cons[currcons].d, start, &nxx, &nyy);
307 xx = nxx; yy = nyy;
308 }
309 for(;;) {
310 u16 attrib = scr_readw(p) & 0xff00;
311 int startx = xx;
312 u16 *q = p;
313 while (xx < video_num_columns && count) {
314 if (attrib != (scr_readw(p) & 0xff00)) {
315 if (p > q)
316 sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
317 startx = xx;
318 q = p;
319 attrib = scr_readw(p) & 0xff00;
320 }
321 p++;
322 xx++;
323 count--;
324 }
325 if (p > q)
326 sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
327 if (!count)
328 break;
329 xx = 0;
330 yy++;
331 if (sw->con_getxy) {
332 p = (u16 *)start;
333 start = sw->con_getxy(vc_cons[currcons].d, start, NULL, NULL);
334 }
335 }
336#endif
337}
338
339void update_region(int currcons, unsigned long start, int count)
340{
341 if (DO_UPDATE) {
342 hide_cursor(currcons);
343 do_update_region(currcons, start, count);
344 set_cursor(currcons);
345 }
346}
347
348
349
350static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
351{
352 if (sw->con_build_attr)
353 return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse);
354
355#ifndef VT_BUF_VRAM_ONLY
356
357
358
359
360
361
362
363
364
365
366 {
367 u8 a = color;
368 if (!can_do_color)
369 return _intensity |
370 (_underline ? 4 : 0) |
371 (_reverse ? 8 : 0) |
372 (_blink ? 0x80 : 0);
373 if (_underline)
374 a = (a & 0xf0) | ulcolor;
375 else if (_intensity == 0)
376 a = (a & 0xf0) | halfcolor;
377 if (_reverse)
378 a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
379 if (_blink)
380 a ^= 0x80;
381 if (_intensity == 2)
382 a ^= 0x08;
383 if (hi_font_mask == 0x100)
384 a <<= 1;
385 return a;
386 }
387#else
388 return 0;
389#endif
390}
391
392static void update_attr(int currcons)
393{
394 attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
395 video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
396}
397
398
399
400void invert_screen(int currcons, int offset, int count, int viewed)
401{
402 unsigned short *p;
403
404 count /= 2;
405 p = screenpos(currcons, offset, viewed);
406 if (sw->con_invert_region)
407 sw->con_invert_region(vc_cons[currcons].d, p, count);
408#ifndef VT_BUF_VRAM_ONLY
409 else {
410 u16 *q = p;
411 int cnt = count;
412 u16 a;
413
414 if (!can_do_color) {
415 while (cnt--) {
416 a = scr_readw(q);
417 a ^= 0x0800;
418 scr_writew(a, q);
419 q++;
420 }
421 } else if (hi_font_mask == 0x100) {
422 while (cnt--) {
423 a = scr_readw(q);
424 a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
425 scr_writew(a, q);
426 q++;
427 }
428 } else {
429 while (cnt--) {
430 a = scr_readw(q);
431 a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
432 scr_writew(a, q);
433 q++;
434 }
435 }
436 }
437#endif
438 if (DO_UPDATE)
439 do_update_region(currcons, (unsigned long) p, count);
440}
441
442
443void complement_pos(int currcons, int offset)
444{
445 static unsigned short *p;
446 static unsigned short old;
447 static unsigned short oldx, oldy;
448
449 if (p) {
450 scr_writew(old, p);
451 if (DO_UPDATE)
452 sw->con_putc(vc_cons[currcons].d, old, oldy, oldx);
453 }
454 if (offset == -1)
455 p = NULL;
456 else {
457 unsigned short new;
458 p = screenpos(currcons, offset, 1);
459 old = scr_readw(p);
460 new = old ^ complement_mask;
461 scr_writew(new, p);
462 if (DO_UPDATE) {
463 oldx = (offset >> 1) % video_num_columns;
464 oldy = (offset >> 1) / video_num_columns;
465 sw->con_putc(vc_cons[currcons].d, new, oldy, oldx);
466 }
467 }
468}
469
470static void insert_char(int currcons, unsigned int nr)
471{
472 unsigned short *p, *q = (unsigned short *) pos;
473
474 p = q + video_num_columns - nr - x;
475 while (--p >= q)
476 scr_writew(scr_readw(p), p + nr);
477 scr_memsetw(q, video_erase_char, nr*2);
478 need_wrap = 0;
479 if (DO_UPDATE) {
480 unsigned short oldattr = attr;
481 sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
482 video_num_columns-x-nr);
483 attr = video_erase_char >> 8;
484 while (nr--)
485 sw->con_putc(vc_cons[currcons].d,
486 video_erase_char,y,x+nr);
487 attr = oldattr;
488 }
489}
490
491static void delete_char(int currcons, unsigned int nr)
492{
493 unsigned int i = x;
494 unsigned short *p = (unsigned short *) pos;
495
496 while (++i <= video_num_columns - nr) {
497 scr_writew(scr_readw(p+nr), p);
498 p++;
499 }
500 scr_memsetw(p, video_erase_char, nr*2);
501 need_wrap = 0;
502 if (DO_UPDATE) {
503 unsigned short oldattr = attr;
504 sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
505 video_num_columns-x-nr);
506 attr = video_erase_char >> 8;
507 while (nr--)
508 sw->con_putc(vc_cons[currcons].d,
509 video_erase_char, y,
510 video_num_columns-1-nr);
511 attr = oldattr;
512 }
513}
514
515static int softcursor_original;
516
517static void add_softcursor(int currcons)
518{
519 int i = scr_readw((u16 *) pos);
520 u32 type = cursor_type;
521
522 if (! (type & 0x10)) return;
523 if (softcursor_original != -1) return;
524 softcursor_original = i;
525 i |= ((type >> 8) & 0xff00 );
526 i ^= ((type) & 0xff00 );
527 if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
528 if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
529 scr_writew(i, (u16 *) pos);
530 if (DO_UPDATE)
531 sw->con_putc(vc_cons[currcons].d, i, y, x);
532}
533
534static void hide_cursor(int currcons)
535{
536 if (currcons == sel_cons)
537 clear_selection();
538 if (softcursor_original != -1) {
539 scr_writew(softcursor_original,(u16 *) pos);
540 if (DO_UPDATE)
541 sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x);
542 softcursor_original = -1;
543 }
544 sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
545}
546
547static void set_cursor(int currcons)
548{
549 if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
550 return;
551 if (deccm) {
552 if (currcons == sel_cons)
553 clear_selection();
554 add_softcursor(currcons);
555 if ((cursor_type & 0x0f) != 1)
556 sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
557 } else
558 hide_cursor(currcons);
559}
560
561static void set_origin(int currcons)
562{
563 if (!IS_VISIBLE ||
564 !sw->con_set_origin ||
565 !sw->con_set_origin(vc_cons[currcons].d))
566 origin = (unsigned long) screenbuf;
567 visible_origin = origin;
568 scr_end = origin + screenbuf_size;
569 pos = origin + video_size_row*y + 2*x;
570}
571
572static inline void save_screen(int currcons)
573{
574 if (sw->con_save_screen)
575 sw->con_save_screen(vc_cons[currcons].d);
576}
577
578
579
580
581
582void redraw_screen(int new_console, int is_switch)
583{
584 int redraw = 1;
585 int currcons, old_console;
586
587 if (!vc_cons_allocated(new_console)) {
588
589
590 return;
591 }
592
593 if (is_switch) {
594 currcons = fg_console;
595 hide_cursor(currcons);
596 if (fg_console != new_console) {
597 struct vc_data **display = vc_cons[new_console].d->vc_display_fg;
598 old_console = (*display) ? (*display)->vc_num : fg_console;
599 *display = vc_cons[new_console].d;
600 fg_console = new_console;
601 currcons = old_console;
602 if (!IS_VISIBLE) {
603 save_screen(currcons);
604 set_origin(currcons);
605 }
606 currcons = new_console;
607 if (old_console == new_console)
608 redraw = 0;
609 }
610 } else {
611 currcons = new_console;
612 hide_cursor(currcons);
613 }
614
615 if (redraw) {
616 int update;
617 set_origin(currcons);
618 update = sw->con_switch(vc_cons[currcons].d);
619 set_palette(currcons);
620 if (update && vcmode != KD_GRAPHICS)
621 do_update_region(currcons, origin, screenbuf_size/2);
622 }
623 set_cursor(currcons);
624 if (is_switch) {
625 set_leds();
626 compute_shiftstate();
627 }
628}
629
630
631
632
633
634int vc_cons_allocated(unsigned int i)
635{
636 return (i < MAX_NR_CONSOLES && vc_cons[i].d);
637}
638
639static void visual_init(int currcons, int init)
640{
641
642 sw = conswitchp;
643#ifndef VT_SINGLE_DRIVER
644 if (con_driver_map[currcons])
645 sw = con_driver_map[currcons];
646#endif
647 cons_num = currcons;
648 display_fg = &master_display_fg;
649 vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir;
650 vc_cons[currcons].d->vc_uni_pagedir = 0;
651 hi_font_mask = 0;
652 complement_mask = 0;
653 can_do_color = 0;
654 sw->con_init(vc_cons[currcons].d, init);
655 if (!complement_mask)
656 complement_mask = can_do_color ? 0x7700 : 0x0800;
657 s_complement_mask = complement_mask;
658 video_size_row = video_num_columns<<1;
659 screenbuf_size = video_num_lines*video_size_row;
660}
661
662int vc_allocate(unsigned int currcons)
663{
664 if (currcons >= MAX_NR_CONSOLES)
665 return -ENXIO;
666 if (!vc_cons[currcons].d) {
667 long p, q;
668
669
670 if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
671 return -EPERM;
672
673
674
675
676
677
678
679 p = (long) kmalloc(structsize, GFP_KERNEL);
680 if (!p)
681 return -ENOMEM;
682 memset((void *)p, 0, structsize);
683 vc_cons[currcons].d = (struct vc_data *)p;
684 vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
685 visual_init(currcons, 1);
686 if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
687 con_set_default_unimap(currcons);
688 q = (long)kmalloc(screenbuf_size, GFP_KERNEL);
689 if (!q) {
690 kfree((char *) p);
691 vc_cons[currcons].d = NULL;
692 vt_cons[currcons] = NULL;
693 return -ENOMEM;
694 }
695 screenbuf = (unsigned short *) q;
696 kmalloced = 1;
697 vc_init(currcons, video_num_lines, video_num_columns, 1);
698
699 if (!pm_con) {
700 pm_con = pm_register(PM_SYS_DEV,
701 PM_SYS_VGA,
702 pm_con_request);
703 }
704 }
705 return 0;
706}
707
708#define VC_RESIZE_MAXCOL (32767)
709#define VC_RESIZE_MAXROW (32767)
710
711
712
713
714
715
716int vc_resize(unsigned int lines, unsigned int cols,
717 unsigned int first, unsigned int last)
718{
719 unsigned int cc, ll, ss, sr, todo = 0;
720 unsigned int currcons = fg_console, i;
721 unsigned short *newscreens[MAX_NR_CONSOLES];
722
723 if (cols > VC_RESIZE_MAXCOL || lines > VC_RESIZE_MAXROW)
724 return -EINVAL;
725
726 cc = (cols ? cols : video_num_columns);
727 ll = (lines ? lines : video_num_lines);
728 sr = cc << 1;
729 ss = sr * ll;
730
731 for (currcons = first; currcons <= last; currcons++) {
732 if (!vc_cons_allocated(currcons) ||
733 (cc == video_num_columns && ll == video_num_lines))
734 newscreens[currcons] = NULL;
735 else {
736 unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER);
737 if (!p) {
738 for (i = first; i < currcons; i++)
739 if (newscreens[i])
740 kfree(newscreens[i]);
741 return -ENOMEM;
742 }
743 newscreens[currcons] = p;
744 todo++;
745 }
746 }
747 if (!todo)
748 return 0;
749
750 for (currcons = first; currcons <= last; currcons++) {
751 unsigned int occ, oll, oss, osr;
752 unsigned long ol, nl, nlend, rlth, rrem;
753 if (!newscreens[currcons] || !vc_cons_allocated(currcons))
754 continue;
755
756 oll = video_num_lines;
757 occ = video_num_columns;
758 osr = video_size_row;
759 oss = screenbuf_size;
760
761 video_num_lines = ll;
762 video_num_columns = cc;
763 video_size_row = sr;
764 screenbuf_size = ss;
765
766 rlth = MIN(osr, sr);
767 rrem = sr - rlth;
768 ol = origin;
769 nl = (long) newscreens[currcons];
770 nlend = nl + ss;
771 if (ll < oll)
772 ol += (oll - ll) * osr;
773
774 update_attr(currcons);
775
776 while (ol < scr_end) {
777 scr_memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
778 if (rrem)
779 scr_memsetw((void *)(nl + rlth), video_erase_char, rrem);
780 ol += osr;
781 nl += sr;
782 }
783 if (nlend > nl)
784 scr_memsetw((void *) nl, video_erase_char, nlend - nl);
785 if (kmalloced)
786 kfree(screenbuf);
787 screenbuf = newscreens[currcons];
788 kmalloced = 1;
789 screenbuf_size = ss;
790 set_origin(currcons);
791
792
793 top = 0;
794 bottom = video_num_lines;
795 gotoxy(currcons, x, y);
796 save_cur(currcons);
797
798 if (console_table[currcons]) {
799 struct winsize ws, *cws = &console_table[currcons]->winsize;
800 memset(&ws, 0, sizeof(ws));
801 ws.ws_row = video_num_lines;
802 ws.ws_col = video_num_columns;
803 if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
804 console_table[currcons]->pgrp > 0)
805 kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1);
806 *cws = ws;
807 }
808
809 if (IS_VISIBLE)
810 update_screen(currcons);
811 }
812
813 return 0;
814}
815
816
817void vc_disallocate(unsigned int currcons)
818{
819 acquire_console_sem();
820 if (vc_cons_allocated(currcons)) {
821 sw->con_deinit(vc_cons[currcons].d);
822 if (kmalloced)
823 kfree(screenbuf);
824 if (currcons >= MIN_NR_CONSOLES)
825 kfree(vc_cons[currcons].d);
826 vc_cons[currcons].d = NULL;
827 }
828 release_console_sem();
829}
830
831
832
833
834
835#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
836#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
837#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
838
839#define decarm VC_REPEAT
840#define decckm VC_CKMODE
841#define kbdapplic VC_APPLIC
842#define lnm VC_CRLF
843
844
845
846
847#define VT100ID "\033[?1;2c"
848#define VT102ID "\033[?6c"
849
850unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
851 8,12,10,14, 9,13,11,15 };
852
853
854int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
855 0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
856int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
857 0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
858int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
859 0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
860
861
862
863
864
865
866static void gotoxy(int currcons, int new_x, int new_y)
867{
868 int min_y, max_y;
869
870 if (new_x < 0)
871 x = 0;
872 else
873 if (new_x >= video_num_columns)
874 x = video_num_columns - 1;
875 else
876 x = new_x;
877 if (decom) {
878 min_y = top;
879 max_y = bottom;
880 } else {
881 min_y = 0;
882 max_y = video_num_lines;
883 }
884 if (new_y < min_y)
885 y = min_y;
886 else if (new_y >= max_y)
887 y = max_y - 1;
888 else
889 y = new_y;
890 pos = origin + y*video_size_row + (x<<1);
891 need_wrap = 0;
892}
893
894
895static void gotoxay(int currcons, int new_x, int new_y)
896{
897 gotoxy(currcons, new_x, decom ? (top+new_y) : new_y);
898}
899
900void scrollback(int lines)
901{
902 int currcons = fg_console;
903
904 if (!lines)
905 lines = video_num_lines/2;
906 scrolldelta(-lines);
907}
908
909void scrollfront(int lines)
910{
911 int currcons = fg_console;
912
913 if (!lines)
914 lines = video_num_lines/2;
915 scrolldelta(lines);
916}
917
918static void lf(int currcons)
919{
920
921
922
923 if (y+1 == bottom)
924 scrup(currcons,top,bottom,1);
925 else if (y < video_num_lines-1) {
926 y++;
927 pos += video_size_row;
928 }
929 need_wrap = 0;
930}
931
932static void ri(int currcons)
933{
934
935
936
937 if (y == top)
938 scrdown(currcons,top,bottom,1);
939 else if (y > 0) {
940 y--;
941 pos -= video_size_row;
942 }
943 need_wrap = 0;
944}
945
946static inline void cr(int currcons)
947{
948 pos -= x<<1;
949 need_wrap = x = 0;
950}
951
952static inline void bs(int currcons)
953{
954 if (x) {
955 pos -= 2;
956 x--;
957 need_wrap = 0;
958 }
959}
960
961static inline void del(int currcons)
962{
963
964}
965
966static void csi_J(int currcons, int vpar)
967{
968 unsigned int count;
969 unsigned short * start;
970
971 switch (vpar) {
972 case 0:
973 count = (scr_end-pos)>>1;
974 start = (unsigned short *) pos;
975 if (DO_UPDATE) {
976
977 sw->con_clear(vc_cons[currcons].d, y, x, 1,
978 video_num_columns-x);
979 sw->con_clear(vc_cons[currcons].d, y+1, 0,
980 video_num_lines-y-1,
981 video_num_columns);
982 }
983 break;
984 case 1:
985 count = ((pos-origin)>>1)+1;
986 start = (unsigned short *) origin;
987 if (DO_UPDATE) {
988
989 sw->con_clear(vc_cons[currcons].d, 0, 0, y,
990 video_num_columns);
991 sw->con_clear(vc_cons[currcons].d, y, 0, 1,
992 x + 1);
993 }
994 break;
995 case 2:
996 count = video_num_columns * video_num_lines;
997 start = (unsigned short *) origin;
998 if (DO_UPDATE)
999 sw->con_clear(vc_cons[currcons].d, 0, 0,
1000 video_num_lines,
1001 video_num_columns);
1002 break;
1003 default:
1004 return;
1005 }
1006 scr_memsetw(start, video_erase_char, 2*count);
1007 need_wrap = 0;
1008}
1009
1010static void csi_K(int currcons, int vpar)
1011{
1012 unsigned int count;
1013 unsigned short * start;
1014
1015 switch (vpar) {
1016 case 0:
1017 count = video_num_columns-x;
1018 start = (unsigned short *) pos;
1019 if (DO_UPDATE)
1020 sw->con_clear(vc_cons[currcons].d, y, x, 1,
1021 video_num_columns-x);
1022 break;
1023 case 1:
1024 start = (unsigned short *) (pos - (x<<1));
1025 count = x+1;
1026 if (DO_UPDATE)
1027 sw->con_clear(vc_cons[currcons].d, y, 0, 1,
1028 x + 1);
1029 break;
1030 case 2:
1031 start = (unsigned short *) (pos - (x<<1));
1032 count = video_num_columns;
1033 if (DO_UPDATE)
1034 sw->con_clear(vc_cons[currcons].d, y, 0, 1,
1035 video_num_columns);
1036 break;
1037 default:
1038 return;
1039 }
1040 scr_memsetw(start, video_erase_char, 2 * count);
1041 need_wrap = 0;
1042}
1043
1044static void csi_X(int currcons, int vpar)
1045{
1046 int count;
1047
1048 if (!vpar)
1049 vpar++;
1050 count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
1051
1052 scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count);
1053 if (DO_UPDATE)
1054 sw->con_clear(vc_cons[currcons].d, y, x, 1, count);
1055 need_wrap = 0;
1056}
1057
1058static void default_attr(int currcons)
1059{
1060 intensity = 1;
1061 underline = 0;
1062 reverse = 0;
1063 blink = 0;
1064 color = def_color;
1065}
1066
1067
1068static void csi_m(int currcons)
1069{
1070 int i;
1071
1072 for (i=0;i<=npar;i++)
1073 switch (par[i]) {
1074 case 0:
1075 default_attr(currcons);
1076 break;
1077 case 1:
1078 intensity = 2;
1079 break;
1080 case 2:
1081 intensity = 0;
1082 break;
1083 case 4:
1084 underline = 1;
1085 break;
1086 case 5:
1087 blink = 1;
1088 break;
1089 case 7:
1090 reverse = 1;
1091 break;
1092 case 10:
1093
1094
1095
1096
1097 translate = set_translate(charset == 0
1098 ? G0_charset
1099 : G1_charset,currcons);
1100 disp_ctrl = 0;
1101 toggle_meta = 0;
1102 break;
1103 case 11:
1104
1105
1106
1107 translate = set_translate(IBMPC_MAP,currcons);
1108 disp_ctrl = 1;
1109 toggle_meta = 0;
1110 break;
1111 case 12:
1112
1113
1114
1115 translate = set_translate(IBMPC_MAP,currcons);
1116 disp_ctrl = 1;
1117 toggle_meta = 1;
1118 break;
1119 case 21:
1120 case 22:
1121 intensity = 1;
1122 break;
1123 case 24:
1124 underline = 0;
1125 break;
1126 case 25:
1127 blink = 0;
1128 break;
1129 case 27:
1130 reverse = 0;
1131 break;
1132 case 38:
1133
1134
1135
1136
1137 color = (def_color & 0x0f) | background;
1138 underline = 1;
1139 break;
1140 case 39:
1141
1142
1143
1144
1145 color = (def_color & 0x0f) | background;
1146 underline = 0;
1147 break;
1148 case 49:
1149 color = (def_color & 0xf0) | foreground;
1150 break;
1151 default:
1152 if (par[i] >= 30 && par[i] <= 37)
1153 color = color_table[par[i]-30]
1154 | background;
1155 else if (par[i] >= 40 && par[i] <= 47)
1156 color = (color_table[par[i]-40]<<4)
1157 | foreground;
1158 break;
1159 }
1160 update_attr(currcons);
1161}
1162
1163static void respond_string(const char * p, struct tty_struct * tty)
1164{
1165 while (*p) {
1166 tty_insert_flip_char(tty, *p, 0);
1167 p++;
1168 }
1169 con_schedule_flip(tty);
1170}
1171
1172static void cursor_report(int currcons, struct tty_struct * tty)
1173{
1174 char buf[40];
1175
1176 sprintf(buf, "\033[%d;%dR", y + (decom ? top+1 : 1), x+1);
1177 respond_string(buf, tty);
1178}
1179
1180static inline void status_report(struct tty_struct * tty)
1181{
1182 respond_string("\033[0n", tty);
1183}
1184
1185static inline void respond_ID(struct tty_struct * tty)
1186{
1187 respond_string(VT102ID, tty);
1188}
1189
1190void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
1191{
1192 char buf[8];
1193
1194 sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
1195 (char)('!' + mry));
1196 respond_string(buf, tty);
1197}
1198
1199
1200int mouse_reporting(void)
1201{
1202 int currcons = fg_console;
1203
1204 return report_mouse;
1205}
1206
1207
1208static void set_mode(int currcons, int on_off)
1209{
1210 int i;
1211
1212 for (i=0; i<=npar; i++)
1213 if (ques) switch(par[i]) {
1214 case 1:
1215 if (on_off)
1216 set_kbd(decckm);
1217 else
1218 clr_kbd(decckm);
1219 break;
1220 case 3:
1221 deccolm = on_off;
1222#if 0
1223 (void) vc_resize(video_num_lines, deccolm ? 132 : 80);
1224
1225
1226#endif
1227 break;
1228 case 5:
1229 if (decscnm != on_off) {
1230 decscnm = on_off;
1231 invert_screen(currcons, 0, screenbuf_size, 0);
1232 update_attr(currcons);
1233 }
1234 break;
1235 case 6:
1236 decom = on_off;
1237 gotoxay(currcons,0,0);
1238 break;
1239 case 7:
1240 decawm = on_off;
1241 break;
1242 case 8:
1243 if (on_off)
1244 set_kbd(decarm);
1245 else
1246 clr_kbd(decarm);
1247 break;
1248 case 9:
1249 report_mouse = on_off ? 1 : 0;
1250 break;
1251 case 25:
1252 deccm = on_off;
1253 break;
1254 case 1000:
1255 report_mouse = on_off ? 2 : 0;
1256 break;
1257 } else switch(par[i]) {
1258 case 3:
1259 disp_ctrl = on_off;
1260 break;
1261 case 4:
1262 decim = on_off;
1263 break;
1264 case 20:
1265 if (on_off)
1266 set_kbd(lnm);
1267 else
1268 clr_kbd(lnm);
1269 break;
1270 }
1271}
1272
1273
1274static void setterm_command(int currcons)
1275{
1276 switch(par[0]) {
1277 case 1:
1278 if (can_do_color && par[1] < 16) {
1279 ulcolor = color_table[par[1]];
1280 if (underline)
1281 update_attr(currcons);
1282 }
1283 break;
1284 case 2:
1285 if (can_do_color && par[1] < 16) {
1286 halfcolor = color_table[par[1]];
1287 if (intensity == 0)
1288 update_attr(currcons);
1289 }
1290 break;
1291 case 8:
1292 def_color = attr;
1293 if (hi_font_mask == 0x100)
1294 def_color >>= 1;
1295 default_attr(currcons);
1296 update_attr(currcons);
1297 break;
1298 case 9:
1299 blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
1300 poke_blanked_console();
1301 break;
1302 case 10:
1303 if (npar >= 1)
1304 bell_pitch = par[1];
1305 else
1306 bell_pitch = DEFAULT_BELL_PITCH;
1307 break;
1308 case 11:
1309 if (npar >= 1)
1310 bell_duration = (par[1] < 2000) ?
1311 par[1]*HZ/1000 : 0;
1312 else
1313 bell_duration = DEFAULT_BELL_DURATION;
1314 break;
1315 case 12:
1316 if (par[1] >= 1 && vc_cons_allocated(par[1]-1))
1317 set_console(par[1] - 1);
1318 break;
1319 case 13:
1320 poke_blanked_console();
1321 break;
1322 case 14:
1323 vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
1324 break;
1325 }
1326}
1327
1328
1329static void csi_at(int currcons, unsigned int nr)
1330{
1331 if (nr > video_num_columns - x)
1332 nr = video_num_columns - x;
1333 else if (!nr)
1334 nr = 1;
1335 insert_char(currcons, nr);
1336}
1337
1338
1339static void csi_L(int currcons, unsigned int nr)
1340{
1341 if (nr > video_num_lines - y)
1342 nr = video_num_lines - y;
1343 else if (!nr)
1344 nr = 1;
1345 scrdown(currcons,y,bottom,nr);
1346 need_wrap = 0;
1347}
1348
1349
1350static void csi_P(int currcons, unsigned int nr)
1351{
1352 if (nr > video_num_columns - x)
1353 nr = video_num_columns - x;
1354 else if (!nr)
1355 nr = 1;
1356 delete_char(currcons, nr);
1357}
1358
1359
1360static void csi_M(int currcons, unsigned int nr)
1361{
1362 if (nr > video_num_lines - y)
1363 nr = video_num_lines - y;
1364 else if (!nr)
1365 nr=1;
1366 scrup(currcons,y,bottom,nr);
1367 need_wrap = 0;
1368}
1369
1370
1371static void save_cur(int currcons)
1372{
1373 saved_x = x;
1374 saved_y = y;
1375 s_intensity = intensity;
1376 s_underline = underline;
1377 s_blink = blink;
1378 s_reverse = reverse;
1379 s_charset = charset;
1380 s_color = color;
1381 saved_G0 = G0_charset;
1382 saved_G1 = G1_charset;
1383}
1384
1385
1386static void restore_cur(int currcons)
1387{
1388 gotoxy(currcons,saved_x,saved_y);
1389 intensity = s_intensity;
1390 underline = s_underline;
1391 blink = s_blink;
1392 reverse = s_reverse;
1393 charset = s_charset;
1394 color = s_color;
1395 G0_charset = saved_G0;
1396 G1_charset = saved_G1;
1397 translate = set_translate(charset ? G1_charset : G0_charset,currcons);
1398 update_attr(currcons);
1399 need_wrap = 0;
1400}
1401
1402enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
1403 EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
1404 ESpalette };
1405
1406
1407static void reset_terminal(int currcons, int do_clear)
1408{
1409 top = 0;
1410 bottom = video_num_lines;
1411 vc_state = ESnormal;
1412 ques = 0;
1413 translate = set_translate(LAT1_MAP,currcons);
1414 G0_charset = LAT1_MAP;
1415 G1_charset = GRAF_MAP;
1416 charset = 0;
1417 need_wrap = 0;
1418 report_mouse = 0;
1419 utf = 0;
1420 utf_count = 0;
1421
1422 disp_ctrl = 0;
1423 toggle_meta = 0;
1424
1425 decscnm = 0;
1426 decom = 0;
1427 decawm = 1;
1428 deccm = 1;
1429 decim = 0;
1430
1431 set_kbd(decarm);
1432 clr_kbd(decckm);
1433 clr_kbd(kbdapplic);
1434 clr_kbd(lnm);
1435 kbd_table[currcons].lockstate = 0;
1436 kbd_table[currcons].slockstate = 0;
1437 kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
1438 kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
1439
1440
1441 if(!atomic_read(&keyboard_tasklet.count))
1442 set_leds();
1443
1444 cursor_type = CUR_DEFAULT;
1445 complement_mask = s_complement_mask;
1446
1447 default_attr(currcons);
1448 update_attr(currcons);
1449
1450 tab_stop[0] = 0x01010100;
1451 tab_stop[1] =
1452 tab_stop[2] =
1453 tab_stop[3] =
1454 tab_stop[4] = 0x01010101;
1455
1456 bell_pitch = DEFAULT_BELL_PITCH;
1457 bell_duration = DEFAULT_BELL_DURATION;
1458
1459 gotoxy(currcons,0,0);
1460 save_cur(currcons);
1461 if (do_clear)
1462 csi_J(currcons,2);
1463}
1464
1465
1466static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
1467{
1468
1469
1470
1471
1472 switch (c) {
1473 case 0:
1474 return;
1475 case 7:
1476 if (bell_duration)
1477 kd_mksound(bell_pitch, bell_duration);
1478 return;
1479 case 8:
1480 bs(currcons);
1481 return;
1482 case 9:
1483 pos -= (x << 1);
1484 while (x < video_num_columns - 1) {
1485 x++;
1486 if (tab_stop[x >> 5] & (1 << (x & 31)))
1487 break;
1488 }
1489 pos += (x << 1);
1490 return;
1491 case 10: case 11: case 12:
1492 lf(currcons);
1493 if (!is_kbd(lnm))
1494 return;
1495 case 13:
1496 cr(currcons);
1497 return;
1498 case 14:
1499 charset = 1;
1500 translate = set_translate(G1_charset,currcons);
1501 disp_ctrl = 1;
1502 return;
1503 case 15:
1504 charset = 0;
1505 translate = set_translate(G0_charset,currcons);
1506 disp_ctrl = 0;
1507 return;
1508 case 24: case 26:
1509 vc_state = ESnormal;
1510 return;
1511 case 27:
1512 vc_state = ESesc;
1513 return;
1514 case 127:
1515 del(currcons);
1516 return;
1517 case 128+27:
1518 vc_state = ESsquare;
1519 return;
1520 }
1521 switch(vc_state) {
1522 case ESesc:
1523 vc_state = ESnormal;
1524 switch (c) {
1525 case '[':
1526 vc_state = ESsquare;
1527 return;
1528 case ']':
1529 vc_state = ESnonstd;
1530 return;
1531 case '%':
1532 vc_state = ESpercent;
1533 return;
1534 case 'E':
1535 cr(currcons);
1536 lf(currcons);
1537 return;
1538 case 'M':
1539 ri(currcons);
1540 return;
1541 case 'D':
1542 lf(currcons);
1543 return;
1544 case 'H':
1545 tab_stop[x >> 5] |= (1 << (x & 31));
1546 return;
1547 case 'Z':
1548 respond_ID(tty);
1549 return;
1550 case '7':
1551 save_cur(currcons);
1552 return;
1553 case '8':
1554 restore_cur(currcons);
1555 return;
1556 case '(':
1557 vc_state = ESsetG0;
1558 return;
1559 case ')':
1560 vc_state = ESsetG1;
1561 return;
1562 case '#':
1563 vc_state = EShash;
1564 return;
1565 case 'c':
1566 reset_terminal(currcons,1);
1567 return;
1568 case '>':
1569 clr_kbd(kbdapplic);
1570 return;
1571 case '=':
1572 set_kbd(kbdapplic);
1573 return;
1574 }
1575 return;
1576 case ESnonstd:
1577 if (c=='P') {
1578 for (npar=0; npar<NPAR; npar++)
1579 par[npar] = 0 ;
1580 npar = 0 ;
1581 vc_state = ESpalette;
1582 return;
1583 } else if (c=='R') {
1584 reset_palette(currcons);
1585 vc_state = ESnormal;
1586 } else
1587 vc_state = ESnormal;
1588 return;
1589 case ESpalette:
1590 if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
1591 par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
1592 if (npar==7) {
1593 int i = par[0]*3, j = 1;
1594 palette[i] = 16*par[j++];
1595 palette[i++] += par[j++];
1596 palette[i] = 16*par[j++];
1597 palette[i++] += par[j++];
1598 palette[i] = 16*par[j++];
1599 palette[i] += par[j];
1600 set_palette(currcons);
1601 vc_state = ESnormal;
1602 }
1603 } else
1604 vc_state = ESnormal;
1605 return;
1606 case ESsquare:
1607 for(npar = 0 ; npar < NPAR ; npar++)
1608 par[npar] = 0;
1609 npar = 0;
1610 vc_state = ESgetpars;
1611 if (c == '[') {
1612 vc_state=ESfunckey;
1613 return;
1614 }
1615 ques = (c=='?');
1616 if (ques)
1617 return;
1618 case ESgetpars:
1619 if (c==';' && npar<NPAR-1) {
1620 npar++;
1621 return;
1622 } else if (c>='0' && c<='9') {
1623 par[npar] *= 10;
1624 par[npar] += c-'0';
1625 return;
1626 } else vc_state=ESgotpars;
1627 case ESgotpars:
1628 vc_state = ESnormal;
1629 switch(c) {
1630 case 'h':
1631 set_mode(currcons,1);
1632 return;
1633 case 'l':
1634 set_mode(currcons,0);
1635 return;
1636 case 'c':
1637 if (ques) {
1638 if (par[0])
1639 cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
1640 else
1641 cursor_type = CUR_DEFAULT;
1642 return;
1643 }
1644 break;
1645 case 'm':
1646 if (ques) {
1647 clear_selection();
1648 if (par[0])
1649 complement_mask = par[0]<<8 | par[1];
1650 else
1651 complement_mask = s_complement_mask;
1652 return;
1653 }
1654 break;
1655 case 'n':
1656 if (!ques) {
1657 if (par[0] == 5)
1658 status_report(tty);
1659 else if (par[0] == 6)
1660 cursor_report(currcons,tty);
1661 }
1662 return;
1663 }
1664 if (ques) {
1665 ques = 0;
1666 return;
1667 }
1668 switch(c) {
1669 case 'G': case '`':
1670 if (par[0]) par[0]--;
1671 gotoxy(currcons,par[0],y);
1672 return;
1673 case 'A':
1674 if (!par[0]) par[0]++;
1675 gotoxy(currcons,x,y-par[0]);
1676 return;
1677 case 'B': case 'e':
1678 if (!par[0]) par[0]++;
1679 gotoxy(currcons,x,y+par[0]);
1680 return;
1681 case 'C': case 'a':
1682 if (!par[0]) par[0]++;
1683 gotoxy(currcons,x+par[0],y);
1684 return;
1685 case 'D':
1686 if (!par[0]) par[0]++;
1687 gotoxy(currcons,x-par[0],y);
1688 return;
1689 case 'E':
1690 if (!par[0]) par[0]++;
1691 gotoxy(currcons,0,y+par[0]);
1692 return;
1693 case 'F':
1694 if (!par[0]) par[0]++;
1695 gotoxy(currcons,0,y-par[0]);
1696 return;
1697 case 'd':
1698 if (par[0]) par[0]--;
1699 gotoxay(currcons,x,par[0]);
1700 return;
1701 case 'H': case 'f':
1702 if (par[0]) par[0]--;
1703 if (par[1]) par[1]--;
1704 gotoxay(currcons,par[1],par[0]);
1705 return;
1706 case 'J':
1707 csi_J(currcons,par[0]);
1708 return;
1709 case 'K':
1710 csi_K(currcons,par[0]);
1711 return;
1712 case 'L':
1713 csi_L(currcons,par[0]);
1714 return;
1715 case 'M':
1716 csi_M(currcons,par[0]);
1717 return;
1718 case 'P':
1719 csi_P(currcons,par[0]);
1720 return;
1721 case 'c':
1722 if (!par[0])
1723 respond_ID(tty);
1724 return;
1725 case 'g':
1726 if (!par[0])
1727 tab_stop[x >> 5] &= ~(1 << (x & 31));
1728 else if (par[0] == 3) {
1729 tab_stop[0] =
1730 tab_stop[1] =
1731 tab_stop[2] =
1732 tab_stop[3] =
1733 tab_stop[4] = 0;
1734 }
1735 return;
1736 case 'm':
1737 csi_m(currcons);
1738 return;
1739 case 'q':
1740
1741 if (par[0] < 4)
1742 setledstate(kbd_table + currcons,
1743 (par[0] < 3) ? par[0] : 4);
1744 return;
1745 case 'r':
1746 if (!par[0])
1747 par[0]++;
1748 if (!par[1])
1749 par[1] = video_num_lines;
1750
1751 if (par[0] < par[1] &&
1752 par[1] <= video_num_lines) {
1753 top=par[0]-1;
1754 bottom=par[1];
1755 gotoxay(currcons,0,0);
1756 }
1757 return;
1758 case 's':
1759 save_cur(currcons);
1760 return;
1761 case 'u':
1762 restore_cur(currcons);
1763 return;
1764 case 'X':
1765 csi_X(currcons, par[0]);
1766 return;
1767 case '@':
1768 csi_at(currcons,par[0]);
1769 return;
1770 case ']':
1771 setterm_command(currcons);
1772 return;
1773 }
1774 return;
1775 case ESpercent:
1776 vc_state = ESnormal;
1777 switch (c) {
1778 case '@':
1779 utf = 0;
1780 return;
1781 case 'G':
1782 case '8':
1783 utf = 1;
1784 return;
1785 }
1786 return;
1787 case ESfunckey:
1788 vc_state = ESnormal;
1789 return;
1790 case EShash:
1791 vc_state = ESnormal;
1792 if (c == '8') {
1793
1794 video_erase_char =
1795 (video_erase_char & 0xff00) | 'E';
1796 csi_J(currcons, 2);
1797 video_erase_char =
1798 (video_erase_char & 0xff00) | ' ';
1799 do_update_region(currcons, origin, screenbuf_size/2);
1800 }
1801 return;
1802 case ESsetG0:
1803 if (c == '0')
1804 G0_charset = GRAF_MAP;
1805 else if (c == 'B')
1806 G0_charset = LAT1_MAP;
1807 else if (c == 'U')
1808 G0_charset = IBMPC_MAP;
1809 else if (c == 'K')
1810 G0_charset = USER_MAP;
1811 if (charset == 0)
1812 translate = set_translate(G0_charset,currcons);
1813 vc_state = ESnormal;
1814 return;
1815 case ESsetG1:
1816 if (c == '0')
1817 G1_charset = GRAF_MAP;
1818 else if (c == 'B')
1819 G1_charset = LAT1_MAP;
1820 else if (c == 'U')
1821 G1_charset = IBMPC_MAP;
1822 else if (c == 'K')
1823 G1_charset = USER_MAP;
1824 if (charset == 1)
1825 translate = set_translate(G1_charset,currcons);
1826 vc_state = ESnormal;
1827 return;
1828 default:
1829 vc_state = ESnormal;
1830 }
1831}
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842char con_buf[PAGE_SIZE];
1843#define CON_BUF_SIZE PAGE_SIZE
1844DECLARE_MUTEX(con_buf_sem);
1845
1846
1847static int do_con_write(struct tty_struct * tty, int from_user,
1848 const unsigned char *buf, int count)
1849{
1850#ifdef VT_BUF_VRAM_ONLY
1851#define FLUSH do { } while(0);
1852#else
1853#define FLUSH if (draw_x >= 0) { \
1854 sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); \
1855 draw_x = -1; \
1856 }
1857#endif
1858
1859 int c, tc, ok, n = 0, draw_x = -1;
1860 unsigned int currcons;
1861 unsigned long draw_from = 0, draw_to = 0;
1862 struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
1863 u16 himask, charmask;
1864 const unsigned char *orig_buf = NULL;
1865 int orig_count;
1866
1867 if (in_interrupt())
1868 return count;
1869
1870 currcons = vt->vc_num;
1871 if (!vc_cons_allocated(currcons)) {
1872
1873 static int error = 0;
1874 if (!error) {
1875 error = 1;
1876 printk("con_write: tty %d not allocated\n", currcons+1);
1877 }
1878 return 0;
1879 }
1880
1881 orig_buf = buf;
1882 orig_count = count;
1883
1884 if (from_user) {
1885 down(&con_buf_sem);
1886
1887again:
1888 if (count > CON_BUF_SIZE)
1889 count = CON_BUF_SIZE;
1890 console_conditional_schedule();
1891 if (copy_from_user(con_buf, buf, count)) {
1892 n = 0;
1893 goto out;
1894 }
1895
1896 buf = con_buf;
1897 }
1898
1899
1900
1901
1902
1903
1904
1905
1906 acquire_console_sem();
1907
1908 himask = hi_font_mask;
1909 charmask = himask ? 0x1ff : 0xff;
1910
1911
1912 if (IS_FG)
1913 hide_cursor(currcons);
1914
1915 while (!tty->stopped && count) {
1916 c = *buf;
1917 buf++;
1918 n++;
1919 count--;
1920
1921 if (utf) {
1922
1923
1924 if(c > 0x7f) {
1925 if (utf_count > 0 && (c & 0xc0) == 0x80) {
1926 utf_char = (utf_char << 6) | (c & 0x3f);
1927 utf_count--;
1928 if (utf_count == 0)
1929 tc = c = utf_char;
1930 else continue;
1931 } else {
1932 if ((c & 0xe0) == 0xc0) {
1933 utf_count = 1;
1934 utf_char = (c & 0x1f);
1935 } else if ((c & 0xf0) == 0xe0) {
1936 utf_count = 2;
1937 utf_char = (c & 0x0f);
1938 } else if ((c & 0xf8) == 0xf0) {
1939 utf_count = 3;
1940 utf_char = (c & 0x07);
1941 } else if ((c & 0xfc) == 0xf8) {
1942 utf_count = 4;
1943 utf_char = (c & 0x03);
1944 } else if ((c & 0xfe) == 0xfc) {
1945 utf_count = 5;
1946 utf_char = (c & 0x01);
1947 } else
1948 utf_count = 0;
1949 continue;
1950 }
1951 } else {
1952 tc = c;
1953 utf_count = 0;
1954 }
1955 } else {
1956 tc = translate[toggle_meta ? (c|0x80) : c];
1957 }
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969 ok = tc && (c >= 32 ||
1970 (!utf && !(((disp_ctrl ? CTRL_ALWAYS
1971 : CTRL_ACTION) >> c) & 1)))
1972 && (c != 127 || disp_ctrl)
1973 && (c != 128+27);
1974
1975 if (vc_state == ESnormal && ok) {
1976
1977 tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
1978 if ( tc == -4 ) {
1979
1980
1981 tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd);
1982
1983
1984
1985
1986 if (tc == -4)
1987 tc = c;
1988 } else if ( tc == -3 ) {
1989
1990 tc = c;
1991 }
1992 if (tc & ~charmask)
1993 continue;
1994
1995 if (need_wrap || decim)
1996 FLUSH
1997 if (need_wrap) {
1998 cr(currcons);
1999 lf(currcons);
2000 }
2001 if (decim)
2002 insert_char(currcons, 1);
2003 scr_writew(himask ?
2004 ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
2005 (attr << 8) + tc,
2006 (u16 *) pos);
2007 if (DO_UPDATE && draw_x < 0) {
2008 draw_x = x;
2009 draw_from = pos;
2010 }
2011 if (x == video_num_columns - 1) {
2012 need_wrap = decawm;
2013 draw_to = pos+2;
2014 } else {
2015 x++;
2016 draw_to = (pos+=2);
2017 }
2018 continue;
2019 }
2020 FLUSH
2021 do_con_trol(tty, currcons, c);
2022 }
2023 FLUSH
2024 console_conditional_schedule();
2025 release_console_sem();
2026
2027out:
2028 if (from_user) {
2029
2030
2031
2032
2033 if ((orig_count > CON_BUF_SIZE) && !tty->stopped) {
2034 orig_count -= CON_BUF_SIZE;
2035 orig_buf += CON_BUF_SIZE;
2036 count = orig_count;
2037 buf = orig_buf;
2038 goto again;
2039 }
2040
2041 up(&con_buf_sem);
2042 }
2043
2044 return n;
2045#undef FLUSH
2046}
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057static void console_callback(void *unused)
2058{
2059 acquire_console_sem();
2060 __console_callback();
2061 release_console_sem();
2062}
2063
2064static void __console_callback(void)
2065{
2066 if (want_console >= 0) {
2067 if (want_console != fg_console && vc_cons_allocated(want_console)) {
2068 hide_cursor(fg_console);
2069 change_console(want_console);
2070
2071
2072
2073 }
2074 want_console = -1;
2075 }
2076 if (do_poke_blanked_console) {
2077 do_poke_blanked_console = 0;
2078 poke_blanked_console();
2079 }
2080 if (scrollback_delta) {
2081 int currcons = fg_console;
2082 clear_selection();
2083 if (vcmode == KD_TEXT)
2084 sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta);
2085 scrollback_delta = 0;
2086 }
2087}
2088
2089void set_console(int nr)
2090{
2091 want_console = nr;
2092 schedule_console_callback();
2093}
2094
2095#ifdef CONFIG_VT_CONSOLE
2096
2097
2098
2099
2100
2101
2102
2103void vt_console_print(struct console *co, const char * b, unsigned count)
2104{
2105 int currcons = fg_console;
2106 unsigned char c;
2107 static unsigned long printing;
2108 const ushort *start;
2109 ushort cnt = 0;
2110 ushort myx;
2111
2112
2113 if (!printable || test_and_set_bit(0, &printing))
2114 return;
2115
2116 pm_access(pm_con);
2117
2118 if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
2119 currcons = kmsg_redirect - 1;
2120
2121
2122
2123 myx = x;
2124
2125 if (!vc_cons_allocated(currcons)) {
2126
2127
2128 goto quit;
2129 }
2130
2131 if (vcmode != KD_TEXT)
2132 goto quit;
2133
2134
2135 if (IS_FG)
2136 hide_cursor(currcons);
2137
2138 start = (ushort *)pos;
2139
2140
2141
2142 while (count--) {
2143 c = *b++;
2144 if (c == 10 || c == 13 || c == 8 || need_wrap) {
2145 if (cnt > 0) {
2146 if (IS_VISIBLE)
2147 sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
2148 x += cnt;
2149 if (need_wrap)
2150 x--;
2151 cnt = 0;
2152 }
2153 if (c == 8) {
2154 bs(currcons);
2155 start = (ushort *)pos;
2156 myx = x;
2157 continue;
2158 }
2159 if (c != 13)
2160 lf(currcons);
2161 cr(currcons);
2162 start = (ushort *)pos;
2163 myx = x;
2164 if (c == 10 || c == 13)
2165 continue;
2166 }
2167 scr_writew((attr << 8) + c, (unsigned short *) pos);
2168 cnt++;
2169 if (myx == video_num_columns - 1) {
2170 need_wrap = 1;
2171 continue;
2172 }
2173 pos+=2;
2174 myx++;
2175 }
2176 if (cnt > 0) {
2177 if (IS_VISIBLE)
2178 sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
2179 x += cnt;
2180 if (x == video_num_columns) {
2181 x--;
2182 need_wrap = 1;
2183 }
2184 }
2185 set_cursor(currcons);
2186
2187 if (!oops_in_progress)
2188 poke_blanked_console();
2189
2190quit:
2191 clear_bit(0, &printing);
2192}
2193
2194static kdev_t vt_console_device(struct console *c)
2195{
2196 return MKDEV(TTY_MAJOR, c->index ? c->index : fg_console + 1);
2197}
2198
2199struct console vt_console_driver = {
2200 name: "tty",
2201 write: vt_console_print,
2202 device: vt_console_device,
2203 unblank: unblank_screen,
2204 flags: CON_PRINTBUFFER,
2205 index: -1,
2206};
2207#endif
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224int tioclinux(struct tty_struct *tty, unsigned long arg)
2225{
2226 char type, data;
2227 int ret;
2228
2229 if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
2230 return -EINVAL;
2231 if (current->tty != tty && !capable(CAP_SYS_ADMIN))
2232 return -EPERM;
2233 if (get_user(type, (char *)arg))
2234 return -EFAULT;
2235 ret = 0;
2236 switch (type)
2237 {
2238 case 2:
2239 acquire_console_sem();
2240 ret = set_selection(arg, tty, 1);
2241 release_console_sem();
2242 break;
2243 case 3:
2244 ret = paste_selection(tty);
2245 break;
2246 case 4:
2247 unblank_screen();
2248 break;
2249 case 5:
2250 ret = sel_loadlut(arg);
2251 break;
2252 case 6:
2253
2254
2255
2256
2257
2258
2259
2260 data = shift_state;
2261 ret = __put_user(data, (char *) arg);
2262 break;
2263 case 7:
2264 data = mouse_reporting();
2265 ret = __put_user(data, (char *) arg);
2266 break;
2267 case 10:
2268 set_vesa_blanking(arg);
2269 break;;
2270 case 11:
2271 if (!capable(CAP_SYS_ADMIN)) {
2272 ret = -EPERM;
2273 } else {
2274 if (get_user(data, (char *)arg+1))
2275 ret = -EFAULT;
2276 else
2277 kmsg_redirect = data;
2278 }
2279 break;
2280 case 12:
2281 ret = fg_console;
2282 break;
2283 default:
2284 ret = -EINVAL;
2285 break;
2286 }
2287 return ret;
2288}
2289
2290
2291
2292
2293
2294static int con_write(struct tty_struct * tty, int from_user,
2295 const unsigned char *buf, int count)
2296{
2297 int retval;
2298
2299 pm_access(pm_con);
2300 retval = do_con_write(tty, from_user, buf, count);
2301 con_flush_chars(tty);
2302
2303 return retval;
2304}
2305
2306static void con_put_char(struct tty_struct *tty, unsigned char ch)
2307{
2308 if (in_interrupt())
2309 return;
2310 pm_access(pm_con);
2311 do_con_write(tty, 0, &ch, 1);
2312}
2313
2314static int con_write_room(struct tty_struct *tty)
2315{
2316 if (tty->stopped)
2317 return 0;
2318 return 4096;
2319}
2320
2321static int con_chars_in_buffer(struct tty_struct *tty)
2322{
2323 return 0;
2324}
2325
2326
2327
2328
2329
2330
2331static void con_throttle(struct tty_struct *tty)
2332{
2333}
2334
2335static void con_unthrottle(struct tty_struct *tty)
2336{
2337 struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2338
2339 wake_up_interruptible(&vt->paste_wait);
2340}
2341
2342
2343
2344
2345static void con_stop(struct tty_struct *tty)
2346{
2347 int console_num;
2348 if (!tty)
2349 return;
2350 console_num = MINOR(tty->device) - (tty->driver.minor_start);
2351 if (!vc_cons_allocated(console_num))
2352 return;
2353 set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
2354 set_leds();
2355}
2356
2357
2358
2359
2360static void con_start(struct tty_struct *tty)
2361{
2362 int console_num;
2363 if (!tty)
2364 return;
2365 console_num = MINOR(tty->device) - (tty->driver.minor_start);
2366 if (!vc_cons_allocated(console_num))
2367 return;
2368 clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
2369 set_leds();
2370}
2371
2372
2373
2374
2375
2376static void con_flush_chars(struct tty_struct *tty)
2377{
2378 struct vt_struct *vt;
2379
2380 if (in_interrupt())
2381 return;
2382
2383 pm_access(pm_con);
2384 lock_kernel();
2385 acquire_console_sem();
2386 vt = (struct vt_struct *)tty->driver_data;
2387 if (vt)
2388 set_cursor(vt->vc_num);
2389 release_console_sem();
2390 unlock_kernel();
2391}
2392
2393
2394
2395
2396static int con_open(struct tty_struct *tty, struct file * filp)
2397{
2398 unsigned int currcons;
2399 int i;
2400
2401 currcons = MINOR(tty->device) - tty->driver.minor_start;
2402
2403 i = vc_allocate(currcons);
2404 if (i)
2405 return i;
2406
2407 vt_cons[currcons]->vc_num = currcons;
2408 tty->driver_data = vt_cons[currcons];
2409
2410 if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2411 tty->winsize.ws_row = video_num_lines;
2412 tty->winsize.ws_col = video_num_columns;
2413 }
2414 if (tty->count == 1)
2415 vcs_make_devfs (currcons, 0);
2416 return 0;
2417}
2418
2419static void con_close(struct tty_struct *tty, struct file * filp)
2420{
2421 if (!tty)
2422 return;
2423 if (tty->count != 1) return;
2424 vcs_make_devfs (MINOR (tty->device) - tty->driver.minor_start, 1);
2425 tty->driver_data = 0;
2426}
2427
2428static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear)
2429{
2430 int j, k ;
2431
2432 video_num_columns = cols;
2433 video_num_lines = rows;
2434 video_size_row = cols<<1;
2435 screenbuf_size = video_num_lines * video_size_row;
2436
2437 set_origin(currcons);
2438 pos = origin;
2439 reset_vc(currcons);
2440 for (j=k=0; j<16; j++) {
2441 vc_cons[currcons].d->vc_palette[k++] = default_red[j] ;
2442 vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
2443 vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
2444 }
2445 def_color = 0x07;
2446 ulcolor = 0x0f;
2447 halfcolor = 0x08;
2448 init_waitqueue_head(&vt_cons[currcons]->paste_wait);
2449 reset_terminal(currcons, do_clear);
2450}
2451
2452
2453
2454
2455
2456
2457
2458struct tty_driver console_driver;
2459static int console_refcount;
2460
2461void __init con_init(void)
2462{
2463 const char *display_desc = NULL;
2464 unsigned int currcons = 0;
2465
2466 if (conswitchp)
2467 display_desc = conswitchp->con_startup();
2468 if (!display_desc) {
2469 fg_console = 0;
2470 return;
2471 }
2472
2473 memset(&console_driver, 0, sizeof(struct tty_driver));
2474 console_driver.magic = TTY_DRIVER_MAGIC;
2475 console_driver.name = "vc/%d";
2476 console_driver.name_base = 1;
2477 console_driver.major = TTY_MAJOR;
2478 console_driver.minor_start = 1;
2479 console_driver.num = MAX_NR_CONSOLES;
2480 console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
2481 console_driver.init_termios = tty_std_termios;
2482 console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
2483
2484
2485
2486
2487 console_driver.flags |= TTY_DRIVER_NO_DEVFS;
2488 console_driver.refcount = &console_refcount;
2489 console_driver.table = console_table;
2490 console_driver.termios = console_termios;
2491 console_driver.termios_locked = console_termios_locked;
2492
2493 console_driver.open = con_open;
2494 console_driver.close = con_close;
2495 console_driver.write = con_write;
2496 console_driver.write_room = con_write_room;
2497 console_driver.put_char = con_put_char;
2498 console_driver.flush_chars = con_flush_chars;
2499 console_driver.chars_in_buffer = con_chars_in_buffer;
2500 console_driver.ioctl = vt_ioctl;
2501 console_driver.stop = con_stop;
2502 console_driver.start = con_start;
2503 console_driver.throttle = con_throttle;
2504 console_driver.unthrottle = con_unthrottle;
2505
2506 if (tty_register_driver(&console_driver))
2507 panic("Couldn't register console driver\n");
2508
2509 init_timer(&console_timer);
2510 console_timer.function = blank_screen;
2511 if (blankinterval) {
2512 mod_timer(&console_timer, jiffies + blankinterval);
2513 }
2514
2515
2516
2517
2518 for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
2519 vc_cons[currcons].d = (struct vc_data *)
2520 alloc_bootmem(sizeof(struct vc_data));
2521 vt_cons[currcons] = (struct vt_struct *)
2522 alloc_bootmem(sizeof(struct vt_struct));
2523 visual_init(currcons, 1);
2524 screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size);
2525 kmalloced = 0;
2526 vc_init(currcons, video_num_lines, video_num_columns,
2527 currcons || !sw->con_save_screen);
2528 }
2529 currcons = fg_console = 0;
2530 master_display_fg = vc_cons[currcons].d;
2531 set_origin(currcons);
2532 save_screen(currcons);
2533 gotoxy(currcons,x,y);
2534 csi_J(currcons, 0);
2535 update_screen(fg_console);
2536 printk("Console: %s %s %dx%d",
2537 can_do_color ? "colour" : "mono",
2538 display_desc, video_num_columns, video_num_lines);
2539 printable = 1;
2540 printk("\n");
2541
2542#ifdef CONFIG_VT_CONSOLE
2543 register_console(&vt_console_driver);
2544#endif
2545}
2546
2547#ifndef VT_SINGLE_DRIVER
2548
2549static void clear_buffer_attributes(int currcons)
2550{
2551 unsigned short *p = (unsigned short *) origin;
2552 int count = screenbuf_size/2;
2553 int mask = hi_font_mask | 0xff;
2554
2555 for (; count > 0; count--, p++) {
2556 scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
2557 }
2558}
2559
2560
2561
2562
2563
2564
2565
2566void take_over_console(const struct consw *csw, int first, int last, int deflt)
2567{
2568 int i, j = -1;
2569 const char *desc;
2570
2571 desc = csw->con_startup();
2572 if (!desc) return;
2573 if (deflt)
2574 conswitchp = csw;
2575
2576 for (i = first; i <= last; i++) {
2577 int old_was_color;
2578 int currcons = i;
2579
2580 con_driver_map[i] = csw;
2581
2582 if (!vc_cons[i].d || !vc_cons[i].d->vc_sw)
2583 continue;
2584
2585 j = i;
2586 if (IS_VISIBLE)
2587 save_screen(i);
2588 old_was_color = vc_cons[i].d->vc_can_do_color;
2589 vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
2590 visual_init(i, 0);
2591 update_attr(i);
2592
2593
2594
2595
2596
2597 if (old_was_color != vc_cons[i].d->vc_can_do_color)
2598 clear_buffer_attributes(i);
2599
2600 if (IS_VISIBLE)
2601 update_screen(i);
2602 }
2603 printk("Console: switching ");
2604 if (!deflt)
2605 printk("consoles %d-%d ", first+1, last+1);
2606 if (j >= 0)
2607 printk("to %s %s %dx%d\n",
2608 vc_cons[j].d->vc_can_do_color ? "colour" : "mono",
2609 desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows);
2610 else
2611 printk("to %s\n", desc);
2612}
2613
2614void give_up_console(const struct consw *csw)
2615{
2616 int i;
2617
2618 for(i = 0; i < MAX_NR_CONSOLES; i++)
2619 if (con_driver_map[i] == csw)
2620 con_driver_map[i] = NULL;
2621}
2622
2623#endif
2624
2625
2626
2627
2628
2629static void set_vesa_blanking(unsigned long arg)
2630{
2631 char *argp = (char *)arg + 1;
2632 unsigned int mode;
2633 if (get_user(mode, argp) == 0)
2634 vesa_blank_mode = (mode < 4) ? mode : 0;
2635}
2636
2637
2638
2639
2640
2641void __init con_init_devfs (void)
2642{
2643 int i;
2644
2645 for (i = 0; i < console_driver.num; i++)
2646 tty_register_devfs (&console_driver, DEVFS_FL_AOPEN_NOTIFY,
2647 console_driver.minor_start + i);
2648}
2649
2650
2651
2652
2653static void vesa_powerdown(void)
2654{
2655 struct vc_data *c = vc_cons[fg_console].d;
2656
2657
2658
2659
2660
2661
2662 switch (vesa_blank_mode) {
2663 case VESA_NO_BLANKING:
2664 c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1);
2665 break;
2666 case VESA_VSYNC_SUSPEND:
2667 case VESA_HSYNC_SUSPEND:
2668 c->vc_sw->con_blank(c, VESA_POWERDOWN+1);
2669 break;
2670 }
2671}
2672
2673
2674
2675
2676static void vesa_powerdown_screen(unsigned long dummy)
2677{
2678 console_timer.function = unblank_screen_t;
2679
2680 vesa_powerdown();
2681}
2682
2683static void timer_do_blank_screen(int entering_gfx, int from_timer_handler)
2684{
2685 int currcons = fg_console;
2686 int i;
2687
2688 if (console_blanked)
2689 return;
2690
2691
2692 if (entering_gfx) {
2693 hide_cursor(currcons);
2694 save_screen(currcons);
2695 sw->con_blank(vc_cons[currcons].d, -1);
2696 console_blanked = fg_console + 1;
2697 set_origin(currcons);
2698 return;
2699 }
2700
2701
2702 if (vcmode != KD_TEXT) {
2703 console_blanked = fg_console + 1;
2704 return;
2705 }
2706
2707 hide_cursor(currcons);
2708 if (!from_timer_handler)
2709 del_timer_sync(&console_timer);
2710 if (vesa_off_interval) {
2711 console_timer.function = vesa_powerdown_screen;
2712 mod_timer(&console_timer, jiffies + vesa_off_interval);
2713 } else {
2714 if (!from_timer_handler)
2715 del_timer_sync(&console_timer);
2716 console_timer.function = unblank_screen_t;
2717 }
2718
2719 save_screen(currcons);
2720
2721 i = sw->con_blank(vc_cons[currcons].d, 1);
2722 console_blanked = fg_console + 1;
2723 if (i)
2724 set_origin(currcons);
2725
2726 if (console_blank_hook && console_blank_hook(1))
2727 return;
2728 if (vesa_blank_mode)
2729 sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
2730}
2731
2732void do_blank_screen(int entering_gfx)
2733{
2734 timer_do_blank_screen(entering_gfx, 0);
2735}
2736
2737
2738
2739
2740static void unblank_screen_t(unsigned long dummy)
2741{
2742 unblank_screen();
2743}
2744
2745
2746
2747
2748void unblank_screen(void)
2749{
2750 int currcons;
2751
2752 if (!console_blanked)
2753 return;
2754 if (!vc_cons_allocated(fg_console)) {
2755
2756 printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
2757 return;
2758 }
2759 currcons = fg_console;
2760 if (vcmode != KD_TEXT)
2761 return;
2762
2763 console_timer.function = blank_screen;
2764 if (blankinterval) {
2765 mod_timer(&console_timer, jiffies + blankinterval);
2766 }
2767
2768 console_blanked = 0;
2769 if (console_blank_hook)
2770 console_blank_hook(0);
2771 set_palette(currcons);
2772 if (sw->con_blank(vc_cons[currcons].d, 0))
2773
2774 update_screen(fg_console);
2775 set_cursor(fg_console);
2776}
2777
2778
2779
2780
2781static void blank_screen(unsigned long dummy)
2782{
2783 timer_do_blank_screen(0, 1);
2784}
2785
2786void disable_console_blank(void)
2787{
2788 del_timer_sync(&console_timer);
2789 blankinterval = 0;
2790}
2791
2792void poke_blanked_console(void)
2793{
2794 del_timer(&console_timer);
2795 if (!vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
2796 return;
2797 if (console_blanked) {
2798 console_timer.function = unblank_screen_t;
2799 mod_timer(&console_timer, jiffies);
2800 } else if (blankinterval) {
2801 mod_timer(&console_timer, jiffies + blankinterval);
2802 }
2803}
2804
2805
2806
2807
2808
2809void set_palette(int currcons)
2810{
2811 if (vcmode != KD_GRAPHICS)
2812 sw->con_set_palette(vc_cons[currcons].d, color_table);
2813}
2814
2815static int set_get_cmap(unsigned char *arg, int set)
2816{
2817 int i, j, k;
2818
2819 for (i = 0; i < 16; i++)
2820 if (set) {
2821 get_user(default_red[i], arg++);
2822 get_user(default_grn[i], arg++);
2823 get_user(default_blu[i], arg++);
2824 } else {
2825 put_user(default_red[i], arg++);
2826 put_user(default_grn[i], arg++);
2827 put_user(default_blu[i], arg++);
2828 }
2829 if (set) {
2830 for (i = 0; i < MAX_NR_CONSOLES; i++)
2831 if (vc_cons_allocated(i)) {
2832 for (j = k = 0; j < 16; j++) {
2833 vc_cons[i].d->vc_palette[k++] = default_red[j];
2834 vc_cons[i].d->vc_palette[k++] = default_grn[j];
2835 vc_cons[i].d->vc_palette[k++] = default_blu[j];
2836 }
2837 set_palette(i);
2838 }
2839 }
2840 return 0;
2841}
2842
2843
2844
2845
2846
2847
2848int con_set_cmap(unsigned char *arg)
2849{
2850 return set_get_cmap (arg,1);
2851}
2852
2853int con_get_cmap(unsigned char *arg)
2854{
2855 return set_get_cmap (arg,0);
2856}
2857
2858void reset_palette(int currcons)
2859{
2860 int j, k;
2861 for (j=k=0; j<16; j++) {
2862 palette[k++] = default_red[j];
2863 palette[k++] = default_grn[j];
2864 palette[k++] = default_blu[j];
2865 }
2866 set_palette(currcons);
2867}
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882#define max_font_size 65536
2883
2884int con_font_op(int currcons, struct console_font_op *op)
2885{
2886 int rc = -EINVAL;
2887 int size = max_font_size, set;
2888 u8 *temp = NULL;
2889 struct console_font_op old_op;
2890
2891 if (vt_cons[currcons]->vc_mode != KD_TEXT)
2892 goto quit;
2893 memcpy(&old_op, op, sizeof(old_op));
2894 if (op->op == KD_FONT_OP_SET) {
2895 if (!op->data)
2896 return -EINVAL;
2897 if (op->charcount > 512)
2898 goto quit;
2899 if (!op->height) {
2900 int h, i;
2901 u8 *charmap = op->data, tmp;
2902
2903
2904
2905 if (!(op->flags & KD_FONT_FLAG_OLD))
2906 goto quit;
2907 rc = -EFAULT;
2908 for (h = 32; h > 0; h--)
2909 for (i = 0; i < op->charcount; i++) {
2910 if (get_user(tmp, &charmap[32*i+h-1]))
2911 goto quit;
2912 if (tmp)
2913 goto nonzero;
2914 }
2915 rc = -EINVAL;
2916 goto quit;
2917 nonzero:
2918 rc = -EINVAL;
2919 op->height = h;
2920 }
2921 if (op->width > 32 || op->height > 32)
2922 goto quit;
2923 size = (op->width+7)/8 * 32 * op->charcount;
2924 if (size > max_font_size)
2925 return -ENOSPC;
2926 set = 1;
2927 } else if (op->op == KD_FONT_OP_GET)
2928 set = 0;
2929 else
2930 return sw->con_font_op(vc_cons[currcons].d, op);
2931 if (op->data) {
2932 temp = kmalloc(size, GFP_KERNEL);
2933 if (!temp)
2934 return -ENOMEM;
2935 if (set && copy_from_user(temp, op->data, size)) {
2936 rc = -EFAULT;
2937 goto quit;
2938 }
2939 op->data = temp;
2940 }
2941
2942 acquire_console_sem();
2943 rc = sw->con_font_op(vc_cons[currcons].d, op);
2944 release_console_sem();
2945
2946 op->data = old_op.data;
2947 if (!rc && !set) {
2948 int c = (op->width+7)/8 * 32 * op->charcount;
2949
2950 if (op->data && op->charcount > old_op.charcount)
2951 rc = -ENOSPC;
2952 if (!(op->flags & KD_FONT_FLAG_OLD)) {
2953 if (op->width > old_op.width ||
2954 op->height > old_op.height)
2955 rc = -ENOSPC;
2956 } else {
2957 if (op->width != 8)
2958 rc = -EIO;
2959 else if ((old_op.height && op->height > old_op.height) ||
2960 op->height > 32)
2961 rc = -ENOSPC;
2962 }
2963 if (!rc && op->data && copy_to_user(op->data, temp, c))
2964 rc = -EFAULT;
2965 }
2966quit: if (temp)
2967 kfree(temp);
2968 return rc;
2969}
2970
2971
2972
2973
2974
2975
2976u16 screen_glyph(int currcons, int offset)
2977{
2978 u16 w = scr_readw(screenpos(currcons, offset, 1));
2979 u16 c = w & 0xff;
2980
2981 if (w & hi_font_mask)
2982 c |= 0x100;
2983 return c;
2984}
2985
2986
2987unsigned short *screen_pos(int currcons, int w_offset, int viewed)
2988{
2989 return screenpos(currcons, 2 * w_offset, viewed);
2990}
2991
2992void getconsxy(int currcons, char *p)
2993{
2994 p[0] = x;
2995 p[1] = y;
2996}
2997
2998void putconsxy(int currcons, char *p)
2999{
3000 gotoxy(currcons, p[0], p[1]);
3001 set_cursor(currcons);
3002}
3003
3004u16 vcs_scr_readw(int currcons, const u16 *org)
3005{
3006 if ((unsigned long)org == pos && softcursor_original != -1)
3007 return softcursor_original;
3008 return scr_readw(org);
3009}
3010
3011void vcs_scr_writew(int currcons, u16 val, u16 *org)
3012{
3013 scr_writew(val, org);
3014 if ((unsigned long)org == pos) {
3015 softcursor_original = -1;
3016 add_softcursor(currcons);
3017 }
3018}
3019
3020static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data)
3021{
3022 switch (rqst)
3023 {
3024 case PM_RESUME:
3025 unblank_screen();
3026 break;
3027 case PM_SUSPEND:
3028 do_blank_screen(0);
3029 break;
3030 }
3031 return 0;
3032}
3033
3034
3035
3036
3037
3038EXPORT_SYMBOL(color_table);
3039EXPORT_SYMBOL(default_red);
3040EXPORT_SYMBOL(default_grn);
3041EXPORT_SYMBOL(default_blu);
3042EXPORT_SYMBOL(video_font_height);
3043EXPORT_SYMBOL(video_scan_lines);
3044EXPORT_SYMBOL(vc_resize);
3045EXPORT_SYMBOL(fg_console);
3046EXPORT_SYMBOL(console_blank_hook);
3047#ifdef CONFIG_VT
3048EXPORT_SYMBOL(vt_cons);
3049#endif
3050#ifndef VT_SINGLE_DRIVER
3051EXPORT_SYMBOL(take_over_console);
3052EXPORT_SYMBOL(give_up_console);
3053#endif
3054