home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.2 / LINUX-1.2 / LINUX-1 / linux / drivers / char / console.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-06  |  56.0 KB  |  2,285 lines

  1. /*
  2.  *  linux/drivers/char/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.  *     'void do_keyboard_interrupt(void)'
  13.  *
  14.  *     'int vc_allocate(unsigned int console)' 
  15.  *     'int vc_cons_allocated(unsigned int console)'
  16.  *     'int vc_resize(unsigned long lines, unsigned long cols)'
  17.  *     'void vc_disallocate(unsigned int currcons)'
  18.  *
  19.  *     'long con_init(long)'
  20.  *     'int con_open(struct tty_struct *tty, struct file * filp)'
  21.  *     'void con_write(struct tty_struct * tty)'
  22.  *     'void console_print(const char * b)'
  23.  *     'void update_screen(int new_console)'
  24.  *
  25.  *     'void do_blank_screen(int)'
  26.  *     'void do_unblank_screen(void)'
  27.  *     'void poke_blanked_console(void)'
  28.  *
  29.  *     'unsigned short *screen_pos(int currcons, int w_offset, int viewed)'
  30.  *     'void complement_pos(int currcons, int offset)'
  31.  *     'void invert_screen(int currcons, int offset, int count, int shift)'
  32.  *
  33.  *     'void scrollback(int lines)'
  34.  *     'void scrollfront(int lines)'
  35.  *
  36.  *     'int con_get_font(char *)' 
  37.  *     'int con_set_font(char *)'
  38.  *
  39.  *     'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)'
  40.  *     'int mouse_reporting(void)'
  41.  *
  42.  * Hopefully this will be a rather complete VT102 implementation.
  43.  *
  44.  * Beeping thanks to John T Kohl.
  45.  * 
  46.  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  47.  *   Chars, and VT100 enhancements by Peter MacDonald.
  48.  *
  49.  * Copy and paste function by Andrew Haylett,
  50.  *   some enhancements by Alessandro Rubini.
  51.  *
  52.  * User definable mapping table and font loading by Eugene G. Crosser,
  53.  * <crosser@pccross.msk.su>
  54.  *
  55.  * Code to check for different video-cards mostly by Galen Hunt,
  56.  * <g-hunt@ee.utah.edu>
  57.  *
  58.  * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
  59.  * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
  60.  *
  61.  * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
  62.  * Resizing of consoles, aeb, 940926
  63.  *
  64.  * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
  65.  * <poe@daimi.aau.dk>
  66.  *
  67.  */
  68.  
  69. #define BLANK 0x0020
  70. #define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
  71.  
  72. /* A bitmap for codes <32. A bit of 1 indicates that the code
  73.  * corresponding to that bit number invokes some special action
  74.  * (such as cursor movement) and should not be displayed as a
  75.  * glyph unless the disp_ctrl mode is explicitly enabled.
  76.  */
  77. #define CTRL_ACTION 0xd00ff80
  78.  
  79. /*
  80.  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  81.  * (to put a word in video IO), but this will work even for keyboard
  82.  * interrupts. We know interrupts aren't enabled when getting a keyboard
  83.  * interrupt, as we use trap-gates. Hopefully all is well.
  84.  */
  85.  
  86. #include <linux/sched.h>
  87. #include <linux/timer.h>
  88. #include <linux/interrupt.h>
  89. #include <linux/tty.h>
  90. #include <linux/tty_flip.h>
  91. #include <linux/config.h>
  92. #include <linux/kernel.h>
  93. #include <linux/string.h>
  94. #include <linux/errno.h>
  95. #include <linux/kd.h>
  96. #include <linux/malloc.h>
  97. #include <linux/major.h>
  98. #include <linux/mm.h>
  99. #include <linux/ioport.h>
  100.  
  101. #include <asm/io.h>
  102. #include <asm/system.h>
  103. #include <asm/segment.h>
  104. #include <asm/bitops.h>
  105.  
  106. #include "kbd_kern.h"
  107. #include "vt_kern.h"
  108. #include "consolemap.h"
  109. #include "selection.h"
  110.  
  111.  
  112. #ifndef MIN
  113. #define MIN(a,b)    ((a) < (b) ? (a) : (b))
  114. #endif
  115.  
  116. struct tty_driver console_driver;
  117. static int console_refcount;
  118. static struct tty_struct *console_table[MAX_NR_CONSOLES];
  119. static struct termios *console_termios[MAX_NR_CONSOLES];
  120. static struct termios *console_termios_locked[MAX_NR_CONSOLES];
  121.  
  122. #define NPAR 16
  123.  
  124. static void con_setsize(unsigned long rows, unsigned long cols);
  125. static void vc_init(unsigned int console, unsigned long rows, unsigned long cols,
  126.             int do_clear);
  127. static void get_scrmem(int currcons);
  128. static void set_scrmem(int currcons, long offset);
  129. static void set_origin(int currcons);
  130. static void blank_screen(void);
  131. static void unblank_screen(void);
  132. void poke_blanked_console(void);
  133. static void gotoxy(int currcons, int new_x, int new_y);
  134. static void save_cur(int currcons);
  135. static inline void set_cursor(int currcons);
  136. static void reset_terminal(int currcons, int do_clear);
  137. extern void reset_vc(unsigned int new_console);
  138. extern void vt_init(void);
  139. extern void register_console(void (*proc)(const char *));
  140. extern void vesa_blank(void);
  141. extern void vesa_unblank(void);
  142. extern void compute_shiftstate(void);
  143. extern int conv_uni_to_pc(unsigned long ucs);
  144.  
  145. /* Description of the hardware situation */
  146. static unsigned char    video_type;        /* Type of display being used    */
  147. static unsigned long    video_mem_base;        /* Base of video memory        */
  148. static unsigned long    video_mem_term;        /* End of video memory        */
  149. static unsigned char    video_page;        /* Initial video page (unused)  */
  150.        /* these two also used in vesa_blank.c */
  151.        unsigned short    video_port_reg;        /* Video register select port    */
  152.        unsigned short    video_port_val;        /* Video register value port    */
  153.        /* these three also used in selection.c */
  154.        unsigned long    video_num_columns;    /* Number of text columns    */
  155.        unsigned long    video_num_lines;    /* Number of text lines        */
  156.        unsigned long    video_size_row;
  157. static unsigned long    video_screen_size;
  158. static int can_do_color = 0;
  159. static int printable = 0;            /* Is console ready for printing? */
  160.  
  161. static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
  162.  
  163. static int console_blanked = 0;
  164. static int blankinterval = 10*60*HZ;
  165. static long blank_origin, blank__origin, unblank_origin;
  166.  
  167. struct vc_data {
  168.     unsigned long    vc_screenbuf_size;
  169.     unsigned short    vc_video_erase_char;    /* Background erase character */
  170.     unsigned char    vc_attr;        /* Current attributes */
  171.     unsigned char    vc_def_color;        /* Default colors */
  172.     unsigned char    vc_color;        /* Foreground & background */
  173.     unsigned char    vc_s_color;        /* Saved foreground & background */
  174.     unsigned char    vc_ulcolor;        /* Colour for underline mode */
  175.     unsigned char    vc_halfcolor;        /* Colour for half intensity mode */
  176.     unsigned long    vc_origin;        /* Used for EGA/VGA fast scroll    */
  177.     unsigned long    vc_scr_end;        /* Used for EGA/VGA fast scroll    */
  178.     unsigned long    vc_pos;
  179.     unsigned long    vc_x,vc_y;
  180.     unsigned long    vc_top,vc_bottom;
  181.     unsigned long    vc_state;
  182.     unsigned long    vc_npar,vc_par[NPAR];
  183.     unsigned long    vc_video_mem_start;    /* Start of video RAM        */
  184.     unsigned long    vc_video_mem_end;    /* End of video RAM (sort of)    */
  185.     unsigned long    vc_saved_x;
  186.     unsigned long    vc_saved_y;
  187.     /* mode flags */
  188.     unsigned long    vc_charset    : 1;    /* Character set G0 / G1 */
  189.     unsigned long    vc_s_charset    : 1;    /* Saved character set */
  190.     unsigned long    vc_disp_ctrl    : 1;    /* Display chars < 32? */
  191.     unsigned long    vc_toggle_meta    : 1;    /* Toggle high bit? */
  192.     unsigned long    vc_decscnm    : 1;    /* Screen Mode */
  193.     unsigned long    vc_decom    : 1;    /* Origin Mode */
  194.     unsigned long    vc_decawm    : 1;    /* Autowrap Mode */
  195.     unsigned long    vc_deccm    : 1;    /* Cursor Visible */
  196.     unsigned long    vc_decim    : 1;    /* Insert Mode */
  197.     unsigned long    vc_deccolm    : 1;    /* 80/132 Column Mode */
  198.     /* attribute flags */
  199.     unsigned long    vc_intensity    : 2;    /* 0=half-bright, 1=normal, 2=bold */
  200.     unsigned long    vc_underline    : 1;
  201.     unsigned long    vc_blink    : 1;
  202.     unsigned long    vc_reverse    : 1;
  203.     unsigned long    vc_s_intensity    : 2;    /* saved rendition */
  204.     unsigned long    vc_s_underline    : 1;
  205.     unsigned long    vc_s_blink    : 1;
  206.     unsigned long    vc_s_reverse    : 1;
  207.     /* misc */
  208.     unsigned long    vc_ques        : 1;
  209.     unsigned long    vc_need_wrap    : 1;
  210.     unsigned long    vc_has_scrolled : 1;    /* Info for unblank_screen */
  211.     unsigned long    vc_kmalloced    : 1;    /* kfree_s() needed */
  212.     unsigned long    vc_report_mouse : 2;
  213.     unsigned char    vc_utf        : 1;    /* Unicode UTF-8 encoding */
  214.     unsigned char    vc_utf_count;
  215.     unsigned long    vc_utf_char;
  216.     unsigned long    vc_tab_stop[5];        /* Tab stops. 160 columns. */
  217.     unsigned char * vc_translate;
  218.     unsigned char     vc_G0_charset;
  219.     unsigned char     vc_G1_charset;
  220.     unsigned char     vc_saved_G0;
  221.     unsigned char     vc_saved_G1;
  222.     /* additional information is in vt_kern.h */
  223. };
  224.  
  225. static struct vc {
  226.     struct vc_data *d;
  227.  
  228.     /* might add  scrmem, vt_struct, kbd  at some time,
  229.        to have everything in one place - the disadvantage
  230.        would be that vc_cons etc can no longer be static */
  231. } vc_cons [MAX_NR_CONSOLES];
  232.  
  233. #define screenbuf_size    (vc_cons[currcons].d->vc_screenbuf_size)
  234. #define origin        (vc_cons[currcons].d->vc_origin)
  235. #define scr_end        (vc_cons[currcons].d->vc_scr_end)
  236. #define pos        (vc_cons[currcons].d->vc_pos)
  237. #define top        (vc_cons[currcons].d->vc_top)
  238. #define bottom        (vc_cons[currcons].d->vc_bottom)
  239. #define x        (vc_cons[currcons].d->vc_x)
  240. #define y        (vc_cons[currcons].d->vc_y)
  241. #define vc_state    (vc_cons[currcons].d->vc_state)
  242. #define npar        (vc_cons[currcons].d->vc_npar)
  243. #define par        (vc_cons[currcons].d->vc_par)
  244. #define ques        (vc_cons[currcons].d->vc_ques)
  245. #define attr        (vc_cons[currcons].d->vc_attr)
  246. #define saved_x        (vc_cons[currcons].d->vc_saved_x)
  247. #define saved_y        (vc_cons[currcons].d->vc_saved_y)
  248. #define translate    (vc_cons[currcons].d->vc_translate)
  249. #define G0_charset    (vc_cons[currcons].d->vc_G0_charset)
  250. #define G1_charset    (vc_cons[currcons].d->vc_G1_charset)
  251. #define saved_G0    (vc_cons[currcons].d->vc_saved_G0)
  252. #define saved_G1    (vc_cons[currcons].d->vc_saved_G1)
  253. #define utf        (vc_cons[currcons].d->vc_utf)
  254. #define utf_count    (vc_cons[currcons].d->vc_utf_count)
  255. #define utf_char    (vc_cons[currcons].d->vc_utf_char)
  256. #define video_mem_start    (vc_cons[currcons].d->vc_video_mem_start)
  257. #define video_mem_end    (vc_cons[currcons].d->vc_video_mem_end)
  258. #define video_erase_char (vc_cons[currcons].d->vc_video_erase_char)    
  259. #define disp_ctrl    (vc_cons[currcons].d->vc_disp_ctrl)
  260. #define toggle_meta    (vc_cons[currcons].d->vc_toggle_meta)
  261. #define decscnm        (vc_cons[currcons].d->vc_decscnm)
  262. #define decom        (vc_cons[currcons].d->vc_decom)
  263. #define decawm        (vc_cons[currcons].d->vc_decawm)
  264. #define deccm        (vc_cons[currcons].d->vc_deccm)
  265. #define decim        (vc_cons[currcons].d->vc_decim)
  266. #define deccolm         (vc_cons[currcons].d->vc_deccolm)
  267. #define need_wrap    (vc_cons[currcons].d->vc_need_wrap)
  268. #define has_scrolled    (vc_cons[currcons].d->vc_has_scrolled)
  269. #define kmalloced    (vc_cons[currcons].d->vc_kmalloced)
  270. #define report_mouse    (vc_cons[currcons].d->vc_report_mouse)
  271. #define color        (vc_cons[currcons].d->vc_color)
  272. #define s_color        (vc_cons[currcons].d->vc_s_color)
  273. #define def_color    (vc_cons[currcons].d->vc_def_color)
  274. #define    foreground    (color & 0x0f)
  275. #define background    (color & 0xf0)
  276. #define charset        (vc_cons[currcons].d->vc_charset)
  277. #define s_charset    (vc_cons[currcons].d->vc_s_charset)
  278. #define    intensity    (vc_cons[currcons].d->vc_intensity)
  279. #define    underline    (vc_cons[currcons].d->vc_underline)
  280. #define    blink        (vc_cons[currcons].d->vc_blink)
  281. #define    reverse        (vc_cons[currcons].d->vc_reverse)
  282. #define    s_intensity    (vc_cons[currcons].d->vc_s_intensity)
  283. #define    s_underline    (vc_cons[currcons].d->vc_s_underline)
  284. #define    s_blink        (vc_cons[currcons].d->vc_s_blink)
  285. #define    s_reverse    (vc_cons[currcons].d->vc_s_reverse)
  286. #define    ulcolor        (vc_cons[currcons].d->vc_ulcolor)
  287. #define    halfcolor    (vc_cons[currcons].d->vc_halfcolor)
  288. #define tab_stop    (vc_cons[currcons].d->vc_tab_stop)
  289.  
  290. #define vcmode        (vt_cons[currcons]->vc_mode)
  291. #define structsize    (sizeof(struct vc_data) + sizeof(struct vt_struct))
  292.  
  293. static void memsetw(void * s, unsigned short c, unsigned int count)
  294. {
  295.     unsigned short * addr = (unsigned short *) s;
  296.  
  297.     count /= 2;
  298.     while (count) {
  299.         count--;
  300.         scr_writew(c, addr++);
  301.     }
  302. }
  303.  
  304. static inline void memcpyw(unsigned short *to, unsigned short *from,
  305.                unsigned int count)
  306. {
  307.     count /= 2;
  308.     while (count) {
  309.         count--;
  310.         scr_writew(scr_readw(from++), to++);
  311.     }
  312. }
  313.  
  314. int vc_cons_allocated(unsigned int i)
  315. {
  316.     return (i < MAX_NR_CONSOLES && vc_cons[i].d);
  317. }
  318.  
  319. int vc_allocate(unsigned int i)        /* return 0 on success */
  320. {
  321.     if (i >= MAX_NR_CONSOLES)
  322.       return -ENODEV;
  323.     if (!vc_cons[i].d) {
  324.         long p, q;
  325.  
  326.         /* prevent users from taking too much memory */
  327.         if (i >= MAX_NR_USER_CONSOLES && !suser())
  328.           return -EPERM;
  329.  
  330.         /* due to the granularity of kmalloc, we waste some memory here */
  331.         /* the alloc is done in two steps, to optimize the common situation
  332.            of a 25x80 console (structsize=216, video_screen_size=4000) */
  333.         q = (long) kmalloc(video_screen_size, GFP_KERNEL);
  334.         if (!q)
  335.           return -ENOMEM;
  336.         p = (long) kmalloc(structsize, GFP_KERNEL);
  337.         if (!p) {
  338.         kfree_s((char *) q, video_screen_size);
  339.         return -ENOMEM;
  340.         }
  341.  
  342.         vc_cons[i].d = (struct vc_data *) p;
  343.         p += sizeof(struct vc_data);
  344.         vt_cons[i] = (struct vt_struct *) p;
  345.         vc_scrbuf[i] = (unsigned short *) q;
  346.         vc_cons[i].d->vc_kmalloced = 1;
  347.         vc_cons[i].d->vc_screenbuf_size = video_screen_size;
  348.         vc_init (i, video_num_lines, video_num_columns, 1);
  349.     }
  350.     return 0;
  351. }
  352.  
  353. /*
  354.  * Change # of rows and columns (0 means unchanged)
  355.  * [this is to be used together with some user program
  356.  * like resize that changes the hardware videomode]
  357.  */
  358. int vc_resize(unsigned long lines, unsigned long cols)
  359. {
  360.     unsigned long cc, ll, ss, sr;
  361.     unsigned long occ, oll, oss, osr;
  362.     unsigned short *p;
  363.     unsigned int currcons, i;
  364.     unsigned short *newscreens[MAX_NR_CONSOLES];
  365.     long ol, nl, rlth, rrem;
  366.  
  367.     cc = (cols ? cols : video_num_columns);
  368.     ll = (lines ? lines : video_num_lines);
  369.     sr = cc << 1;
  370.     ss = sr * ll;
  371.  
  372.     if (ss > video_mem_term - video_mem_base)
  373.       return -ENOMEM;
  374.  
  375.     /*
  376.      * Some earlier version had all consoles of potentially
  377.      * different sizes, but that was really messy.
  378.      * So now we only change if there is room for all consoles
  379.      * of the same size.
  380.      */
  381.     for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
  382.         if (!vc_cons_allocated(currcons))
  383.           newscreens[currcons] = 0;
  384.         else {
  385.         p = (unsigned short *) kmalloc(ss, GFP_USER);
  386.         if (!p) {
  387.             for (i = 0; i< currcons; i++)
  388.               if (newscreens[i])
  389.             kfree_s(newscreens[i], ss);
  390.             return -ENOMEM;
  391.         }
  392.         newscreens[currcons] = p;
  393.         }
  394.     }
  395.  
  396.     get_scrmem(fg_console);
  397.  
  398.     oll = video_num_lines;
  399.     occ = video_num_columns;
  400.     osr = video_size_row;
  401.     oss = video_screen_size;
  402.  
  403.     video_num_lines = ll;
  404.     video_num_columns = cc;
  405.     video_size_row = sr;
  406.     video_screen_size = ss;
  407.  
  408.     for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
  409.         if (!vc_cons_allocated(currcons))
  410.           continue;
  411.  
  412.         rlth = MIN(osr, sr);
  413.         rrem = sr - rlth;
  414.         ol = origin;
  415.         nl = (long) newscreens[currcons];
  416.         if (ll < oll)
  417.           ol += (oll - ll) * osr;
  418.  
  419.         while (ol < scr_end) {
  420.         memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
  421.         if (rrem)
  422.           memsetw((void *)(nl + rlth), video_erase_char, rrem);
  423.         ol += osr;
  424.         nl += sr;
  425.         }
  426.  
  427.         if (kmalloced)
  428.           kfree_s(vc_scrbuf[currcons], screenbuf_size);
  429.         vc_scrbuf[currcons] = newscreens[currcons];
  430.         kmalloced = 1;
  431.         screenbuf_size = ss;
  432.  
  433.         origin = video_mem_start = (long) vc_scrbuf[currcons];
  434.         scr_end = video_mem_end = video_mem_start + ss;
  435.  
  436.         if (scr_end > nl)
  437.           memsetw((void *) nl, video_erase_char, scr_end - nl);
  438.  
  439.         /* do part of a reset_terminal() */
  440.         top = 0;
  441.         bottom = video_num_lines;
  442.         gotoxy(currcons, x, y);
  443.         save_cur(currcons);
  444.     }
  445.  
  446.     set_scrmem(fg_console, 0);
  447.     set_origin(fg_console);
  448.     set_cursor(fg_console);
  449.  
  450.     return 0;
  451. }
  452.  
  453. void vc_disallocate(unsigned int currcons)
  454. {
  455.     if (vc_cons_allocated(currcons)) {
  456.         if (kmalloced)
  457.           kfree_s(vc_scrbuf[currcons], screenbuf_size);
  458.         if (currcons >= MIN_NR_CONSOLES)
  459.           kfree_s(vc_cons[currcons].d, structsize);
  460.         vc_cons[currcons].d = 0;
  461.     }
  462. }
  463.  
  464.  
  465. #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
  466. #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
  467. #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
  468.  
  469. #define decarm        VC_REPEAT
  470. #define decckm        VC_CKMODE
  471. #define kbdapplic    VC_APPLIC
  472. #define lnm        VC_CRLF
  473.  
  474. /*
  475.  * this is what the terminal answers to a ESC-Z or csi0c query.
  476.  */
  477. #define VT100ID "\033[?1;2c"
  478. #define VT102ID "\033[?6c"
  479.  
  480. static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
  481.                        8,12,10,14, 9,13,11,15 };
  482.  
  483. /*
  484.  * gotoxy() must verify all boundaries, because the arguments
  485.  * might also be negative. If the given position is out of
  486.  * bounds, the cursor is placed at the nearest margin.
  487.  */
  488. static void gotoxy(int currcons, int new_x, int new_y)
  489. {
  490.     int max_y;
  491.  
  492.     if (new_x < 0)
  493.         x = 0;
  494.     else
  495.         if (new_x >= video_num_columns)
  496.             x = video_num_columns - 1;
  497.         else
  498.             x = new_x;
  499.      if (decom) {
  500.         new_y += top;
  501.         max_y = bottom;
  502.     } else
  503.         max_y = video_num_lines;
  504.     if (new_y < 0)
  505.         y = 0;
  506.     else
  507.         if (new_y >= max_y)
  508.             y = max_y - 1;
  509.         else
  510.             y = new_y;
  511.     pos = origin + y*video_size_row + (x<<1);
  512.     need_wrap = 0;
  513. }
  514.  
  515. /*
  516.  * *Very* limited hardware scrollback support..
  517.  */
  518. static unsigned short __real_origin;
  519. static unsigned short __origin;        /* offset of currently displayed screen */
  520.  
  521. static inline void __set_origin(unsigned short offset)
  522. {
  523.     unsigned long flags;
  524.  
  525.     clear_selection();
  526.  
  527.     save_flags(flags); cli();
  528.     __origin = offset;
  529.     outb_p(12, video_port_reg);
  530.     outb_p(offset >> 8, video_port_val);
  531.     outb_p(13, video_port_reg);
  532.     outb_p(offset, video_port_val);
  533.     restore_flags(flags);
  534. }
  535.  
  536. void scrollback(int lines)
  537. {
  538.     if (!lines)
  539.         lines = video_num_lines/2;
  540.     lines *= video_num_columns;
  541.     lines = __origin - lines;
  542.     if (lines < 0)
  543.         lines = 0;
  544.     __set_origin(lines);
  545. }
  546.  
  547. void scrollfront(int lines)
  548. {
  549.     if (!lines)
  550.         lines = video_num_lines/2;
  551.     lines *= video_num_columns;
  552.     lines = __origin + lines;
  553.     if (lines > __real_origin)
  554.         lines = __real_origin;
  555.     __set_origin(lines);
  556. }
  557.  
  558. static void set_origin(int currcons)
  559. {
  560.     if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
  561.         return;
  562.     if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
  563.         return;
  564.     __real_origin = (origin-video_mem_base) >> 1;
  565.     __set_origin(__real_origin);
  566. }
  567.  
  568. /*
  569.  * Put the cursor just beyond the end of the display adaptor memory.
  570.  */
  571. static inline void hide_cursor(void)
  572. {
  573.   /* This is inefficient, we could just put the cursor at 0xffff,
  574.      but perhaps the delays due to the inefficiency are useful for
  575.      some hardware... */
  576.     outb_p(14, video_port_reg);
  577.     outb_p(0xff&((video_mem_term-video_mem_base)>>9), video_port_val);
  578.     outb_p(15, video_port_reg);
  579.     outb_p(0xff&((video_mem_term-video_mem_base)>>1), video_port_val);
  580. }
  581.  
  582. static inline void set_cursor(int currcons)
  583. {
  584.     unsigned long flags;
  585.  
  586.     if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
  587.         return;
  588.     if (__real_origin != __origin)
  589.         __set_origin(__real_origin);
  590.     save_flags(flags); cli();
  591.     if (deccm) {
  592.         outb_p(14, video_port_reg);
  593.         outb_p(0xff&((pos-video_mem_base)>>9), video_port_val);
  594.         outb_p(15, video_port_reg);
  595.         outb_p(0xff&((pos-video_mem_base)>>1), video_port_val);
  596.     } else
  597.         hide_cursor();
  598.     restore_flags(flags);
  599. }
  600.  
  601. static void scrup(int currcons, unsigned int t, unsigned int b)
  602. {
  603.     int hardscroll = 1;
  604.  
  605.     if (b > video_num_lines || t >= b)
  606.         return;
  607.     if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM)
  608.         hardscroll = 0;
  609.     else if (t || b != video_num_lines)
  610.         hardscroll = 0;
  611.     if (hardscroll) {
  612.         origin += video_size_row;
  613.         pos += video_size_row;
  614.         scr_end += video_size_row;
  615.         if (scr_end > video_mem_end) {
  616.             unsigned short * d = (unsigned short *) video_mem_start;
  617.             unsigned short * s = (unsigned short *) origin;
  618.             unsigned int count;
  619.  
  620.             count = (video_num_lines-1)*video_num_columns;
  621.             while (count) {
  622.                 count--;
  623.                 scr_writew(scr_readw(s++),d++);
  624.             }
  625.             count = video_num_columns;
  626.             while (count) {
  627.                 count--;
  628.                 scr_writew(video_erase_char, d++);
  629.             }
  630.             scr_end -= origin-video_mem_start;
  631.             pos -= origin-video_mem_start;
  632.             origin = video_mem_start;
  633.             has_scrolled = 1;
  634.         } else {
  635.             unsigned short * d;
  636.             unsigned int count;
  637.  
  638.             d = (unsigned short *) (scr_end - video_size_row);
  639.             count = video_num_columns;
  640.             while (count) {
  641.                 count--;
  642.                 scr_writew(video_erase_char, d++);
  643.             }
  644.         }
  645.         set_origin(currcons);
  646.     } else {
  647.         unsigned short * d = (unsigned short *) (origin+video_size_row*t);
  648.         unsigned short * s = (unsigned short *) (origin+video_size_row*(t+1));
  649.         unsigned int count = (b-t-1) * video_num_columns;
  650.  
  651.         while (count) {
  652.             count--;
  653.             scr_writew(scr_readw(s++), d++);
  654.         }
  655.         count = video_num_columns;
  656.         while (count) {
  657.             count--;
  658.             scr_writew(video_erase_char, d++);
  659.         }
  660.     }
  661. }
  662.  
  663. static void scrdown(int currcons, unsigned int t, unsigned int b)
  664. {
  665.     unsigned short *d, *s;
  666.     unsigned int count;
  667.  
  668.     if (b > video_num_lines || t >= b)
  669.         return;
  670.     d = (unsigned short *) (origin+video_size_row*b);
  671.     s = (unsigned short *) (origin+video_size_row*(b-1));
  672.     count = (b-t-1)*video_num_columns;
  673.     while (count) {
  674.         count--;
  675.         scr_writew(scr_readw(--s), --d);
  676.     }
  677.     count = video_num_columns;
  678.     while (count) {
  679.         count--;
  680.         scr_writew(video_erase_char, --d);
  681.     }
  682.     has_scrolled = 1;
  683. }
  684.  
  685. static void lf(int currcons)
  686. {
  687.         /* don't scroll if above bottom of scrolling region, or
  688.      * if below scrolling region
  689.      */
  690.         if (y+1 == bottom)
  691.         scrup(currcons,top,bottom);
  692.     else if (y < video_num_lines-1) {
  693.             y++;
  694.         pos += video_size_row;
  695.     }
  696.     need_wrap = 0;
  697. }
  698.  
  699. static void ri(int currcons)
  700. {
  701.         /* don't scroll if below top of scrolling region, or
  702.      * if above scrolling region
  703.      */
  704.     if (y == top)
  705.         scrdown(currcons,top,bottom);
  706.     else if (y > 0) {
  707.         y--;
  708.         pos -= video_size_row;
  709.     }
  710.     need_wrap = 0;
  711. }
  712.  
  713. static inline void cr(int currcons)
  714. {
  715.     pos -= x<<1;
  716.     need_wrap = x = 0;
  717. }
  718.  
  719. static inline void bs(int currcons)
  720. {
  721.     if (x) {
  722.         pos -= 2;
  723.         x--;
  724.         need_wrap = 0;
  725.     }
  726. }
  727.  
  728. static inline void del(int currcons)
  729. {
  730.     /* ignored */
  731. }
  732.  
  733. static void csi_J(int currcons, int vpar)
  734. {
  735.     unsigned long count;
  736.     unsigned short * start;
  737.  
  738.     switch (vpar) {
  739.         case 0:    /* erase from cursor to end of display */
  740.             count = (scr_end-pos)>>1;
  741.             start = (unsigned short *) pos;
  742.             break;
  743.         case 1:    /* erase from start to cursor */
  744.             count = ((pos-origin)>>1)+1;
  745.             start = (unsigned short *) origin;
  746.             break;
  747.         case 2: /* erase whole display */
  748.             count = video_num_columns * video_num_lines;
  749.             start = (unsigned short *) origin;
  750.             break;
  751.         default:
  752.             return;
  753.     }
  754.     while (count) {
  755.         count--;
  756.         scr_writew(video_erase_char, start++);
  757.     }
  758.     need_wrap = 0;
  759. }
  760.  
  761. static void csi_K(int currcons, int vpar)
  762. {
  763.     unsigned long count;
  764.     unsigned short * start;
  765.  
  766.     switch (vpar) {
  767.         case 0:    /* erase from cursor to end of line */
  768.             count = video_num_columns-x;
  769.             start = (unsigned short *) pos;
  770.             break;
  771.         case 1:    /* erase from start of line to cursor */
  772.             start = (unsigned short *) (pos - (x<<1));
  773.             count = x+1;
  774.             break;
  775.         case 2: /* erase whole line */
  776.             start = (unsigned short *) (pos - (x<<1));
  777.             count = video_num_columns;
  778.             break;
  779.         default:
  780.             return;
  781.     }
  782.     while (count) {
  783.         count--;
  784.         scr_writew(video_erase_char, start++);
  785.     }
  786.     need_wrap = 0;
  787. }
  788.  
  789. static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
  790. {                      /* not vt100? */
  791.     unsigned long count;
  792.     unsigned short * start;
  793.  
  794.     if (!vpar)
  795.         vpar++;
  796.  
  797.     start = (unsigned short *) pos;
  798.     count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
  799.  
  800.     while (count) {
  801.         count--;
  802.         scr_writew(video_erase_char, start++);
  803.     }
  804.     need_wrap = 0;
  805. }
  806.  
  807. static void update_attr(int currcons)
  808. {
  809.     attr = color;
  810.     if (can_do_color) {
  811.         if (underline)
  812.             attr = (attr & 0xf0) | ulcolor;
  813.         else if (intensity == 0)
  814.             attr = (attr & 0xf0) | halfcolor;
  815.     }
  816.     if (reverse ^ decscnm)
  817.         attr = reverse_video_char(attr);
  818.     if (blink)
  819.         attr ^= 0x80;
  820.     if (intensity == 2)
  821.         attr ^= 0x08;
  822.     if (!can_do_color) {
  823.         if (underline)
  824.             attr = (attr & 0xf8) | 0x01;
  825.         else if (intensity == 0)
  826.             attr = (attr & 0xf0) | 0x08;
  827.     }
  828.     if (decscnm)
  829.         video_erase_char = (reverse_video_char(color) << 8) | ' ';
  830.     else
  831.         video_erase_char = (color << 8) | ' ';
  832. }
  833.  
  834. static void default_attr(int currcons)
  835. {
  836.     intensity = 1;
  837.     underline = 0;
  838.     reverse = 0;
  839.     blink = 0;
  840.     color = def_color;
  841. }
  842.  
  843. static void csi_m(int currcons)
  844. {
  845.     int i;
  846.  
  847.     for (i=0;i<=npar;i++)
  848.         switch (par[i]) {
  849.             case 0:    /* all attributes off */
  850.                 default_attr(currcons);
  851.                 break;
  852.             case 1:
  853.                 intensity = 2;
  854.                 break;
  855.             case 2:
  856.                 intensity = 0;
  857.                 break;
  858.             case 4:
  859.                 underline = 1;
  860.                 break;
  861.             case 5:
  862.                 blink = 1;
  863.                 break;
  864.             case 7:
  865.                 reverse = 1;
  866.                 break;
  867.             case 10: /* ANSI X3.64-1979 (SCO-ish?)
  868.                   * Select primary font, don't display
  869.                   * control chars if defined, don't set
  870.                   * bit 8 on output.
  871.                   */
  872.                 translate = set_translate(charset == 0
  873.                         ? G0_charset
  874.                         : G1_charset);
  875.                 disp_ctrl = 0;
  876.                 toggle_meta = 0;
  877.                 break;
  878.             case 11: /* ANSI X3.64-1979 (SCO-ish?)
  879.                   * Select first alternate font, let's
  880.                   * chars < 32 be displayed as ROM chars.
  881.                   */
  882.                 translate = set_translate(NULL_MAP);
  883.                 disp_ctrl = 1;
  884.                 toggle_meta = 0;
  885.                 break;
  886.             case 12: /* ANSI X3.64-1979 (SCO-ish?)
  887.                   * Select second alternate font, toggle
  888.                   * high bit before displaying as ROM char.
  889.                   */
  890.                 translate = set_translate(NULL_MAP);
  891.                 disp_ctrl = 1;
  892.                 toggle_meta = 1;
  893.                 break;
  894.             case 21:
  895.             case 22:
  896.                 intensity = 1;
  897.                 break;
  898.             case 24:
  899.                 underline = 0;
  900.                 break;
  901.             case 25:
  902.                 blink = 0;
  903.                 break;
  904.             case 27:
  905.                 reverse = 0;
  906.                 break;
  907.             case 38: /* ANSI X3.64-1979 (SCO-ish?)
  908.                   * Enables underscore, white foreground
  909.                   * with white underscore (Linux - use
  910.                   * default foreground).
  911.                   */
  912.                 color = (def_color & 0x0f) | background;
  913.                 underline = 1;
  914.                 break;
  915.             case 39: /* ANSI X3.64-1979 (SCO-ish?)
  916.                   * Disable underline option.
  917.                   * Reset colour to default? It did this
  918.                   * before...
  919.                   */
  920.                 color = (def_color & 0x0f) | background;
  921.                 underline = 0;
  922.                 break;
  923.             case 49:
  924.                 color = (def_color & 0xf0) | foreground;
  925.                 break;
  926.             default:
  927.                 if (par[i] >= 30 && par[i] <= 37)
  928.                     color = color_table[par[i]-30]
  929.                         | background; 
  930.                 else if (par[i] >= 40 && par[i] <= 47)
  931.                     color = (color_table[par[i]-40]<<4)
  932.                         | foreground;
  933.                 break;
  934.         }
  935.     update_attr(currcons);
  936. }
  937.  
  938. static void respond_string(char * p, struct tty_struct * tty)
  939. {
  940.     while (*p) {
  941.         tty_insert_flip_char(tty, *p, 0);
  942.         p++;
  943.     }
  944.     tty_schedule_flip(tty);
  945. }
  946.  
  947. static void cursor_report(int currcons, struct tty_struct * tty)
  948. {
  949.     char buf[40];
  950.  
  951.     sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
  952.     respond_string(buf, tty);
  953. }
  954.  
  955. static inline void status_report(struct tty_struct * tty)
  956. {
  957.     respond_string("\033[0n", tty);    /* Terminal ok */
  958. }
  959.  
  960. static inline void respond_ID(struct tty_struct * tty)
  961. {
  962.     respond_string(VT102ID, tty);
  963. }
  964.  
  965. void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
  966. {
  967.     char buf[8];
  968.  
  969.     sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
  970.         (char)('!' + mry));
  971.     respond_string(buf, tty);
  972. }
  973.  
  974. /* invoked via ioctl(TIOCLINUX) */
  975. int mouse_reporting(void)
  976. {
  977.     int currcons = fg_console;
  978.  
  979.     return report_mouse;
  980. }
  981.  
  982. static inline unsigned short *screenpos(int currcons, int offset, int viewed)
  983. {
  984.     unsigned short *p = (unsigned short *)(origin + offset);
  985.     if (viewed && currcons == fg_console)
  986.         p -= (__real_origin - __origin);
  987.     return p;
  988. }
  989.  
  990. /* Note: inverting the screen twice should revert to the original state */
  991. void invert_screen(int currcons, int offset, int count, int viewed)
  992. {
  993.     unsigned short *p;
  994.  
  995.     count /= 2;
  996.     p = screenpos(currcons, offset, viewed);
  997.     if (can_do_color)
  998.         while (count--) {
  999.             unsigned short old = scr_readw(p);
  1000.             scr_writew(reverse_video_short(old), p);
  1001.             p++;
  1002.         }
  1003.     else
  1004.         while (count--) {
  1005.             unsigned short old = scr_readw(p);
  1006.             scr_writew(old ^ (((old & 0x0700) == 0x0100)
  1007.                       ? 0x7000 : 0x7700), p);
  1008.             p++;
  1009.         }
  1010. }
  1011.  
  1012. /* used by selection: complement pointer position */
  1013. void complement_pos(int currcons, int offset)
  1014. {
  1015.     static unsigned short *p = NULL;
  1016.     static unsigned short old = 0;
  1017.  
  1018.     if (p)
  1019.         scr_writew(old, p);
  1020.     if (offset == -1)
  1021.         p = NULL;
  1022.     else {
  1023.         p = screenpos(currcons, offset, 1);
  1024.         old = scr_readw(p);
  1025.         scr_writew(old ^ 0x7700, p);
  1026.     }
  1027. }
  1028.  
  1029. /* used by selection */
  1030. unsigned short screen_word(int currcons, int offset, int viewed)
  1031. {
  1032.     return scr_readw(screenpos(currcons, offset, viewed));
  1033. }
  1034.  
  1035. /* used by vcs - note the word offset */
  1036. unsigned short *screen_pos(int currcons, int w_offset, int viewed)
  1037. {
  1038.     return screenpos(currcons, 2 * w_offset, viewed);
  1039. }
  1040.  
  1041. void getconsxy(int currcons, char *p)
  1042. {
  1043.     p[0] = x;
  1044.     p[1] = y;
  1045. }
  1046.  
  1047. void putconsxy(int currcons, char *p)
  1048. {
  1049.     gotoxy(currcons, p[0], p[1]);
  1050.     set_cursor(currcons);
  1051. }
  1052.  
  1053. static void set_mode(int currcons, int on_off)
  1054. {
  1055.     int i;
  1056.  
  1057.     for (i=0; i<=npar; i++)
  1058.         if (ques) switch(par[i]) {    /* DEC private modes set/reset */
  1059.             case 1:            /* Cursor keys send ^[Ox/^[[x */
  1060.                 if (on_off)
  1061.                     set_kbd(decckm);
  1062.                 else
  1063.                     clr_kbd(decckm);
  1064.                 break;
  1065.             case 3:    /* 80/132 mode switch unimplemented */
  1066.                 deccolm = on_off;
  1067. #if 0
  1068.                 (void) vc_resize(video_num_lines, deccolm ? 132 : 80);
  1069.                 /* this alone does not suffice; some user mode
  1070.                    utility has to change the hardware regs */
  1071. #endif
  1072.                 break;
  1073.             case 5:            /* Inverted screen on/off */
  1074.                 if (decscnm != on_off) {
  1075.                     decscnm = on_off;
  1076.                     invert_screen(currcons, 0, video_screen_size, 0);
  1077.                     update_attr(currcons);
  1078.                 }
  1079.                 break;
  1080.             case 6:            /* Origin relative/absolute */
  1081.                 decom = on_off;
  1082.                 gotoxy(currcons,0,0);
  1083.                 break;
  1084.             case 7:            /* Autowrap on/off */
  1085.                 decawm = on_off;
  1086.                 break;
  1087.             case 8:            /* Autorepeat on/off */
  1088.                 if (on_off)
  1089.                     set_kbd(decarm);
  1090.                 else
  1091.                     clr_kbd(decarm);
  1092.                 break;
  1093.             case 9:
  1094.                 report_mouse = on_off ? 1 : 0;
  1095.                 break;
  1096.             case 25:        /* Cursor on/off */
  1097.                 deccm = on_off;
  1098.                 set_cursor(currcons);
  1099.                 break;
  1100.             case 1000:
  1101.                 report_mouse = on_off ? 2 : 0;
  1102.                 break;
  1103.         } else switch(par[i]) {        /* ANSI modes set/reset */
  1104.             case 3:            /* Monitor (display ctrls) */
  1105.                 disp_ctrl = on_off;
  1106.                 break;
  1107.             case 4:            /* Insert Mode on/off */
  1108.                 decim = on_off;
  1109.                 break;
  1110.             case 20:        /* Lf, Enter == CrLf/Lf */
  1111.                 if (on_off)
  1112.                     set_kbd(lnm);
  1113.                 else
  1114.                     clr_kbd(lnm);
  1115.                 break;
  1116.         }
  1117. }
  1118.  
  1119. static void setterm_command(int currcons)
  1120. {
  1121.     switch(par[0]) {
  1122.         case 1:    /* set color for underline mode */
  1123.             if (can_do_color && par[1] < 16) {
  1124.                 ulcolor = color_table[par[1]];
  1125.                 if (underline)
  1126.                     update_attr(currcons);
  1127.             }
  1128.             break;
  1129.         case 2:    /* set color for half intensity mode */
  1130.             if (can_do_color && par[1] < 16) {
  1131.                 halfcolor = color_table[par[1]];
  1132.                 if (intensity == 0)
  1133.                     update_attr(currcons);
  1134.             }
  1135.             break;
  1136.         case 8:    /* store colors as defaults */
  1137.             def_color = attr;
  1138.             default_attr(currcons);
  1139.             update_attr(currcons);
  1140.             break;
  1141.         case 9:    /* set blanking interval */
  1142.             blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
  1143.             poke_blanked_console();
  1144.             break;
  1145.     }
  1146. }
  1147.  
  1148. static void insert_char(int currcons)
  1149. {
  1150.     unsigned int i = x;
  1151.     unsigned short tmp, old = video_erase_char;
  1152.     unsigned short * p = (unsigned short *) pos;
  1153.  
  1154.     while (i++ < video_num_columns) {
  1155.         tmp = scr_readw(p);
  1156.         scr_writew(old, p);
  1157.         old = tmp;
  1158.         p++;
  1159.     }
  1160.     need_wrap = 0;
  1161. }
  1162.  
  1163. static void insert_line(int currcons)
  1164. {
  1165.     scrdown(currcons,y,bottom);
  1166.     need_wrap = 0;
  1167. }
  1168.  
  1169. static void delete_char(int currcons)
  1170. {
  1171.     unsigned int i = x;
  1172.     unsigned short * p = (unsigned short *) pos;
  1173.  
  1174.     while (++i < video_num_columns) {
  1175.         scr_writew(scr_readw(p+1), p);
  1176.         p++;
  1177.     }
  1178.     scr_writew(video_erase_char, p);
  1179.     need_wrap = 0;
  1180. }
  1181.  
  1182. static void delete_line(int currcons)
  1183. {
  1184.     scrup(currcons,y,bottom);
  1185.     need_wrap = 0;
  1186. }
  1187.  
  1188. static void csi_at(int currcons, unsigned int nr)
  1189. {
  1190.     if (nr > video_num_columns)
  1191.         nr = video_num_columns;
  1192.     else if (!nr)
  1193.         nr = 1;
  1194.     while (nr--)
  1195.         insert_char(currcons);
  1196. }
  1197.  
  1198. static void csi_L(int currcons, unsigned int nr)
  1199. {
  1200.     if (nr > video_num_lines)
  1201.         nr = video_num_lines;
  1202.     else if (!nr)
  1203.         nr = 1;
  1204.     while (nr--)
  1205.         insert_line(currcons);
  1206. }
  1207.  
  1208. static void csi_P(int currcons, unsigned int nr)
  1209. {
  1210.     if (nr > video_num_columns)
  1211.         nr = video_num_columns;
  1212.     else if (!nr)
  1213.         nr = 1;
  1214.     while (nr--)
  1215.         delete_char(currcons);
  1216. }
  1217.  
  1218. static void csi_M(int currcons, unsigned int nr)
  1219. {
  1220.     if (nr > video_num_lines)
  1221.         nr = video_num_lines;
  1222.     else if (!nr)
  1223.         nr=1;
  1224.     while (nr--)
  1225.         delete_line(currcons);
  1226. }
  1227.  
  1228. static void save_cur(int currcons)
  1229. {
  1230.     saved_x        = x;
  1231.     saved_y        = y;
  1232.     s_intensity    = intensity;
  1233.     s_underline    = underline;
  1234.     s_blink        = blink;
  1235.     s_reverse    = reverse;
  1236.     s_charset    = charset;
  1237.     s_color        = color;
  1238.     saved_G0    = G0_charset;
  1239.     saved_G1    = G1_charset;
  1240. }
  1241.  
  1242. static void restore_cur(int currcons)
  1243. {
  1244.     gotoxy(currcons,saved_x,saved_y);
  1245.     intensity    = s_intensity;
  1246.     underline    = s_underline;
  1247.     blink        = s_blink;
  1248.     reverse        = s_reverse;
  1249.     charset        = s_charset;
  1250.     color        = s_color;
  1251.     G0_charset    = saved_G0;
  1252.     G1_charset    = saved_G1;
  1253.     translate    = set_translate(charset ? G1_charset : G0_charset);
  1254.     update_attr(currcons);
  1255.     need_wrap = 0;
  1256. }
  1257.  
  1258. enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
  1259.     EShash, ESsetG0, ESsetG1, ESpercent, ESignore };
  1260.  
  1261. static void reset_terminal(int currcons, int do_clear)
  1262. {
  1263.     top        = 0;
  1264.     bottom        = video_num_lines;
  1265.     vc_state    = ESnormal;
  1266.     ques        = 0;
  1267.     translate    = set_translate(NORM_MAP);
  1268.     G0_charset    = NORM_MAP;
  1269.     G1_charset    = GRAF_MAP;
  1270.     charset        = 0;
  1271.     need_wrap    = 0;
  1272.     report_mouse    = 0;
  1273.     utf             = 0;
  1274.     utf_count       = 0;
  1275.  
  1276.     disp_ctrl    = 0;
  1277.     toggle_meta    = 0;
  1278.  
  1279.     decscnm        = 0;
  1280.     decom        = 0;
  1281.     decawm        = 1;
  1282.     deccm        = 1;
  1283.     decim        = 0;
  1284.  
  1285.     set_kbd(decarm);
  1286.     clr_kbd(decckm);
  1287.     clr_kbd(kbdapplic);
  1288.     clr_kbd(lnm);
  1289.     kbd_table[currcons].lockstate = 0;
  1290.     kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
  1291.     kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
  1292.     set_leds();
  1293.  
  1294.     default_attr(currcons);
  1295.     update_attr(currcons);
  1296.  
  1297.     tab_stop[0]    = 0x01010100;
  1298.     tab_stop[1]    =
  1299.     tab_stop[2]    =
  1300.     tab_stop[3]    =
  1301.     tab_stop[4]    = 0x01010101;
  1302.  
  1303.     gotoxy(currcons,0,0);
  1304.     save_cur(currcons);
  1305.     if (do_clear)
  1306.         csi_J(currcons,2);
  1307. }
  1308.  
  1309. /*
  1310.  * Turn the Scroll-Lock LED on when the tty is stopped
  1311.  */
  1312. static void con_stop(struct tty_struct *tty)
  1313. {
  1314.     int console_num;
  1315.     if (!tty)
  1316.         return;
  1317.     console_num = MINOR(tty->device) - (tty->driver.minor_start);
  1318.     if (!vc_cons_allocated(console_num))
  1319.         return;
  1320.     set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
  1321.     set_leds();
  1322. }
  1323.  
  1324. /*
  1325.  * Turn the Scroll-Lock LED off when the console is started
  1326.  */
  1327. static void con_start(struct tty_struct *tty)
  1328. {
  1329.     int console_num;
  1330.     if (!tty)
  1331.         return;
  1332.     console_num = MINOR(tty->device) - (tty->driver.minor_start);
  1333.     if (!vc_cons_allocated(console_num))
  1334.         return;
  1335.     clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
  1336.     set_leds();
  1337. }
  1338.  
  1339. static int con_write(struct tty_struct * tty, int from_user,
  1340.              unsigned char *buf, int count)
  1341. {
  1342.     int c, tc, ok, n = 0;
  1343.     unsigned int currcons;
  1344.     struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
  1345.  
  1346.     currcons = vt->vc_num;
  1347.     if (!vc_cons_allocated(currcons)) {
  1348.         /* could this happen? */
  1349.         static int error = 0;
  1350.         if (!error) {
  1351.         error = 1;
  1352.         printk("con_write: tty %d not allocated\n", currcons+1);
  1353.         }
  1354.         return 0;
  1355.     }
  1356.  
  1357.     if (currcons == sel_cons)
  1358.         clear_selection();
  1359.  
  1360.     disable_bh(KEYBOARD_BH);
  1361.     while (!tty->stopped &&    count) {
  1362.         c = from_user ? get_fs_byte(buf) : *buf;
  1363.         buf++; n++; count--;
  1364.  
  1365.         if (utf) {
  1366.             /* Combine UTF-8 into Unicode */
  1367.             /* Incomplete characters silently ignored */
  1368.             if(c > 0x7f) {   
  1369.             if (utf_count > 0 && (c & 0xc0) == 0x80) {
  1370.                 utf_char = (utf_char << 6) | (c & 0x3f);
  1371.                 utf_count--;
  1372.                 if (utf_count == 0)
  1373.                     c = utf_char;
  1374.                 else continue;
  1375.             } else {
  1376.                 if ((c & 0xe0) == 0xc0) {
  1377.                     utf_count = 1;
  1378.                     utf_char = (c & 0x1f);
  1379.                 } else if ((c & 0xf0) == 0xe0) {
  1380.                     utf_count = 2;
  1381.                     utf_char = (c & 0x0f);
  1382.                 } else
  1383.                     utf_count = 0;
  1384.                 continue;
  1385.             }
  1386.             } else
  1387.             utf_count = 0;
  1388.  
  1389.             /* Now try to find out how to display it */
  1390.             tc = conv_uni_to_pc(c);
  1391.             if (tc == -1 || tc == -2)
  1392.               continue;
  1393.             if (tc == -3 || tc == -4) {    /* hashtable not valid */
  1394.                         /* or symbol not found */
  1395.             tc = (c <= 0xff) ? translate[c] : 040;
  1396.             ok = 0;
  1397.             } else
  1398.                 ok = 1;
  1399.         } else {    /* no utf */
  1400.             tc = translate[toggle_meta ? (c|0x80) : c];
  1401.             ok = 0;
  1402.         }
  1403.  
  1404.         /* If the original code was < 32 we only allow a
  1405.          * glyph to be displayed if the code is not normally
  1406.          * used (such as for cursor movement) or if the
  1407.          * disp_ctrl mode has been explicitly enabled.
  1408.          * Note: ESC is *never* allowed to be displayed as
  1409.          * that would disable all escape sequences!
  1410.          */
  1411.         if (!ok && tc && (c >= 32 || (disp_ctrl && c != 0x1b)
  1412.         || !((CTRL_ACTION >> c) & 1)))
  1413.             ok = 1;
  1414.  
  1415.         if (vc_state == ESnormal && ok) {
  1416.             if (need_wrap) {
  1417.                 cr(currcons);
  1418.                 lf(currcons);
  1419.             }
  1420.             if (decim)
  1421.                 insert_char(currcons);
  1422.             scr_writew((attr << 8) + tc, (unsigned short *) pos);
  1423.             if (x == video_num_columns - 1)
  1424.                 need_wrap = decawm;
  1425.             else {
  1426.                 x++;
  1427.                 pos+=2;
  1428.             }
  1429.             continue;
  1430.         }
  1431.  
  1432.         /*
  1433.          *  Control characters can be used in the _middle_
  1434.          *  of an escape sequence.
  1435.          */
  1436.         switch (c) {
  1437.             case 7:
  1438.                 kd_mksound(0x637, HZ/8);
  1439.                 continue;
  1440.             case 8:
  1441.                 bs(currcons);
  1442.                 continue;
  1443.             case 9:
  1444.                 pos -= (x << 1);
  1445.                 while (x < video_num_columns - 1) {
  1446.                     x++;
  1447.                     if (tab_stop[x >> 5] & (1 << (x & 31)))
  1448.                         break;
  1449.                 }
  1450.                 pos += (x << 1);
  1451.                 continue;
  1452.             case 10: case 11: case 12:
  1453.                 lf(currcons);
  1454.                 if (!is_kbd(lnm))
  1455.                     continue;
  1456.             case 13:
  1457.                 cr(currcons);
  1458.                 continue;
  1459.             case 14:
  1460.                 charset = 1;
  1461.                 translate = set_translate(G1_charset);
  1462.                 disp_ctrl = 1;
  1463.                 continue;
  1464.             case 15:
  1465.                 charset = 0;
  1466.                 translate = set_translate(G0_charset);
  1467.                 disp_ctrl = 0;
  1468.                 continue;
  1469.             case 24: case 26:
  1470.                 vc_state = ESnormal;
  1471.                 continue;
  1472.             case 27:
  1473.                 vc_state = ESesc;
  1474.                 continue;
  1475.             case 127:
  1476.                 del(currcons);
  1477.                 continue;
  1478.             case 128+27:
  1479.                 vc_state = ESsquare;
  1480.                 continue;
  1481.         }
  1482.         switch(vc_state) {
  1483.             case ESesc:
  1484.                 vc_state = ESnormal;
  1485.                 switch (c) {
  1486.                   case '[':
  1487.                     vc_state = ESsquare;
  1488.                     continue;
  1489.                   case '%':
  1490.                     vc_state = ESpercent;
  1491.                     continue;
  1492.                   case 'E':
  1493.                     cr(currcons);
  1494.                     lf(currcons);
  1495.                     continue;
  1496.                   case 'M':
  1497.                     ri(currcons);
  1498.                     continue;
  1499.                   case 'D':
  1500.                     lf(currcons);
  1501.                     continue;
  1502.                   case 'H':
  1503.                     tab_stop[x >> 5] |= (1 << (x & 31));
  1504.                     continue;
  1505.                   case 'Z':
  1506.                     respond_ID(tty);
  1507.                     continue;
  1508.                   case '7':
  1509.                     save_cur(currcons);
  1510.                     continue;
  1511.                   case '8':
  1512.                     restore_cur(currcons);
  1513.                     continue;
  1514.                   case '(':
  1515.                     vc_state = ESsetG0;
  1516.                     continue;
  1517.                   case ')':
  1518.                     vc_state = ESsetG1;
  1519.                     continue;
  1520.                   case '#':
  1521.                     vc_state = EShash;
  1522.                     continue;
  1523.                   case 'c':
  1524.                     reset_terminal(currcons,1);
  1525.                     continue;
  1526.                   case '>':  /* Numeric keypad */
  1527.                     clr_kbd(kbdapplic);
  1528.                     continue;
  1529.                   case '=':  /* Appl. keypad */
  1530.                     set_kbd(kbdapplic);
  1531.                      continue;
  1532.                 }    
  1533.                 continue;
  1534.             case ESsquare:
  1535.                 for(npar = 0 ; npar < NPAR ; npar++)
  1536.                     par[npar] = 0;
  1537.                 npar = 0;
  1538.                 vc_state = ESgetpars;
  1539.                 if (c == '[') { /* Function key */
  1540.                     vc_state=ESfunckey;
  1541.                     continue;
  1542.                 }
  1543.                 ques = (c=='?');
  1544.                 if (ques)
  1545.                     continue;
  1546.             case ESgetpars:
  1547.                 if (c==';' && npar<NPAR-1) {
  1548.                     npar++;
  1549.                     continue;
  1550.                 } else if (c>='0' && c<='9') {
  1551.                     par[npar] *= 10;
  1552.                     par[npar] += c-'0';
  1553.                     continue;
  1554.                 } else vc_state=ESgotpars;
  1555.             case ESgotpars:
  1556.                 vc_state = ESnormal;
  1557.                 switch(c) {
  1558.                     case 'h':
  1559.                         set_mode(currcons,1);
  1560.                         continue;
  1561.                     case 'l':
  1562.                         set_mode(currcons,0);
  1563.                         continue;
  1564.                     case 'n':
  1565.                         if (!ques)
  1566.                             if (par[0] == 5)
  1567.                                 status_report(tty);
  1568.                             else if (par[0] == 6)
  1569.                                 cursor_report(currcons,tty);
  1570.                         continue;
  1571.                 }
  1572.                 if (ques) {
  1573.                     ques = 0;
  1574.                     continue;
  1575.                 }
  1576.                 switch(c) {
  1577.                     case 'G': case '`':
  1578.                         if (par[0]) par[0]--;
  1579.                         gotoxy(currcons,par[0],y);
  1580.                         continue;
  1581.                     case 'A':
  1582.                         if (!par[0]) par[0]++;
  1583.                         gotoxy(currcons,x,y-par[0]);
  1584.                         continue;
  1585.                     case 'B': case 'e':
  1586.                         if (!par[0]) par[0]++;
  1587.                         gotoxy(currcons,x,y+par[0]);
  1588.                         continue;
  1589.                     case 'C': case 'a':
  1590.                         if (!par[0]) par[0]++;
  1591.                         gotoxy(currcons,x+par[0],y);
  1592.                         continue;
  1593.                     case 'D':
  1594.                         if (!par[0]) par[0]++;
  1595.                         gotoxy(currcons,x-par[0],y);
  1596.                         continue;
  1597.                     case 'E':
  1598.                         if (!par[0]) par[0]++;
  1599.                         gotoxy(currcons,0,y+par[0]);
  1600.                         continue;
  1601.                     case 'F':
  1602.                         if (!par[0]) par[0]++;
  1603.                         gotoxy(currcons,0,y-par[0]);
  1604.                         continue;
  1605.                     case 'd':
  1606.                         if (par[0]) par[0]--;
  1607.                         gotoxy(currcons,x,par[0]);
  1608.                         continue;
  1609.                     case 'H': case 'f':
  1610.                         if (par[0]) par[0]--;
  1611.                         if (par[1]) par[1]--;
  1612.                         gotoxy(currcons,par[1],par[0]);
  1613.                         continue;
  1614.                     case 'J':
  1615.                         csi_J(currcons,par[0]);
  1616.                         continue;
  1617.                     case 'K':
  1618.                         csi_K(currcons,par[0]);
  1619.                         continue;
  1620.                     case 'L':
  1621.                         csi_L(currcons,par[0]);
  1622.                         continue;
  1623.                     case 'M':
  1624.                         csi_M(currcons,par[0]);
  1625.                         continue;
  1626.                     case 'P':
  1627.                         csi_P(currcons,par[0]);
  1628.                         continue;
  1629.                     case 'c':
  1630.                         if (!par[0])
  1631.                             respond_ID(tty);
  1632.                         continue;
  1633.                     case 'g':
  1634.                         if (!par[0])
  1635.                             tab_stop[x >> 5] &= ~(1 << (x & 31));
  1636.                         else if (par[0] == 3) {
  1637.                             tab_stop[0] =
  1638.                             tab_stop[1] =
  1639.                             tab_stop[2] =
  1640.                             tab_stop[3] =
  1641.                             tab_stop[4] = 0;
  1642.                         }
  1643.                         continue;
  1644.                     case 'm':
  1645.                         csi_m(currcons);
  1646.                         continue;
  1647.                     case 'q': /* DECLL - but only 3 leds */
  1648.                         /* map 0,1,2,3 to 0,1,2,4 */
  1649.                         if (par[0] < 4)
  1650.                           setledstate(kbd_table + currcons,
  1651.                                   (par[0] < 3) ? par[0] : 4);
  1652.                         continue;
  1653.                     case 'r':
  1654.                         if (!par[0])
  1655.                             par[0]++;
  1656.                         if (!par[1])
  1657.                             par[1] = video_num_lines;
  1658.                         /* Minimum allowed region is 2 lines */
  1659.                         if (par[0] < par[1] &&
  1660.                             par[1] <= video_num_lines) {
  1661.                             top=par[0]-1;
  1662.                             bottom=par[1];
  1663.                             gotoxy(currcons,0,0);
  1664.                         }
  1665.                         continue;
  1666.                     case 's':
  1667.                         save_cur(currcons);
  1668.                         continue;
  1669.                     case 'u':
  1670.                         restore_cur(currcons);
  1671.                         continue;
  1672.                     case 'X':
  1673.                         csi_X(currcons, par[0]);
  1674.                         continue;
  1675.                     case '@':
  1676.                         csi_at(currcons,par[0]);
  1677.                         continue;
  1678.                     case ']': /* setterm functions */
  1679.                         setterm_command(currcons);
  1680.                         continue;
  1681.                 }
  1682.                 continue;
  1683.             case ESpercent:
  1684.                 vc_state = ESnormal;
  1685.                 switch (c) {
  1686.                   case '@':  /* defined in ISO 2022 */
  1687.                     utf = 0;
  1688.                     continue;
  1689.                   case '8':
  1690.                     /* ISO/ECMA hasn't yet registered an
  1691.                        official ESC sequence for UTF-8,
  1692.                        so this one (ESC %8) will likely
  1693.                        change in the future. */
  1694.                     utf = 1;
  1695.                     continue;
  1696.                 }
  1697.                 continue;
  1698.             case ESfunckey:
  1699.                 vc_state = ESnormal;
  1700.                 continue;
  1701.             case EShash:
  1702.                 vc_state = ESnormal;
  1703.                 if (c == '8') {
  1704.                     /* DEC screen alignment test. kludge :-) */
  1705.                     video_erase_char =
  1706.                         (video_erase_char & 0xff00) | 'E';
  1707.                     csi_J(currcons, 2);
  1708.                     video_erase_char =
  1709.                         (video_erase_char & 0xff00) | ' ';
  1710.                 }
  1711.                 continue;
  1712.             case ESsetG0:
  1713.                 if (c == '0')
  1714.                     G0_charset = GRAF_MAP;
  1715.                 else if (c == 'B')
  1716.                     G0_charset = NORM_MAP;
  1717.                 else if (c == 'U')
  1718.                     G0_charset = NULL_MAP;
  1719.                 else if (c == 'K')
  1720.                     G0_charset = USER_MAP;
  1721.                 if (charset == 0)
  1722.                     translate = set_translate(G0_charset);
  1723.                 vc_state = ESnormal;
  1724.                 continue;
  1725.             case ESsetG1:
  1726.                 if (c == '0')
  1727.                     G1_charset = GRAF_MAP;
  1728.                 else if (c == 'B')
  1729.                     G1_charset = NORM_MAP;
  1730.                 else if (c == 'U')
  1731.                     G1_charset = NULL_MAP;
  1732.                 else if (c == 'K')
  1733.                     G1_charset = USER_MAP;
  1734.                 if (charset == 1)
  1735.                     translate = set_translate(G1_charset);
  1736.                 vc_state = ESnormal;
  1737.                 continue;
  1738.             default:
  1739.                 vc_state = ESnormal;
  1740.         }
  1741.     }
  1742.     if (vcmode != KD_GRAPHICS)
  1743.         set_cursor(currcons);
  1744.     enable_bh(KEYBOARD_BH);
  1745.     return n;
  1746. }
  1747.  
  1748. static int con_write_room(struct tty_struct *tty)
  1749. {
  1750.     if (tty->stopped)
  1751.         return 0;
  1752.     return 4096;        /* No limit, really; we're not buffering */
  1753. }
  1754.  
  1755. static int con_chars_in_buffer(struct tty_struct *tty)
  1756. {
  1757.     return 0;        /* we're not buffering */
  1758. }
  1759.  
  1760. void poke_blanked_console(void)
  1761. {
  1762.     timer_active &= ~(1<<BLANK_TIMER);
  1763.     if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
  1764.         return;
  1765.     if (console_blanked) {
  1766.         timer_table[BLANK_TIMER].expires = 0;
  1767.         timer_active |= 1<<BLANK_TIMER;
  1768.     } else if (blankinterval) {
  1769.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  1770.         timer_active |= 1<<BLANK_TIMER;
  1771.     }
  1772. }
  1773.  
  1774. void console_print(const char * b)
  1775. {
  1776.     int currcons = fg_console;
  1777.     unsigned char c;
  1778.     static int printing = 0;
  1779.  
  1780.     if (!printable || printing)
  1781.         return;     /* console not yet initialized */
  1782.     printing = 1;
  1783.  
  1784.     if (!vc_cons_allocated(currcons)) {
  1785.         /* impossible */
  1786.         printk("console_print: tty %d not allocated ??\n", currcons+1);
  1787.         return;
  1788.     }
  1789.  
  1790.     while ((c = *(b++)) != 0) {
  1791.         if (c == 10 || c == 13 || need_wrap) {
  1792.             if (c != 13)
  1793.                 lf(currcons);
  1794.             cr(currcons);
  1795.             if (c == 10 || c == 13)
  1796.                 continue;
  1797.         }
  1798.         scr_writew((attr << 8) + c, (unsigned short *) pos);
  1799.         if (x == video_num_columns - 1) {
  1800.             need_wrap = 1;
  1801.             continue;
  1802.         }
  1803.         x++;
  1804.         pos+=2;
  1805.     }
  1806.     set_cursor(currcons);
  1807.     poke_blanked_console();
  1808.     printing = 0;
  1809. }
  1810.  
  1811. /*
  1812.  * con_throttle and con_unthrottle are only used for
  1813.  * paste_selection(), which has to stuff in a large number of
  1814.  * characters...
  1815.  */
  1816. static void con_throttle(struct tty_struct *tty)
  1817. {
  1818. }
  1819.  
  1820. static void con_unthrottle(struct tty_struct *tty)
  1821. {
  1822.     struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
  1823.  
  1824.     wake_up_interruptible(&vt->paste_wait);
  1825. }
  1826.  
  1827. static void vc_init(unsigned int currcons, unsigned long rows, unsigned long cols, int do_clear)
  1828. {
  1829.     long base = (long) vc_scrbuf[currcons];
  1830.  
  1831.     video_num_columns = cols;
  1832.     video_num_lines = rows;
  1833.     video_size_row = cols<<1;
  1834.     video_screen_size = video_num_lines * video_size_row;
  1835.  
  1836.     pos = origin = video_mem_start = base;
  1837.     scr_end = base + video_screen_size;
  1838.     video_mem_end = base + video_screen_size;
  1839.     reset_vc(currcons);
  1840.     def_color       = 0x07;   /* white */
  1841.     ulcolor        = 0x0f;   /* bold white */
  1842.     halfcolor       = 0x08;   /* grey */
  1843.     vt_cons[currcons]->paste_wait = 0;
  1844.     reset_terminal(currcons, do_clear);
  1845. }
  1846.  
  1847. static void con_setsize(unsigned long rows, unsigned long cols)
  1848. {
  1849.     video_num_lines = rows;
  1850.     video_num_columns = cols;
  1851.     video_size_row = 2 * cols;
  1852.     video_screen_size = video_num_lines * video_size_row;
  1853. }
  1854.  
  1855. /*
  1856.  *  long con_init(long);
  1857.  *
  1858.  * This routine initializes console interrupts, and does nothing
  1859.  * else. If you want the screen to clear, call tty_write with
  1860.  * the appropriate escape-sequence.
  1861.  *
  1862.  * Reads the information preserved by setup.s to determine the current display
  1863.  * type and sets everything accordingly.
  1864.  */
  1865. long con_init(long kmem_start)
  1866. {
  1867.     char *display_desc = "????";
  1868.     int currcons = 0;
  1869.     int orig_x = ORIG_X;
  1870.     int orig_y = ORIG_Y;
  1871.  
  1872.     memset(&console_driver, 0, sizeof(struct tty_driver));
  1873.     console_driver.magic = TTY_DRIVER_MAGIC;
  1874.     console_driver.name = "tty";
  1875.     console_driver.name_base = 1;
  1876.     console_driver.major = TTY_MAJOR;
  1877.     console_driver.minor_start = 1;
  1878.     console_driver.num = MAX_NR_CONSOLES;
  1879.     console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
  1880.     console_driver.init_termios = tty_std_termios;
  1881.     console_driver.flags = TTY_DRIVER_REAL_RAW;
  1882.     console_driver.refcount = &console_refcount;
  1883.     console_driver.table = console_table;
  1884.     console_driver.termios = console_termios;
  1885.     console_driver.termios_locked = console_termios_locked;
  1886.  
  1887.     console_driver.open = con_open;
  1888.     console_driver.write = con_write;
  1889.     console_driver.write_room = con_write_room;
  1890.     console_driver.chars_in_buffer = con_chars_in_buffer;
  1891.     console_driver.ioctl = vt_ioctl;
  1892.     console_driver.stop = con_stop;
  1893.     console_driver.start = con_start;
  1894.     console_driver.throttle = con_throttle;
  1895.     console_driver.unthrottle = con_unthrottle;
  1896.     
  1897.     if (tty_register_driver(&console_driver))
  1898.         panic("Couldn't register console driver\n");
  1899.     
  1900.     con_setsize(ORIG_VIDEO_LINES, ORIG_VIDEO_COLS);
  1901.     video_page = ORIG_VIDEO_PAGE;             /* never used */
  1902.  
  1903.     timer_table[BLANK_TIMER].fn = blank_screen;
  1904.     timer_table[BLANK_TIMER].expires = 0;
  1905.     if (blankinterval) {
  1906.         timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
  1907.         timer_active |= 1<<BLANK_TIMER;
  1908.     }
  1909.     
  1910.     if (ORIG_VIDEO_MODE == 7)    /* Is this a monochrome display? */
  1911.     {
  1912.         video_mem_base = 0xb0000;
  1913.         video_port_reg = 0x3b4;
  1914.         video_port_val = 0x3b5;
  1915.         if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
  1916.         {
  1917.             video_type = VIDEO_TYPE_EGAM;
  1918.             video_mem_term = 0xb8000;
  1919.             display_desc = "EGA+";
  1920.             request_region(0x3b4,2,"ega+");
  1921.         }
  1922.         else
  1923.         {
  1924.             video_type = VIDEO_TYPE_MDA;
  1925.             video_mem_term = 0xb2000;
  1926.             display_desc = "*MDA";
  1927.             request_region(0x3b4,2,"mda");
  1928.             request_region(0x3b8,1,"mda");
  1929.             request_region(0x3bf,1,"mda");
  1930.         }
  1931.     }
  1932.     else                /* If not, it is color. */
  1933.     {
  1934.         can_do_color = 1;
  1935.         video_mem_base = 0xb8000;
  1936.         video_port_reg    = 0x3d4;
  1937.         video_port_val    = 0x3d5;
  1938.         if ((ORIG_VIDEO_EGA_BX & 0xff) != 0x10)
  1939.         {
  1940.             video_type = VIDEO_TYPE_EGAC;
  1941.             video_mem_term = 0xc0000;
  1942.             display_desc = "EGA+";
  1943.             request_region(0x3d4,2,"ega+");
  1944.         }
  1945.         else
  1946.         {
  1947.             video_type = VIDEO_TYPE_CGA;
  1948.             video_mem_term = 0xba000;
  1949.             display_desc = "*CGA";
  1950.             request_region(0x3d4,2,"cga");
  1951.         }
  1952.     }
  1953.     
  1954.     /* Initialize the variables used for scrolling (mostly EGA/VGA)    */
  1955.  
  1956.     /* Due to kmalloc roundup allocating statically is more efficient -
  1957.        so provide MIN_NR_CONSOLES for people with very little memory */
  1958.     for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
  1959.         vc_cons[currcons].d = (struct vc_data *) kmem_start;
  1960.         kmem_start += sizeof(struct vc_data);
  1961.         vt_cons[currcons] = (struct vt_struct *) kmem_start;
  1962.         kmem_start += sizeof(struct vt_struct);
  1963.         vc_scrbuf[currcons] = (unsigned short *) kmem_start;
  1964.         kmem_start += video_screen_size;
  1965.         kmalloced = 0;
  1966.         screenbuf_size = video_screen_size;
  1967.         vc_init(currcons, video_num_lines, video_num_columns, currcons);
  1968.     }
  1969.  
  1970.     currcons = fg_console = 0;
  1971.  
  1972.     video_mem_start = video_mem_base;
  1973.     video_mem_end = video_mem_term;
  1974.     origin = video_mem_start;
  1975.     scr_end    = video_mem_start + video_num_lines * video_size_row;
  1976.     gotoxy(currcons,orig_x,orig_y);
  1977.     set_origin(currcons);
  1978.     csi_J(currcons, 0);
  1979.     printable = 1;
  1980.     printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
  1981.         can_do_color ? "colour" : "mono",
  1982.         display_desc,
  1983.         video_num_columns,video_num_lines,
  1984.         MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
  1985.     register_console(console_print);
  1986.     return kmem_start;
  1987. }
  1988.  
  1989. static void get_scrmem(int currcons)
  1990. {
  1991.     memcpyw((unsigned short *)vc_scrbuf[currcons],
  1992.         (unsigned short *)origin, video_screen_size);
  1993.     origin = video_mem_start = (unsigned long)vc_scrbuf[currcons];
  1994.     scr_end = video_mem_end = video_mem_start + video_screen_size;
  1995.     pos = origin + y*video_size_row + (x<<1);
  1996. }
  1997.  
  1998. static void set_scrmem(int currcons, long offset)
  1999. {
  2000. #ifdef CONFIG_HGA
  2001.   /* This works with XFree86 1.2, 1.3 and 2.0
  2002.      This code could be extended and made more generally useful if we could
  2003.      determine the actual video mode. It appears that this should be
  2004.      possible on a genuine Hercules card, but I (WM) haven't been able to
  2005.      read from any of the required registers on my clone card.
  2006.      */
  2007.     /* This code should work with Hercules and MDA cards. */
  2008.     if (video_type == VIDEO_TYPE_MDA)
  2009.       {
  2010.         if (vcmode == KD_TEXT)
  2011.           {
  2012.         /* Ensure that the card is in text mode. */
  2013.         int    i;
  2014.         static char herc_txt_tbl[12] = {
  2015.           0x61,0x50,0x52,0x0f,0x19,6,0x19,0x19,2,0x0d,0x0b,0x0c };
  2016.         outb_p(0, 0x3bf);  /* Back to power-on defaults */
  2017.         outb_p(0, 0x3b8);  /* Blank the screen, select page 0, etc */
  2018.         for ( i = 0 ; i < 12 ; i++ )
  2019.           {
  2020.             outb_p(i, 0x3b4);
  2021.             outb_p(herc_txt_tbl[i], 0x3b5);
  2022.           }
  2023.           }
  2024. #define HGA_BLINKER_ON 0x20
  2025. #define HGA_SCREEN_ON  8
  2026.         /* Make sure that the hardware is not blanked */
  2027.         outb_p(HGA_BLINKER_ON | HGA_SCREEN_ON, 0x3b8);
  2028.       }
  2029. #endif CONFIG_HGA
  2030.  
  2031.     if (video_mem_term - video_mem_base < offset + video_screen_size)
  2032.       offset = 0;    /* strange ... */
  2033.     memcpyw((unsigned short *)(video_mem_base + offset),
  2034.         (unsigned short *) origin, video_screen_size);
  2035.     video_mem_start = video_mem_base;
  2036.     video_mem_end = video_mem_term;
  2037.     origin = video_mem_base + offset;
  2038.     scr_end = origin + video_screen_size;
  2039.     pos = origin + y*video_size_row + (x<<1);
  2040. }
  2041.  
  2042. void do_blank_screen(int nopowersave)
  2043. {
  2044.     int currcons;
  2045.  
  2046.     if (console_blanked)
  2047.         return;
  2048.  
  2049.     timer_active &= ~(1<<BLANK_TIMER);
  2050.     timer_table[BLANK_TIMER].fn = unblank_screen;
  2051.  
  2052.     /* try not to lose information by blanking, and not to waste memory */
  2053.     currcons = fg_console;
  2054.     has_scrolled = 0;
  2055.     blank__origin = __origin;
  2056.     blank_origin = origin;
  2057.     set_origin(fg_console);
  2058.     get_scrmem(fg_console);
  2059.     unblank_origin = origin;
  2060.     memsetw((void *)blank_origin, BLANK, video_mem_term-blank_origin);
  2061.     hide_cursor();
  2062.     console_blanked = fg_console + 1;
  2063.  
  2064.     if(!nopowersave)
  2065.         vesa_blank();
  2066. }
  2067.  
  2068. void do_unblank_screen(void)
  2069. {
  2070.     int currcons;
  2071.     int resetorg;
  2072.     long offset;
  2073.  
  2074.     if (!console_blanked)
  2075.         return;
  2076.     if (!vc_cons_allocated(fg_console)) {
  2077.         /* impossible */
  2078.         printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
  2079.         return;
  2080.     }
  2081.     timer_table[BLANK_TIMER].fn = blank_screen;
  2082.     if (blankinterval) {
  2083.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  2084.         timer_active |= 1<<BLANK_TIMER;
  2085.     }
  2086.  
  2087.     currcons = fg_console;
  2088.     offset = 0;
  2089.     resetorg = 0;
  2090.     if (console_blanked == fg_console + 1 && origin == unblank_origin
  2091.         && !has_scrolled) {
  2092.         /* try to restore the exact situation before blanking */
  2093.         resetorg = 1;
  2094.         offset = (blank_origin - video_mem_base)
  2095.             - (unblank_origin - video_mem_start);
  2096.     }
  2097.  
  2098.     console_blanked = 0;
  2099.     set_scrmem(fg_console, offset);
  2100.     set_origin(fg_console);
  2101.     set_cursor(fg_console);
  2102.     if (resetorg)
  2103.         __set_origin(blank__origin);
  2104.  
  2105.     vesa_unblank();
  2106. }
  2107.  
  2108. /*
  2109.  * If a blank_screen is due to a timer, then a power save is allowed.
  2110.  * If it is related to console_switching, then avoid vesa_blank().
  2111.  */
  2112. static void blank_screen(void)
  2113. {
  2114.     do_blank_screen(0);
  2115. }
  2116.  
  2117. static void unblank_screen(void)
  2118. {
  2119.     do_unblank_screen();
  2120. }
  2121.  
  2122. void update_screen(int new_console)
  2123. {
  2124.     static int lock = 0;
  2125.  
  2126.     if (new_console == fg_console || lock)
  2127.         return;
  2128.     if (!vc_cons_allocated(new_console)) {
  2129.         /* strange ... */
  2130.         printk("update_screen: tty %d not allocated ??\n", new_console+1);
  2131.         return;
  2132.     }
  2133.     lock = 1;
  2134.  
  2135.     clear_selection();
  2136.  
  2137.     if (!console_blanked)
  2138.         get_scrmem(fg_console);
  2139.     else
  2140.         console_blanked = -1;       /* no longer of the form console+1 */
  2141.     fg_console = new_console; /* this is the only (nonzero) assignment to fg_console */
  2142.                   /* consequently, fg_console will always be allocated */
  2143.     set_scrmem(fg_console, 0); 
  2144.     set_origin(fg_console);
  2145.     set_cursor(fg_console);
  2146.     set_leds();
  2147.     compute_shiftstate();
  2148.     lock = 0;
  2149. }
  2150.  
  2151. /*
  2152.  * Allocate the console screen memory.
  2153.  */
  2154. int con_open(struct tty_struct *tty, struct file * filp)
  2155. {
  2156.     unsigned int    idx;
  2157.     int i;
  2158.  
  2159.     idx = MINOR(tty->device) - tty->driver.minor_start;
  2160.     
  2161.     i = vc_allocate(idx);
  2162.     if (i)
  2163.         return i;
  2164.  
  2165.     vt_cons[idx]->vc_num = idx;
  2166.     tty->driver_data = vt_cons[idx];
  2167.     
  2168.     if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
  2169.         tty->winsize.ws_row = video_num_lines;
  2170.         tty->winsize.ws_col = video_num_columns;
  2171.     }
  2172.     return 0;
  2173. }
  2174.  
  2175.  
  2176. /*
  2177.  * PIO_FONT support.
  2178.  *
  2179.  * The font loading code goes back to the codepage package by
  2180.  * Joel Hoffman (joel@wam.umd.edu). (He reports that the original
  2181.  * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2
  2182.  * Video Systems_ by Richard Wilton. 1987.  Microsoft Press".)
  2183.  *
  2184.  * Change for certain monochrome monitors by Yury Shevchuck
  2185.  * (sizif@botik.yaroslavl.su).
  2186.  */
  2187.  
  2188. #define colourmap ((char *)0xa0000)
  2189. /* Pauline Middelink <middelin@polyware.iaf.nl> reports that we
  2190.    should use 0xA0000 for the bwmap as well.. */
  2191. #define blackwmap ((char *)0xa0000)
  2192. #define cmapsz 8192
  2193. #define seq_port_reg (0x3c4)
  2194. #define seq_port_val (0x3c5)
  2195. #define gr_port_reg (0x3ce)
  2196. #define gr_port_val (0x3cf)
  2197.  
  2198. static int set_get_font(char * arg, int set)
  2199. {
  2200. #ifdef CAN_LOAD_EGA_FONTS
  2201.     int i;
  2202.     char *charmap;
  2203.     int beg;
  2204.  
  2205.     /* no use to "load" CGA... */
  2206.  
  2207.     if (video_type == VIDEO_TYPE_EGAC) {
  2208.         charmap = colourmap;
  2209.         beg = 0x0e;
  2210.     } else if (video_type == VIDEO_TYPE_EGAM) {
  2211.         charmap = blackwmap;
  2212.         beg = 0x0a;
  2213.     } else
  2214.         return -EINVAL;
  2215.  
  2216.     i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
  2217.     if (i)
  2218.         return i;
  2219.  
  2220.     cli();
  2221.     outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
  2222.     outb_p( 0x01, seq_port_val );   /* Synchronous reset */
  2223.     outb_p( 0x02, seq_port_reg );
  2224.     outb_p( 0x04, seq_port_val );   /* CPU writes only to map 2 */
  2225.     outb_p( 0x04, seq_port_reg );
  2226.     outb_p( 0x07, seq_port_val );   /* Sequential addressing */
  2227.     outb_p( 0x00, seq_port_reg );
  2228.     outb_p( 0x03, seq_port_val );   /* Clear synchronous reset */
  2229.  
  2230.     outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
  2231.     outb_p( 0x02, gr_port_val );    /* select map 2 */
  2232.     outb_p( 0x05, gr_port_reg );
  2233.     outb_p( 0x00, gr_port_val );    /* disable odd-even addressing */
  2234.     outb_p( 0x06, gr_port_reg );
  2235.     outb_p( 0x00, gr_port_val );    /* map start at A000:0000 */
  2236.     sti();
  2237.  
  2238.     if (set)
  2239.         for (i=0; i<cmapsz ; i++)
  2240.             *(charmap+i) = get_fs_byte(arg+i);
  2241.     else
  2242.         for (i=0; i<cmapsz ; i++)
  2243.             put_fs_byte(*(charmap+i), arg+i);
  2244.  
  2245.     cli();
  2246.     outb_p( 0x00, seq_port_reg );   /* First, the sequencer */
  2247.     outb_p( 0x01, seq_port_val );   /* Synchronous reset */
  2248.     outb_p( 0x02, seq_port_reg );
  2249.     outb_p( 0x03, seq_port_val );   /* CPU writes to maps 0 and 1 */
  2250.     outb_p( 0x04, seq_port_reg );
  2251.     outb_p( 0x03, seq_port_val );   /* odd-even addressing */
  2252.     outb_p( 0x00, seq_port_reg );
  2253.     outb_p( 0x03, seq_port_val );   /* clear synchronous reset */
  2254.  
  2255.     outb_p( 0x04, gr_port_reg );    /* Now, the graphics controller */
  2256.     outb_p( 0x00, gr_port_val );    /* select map 0 for CPU */
  2257.     outb_p( 0x05, gr_port_reg );
  2258.     outb_p( 0x10, gr_port_val );    /* enable even-odd addressing */
  2259.     outb_p( 0x06, gr_port_reg );
  2260.     outb_p( beg, gr_port_val );     /* map starts at b800:0 or b000:0 */
  2261.     sti();
  2262.  
  2263.     return 0;
  2264. #else
  2265.     return -EINVAL;
  2266. #endif
  2267. }
  2268.  
  2269. /*
  2270.  * Load font into the EGA/VGA character generator. arg points to a 8192
  2271.  * byte map, 32 bytes per character. Only first H of them are used for
  2272.  * 8xH fonts (0 < H <= 32).
  2273.  */
  2274.  
  2275. int con_set_font (char *arg)
  2276. {
  2277.     hashtable_contents_valid = 0;
  2278.     return set_get_font (arg,1);
  2279. }
  2280.  
  2281. int con_get_font (char *arg)
  2282. {
  2283.     return set_get_font (arg,0);
  2284. }
  2285.