This source file includes following definitions.
- gotoxy
- __set_origin
- scrollback
- scrollfront
- set_origin
- hide_cursor
- set_cursor
- scrup
- scrdown
- lf
- ri
- cr
- bs
- del
- csi_J
- csi_K
- update_attr
- default_attr
- csi_m
- respond_string
- cursor_report
- mouse_report
- status_report
- respond_ID
- invert_screen
- set_mode
- setterm_command
- insert_char
- insert_line
- delete_char
- delete_line
- csi_at
- csi_L
- csi_P
- csi_M
- save_cur
- restore_cur
- reset_terminal
- con_stop
- con_start
- con_write
- con_write_room
- con_chars_in_buffer
- poke_blanked_console
- memsetw
- console_print
- con_throttle
- con_unthrottle
- con_init
- kbdsave
- get_scrmem
- set_scrmem
- blank_screen
- unblank_screen
- update_screen
- do_screendump
- con_open
- highlight
- highlight_pointer
- inword
- sel_loadlut
- atedge
- limit
- mouse_reporting
- set_selection
- paste_selection
- clear_selection
- set_get_font
- con_set_font
- con_get_font
- con_set_trans
- con_get_trans
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 #define CAN_LOAD_EGA_FONTS
44
45
46
47
48
49
50
51
52 #include <linux/sched.h>
53 #include <linux/timer.h>
54 #include <linux/interrupt.h>
55 #include <linux/tty.h>
56 #include <linux/tty_flip.h>
57 #include <linux/config.h>
58 #include <linux/kernel.h>
59 #include <linux/string.h>
60 #include <linux/errno.h>
61 #include <linux/kd.h>
62 #include <linux/major.h>
63
64 #include <asm/io.h>
65 #include <asm/system.h>
66 #include <asm/segment.h>
67 #include <asm/bitops.h>
68
69 #include "kbd_kern.h"
70 #include "vt_kern.h"
71
72 #ifndef MIN
73 #define MIN(a,b) ((a) < (b) ? (a) : (b))
74 #endif
75
76 struct tty_driver console_driver;
77 static int console_refcount;
78 static struct tty_struct *console_table[NR_CONSOLES];
79 static struct termios *console_termios[NR_CONSOLES];
80 static struct termios *console_termios_locked[NR_CONSOLES];
81
82 #ifdef CONFIG_SELECTION
83 #include <linux/ctype.h>
84
85
86 int set_selection(const int arg, struct tty_struct *tty);
87 int paste_selection(struct tty_struct *tty);
88 static void clear_selection(void);
89 static void highlight_pointer(const int currcons, const int where);
90
91
92 #define SEL_BUFFER_SIZE 4096
93 static int sel_cons;
94 static int sel_start = -1;
95 static int sel_end;
96 static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
97 #endif
98
99 #define NPAR 16
100
101 extern void vt_init(void);
102 extern void register_console(void (*proc)(const char *));
103 extern void compute_shiftstate(void);
104
105 unsigned long video_num_columns;
106 unsigned long video_num_lines;
107
108 static unsigned char video_type;
109 static unsigned long video_mem_base;
110 static unsigned long video_mem_term;
111 static unsigned long video_size_row;
112 static unsigned char video_page;
113 static unsigned short video_port_reg;
114 static unsigned short video_port_val;
115 static int can_do_color = 0;
116 static int printable = 0;
117
118 static struct {
119 unsigned short vc_video_erase_char;
120 unsigned char vc_attr;
121 unsigned char vc_def_color;
122 unsigned char vc_color;
123 unsigned char vc_s_color;
124 unsigned char vc_ulcolor;
125 unsigned char vc_halfcolor;
126 unsigned long vc_origin;
127 unsigned long vc_scr_end;
128 unsigned long vc_pos;
129 unsigned long vc_x,vc_y;
130 unsigned long vc_top,vc_bottom;
131 unsigned long vc_state;
132 unsigned long vc_npar,vc_par[NPAR];
133 unsigned long vc_video_mem_start;
134 unsigned long vc_video_mem_end;
135 unsigned long vc_saved_x;
136 unsigned long vc_saved_y;
137
138 unsigned long vc_charset : 1;
139 unsigned long vc_s_charset : 1;
140 unsigned long vc_disp_ctrl : 1;
141 unsigned long vc_toggle_meta : 1;
142 unsigned long vc_decscnm : 1;
143 unsigned long vc_decom : 1;
144 unsigned long vc_decawm : 1;
145 unsigned long vc_deccm : 1;
146 unsigned long vc_decim : 1;
147
148 unsigned long vc_intensity : 2;
149 unsigned long vc_underline : 1;
150 unsigned long vc_blink : 1;
151 unsigned long vc_reverse : 1;
152 unsigned long vc_s_intensity : 2;
153 unsigned long vc_s_underline : 1;
154 unsigned long vc_s_blink : 1;
155 unsigned long vc_s_reverse : 1;
156
157 unsigned long vc_ques : 1;
158 unsigned long vc_need_wrap : 1;
159 unsigned long vc_report_mouse : 2;
160 unsigned long vc_tab_stop[5];
161 unsigned char * vc_translate;
162 unsigned char * vc_G0_charset;
163 unsigned char * vc_G1_charset;
164 unsigned char * vc_saved_G0;
165 unsigned char * vc_saved_G1;
166
167 } vc_cons [NR_CONSOLES];
168
169 unsigned short *vc_scrbuf[NR_CONSOLES];
170 static unsigned short * vc_scrmembuf;
171 static int console_blanked = 0;
172
173 #define origin (vc_cons[currcons].vc_origin)
174 #define scr_end (vc_cons[currcons].vc_scr_end)
175 #define pos (vc_cons[currcons].vc_pos)
176 #define top (vc_cons[currcons].vc_top)
177 #define bottom (vc_cons[currcons].vc_bottom)
178 #define x (vc_cons[currcons].vc_x)
179 #define y (vc_cons[currcons].vc_y)
180 #define vc_state (vc_cons[currcons].vc_state)
181 #define npar (vc_cons[currcons].vc_npar)
182 #define par (vc_cons[currcons].vc_par)
183 #define ques (vc_cons[currcons].vc_ques)
184 #define attr (vc_cons[currcons].vc_attr)
185 #define saved_x (vc_cons[currcons].vc_saved_x)
186 #define saved_y (vc_cons[currcons].vc_saved_y)
187 #define translate (vc_cons[currcons].vc_translate)
188 #define G0_charset (vc_cons[currcons].vc_G0_charset)
189 #define G1_charset (vc_cons[currcons].vc_G1_charset)
190 #define saved_G0 (vc_cons[currcons].vc_saved_G0)
191 #define saved_G1 (vc_cons[currcons].vc_saved_G1)
192 #define video_mem_start (vc_cons[currcons].vc_video_mem_start)
193 #define video_mem_end (vc_cons[currcons].vc_video_mem_end)
194 #define video_erase_char (vc_cons[currcons].vc_video_erase_char)
195 #define disp_ctrl (vc_cons[currcons].vc_disp_ctrl)
196 #define toggle_meta (vc_cons[currcons].vc_toggle_meta)
197 #define decscnm (vc_cons[currcons].vc_decscnm)
198 #define decom (vc_cons[currcons].vc_decom)
199 #define decawm (vc_cons[currcons].vc_decawm)
200 #define deccm (vc_cons[currcons].vc_deccm)
201 #define decim (vc_cons[currcons].vc_decim)
202 #define need_wrap (vc_cons[currcons].vc_need_wrap)
203 #define report_mouse (vc_cons[currcons].vc_report_mouse)
204 #define color (vc_cons[currcons].vc_color)
205 #define s_color (vc_cons[currcons].vc_s_color)
206 #define def_color (vc_cons[currcons].vc_def_color)
207 #define foreground (color & 0x0f)
208 #define background (color & 0xf0)
209 #define charset (vc_cons[currcons].vc_charset)
210 #define s_charset (vc_cons[currcons].vc_s_charset)
211 #define intensity (vc_cons[currcons].vc_intensity)
212 #define underline (vc_cons[currcons].vc_underline)
213 #define blink (vc_cons[currcons].vc_blink)
214 #define reverse (vc_cons[currcons].vc_reverse)
215 #define s_intensity (vc_cons[currcons].vc_s_intensity)
216 #define s_underline (vc_cons[currcons].vc_s_underline)
217 #define s_blink (vc_cons[currcons].vc_s_blink)
218 #define s_reverse (vc_cons[currcons].vc_s_reverse)
219 #define ulcolor (vc_cons[currcons].vc_ulcolor)
220 #define halfcolor (vc_cons[currcons].vc_halfcolor)
221 #define tab_stop (vc_cons[currcons].vc_tab_stop)
222 #define vcmode (vt_cons[currcons].vc_mode)
223 #define vtmode (vt_cons[currcons].vt_mode)
224 #define vtpid (vt_cons[currcons].vt_pid)
225 #define vtnewvt (vt_cons[currcons].vt_newvt)
226
227 #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
228 #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
229 #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
230
231 #define decarm VC_REPEAT
232 #define decckm VC_CKMODE
233 #define kbdapplic VC_APPLIC
234 #define kbdraw VC_RAW
235 #define lnm VC_CRLF
236
237 int blankinterval = 10*60*HZ;
238 static int screen_size = 0;
239
240
241
242
243 #define VT100ID "\033[?1;2c"
244 #define VT102ID "\033[?6c"
245
246 static unsigned char * translations[] = {
247
248 (unsigned char *)
249 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
250 "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
251 " !\"#$%&'()*+,-./0123456789:;<=>?"
252 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
253 "`abcdefghijklmnopqrstuvwxyz{|}~\0"
254 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
255 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
256 "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
257 "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
258 "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
259 "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
260 "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
261 "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
262
263 (unsigned char *)
264 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
265 "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
266 " !\"#$%&'()*+,-./0123456789:;<=>?"
267 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
268 "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
269 "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
270 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
271 "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
272 "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
273 "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
274 "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
275 "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
276 "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
277 "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
278
279 (unsigned char *)
280 "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
281 "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
282 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
283 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
284 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
285 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
286 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
287 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
288 "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
289 "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
290 "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
291 "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
292 "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
293 "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
294 "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
295 "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377",
296
297 (unsigned char *)
298 "\000\001\002\003\004\005\006\007\010\011\000\013\000\000\016\017"
299 "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
300 "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
301 "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
302 "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
303 "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
304 "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
305 "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
306 "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
307 "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
308 "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
309 "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
310 "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
311 "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
312 "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
313 "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
314 };
315
316 #define NORM_TRANS (translations[0])
317 #define GRAF_TRANS (translations[1])
318 #define NULL_TRANS (translations[2])
319 #define USER_TRANS (translations[3])
320
321 static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
322 8,12,10,14, 9,13,11,15 };
323
324
325
326
327
328
329 static void gotoxy(int currcons, int new_x, int new_y)
330 {
331 int max_y;
332
333 if (new_x < 0)
334 x = 0;
335 else
336 if (new_x >= video_num_columns)
337 x = video_num_columns - 1;
338 else
339 x = new_x;
340 if (decom) {
341 new_y += top;
342 max_y = bottom;
343 } else
344 max_y = video_num_lines;
345 if (new_y < 0)
346 y = 0;
347 else
348 if (new_y >= max_y)
349 y = max_y - 1;
350 else
351 y = new_y;
352 pos = origin + y*video_size_row + (x<<1);
353 need_wrap = 0;
354 }
355
356
357
358
359 static unsigned short __real_origin;
360 static unsigned short __origin;
361
362 static inline void __set_origin(unsigned short offset)
363 {
364 unsigned long flags;
365 #ifdef CONFIG_SELECTION
366 clear_selection();
367 #endif
368 save_flags(flags); cli();
369 __origin = offset;
370 outb_p(12, video_port_reg);
371 outb_p(offset >> 8, video_port_val);
372 outb_p(13, video_port_reg);
373 outb_p(offset, video_port_val);
374 restore_flags(flags);
375 }
376
377 void scrollback(int lines)
378 {
379 if (!lines)
380 lines = video_num_lines/2;
381 lines *= video_num_columns;
382 lines = __origin - lines;
383 if (lines < 0)
384 lines = 0;
385 __set_origin(lines);
386 }
387
388 void scrollfront(int lines)
389 {
390 if (!lines)
391 lines = video_num_lines/2;
392 lines *= video_num_columns;
393 lines = __origin + lines;
394 if (lines > __real_origin)
395 lines = __real_origin;
396 __set_origin(lines);
397 }
398
399 static void set_origin(int currcons)
400 {
401 if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
402 return;
403 if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
404 return;
405 __real_origin = (origin-video_mem_base) >> 1;
406 __set_origin(__real_origin);
407 }
408
409
410
411
412 static inline void hide_cursor(void)
413 {
414
415
416
417 outb_p(14, video_port_reg);
418 outb_p(0xff&((video_mem_term-video_mem_base)>>9), video_port_val);
419 outb_p(15, video_port_reg);
420 outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
421 }
422
423 static inline void set_cursor(int currcons)
424 {
425 unsigned long flags;
426
427 if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
428 return;
429 if (__real_origin != __origin)
430 set_origin(__real_origin);
431 save_flags(flags); cli();
432 if (deccm) {
433 outb_p(14, video_port_reg);
434 outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
435 outb_p(15, video_port_reg);
436 outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
437 } else
438 hide_cursor();
439 restore_flags(flags);
440 }
441
442 static void scrup(int currcons, unsigned int t, unsigned int b)
443 {
444 int hardscroll = 1;
445
446 if (b > video_num_lines || t >= b)
447 return;
448 if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
449 hardscroll = 0;
450 else if (t || b != video_num_lines)
451 hardscroll = 0;
452 if (hardscroll) {
453 origin += video_size_row;
454 pos += video_size_row;
455 scr_end += video_size_row;
456 if (scr_end > video_mem_end) {
457 __asm__("cld\n\t"
458 "rep\n\t"
459 "movsl\n\t"
460 "movl _video_num_columns,%1\n\t"
461 "rep\n\t"
462 "stosw"
463 :
464 :"a" (video_erase_char),
465 "c" ((video_num_lines-1)*video_num_columns>>1),
466 "D" (video_mem_start),
467 "S" (origin)
468 :"cx","di","si");
469 scr_end -= origin-video_mem_start;
470 pos -= origin-video_mem_start;
471 origin = video_mem_start;
472 } else {
473 __asm__("cld\n\t"
474 "rep\n\t"
475 "stosw"
476 :
477 :"a" (video_erase_char),
478 "c" (video_num_columns),
479 "D" (scr_end-video_size_row)
480 :"cx","di");
481 }
482 set_origin(currcons);
483 } else {
484 __asm__("cld\n\t"
485 "rep\n\t"
486 "movsl\n\t"
487 "movl _video_num_columns,%%ecx\n\t"
488 "rep\n\t"
489 "stosw"
490 :
491 :"a" (video_erase_char),
492 "c" ((b-t-1)*video_num_columns>>1),
493 "D" (origin+video_size_row*t),
494 "S" (origin+video_size_row*(t+1))
495 :"cx","di","si");
496 }
497 }
498
499 static void scrdown(int currcons, unsigned int t, unsigned int b)
500 {
501 if (b > video_num_lines || t >= b)
502 return;
503 __asm__("std\n\t"
504 "rep\n\t"
505 "movsl\n\t"
506 "addl $2,%%edi\n\t"
507 "movl _video_num_columns,%%ecx\n\t"
508 "rep\n\t"
509 "stosw\n\t"
510 "cld"
511 :
512 :"a" (video_erase_char),
513 "c" ((b-t-1)*video_num_columns>>1),
514 "D" (origin+video_size_row*b-4),
515 "S" (origin+video_size_row*(b-1)-4)
516 :"ax","cx","di","si");
517 }
518
519 static void lf(int currcons)
520 {
521 if (y+1<bottom) {
522 y++;
523 pos += video_size_row;
524 return;
525 } else
526 scrup(currcons,top,bottom);
527 need_wrap = 0;
528 }
529
530 static void ri(int currcons)
531 {
532 if (y>top) {
533 y--;
534 pos -= video_size_row;
535 return;
536 } else
537 scrdown(currcons,top,bottom);
538 need_wrap = 0;
539 }
540
541 static inline void cr(int currcons)
542 {
543 pos -= x<<1;
544 need_wrap = x = 0;
545 }
546
547 static inline void bs(int currcons)
548 {
549 if (x) {
550 pos -= 2;
551 x--;
552 need_wrap = 0;
553 }
554 }
555
556 static inline void del(int currcons)
557 {
558 #if 0
559 if (x) {
560 if (!need_wrap) {
561 pos -= 2;
562 x--;
563 }
564 *(unsigned short *)pos = video_erase_char;
565 need_wrap = 0;
566 }
567 #endif
568 }
569
570 static void csi_J(int currcons, int vpar)
571 {
572 unsigned long count;
573 unsigned long start;
574
575 switch (vpar) {
576 case 0:
577 count = (scr_end-pos)>>1;
578 start = pos;
579 break;
580 case 1:
581 count = ((pos-origin)>>1)+1;
582 start = origin;
583 break;
584 case 2:
585 count = video_num_columns * video_num_lines;
586 start = origin;
587 break;
588 default:
589 return;
590 }
591 __asm__("cld\n\t"
592 "rep\n\t"
593 "stosw\n\t"
594 :
595 :"c" (count),
596 "D" (start),"a" (video_erase_char)
597 :"cx","di");
598 need_wrap = 0;
599 }
600
601 static void csi_K(int currcons, int vpar)
602 {
603 long count;
604 long start;
605
606 switch (vpar) {
607 case 0:
608 count = video_num_columns-x;
609 start = pos;
610 break;
611 case 1:
612 start = pos - (x<<1);
613 count = x+1;
614 break;
615 case 2:
616 start = pos - (x<<1);
617 count = video_num_columns;
618 break;
619 default:
620 return;
621 }
622 __asm__("cld\n\t"
623 "rep\n\t"
624 "stosw\n\t"
625 :
626 :"c" (count),
627 "D" (start),"a" (video_erase_char)
628 :"cx","di");
629 need_wrap = 0;
630 }
631
632
633
634
635 static void update_attr(int currcons)
636 {
637 attr = color;
638 if (can_do_color) {
639 if (underline)
640 attr = (attr & 0xf0) | ulcolor;
641 else if (intensity == 0)
642 attr = (attr & 0xf0) | halfcolor;
643 }
644 if (reverse ^ decscnm)
645 attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
646 if (blink)
647 attr ^= 0x80;
648 if (intensity == 2)
649 attr ^= 0x08;
650 if (!can_do_color) {
651 if (underline)
652 attr = (attr & 0xf8) | 0x01;
653 else if (intensity == 0)
654 attr = (attr & 0xf0) | 0x08;
655 }
656 if (decscnm)
657 video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
658 else
659 video_erase_char = (color << 8) | ' ';
660 }
661
662 static void default_attr(int currcons)
663 {
664 intensity = 1;
665 underline = 0;
666 reverse = 0;
667 blink = 0;
668 color = def_color;
669 }
670
671 static void csi_m(int currcons)
672 {
673 int i;
674
675 for (i=0;i<=npar;i++)
676 switch (par[i]) {
677 case 0:
678 default_attr(currcons);
679 break;
680 case 1:
681 intensity = 2;
682 break;
683 case 2:
684 intensity = 0;
685 break;
686 case 4:
687 underline = 1;
688 break;
689 case 5:
690 blink = 1;
691 break;
692 case 7:
693 reverse = 1;
694 break;
695 case 10:
696
697
698
699
700 translate = (charset == 0
701 ? G0_charset
702 : G1_charset);
703 disp_ctrl = 0;
704 toggle_meta = 0;
705 break;
706 case 11:
707
708
709
710 translate = NULL_TRANS;
711 disp_ctrl = 1;
712 toggle_meta = 0;
713 break;
714 case 12:
715
716
717
718 translate = NULL_TRANS;
719 disp_ctrl = 1;
720 toggle_meta = 1;
721 break;
722 case 21:
723 case 22:
724 intensity = 1;
725 break;
726 case 24:
727 underline = 0;
728 break;
729 case 25:
730 blink = 0;
731 break;
732 case 27:
733 reverse = 0;
734 break;
735 case 38:
736
737
738
739
740 color = (def_color & 0x0f) | background;
741 underline = 1;
742 break;
743 case 39:
744
745
746
747
748 color = (def_color & 0x0f) | background;
749 underline = 0;
750 break;
751 case 49:
752 color = (def_color & 0xf0) | foreground;
753 break;
754 default:
755 if (par[i] >= 30 && par[i] <= 37)
756 color = color_table[par[i]-30]
757 | background;
758 else if (par[i] >= 40 && par[i] <= 47)
759 color = (color_table[par[i]-40]<<4)
760 | foreground;
761 break;
762 }
763 update_attr(currcons);
764 }
765
766 static void respond_string(char * p, struct tty_struct * tty)
767 {
768 while (*p) {
769 tty_insert_flip_char(tty, *p, 0);
770 p++;
771 }
772 tty_schedule_flip(tty);
773 }
774
775 static void cursor_report(int currcons, struct tty_struct * tty)
776 {
777 char buf[40];
778
779 sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
780 respond_string(buf, tty);
781 }
782
783 static void mouse_report(int currcons, struct tty_struct * tty,
784 int butt, int mrx, int mry)
785 {
786 char buf[8];
787
788 sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
789 (char)('!' + mry));
790 respond_string(buf, tty);
791 }
792
793 static inline void status_report(int currcons, struct tty_struct * tty)
794 {
795 respond_string("\033[0n", tty);
796 }
797
798 static inline void respond_ID(int currcons, struct tty_struct * tty)
799 {
800 respond_string(VT102ID, tty);
801 }
802
803 static void invert_screen(int currcons) {
804 unsigned char *p;
805
806 if (can_do_color)
807 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
808 *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
809 else
810 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
811 *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
812 }
813
814 static void set_mode(int currcons, int on_off)
815 {
816 int i;
817
818 for (i=0; i<=npar; i++)
819 if (ques) switch(par[i]) {
820 case 1:
821 if (on_off)
822 set_kbd(decckm);
823 else
824 clr_kbd(decckm);
825 break;
826 case 3:
827 csi_J(currcons,2);
828 gotoxy(currcons,0,0);
829 break;
830 case 5:
831 if (decscnm != on_off) {
832 decscnm = on_off;
833 invert_screen(currcons);
834 update_attr(currcons);
835 }
836 break;
837 case 6:
838 decom = on_off;
839 gotoxy(currcons,0,0);
840 break;
841 case 7:
842 decawm = on_off;
843 break;
844 case 8:
845 if (on_off)
846 set_kbd(decarm);
847 else
848 clr_kbd(decarm);
849 break;
850 case 9:
851 report_mouse = on_off ? 1 : 0;
852 break;
853 case 25:
854 deccm = on_off;
855 set_cursor(currcons);
856 break;
857 case 1000:
858 report_mouse = on_off ? 2 : 0;
859 break;
860 } else switch(par[i]) {
861 case 4:
862 decim = on_off;
863 break;
864 case 20:
865 if (on_off)
866 set_kbd(lnm);
867 else
868 clr_kbd(lnm);
869 break;
870 }
871 }
872
873 static void setterm_command(int currcons)
874 {
875 switch(par[0]) {
876 case 1:
877 if (can_do_color && par[1] < 16) {
878 ulcolor = color_table[par[1]];
879 if (underline)
880 update_attr(currcons);
881 }
882 break;
883 case 2:
884 if (can_do_color && par[1] < 16) {
885 halfcolor = color_table[par[1]];
886 if (intensity == 0)
887 update_attr(currcons);
888 }
889 break;
890 case 8:
891 def_color = attr;
892 default_attr(currcons);
893 update_attr(currcons);
894 break;
895 case 9:
896 blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
897 break;
898 }
899 }
900
901 static void insert_char(int currcons)
902 {
903 unsigned int i = x;
904 unsigned short tmp, old = video_erase_char;
905 unsigned short * p = (unsigned short *) pos;
906
907 while (i++ < video_num_columns) {
908 tmp = *p;
909 *p = old;
910 old = tmp;
911 p++;
912 }
913 need_wrap = 0;
914 }
915
916 static void insert_line(int currcons)
917 {
918 scrdown(currcons,y,bottom);
919 need_wrap = 0;
920 }
921
922 static void delete_char(int currcons)
923 {
924 unsigned int i = x;
925 unsigned short * p = (unsigned short *) pos;
926
927 while (++i < video_num_columns) {
928 *p = *(p+1);
929 p++;
930 }
931 *p = video_erase_char;
932 need_wrap = 0;
933 }
934
935 static void delete_line(int currcons)
936 {
937 scrup(currcons,y,bottom);
938 need_wrap = 0;
939 }
940
941 static void csi_at(int currcons, unsigned int nr)
942 {
943 if (nr > video_num_columns)
944 nr = video_num_columns;
945 else if (!nr)
946 nr = 1;
947 while (nr--)
948 insert_char(currcons);
949 }
950
951 static void csi_L(int currcons, unsigned int nr)
952 {
953 if (nr > video_num_lines)
954 nr = video_num_lines;
955 else if (!nr)
956 nr = 1;
957 while (nr--)
958 insert_line(currcons);
959 }
960
961 static void csi_P(int currcons, unsigned int nr)
962 {
963 if (nr > video_num_columns)
964 nr = video_num_columns;
965 else if (!nr)
966 nr = 1;
967 while (nr--)
968 delete_char(currcons);
969 }
970
971 static void csi_M(int currcons, unsigned int nr)
972 {
973 if (nr > video_num_lines)
974 nr = video_num_lines;
975 else if (!nr)
976 nr=1;
977 while (nr--)
978 delete_line(currcons);
979 }
980
981 static void save_cur(int currcons)
982 {
983 saved_x = x;
984 saved_y = y;
985 s_intensity = intensity;
986 s_underline = underline;
987 s_blink = blink;
988 s_reverse = reverse;
989 s_charset = charset;
990 s_color = color;
991 saved_G0 = G0_charset;
992 saved_G1 = G1_charset;
993 }
994
995 static void restore_cur(int currcons)
996 {
997 gotoxy(currcons,saved_x,saved_y);
998 intensity = s_intensity;
999 underline = s_underline;
1000 blink = s_blink;
1001 reverse = s_reverse;
1002 charset = s_charset;
1003 color = s_color;
1004 G0_charset = saved_G0;
1005 G1_charset = saved_G1;
1006 translate = charset ? G1_charset : G0_charset;
1007 update_attr(currcons);
1008 need_wrap = 0;
1009 }
1010
1011 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
1012 EShash, ESsetG0, ESsetG1, ESignore };
1013
1014 static void reset_terminal(int currcons, int do_clear)
1015 {
1016 top = 0;
1017 bottom = video_num_lines;
1018 vc_state = ESnormal;
1019 ques = 0;
1020 translate = NORM_TRANS;
1021 G0_charset = NORM_TRANS;
1022 G1_charset = GRAF_TRANS;
1023 charset = 0;
1024 need_wrap = 0;
1025 report_mouse = 0;
1026
1027 disp_ctrl = 0;
1028 toggle_meta = 0;
1029
1030 decscnm = 0;
1031 decom = 0;
1032 decawm = 1;
1033 deccm = 1;
1034 decim = 0;
1035
1036 set_kbd(decarm);
1037 clr_kbd(decckm);
1038 clr_kbd(kbdapplic);
1039 clr_kbd(lnm);
1040 kbd_table[currcons].lockstate = 0;
1041 kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
1042 set_leds();
1043
1044 default_attr(currcons);
1045 update_attr(currcons);
1046
1047 tab_stop[0] = 0x01010100;
1048 tab_stop[1] =
1049 tab_stop[2] =
1050 tab_stop[3] =
1051 tab_stop[4] = 0x01010101;
1052
1053 if (do_clear) {
1054 gotoxy(currcons,0,0);
1055 csi_J(currcons,2);
1056 save_cur(currcons);
1057 }
1058 }
1059
1060
1061
1062
1063 static void con_stop(struct tty_struct *tty)
1064 {
1065 set_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
1066 set_leds();
1067 }
1068
1069
1070
1071
1072 static void con_start(struct tty_struct *tty)
1073 {
1074 clr_vc_kbd_led(kbd_table + fg_console, VC_SCROLLOCK);
1075 set_leds();
1076 }
1077
1078 static int con_write(struct tty_struct * tty, int from_user,
1079 unsigned char *buf, int count)
1080 {
1081 int c, n = 0;
1082 unsigned int currcons;
1083 struct vt_struct *vt = tty->driver_data;
1084
1085 currcons = vt->vc_num;
1086 if (currcons >= NR_CONSOLES) {
1087 printk("con_write: illegal vc index (%d)\n", currcons);
1088 return 0;
1089 }
1090 #ifdef CONFIG_SELECTION
1091
1092 if (currcons == sel_cons)
1093 clear_selection();
1094 #endif
1095 disable_bh(KEYBOARD_BH);
1096 while (!tty->stopped && count) {
1097 c = from_user ? get_fs_byte(buf) : *buf;
1098 buf++; n++; count--;
1099 if (vc_state == ESnormal
1100 && (c >= 32 || (disp_ctrl && (c&0x7f) != 27))
1101 && (toggle_meta ? translate[c|0x80] : translate[c])) {
1102 if (toggle_meta)
1103 c |= 0x80;
1104 if (need_wrap) {
1105 cr(currcons);
1106 lf(currcons);
1107 }
1108 if (decim)
1109 insert_char(currcons);
1110 c = translate[c];
1111 *(unsigned short *) pos = (attr << 8) + c;
1112 if (x == video_num_columns - 1)
1113 need_wrap = decawm;
1114 else {
1115 x++;
1116 pos+=2;
1117 }
1118 continue;
1119 }
1120
1121
1122
1123
1124
1125 switch (c) {
1126 case 7:
1127 kd_mksound(0x637, HZ/8);
1128 continue;
1129 case 8:
1130 bs(currcons);
1131 continue;
1132 case 9:
1133 pos -= (x << 1);
1134 while (x < video_num_columns - 1) {
1135 x++;
1136 if (tab_stop[x >> 5] & (1 << (x & 31)))
1137 break;
1138 }
1139 pos += (x << 1);
1140 continue;
1141 case 10: case 11: case 12:
1142 lf(currcons);
1143 if (!is_kbd(lnm))
1144 continue;
1145 case 13:
1146 cr(currcons);
1147 continue;
1148 case 14:
1149 charset = 1;
1150 translate = G1_charset;
1151 continue;
1152 case 15:
1153 charset = 0;
1154 translate = G0_charset;
1155 continue;
1156 case 24: case 26:
1157 vc_state = ESnormal;
1158 continue;
1159 case 27:
1160 vc_state = ESesc;
1161 continue;
1162 case 127:
1163 del(currcons);
1164 continue;
1165 case 128+27:
1166 vc_state = ESsquare;
1167 continue;
1168 }
1169 switch(vc_state) {
1170 case ESesc:
1171 vc_state = ESnormal;
1172 switch (c) {
1173 case '[':
1174 vc_state = ESsquare;
1175 continue;
1176 case 'E':
1177 cr(currcons);
1178 lf(currcons);
1179 continue;
1180 case 'M':
1181 ri(currcons);
1182 continue;
1183 case 'D':
1184 lf(currcons);
1185 continue;
1186 case 'H':
1187 tab_stop[x >> 5] |= (1 << (x & 31));
1188 continue;
1189 case 'Z':
1190 respond_ID(currcons,tty);
1191 continue;
1192 case '7':
1193 save_cur(currcons);
1194 continue;
1195 case '8':
1196 restore_cur(currcons);
1197 continue;
1198 case '(':
1199 vc_state = ESsetG0;
1200 continue;
1201 case ')':
1202 vc_state = ESsetG1;
1203 continue;
1204 case '#':
1205 vc_state = EShash;
1206 continue;
1207 case 'c':
1208 reset_terminal(currcons,1);
1209 continue;
1210 case '>':
1211 clr_kbd(kbdapplic);
1212 continue;
1213 case '=':
1214 set_kbd(kbdapplic);
1215 continue;
1216 }
1217 continue;
1218 case ESsquare:
1219 for(npar = 0 ; npar < NPAR ; npar++)
1220 par[npar] = 0;
1221 npar = 0;
1222 vc_state = ESgetpars;
1223 if (c == '[') {
1224 vc_state=ESfunckey;
1225 continue;
1226 }
1227 ques = (c=='?');
1228 if (ques)
1229 continue;
1230 case ESgetpars:
1231 if (c==';' && npar<NPAR-1) {
1232 npar++;
1233 continue;
1234 } else if (c>='0' && c<='9') {
1235 par[npar] *= 10;
1236 par[npar] += c-'0';
1237 continue;
1238 } else vc_state=ESgotpars;
1239 case ESgotpars:
1240 vc_state = ESnormal;
1241 switch(c) {
1242 case 'h':
1243 set_mode(currcons,1);
1244 continue;
1245 case 'l':
1246 set_mode(currcons,0);
1247 continue;
1248 case 'n':
1249 if (!ques)
1250 if (par[0] == 5)
1251 status_report(currcons,tty);
1252 else if (par[0] == 6)
1253 cursor_report(currcons,tty);
1254 continue;
1255 }
1256 if (ques) {
1257 ques = 0;
1258 continue;
1259 }
1260 switch(c) {
1261 case 'G': case '`':
1262 if (par[0]) par[0]--;
1263 gotoxy(currcons,par[0],y);
1264 continue;
1265 case 'A':
1266 if (!par[0]) par[0]++;
1267 gotoxy(currcons,x,y-par[0]);
1268 continue;
1269 case 'B': case 'e':
1270 if (!par[0]) par[0]++;
1271 gotoxy(currcons,x,y+par[0]);
1272 continue;
1273 case 'C': case 'a':
1274 if (!par[0]) par[0]++;
1275 gotoxy(currcons,x+par[0],y);
1276 continue;
1277 case 'D':
1278 if (!par[0]) par[0]++;
1279 gotoxy(currcons,x-par[0],y);
1280 continue;
1281 case 'E':
1282 if (!par[0]) par[0]++;
1283 gotoxy(currcons,0,y+par[0]);
1284 continue;
1285 case 'F':
1286 if (!par[0]) par[0]++;
1287 gotoxy(currcons,0,y-par[0]);
1288 continue;
1289 case 'd':
1290 if (par[0]) par[0]--;
1291 gotoxy(currcons,x,par[0]);
1292 continue;
1293 case 'H': case 'f':
1294 if (par[0]) par[0]--;
1295 if (par[1]) par[1]--;
1296 gotoxy(currcons,par[1],par[0]);
1297 continue;
1298 case 'J':
1299 csi_J(currcons,par[0]);
1300 continue;
1301 case 'K':
1302 csi_K(currcons,par[0]);
1303 continue;
1304 case 'L':
1305 csi_L(currcons,par[0]);
1306 continue;
1307 case 'M':
1308 csi_M(currcons,par[0]);
1309 continue;
1310 case 'P':
1311 csi_P(currcons,par[0]);
1312 continue;
1313 case 'c':
1314 if (!par[0])
1315 respond_ID(currcons,tty);
1316 continue;
1317 case 'g':
1318 if (!par[0])
1319 tab_stop[x >> 5] &= ~(1 << (x & 31));
1320 else if (par[0] == 3) {
1321 tab_stop[0] =
1322 tab_stop[1] =
1323 tab_stop[2] =
1324 tab_stop[3] =
1325 tab_stop[4] = 0;
1326 }
1327 continue;
1328 case 'm':
1329 csi_m(currcons);
1330 continue;
1331 case 'r':
1332 if (!par[0])
1333 par[0]++;
1334 if (!par[1])
1335 par[1] = video_num_lines;
1336
1337 if (par[0] < par[1] &&
1338 par[1] <= video_num_lines) {
1339 top=par[0]-1;
1340 bottom=par[1];
1341 gotoxy(currcons,0,0);
1342 }
1343 continue;
1344 case 's':
1345 save_cur(currcons);
1346 continue;
1347 case 'u':
1348 restore_cur(currcons);
1349 continue;
1350 case '@':
1351 csi_at(currcons,par[0]);
1352 continue;
1353 case ']':
1354 setterm_command(currcons);
1355 continue;
1356 }
1357 continue;
1358 case ESfunckey:
1359 vc_state = ESnormal;
1360 continue;
1361 case EShash:
1362 vc_state = ESnormal;
1363 if (c == '8') {
1364
1365 video_erase_char =
1366 (video_erase_char & 0xff00) | 'E';
1367 csi_J(currcons, 2);
1368 video_erase_char =
1369 (video_erase_char & 0xff00) | ' ';
1370 }
1371 continue;
1372 case ESsetG0:
1373 if (c == '0')
1374 G0_charset = GRAF_TRANS;
1375 else if (c == 'B')
1376 G0_charset = NORM_TRANS;
1377 else if (c == 'U')
1378 G0_charset = NULL_TRANS;
1379 else if (c == 'K')
1380 G0_charset = USER_TRANS;
1381 if (charset == 0)
1382 translate = G0_charset;
1383 vc_state = ESnormal;
1384 continue;
1385 case ESsetG1:
1386 if (c == '0')
1387 G1_charset = GRAF_TRANS;
1388 else if (c == 'B')
1389 G1_charset = NORM_TRANS;
1390 else if (c == 'U')
1391 G1_charset = NULL_TRANS;
1392 else if (c == 'K')
1393 G1_charset = USER_TRANS;
1394 if (charset == 1)
1395 translate = G1_charset;
1396 vc_state = ESnormal;
1397 continue;
1398 default:
1399 vc_state = ESnormal;
1400 }
1401 }
1402 if (vcmode != KD_GRAPHICS)
1403 set_cursor(currcons);
1404 enable_bh(KEYBOARD_BH);
1405 return n;
1406 }
1407
1408 static int con_write_room(struct tty_struct *tty)
1409 {
1410 if (tty->stopped)
1411 return 0;
1412 return 4096;
1413 }
1414
1415 static int con_chars_in_buffer(struct tty_struct *tty)
1416 {
1417 return 0;
1418 }
1419
1420 void poke_blanked_console(void)
1421 {
1422 timer_active &= ~(1<<BLANK_TIMER);
1423 if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1424 return;
1425 if (console_blanked) {
1426 timer_table[BLANK_TIMER].expires = 0;
1427 timer_active |= 1<<BLANK_TIMER;
1428 } else if (blankinterval) {
1429 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1430 timer_active |= 1<<BLANK_TIMER;
1431 }
1432 }
1433
1434 void * memsetw(void * s,unsigned short c,int count)
1435 {
1436 __asm__("cld\n\t"
1437 "rep\n\t"
1438 "stosw"
1439 :
1440 :"a" (c),"D" (s),"c" (count)
1441 :"cx","di");
1442 return s;
1443 }
1444
1445 void console_print(const char * b)
1446 {
1447 int currcons = fg_console;
1448 unsigned char c;
1449
1450 if (!printable || currcons<0 || currcons>=NR_CONSOLES)
1451 return;
1452 while ((c = *(b++)) != 0) {
1453 if (c == 10 || c == 13 || need_wrap) {
1454 if (c != 13)
1455 lf(currcons);
1456 cr(currcons);
1457 if (c == 10 || c == 13)
1458 continue;
1459 }
1460 *(unsigned short *) pos = (attr << 8) + c;
1461 if (x == video_num_columns - 1) {
1462 need_wrap = 1;
1463 continue;
1464 }
1465 x++;
1466 pos+=2;
1467 }
1468 set_cursor(currcons);
1469 if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1470 return;
1471 timer_active &= ~(1<<BLANK_TIMER);
1472 if (console_blanked) {
1473 timer_table[BLANK_TIMER].expires = 0;
1474 timer_active |= 1<<BLANK_TIMER;
1475 } else if (blankinterval) {
1476 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1477 timer_active |= 1<<BLANK_TIMER;
1478 }
1479 }
1480
1481
1482
1483
1484
1485
1486 static void con_throttle(struct tty_struct *tty)
1487 {
1488 }
1489
1490 static void con_unthrottle(struct tty_struct *tty)
1491 {
1492 struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
1493
1494 wake_up_interruptible(&vt->paste_wait);
1495 }
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507 long con_init(long kmem_start)
1508 {
1509 char *display_desc = "????";
1510 int currcons = 0;
1511 long base;
1512 int orig_x = ORIG_X;
1513 int orig_y = ORIG_Y;
1514
1515 memset(&console_driver, 0, sizeof(struct tty_driver));
1516 console_driver.magic = TTY_DRIVER_MAGIC;
1517 console_driver.name = "tty";
1518 console_driver.name_base = 1;
1519 console_driver.major = TTY_MAJOR;
1520 console_driver.minor_start = 1;
1521 console_driver.num = NR_CONSOLES;
1522 console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
1523 console_driver.init_termios = tty_std_termios;
1524 console_driver.flags = TTY_DRIVER_REAL_RAW;
1525 console_driver.refcount = &console_refcount;
1526 console_driver.table = console_table;
1527 console_driver.termios = console_termios;
1528 console_driver.termios_locked = console_termios_locked;
1529
1530 console_driver.open = con_open;
1531 console_driver.write = con_write;
1532 console_driver.write_room = con_write_room;
1533 console_driver.chars_in_buffer = con_chars_in_buffer;
1534 console_driver.ioctl = vt_ioctl;
1535 console_driver.stop = con_stop;
1536 console_driver.start = con_start;
1537 console_driver.throttle = con_throttle;
1538 console_driver.unthrottle = con_unthrottle;
1539
1540 if (tty_register_driver(&console_driver))
1541 panic("Couldn't register console driver\n");
1542
1543 vc_scrmembuf = (unsigned short *) kmem_start;
1544 video_num_columns = ORIG_VIDEO_COLS;
1545 video_size_row = video_num_columns * 2;
1546 video_num_lines = ORIG_VIDEO_LINES;
1547 video_page = ORIG_VIDEO_PAGE;
1548 screen_size = (video_num_lines * video_size_row);
1549 kmem_start += NR_CONSOLES * screen_size;
1550 timer_table[BLANK_TIMER].fn = blank_screen;
1551 timer_table[BLANK_TIMER].expires = 0;
1552 if (blankinterval) {
1553 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1554 timer_active |= 1<<BLANK_TIMER;
1555 }
1556
1557 if (ORIG_VIDEO_MODE == 7)
1558 {
1559 video_mem_base = 0xb0000;
1560 video_port_reg = 0x3b4;
1561 video_port_val = 0x3b5;
1562 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1563 {
1564 video_type = VIDEO_TYPE_EGAM;
1565 video_mem_term = 0xb8000;
1566 display_desc = "EGA+";
1567 }
1568 else
1569 {
1570 video_type = VIDEO_TYPE_MDA;
1571 video_mem_term = 0xb2000;
1572 display_desc = "*MDA";
1573 }
1574 }
1575 else
1576 {
1577 can_do_color = 1;
1578 video_mem_base = 0xb8000;
1579 video_port_reg = 0x3d4;
1580 video_port_val = 0x3d5;
1581 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1582 {
1583 video_type = VIDEO_TYPE_EGAC;
1584 video_mem_term = 0xc0000;
1585 display_desc = "EGA+";
1586 }
1587 else
1588 {
1589 video_type = VIDEO_TYPE_CGA;
1590 video_mem_term = 0xba000;
1591 display_desc = "*CGA";
1592 }
1593 }
1594
1595
1596
1597 base = (long)vc_scrmembuf;
1598 for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1599 pos = origin = video_mem_start = base;
1600 scr_end = video_mem_end = (base += screen_size);
1601 vc_scrbuf[currcons] = (unsigned short *) origin;
1602 vcmode = KD_TEXT;
1603 vtmode.mode = VT_AUTO;
1604 vtmode.waitv = 0;
1605 vtmode.relsig = 0;
1606 vtmode.acqsig = 0;
1607 vtmode.frsig = 0;
1608 vtpid = -1;
1609 vtnewvt = -1;
1610 clr_kbd(kbdraw);
1611 def_color = 0x07;
1612 ulcolor = 0x0f;
1613 halfcolor = 0x08;
1614 vt_cons[currcons].paste_wait = 0;
1615 reset_terminal(currcons, currcons);
1616 }
1617 currcons = fg_console = 0;
1618
1619 video_mem_start = video_mem_base;
1620 video_mem_end = video_mem_term;
1621 origin = video_mem_start;
1622 scr_end = video_mem_start + video_num_lines * video_size_row;
1623 gotoxy(currcons,0,0);
1624 save_cur(currcons);
1625 gotoxy(currcons,orig_x,orig_y);
1626 update_screen(fg_console);
1627 printable = 1;
1628 printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1629 can_do_color?"colour":"mono",
1630 display_desc,
1631 video_num_columns,video_num_lines,
1632 NR_CONSOLES);
1633 register_console(console_print);
1634 return kmem_start;
1635 }
1636
1637
1638
1639
1640
1641 void kbdsave(int new_console)
1642 {
1643 }
1644
1645 static void get_scrmem(int currcons)
1646 {
1647 memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
1648 video_mem_start = (unsigned long)vc_scrbuf[currcons];
1649 origin = video_mem_start;
1650 scr_end = video_mem_end = video_mem_start+screen_size;
1651 pos = origin + y*video_size_row + (x<<1);
1652 }
1653
1654 static void set_scrmem(int currcons)
1655 {
1656 #ifdef CONFIG_HGA
1657
1658
1659
1660
1661
1662
1663
1664 if (video_type == VIDEO_TYPE_MDA)
1665 {
1666 if (vcmode == KD_TEXT)
1667 {
1668
1669 int i;
1670 static char herc_txt_tbl[12] = {
1671 0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
1672 outb_p(0, 0x3bf);
1673 outb_p(0, 0x3b8);
1674 for ( i = 0 ; i < 12 ; i++ )
1675 {
1676 outb_p(i, 0x3b4);
1677 outb_p(herc_txt_tbl[i], 0x3b5);
1678 }
1679 }
1680 #define HGA_BLINKER_ON 0x20
1681 #define HGA_SCREEN_ON 8
1682
1683 outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
1684 }
1685 #endif CONFIG_HGA
1686
1687 video_mem_start = video_mem_base;
1688 video_mem_end = video_mem_term;
1689 origin = video_mem_start;
1690 scr_end = video_mem_start + screen_size;
1691 pos = origin + y*video_size_row + (x<<1);
1692 memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1693 }
1694
1695 void blank_screen(void)
1696 {
1697 if (console_blanked)
1698 return;
1699 timer_table[BLANK_TIMER].fn = unblank_screen;
1700 get_scrmem(fg_console);
1701 hide_cursor();
1702 console_blanked = 1;
1703 memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1704 }
1705
1706 void unblank_screen(void)
1707 {
1708 if (!console_blanked)
1709 return;
1710 timer_table[BLANK_TIMER].fn = blank_screen;
1711 if (blankinterval) {
1712 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1713 timer_active |= 1<<BLANK_TIMER;
1714 }
1715 console_blanked = 0;
1716 set_scrmem(fg_console);
1717 set_origin(fg_console);
1718 set_cursor(fg_console);
1719 }
1720
1721 void update_screen(int new_console)
1722 {
1723 static int lock = 0;
1724
1725 if (new_console == fg_console || lock)
1726 return;
1727 lock = 1;
1728 kbdsave(new_console);
1729 #ifdef CONFIG_SELECTION
1730 highlight_pointer(fg_console,-1);
1731 #endif
1732 get_scrmem(fg_console);
1733 fg_console = new_console;
1734 set_scrmem(fg_console);
1735 set_origin(fg_console);
1736 set_cursor(new_console);
1737 set_leds();
1738 compute_shiftstate();
1739 lock = 0;
1740 }
1741
1742 int do_screendump(int arg)
1743 {
1744 char *sptr, *buf = (char *)arg;
1745 int currcons, l;
1746
1747 if (!suser())
1748 return -EPERM;
1749 l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
1750 if (l)
1751 return l;
1752 currcons = get_fs_byte(buf+1);
1753 if ((currcons<0) || (currcons>NR_CONSOLES))
1754 return -EIO;
1755 put_fs_byte((char)(video_num_lines),buf++);
1756 put_fs_byte((char)(video_num_columns),buf++);
1757 currcons = (currcons ? currcons-1 : fg_console);
1758 sptr = (char *) origin;
1759 for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1760 put_fs_byte(*sptr++,buf++);
1761 return(0);
1762 }
1763
1764
1765
1766
1767
1768 int con_open(struct tty_struct *tty, struct file * filp)
1769 {
1770 int idx;
1771
1772 idx = MINOR(tty->device) - tty->driver.minor_start;
1773
1774 if (idx > NR_CONSOLES)
1775 return -ENODEV;
1776 vt_cons[idx].vc_num = idx;
1777 tty->driver_data = &vt_cons[idx];
1778
1779 if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
1780 tty->winsize.ws_row = video_num_lines;
1781 tty->winsize.ws_col = video_num_columns;
1782 }
1783 return 0;
1784 }
1785
1786 #ifdef CONFIG_SELECTION
1787
1788 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1789
1790
1791 static void highlight(const int currcons, const int s, const int e)
1792 {
1793 unsigned char *p, *p1, *p2;
1794
1795 p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
1796 p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
1797 if (p1 > p2)
1798 {
1799 p = p1;
1800 p1 = p2;
1801 p2 = p;
1802 }
1803 for (p = p1; p <= p2; p += 2)
1804 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
1805 }
1806
1807
1808 static void highlight_pointer(const int currcons, const int where)
1809 {
1810 unsigned char *p;
1811 static char *prev=NULL;
1812
1813 if (where==-1)
1814 {
1815 if (prev)
1816 {
1817 *prev ^= 0x77;
1818 prev=NULL;
1819 }
1820 }
1821 else
1822 {
1823 p = (unsigned char *)origin - hwscroll_offset + where + 1;
1824 *p ^= 0x77;
1825 if (prev) *prev ^= 0x77;
1826 prev=p;
1827 }
1828 }
1829
1830
1831
1832
1833
1834 static unsigned long inwordLut[4]={
1835 0x00000000,
1836 0x03FF0000,
1837 0x87FFFFFE,
1838 0x07FFFFFE
1839 };
1840 static inline int inword(const char c) {
1841 return ( inwordLut[(c>>5)&3] >> (c&0x1F) ) & 1;
1842 }
1843
1844
1845 int sel_loadlut(const int arg)
1846 {
1847 memcpy_fromfs(inwordLut,(unsigned long *)(arg+4),16);
1848 return 0;
1849 }
1850
1851
1852 static inline int atedge(const int p)
1853 {
1854 return (!(p % video_size_row) || !((p + 2) % video_size_row));
1855 }
1856
1857
1858 static inline short limit(const int v, const int l, const int u)
1859 {
1860 return (v < l) ? l : ((v > u) ? u : v);
1861 }
1862
1863
1864 int mouse_reporting(void)
1865 {
1866 int currcons = fg_console;
1867
1868 return report_mouse;
1869 }
1870
1871
1872 int set_selection(const int arg, struct tty_struct *tty)
1873 {
1874 unsigned short *args, xs, ys, xe, ye;
1875 int currcons = fg_console;
1876 int sel_mode, new_sel_start, new_sel_end, spc;
1877 char *bp, *obp, *spos;
1878 int i, ps, pe;
1879 char *off = (char *)origin - hwscroll_offset;
1880
1881 unblank_screen();
1882 args = (unsigned short *)(arg + 1);
1883 xs = get_fs_word(args++) - 1;
1884 ys = get_fs_word(args++) - 1;
1885 xe = get_fs_word(args++) - 1;
1886 ye = get_fs_word(args++) - 1;
1887 sel_mode = get_fs_word(args);
1888
1889 xs = limit(xs, 0, video_num_columns - 1);
1890 ys = limit(ys, 0, video_num_lines - 1);
1891 xe = limit(xe, 0, video_num_columns - 1);
1892 ye = limit(ye, 0, video_num_lines - 1);
1893 ps = ys * video_size_row + (xs << 1);
1894 pe = ye * video_size_row + (xe << 1);
1895
1896 if (report_mouse && (sel_mode & 16)) {
1897 mouse_report(currcons, tty, sel_mode & 15, xs, ys);
1898 return 0;
1899 }
1900
1901 if (ps > pe)
1902 {
1903 int tmp = ps;
1904 ps = pe;
1905 pe = tmp;
1906 }
1907
1908 switch (sel_mode)
1909 {
1910 case 0:
1911 new_sel_start = ps;
1912 new_sel_end = pe;
1913 break;
1914 case 1:
1915 spc = isspace(*(off + ps));
1916 for (new_sel_start = ps; ; ps -= 2)
1917 {
1918 if ((spc && !isspace(*(off + ps))) ||
1919 (!spc && !inword(*(off + ps))))
1920 break;
1921 new_sel_start = ps;
1922 if (!(ps % video_size_row))
1923 break;
1924 }
1925 spc = isspace(*(off + pe));
1926 for (new_sel_end = pe; ; pe += 2)
1927 {
1928 if ((spc && !isspace(*(off + pe))) ||
1929 (!spc && !inword(*(off + pe))))
1930 break;
1931 new_sel_end = pe;
1932 if (!((pe + 2) % video_size_row))
1933 break;
1934 }
1935 break;
1936 case 2:
1937 new_sel_start = ps - ps % video_size_row;
1938 new_sel_end = pe + video_size_row
1939 - pe % video_size_row - 2;
1940 break;
1941 case 3:
1942 if (sel_cons != currcons)
1943 {
1944 highlight_pointer(sel_cons,-1);
1945 clear_selection();
1946 sel_cons = currcons;
1947 }
1948 highlight_pointer(sel_cons,pe);
1949 return 0;
1950 default:
1951 return -EINVAL;
1952 }
1953
1954 if (new_sel_end > new_sel_start &&
1955 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
1956 {
1957 for (pe = new_sel_end + 2; ; pe += 2)
1958 {
1959 if (!isspace(*(off + pe)) || atedge(pe))
1960 break;
1961 }
1962 if (isspace(*(off + pe)))
1963 new_sel_end = pe;
1964 }
1965 if (sel_cons != currcons)
1966 {
1967 clear_selection();
1968 sel_cons = currcons;
1969 }
1970 if (sel_start == -1)
1971 highlight(sel_cons, new_sel_start, new_sel_end);
1972 else if (new_sel_start == sel_start)
1973 {
1974 if (new_sel_end == sel_end)
1975 return 0;
1976 else if (new_sel_end > sel_end)
1977 highlight(sel_cons, sel_end + 2, new_sel_end);
1978 else
1979 highlight(sel_cons, new_sel_end + 2, sel_end);
1980 }
1981 else if (new_sel_end == sel_end)
1982 {
1983 if (new_sel_start < sel_start)
1984 highlight(sel_cons, new_sel_start, sel_start - 2);
1985 else
1986 highlight(sel_cons, sel_start, new_sel_start - 2);
1987 }
1988 else
1989 {
1990 clear_selection();
1991 highlight(sel_cons, new_sel_start, new_sel_end);
1992 }
1993 sel_start = new_sel_start;
1994 sel_end = new_sel_end;
1995 obp = bp = sel_buffer;
1996 for (i = sel_start; i <= sel_end; i += 2)
1997 {
1998 spos = (char *)off + i;
1999 *bp++ = *spos;
2000 if (!isspace(*spos))
2001 obp = bp;
2002 if (! ((i + 2) % video_size_row))
2003 {
2004
2005
2006 if (obp != bp)
2007 {
2008 bp = obp;
2009 *bp++ = '\r';
2010 }
2011 obp = bp;
2012 }
2013
2014
2015 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
2016 break;
2017 }
2018 *bp = '\0';
2019 return 0;
2020 }
2021
2022
2023
2024 int paste_selection(struct tty_struct *tty)
2025 {
2026 struct wait_queue wait = { current, NULL };
2027 char *bp = sel_buffer;
2028 int c, l;
2029 struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2030
2031 if (!sel_buffer[0])
2032 return 0;
2033 unblank_screen();
2034 c = strlen(sel_buffer);
2035 current->state = TASK_INTERRUPTIBLE;
2036 add_wait_queue(&vt->paste_wait, &wait);
2037 while (c) {
2038 if (test_bit(TTY_THROTTLED, &tty->flags)) {
2039 schedule();
2040 continue;
2041 }
2042 l = MIN(c, tty->ldisc.receive_room(tty));
2043 tty->ldisc.receive_buf(tty, bp, 0, l);
2044 c -= l;
2045 bp += l;
2046 }
2047 current->state = TASK_RUNNING;
2048 return 0;
2049 }
2050
2051
2052
2053 static void clear_selection()
2054 {
2055 highlight_pointer(sel_cons, -1);
2056 if (sel_start != -1)
2057 {
2058 highlight(sel_cons, sel_start, sel_end);
2059 sel_start = -1;
2060 }
2061 }
2062 #endif
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076 #define colourmap ((char *)0xa0000)
2077 #define blackwmap ((char *)0xb0000)
2078 #define cmapsz 8192
2079 #define seq_port_reg (0x3c4)
2080 #define seq_port_val (0x3c5)
2081 #define gr_port_reg (0x3ce)
2082 #define gr_port_val (0x3cf)
2083
2084 static int set_get_font(char * arg, int set)
2085 {
2086 #ifdef CAN_LOAD_EGA_FONTS
2087 int i;
2088 char *charmap;
2089 int beg;
2090
2091
2092
2093 if (video_type == VIDEO_TYPE_EGAC) {
2094 charmap = colourmap;
2095 beg = 0x0e;
2096 } else if (video_type == VIDEO_TYPE_EGAM) {
2097 charmap = blackwmap;
2098 beg = 0x0a;
2099 } else
2100 return -EINVAL;
2101
2102 i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
2103 if (i)
2104 return i;
2105
2106 cli();
2107 outb_p( 0x00, seq_port_reg );
2108 outb_p( 0x01, seq_port_val );
2109 outb_p( 0x02, seq_port_reg );
2110 outb_p( 0x04, seq_port_val );
2111 outb_p( 0x04, seq_port_reg );
2112 outb_p( 0x07, seq_port_val );
2113 outb_p( 0x00, seq_port_reg );
2114 outb_p( 0x03, seq_port_val );
2115
2116 outb_p( 0x04, gr_port_reg );
2117 outb_p( 0x02, gr_port_val );
2118 outb_p( 0x05, gr_port_reg );
2119 outb_p( 0x00, gr_port_val );
2120 outb_p( 0x06, gr_port_reg );
2121 outb_p( 0x00, gr_port_val );
2122 sti();
2123
2124 if (set)
2125 for (i=0; i<cmapsz ; i++)
2126 *(charmap+i) = get_fs_byte(arg+i);
2127 else
2128 for (i=0; i<cmapsz ; i++)
2129 put_fs_byte(*(charmap+i), arg+i);
2130
2131 cli();
2132 outb_p( 0x00, seq_port_reg );
2133 outb_p( 0x01, seq_port_val );
2134 outb_p( 0x02, seq_port_reg );
2135 outb_p( 0x03, seq_port_val );
2136 outb_p( 0x04, seq_port_reg );
2137 outb_p( 0x03, seq_port_val );
2138 outb_p( 0x00, seq_port_reg );
2139 outb_p( 0x03, seq_port_val );
2140
2141 outb_p( 0x04, gr_port_reg );
2142 outb_p( 0x00, gr_port_val );
2143 outb_p( 0x05, gr_port_reg );
2144 outb_p( 0x10, gr_port_val );
2145 outb_p( 0x06, gr_port_reg );
2146 outb_p( beg, gr_port_val );
2147 sti();
2148
2149 return 0;
2150 #else
2151 return -EINVAL;
2152 #endif
2153 }
2154
2155
2156
2157
2158
2159
2160
2161 int con_set_font (char *arg)
2162 {
2163 return set_get_font (arg,1);
2164 }
2165
2166 int con_get_font (char *arg)
2167 {
2168 return set_get_font (arg,0);
2169 }
2170
2171
2172
2173
2174
2175
2176 int con_set_trans(char * arg)
2177 {
2178 int i;
2179
2180 i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
2181 if (i)
2182 return i;
2183
2184 for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
2185 USER_TRANS[012]=0;
2186 USER_TRANS[014]=0;
2187 USER_TRANS[015]=0;
2188 USER_TRANS[033]=0;
2189 return 0;
2190 }
2191
2192 int con_get_trans(char * arg)
2193 {
2194 int i;
2195
2196 i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
2197 if (i)
2198 return i;
2199
2200 for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
2201 return 0;
2202 }