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) | (color << 4)) & 0x77)) << 8) | ' ';
628 else
629 video_erase_char = (color << 8) | ' ';
630 }
631
632 static void default_attr(int currcons)
633 {
634 intensity = 1;
635 underline = 0;
636 reverse = 0;
637 blink = 0;
638 color = def_color;
639 }
640
641 static void csi_m(int currcons)
642 {
643 int i;
644
645 for (i=0;i<=npar;i++)
646 switch (par[i]) {
647 case 0:
648 default_attr(currcons);
649 break;
650 case 1:
651 intensity = 2;
652 break;
653 case 2:
654 intensity = 0;
655 break;
656 case 4:
657 underline = 1;
658 break;
659 case 5:
660 blink = 1;
661 break;
662 case 7:
663 reverse = 1;
664 break;
665 case 21:
666 case 22:
667 intensity = 1;
668 break;
669 case 24:
670 underline = 0;
671 break;
672 case 25:
673 blink = 0;
674 break;
675 case 27:
676 reverse = 0;
677 break;
678 case 39:
679 color = (def_color & 0x0f) | background;
680 break;
681 case 49:
682 color = (def_color & 0xf0) | foreground;
683 break;
684 default:
685 if (par[i] >= 30 && par[i] <= 37)
686 color = color_table[par[i]-30]
687 | background;
688 else if (par[i] >= 40 && par[i] <= 47)
689 color = (color_table[par[i]-40]<<4)
690 | foreground;
691 break;
692 }
693 update_attr(currcons);
694 }
695
696 static void respond_string(char * p, int currcons, struct tty_struct * tty)
697 {
698 while (*p) {
699 put_tty_queue(*p, &tty->read_q);
700 p++;
701 }
702 TTY_READ_FLUSH(tty);
703 }
704
705 static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
706 {
707 char buff[3];
708 int i = 0;
709
710 do {
711 buff[i++] = (n%10)+'0';
712 n /= 10;
713 } while(n && i < 3);
714 while (i--) {
715 put_tty_queue(buff[i], &tty->read_q);
716 }
717
718 }
719
720 static void cursor_report(int currcons, struct tty_struct * tty)
721 {
722 put_tty_queue('\033', &tty->read_q);
723 put_tty_queue('[', &tty->read_q);
724 respond_num(y + (decom ? top+1 : 1), currcons, tty);
725 put_tty_queue(';', &tty->read_q);
726 respond_num(x+1, currcons, tty);
727 put_tty_queue('R', &tty->read_q);
728 TTY_READ_FLUSH(tty);
729 }
730
731 static inline void status_report(int currcons, struct tty_struct * tty)
732 {
733 respond_string("\033[0n", currcons, tty);
734 }
735
736 static inline void respond_ID(int currcons, struct tty_struct * tty)
737 {
738 respond_string(VT102ID, currcons, tty);
739 }
740
741 static void invert_screen(int currcons) {
742 unsigned char *p;
743
744 if (can_do_color)
745 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
746 *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
747 else
748 for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
749 *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
750 }
751
752 static void set_mode(int currcons, int on_off)
753 {
754 int i;
755
756 for (i=0; i<=npar; i++)
757 if (ques) switch(par[i]) {
758 case 1:
759 if (on_off)
760 set_kbd(decckm);
761 else
762 clr_kbd(decckm);
763 break;
764 case 3:
765 csi_J(currcons,2);
766 gotoxy(currcons,0,0);
767 break;
768 case 5:
769 if (decscnm != on_off) {
770 decscnm = on_off;
771 invert_screen(currcons);
772 update_attr(currcons);
773 }
774 break;
775 case 6:
776 decom = on_off;
777 gotoxy(currcons,0,0);
778 break;
779 case 7:
780 decawm = on_off;
781 break;
782 case 8:
783 if (on_off)
784 set_kbd(decarm);
785 else
786 clr_kbd(decarm);
787 break;
788 case 25:
789 deccm = on_off;
790 set_cursor(currcons);
791 break;
792 } else switch(par[i]) {
793 case 4:
794 decim = on_off;
795 break;
796 case 20:
797 if (on_off)
798 set_kbd(lnm);
799 else
800 clr_kbd(lnm);
801 break;
802 }
803 }
804
805 static void setterm_command(int currcons)
806 {
807 switch(par[0]) {
808 case 1:
809 if (can_do_color && par[1] < 16) {
810 ulcolor = color_table[par[1]];
811 if (underline)
812 update_attr(currcons);
813 }
814 break;
815 case 2:
816 if (can_do_color && par[1] < 16) {
817 halfcolor = color_table[par[1]];
818 if (intensity == 0)
819 update_attr(currcons);
820 }
821 break;
822 case 8:
823 def_color = attr;
824 default_attr(currcons);
825 update_attr(currcons);
826 break;
827 case 9:
828 blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
829 break;
830 }
831 }
832
833 static void insert_char(int currcons)
834 {
835 unsigned int i = x;
836 unsigned short tmp, old = video_erase_char;
837 unsigned short * p = (unsigned short *) pos;
838
839 while (i++ < video_num_columns) {
840 tmp = *p;
841 *p = old;
842 old = tmp;
843 p++;
844 }
845 need_wrap = 0;
846 }
847
848 static void insert_line(int currcons)
849 {
850 scrdown(currcons,y,bottom);
851 need_wrap = 0;
852 }
853
854 static void delete_char(int currcons)
855 {
856 unsigned int i = x;
857 unsigned short * p = (unsigned short *) pos;
858
859 while (++i < video_num_columns) {
860 *p = *(p+1);
861 p++;
862 }
863 *p = video_erase_char;
864 need_wrap = 0;
865 }
866
867 static void delete_line(int currcons)
868 {
869 scrup(currcons,y,bottom);
870 need_wrap = 0;
871 }
872
873 static void csi_at(int currcons, unsigned int nr)
874 {
875 if (nr > video_num_columns)
876 nr = video_num_columns;
877 else if (!nr)
878 nr = 1;
879 while (nr--)
880 insert_char(currcons);
881 }
882
883 static void csi_L(int currcons, unsigned int nr)
884 {
885 if (nr > video_num_lines)
886 nr = video_num_lines;
887 else if (!nr)
888 nr = 1;
889 while (nr--)
890 insert_line(currcons);
891 }
892
893 static void csi_P(int currcons, unsigned int nr)
894 {
895 if (nr > video_num_columns)
896 nr = video_num_columns;
897 else if (!nr)
898 nr = 1;
899 while (nr--)
900 delete_char(currcons);
901 }
902
903 static void csi_M(int currcons, unsigned int nr)
904 {
905 if (nr > video_num_lines)
906 nr = video_num_lines;
907 else if (!nr)
908 nr=1;
909 while (nr--)
910 delete_line(currcons);
911 }
912
913 static void save_cur(int currcons)
914 {
915 saved_x = x;
916 saved_y = y;
917 s_intensity = intensity;
918 s_underline = underline;
919 s_blink = blink;
920 s_reverse = reverse;
921 s_charset = charset;
922 s_color = color;
923 saved_G0 = G0_charset;
924 saved_G1 = G1_charset;
925 }
926
927 static void restore_cur(int currcons)
928 {
929 gotoxy(currcons,saved_x,saved_y);
930 intensity = s_intensity;
931 underline = s_underline;
932 blink = s_blink;
933 reverse = s_reverse;
934 charset = s_charset;
935 color = s_color;
936 G0_charset = saved_G0;
937 G1_charset = saved_G1;
938 translate = charset ? G1_charset : G0_charset;
939 update_attr(currcons);
940 need_wrap = 0;
941 }
942
943 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
944 EShash, ESsetG0, ESsetG1, ESignore };
945
946 static void reset_terminal(int currcons, int do_clear)
947 {
948 top = 0;
949 bottom = video_num_lines;
950 state = ESnormal;
951 ques = 0;
952 translate = NORM_TRANS;
953 G0_charset = NORM_TRANS;
954 G1_charset = GRAF_TRANS;
955 charset = 0;
956 need_wrap = 0;
957
958 decscnm = 0;
959 decom = 0;
960 decawm = 1;
961 deccm = 1;
962 decim = 0;
963
964 set_kbd(decarm);
965 clr_kbd(decckm);
966 clr_kbd(kbdapplic);
967 clr_kbd(lnm);
968 kbd_table[currcons].lockstate = 0;
969 kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
970 set_leds();
971
972 default_attr(currcons);
973 update_attr(currcons);
974
975 tab_stop[0] = 0x01010100;
976 tab_stop[1] =
977 tab_stop[2] =
978 tab_stop[3] =
979 tab_stop[4] = 0x01010101;
980
981 if (do_clear) {
982 gotoxy(currcons,0,0);
983 csi_J(currcons,2);
984 save_cur(currcons);
985 }
986 }
987
988 void con_write(struct tty_struct * tty)
989 {
990 int c;
991 unsigned int currcons;
992
993 currcons = tty->line - 1;
994 if (currcons >= NR_CONSOLES) {
995 printk("con_write: illegal tty (%d)\n", currcons);
996 return;
997 }
998 #ifdef CONFIG_SELECTION
999
1000
1001 if (!EMPTY(&tty->write_q) && currcons == sel_cons)
1002 clear_selection();
1003 #endif
1004 disable_bh(KEYBOARD_BH);
1005 while (!tty->stopped && (c = get_tty_queue(&tty->write_q)) >= 0) {
1006 if (state == ESnormal && translate[c]) {
1007 if (need_wrap) {
1008 cr(currcons);
1009 lf(currcons);
1010 }
1011 if (decim)
1012 insert_char(currcons);
1013 c = translate[c];
1014 *(unsigned short *) pos = (attr << 8) + c;
1015 if (x == video_num_columns - 1)
1016 need_wrap = decawm;
1017 else {
1018 x++;
1019 pos+=2;
1020 }
1021 continue;
1022 }
1023
1024
1025
1026
1027
1028 switch (c) {
1029 case 7:
1030 kd_mksound(0x637, HZ/8);
1031 continue;
1032 case 8:
1033 bs(currcons);
1034 continue;
1035 case 9:
1036 pos -= (x << 1);
1037 while (x < video_num_columns - 1) {
1038 x++;
1039 if (tab_stop[x >> 5] & (1 << (x & 31)))
1040 break;
1041 }
1042 pos += (x << 1);
1043 continue;
1044 case 10: case 11: case 12:
1045 lf(currcons);
1046 if (!is_kbd(lnm))
1047 continue;
1048 case 13:
1049 cr(currcons);
1050 continue;
1051 case 14:
1052 charset = 1;
1053 translate = G1_charset;
1054 continue;
1055 case 15:
1056 charset = 0;
1057 translate = G0_charset;
1058 continue;
1059 case 24: case 26:
1060 state = ESnormal;
1061 continue;
1062 case 27:
1063 state = ESesc;
1064 continue;
1065 case 127:
1066 del(currcons);
1067 continue;
1068 case 128+27:
1069 state = ESsquare;
1070 continue;
1071 }
1072 switch(state) {
1073 case ESesc:
1074 state = ESnormal;
1075 switch (c) {
1076 case '[':
1077 state = ESsquare;
1078 continue;
1079 case 'E':
1080 cr(currcons);
1081 lf(currcons);
1082 continue;
1083 case 'M':
1084 ri(currcons);
1085 continue;
1086 case 'D':
1087 lf(currcons);
1088 continue;
1089 case 'H':
1090 tab_stop[x >> 5] |= (1 << (x & 31));
1091 continue;
1092 case 'Z':
1093 respond_ID(currcons,tty);
1094 continue;
1095 case '7':
1096 save_cur(currcons);
1097 continue;
1098 case '8':
1099 restore_cur(currcons);
1100 continue;
1101 case '(':
1102 state = ESsetG0;
1103 continue;
1104 case ')':
1105 state = ESsetG1;
1106 continue;
1107 case '#':
1108 state = EShash;
1109 continue;
1110 case 'c':
1111 reset_terminal(currcons,1);
1112 continue;
1113 case '>':
1114 clr_kbd(kbdapplic);
1115 continue;
1116 case '=':
1117 set_kbd(kbdapplic);
1118 continue;
1119 }
1120 continue;
1121 case ESsquare:
1122 for(npar = 0 ; npar < NPAR ; npar++)
1123 par[npar] = 0;
1124 npar = 0;
1125 state = ESgetpars;
1126 if (c == '[') {
1127 state=ESfunckey;
1128 continue;
1129 }
1130 ques = (c=='?');
1131 if (ques)
1132 continue;
1133 case ESgetpars:
1134 if (c==';' && npar<NPAR-1) {
1135 npar++;
1136 continue;
1137 } else if (c>='0' && c<='9') {
1138 par[npar] *= 10;
1139 par[npar] += c-'0';
1140 continue;
1141 } else state=ESgotpars;
1142 case ESgotpars:
1143 state = ESnormal;
1144 switch(c) {
1145 case 'h':
1146 set_mode(currcons,1);
1147 continue;
1148 case 'l':
1149 set_mode(currcons,0);
1150 continue;
1151 case 'n':
1152 if (!ques)
1153 if (par[0] == 5)
1154 status_report(currcons,tty);
1155 else if (par[0] == 6)
1156 cursor_report(currcons,tty);
1157 continue;
1158 }
1159 if (ques) {
1160 ques = 0;
1161 continue;
1162 }
1163 switch(c) {
1164 case 'G': case '`':
1165 if (par[0]) par[0]--;
1166 gotoxy(currcons,par[0],y);
1167 continue;
1168 case 'A':
1169 if (!par[0]) par[0]++;
1170 gotoxy(currcons,x,y-par[0]);
1171 continue;
1172 case 'B': case 'e':
1173 if (!par[0]) par[0]++;
1174 gotoxy(currcons,x,y+par[0]);
1175 continue;
1176 case 'C': case 'a':
1177 if (!par[0]) par[0]++;
1178 gotoxy(currcons,x+par[0],y);
1179 continue;
1180 case 'D':
1181 if (!par[0]) par[0]++;
1182 gotoxy(currcons,x-par[0],y);
1183 continue;
1184 case 'E':
1185 if (!par[0]) par[0]++;
1186 gotoxy(currcons,0,y+par[0]);
1187 continue;
1188 case 'F':
1189 if (!par[0]) par[0]++;
1190 gotoxy(currcons,0,y-par[0]);
1191 continue;
1192 case 'd':
1193 if (par[0]) par[0]--;
1194 gotoxy(currcons,x,par[0]);
1195 continue;
1196 case 'H': case 'f':
1197 if (par[0]) par[0]--;
1198 if (par[1]) par[1]--;
1199 gotoxy(currcons,par[1],par[0]);
1200 continue;
1201 case 'J':
1202 csi_J(currcons,par[0]);
1203 continue;
1204 case 'K':
1205 csi_K(currcons,par[0]);
1206 continue;
1207 case 'L':
1208 csi_L(currcons,par[0]);
1209 continue;
1210 case 'M':
1211 csi_M(currcons,par[0]);
1212 continue;
1213 case 'P':
1214 csi_P(currcons,par[0]);
1215 continue;
1216 case 'c':
1217 if (!par[0])
1218 respond_ID(currcons,tty);
1219 continue;
1220 case 'g':
1221 if (!par[0])
1222 tab_stop[x >> 5] &= ~(1 << (x & 31));
1223 else if (par[0] == 3) {
1224 tab_stop[0] =
1225 tab_stop[1] =
1226 tab_stop[2] =
1227 tab_stop[3] =
1228 tab_stop[4] = 0;
1229 }
1230 continue;
1231 case 'm':
1232 csi_m(currcons);
1233 continue;
1234 case 'r':
1235 if (!par[0])
1236 par[0]++;
1237 if (!par[1])
1238 par[1] = video_num_lines;
1239
1240 if (par[0] < par[1] &&
1241 par[1] <= video_num_lines) {
1242 top=par[0]-1;
1243 bottom=par[1];
1244 gotoxy(currcons,0,0);
1245 }
1246 continue;
1247 case 's':
1248 save_cur(currcons);
1249 continue;
1250 case 'u':
1251 restore_cur(currcons);
1252 continue;
1253 case '@':
1254 csi_at(currcons,par[0]);
1255 continue;
1256 case ']':
1257 setterm_command(currcons);
1258 continue;
1259 }
1260 continue;
1261 case ESfunckey:
1262 state = ESnormal;
1263 continue;
1264 case EShash:
1265 state = ESnormal;
1266 if (c == '8') {
1267
1268 video_erase_char =
1269 (video_erase_char & 0xff00) | 'E';
1270 csi_J(currcons, 2);
1271 video_erase_char =
1272 (video_erase_char & 0xff00) | ' ';
1273 }
1274 continue;
1275 case ESsetG0:
1276 if (c == '0')
1277 G0_charset = GRAF_TRANS;
1278 else if (c == 'B')
1279 G0_charset = NORM_TRANS;
1280 else if (c == 'U')
1281 G0_charset = NULL_TRANS;
1282 else if (c == 'K')
1283 G0_charset = USER_TRANS;
1284 if (charset == 0)
1285 translate = G0_charset;
1286 state = ESnormal;
1287 continue;
1288 case ESsetG1:
1289 if (c == '0')
1290 G1_charset = GRAF_TRANS;
1291 else if (c == 'B')
1292 G1_charset = NORM_TRANS;
1293 else if (c == 'U')
1294 G1_charset = NULL_TRANS;
1295 else if (c == 'K')
1296 G1_charset = USER_TRANS;
1297 if (charset == 1)
1298 translate = G1_charset;
1299 state = ESnormal;
1300 continue;
1301 default:
1302 state = ESnormal;
1303 }
1304 }
1305 if (vcmode != KD_GRAPHICS)
1306 set_cursor(currcons);
1307 enable_bh(KEYBOARD_BH);
1308 if (LEFT(&tty->write_q) > WAKEUP_CHARS)
1309 wake_up_interruptible(&tty->write_q.proc_list);
1310 }
1311
1312 void do_keyboard_interrupt(void)
1313 {
1314 TTY_READ_FLUSH(TTY_TABLE(0));
1315 timer_active &= ~(1<<BLANK_TIMER);
1316 if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1317 return;
1318 if (console_blanked) {
1319 timer_table[BLANK_TIMER].expires = 0;
1320 timer_active |= 1<<BLANK_TIMER;
1321 } else if (blankinterval) {
1322 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1323 timer_active |= 1<<BLANK_TIMER;
1324 }
1325 }
1326
1327 void * memsetw(void * s,unsigned short c,int count)
1328 {
1329 __asm__("cld\n\t"
1330 "rep\n\t"
1331 "stosw"
1332 :
1333 :"a" (c),"D" (s),"c" (count)
1334 :"cx","di");
1335 return s;
1336 }
1337
1338 void console_print(const char * b)
1339 {
1340 int currcons = fg_console;
1341 unsigned char c;
1342
1343 if (!printable || currcons<0 || currcons>=NR_CONSOLES)
1344 return;
1345 while ((c = *(b++)) != 0) {
1346 if (c == 10 || c == 13 || need_wrap) {
1347 if (c != 13)
1348 lf(currcons);
1349 cr(currcons);
1350 if (c == 10 || c == 13)
1351 continue;
1352 }
1353 *(unsigned short *) pos = (attr << 8) + c;
1354 if (x == video_num_columns - 1) {
1355 need_wrap = 1;
1356 continue;
1357 }
1358 x++;
1359 pos+=2;
1360 }
1361 set_cursor(currcons);
1362 if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
1363 return;
1364 timer_active &= ~(1<<BLANK_TIMER);
1365 if (console_blanked) {
1366 timer_table[BLANK_TIMER].expires = 0;
1367 timer_active |= 1<<BLANK_TIMER;
1368 } else if (blankinterval) {
1369 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1370 timer_active |= 1<<BLANK_TIMER;
1371 }
1372 }
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384 long con_init(long kmem_start)
1385 {
1386 char *display_desc = "????";
1387 int currcons = 0;
1388 long base;
1389 int orig_x = ORIG_X;
1390 int orig_y = ORIG_Y;
1391
1392 vc_scrmembuf = (unsigned short *) kmem_start;
1393 video_num_columns = ORIG_VIDEO_COLS;
1394 video_size_row = video_num_columns * 2;
1395 video_num_lines = ORIG_VIDEO_LINES;
1396 video_page = ORIG_VIDEO_PAGE;
1397 screen_size = (video_num_lines * video_size_row);
1398 kmem_start += NR_CONSOLES * screen_size;
1399 timer_table[BLANK_TIMER].fn = blank_screen;
1400 timer_table[BLANK_TIMER].expires = 0;
1401 if (blankinterval) {
1402 timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
1403 timer_active |= 1<<BLANK_TIMER;
1404 }
1405
1406 if (ORIG_VIDEO_MODE == 7)
1407 {
1408 video_mem_base = 0xb0000;
1409 video_port_reg = 0x3b4;
1410 video_port_val = 0x3b5;
1411 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1412 {
1413 video_type = VIDEO_TYPE_EGAM;
1414 video_mem_term = 0xb8000;
1415 display_desc = "EGA+";
1416 }
1417 else
1418 {
1419 video_type = VIDEO_TYPE_MDA;
1420 video_mem_term = 0xb2000;
1421 display_desc = "*MDA";
1422 }
1423 }
1424 else
1425 {
1426 can_do_color = 1;
1427 video_mem_base = 0xb8000;
1428 video_port_reg = 0x3d4;
1429 video_port_val = 0x3d5;
1430 if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
1431 {
1432 video_type = VIDEO_TYPE_EGAC;
1433 video_mem_term = 0xc0000;
1434 display_desc = "EGA+";
1435 }
1436 else
1437 {
1438 video_type = VIDEO_TYPE_CGA;
1439 video_mem_term = 0xba000;
1440 display_desc = "*CGA";
1441 }
1442 }
1443
1444
1445
1446 base = (long)vc_scrmembuf;
1447 for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
1448 pos = origin = video_mem_start = base;
1449 scr_end = video_mem_end = (base += screen_size);
1450 vc_scrbuf[currcons] = (unsigned short *) origin;
1451 vcmode = KD_TEXT;
1452 vtmode.mode = VT_AUTO;
1453 vtmode.waitv = 0;
1454 vtmode.relsig = 0;
1455 vtmode.acqsig = 0;
1456 vtmode.frsig = 0;
1457 vtpid = -1;
1458 vtnewvt = -1;
1459 clr_kbd(kbdraw);
1460 def_color = 0x07;
1461 ulcolor = 0x0f;
1462 halfcolor = 0x08;
1463 reset_terminal(currcons, currcons);
1464 }
1465 currcons = fg_console = 0;
1466
1467 video_mem_start = video_mem_base;
1468 video_mem_end = video_mem_term;
1469 origin = video_mem_start;
1470 scr_end = video_mem_start + video_num_lines * video_size_row;
1471 gotoxy(currcons,0,0);
1472 save_cur(currcons);
1473 gotoxy(currcons,orig_x,orig_y);
1474 update_screen(fg_console);
1475 printable = 1;
1476 printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1477 can_do_color?"colour":"mono",
1478 display_desc,
1479 video_num_columns,video_num_lines,
1480 NR_CONSOLES);
1481 register_console(console_print);
1482 return kmem_start;
1483 }
1484
1485
1486
1487
1488
1489 void kbdsave(int new_console)
1490 {
1491 }
1492
1493 static void get_scrmem(int currcons)
1494 {
1495 memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
1496 video_mem_start = (unsigned long)vc_scrbuf[currcons];
1497 origin = video_mem_start;
1498 scr_end = video_mem_end = video_mem_start+screen_size;
1499 pos = origin + y*video_size_row + (x<<1);
1500 }
1501
1502 static void set_scrmem(int currcons)
1503 {
1504 #ifdef CONFIG_HGA
1505
1506
1507
1508
1509
1510
1511
1512 if (video_type == VIDEO_TYPE_MDA)
1513 {
1514 if (vcmode == KD_TEXT)
1515 {
1516
1517 int i;
1518 static char herc_txt_tbl[12] = {
1519 0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
1520 outb_p(0, 0x3bf);
1521 outb_p(0, 0x3b8);
1522 for ( i = 0 ; i < 12 ; i++ )
1523 {
1524 outb_p(i, 0x3b4);
1525 outb_p(herc_txt_tbl[i], 0x3b5);
1526 }
1527 }
1528 #define HGA_BLINKER_ON 0x20
1529 #define HGA_SCREEN_ON 8
1530
1531 outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
1532 }
1533 #endif CONFIG_HGA
1534
1535 video_mem_start = video_mem_base;
1536 video_mem_end = video_mem_term;
1537 origin = video_mem_start;
1538 scr_end = video_mem_start + screen_size;
1539 pos = origin + y*video_size_row + (x<<1);
1540 memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
1541 }
1542
1543 void blank_screen(void)
1544 {
1545 if (console_blanked)
1546 return;
1547 timer_table[BLANK_TIMER].fn = unblank_screen;
1548 get_scrmem(fg_console);
1549 hide_cursor(fg_console);
1550 console_blanked = 1;
1551 memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
1552 }
1553
1554 void unblank_screen(void)
1555 {
1556 if (!console_blanked)
1557 return;
1558 timer_table[BLANK_TIMER].fn = blank_screen;
1559 if (blankinterval) {
1560 timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
1561 timer_active |= 1<<BLANK_TIMER;
1562 }
1563 console_blanked = 0;
1564 set_scrmem(fg_console);
1565 set_origin(fg_console);
1566 set_cursor(fg_console);
1567 }
1568
1569 void update_screen(int new_console)
1570 {
1571 static int lock = 0;
1572
1573 if (new_console == fg_console || lock)
1574 return;
1575 lock = 1;
1576 kbdsave(new_console);
1577 get_scrmem(fg_console);
1578 fg_console = new_console;
1579 set_scrmem(fg_console);
1580 set_origin(fg_console);
1581 set_cursor(new_console);
1582 set_leds();
1583 compute_shiftstate();
1584 lock = 0;
1585 }
1586
1587 int do_screendump(int arg)
1588 {
1589 char *sptr, *buf = (char *)arg;
1590 int currcons, l;
1591
1592 if (!suser())
1593 return -EPERM;
1594 l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
1595 if (l)
1596 return l;
1597 currcons = get_fs_byte(buf+1);
1598 if ((currcons<0) || (currcons>NR_CONSOLES))
1599 return -EIO;
1600 put_fs_byte((char)(video_num_lines),buf++);
1601 put_fs_byte((char)(video_num_columns),buf++);
1602 currcons = (currcons ? currcons-1 : fg_console);
1603 sptr = (char *) origin;
1604 for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
1605 put_fs_byte(*sptr++,buf++);
1606 return(0);
1607 }
1608
1609
1610
1611
1612
1613 int con_open(struct tty_struct *tty, struct file * filp)
1614 {
1615 tty->write = con_write;
1616 tty->ioctl = vt_ioctl;
1617 if (tty->line > NR_CONSOLES)
1618 return -ENODEV;
1619 return 0;
1620 }
1621
1622 #ifdef CONFIG_SELECTION
1623
1624 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1625
1626
1627 static void highlight(const int currcons, const int s, const int e)
1628 {
1629 unsigned char *p, *p1, *p2;
1630
1631 p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
1632 p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
1633 if (p1 > p2)
1634 {
1635 p = p1;
1636 p1 = p2;
1637 p2 = p;
1638 }
1639 for (p = p1; p <= p2; p += 2)
1640 *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
1641 }
1642
1643
1644 static inline int inword(const char c) { return (isalnum(c) || c == '_'); }
1645
1646
1647 static inline int atedge(const int p)
1648 {
1649 return (!(p % video_size_row) || !((p + 2) % video_size_row));
1650 }
1651
1652
1653 static inline short limit(const int v, const int l, const int u)
1654 {
1655 return (v < l) ? l : ((v > u) ? u : v);
1656 }
1657
1658
1659 int set_selection(const int arg)
1660 {
1661 unsigned short *args, xs, ys, xe, ye;
1662 int currcons = fg_console;
1663 int sel_mode, new_sel_start, new_sel_end, spc;
1664 char *bp, *obp, *spos;
1665 int i, ps, pe;
1666 char *off = (char *)origin - hwscroll_offset;
1667
1668 unblank_screen();
1669 args = (unsigned short *)(arg + 1);
1670 xs = get_fs_word(args++) - 1;
1671 ys = get_fs_word(args++) - 1;
1672 xe = get_fs_word(args++) - 1;
1673 ye = get_fs_word(args++) - 1;
1674 sel_mode = get_fs_word(args);
1675
1676 xs = limit(xs, 0, video_num_columns - 1);
1677 ys = limit(ys, 0, video_num_lines - 1);
1678 xe = limit(xe, 0, video_num_columns - 1);
1679 ye = limit(ye, 0, video_num_lines - 1);
1680 ps = ys * video_size_row + (xs << 1);
1681 pe = ye * video_size_row + (xe << 1);
1682
1683 if (ps > pe)
1684 {
1685 int tmp = ps;
1686 ps = pe;
1687 pe = tmp;
1688 }
1689
1690 switch (sel_mode)
1691 {
1692 case 0:
1693 default:
1694 new_sel_start = ps;
1695 new_sel_end = pe;
1696 break;
1697 case 1:
1698 spc = isspace(*(off + ps));
1699 for (new_sel_start = ps; ; ps -= 2)
1700 {
1701 if ((spc && !isspace(*(off + ps))) ||
1702 (!spc && !inword(*(off + ps))))
1703 break;
1704 new_sel_start = ps;
1705 if (!(ps % video_size_row))
1706 break;
1707 }
1708 spc = isspace(*(off + pe));
1709 for (new_sel_end = pe; ; pe += 2)
1710 {
1711 if ((spc && !isspace(*(off + pe))) ||
1712 (!spc && !inword(*(off + pe))))
1713 break;
1714 new_sel_end = pe;
1715 if (!((pe + 2) % video_size_row))
1716 break;
1717 }
1718 break;
1719 case 2:
1720 new_sel_start = ps - ps % video_size_row;
1721 new_sel_end = pe + video_size_row
1722 - pe % video_size_row - 2;
1723 break;
1724 }
1725
1726 if (new_sel_end > new_sel_start &&
1727 !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
1728 {
1729 for (pe = new_sel_end + 2; ; pe += 2)
1730 {
1731 if (!isspace(*(off + pe)) || atedge(pe))
1732 break;
1733 }
1734 if (isspace(*(off + pe)))
1735 new_sel_end = pe;
1736 }
1737 if (sel_cons != currcons)
1738 {
1739 clear_selection();
1740 sel_cons = currcons;
1741 }
1742 if (sel_start == -1)
1743 highlight(sel_cons, new_sel_start, new_sel_end);
1744 else if (new_sel_start == sel_start)
1745 {
1746 if (new_sel_end == sel_end)
1747 return 0;
1748 else if (new_sel_end > sel_end)
1749 highlight(sel_cons, sel_end + 2, new_sel_end);
1750 else
1751 highlight(sel_cons, new_sel_end + 2, sel_end);
1752 }
1753 else if (new_sel_end == sel_end)
1754 {
1755 if (new_sel_start < sel_start)
1756 highlight(sel_cons, new_sel_start, sel_start - 2);
1757 else
1758 highlight(sel_cons, sel_start, new_sel_start - 2);
1759 }
1760 else
1761 {
1762 clear_selection();
1763 highlight(sel_cons, new_sel_start, new_sel_end);
1764 }
1765 sel_start = new_sel_start;
1766 sel_end = new_sel_end;
1767 obp = bp = sel_buffer;
1768 for (i = sel_start; i <= sel_end; i += 2)
1769 {
1770 spos = (char *)off + i;
1771 *bp++ = *spos;
1772 if (!isspace(*spos))
1773 obp = bp;
1774 if (! ((i + 2) % video_size_row))
1775 {
1776
1777
1778 if (obp != bp)
1779 {
1780 bp = obp;
1781 *bp++ = '\r';
1782 }
1783 obp = bp;
1784 }
1785
1786
1787 if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
1788 break;
1789 }
1790 *bp = '\0';
1791 return 0;
1792 }
1793
1794
1795
1796 int paste_selection(struct tty_struct *tty)
1797 {
1798 char *bp = sel_buffer;
1799
1800 if (! *bp)
1801 return 0;
1802 unblank_screen();
1803 while (*bp) {
1804 put_tty_queue(*bp, &tty->read_q);
1805 bp++;
1806 TTY_READ_FLUSH(tty);
1807 }
1808 return 0;
1809 }
1810
1811
1812
1813 static void clear_selection()
1814 {
1815 if (sel_start != -1)
1816 {
1817 highlight(sel_cons, sel_start, sel_end);
1818 sel_start = -1;
1819 }
1820 }
1821 #endif
1822
1823
1824
1825
1826
1827 #define colourmap ((char *)0xa0000)
1828 #define blackwmap ((char *)0xb0000)
1829 #define cmapsz 8192
1830 #define seq_port_reg (0x3c4)
1831 #define seq_port_val (0x3c5)
1832 #define gr_port_reg (0x3ce)
1833 #define gr_port_val (0x3cf)
1834
1835 static int set_get_font(char * arg, int set)
1836 {
1837 #ifdef CAN_LOAD_EGA_FONTS
1838 int i;
1839 char *charmap;
1840
1841
1842
1843 if (video_type == VIDEO_TYPE_EGAC)
1844 charmap = colourmap;
1845 else if (video_type == VIDEO_TYPE_EGAM)
1846 charmap = blackwmap;
1847 else
1848 return -EINVAL;
1849
1850 i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
1851 if (i)
1852 return i;
1853
1854 cli();
1855 outb_p( 0x00, seq_port_reg );
1856 outb_p( 0x01, seq_port_val );
1857 outb_p( 0x02, seq_port_reg );
1858 outb_p( 0x04, seq_port_val );
1859 outb_p( 0x04, seq_port_reg );
1860 outb_p( 0x07, seq_port_val );
1861 outb_p( 0x00, seq_port_reg );
1862 outb_p( 0x03, seq_port_val );
1863
1864 outb_p( 0x04, gr_port_reg );
1865 outb_p( 0x02, gr_port_val );
1866 outb_p( 0x05, gr_port_reg );
1867 outb_p( 0x00, gr_port_val );
1868 outb_p( 0x06, gr_port_reg );
1869 outb_p( 0x00, gr_port_val );
1870 sti();
1871
1872 if (set)
1873 for (i=0; i<cmapsz ; i++)
1874 *(charmap+i) = get_fs_byte(arg+i);
1875 else
1876 for (i=0; i<cmapsz ; i++)
1877 put_fs_byte(*(charmap+i), arg+i);
1878
1879 cli();
1880 outb_p( 0x00, seq_port_reg );
1881 outb_p( 0x01, seq_port_val );
1882 outb_p( 0x02, seq_port_reg );
1883 outb_p( 0x03, seq_port_val );
1884 outb_p( 0x04, seq_port_reg );
1885 outb_p( 0x03, seq_port_val );
1886 outb_p( 0x00, seq_port_reg );
1887 outb_p( 0x03, seq_port_val );
1888
1889 outb_p( 0x04, gr_port_reg );
1890 outb_p( 0x00, gr_port_val );
1891 outb_p( 0x05, gr_port_reg );
1892 outb_p( 0x10, gr_port_val );
1893 outb_p( 0x06, gr_port_reg );
1894 outb_p( 0x0e, gr_port_val );
1895 sti();
1896
1897 return 0;
1898 #else
1899 return -EINVAL;
1900 #endif
1901 }
1902
1903
1904
1905
1906
1907
1908
1909 int con_set_font (char *arg)
1910 {
1911 return set_get_font (arg,1);
1912 }
1913
1914 int con_get_font (char *arg)
1915 {
1916 return set_get_font (arg,0);
1917 }
1918
1919
1920
1921
1922
1923
1924 int con_set_trans(char * arg)
1925 {
1926 int i;
1927
1928 i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
1929 if (i)
1930 return i;
1931
1932 for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
1933 USER_TRANS[012]=0;
1934 USER_TRANS[014]=0;
1935 USER_TRANS[015]=0;
1936 USER_TRANS[033]=0;
1937 return 0;
1938 }
1939
1940 int con_get_trans(char * arg)
1941 {
1942 int i;
1943
1944 i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
1945 if (i)
1946 return i;
1947
1948 for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
1949 return 0;
1950 }