home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / drivers / char / console.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-23  |  48.4 KB  |  1,968 lines

  1. /*
  2.  *  linux/kernel/console.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6.  
  7. /*
  8.  *    console.c
  9.  *
  10.  * This module exports the console io functions:
  11.  * 
  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)'
  17.  *
  18.  *      'int  con_get_font(char *)' 
  19.  *      'int  con_set_font(char *)' 
  20.  *      'int  con_get_trans(char *)'
  21.  *      'int  con_set_trans(char *)'
  22.  * 
  23.  * Hopefully this will be a rather complete VT102 implementation.
  24.  *
  25.  * Beeping thanks to John T Kohl.
  26.  * 
  27.  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  28.  *   Chars, and VT100 enhancements by Peter MacDonald.
  29.  *
  30.  * Copy and paste function by Andrew Haylett.
  31.  *
  32.  * User definable mapping table and font loading by Eugene G. Crosser,
  33.  * <crosser@pccross.msk.su>
  34.  *
  35.  * Code to check for different video-cards mostly by Galen Hunt,
  36.  * <g-hunt@ee.utah.edu>
  37.  *
  38.  */
  39.  
  40. #define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
  41.  
  42. /*
  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.
  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. /* 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);
  72.  
  73. /* Variables for selection control. */
  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 /* CONFIG_SELECTION */
  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;        /* Number of text columns    */
  88. unsigned long    video_num_lines;        /* Number of text lines        */
  89.  
  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;
  99.  
  100. static struct {
  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;
  119.     /* mode flags */
  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;
  136.     /* misc */
  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];
  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.  * this is what the terminal answers to a ESC-Z or csi0c query.
  218.  */
  219. #define VT100ID "\033[?1;2c"
  220. #define VT102ID "\033[?6c"
  221.  
  222. static unsigned char * translations[] = {
  223. /* 8-bit Latin-1 mapped to the PC character set: '\0' means non-printable */
  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. /* vt100 graphics */
  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. /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
  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.  /* USER: customizable mappings, initialized as the previous one (IBM) */
  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.  * 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.
  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.  * *Very* limited hardware scrollback support..
  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 /* CONFIG_SELECTION */
  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. /*
  386.  * Put the cursor just beyond the end of the display adaptor memory.
  387.  */
  388. static inline void hide_cursor(void)
  389. {
  390.   /* This is inefficient, we could just put the cursor at 0xffff,
  391.      but perhaps the delays due to the inefficiency are useful for
  392.      some hardware... */
  393.     outb_p(14, video_port_reg);
  394.     outb_p(0xff&((video_mem_term-video_mem_base)>>9), video_port_val);
  395.     outb_p(15, video_port_reg);
  396.     outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
  397. }
  398.  
  399. static inline void set_cursor(int currcons)
  400. {
  401.     unsigned long flags;
  402.  
  403.     if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
  404.         return;
  405.     if (__real_origin != __origin)
  406.         set_origin(__real_origin);
  407.     save_flags(flags); cli();
  408.     if (deccm) {
  409.         outb_p(14, video_port_reg);
  410.         outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
  411.         outb_p(15, video_port_reg);
  412.         outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
  413.     } else
  414.         hide_cursor();
  415.     restore_flags(flags);
  416. }
  417.  
  418. static void scrup(int currcons, unsigned int t, unsigned int b)
  419. {
  420.     int hardscroll = 1;
  421.  
  422.     if (b > video_num_lines || t >= b)
  423.         return;
  424.     if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
  425.         hardscroll = 0;
  426.     else if (t || b != video_num_lines)
  427.         hardscroll = 0;
  428.     if (hardscroll) {
  429.         origin += video_size_row;
  430.         pos += video_size_row;
  431.         scr_end += video_size_row;
  432.         if (scr_end > video_mem_end) {
  433.             __asm__("cld\n\t"
  434.                 "rep\n\t"
  435.                 "movsl\n\t"
  436.                 "movl _video_num_columns,%1\n\t"
  437.                 "rep\n\t"
  438.                 "stosw"
  439.                 : /* no output */
  440.                 :"a" (video_erase_char),
  441.                 "c" ((video_num_lines-1)*video_num_columns>>1),
  442.                 "D" (video_mem_start),
  443.                 "S" (origin)
  444.                 :"cx","di","si");
  445.             scr_end -= origin-video_mem_start;
  446.             pos -= origin-video_mem_start;
  447.             origin = video_mem_start;
  448.         } else {
  449.             __asm__("cld\n\t"
  450.                 "rep\n\t"
  451.                 "stosw"
  452.                 : /* no output */
  453.                 :"a" (video_erase_char),
  454.                 "c" (video_num_columns),
  455.                 "D" (scr_end-video_size_row)
  456.                 :"cx","di");
  457.         }
  458.         set_origin(currcons);
  459.     } else {
  460.         __asm__("cld\n\t"
  461.             "rep\n\t"
  462.             "movsl\n\t"
  463.             "movl _video_num_columns,%%ecx\n\t"
  464.             "rep\n\t"
  465.             "stosw"
  466.             : /* no output */
  467.             :"a" (video_erase_char),
  468.             "c" ((b-t-1)*video_num_columns>>1),
  469.             "D" (origin+video_size_row*t),
  470.             "S" (origin+video_size_row*(t+1))
  471.             :"cx","di","si");
  472.     }
  473. }
  474.  
  475. static void scrdown(int currcons, unsigned int t, unsigned int b)
  476. {
  477.     if (b > video_num_lines || t >= b)
  478.         return;
  479.     __asm__("std\n\t"
  480.         "rep\n\t"
  481.         "movsl\n\t"
  482.         "addl $2,%%edi\n\t"    /* %edi has been decremented by 4 */
  483.         "movl _video_num_columns,%%ecx\n\t"
  484.         "rep\n\t"
  485.         "stosw\n\t"
  486.         "cld"
  487.         : /* no output */
  488.         :"a" (video_erase_char),
  489.         "c" ((b-t-1)*video_num_columns>>1),
  490.         "D" (origin+video_size_row*b-4),
  491.         "S" (origin+video_size_row*(b-1)-4)
  492.         :"ax","cx","di","si");
  493. }
  494.  
  495. static void lf(int currcons)
  496. {
  497.     if (y+1<bottom) {
  498.         y++;
  499.         pos += video_size_row;
  500.         return;
  501.     } else 
  502.         scrup(currcons,top,bottom);
  503.     need_wrap = 0;
  504. }
  505.  
  506. static void ri(int currcons)
  507. {
  508.     if (y>top) {
  509.         y--;
  510.         pos -= video_size_row;
  511.         return;
  512.     } else
  513.         scrdown(currcons,top,bottom);
  514.     need_wrap = 0;
  515. }
  516.  
  517. static inline void cr(int currcons)
  518. {
  519.     pos -= x<<1;
  520.     need_wrap = x = 0;
  521. }
  522.  
  523. static inline void bs(int currcons)
  524. {
  525.     if (x) {
  526.         pos -= 2;
  527.         x--;
  528.         need_wrap = 0;
  529.     }
  530. }
  531.  
  532. static inline void del(int currcons)
  533. {
  534. #if 0
  535.     if (x) {
  536.         if (!need_wrap) {    /* this is not the right condition */
  537.                 pos -= 2;
  538.             x--;
  539.         }
  540.         *(unsigned short *)pos = video_erase_char;
  541.         need_wrap = 0;
  542.     }
  543. #endif
  544. }
  545.  
  546. static void csi_J(int currcons, int vpar)
  547. {
  548.     unsigned long count;
  549.     unsigned long start;
  550.  
  551.     switch (vpar) {
  552.         case 0:    /* erase from cursor to end of display */
  553.             count = (scr_end-pos)>>1;
  554.             start = pos;
  555.             break;
  556.         case 1:    /* erase from start to cursor */
  557.             count = ((pos-origin)>>1)+1;
  558.             start = origin;
  559.             break;
  560.         case 2: /* erase whole display */
  561.             count = video_num_columns * video_num_lines;
  562.             start = origin;
  563.             break;
  564.         default:
  565.             return;
  566.     }
  567.     __asm__("cld\n\t"
  568.         "rep\n\t"
  569.         "stosw\n\t"
  570.         : /* no output */
  571.         :"c" (count),
  572.         "D" (start),"a" (video_erase_char)
  573.         :"cx","di");
  574.     need_wrap = 0;
  575. }
  576.  
  577. static void csi_K(int currcons, int vpar)
  578. {
  579.     long count;
  580.     long start;
  581.  
  582.     switch (vpar) {
  583.         case 0:    /* erase from cursor to end of line */
  584.             count = video_num_columns-x;
  585.             start = pos;
  586.             break;
  587.         case 1:    /* erase from start of line to cursor */
  588.             start = pos - (x<<1);
  589.             count = x+1;
  590.             break;
  591.         case 2: /* erase whole line */
  592.             start = pos - (x<<1);
  593.             count = video_num_columns;
  594.             break;
  595.         default:
  596.             return;
  597.     }
  598.     __asm__("cld\n\t"
  599.         "rep\n\t"
  600.         "stosw\n\t"
  601.         : /* no output */
  602.         :"c" (count),
  603.         "D" (start),"a" (video_erase_char)
  604.         :"cx","di");
  605.     need_wrap = 0;
  606. }
  607.  
  608. /*
  609.  *  I hope this works. The monochrome part is untested.
  610.  */
  611. static void update_attr(int currcons)
  612. {
  613.     attr = color;
  614.     if (can_do_color) {
  615.         if (underline)
  616.             attr = (attr & 0xf0) | ulcolor;
  617.         else if (intensity == 0)
  618.             attr = (attr & 0xf0) | halfcolor;
  619.     }
  620.     if (reverse ^ decscnm)
  621.         attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
  622.     if (blink)
  623.         attr ^= 0x80;
  624.     if (intensity == 2)
  625.         attr ^= 0x08;
  626.     if (!can_do_color) {
  627.         if (underline)
  628.             attr = (attr & 0xf8) | 0x01;
  629.         else if (intensity == 0)
  630.             attr = (attr & 0xf0) | 0x08;
  631.     }
  632.     if (decscnm)
  633.         video_erase_char = (((color & 0x88) | (((color >> 4) | (color << 4)) & 0x77)) << 8) | ' ';
  634.     else
  635.         video_erase_char = (color << 8) | ' ';
  636. }
  637.  
  638. static void default_attr(int currcons)
  639. {
  640.     intensity = 1;
  641.     underline = 0;
  642.     reverse = 0;
  643.     blink = 0;
  644.     color = def_color;
  645. }
  646.  
  647. static void csi_m(int currcons)
  648. {
  649.     int i;
  650.  
  651.     for (i=0;i<=npar;i++)
  652.         switch (par[i]) {
  653.             case 0:    /* all attributes off */
  654.                 default_attr(currcons);
  655.                 break;
  656.             case 1:
  657.                 intensity = 2;
  658.                 break;
  659.             case 2:
  660.                 intensity = 0;
  661.                 break;
  662.             case 4:
  663.                 underline = 1;
  664.                 break;
  665.             case 5:
  666.                 blink = 1;
  667.                 break;
  668.             case 7:
  669.                 reverse = 1;
  670.                 break;
  671.             case 21:
  672.             case 22:
  673.                 intensity = 1;
  674.                 break;
  675.             case 24:
  676.                 underline = 0;
  677.                 break;
  678.             case 25:
  679.                 blink = 0;
  680.                 break;
  681.             case 27:
  682.                 reverse = 0;
  683.                 break;
  684.             case 39:
  685.                 color = (def_color & 0x0f) | background;
  686.                 break;
  687.             case 49:
  688.                 color = (def_color & 0xf0) | foreground;
  689.                 break;
  690.             default:
  691.                 if (par[i] >= 30 && par[i] <= 37)
  692.                     color = color_table[par[i]-30]
  693.                         | background; 
  694.                 else if (par[i] >= 40 && par[i] <= 47)
  695.                     color = (color_table[par[i]-40]<<4)
  696.                         | foreground;
  697.                 break;
  698.         }
  699.     update_attr(currcons);
  700. }
  701.  
  702. static void respond_string(char * p, int currcons, struct tty_struct * tty)
  703. {
  704.     while (*p) {
  705.         put_tty_queue(*p, &tty->read_q);
  706.         p++;
  707.     }
  708.     TTY_READ_FLUSH(tty);
  709. }
  710.  
  711. static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
  712. {
  713.     char buff[3];
  714.     int i = 0;
  715.  
  716.     do {
  717.         buff[i++] = (n%10)+'0';
  718.         n /= 10;
  719.     } while(n && i < 3);    /* We'll take no chances */
  720.     while (i--) {
  721.         put_tty_queue(buff[i], &tty->read_q);
  722.     }
  723.     /* caller must flush */
  724. }
  725.  
  726. static void cursor_report(int currcons, struct tty_struct * tty)
  727. {
  728.     put_tty_queue('\033', &tty->read_q);
  729.     put_tty_queue('[', &tty->read_q);
  730.     respond_num(y + (decom ? top+1 : 1), currcons, tty);
  731.     put_tty_queue(';', &tty->read_q);
  732.     respond_num(x+1, currcons, tty);
  733.     put_tty_queue('R', &tty->read_q);
  734.     TTY_READ_FLUSH(tty);
  735. }
  736.  
  737. static inline void status_report(int currcons, struct tty_struct * tty)
  738. {
  739.     respond_string("\033[0n", currcons, tty);    /* Terminal ok */
  740. }
  741.  
  742. static inline void respond_ID(int currcons, struct tty_struct * tty)
  743. {
  744.     respond_string(VT102ID, currcons, tty);
  745. }
  746.  
  747. static void invert_screen(int currcons) {
  748.     unsigned char *p;
  749.  
  750.     if (can_do_color)
  751.         for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
  752.             *p = (*p & 0x88) | (((*p >> 4) | (*p << 4)) & 0x77);
  753.     else
  754.         for (p = (unsigned char *)origin+1; p < (unsigned char *)scr_end; p+=2)
  755.             *p ^= *p & 0x07 == 1 ? 0x70 : 0x77;
  756. }
  757.  
  758. static void set_mode(int currcons, int on_off)
  759. {
  760.     int i;
  761.  
  762.     for (i=0; i<=npar; i++)
  763.         if (ques) switch(par[i]) {    /* DEC private modes set/reset */
  764.             case 1:            /* Cursor keys send ^[Ox/^[[x */
  765.                 if (on_off)
  766.                     set_kbd(decckm);
  767.                 else
  768.                     clr_kbd(decckm);
  769.                 break;
  770.             case 3:    /* 80/132 mode switch unimplemented */
  771.                 csi_J(currcons,2);
  772.                 gotoxy(currcons,0,0);
  773.                 break;
  774.             case 5:            /* Inverted screen on/off */
  775.                 if (decscnm != on_off) {
  776.                     decscnm = on_off;
  777.                     invert_screen(currcons);
  778.                     update_attr(currcons);
  779.                 }
  780.                 break;
  781.             case 6:            /* Origin relative/absolute */
  782.                 decom = on_off;
  783.                 gotoxy(currcons,0,0);
  784.                 break;
  785.             case 7:            /* Autowrap on/off */
  786.                 decawm = on_off;
  787.                 break;
  788.             case 8:            /* Autorepeat on/off */
  789.                 if (on_off)
  790.                     set_kbd(decarm);
  791.                 else
  792.                     clr_kbd(decarm);
  793.                 break;
  794.             case 25:        /* Cursor on/off */
  795.                 deccm = on_off;
  796.                 set_cursor(currcons);
  797.                 break;
  798.         } else switch(par[i]) {        /* ANSI modes set/reset */
  799.             case 4:            /* Insert Mode on/off */
  800.                 decim = on_off;
  801.                 break;
  802.             case 20:        /* Lf, Enter == CrLf/Lf */
  803.                 if (on_off)
  804.                     set_kbd(lnm);
  805.                 else
  806.                     clr_kbd(lnm);
  807.                 break;
  808.         }
  809. }
  810.  
  811. static void setterm_command(int currcons)
  812. {
  813.     switch(par[0]) {
  814.         case 1:    /* set color for underline mode */
  815.             if (can_do_color && par[1] < 16) {
  816.                 ulcolor = color_table[par[1]];
  817.                 if (underline)
  818.                     update_attr(currcons);
  819.             }
  820.             break;
  821.         case 2:    /* set color for half intensity mode */
  822.             if (can_do_color && par[1] < 16) {
  823.                 halfcolor = color_table[par[1]];
  824.                 if (intensity == 0)
  825.                     update_attr(currcons);
  826.             }
  827.             break;
  828.         case 8:    /* store colors as defaults */
  829.             def_color = attr;
  830.             default_attr(currcons);
  831.             update_attr(currcons);
  832.             break;
  833.         case 9:    /* set blanking interval */
  834.             blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
  835.             break;
  836.     }
  837. }
  838.  
  839. static void insert_char(int currcons)
  840. {
  841.     unsigned int i = x;
  842.     unsigned short tmp, old = video_erase_char;
  843.     unsigned short * p = (unsigned short *) pos;
  844.  
  845.     while (i++ < video_num_columns) {
  846.         tmp = *p;
  847.         *p = old;
  848.         old = tmp;
  849.         p++;
  850.     }
  851.     need_wrap = 0;
  852. }
  853.  
  854. static void insert_line(int currcons)
  855. {
  856.     scrdown(currcons,y,bottom);
  857.     need_wrap = 0;
  858. }
  859.  
  860. static void delete_char(int currcons)
  861. {
  862.     unsigned int i = x;
  863.     unsigned short * p = (unsigned short *) pos;
  864.  
  865.     while (++i < video_num_columns) {
  866.         *p = *(p+1);
  867.         p++;
  868.     }
  869.     *p = video_erase_char;
  870.     need_wrap = 0;
  871. }
  872.  
  873. static void delete_line(int currcons)
  874. {
  875.     scrup(currcons,y,bottom);
  876.     need_wrap = 0;
  877. }
  878.  
  879. static void csi_at(int currcons, unsigned int nr)
  880. {
  881.     if (nr > video_num_columns)
  882.         nr = video_num_columns;
  883.     else if (!nr)
  884.         nr = 1;
  885.     while (nr--)
  886.         insert_char(currcons);
  887. }
  888.  
  889. static void csi_L(int currcons, unsigned int nr)
  890. {
  891.     if (nr > video_num_lines)
  892.         nr = video_num_lines;
  893.     else if (!nr)
  894.         nr = 1;
  895.     while (nr--)
  896.         insert_line(currcons);
  897. }
  898.  
  899. static void csi_P(int currcons, unsigned int nr)
  900. {
  901.     if (nr > video_num_columns)
  902.         nr = video_num_columns;
  903.     else if (!nr)
  904.         nr = 1;
  905.     while (nr--)
  906.         delete_char(currcons);
  907. }
  908.  
  909. static void csi_M(int currcons, unsigned int nr)
  910. {
  911.     if (nr > video_num_lines)
  912.         nr = video_num_lines;
  913.     else if (!nr)
  914.         nr=1;
  915.     while (nr--)
  916.         delete_line(currcons);
  917. }
  918.  
  919. static void save_cur(int currcons)
  920. {
  921.     saved_x        = x;
  922.     saved_y        = y;
  923.     s_intensity    = intensity;
  924.     s_underline    = underline;
  925.     s_blink        = blink;
  926.     s_reverse    = reverse;
  927.     s_charset    = charset;
  928.     s_color        = color;
  929.     saved_G0    = G0_charset;
  930.     saved_G1    = G1_charset;
  931. }
  932.  
  933. static void restore_cur(int currcons)
  934. {
  935.     gotoxy(currcons,saved_x,saved_y);
  936.     intensity    = s_intensity;
  937.     underline    = s_underline;
  938.     blink        = s_blink;
  939.     reverse        = s_reverse;
  940.     charset        = s_charset;
  941.     color        = s_color;
  942.     G0_charset    = saved_G0;
  943.     G1_charset    = saved_G1;
  944.     translate    = charset ? G1_charset : G0_charset;
  945.     update_attr(currcons);
  946.     need_wrap = 0;
  947. }
  948.  
  949. enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
  950.     EShash, ESsetG0, ESsetG1, ESignore };
  951.  
  952. static void reset_terminal(int currcons, int do_clear)
  953. {
  954.     top        = 0;
  955.     bottom        = video_num_lines;
  956.     state        = ESnormal;
  957.     ques        = 0;
  958.     translate    = NORM_TRANS;
  959.     G0_charset    = NORM_TRANS;
  960.     G1_charset    = GRAF_TRANS;
  961.     charset        = 0;
  962.     need_wrap    = 0;
  963.  
  964.     decscnm        = 0;
  965.     decom        = 0;
  966.     decawm        = 1;
  967.     deccm        = 1;
  968.     decim        = 0;
  969.  
  970.     set_kbd(decarm);
  971.     clr_kbd(decckm);
  972.     clr_kbd(kbdapplic);
  973.     clr_kbd(lnm);
  974.     kbd_table[currcons].lockstate = 0;
  975.     kbd_table[currcons].ledstate = kbd_table[currcons].default_ledstate;
  976.     set_leds();
  977.  
  978.     default_attr(currcons);
  979.     update_attr(currcons);
  980.  
  981.     tab_stop[0]    = 0x01010100;
  982.     tab_stop[1]    =
  983.     tab_stop[2]    =
  984.     tab_stop[3]    =
  985.     tab_stop[4]    = 0x01010101;
  986.  
  987.     if (do_clear) {
  988.         gotoxy(currcons,0,0);
  989.         csi_J(currcons,2);
  990.         save_cur(currcons);
  991.     }
  992. }
  993.  
  994. void con_write(struct tty_struct * tty)
  995. {
  996.     int c;
  997.     unsigned int currcons;
  998.  
  999.     currcons = tty->line - 1;
  1000.     if (currcons >= NR_CONSOLES) {
  1001.         printk("con_write: illegal tty (%d)\n", currcons);
  1002.         return;
  1003.     }
  1004. #ifdef CONFIG_SELECTION
  1005.     /* clear the selection as soon as any characters are to be written
  1006.        out on the console holding the selection. */
  1007.     if (!EMPTY(&tty->write_q) && currcons == sel_cons)
  1008.         clear_selection();
  1009. #endif /* CONFIG_SELECTION */
  1010.     disable_bh(KEYBOARD_BH);
  1011.     while (!tty->stopped &&    (c = get_tty_queue(&tty->write_q)) >= 0) {
  1012.         if (state == ESnormal && translate[c]) {
  1013.             if (need_wrap) {
  1014.                 cr(currcons);
  1015.                 lf(currcons);
  1016.             }
  1017.             if (decim)
  1018.                 insert_char(currcons);
  1019.             c = translate[c];
  1020.             *(unsigned short *) pos = (attr << 8) + c;
  1021.             if (x == video_num_columns - 1)
  1022.                 need_wrap = decawm;
  1023.             else {
  1024.                 x++;
  1025.                 pos+=2;
  1026.             }
  1027.             continue;
  1028.         }
  1029.  
  1030.         /*
  1031.          *  Control characters can be used in the _middle_
  1032.          *  of an escape sequence.
  1033.          */
  1034.         switch (c) {
  1035.             case 7:
  1036.                 kd_mksound(0x637, HZ/8);
  1037.                 continue;
  1038.             case 8:
  1039.                 bs(currcons);
  1040.                 continue;
  1041.             case 9:
  1042.                 pos -= (x << 1);
  1043.                 while (x < video_num_columns - 1) {
  1044.                     x++;
  1045.                     if (tab_stop[x >> 5] & (1 << (x & 31)))
  1046.                         break;
  1047.                 }
  1048.                 pos += (x << 1);
  1049.                 continue;
  1050.             case 10: case 11: case 12:
  1051.                 lf(currcons);
  1052.                 if (!is_kbd(lnm))
  1053.                     continue;
  1054.             case 13:
  1055.                 cr(currcons);
  1056.                 continue;
  1057.             case 14:
  1058.                 charset = 1;
  1059.                 translate = G1_charset;
  1060.                 continue;
  1061.             case 15:
  1062.                 charset = 0;
  1063.                 translate = G0_charset;
  1064.                 continue;
  1065.             case 24: case 26:
  1066.                 state = ESnormal;
  1067.                 continue;
  1068.             case 27:
  1069.                 state = ESesc;
  1070.                 continue;
  1071.             case 127:
  1072.                 del(currcons);
  1073.                 continue;
  1074.             case 128+27:
  1075.                 state = ESsquare;
  1076.                 continue;
  1077.         }
  1078.         switch(state) {
  1079.             case ESesc:
  1080.                 state = ESnormal;
  1081.                 switch (c) {
  1082.                   case '[':
  1083.                     state = ESsquare;
  1084.                     continue;
  1085.                   case 'E':
  1086.                     cr(currcons);
  1087.                     lf(currcons);
  1088.                     continue;
  1089.                   case 'M':
  1090.                     ri(currcons);
  1091.                     continue;
  1092.                   case 'D':
  1093.                     lf(currcons);
  1094.                     continue;
  1095.                   case 'H':
  1096.                     tab_stop[x >> 5] |= (1 << (x & 31));
  1097.                     continue;
  1098.                   case 'Z':
  1099.                     respond_ID(currcons,tty);
  1100.                     continue;
  1101.                   case '7':
  1102.                     save_cur(currcons);
  1103.                     continue;
  1104.                   case '8':
  1105.                     restore_cur(currcons);
  1106.                     continue;
  1107.                   case '(':
  1108.                     state = ESsetG0;
  1109.                     continue;
  1110.                   case ')':
  1111.                     state = ESsetG1;
  1112.                     continue;
  1113.                   case '#':
  1114.                     state = EShash;
  1115.                     continue;
  1116.                   case 'c':
  1117.                     reset_terminal(currcons,1);
  1118.                     continue;
  1119.                   case '>':  /* Numeric keypad */
  1120.                     clr_kbd(kbdapplic);
  1121.                     continue;
  1122.                   case '=':  /* Appl. keypad */
  1123.                     set_kbd(kbdapplic);
  1124.                      continue;
  1125.                 }    
  1126.                 continue;
  1127.             case ESsquare:
  1128.                 for(npar = 0 ; npar < NPAR ; npar++)
  1129.                     par[npar] = 0;
  1130.                 npar = 0;
  1131.                 state = ESgetpars;
  1132.                 if (c == '[') { /* Function key */
  1133.                     state=ESfunckey;
  1134.                     continue;
  1135.                 }
  1136.                 ques = (c=='?');
  1137.                 if (ques)
  1138.                     continue;
  1139.             case ESgetpars:
  1140.                 if (c==';' && npar<NPAR-1) {
  1141.                     npar++;
  1142.                     continue;
  1143.                 } else if (c>='0' && c<='9') {
  1144.                     par[npar] *= 10;
  1145.                     par[npar] += c-'0';
  1146.                     continue;
  1147.                 } else state=ESgotpars;
  1148.             case ESgotpars:
  1149.                 state = ESnormal;
  1150.                 switch(c) {
  1151.                     case 'h':
  1152.                         set_mode(currcons,1);
  1153.                         continue;
  1154.                     case 'l':
  1155.                         set_mode(currcons,0);
  1156.                         continue;
  1157.                     case 'n':
  1158.                         if (!ques)
  1159.                             if (par[0] == 5)
  1160.                                 status_report(currcons,tty);
  1161.                             else if (par[0] == 6)
  1162.                                 cursor_report(currcons,tty);
  1163.                         continue;
  1164.                 }
  1165.                 if (ques) {
  1166.                     ques = 0;
  1167.                     continue;
  1168.                 }
  1169.                 switch(c) {
  1170.                     case 'G': case '`':
  1171.                         if (par[0]) par[0]--;
  1172.                         gotoxy(currcons,par[0],y);
  1173.                         continue;
  1174.                     case 'A':
  1175.                         if (!par[0]) par[0]++;
  1176.                         gotoxy(currcons,x,y-par[0]);
  1177.                         continue;
  1178.                     case 'B': case 'e':
  1179.                         if (!par[0]) par[0]++;
  1180.                         gotoxy(currcons,x,y+par[0]);
  1181.                         continue;
  1182.                     case 'C': case 'a':
  1183.                         if (!par[0]) par[0]++;
  1184.                         gotoxy(currcons,x+par[0],y);
  1185.                         continue;
  1186.                     case 'D':
  1187.                         if (!par[0]) par[0]++;
  1188.                         gotoxy(currcons,x-par[0],y);
  1189.                         continue;
  1190.                     case 'E':
  1191.                         if (!par[0]) par[0]++;
  1192.                         gotoxy(currcons,0,y+par[0]);
  1193.                         continue;
  1194.                     case 'F':
  1195.                         if (!par[0]) par[0]++;
  1196.                         gotoxy(currcons,0,y-par[0]);
  1197.                         continue;
  1198.                     case 'd':
  1199.                         if (par[0]) par[0]--;
  1200.                         gotoxy(currcons,x,par[0]);
  1201.                         continue;
  1202.                     case 'H': case 'f':
  1203.                         if (par[0]) par[0]--;
  1204.                         if (par[1]) par[1]--;
  1205.                         gotoxy(currcons,par[1],par[0]);
  1206.                         continue;
  1207.                     case 'J':
  1208.                         csi_J(currcons,par[0]);
  1209.                         continue;
  1210.                     case 'K':
  1211.                         csi_K(currcons,par[0]);
  1212.                         continue;
  1213.                     case 'L':
  1214.                         csi_L(currcons,par[0]);
  1215.                         continue;
  1216.                     case 'M':
  1217.                         csi_M(currcons,par[0]);
  1218.                         continue;
  1219.                     case 'P':
  1220.                         csi_P(currcons,par[0]);
  1221.                         continue;
  1222.                     case 'c':
  1223.                         if (!par[0])
  1224.                             respond_ID(currcons,tty);
  1225.                         continue;
  1226.                     case 'g':
  1227.                         if (!par[0])
  1228.                             tab_stop[x >> 5] &= ~(1 << (x & 31));
  1229.                         else if (par[0] == 3) {
  1230.                             tab_stop[0] =
  1231.                             tab_stop[1] =
  1232.                             tab_stop[2] =
  1233.                             tab_stop[3] =
  1234.                             tab_stop[4] = 0;
  1235.                         }
  1236.                         continue;
  1237.                     case 'm':
  1238.                         csi_m(currcons);
  1239.                         continue;
  1240.                     case 'r':
  1241.                         if (!par[0])
  1242.                             par[0]++;
  1243.                         if (!par[1])
  1244.                             par[1] = video_num_lines;
  1245.                         /* Minimum allowed region is 2 lines */
  1246.                         if (par[0] < par[1] &&
  1247.                             par[1] <= video_num_lines) {
  1248.                             top=par[0]-1;
  1249.                             bottom=par[1];
  1250.                             gotoxy(currcons,0,0);
  1251.                         }
  1252.                         continue;
  1253.                     case 's':
  1254.                         save_cur(currcons);
  1255.                         continue;
  1256.                     case 'u':
  1257.                         restore_cur(currcons);
  1258.                         continue;
  1259.                     case '@':
  1260.                         csi_at(currcons,par[0]);
  1261.                         continue;
  1262.                     case ']': /* setterm functions */
  1263.                         setterm_command(currcons);
  1264.                         continue;
  1265.                 }
  1266.                 continue;
  1267.             case ESfunckey:
  1268.                 state = ESnormal;
  1269.                 continue;
  1270.             case EShash:
  1271.                 state = ESnormal;
  1272.                 if (c == '8') {
  1273.                     /* DEC screen alignment test. kludge :-) */
  1274.                     video_erase_char =
  1275.                         (video_erase_char & 0xff00) | 'E';
  1276.                     csi_J(currcons, 2);
  1277.                     video_erase_char =
  1278.                         (video_erase_char & 0xff00) | ' ';
  1279.                 }
  1280.                 continue;
  1281.             case ESsetG0:
  1282.                 if (c == '0')
  1283.                     G0_charset = GRAF_TRANS;
  1284.                 else if (c == 'B')
  1285.                     G0_charset = NORM_TRANS;
  1286.                 else if (c == 'U')
  1287.                     G0_charset = NULL_TRANS;
  1288.                 else if (c == 'K')
  1289.                     G0_charset = USER_TRANS;
  1290.                 if (charset == 0)
  1291.                     translate = G0_charset;
  1292.                 state = ESnormal;
  1293.                 continue;
  1294.             case ESsetG1:
  1295.                 if (c == '0')
  1296.                     G1_charset = GRAF_TRANS;
  1297.                 else if (c == 'B')
  1298.                     G1_charset = NORM_TRANS;
  1299.                 else if (c == 'U')
  1300.                     G1_charset = NULL_TRANS;
  1301.                 else if (c == 'K')
  1302.                     G1_charset = USER_TRANS;
  1303.                 if (charset == 1)
  1304.                     translate = G1_charset;
  1305.                 state = ESnormal;
  1306.                 continue;
  1307.             default:
  1308.                 state = ESnormal;
  1309.         }
  1310.     }
  1311.     if (vcmode != KD_GRAPHICS)
  1312.         set_cursor(currcons);
  1313.     enable_bh(KEYBOARD_BH);
  1314.     if (LEFT(&tty->write_q) > WAKEUP_CHARS)
  1315.         wake_up_interruptible(&tty->write_q.proc_list);
  1316. }
  1317.  
  1318. void do_keyboard_interrupt(void)
  1319. {
  1320.     TTY_READ_FLUSH(TTY_TABLE(0));
  1321.     timer_active &= ~(1<<BLANK_TIMER);
  1322.     if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
  1323.         return;
  1324.     if (console_blanked) {
  1325.         timer_table[BLANK_TIMER].expires = 0;
  1326.         timer_active |= 1<<BLANK_TIMER;
  1327.     } else if (blankinterval) {
  1328.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  1329.         timer_active |= 1<<BLANK_TIMER;
  1330.     }
  1331. }
  1332.  
  1333. void * memsetw(void * s,unsigned short c,int count)
  1334. {
  1335. __asm__("cld\n\t"
  1336.     "rep\n\t"
  1337.     "stosw"
  1338.     : /* no output */
  1339.     :"a" (c),"D" (s),"c" (count)
  1340.     :"cx","di");
  1341. return s;
  1342. }
  1343.  
  1344. void console_print(const char * b)
  1345. {
  1346.     int currcons = fg_console;
  1347.     unsigned char c;
  1348.  
  1349.     if (!printable || currcons<0 || currcons>=NR_CONSOLES)
  1350.         return;
  1351.     while ((c = *(b++)) != 0) {
  1352.         if (c == 10 || c == 13 || need_wrap) {
  1353.             if (c != 13)
  1354.                 lf(currcons);
  1355.             cr(currcons);
  1356.             if (c == 10 || c == 13)
  1357.                 continue;
  1358.         }
  1359.         *(unsigned short *) pos = (attr << 8) + c;
  1360.         if (x == video_num_columns - 1) {
  1361.             need_wrap = 1;
  1362.             continue;
  1363.         }
  1364.         x++;
  1365.         pos+=2;
  1366.     }
  1367.     set_cursor(currcons);
  1368.     if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
  1369.         return;
  1370.     timer_active &= ~(1<<BLANK_TIMER);
  1371.     if (console_blanked) {
  1372.         timer_table[BLANK_TIMER].expires = 0;
  1373.         timer_active |= 1<<BLANK_TIMER;
  1374.     } else if (blankinterval) {
  1375.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  1376.         timer_active |= 1<<BLANK_TIMER;
  1377.     }
  1378. }
  1379.  
  1380. /*
  1381.  *  long con_init(long);
  1382.  *
  1383.  * This routine initalizes console interrupts, and does nothing
  1384.  * else. If you want the screen to clear, call tty_write with
  1385.  * the appropriate escape-sequece.
  1386.  *
  1387.  * Reads the information preserved by setup.s to determine the current display
  1388.  * type and sets everything accordingly.
  1389.  */
  1390. long con_init(long kmem_start)
  1391. {
  1392.     char *display_desc = "????";
  1393.     int currcons = 0;
  1394.     long base;
  1395.     int orig_x = ORIG_X;
  1396.     int orig_y = ORIG_Y;
  1397.  
  1398.     vc_scrmembuf = (unsigned short *) kmem_start;
  1399.     video_num_columns = ORIG_VIDEO_COLS;
  1400.     video_size_row = video_num_columns * 2;
  1401.     video_num_lines = ORIG_VIDEO_LINES;
  1402.     video_page = ORIG_VIDEO_PAGE;
  1403.     screen_size = (video_num_lines * video_size_row);
  1404.     kmem_start += NR_CONSOLES * screen_size;
  1405.     timer_table[BLANK_TIMER].fn = blank_screen;
  1406.     timer_table[BLANK_TIMER].expires = 0;
  1407.     if (blankinterval) {
  1408.         timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
  1409.         timer_active |= 1<<BLANK_TIMER;
  1410.     }
  1411.     
  1412.     if (ORIG_VIDEO_MODE == 7)    /* Is this a monochrome display? */
  1413.     {
  1414.         video_mem_base = 0xb0000;
  1415.         video_port_reg = 0x3b4;
  1416.         video_port_val = 0x3b5;
  1417.         if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
  1418.         {
  1419.             video_type = VIDEO_TYPE_EGAM;
  1420.             video_mem_term = 0xb8000;
  1421.             display_desc = "EGA+";
  1422.         }
  1423.         else
  1424.         {
  1425.             video_type = VIDEO_TYPE_MDA;
  1426.             video_mem_term = 0xb2000;
  1427.             display_desc = "*MDA";
  1428.         }
  1429.     }
  1430.     else                /* If not, it is color. */
  1431.     {
  1432.         can_do_color = 1;
  1433.         video_mem_base = 0xb8000;
  1434.         video_port_reg    = 0x3d4;
  1435.         video_port_val    = 0x3d5;
  1436.         if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
  1437.         {
  1438.             video_type = VIDEO_TYPE_EGAC;
  1439.             video_mem_term = 0xc0000;
  1440.             display_desc = "EGA+";
  1441.         }
  1442.         else
  1443.         {
  1444.             video_type = VIDEO_TYPE_CGA;
  1445.             video_mem_term = 0xba000;
  1446.             display_desc = "*CGA";
  1447.         }
  1448.     }
  1449.     
  1450.     /* Initialize the variables used for scrolling (mostly EGA/VGA)    */
  1451.  
  1452.     base = (long)vc_scrmembuf;
  1453.     for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
  1454.         pos = origin = video_mem_start = base;
  1455.         scr_end = video_mem_end = (base += screen_size);
  1456.         vc_scrbuf[currcons] = (unsigned short *) origin;
  1457.         vcmode        = KD_TEXT;
  1458.         vtmode.mode    = VT_AUTO;
  1459.         vtmode.waitv    = 0;
  1460.         vtmode.relsig    = 0;
  1461.         vtmode.acqsig    = 0;
  1462.         vtmode.frsig    = 0;
  1463.         vtpid        = -1;
  1464.         vtnewvt        = -1;
  1465.         clr_kbd(kbdraw);
  1466.         def_color    = 0x07;   /* white */
  1467.         ulcolor        = 0x0f;   /* bold white */
  1468.         halfcolor    = 0x08;   /* grey */
  1469.         reset_terminal(currcons, currcons);
  1470.     }
  1471.     currcons = fg_console = 0;
  1472.  
  1473.     video_mem_start = video_mem_base;
  1474.     video_mem_end = video_mem_term;
  1475.     origin = video_mem_start;
  1476.     scr_end    = video_mem_start + video_num_lines * video_size_row;
  1477.     gotoxy(currcons,0,0);
  1478.     save_cur(currcons);
  1479.     gotoxy(currcons,orig_x,orig_y);
  1480.     update_screen(fg_console);
  1481.     printable = 1;
  1482.     printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
  1483.         can_do_color?"colour":"mono",
  1484.         display_desc,
  1485.         video_num_columns,video_num_lines,
  1486.         NR_CONSOLES);
  1487.     register_console(console_print);
  1488.     return kmem_start;
  1489. }
  1490.  
  1491. /*
  1492.  * kbdsave doesn't need to do anything: it's all handled automatically
  1493.  * with the new data structures..
  1494.  */
  1495. void kbdsave(int new_console)
  1496. {
  1497. }
  1498.  
  1499. static void get_scrmem(int currcons)
  1500. {
  1501.     memcpy((void *)vc_scrbuf[currcons],(void *)origin, screen_size);
  1502.     video_mem_start = (unsigned long)vc_scrbuf[currcons];
  1503.     origin     = video_mem_start;
  1504.     scr_end = video_mem_end = video_mem_start+screen_size;
  1505.     pos = origin + y*video_size_row + (x<<1);
  1506. }
  1507.  
  1508. static void set_scrmem(int currcons)
  1509. {
  1510. #ifdef CONFIG_HGA
  1511.   /* This works with XFree86 1.2, 1.3 and 2.0
  1512.      This code could be extended and made more generally useful if we could
  1513.      determine the actual video mode. It appears that this should be
  1514.      possible on a genuine Hercules card, but I (WM) haven't been able to
  1515.      read from any of the required registers on my clone card.
  1516.      */
  1517.     /* This code should work with Hercules and MDA cards. */
  1518.     if (video_type == VIDEO_TYPE_MDA)
  1519.       {
  1520.         if (vcmode == KD_TEXT)
  1521.           {
  1522.         /* Ensure that the card is in text mode. */
  1523.         int    i;
  1524.         static char herc_txt_tbl[12] = {
  1525.           0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
  1526.         outb_p(0, 0x3bf);  /* Back to power-on defaults */
  1527.         outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
  1528.         for ( i = 0 ; i < 12 ; i++ )
  1529.           {
  1530.             outb_p(i, 0x3b4);
  1531.             outb_p(herc_txt_tbl[i], 0x3b5);
  1532.           }
  1533.           }
  1534. #define HGA_BLINKER_ON 0x20
  1535. #define HGA_SCREEN_ON  8
  1536.         /* Make sure that the hardware is not blanked */
  1537.         outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
  1538.       }
  1539. #endif CONFIG_HGA
  1540.  
  1541.     video_mem_start = video_mem_base;
  1542.     video_mem_end = video_mem_term;
  1543.     origin    = video_mem_start;
  1544.     scr_end    = video_mem_start + screen_size;
  1545.     pos = origin + y*video_size_row + (x<<1);
  1546.     memcpy((void *)video_mem_base, (void *)vc_scrbuf[fg_console], screen_size);
  1547. }
  1548.  
  1549. void blank_screen(void)
  1550. {
  1551.     if (console_blanked)
  1552.         return;
  1553.     timer_table[BLANK_TIMER].fn = unblank_screen;
  1554.     get_scrmem(fg_console);
  1555.     hide_cursor();
  1556.     console_blanked = 1;
  1557.     memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
  1558. }
  1559.  
  1560. void unblank_screen(void)
  1561. {
  1562.     if (!console_blanked)
  1563.         return;
  1564.     timer_table[BLANK_TIMER].fn = blank_screen;
  1565.     if (blankinterval) {
  1566.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  1567.         timer_active |= 1<<BLANK_TIMER;
  1568.     }
  1569.     console_blanked = 0;
  1570.     set_scrmem(fg_console);
  1571.     set_origin(fg_console);
  1572.     set_cursor(fg_console);
  1573. }
  1574.  
  1575. void update_screen(int new_console)
  1576. {
  1577.     static int lock = 0;
  1578.  
  1579.     if (new_console == fg_console || lock)
  1580.         return;
  1581.     lock = 1;
  1582.     kbdsave(new_console);
  1583.     get_scrmem(fg_console); 
  1584.     fg_console = new_console;
  1585.     set_scrmem(fg_console); 
  1586.     set_origin(fg_console);
  1587.     set_cursor(new_console);
  1588.     set_leds();
  1589.     compute_shiftstate();
  1590.     lock = 0;
  1591. }
  1592.  
  1593. int do_screendump(int arg)
  1594. {
  1595.     char *sptr, *buf = (char *)arg;
  1596.     int currcons, l;
  1597.  
  1598.     if (!suser())
  1599.         return -EPERM;
  1600.     l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
  1601.     if (l)
  1602.         return l;
  1603.     currcons = get_fs_byte(buf+1);
  1604.     if ((currcons<0) || (currcons>NR_CONSOLES))
  1605.         return -EIO;
  1606.     put_fs_byte((char)(video_num_lines),buf++);    
  1607.     put_fs_byte((char)(video_num_columns),buf++);
  1608.     currcons = (currcons ? currcons-1 : fg_console);
  1609.     sptr = (char *) origin;
  1610.     for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
  1611.         put_fs_byte(*sptr++,buf++);    
  1612.     return(0);
  1613. }
  1614.  
  1615. /*
  1616.  * All we do is set the write and ioctl subroutines; later on maybe we'll
  1617.  * dynamically allocate the console screen memory.
  1618.  */
  1619. int con_open(struct tty_struct *tty, struct file * filp)
  1620. {
  1621.     tty->write = con_write;
  1622.     tty->ioctl = vt_ioctl;
  1623.     if (tty->line > NR_CONSOLES)
  1624.         return -ENODEV;
  1625.     return 0;
  1626. }
  1627.  
  1628. #ifdef CONFIG_SELECTION
  1629. /* correction factor for when screen is hardware-scrolled */
  1630. #define    hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
  1631.  
  1632. /* set reverse video on characters s-e of console with selection. */
  1633. static void highlight(const int currcons, const int s, const int e)
  1634. {
  1635.     unsigned char *p, *p1, *p2;
  1636.  
  1637.     p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
  1638.     p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
  1639.     if (p1 > p2)
  1640.     {
  1641.         p = p1;
  1642.         p1 = p2;
  1643.         p2 = p;
  1644.     }
  1645.     for (p = p1; p <= p2; p += 2)
  1646.         *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
  1647. }
  1648.  
  1649. /* is c in range [a-zA-Z0-9_]? */
  1650. static inline int inword(const char c) { return (isalnum(c) || c == '_'); }
  1651.  
  1652. /* does screen address p correspond to character at LH/RH edge of screen? */
  1653. static inline int atedge(const int p)
  1654. {
  1655.     return (!(p % video_size_row) || !((p + 2) % video_size_row));
  1656. }
  1657.  
  1658. /* constrain v such that l <= v <= u */
  1659. static inline short limit(const int v, const int l, const int u)
  1660. {
  1661.     return (v < l) ? l : ((v > u) ? u : v);
  1662. }
  1663.  
  1664. /* set the current selection. Invoked by ioctl(). */
  1665. int set_selection(const int arg)
  1666. {
  1667.     unsigned short *args, xs, ys, xe, ye;
  1668.     int currcons = fg_console;
  1669.     int sel_mode, new_sel_start, new_sel_end, spc;
  1670.     char *bp, *obp, *spos;
  1671.     int i, ps, pe;
  1672.     char *off = (char *)origin - hwscroll_offset;
  1673.  
  1674.     unblank_screen();
  1675.     args = (unsigned short *)(arg + 1);
  1676.     xs = get_fs_word(args++) - 1;
  1677.     ys = get_fs_word(args++) - 1;
  1678.     xe = get_fs_word(args++) - 1;
  1679.     ye = get_fs_word(args++) - 1;
  1680.     sel_mode = get_fs_word(args);
  1681.  
  1682.     xs = limit(xs, 0, video_num_columns - 1);
  1683.     ys = limit(ys, 0, video_num_lines - 1);
  1684.     xe = limit(xe, 0, video_num_columns - 1);
  1685.     ye = limit(ye, 0, video_num_lines - 1);
  1686.     ps = ys * video_size_row + (xs << 1);
  1687.     pe = ye * video_size_row + (xe << 1);
  1688.  
  1689.     if (ps > pe)    /* make sel_start <= sel_end */
  1690.     {
  1691.         int tmp = ps;
  1692.         ps = pe;
  1693.         pe = tmp;
  1694.     }
  1695.  
  1696.     switch (sel_mode)
  1697.     {
  1698.         case 0:    /* character-by-character selection */
  1699.         default:
  1700.             new_sel_start = ps;
  1701.             new_sel_end = pe;
  1702.             break;
  1703.         case 1:    /* word-by-word selection */
  1704.             spc = isspace(*(off + ps));
  1705.             for (new_sel_start = ps; ; ps -= 2)
  1706.             {
  1707.                 if ((spc && !isspace(*(off + ps))) ||
  1708.                     (!spc && !inword(*(off + ps))))
  1709.                     break;
  1710.                 new_sel_start = ps;
  1711.                 if (!(ps % video_size_row))
  1712.                     break;
  1713.             }
  1714.             spc = isspace(*(off + pe));
  1715.             for (new_sel_end = pe; ; pe += 2)
  1716.             {
  1717.                 if ((spc && !isspace(*(off + pe))) ||
  1718.                     (!spc && !inword(*(off + pe))))
  1719.                     break;
  1720.                 new_sel_end = pe;
  1721.                 if (!((pe + 2) % video_size_row))
  1722.                     break;
  1723.             }
  1724.             break;
  1725.         case 2:    /* line-by-line selection */
  1726.             new_sel_start = ps - ps % video_size_row;
  1727.             new_sel_end = pe + video_size_row
  1728.                     - pe % video_size_row - 2;
  1729.             break;
  1730.     }
  1731.     /* select to end of line if on trailing space */
  1732.     if (new_sel_end > new_sel_start &&
  1733.         !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
  1734.     {
  1735.         for (pe = new_sel_end + 2; ; pe += 2)
  1736.         {
  1737.             if (!isspace(*(off + pe)) || atedge(pe))
  1738.                 break;
  1739.         }
  1740.         if (isspace(*(off + pe)))
  1741.             new_sel_end = pe;
  1742.     }
  1743.     if (sel_cons != currcons)
  1744.     {
  1745.         clear_selection();
  1746.         sel_cons = currcons;
  1747.     }
  1748.     if (sel_start == -1)    /* no current selection */
  1749.         highlight(sel_cons, new_sel_start, new_sel_end);
  1750.     else if (new_sel_start == sel_start)
  1751.     {
  1752.         if (new_sel_end == sel_end)    /* no action required */
  1753.             return 0;
  1754.         else if (new_sel_end > sel_end)    /* extend to right */
  1755.             highlight(sel_cons, sel_end + 2, new_sel_end);
  1756.         else                /* contract from right */
  1757.             highlight(sel_cons, new_sel_end + 2, sel_end);
  1758.     }
  1759.     else if (new_sel_end == sel_end)
  1760.     {
  1761.         if (new_sel_start < sel_start)    /* extend to left */
  1762.             highlight(sel_cons, new_sel_start, sel_start - 2);
  1763.         else                /* contract from left */
  1764.             highlight(sel_cons, sel_start, new_sel_start - 2);
  1765.     }
  1766.     else    /* some other case; start selection from scratch */
  1767.     {
  1768.         clear_selection();
  1769.         highlight(sel_cons, new_sel_start, new_sel_end);
  1770.     }
  1771.     sel_start = new_sel_start;
  1772.     sel_end = new_sel_end;
  1773.     obp = bp = sel_buffer;
  1774.     for (i = sel_start; i <= sel_end; i += 2)
  1775.     {
  1776.         spos = (char *)off + i;
  1777.         *bp++ = *spos;
  1778.         if (!isspace(*spos))
  1779.             obp = bp;
  1780.         if (! ((i + 2) % video_size_row))
  1781.         {
  1782.             /* strip trailing blanks from line and add newline,
  1783.                unless non-space at end of line. */
  1784.             if (obp != bp)
  1785.             {
  1786.                 bp = obp;
  1787.                 *bp++ = '\r';
  1788.             }
  1789.             obp = bp;
  1790.         }
  1791.         /* check for space, leaving room for next character, possible
  1792.            newline, and null at end. */
  1793.         if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
  1794.             break;
  1795.     }
  1796.     *bp = '\0';
  1797.     return 0;
  1798. }
  1799.  
  1800. /* insert the contents of the selection buffer into the queue of the
  1801.    tty associated with the current console. Invoked by ioctl(). */
  1802. int paste_selection(struct tty_struct *tty)
  1803. {
  1804.     char *bp = sel_buffer;
  1805.  
  1806.     if (! *bp)
  1807.         return 0;
  1808.     unblank_screen();
  1809.     while (*bp) {
  1810.         put_tty_queue(*bp, &tty->read_q);
  1811.         bp++;
  1812.         TTY_READ_FLUSH(tty);
  1813.     }
  1814.     return 0;
  1815. }
  1816.  
  1817. /* remove the current selection highlight, if any, from the console holding
  1818.    the selection. */
  1819. static void clear_selection()
  1820. {
  1821.     if (sel_start != -1)
  1822.     {
  1823.         highlight(sel_cons, sel_start, sel_end);
  1824.         sel_start = -1;
  1825.     }
  1826. }
  1827. #endif /* CONFIG_SELECTION */
  1828.  
  1829. /*
  1830.  * PIO_FONT support.
  1831.  *
  1832.  * The font loading code goes back to the codepage package by
  1833.  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
  1834.  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
  1835.  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
  1836.  *
  1837.  * Change for certain monochrome monitors by Yury Shevchuck
  1838.  * (sizif@botik.yaroslavl.su).
  1839.  */
  1840.  
  1841. #define colourmap ((char *)0xa0000)
  1842. #define blackwmap ((char *)0xb0000)
  1843. #define cmapsz 8192
  1844. #define seq_port_reg (0x3c4)
  1845. #define seq_port_val (0x3c5)
  1846. #define gr_port_reg (0x3ce)
  1847. #define gr_port_val (0x3cf)
  1848.  
  1849. static int set_get_font(char * arg, int set)
  1850. {
  1851. #ifdef CAN_LOAD_EGA_FONTS
  1852.     int i;
  1853.     char *charmap;
  1854.     int beg;
  1855.  
  1856.     /* no use to "load" CGA... */
  1857.  
  1858.     if (video_type == VIDEO_TYPE_EGAC) {
  1859.         charmap = colourmap;
  1860.         beg = 0x0e;
  1861.     } else if (video_type == VIDEO_TYPE_EGAM) {
  1862.         charmap = blackwmap;
  1863.         beg = 0x0a;
  1864.     } else
  1865.         return -EINVAL;
  1866.  
  1867.     i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
  1868.     if (i)
  1869.             return i;
  1870.  
  1871.     cli();
  1872.     outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
  1873.     outb_p( 0x01, seq_port_val );   /* Synchronous reset */
  1874.     outb_p( 0x02, seq_port_reg );
  1875.     outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
  1876.     outb_p( 0x04, seq_port_reg );
  1877.     outb_p( 0x07, seq_port_val );   /* Sequential addressing */
  1878.     outb_p( 0x00, seq_port_reg );
  1879.     outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
  1880.  
  1881.     outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
  1882.     outb_p( 0x02, gr_port_val );    /* select map 2 */
  1883.     outb_p( 0x05, gr_port_reg );
  1884.     outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
  1885.     outb_p( 0x06, gr_port_reg );
  1886.     outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
  1887.     sti();
  1888.  
  1889.     if (set)
  1890.         for (i=0; i<cmapsz ; i++)
  1891.             *(charmap+i) = get_fs_byte(arg+i);
  1892.     else
  1893.         for (i=0; i<cmapsz ; i++)
  1894.             put_fs_byte(*(charmap+i), arg+i);
  1895.  
  1896.     cli();
  1897.     outb_p( 0x00, seq_port_reg );   /* Frist, the sequencer */
  1898.     outb_p( 0x01, seq_port_val );   /* Synchronous reset */
  1899.     outb_p( 0x02, seq_port_reg );
  1900.     outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
  1901.     outb_p( 0x04, seq_port_reg );
  1902.     outb_p( 0x03, seq_port_val );   /* odd-even addressing */
  1903.     outb_p( 0x00, seq_port_reg );
  1904.     outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
  1905.  
  1906.     outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
  1907.     outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
  1908.     outb_p( 0x05, gr_port_reg );
  1909.     outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
  1910.     outb_p( 0x06, gr_port_reg );
  1911.     outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
  1912.     sti();
  1913.  
  1914.     return 0;
  1915. #else
  1916.     return -EINVAL;
  1917. #endif
  1918. }
  1919.  
  1920. /*
  1921.  * Load font into the EGA/VGA character generator. arg points to a 8192
  1922.  * byte map, 32 bytes per character. Only first H of them are used for
  1923.  * 8xH fonts (0 < H <= 32).
  1924.  */
  1925.  
  1926. int con_set_font (char *arg)
  1927. {
  1928.     return set_get_font (arg,1);
  1929. }
  1930.  
  1931. int con_get_font (char *arg)
  1932. {
  1933.     return set_get_font (arg,0);
  1934. }
  1935.  
  1936. /*
  1937.  * Load customizable translation table (USER_TRANS[]). All checks are here,
  1938.  * so we need only include 'return con_set_trans(arg)' in the ioctl handler
  1939.  * arg points to a 256 byte translation table.
  1940.  */
  1941. int con_set_trans(char * arg)
  1942. {
  1943.     int i;
  1944.  
  1945.     i = verify_area(VERIFY_READ, (void *)arg, E_TABSZ);
  1946.     if (i)
  1947.             return i;
  1948.  
  1949.     for (i=0; i<E_TABSZ ; i++) USER_TRANS[i] = get_fs_byte(arg+i);
  1950.     USER_TRANS[012]=0;
  1951.     USER_TRANS[014]=0;
  1952.     USER_TRANS[015]=0;
  1953.     USER_TRANS[033]=0;
  1954.     return 0;
  1955. }
  1956.  
  1957. int con_get_trans(char * arg)
  1958. {
  1959.     int i;
  1960.  
  1961.     i = verify_area(VERIFY_WRITE, (void *)arg, E_TABSZ);
  1962.     if (i)
  1963.             return i;
  1964.  
  1965.     for (i=0; i<E_TABSZ ; i++) put_fs_byte(USER_TRANS[i],arg+i);
  1966.     return 0;
  1967. }
  1968.