2 * linux/kernel/console.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
10 * This module exports the console io functions:
12 * 'long con_init(long)'
13 * 'int con_open(struct tty_struct *tty, struct file * filp)'
14 * 'void update_screen(int new_console)'
15 * 'void blank_screen(void)'
16 * 'void unblank_screen(void)'
18 * 'int con_get_font(char *)'
19 * 'int con_set_font(char *)'
20 * 'int con_get_trans(char *)'
21 * 'int con_set_trans(char *)'
23 * Hopefully this will be a rather complete VT102 implementation.
25 * Beeping thanks to John T Kohl.
27 * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
28 * Chars, and VT100 enhancements by Peter MacDonald.
30 * Copy and paste function by Andrew Haylett.
32 * User definable mapping table and font loading by Eugene G. Crosser,
33 * <crosser@pccross.msk.su>
35 * Code to check for different video-cards mostly by Galen Hunt,
36 * <g-hunt@ee.utah.edu>
40 #define CAN_LOAD_EGA_FONTS /* undefine if the user must not do this */
43 * NOTE!!! We sometimes disable and enable interrupts for a short while
44 * (to put a word in video IO), but this will work even for keyboard
45 * interrupts. We know interrupts aren't enabled when getting a keyboard
46 * interrupt, as we use trap-gates. Hopefully all is well.
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>
59 #include <asm/system.h>
60 #include <asm/segment.h>
65 #ifdef CONFIG_SELECTION
66 #include <linux/ctype.h>
68 /* Routines for selection control. */
69 int set_selection(const int arg
);
70 int paste_selection(struct tty_struct
*tty
);
71 static void clear_selection(void);
73 /* Variables for selection control. */
74 #define SEL_BUFFER_SIZE TTY_BUF_SIZE
76 static int sel_start
= -1;
78 static char sel_buffer
[SEL_BUFFER_SIZE
] = { '\0' };
79 #endif /* CONFIG_SELECTION */
83 extern void vt_init(void);
84 extern void register_console(void (*proc
)(const char *));
85 extern void compute_shiftstate(void);
87 unsigned long video_num_columns
; /* Number of text columns */
88 unsigned long video_num_lines
; /* Number of text lines */
90 static unsigned char video_type
; /* Type of display being used */
91 static unsigned long video_mem_base
; /* Base of video memory */
92 static unsigned long video_mem_term
; /* End of video memory */
93 static unsigned long video_size_row
; /* Bytes per row */
94 static unsigned char video_page
; /* Initial video page */
95 static unsigned short video_port_reg
; /* Video register select port */
96 static unsigned short video_port_val
; /* Video register value port */
97 static int can_do_color
= 0;
98 static int printable
= 0;
101 unsigned short vc_video_erase_char
; /* Background erase character */
102 unsigned char vc_attr
; /* Current attributes */
103 unsigned char vc_def_color
; /* Default colors */
104 unsigned char vc_color
; /* Foreground & background */
105 unsigned char vc_s_color
; /* Saved foreground & background */
106 unsigned char vc_ulcolor
; /* Colour for underline mode */
107 unsigned char vc_halfcolor
; /* Colour for half intensity mode */
108 unsigned long vc_origin
; /* Used for EGA/VGA fast scroll */
109 unsigned long vc_scr_end
; /* Used for EGA/VGA fast scroll */
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
; /* Start of video RAM */
116 unsigned long vc_video_mem_end
; /* End of video RAM (sort of) */
117 unsigned long vc_saved_x
;
118 unsigned long vc_saved_y
;
120 unsigned long vc_charset
: 1; /* Character set G0 / G1 */
121 unsigned long vc_s_charset
: 1; /* Saved character set */
122 unsigned long vc_decscnm
: 1; /* Screen Mode */
123 unsigned long vc_decom
: 1; /* Origin Mode */
124 unsigned long vc_decawm
: 1; /* Autowrap Mode */
125 unsigned long vc_deccm
: 1; /* Cursor Visible */
126 unsigned long vc_decim
: 1; /* Insert Mode */
127 /* attribute flags */
128 unsigned long vc_intensity
: 2; /* 0=half-bright, 1=normal, 2=bold */
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; /* saved rendition */
133 unsigned long vc_s_underline
: 1;
134 unsigned long vc_s_blink
: 1;
135 unsigned long vc_s_reverse
: 1;
137 unsigned long vc_ques
: 1;
138 unsigned long vc_need_wrap
: 1;
139 unsigned long vc_tab_stop
[5]; /* Tab stops. 160 columns. */
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 /* additional information is in vt_kern.h */
146 } vc_cons
[NR_CONSOLES
];
148 unsigned short *vc_scrbuf
[NR_CONSOLES
];
149 static unsigned short * vc_scrmembuf
;
150 static int console_blanked
= 0;
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)
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)
207 #define decarm VC_REPEAT
208 #define decckm VC_CKMODE
209 #define kbdapplic VC_APPLIC
210 #define kbdraw VC_RAW
213 int blankinterval
= 10*60*HZ
;
214 static int screen_size
= 0;
217 * this is what the terminal answers to a ESC-Z or csi0c query.
219 #define VT100ID "\033[?1;2c"
220 #define VT102ID "\033[?6c"
222 static unsigned char * translations
[] = {
223 /* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
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",
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 /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
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 /* USER: customizable mappings, initialized as the previous one (IBM) */
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"
292 #define NORM_TRANS (translations[0])
293 #define GRAF_TRANS (translations[1])
294 #define NULL_TRANS (translations[2])
295 #define USER_TRANS (translations[3])
297 static unsigned char color_table
[] = { 0, 4, 2, 6, 1, 5, 3, 7,
298 8,12,10,14, 9,13,11,15 };
301 * gotoxy() must verify all boundaries, because the arguments
302 * might also be negative. If the given position is out of
303 * bounds, the cursor is placed at the nearest margin.
305 static void gotoxy(int currcons
, int new_x
, int new_y
)
312 if (new_x
>= video_num_columns
)
313 x
= video_num_columns
- 1;
320 max_y
= video_num_lines
;
328 pos
= origin
+ y
*video_size_row
+ (x
<<1);
333 * *Very* limited hardware scrollback support..
335 static unsigned short __real_origin
;
336 static unsigned short __origin
;
338 static inline void __set_origin(unsigned short offset
)
341 #ifdef CONFIG_SELECTION
343 #endif /* CONFIG_SELECTION */
344 save_flags(flags
); cli();
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
);
353 void scrollback(int lines
)
356 lines
= video_num_lines
/2;
357 lines
*= video_num_columns
;
358 lines
= __origin
- lines
;
364 void scrollfront(int 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
;
375 static void set_origin(int currcons
)
377 if (video_type
!= VIDEO_TYPE_EGAC
&& video_type
!= VIDEO_TYPE_EGAM
)
379 if (currcons
!= fg_console
|| console_blanked
|| vcmode
== KD_GRAPHICS
)
381 __real_origin
= (origin
-video_mem_base
) >> 1;
382 __set_origin(__real_origin
);
385 static inline void hide_cursor(int currcons
)
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
);
393 static inline void set_cursor(int currcons
)
397 if (currcons
!= fg_console
|| console_blanked
|| vcmode
== KD_GRAPHICS
)
399 if (__real_origin
!= __origin
)
400 set_origin(__real_origin
);
401 save_flags(flags
); cli();
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
);
408 hide_cursor(currcons
);
409 restore_flags(flags
);
412 static void scrup(int currcons
, unsigned int t
, unsigned int b
)
416 if (b
> video_num_lines
|| t
>= b
)
418 if (video_type
!= VIDEO_TYPE_EGAC
&& video_type
!= VIDEO_TYPE_EGAM
)
420 else if (t
|| b
!= video_num_lines
)
423 origin
+= video_size_row
;
424 pos
+= video_size_row
;
425 scr_end
+= video_size_row
;
426 if (scr_end
> video_mem_end
) {
430 "movl _video_num_columns,%1\n\t"
434 :"a" (video_erase_char
),
435 "c" ((video_num_lines
-1)*video_num_columns
>>1),
436 "D" (video_mem_start
),
439 scr_end
-= origin
-video_mem_start
;
440 pos
-= origin
-video_mem_start
;
441 origin
= video_mem_start
;
447 :"a" (video_erase_char
),
448 "c" (video_num_columns
),
449 "D" (scr_end
-video_size_row
)
452 set_origin(currcons
);
457 "movl _video_num_columns,%%ecx\n\t"
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))
469 static void scrdown(int currcons
, unsigned int t
, unsigned int b
)
471 if (b
> video_num_lines
|| t
>= b
)
476 "addl $2,%%edi\n\t" /* %edi has been decremented by 4 */
477 "movl _video_num_columns,%%ecx\n\t"
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");
489 static void lf(int currcons
)
493 pos
+= video_size_row
;
496 scrup(currcons
,top
,bottom
);
500 static void ri(int currcons
)
504 pos
-= video_size_row
;
507 scrdown(currcons
,top
,bottom
);
511 static inline void cr(int currcons
)
517 static inline void bs(int currcons
)
526 static inline void del(int currcons
)
530 if (!need_wrap
) { /* this is not the right condition */
534 *(unsigned short *)pos
= video_erase_char
;
540 static void csi_J(int currcons
, int vpar
)
546 case 0: /* erase from cursor to end of display */
547 count
= (scr_end
-pos
)>>1;
550 case 1: /* erase from start to cursor */
551 count
= ((pos
-origin
)>>1)+1;
554 case 2: /* erase whole display */
555 count
= video_num_columns
* video_num_lines
;
566 "D" (start
),"a" (video_erase_char
)
571 static void csi_K(int currcons
, int vpar
)
577 case 0: /* erase from cursor to end of line */
578 count
= video_num_columns
-x
;
581 case 1: /* erase from start of line to cursor */
582 start
= pos
- (x
<<1);
585 case 2: /* erase whole line */
586 start
= pos
- (x
<<1);
587 count
= video_num_columns
;
597 "D" (start
),"a" (video_erase_char
)
603 * I hope this works. The monochrome part is untested.
605 static void update_attr(int currcons
)
610 attr
= (attr
& 0xf0) | ulcolor
;
611 else if (intensity
== 0)
612 attr
= (attr
& 0xf0) | halfcolor
;
614 if (reverse
^ decscnm
)
615 attr
= (attr
& 0x88) | (((attr
>> 4) | (attr
<< 4)) & 0x77);
622 attr
= (attr
& 0xf8) | 0x01;
623 else if (intensity
== 0)
624 attr
= (attr
& 0xf0) | 0x08;
627 video_erase_char
= (((color
& 0x88) | (((color
>> 4) | (color
<< 4)) & 0x77)) << 8) | ' ';
629 video_erase_char
= (color
<< 8) | ' ';
632 static void default_attr(int currcons
)
641 static void csi_m(int currcons
)
645 for (i
=0;i
<=npar
;i
++)
647 case 0: /* all attributes off */
648 default_attr(currcons
);
679 color
= (def_color
& 0x0f) | background
;
682 color
= (def_color
& 0xf0) | foreground
;
685 if (par
[i
] >= 30 && par
[i
] <= 37)
686 color
= color_table
[par
[i
]-30]
688 else if (par
[i
] >= 40 && par
[i
] <= 47)
689 color
= (color_table
[par
[i
]-40]<<4)
693 update_attr(currcons
);
696 static void respond_string(char * p
, int currcons
, struct tty_struct
* tty
)
699 put_tty_queue(*p
, &tty
->read_q
);
705 static void respond_num(unsigned int n
, int currcons
, struct tty_struct
* tty
)
711 buff
[i
++] = (n
%10)+'0';
713 } while(n
&& i
< 3); /* We'll take no chances */
715 put_tty_queue(buff
[i
], &tty
->read_q
);
717 /* caller must flush */
720 static void cursor_report(int currcons
, struct tty_struct
* tty
)
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
);
731 static inline void status_report(int currcons
, struct tty_struct
* tty
)
733 respond_string("\033[0n", currcons
, tty
); /* Terminal ok */
736 static inline void respond_ID(int currcons
, struct tty_struct
* tty
)
738 respond_string(VT102ID
, currcons
, tty
);
741 static void invert_screen(int currcons
) {
745 for (p
= (unsigned char *)origin
+1; p
< (unsigned char *)scr_end
; p
+=2)
746 *p
= (*p
& 0x88) | (((*p
>> 4) | (*p
<< 4)) & 0x77);
748 for (p
= (unsigned char *)origin
+1; p
< (unsigned char *)scr_end
; p
+=2)
749 *p
^= *p
& 0x07 == 1 ? 0x70 : 0x77;
752 static void set_mode(int currcons
, int on_off
)
756 for (i
=0; i
<=npar
; i
++)
757 if (ques
) switch(par
[i
]) { /* DEC private modes set/reset */
758 case 1: /* Cursor keys send ^[Ox/^[[x */
764 case 3: /* 80/132 mode switch unimplemented */
766 gotoxy(currcons
,0,0);
768 case 5: /* Inverted screen on/off */
769 if (decscnm
!= on_off
) {
771 invert_screen(currcons
);
772 update_attr(currcons
);
775 case 6: /* Origin relative/absolute */
777 gotoxy(currcons
,0,0);
779 case 7: /* Autowrap on/off */
782 case 8: /* Autorepeat on/off */
788 case 25: /* Cursor on/off */
790 set_cursor(currcons
);
792 } else switch(par
[i
]) { /* ANSI modes set/reset */
793 case 4: /* Insert Mode on/off */
796 case 20: /* Lf, Enter == CrLf/Lf */
805 static void setterm_command(int currcons
)
808 case 1: /* set color for underline mode */
809 if (can_do_color
&& par
[1] < 16) {
810 ulcolor
= color_table
[par
[1]];
812 update_attr(currcons
);
815 case 2: /* set color for half intensity mode */
816 if (can_do_color
&& par
[1] < 16) {
817 halfcolor
= color_table
[par
[1]];
819 update_attr(currcons
);
822 case 8: /* store colors as defaults */
824 default_attr(currcons
);
825 update_attr(currcons
);
827 case 9: /* set blanking interval */
828 blankinterval
= ((par
[1] < 60) ? par
[1] : 60) * 60 * HZ
;
833 static void insert_char(int currcons
)
836 unsigned short tmp
, old
= video_erase_char
;
837 unsigned short * p
= (unsigned short *) pos
;
839 while (i
++ < video_num_columns
) {
848 static void insert_line(int currcons
)
850 scrdown(currcons
,y
,bottom
);
854 static void delete_char(int currcons
)
857 unsigned short * p
= (unsigned short *) pos
;
859 while (++i
< video_num_columns
) {
863 *p
= video_erase_char
;
867 static void delete_line(int currcons
)
869 scrup(currcons
,y
,bottom
);
873 static void csi_at(int currcons
, unsigned int nr
)
875 if (nr
> video_num_columns
)
876 nr
= video_num_columns
;
880 insert_char(currcons
);
883 static void csi_L(int currcons
, unsigned int nr
)
885 if (nr
> video_num_lines
)
886 nr
= video_num_lines
;
890 insert_line(currcons
);
893 static void csi_P(int currcons
, unsigned int nr
)
895 if (nr
> video_num_columns
)
896 nr
= video_num_columns
;
900 delete_char(currcons
);
903 static void csi_M(int currcons
, unsigned int nr
)
905 if (nr
> video_num_lines
)
906 nr
= video_num_lines
;
910 delete_line(currcons
);
913 static void save_cur(int currcons
)
917 s_intensity
= intensity
;
918 s_underline
= underline
;
923 saved_G0
= G0_charset
;
924 saved_G1
= G1_charset
;
927 static void restore_cur(int currcons
)
929 gotoxy(currcons
,saved_x
,saved_y
);
930 intensity
= s_intensity
;
931 underline
= s_underline
;
936 G0_charset
= saved_G0
;
937 G1_charset
= saved_G1
;
938 translate
= charset
? G1_charset
: G0_charset
;
939 update_attr(currcons
);
943 enum { ESnormal
, ESesc
, ESsquare
, ESgetpars
, ESgotpars
, ESfunckey
,
944 EShash
, ESsetG0
, ESsetG1
, ESignore
};
946 static void reset_terminal(int currcons
, int do_clear
)
949 bottom
= video_num_lines
;
952 translate
= NORM_TRANS
;
953 G0_charset
= NORM_TRANS
;
954 G1_charset
= GRAF_TRANS
;
968 kbd_table
[currcons
].lockstate
= 0;
969 kbd_table
[currcons
].ledstate
= kbd_table
[currcons
].default_ledstate
;
972 default_attr(currcons
);
973 update_attr(currcons
);
975 tab_stop
[0] = 0x01010100;
979 tab_stop
[4] = 0x01010101;
982 gotoxy(currcons
,0,0);
988 void con_write(struct tty_struct
* tty
)
991 unsigned int currcons
;
993 currcons
= tty
->line
- 1;
994 if (currcons
>= NR_CONSOLES
) {
995 printk("con_write: illegal tty (%d)\n", currcons
);
998 #ifdef CONFIG_SELECTION
999 /* clear the selection as soon as any characters are to be written
1000 out on the console holding the selection. */
1001 if (!EMPTY(&tty
->write_q
) && currcons
== sel_cons
)
1003 #endif /* CONFIG_SELECTION */
1004 disable_bh(KEYBOARD_BH
);
1005 while (!tty
->stopped
&& (c
= get_tty_queue(&tty
->write_q
)) >= 0) {
1006 if (state
== ESnormal
&& translate
[c
]) {
1012 insert_char(currcons
);
1014 *(unsigned short *) pos
= (attr
<< 8) + c
;
1015 if (x
== video_num_columns
- 1)
1025 * Control characters can be used in the _middle_
1026 * of an escape sequence.
1030 kd_mksound(0x637, HZ
/8);
1037 while (x
< video_num_columns
- 1) {
1039 if (tab_stop
[x
>> 5] & (1 << (x
& 31)))
1044 case 10: case 11: case 12:
1053 translate
= G1_charset
;
1057 translate
= G0_charset
;
1090 tab_stop
[x
>> 5] |= (1 << (x
& 31));
1093 respond_ID(currcons
,tty
);
1099 restore_cur(currcons
);
1111 reset_terminal(currcons
,1);
1113 case '>': /* Numeric keypad */
1116 case '=': /* Appl. keypad */
1122 for(npar
= 0 ; npar
< NPAR
; npar
++)
1126 if (c
== '[') { /* Function key */
1134 if (c
==';' && npar
<NPAR
-1) {
1137 } else if (c
>='0' && c
<='9') {
1141 } else state
=ESgotpars
;
1146 set_mode(currcons
,1);
1149 set_mode(currcons
,0);
1154 status_report(currcons
,tty
);
1155 else if (par
[0] == 6)
1156 cursor_report(currcons
,tty
);
1165 if (par
[0]) par
[0]--;
1166 gotoxy(currcons
,par
[0],y
);
1169 if (!par
[0]) par
[0]++;
1170 gotoxy(currcons
,x
,y
-par
[0]);
1173 if (!par
[0]) par
[0]++;
1174 gotoxy(currcons
,x
,y
+par
[0]);
1177 if (!par
[0]) par
[0]++;
1178 gotoxy(currcons
,x
+par
[0],y
);
1181 if (!par
[0]) par
[0]++;
1182 gotoxy(currcons
,x
-par
[0],y
);
1185 if (!par
[0]) par
[0]++;
1186 gotoxy(currcons
,0,y
+par
[0]);
1189 if (!par
[0]) par
[0]++;
1190 gotoxy(currcons
,0,y
-par
[0]);
1193 if (par
[0]) par
[0]--;
1194 gotoxy(currcons
,x
,par
[0]);
1197 if (par
[0]) par
[0]--;
1198 if (par
[1]) par
[1]--;
1199 gotoxy(currcons
,par
[1],par
[0]);
1202 csi_J(currcons
,par
[0]);
1205 csi_K(currcons
,par
[0]);
1208 csi_L(currcons
,par
[0]);
1211 csi_M(currcons
,par
[0]);
1214 csi_P(currcons
,par
[0]);
1218 respond_ID(currcons
,tty
);
1222 tab_stop
[x
>> 5] &= ~(1 << (x
& 31));
1223 else if (par
[0] == 3) {
1238 par
[1] = video_num_lines
;
1239 /* Minimum allowed region is 2 lines */
1240 if (par
[0] < par
[1] &&
1241 par
[1] <= video_num_lines
) {
1244 gotoxy(currcons
,0,0);
1251 restore_cur(currcons
);
1254 csi_at(currcons
,par
[0]);
1256 case ']': /* setterm functions */
1257 setterm_command(currcons
);
1267 /* DEC screen alignment test. kludge :-) */
1269 (video_erase_char
& 0xff00) | 'E';
1272 (video_erase_char
& 0xff00) | ' ';
1277 G0_charset
= GRAF_TRANS
;
1279 G0_charset
= NORM_TRANS
;
1281 G0_charset
= NULL_TRANS
;
1283 G0_charset
= USER_TRANS
;
1285 translate
= G0_charset
;
1290 G1_charset
= GRAF_TRANS
;
1292 G1_charset
= NORM_TRANS
;
1294 G1_charset
= NULL_TRANS
;
1296 G1_charset
= USER_TRANS
;
1298 translate
= G1_charset
;
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
);
1312 void do_keyboard_interrupt(void)
1314 TTY_READ_FLUSH(TTY_TABLE(0));
1315 timer_active
&= ~(1<<BLANK_TIMER
);
1316 if (vt_cons
[fg_console
].vc_mode
== KD_GRAPHICS
)
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
;
1327 void * memsetw(void * s
,unsigned short c
,int count
)
1333 :"a" (c
),"D" (s
),"c" (count
)
1338 void console_print(const char * b
)
1340 int currcons
= fg_console
;
1343 if (!printable
|| currcons
<0 || currcons
>=NR_CONSOLES
)
1345 while ((c
= *(b
++)) != 0) {
1346 if (c
== 10 || c
== 13 || need_wrap
) {
1350 if (c
== 10 || c
== 13)
1353 *(unsigned short *) pos
= (attr
<< 8) + c
;
1354 if (x
== video_num_columns
- 1) {
1361 set_cursor(currcons
);
1362 if (vt_cons
[fg_console
].vc_mode
== KD_GRAPHICS
)
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
;
1375 * long con_init(long);
1377 * This routine initalizes console interrupts, and does nothing
1378 * else. If you want the screen to clear, call tty_write with
1379 * the appropriate escape-sequece.
1381 * Reads the information preserved by setup.s to determine the current display
1382 * type and sets everything accordingly.
1384 long con_init(long kmem_start
)
1386 char *display_desc
= "????";
1389 int orig_x
= ORIG_X
;
1390 int orig_y
= ORIG_Y
;
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
;
1406 if (ORIG_VIDEO_MODE
== 7) /* Is this a monochrome display? */
1408 video_mem_base
= 0xb0000;
1409 video_port_reg
= 0x3b4;
1410 video_port_val
= 0x3b5;
1411 if ((ORIG_VIDEO_EGA_BX
& 0xff) != 0x10)
1413 video_type
= VIDEO_TYPE_EGAM
;
1414 video_mem_term
= 0xb8000;
1415 display_desc
= "EGA+";
1419 video_type
= VIDEO_TYPE_MDA
;
1420 video_mem_term
= 0xb2000;
1421 display_desc
= "*MDA";
1424 else /* If not, it is color. */
1427 video_mem_base
= 0xb8000;
1428 video_port_reg
= 0x3d4;
1429 video_port_val
= 0x3d5;
1430 if ((ORIG_VIDEO_EGA_BX
& 0xff) != 0x10)
1432 video_type
= VIDEO_TYPE_EGAC
;
1433 video_mem_term
= 0xc0000;
1434 display_desc
= "EGA+";
1438 video_type
= VIDEO_TYPE_CGA
;
1439 video_mem_term
= 0xba000;
1440 display_desc
= "*CGA";
1444 /* Initialize the variables used for scrolling (mostly EGA/VGA) */
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
;
1452 vtmode
.mode
= VT_AUTO
;
1460 def_color
= 0x07; /* white */
1461 ulcolor
= 0x0f; /* bold white */
1462 halfcolor
= 0x08; /* grey */
1463 reset_terminal(currcons
, currcons
);
1465 currcons
= fg_console
= 0;
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);
1473 gotoxy(currcons
,orig_x
,orig_y
);
1474 update_screen(fg_console
);
1476 printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
1477 can_do_color
?"colour":"mono",
1479 video_num_columns
,video_num_lines
,
1481 register_console(console_print
);
1486 * kbdsave doesn't need to do anything: it's all handled automatically
1487 * with the new data structures..
1489 void kbdsave(int new_console
)
1493 static void get_scrmem(int currcons
)
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);
1502 static void set_scrmem(int currcons
)
1505 /* This works with XFree86 1.2, 1.3 and 2.0
1506 This code could be extended and made more generally useful if we could
1507 determine the actual video mode. It appears that this should be
1508 possible on a genuine Hercules card, but I (WM) haven't been able to
1509 read from any of the required registers on my clone card.
1511 /* This code should work with Hercules and MDA cards. */
1512 if (video_type
== VIDEO_TYPE_MDA
)
1514 if (vcmode
== KD_TEXT
)
1516 /* Ensure that the card is in text mode. */
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); /* Back to power-on defaults */
1521 outb_p(0, 0x3b8); /* Blank the screen, select page 0, etc */
1522 for ( i
= 0 ; i
< 12 ; i
++ )
1525 outb_p(herc_txt_tbl
[i
], 0x3b5);
1528 #define HGA_BLINKER_ON 0x20
1529 #define HGA_SCREEN_ON 8
1530 /* Make sure that the hardware is not blanked */
1531 outb_p(HGA_BLINKER_ON
| HGA_SCREEN_ON
, 0x3b8);
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
);
1543 void blank_screen(void)
1545 if (console_blanked
)
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
);
1554 void unblank_screen(void)
1556 if (!console_blanked
)
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
;
1563 console_blanked
= 0;
1564 set_scrmem(fg_console
);
1565 set_origin(fg_console
);
1566 set_cursor(fg_console
);
1569 void update_screen(int new_console
)
1571 static int lock
= 0;
1573 if (new_console
== fg_console
|| lock
)
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
);
1583 compute_shiftstate();
1587 int do_screendump(int arg
)
1589 char *sptr
, *buf
= (char *)arg
;
1594 l
= verify_area(VERIFY_WRITE
, buf
,2+video_num_columns
*video_num_lines
);
1597 currcons
= get_fs_byte(buf
+1);
1598 if ((currcons
<0) || (currcons
>NR_CONSOLES
))
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
++);
1610 * All we do is set the write and ioctl subroutines; later on maybe we'll
1611 * dynamically allocate the console screen memory.
1613 int con_open(struct tty_struct
*tty
, struct file
* filp
)
1615 tty
->write
= con_write
;
1616 tty
->ioctl
= vt_ioctl
;
1617 if (tty
->line
> NR_CONSOLES
)
1622 #ifdef CONFIG_SELECTION
1623 /* correction factor for when screen is hardware-scrolled */
1624 #define hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
1626 /* set reverse video on characters s-e of console with selection. */
1627 static void highlight(const int currcons
, const int s
, const int e
)
1629 unsigned char *p
, *p1
, *p2
;
1631 p1
= (unsigned char *)origin
- hwscroll_offset
+ s
+ 1;
1632 p2
= (unsigned char *)origin
- hwscroll_offset
+ e
+ 1;
1639 for (p
= p1
; p
<= p2
; p
+= 2)
1640 *p
= (*p
& 0x88) | ((*p
<< 4) & 0x70) | ((*p
>> 4) & 0x07);
1643 /* is c in range [a-zA-Z0-9_]? */
1644 static inline int inword(const char c
) { return (isalnum(c
) || c
== '_'); }
1646 /* does screen address p correspond to character at LH/RH edge of screen? */
1647 static inline int atedge(const int p
)
1649 return (!(p
% video_size_row
) || !((p
+ 2) % video_size_row
));
1652 /* constrain v such that l <= v <= u */
1653 static inline short limit(const int v
, const int l
, const int u
)
1655 return (v
< l
) ? l
: ((v
> u
) ? u
: v
);
1658 /* set the current selection. Invoked by ioctl(). */
1659 int set_selection(const int arg
)
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
;
1666 char *off
= (char *)origin
- hwscroll_offset
;
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
);
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);
1683 if (ps
> pe
) /* make sel_start <= sel_end */
1692 case 0: /* character-by-character selection */
1697 case 1: /* word-by-word selection */
1698 spc
= isspace(*(off
+ ps
));
1699 for (new_sel_start
= ps
; ; ps
-= 2)
1701 if ((spc
&& !isspace(*(off
+ ps
))) ||
1702 (!spc
&& !inword(*(off
+ ps
))))
1705 if (!(ps
% video_size_row
))
1708 spc
= isspace(*(off
+ pe
));
1709 for (new_sel_end
= pe
; ; pe
+= 2)
1711 if ((spc
&& !isspace(*(off
+ pe
))) ||
1712 (!spc
&& !inword(*(off
+ pe
))))
1715 if (!((pe
+ 2) % video_size_row
))
1719 case 2: /* line-by-line selection */
1720 new_sel_start
= ps
- ps
% video_size_row
;
1721 new_sel_end
= pe
+ video_size_row
1722 - pe
% video_size_row
- 2;
1725 /* select to end of line if on trailing space */
1726 if (new_sel_end
> new_sel_start
&&
1727 !atedge(new_sel_end
) && isspace(*(off
+ new_sel_end
)))
1729 for (pe
= new_sel_end
+ 2; ; pe
+= 2)
1731 if (!isspace(*(off
+ pe
)) || atedge(pe
))
1734 if (isspace(*(off
+ pe
)))
1737 if (sel_cons
!= currcons
)
1740 sel_cons
= currcons
;
1742 if (sel_start
== -1) /* no current selection */
1743 highlight(sel_cons
, new_sel_start
, new_sel_end
);
1744 else if (new_sel_start
== sel_start
)
1746 if (new_sel_end
== sel_end
) /* no action required */
1748 else if (new_sel_end
> sel_end
) /* extend to right */
1749 highlight(sel_cons
, sel_end
+ 2, new_sel_end
);
1750 else /* contract from right */
1751 highlight(sel_cons
, new_sel_end
+ 2, sel_end
);
1753 else if (new_sel_end
== sel_end
)
1755 if (new_sel_start
< sel_start
) /* extend to left */
1756 highlight(sel_cons
, new_sel_start
, sel_start
- 2);
1757 else /* contract from left */
1758 highlight(sel_cons
, sel_start
, new_sel_start
- 2);
1760 else /* some other case; start selection from scratch */
1763 highlight(sel_cons
, new_sel_start
, new_sel_end
);
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)
1770 spos
= (char *)off
+ i
;
1772 if (!isspace(*spos
))
1774 if (! ((i
+ 2) % video_size_row
))
1776 /* strip trailing blanks from line and add newline,
1777 unless non-space at end of line. */
1785 /* check for space, leaving room for next character, possible
1786 newline, and null at end. */
1787 if (bp
- sel_buffer
> SEL_BUFFER_SIZE
- 3)
1794 /* insert the contents of the selection buffer into the queue of the
1795 tty associated with the current console. Invoked by ioctl(). */
1796 int paste_selection(struct tty_struct
*tty
)
1798 char *bp
= sel_buffer
;
1805 put_tty_queue(*bp
, &tty
->read_q
);
1808 TTY_READ_FLUSH(tty
);
1812 /* remove the current selection highlight, if any, from the console holding
1814 static void clear_selection()
1816 if (sel_start
!= -1)
1818 highlight(sel_cons
, sel_start
, sel_end
);
1822 #endif /* CONFIG_SELECTION */
1828 #define colourmap ((char *)0xa0000)
1829 #define blackwmap ((char *)0xb0000)
1831 #define seq_port_reg (0x3c4)
1832 #define seq_port_val (0x3c5)
1833 #define gr_port_reg (0x3ce)
1834 #define gr_port_val (0x3cf)
1836 static int set_get_font(char * arg
, int set
)
1838 #ifdef CAN_LOAD_EGA_FONTS
1842 /* no use to "load" CGA... */
1844 if (video_type
== VIDEO_TYPE_EGAC
)
1845 charmap
= colourmap
;
1846 else if (video_type
== VIDEO_TYPE_EGAM
)
1847 charmap
= blackwmap
;
1851 i
= verify_area(set
? VERIFY_READ
: VERIFY_WRITE
, (void *)arg
, cmapsz
);
1856 outb_p( 0x00, seq_port_reg
); /* First, the sequencer */
1857 outb_p( 0x01, seq_port_val
); /* Synchronous reset */
1858 outb_p( 0x02, seq_port_reg
);
1859 outb_p( 0x04, seq_port_val
); /* CPU writes only to map 2 */
1860 outb_p( 0x04, seq_port_reg
);
1861 outb_p( 0x07, seq_port_val
); /* Sequential addressing */
1862 outb_p( 0x00, seq_port_reg
);
1863 outb_p( 0x03, seq_port_val
); /* Clear synchronous reset */
1865 outb_p( 0x04, gr_port_reg
); /* Now, the graphics controller */
1866 outb_p( 0x02, gr_port_val
); /* select map 2 */
1867 outb_p( 0x05, gr_port_reg
);
1868 outb_p( 0x00, gr_port_val
); /* disable odd-even addressing */
1869 outb_p( 0x06, gr_port_reg
);
1870 outb_p( 0x00, gr_port_val
); /* map start at A000:0000 */
1874 for (i
=0; i
<cmapsz
; i
++)
1875 *(charmap
+i
) = get_fs_byte(arg
+i
);
1877 for (i
=0; i
<cmapsz
; i
++)
1878 put_fs_byte(*(charmap
+i
), arg
+i
);
1881 outb_p( 0x00, seq_port_reg
); /* Frist, the sequencer */
1882 outb_p( 0x01, seq_port_val
); /* Synchronous reset */
1883 outb_p( 0x02, seq_port_reg
);
1884 outb_p( 0x03, seq_port_val
); /* CPU writes to maps 0 and 1 */
1885 outb_p( 0x04, seq_port_reg
);
1886 outb_p( 0x03, seq_port_val
); /* odd-even addressing */
1887 outb_p( 0x00, seq_port_reg
);
1888 outb_p( 0x03, seq_port_val
); /* clear synchronous reset */
1890 outb_p( 0x04, gr_port_reg
); /* Now, the graphics controller */
1891 outb_p( 0x00, gr_port_val
); /* select map 0 for CPU */
1892 outb_p( 0x05, gr_port_reg
);
1893 outb_p( 0x10, gr_port_val
); /* enable even-odd addressing */
1894 outb_p( 0x06, gr_port_reg
);
1895 outb_p( 0x0e, gr_port_val
); /* map starts at b800:0000 */
1905 * Load font into the EGA/VGA character generator. arg points to a 8192
1906 * byte map, 32 bytes per character. Only first H of them are used for
1907 * 8xH fonts (0 < H <= 32).
1910 int con_set_font (char *arg
)
1912 return set_get_font (arg
,1);
1915 int con_get_font (char *arg
)
1917 return set_get_font (arg
,0);
1921 * Load customizable translation table (USER_TRANS[]). All checks are here,
1922 * so we need only include 'return con_set_trans(arg)' in the ioctl handler
1923 * arg points to a 256 byte translation table.
1925 int con_set_trans(char * arg
)
1929 i
= verify_area(VERIFY_READ
, (void *)arg
, E_TABSZ
);
1933 for (i
=0; i
<E_TABSZ
; i
++) USER_TRANS
[i
] = get_fs_byte(arg
+i
);
1941 int con_get_trans(char * arg
)
1945 i
= verify_area(VERIFY_WRITE
, (void *)arg
, E_TABSZ
);
1949 for (i
=0; i
<E_TABSZ
; i
++) put_fs_byte(USER_TRANS
[i
],arg
+i
);