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