home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: Alpha / Whiteline Alpha.iso / linux / atari / source / source.lzh / atari-linux-0.01pl3 / drivers / char / console.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-16  |  40.5 KB  |  1,728 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.  * Hopefully this will be a rather complete VT102 implementation.
  19.  *
  20.  * Beeping thanks to John T Kohl.
  21.  * 
  22.  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  23.  *   Chars, and VT100 enhancements by Peter MacDonald.
  24.  *
  25.  * Copy and paste function by Andrew Haylett.
  26.  *
  27.  * 680x0 LINUX support by Arno Griffioen (arno@usn.nl)
  28.  * 680x0 doesn't have cut&paste support yet. Bit hard on a bitmapped
  29.  * screen. Have to keep some sort of second (ASCII) screen in the
  30.  * background for that. May even be used for VC's....
  31.  *
  32.  * 9-Apr-94:  Arno Griffioen: fixed scrolling and delete-char bug.
  33.  *            Scrolling code moved to amicon.c
  34.  *
  35.  * 18-Apr-94: David Carter [carter@cs.bris.ac.uk]. 680x0 LINUX modified 
  36.  *            Integrated support for new low level driver `amicon_ocs.c'
  37.  *
  38.  */
  39.  
  40. /*
  41.  *  NOTE!!! We sometimes disable and enable interrupts for a short while
  42.  * (to put a word in video IO), but this will work even for keyboard
  43.  * interrupts. We know interrupts aren't enabled when getting a keyboard
  44.  * interrupt, as we use trap-gates. Hopefully all is well.
  45.  */
  46.  
  47. /*
  48.  * Code to check for different video-cards mostly by Galen Hunt,
  49.  * <g-hunt@ee.utah.edu>
  50.  */
  51.  
  52. #include <linux/sched.h>
  53. #include <linux/timer.h>
  54. #include <linux/tty.h>
  55. #include <linux/config.h>
  56. #include <linux/kernel.h>
  57. #include <linux/string.h>
  58. #include <linux/errno.h>
  59. #include <linux/console.h>
  60. #include <linux/kd.h>
  61.  
  62. #include "vt_kern.h"
  63.  
  64. #ifdef CONFIG_SELECTION
  65. #include <linux/ctype.h>
  66.  
  67. /* Routines for selection control. */
  68. int set_selection(const int arg);
  69. int paste_selection(struct tty_struct *tty);
  70. static void clear_selection(void);
  71.  
  72. /* Variables for selection control. */
  73. #define SEL_BUFFER_SIZE TTY_BUF_SIZE
  74. static int sel_cons;
  75. static int sel_start = -1;
  76. static int sel_end;
  77. static char sel_buffer[SEL_BUFFER_SIZE] = { '\0' };
  78. #endif /* CONFIG_SELECTION */
  79.  
  80. extern void vt_init(void);
  81. extern void register_console(void (*proc)(const char *));
  82. extern void compute_shiftstate(void);
  83.  
  84. static int console_blanked = 0;
  85. static int can_do_color = 0;
  86. static int printable = 0;
  87.  
  88. struct condata vc_cons[NR_CONSOLES];
  89. struct consw *conswitchp;
  90.  
  91. #define    flags        (vc_cons[currcons].vc_flags)
  92. #define    x        (vc_cons[currcons].vc_x)
  93. #define    y        (vc_cons[currcons].vc_y)
  94. #define top        (vc_cons[currcons].vc_top)
  95. #define bottom        (vc_cons[currcons].vc_bottom)
  96. /*
  97.  * Arno:
  98.  * On the 680x0 we could have screens with different sizes (at least
  99.  * on the Amiga), so we have to store it with each console instead
  100.  * of using a global variable like the original PC code.
  101.  */
  102. #define    video_num_columns    (vc_cons[currcons].vc_cols)
  103. #define    video_num_lines        (vc_cons[currcons].vc_rows)
  104. #define    state        (vc_cons[currcons].vc_state)
  105. #define    npar        (vc_cons[currcons].vc_npar)
  106. #define    par        (vc_cons[currcons].vc_par)
  107. #define    ques        (vc_cons[currcons].vc_ques)
  108. #define    attr        (vc_cons[currcons].vc_attr)
  109. #define    saved_x        (vc_cons[currcons].vc_saved_x)
  110. #define    saved_y        (vc_cons[currcons].vc_saved_y)
  111. #define    translate    (vc_cons[currcons].vc_translate)
  112. #define    G0_charset    (vc_cons[currcons].vc_G0_charset)
  113. #define    G1_charset    (vc_cons[currcons].vc_G1_charset)
  114. #define    saved_G0    (vc_cons[currcons].vc_saved_G0)
  115. #define    saved_G1    (vc_cons[currcons].vc_saved_G1)
  116. #define    video_erase_char (vc_cons[currcons].vc_video_erase_char)    
  117. #define    decscnm        (vc_cons[currcons].vc_decscnm)
  118. #define    decom        (vc_cons[currcons].vc_decom)
  119. #define    decawm        (vc_cons[currcons].vc_decawm)
  120. #define    deccm        (vc_cons[currcons].vc_deccm)
  121. #define    decim        (vc_cons[currcons].vc_decim)
  122. #define    need_wrap    (vc_cons[currcons].vc_need_wrap)
  123. #define    color        (vc_cons[currcons].vc_color)
  124. #define    s_color        (vc_cons[currcons].vc_s_color)
  125. #define    def_color    (vc_cons[currcons].vc_def_color)
  126. #define    foreground    (color & 0x0f)
  127. #define    background    (color & 0xf0)
  128. #define    charset        (vc_cons[currcons].vc_charset)
  129. #define    s_charset    (vc_cons[currcons].vc_s_charset)
  130. #define    intensity    (vc_cons[currcons].vc_intensity)
  131. #define    underline    (vc_cons[currcons].vc_underline)
  132. #define    blink        (vc_cons[currcons].vc_blink)
  133. #define    reverse        (vc_cons[currcons].vc_reverse)
  134. #define    s_intensity    (vc_cons[currcons].vc_s_intensity)
  135. #define    s_underline    (vc_cons[currcons].vc_s_underline)
  136. #define    s_blink        (vc_cons[currcons].vc_s_blink)
  137. #define    s_reverse    (vc_cons[currcons].vc_s_reverse)
  138. #define    ulcolor        (vc_cons[currcons].vc_ulcolor)
  139. #define    halfcolor    (vc_cons[currcons].vc_halfcolor)
  140. #define    kbdmode        (vc_cons[currcons].vc_kbdmode)
  141. #define    tab_stop    (vc_cons[currcons].vc_tab_stop)
  142. #define    sw        (vc_cons[currcons].vc_sw)
  143.  
  144. #define    vcmode        (vt_cons[currcons].vc_mode)
  145. #define    vtmode        (vt_cons[currcons].vt_mode)
  146. #define    vtpid        (vt_cons[currcons].vt_pid)
  147. #define    vtnewvt        (vt_cons[currcons].vt_newvt)
  148.  
  149. #define decarm        VC_REPEAT
  150. #define decckm        VC_CKMODE
  151. #define kbdapplic    VC_APPLIC
  152. #define kbdraw        VC_RAW
  153. #define lnm        VC_CRLF
  154.  
  155. /*
  156.  * this is what the terminal answers to a ESC-Z or csi0c query.
  157.  */
  158. #define VT100ID "\033[?1;2c"
  159. #define VT102ID "\033[?6c"
  160.  
  161. static unsigned char * translations[] = {
  162. /* 8-bit Latin-1 mapped to the PC charater set: '\0' means non-printable */
  163. (unsigned char *)
  164.     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  165.     "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
  166.     " !\"#$%&'()*+,-./0123456789:;<=>?"
  167.     "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
  168.     "`abcdefghijklmnopqrstuvwxyz{|}~\0"
  169.     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  170.     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  171.     "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
  172.     "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
  173.     "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
  174.     "\376\245\376\376\376\376\231\376\350\376\376\376\232\376\376\341"
  175.     "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
  176.     "\376\244\225\242\223\376\224\366\355\227\243\226\201\376\376\230",
  177. /* vt100 graphics */
  178. (unsigned char *)
  179.     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  180.     "\0\0\0\0\0\0\0\0\0\0\376\0\0\0\0\0"
  181.     " !\"#$%&'()*+,-./0123456789:;<=>?"
  182.     "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^ "
  183.     "\004\261\007\007\007\007\370\361\007\007\331\277\332\300\305\304"
  184.     "\304\304\137\137\303\264\301\302\263\363\362\343\330\234\007\0"
  185.     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  186.     "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
  187.     "\377\255\233\234\376\235\174\025\376\376\246\256\252\055\376\376"
  188.     "\370\361\375\376\376\346\024\371\376\376\247\257\254\253\376\250"
  189.     "\376\376\376\376\216\217\222\200\376\220\376\376\376\376\376\376"
  190.     "\376\245\376\376\376\376\231\376\376\376\376\376\232\376\376\341"
  191.     "\205\240\203\376\204\206\221\207\212\202\210\211\215\241\214\213"
  192.     "\376\244\225\242\223\376\224\366\376\227\243\226\201\376\376\230",
  193. /* IBM graphics: minimal translations (BS, CR, LF, LL, SO, SI and ESC) */
  194. (unsigned char *)
  195.     "\000\001\002\003\004\005\006\007\000\011\000\013\000\000\000\000"
  196.     "\020\021\022\023\024\025\026\027\030\031\032\000\034\035\036\037"
  197.     "\040\041\042\043\044\045\046\047\050\051\052\053\054\055\056\057"
  198.     "\060\061\062\063\064\065\066\067\070\071\072\073\074\075\076\077"
  199.     "\100\101\102\103\104\105\106\107\110\111\112\113\114\115\116\117"
  200.     "\120\121\122\123\124\125\126\127\130\131\132\133\134\135\136\137"
  201.     "\140\141\142\143\144\145\146\147\150\151\152\153\154\155\156\157"
  202.     "\160\161\162\163\164\165\166\167\170\171\172\173\174\175\176\177"
  203.     "\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217"
  204.     "\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237"
  205.     "\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257"
  206.     "\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277"
  207.     "\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317"
  208.     "\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337"
  209.     "\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357"
  210.     "\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"
  211. };
  212.  
  213. #define NORM_TRANS (translations[0])
  214. #define GRAF_TRANS (translations[1])
  215. #define NULL_TRANS (translations[2])
  216.  
  217. static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
  218.                        8,12,10,14, 9,13,11,15 };
  219.  
  220. /*
  221.  * gotoxy() must verify all boundaries, because the arguments
  222.  * might also be negative. If the given position is out of
  223.  * bounds, the cursor is placed at the nearest margin.
  224.  */
  225. static void gotoxy(int currcons, int new_x, int new_y)
  226. {
  227.     int max_y;
  228.  
  229.     if (new_x < 0)
  230.         x = 0;
  231.     else
  232.         if (new_x >= video_num_columns)
  233.             x = video_num_columns - 1;
  234.         else
  235.             x = new_x;
  236.      if (decom) {
  237.         new_y += top;
  238.         max_y = bottom;
  239.     } else
  240.         max_y = video_num_lines;
  241.     if (new_y < 0)
  242.         y = 0;
  243.     else
  244.         if (new_y >= max_y)
  245.             y = max_y - 1;
  246.         else
  247.             y = new_y;
  248.     need_wrap = 0;
  249. }
  250.  
  251. static void hide_cursor(int currcons)
  252. {
  253.     sw->con_cursor(&vc_cons[currcons],CM_ERASE);
  254.     return;
  255. }
  256.  
  257. static void set_cursor(int currcons)
  258. {
  259.     if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
  260.         return;
  261.     if (deccm) {
  262.         sw->con_cursor(&vc_cons[currcons],CM_DRAW);
  263.     } else
  264.         hide_cursor(currcons);
  265.     return;
  266. }
  267.  
  268. /*
  269.  * Arno:
  270.  * Why do we need these? The keyboard code doesn't seem to do anything
  271.  * with them either...
  272.  */
  273. void scrollfront(int l)
  274. {
  275.     return;
  276. }
  277.  
  278. void scrollback(int l)
  279. {
  280.     return;
  281. }
  282.  
  283. static void scrup(int currcons, unsigned int t, unsigned int b)
  284. {
  285.     if (b > video_num_lines || t >= b)
  286.         return;
  287.  
  288. /*
  289.  * Arno:
  290.  * Scrolling has now been moved to amicon.c where it should have
  291.  * been all along.
  292.  */
  293.     sw->con_scroll(&vc_cons[currcons], t, b, SM_UP, 1);
  294.  
  295.     return;
  296.     
  297. }
  298.  
  299. static void scrdown(int currcons, unsigned int t, unsigned int b)
  300. {
  301.     if (b > video_num_lines || t >= b)
  302.         return;
  303.  
  304. /*
  305.  * Arno:
  306.  * Scrolling has now been moved to amicon.c where it should have
  307.  * been all along.
  308.  */
  309.     sw->con_scroll(&vc_cons[currcons], t, b, SM_DOWN, 1);
  310.  
  311.     return;
  312. }
  313.  
  314. static void lf(int currcons)
  315. {
  316.     if (y+1<bottom) {
  317.         y++;
  318.         return;
  319.     } else 
  320.         scrup(currcons,top,bottom);
  321.     need_wrap = 0;
  322. }
  323.  
  324. static void ri(int currcons)
  325. {
  326.     if (y>top) {
  327.         y--;
  328.         return;
  329.     } else
  330.         scrdown(currcons,top,bottom);
  331.     need_wrap = 0;
  332. }
  333.  
  334. static inline void cr(int currcons)
  335. {
  336.     need_wrap = x = 0;
  337. }
  338.  
  339. static inline void bs(int currcons)
  340. {
  341.     if (x) {
  342.         x--;
  343.         need_wrap = 0;
  344.     }
  345. }
  346.  
  347. static inline void del(int currcons)
  348. {
  349. #if 0
  350.     if (x) {
  351.         if (!need_wrap) {    /* this is not the right condition */
  352.             x--;
  353.         }
  354.         need_wrap = 0;
  355.     }
  356. #endif
  357. }
  358.  
  359. static void csi_J(int currcons, int vpar)
  360. {
  361.     switch (vpar) {
  362.         case 0:    /* erase from cursor to end of display */
  363.             /* 680x0 do in two stages */
  364.             sw->con_clear(&vc_cons[currcons],y,x,1,video_num_columns-x);
  365.             sw->con_clear(&vc_cons[currcons],y+1,0,video_num_lines-y-1, video_num_columns);
  366.             break;
  367.         case 1:    /* erase from start to cursor */
  368.             /* 680x0 do in two stages */
  369.             sw->con_clear(&vc_cons[currcons],0,0,y, video_num_columns);
  370.             sw->con_clear(&vc_cons[currcons],y,0,1,x);
  371.             break;
  372.         case 2: /* erase whole display */
  373.             sw->con_clear(&vc_cons[currcons],0,0,video_num_lines, video_num_columns);
  374.             break;
  375.         default:
  376.             return;
  377.     }
  378.     need_wrap = 0;
  379. }
  380.  
  381. static void csi_K(int currcons, int vpar)
  382. {
  383.     switch (vpar) {
  384.         case 0:    /* erase from cursor to end of line */
  385.             sw->con_clear(&vc_cons[currcons],y,x,1,video_num_columns-x);
  386.             break;
  387.         case 1:    /* erase from start of line to cursor */
  388.             sw->con_clear(&vc_cons[currcons],y,0,1,x);
  389.             break;
  390.         case 2: /* erase whole line */
  391.             sw->con_clear(&vc_cons[currcons],y,0,1,video_num_columns);
  392.             break;
  393.         default:
  394.             return;
  395.     }
  396.     need_wrap = 0;
  397. }
  398.  
  399. /*
  400.  *  I hope this works. The monochrome part is untested.
  401.  */
  402.  
  403. /*
  404.  * Arno: 
  405.  * On 680x0 attributes are currently not used. This piece of code
  406.  * seems hardware independent, but uses the EGA/VGA way of representing
  407.  * attributes. 
  408.  * TODO: modify for 680x0 and add attribute processing to putc code.
  409.  */
  410. static void update_attr(int currcons)
  411. {
  412.     attr = color;
  413.     if (can_do_color) {
  414.         if (underline)
  415.             attr = (attr & 0xf0) | ulcolor;
  416.         else if (intensity == 0)
  417.             attr = (attr & 0xf0) | halfcolor;
  418.     }
  419.     if (reverse ^ decscnm)
  420.         attr = (attr & 0x88) | (((attr >> 4) | (attr << 4)) & 0x77);
  421.     if (blink)
  422.         attr ^= 0x80;
  423.     if (intensity == 2)
  424.         attr ^= 0x08;
  425.     if (!can_do_color) {
  426.         if (underline)
  427.             attr = (attr & 0xf8) | 0x01;
  428.         else if (intensity == 0)
  429.             attr = (attr & 0xf0) | 0x08;
  430.     }
  431.     if (decscnm)
  432.         video_erase_char = ((color & 0x88) | (((color >> 4) |
  433.             (color << 4)) & 0x77) << 8) | ' ';
  434.     else
  435.         video_erase_char = (color << 8) | ' ';
  436. }
  437.  
  438. static void default_attr(int currcons)
  439. {
  440.     intensity = 1;
  441.     underline = 0;
  442.     reverse = 0;
  443.     blink = 0;
  444.     color = def_color;
  445. }
  446.  
  447. static void csi_m(int currcons)
  448. {
  449.     int i;
  450.  
  451.     for (i=0;i<=npar;i++)
  452.         switch (par[i]) {
  453.             case 0:    /* all attributes off */
  454.                 default_attr(currcons);
  455.                 break;
  456.             case 1:
  457.                 intensity = 2;
  458.                 break;
  459.             case 2:
  460.                 intensity = 0;
  461.                 break;
  462.             case 4:
  463.                 underline = 1;
  464.                 break;
  465.             case 5:
  466.                 blink = 1;
  467.                 break;
  468.             case 7:
  469.                 reverse = 1;
  470.                 break;
  471.             case 21:
  472.             case 22:
  473.                 intensity = 1;
  474.                 break;
  475.             case 24:
  476.                 underline = 0;
  477.                 break;
  478.             case 25:
  479.                 blink = 0;
  480.                 break;
  481.             case 27:
  482.                 reverse = 0;
  483.                 break;
  484.             case 39:
  485.                 color = (def_color & 0x0f) | background;
  486.                 break;
  487.             case 49:
  488.                 color = (def_color & 0xf0) | foreground;
  489.                 break;
  490.             default:
  491.                 if (par[i] >= 30 && par[i] <= 37)
  492.                     color = color_table[par[i]-30]
  493.                         | background; 
  494.                 else if (par[i] >= 40 && par[i] <= 47)
  495.                     color = (color_table[par[i]-40]<<4)
  496.                         | foreground;
  497.                 break;
  498.         }
  499.     update_attr(currcons);
  500. }
  501.  
  502. static void respond_string(char * p, int currcons, struct tty_struct * tty)
  503. {
  504.     while (*p) {
  505.         put_tty_queue(*p, &tty->read_q);
  506.         p++;
  507.     }
  508.     TTY_READ_FLUSH(tty);
  509. }
  510.  
  511. static void respond_num(unsigned int n, int currcons, struct tty_struct * tty)
  512. {
  513.     char buff[3];
  514.     int i = 0;
  515.  
  516.     do {
  517.         buff[i++] = (n%10)+'0';
  518.         n /= 10;
  519.     } while(n && i < 3);    /* We'll take no chances */
  520.     while (i--) {
  521.         put_tty_queue(buff[i], &tty->read_q);
  522.     }
  523.     /* caller must flush */
  524. }
  525.  
  526. static void cursor_report(int currcons, struct tty_struct * tty)
  527. {
  528.     put_tty_queue('\033', &tty->read_q);
  529.     put_tty_queue('[', &tty->read_q);
  530.     respond_num(y + (decom ? top+1 : 1), currcons, tty);
  531.     put_tty_queue(';', &tty->read_q);
  532.     respond_num(x+1, currcons, tty);
  533.     put_tty_queue('R', &tty->read_q);
  534.     TTY_READ_FLUSH(tty);
  535. }
  536.  
  537. static inline void status_report(int currcons, struct tty_struct * tty)
  538. {
  539.     respond_string("\033[0n", currcons, tty);    /* Terminal ok */
  540. }
  541.  
  542. static inline void respond_ID(int currcons, struct tty_struct * tty)
  543. {
  544.     respond_string(VT102ID, currcons, tty);
  545. }
  546.  
  547. #if 0
  548. /* 
  549.  * Arno:
  550.  * Not nice on a bit-mapped screen :-(
  551.  * Won't implement it for now... Don't think anyone will care..
  552.  */
  553.  
  554. static void invert_screen(int currcons) {
  555.     return;
  556. }
  557. #endif
  558.  
  559. static void set_mode(int currcons, int on_off)
  560. {
  561.     int i;
  562.  
  563.     for (i=0; i<=npar; i++)
  564.         if (ques) switch(par[i]) {    /* DEC private modes set/reset */
  565.             case 1:            /* Cursor keys send ^[Ox/^[[x */
  566.             /* Arno: Dunno about KBD stuff...
  567.              * Just ignire it for the moment.
  568.                 if (on_off)
  569.                     set_kbd(decckm);
  570.                 else
  571.                     clr_kbd(decckm); 
  572.             */
  573.                 break;
  574.             case 3:    /* 80/132 mode switch unimplemented */
  575.                 csi_J(currcons,2);
  576.                 gotoxy(currcons,0,0);
  577.                 break;
  578.             case 5:            /* Inverted screen on/off */
  579.                 if (decscnm != on_off) {
  580.                     decscnm = on_off;
  581.                     /*invert_screen(currcons);*/
  582.                     update_attr(currcons);
  583.                 }
  584.                 break;
  585.             case 6:            /* Origin relative/absolute */
  586.                 decom = on_off;
  587.                 gotoxy(currcons,0,0);
  588.                 break;
  589.             case 7:            /* Autowrap on/off */
  590.                 decawm = on_off;
  591.                 break;
  592.             case 8:            /* Autorepeat on/off */
  593.                 /* 680x0: no kbd handling?
  594.                 if (on_off)
  595.                     set_kbd(decarm);
  596.                 else
  597.                     clr_kbd(decarm);
  598.                 */
  599.                 break;
  600.             case 25:        /* Cursor on/off */
  601.                 deccm = on_off;
  602.                 set_cursor(currcons);
  603.                 break;
  604.         } else switch(par[i]) {        /* ANSI modes set/reset */
  605.             case 4:            /* Insert Mode on/off */
  606.                 decim = on_off;
  607.                 break;
  608.             case 20:        /* Lf, Enter == CrLf/Lf */
  609.                 /* 680x0: no kkbd handling?
  610.                 if (on_off)
  611.                     set_kbd(lnm);
  612.                 else
  613.                     clr_kbd(lnm);
  614.                 */
  615.                 break;
  616.         }
  617. }
  618.  
  619. static void setterm_command(int currcons)
  620. {
  621.     switch(par[0]) {
  622.         case 1:    /* set color for underline mode */
  623.             if (can_do_color && par[1] < 16) {
  624.                 ulcolor = color_table[par[1]];
  625.                 if (underline)
  626.                     update_attr(currcons);
  627.             }
  628.             break;
  629.         case 2:    /* set color for half intensity mode */
  630.             if (can_do_color && par[1] < 16) {
  631.                 halfcolor = color_table[par[1]];
  632.                 if (intensity == 0)
  633.                     update_attr(currcons);
  634.             }
  635.             break;
  636.         case 8:    /* store colors as defaults */
  637.             def_color = attr;
  638.             default_attr(currcons);
  639.             update_attr(currcons);
  640.             break;
  641.         case 9:    /* set blanking interval */
  642.             /* Arno:
  643.              * Well... How does blanking work? Can it
  644.              * function in the 680x0 kernel? 
  645.              * blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
  646.              */
  647.             break;
  648.     }
  649. }
  650.  
  651. static void insert_char(int currcons)
  652. {
  653.     /* Arno:
  654.      * Move the remainder of the line (-1 character) one spot to the right
  655.      */
  656.     sw->con_bmove(&vc_cons[currcons],y,x,y,x+1,1,(video_num_columns-x-1));
  657.     /*
  658.      * Print the erase char on the current position
  659.      */
  660.     sw->con_putc(&vc_cons[currcons],(video_erase_char & 0x00ff),y,x,DM_COPY);
  661.  
  662.     need_wrap = 0;
  663. }
  664.  
  665. static void insert_line(int currcons)
  666. {
  667.     scrdown(currcons,y,bottom);
  668.     need_wrap = 0;
  669. }
  670.  
  671. static void delete_char(int currcons)
  672. {
  673.     /* Arno
  674.      * Move the remainder of the line one spot to the left 
  675.      */
  676.  
  677.     sw->con_bmove(&vc_cons[currcons],y,x+1,y,x,1,(video_num_columns-x-1));
  678.  
  679.     /* 
  680.      * Print the erase char at the end of the line to remove any 
  681.      * remaining junk
  682.      */
  683.     sw->con_putc(&vc_cons[currcons],(video_erase_char & 0x00ff),y,video_num_columns-1,DM_COPY);
  684.  
  685.     need_wrap = 0;
  686. }
  687.  
  688. static void delete_line(int currcons)
  689. {
  690.     scrup(currcons,y,bottom);
  691.     need_wrap = 0;
  692. }
  693.  
  694. static void csi_at(int currcons, unsigned int nr)
  695. {
  696.     if (nr > video_num_columns)
  697.         nr = video_num_columns;
  698.     else if (!nr)
  699.         nr = 1;
  700.     while (nr--)
  701.         insert_char(currcons);
  702. }
  703.  
  704. static void csi_L(int currcons, unsigned int nr)
  705. {
  706.     if (nr > video_num_lines)
  707.         nr = video_num_lines;
  708.     else if (!nr)
  709.         nr = 1;
  710.     while (nr--)
  711.         insert_line(currcons);
  712. }
  713.  
  714. static void csi_P(int currcons, unsigned int nr)
  715. {
  716.     if (nr > video_num_columns)
  717.         nr = video_num_columns;
  718.     else if (!nr)
  719.         nr = 1;
  720.     while (nr--)
  721.         delete_char(currcons);
  722. }
  723.  
  724. static void csi_M(int currcons, unsigned int nr)
  725. {
  726.     if (nr > video_num_lines)
  727.         nr = video_num_lines;
  728.     else if (!nr)
  729.         nr=1;
  730.     while (nr--)
  731.         delete_line(currcons);
  732. }
  733.  
  734. static void save_cur(int currcons)
  735. {
  736.     saved_x        = x;
  737.     saved_y        = y;
  738.     s_intensity    = intensity;
  739.     s_underline    = underline;
  740.     s_blink        = blink;
  741.     s_reverse    = reverse;
  742.     s_charset    = charset;
  743.     s_color        = color;
  744.     saved_G0    = G0_charset;
  745.     saved_G1    = G1_charset;
  746. }
  747.  
  748. static void restore_cur(int currcons)
  749. {
  750.     gotoxy(currcons,saved_x,saved_y);
  751.     intensity    = s_intensity;
  752.     underline    = s_underline;
  753.     blink        = s_blink;
  754.     reverse        = s_reverse;
  755.     charset        = s_charset;
  756.     color        = s_color;
  757.     G0_charset    = saved_G0;
  758.     G1_charset    = saved_G1;
  759.     translate    = charset ? G1_charset : G0_charset;
  760.     update_attr(currcons);
  761.     need_wrap = 0;
  762. }
  763.  
  764. enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey, 
  765.     EShash, ESsetG0, ESsetG1, ESignore };
  766.  
  767. static void reset_terminal(int currcons, int do_clear)
  768. {
  769.     top        = 0;
  770.     bottom        = video_num_lines;
  771.     state        = ESnormal;
  772.     ques        = 0;
  773.     translate    = NORM_TRANS;
  774.     G0_charset    = NORM_TRANS;
  775.     G1_charset    = GRAF_TRANS;
  776.     charset        = 0;
  777.     need_wrap    = 0;
  778.  
  779.     decscnm        = 0;
  780.     decom        = 0;
  781.     decawm        = 1;
  782.     deccm        = 1;
  783.     decim        = 0;
  784.  
  785. #if 0
  786. /* 
  787.  * Arno:
  788.  * Here's the kbd stuff again.. What part is PC specific?
  789.  */
  790.     set_kbd(decarm);
  791.     clr_kbd(decckm);
  792.     clr_kbd(kbdapplic);
  793.     clr_kbd(lnm);
  794.     kbd_table[currcons].flags =
  795.         (kbd_table[currcons].flags & ~LED_MASK) |
  796.         (kbd_table[currcons].default_flags & LED_MASK);
  797.     kbdmode        = 0;
  798.     set_leds();
  799. #endif
  800.  
  801.     default_attr(currcons);
  802.     update_attr(currcons);
  803.  
  804.     tab_stop[0]    = 0x01010100;
  805.     tab_stop[1]    =
  806.     tab_stop[2]    =
  807.     tab_stop[3]    =
  808.     tab_stop[4]    = 0x01010101;
  809.  
  810.     if (do_clear) {
  811.         gotoxy(currcons,0,0);
  812.         csi_J(currcons,2);
  813.         save_cur(currcons);
  814.     }
  815. }
  816.  
  817. void con_write(struct tty_struct * tty)
  818. {
  819.     int c = 0;
  820.     ushort buf_flag = 0;    /* DPC: Needed by putcs() */
  821.     unsigned int currcons;
  822.  
  823.     wake_up_interruptible(&tty->write_q.proc_list);
  824.     currcons = tty->line - 1;
  825.     if (currcons >= NR_CONSOLES) {
  826.         printk("con_write: illegal tty (%d)\n", currcons);
  827.         return;
  828.     }
  829. #ifdef CONFIG_SELECTION
  830.     /* clear the selection as soon as any characters are to be written
  831.        out on the console holding the selection. */
  832.     if (!EMPTY(&tty->write_q) && currcons == sel_cons)
  833.         clear_selection();
  834. #endif /* CONFIG_SELECTION */
  835.     /* Arno:
  836.      * huh? What's this?
  837.      * disable_bh(KEYBOARD_BH);
  838.      */
  839.  
  840.     while (!tty->stopped &&
  841.                (c = (buf_flag) ? c : get_tty_queue(&tty->write_q)) >= 0) {
  842.                 static char buf[256]; /* DPC: XXX Limits line LENGTH XXX */
  843.                 buf_flag = 0;
  844.  
  845.         if (state == ESnormal && translate[c]) {
  846.             if (need_wrap) {
  847.                 cr(currcons);
  848.                 lf(currcons);
  849.             }
  850.  
  851.                         /* DPC: 1994-04-12
  852.                          *   Speed up overstrike mode, using new putcs.
  853.                          *
  854.                          * P.S. I hate 8 spaces per tab! Use Emacs!
  855.                         */
  856.  
  857.                         if (!decim) { 
  858.                             char   *p     = buf;
  859.                             ushort count  = 0;
  860.                             ushort nextx  = x;
  861.                             ushort cols   = video_num_columns;
  862.                             
  863.                             *p++ = c;
  864.  
  865.                             if (nextx == cols) {
  866.                                 sw->con_putc(&vc_cons[currcons],
  867.                                              *buf, y, x, DM_COPY);
  868.                                 need_wrap = decawm;
  869.                                 continue;
  870.                             }
  871.  
  872.                             /* TAB TAB TAB - Arghh!!!! */
  873.  
  874.                             while ((c=get_tty_queue(&tty->write_q)) >= 0 &&
  875.                                    translate[c] && ++nextx < cols)
  876.                                 *p++ = c;
  877.  
  878.                             count = p-buf;
  879.                             sw->con_putcs(&vc_cons[currcons],
  880.                                           buf, count, y, x, DM_COPY);
  881.                             if (nextx == cols) {
  882.                                 x         = cols-1;
  883.                                 need_wrap = decawm;
  884.                             } else
  885.                                 x += count;
  886.                             buf_flag = 1;
  887.                             continue;
  888.                         }
  889.  
  890.                         /* DPC: End of putcs support */
  891.  
  892.             if (decim)
  893.                 insert_char(currcons);
  894.             /* Arno:
  895.              * Translation table not really correct
  896.              * for 680x0 charset. No translation yet.
  897.              * TODO: build VT100 charset and enable translation.
  898.              */
  899.  
  900.             /*c = translate[c];*/
  901.  
  902.             /* Arno:
  903.              * 680x0: ignore attributes for now, just 
  904.              * print character.
  905.              */
  906.             sw->con_putc(&vc_cons[currcons],c,y,x,DM_COPY);
  907.             if (x == video_num_columns - 1)
  908.                 need_wrap = decawm;
  909.             else {
  910.                 x++;
  911.             }
  912.             continue;
  913.         }
  914.  
  915.         /*
  916.          *  Control characters can be used in the _middle_
  917.          *  of an escape sequence.
  918.          */
  919.         switch (c) {
  920.             case 7:
  921.                 kd_mksound(0x637, HZ/8);
  922.                 continue;
  923.             case 8:
  924.                 bs(currcons);
  925.                 continue;
  926.             case 9:
  927.                 while (x < video_num_columns - 1) {
  928.                     x++;
  929.                     if (tab_stop[x >> 5] & (1 << (x & 31)))
  930.                         break;
  931.                 }
  932.                 continue;
  933.             case 10: case 11: case 12:
  934.                 lf(currcons);
  935.                 /* KBD stuff...
  936.                 if (!is_kbd(lnm))
  937.                     continue;
  938.                 */
  939.             case 13:
  940.                 cr(currcons);
  941.                 continue;
  942.             case 14:
  943.                 charset = 1;
  944.                 translate = G1_charset;
  945.                 continue;
  946.             case 15:
  947.                 charset = 0;
  948.                 translate = G0_charset;
  949.                 continue;
  950.             case 24: case 26:
  951.                 state = ESnormal;
  952.                 continue;
  953.             case 27:
  954.                 state = ESesc;
  955.                 continue;
  956.             case 127:
  957.                 del(currcons);
  958.                 continue;
  959.             case 128+27:
  960.                 state = ESsquare;
  961.                 continue;
  962.         }
  963.         switch(state) {
  964.             case ESesc:
  965.                 state = ESnormal;
  966.                 switch (c) {
  967.                   case '[':
  968.                     state = ESsquare;
  969.                     continue;
  970.                   case 'E':
  971.                     cr(currcons);
  972.                     lf(currcons);
  973.                     continue;
  974.                   case 'M':
  975.                     ri(currcons);
  976.                     continue;
  977.                   case 'D':
  978.                     lf(currcons);
  979.                     continue;
  980.                   case 'H':
  981.                     tab_stop[x >> 5] |= (1 << (x & 31));
  982.                     continue;
  983.                   case 'Z':
  984.                     respond_ID(currcons,tty);
  985.                     continue;
  986.                   case '7':
  987.                     save_cur(currcons);
  988.                     continue;
  989.                   case '8':
  990.                     restore_cur(currcons);
  991.                     continue;
  992.                   case '(':
  993.                     state = ESsetG0;
  994.                     continue;
  995.                   case ')':
  996.                     state = ESsetG1;
  997.                     continue;
  998.                   case '#':
  999.                     state = EShash;
  1000.                     continue;
  1001.                   case 'c':
  1002.                     reset_terminal(currcons,1);
  1003.                     continue;
  1004.                   case '>':  /* Numeric keypad */
  1005.                     /* ignore kbd stuff
  1006.                     clr_kbd(kbdapplic);
  1007.                     */
  1008.                     continue;
  1009.                   case '=':  /* Appl. keypad */
  1010.                     /* ignore kbd stuff
  1011.                     set_kbd(kbdapplic);
  1012.                     */
  1013.                      continue;
  1014.                 }    
  1015.                 continue;
  1016.             case ESsquare:
  1017.                 for(npar = 0 ; npar < NPAR ; npar++)
  1018.                     par[npar] = 0;
  1019.                 npar = 0;
  1020.                 state = ESgetpars;
  1021.                 if (c == '[') { /* Function key */
  1022.                     state=ESfunckey;
  1023.                     continue;
  1024.                 }
  1025.                 ques = (c=='?');
  1026.                 if (ques)
  1027.                     continue;
  1028.             case ESgetpars:
  1029.                 if (c==';' && npar<NPAR-1) {
  1030.                     npar++;
  1031.                     continue;
  1032.                 } else if (c>='0' && c<='9') {
  1033.                     par[npar] *= 10;
  1034.                     par[npar] += c-'0';
  1035.                     continue;
  1036.                 } else state=ESgotpars;
  1037.             case ESgotpars:
  1038.                 state = ESnormal;
  1039.                 switch(c) {
  1040.                     case 'h':
  1041.                         set_mode(currcons,1);
  1042.                         continue;
  1043.                     case 'l':
  1044.                         set_mode(currcons,0);
  1045.                         continue;
  1046.                     case 'n':
  1047.                         if (!ques)
  1048.                             if (par[0] == 5)
  1049.                                 status_report(currcons,tty);
  1050.                             else if (par[0] == 6)
  1051.                                 cursor_report(currcons,tty);
  1052.                         continue;
  1053.                 }
  1054.                 if (ques) {
  1055.                     ques = 0;
  1056.                     continue;
  1057.                 }
  1058.                 switch(c) {
  1059.                     case 'G': case '`':
  1060.                         if (par[0]) par[0]--;
  1061.                         gotoxy(currcons,par[0],y);
  1062.                         continue;
  1063.                     case 'A':
  1064.                         if (!par[0]) par[0]++;
  1065.                         gotoxy(currcons,x,y-par[0]);
  1066.                         continue;
  1067.                     case 'B': case 'e':
  1068.                         if (!par[0]) par[0]++;
  1069.                         gotoxy(currcons,x,y+par[0]);
  1070.                         continue;
  1071.                     case 'C': case 'a':
  1072.                         if (!par[0]) par[0]++;
  1073.                         gotoxy(currcons,x+par[0],y);
  1074.                         continue;
  1075.                     case 'D':
  1076.                         if (!par[0]) par[0]++;
  1077.                         gotoxy(currcons,x-par[0],y);
  1078.                         continue;
  1079.                     case 'E':
  1080.                         if (!par[0]) par[0]++;
  1081.                         gotoxy(currcons,0,y+par[0]);
  1082.                         continue;
  1083.                     case 'F':
  1084.                         if (!par[0]) par[0]++;
  1085.                         gotoxy(currcons,0,y-par[0]);
  1086.                         continue;
  1087.                     case 'd':
  1088.                         if (par[0]) par[0]--;
  1089.                         gotoxy(currcons,x,par[0]);
  1090.                         continue;
  1091.                     case 'H': case 'f':
  1092.                         if (par[0]) par[0]--;
  1093.                         if (par[1]) par[1]--;
  1094.                         gotoxy(currcons,par[1],par[0]);
  1095.                         continue;
  1096.                     case 'J':
  1097.                         csi_J(currcons,par[0]);
  1098.                         continue;
  1099.                     case 'K':
  1100.                         csi_K(currcons,par[0]);
  1101.                         continue;
  1102.                     case 'L':
  1103.                         csi_L(currcons,par[0]);
  1104.                         continue;
  1105.                     case 'M':
  1106.                         csi_M(currcons,par[0]);
  1107.                         continue;
  1108.                     case 'P':
  1109.                         csi_P(currcons,par[0]);
  1110.                         continue;
  1111.                     case 'c':
  1112.                         if (!par[0])
  1113.                             respond_ID(currcons,tty);
  1114.                         continue;
  1115.                     case 'g':
  1116.                         if (!par[0])
  1117.                             tab_stop[x >> 5] &= ~(1 << (x & 31));
  1118.                         else if (par[0] == 3) {
  1119.                             tab_stop[0] =
  1120.                             tab_stop[1] =
  1121.                             tab_stop[2] =
  1122.                             tab_stop[3] =
  1123.                             tab_stop[4] = 0;
  1124.                         }
  1125.                         continue;
  1126.                     case 'm':
  1127.                         csi_m(currcons);
  1128.                         continue;
  1129.                     case 'r':
  1130.                         if (!par[0])
  1131.                             par[0]++;
  1132.                         if (!par[1])
  1133.                             par[1] = video_num_lines;
  1134.                         /* Minimum allowed region is 2 lines */
  1135.                         if (par[0] < par[1] &&
  1136.                             par[1] <= video_num_lines) {
  1137.                             top=par[0]-1;
  1138.                             bottom=par[1];
  1139.                             gotoxy(currcons,0,0);
  1140.                         }
  1141.                         continue;
  1142.                     case 's':
  1143.                         save_cur(currcons);
  1144.                         continue;
  1145.                     case 'u':
  1146.                         restore_cur(currcons);
  1147.                         continue;
  1148.                     case '@':
  1149.                         csi_at(currcons,par[0]);
  1150.                         continue;
  1151.                     case ']': /* setterm functions */
  1152.                         setterm_command(currcons);
  1153.                         continue;
  1154.                 }
  1155.                 continue;
  1156.             case ESfunckey:
  1157.                 state = ESnormal;
  1158.                 continue;
  1159.             case EShash:
  1160.                 state = ESnormal;
  1161.                 if (c == '8') {
  1162.                     /* DEC screen alignment test. kludge :-) */
  1163.                     video_erase_char =
  1164.                         (video_erase_char & 0x00ff) | 'E';
  1165.                     /* Arno:
  1166.                      * Doesn't work, because csi_J(c,2)
  1167.                      * calls con_clear and doesn't print
  1168.                      * the erase char..
  1169.                      */
  1170.                     csi_J(currcons, 2);
  1171.                     video_erase_char =
  1172.                         (video_erase_char & 0x00ff) | ' ';
  1173.                 }
  1174.                 continue;
  1175.             case ESsetG0:
  1176.                 if (c == '0')
  1177.                     G0_charset = GRAF_TRANS;
  1178.                 else if (c == 'B')
  1179.                     G0_charset = NORM_TRANS;
  1180.                 else if (c == 'U')
  1181.                     G0_charset = NULL_TRANS;
  1182.                 if (charset == 0)
  1183.                     translate = G0_charset;
  1184.                 state = ESnormal;
  1185.                 continue;
  1186.             case ESsetG1:
  1187.                 if (c == '0')
  1188.                     G1_charset = GRAF_TRANS;
  1189.                 else if (c == 'B')
  1190.                     G1_charset = NORM_TRANS;
  1191.                 else if (c == 'U')
  1192.                     G1_charset = NULL_TRANS;
  1193.                 if (charset == 1)
  1194.                     translate = G1_charset;
  1195.                 state = ESnormal;
  1196.                 continue;
  1197.             default:
  1198.                 state = ESnormal;
  1199.         }
  1200.     }
  1201.     if (vcmode != KD_GRAPHICS)
  1202.         set_cursor(currcons);
  1203.     /*
  1204.     enable_bh(KEYBOARD_BH);
  1205.     */
  1206. }
  1207.  
  1208. void do_keyboard_interrupt(void)
  1209. {
  1210.     TTY_READ_FLUSH(TTY_TABLE(0));
  1211. #if 0
  1212. /* 
  1213.  * Arno:
  1214.  * No blanking stuff yet. 
  1215.  * Haven't looked at it..
  1216.  */
  1217.     timer_active &= ~(1<<BLANK_TIMER);
  1218.     if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
  1219.         return;
  1220.     if (console_blanked) {
  1221.         timer_table[BLANK_TIMER].expires = 0;
  1222.         timer_active |= 1<<BLANK_TIMER;
  1223.     } else if (blankinterval) {
  1224.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  1225.         timer_active |= 1<<BLANK_TIMER;
  1226.     }
  1227. #endif
  1228. }
  1229.  
  1230. #if 0
  1231. /* DPC: New version of console_print using putcs */
  1232.  
  1233. void console_print(const char * b)
  1234. {
  1235.    int currcons = fg_console;
  1236.    unsigned char c;
  1237.    const char *start = b;
  1238.    ushort count      = 0;
  1239.    ushort myx        = x;
  1240.    ushort cols       = video_num_columns;
  1241.  
  1242.    if (!printable || currcons<0 || currcons>=NR_CONSOLES)
  1243.       return;
  1244.  
  1245.    /* Contrived structure to try and emulate original need_wrap behaviour
  1246.     * Problems caused when we have need_wrap set on '\n' character */
  1247.    
  1248.    while ((c = *(b++)) != 0) {
  1249.        if (c == 10 || c == 13 || need_wrap) {
  1250.            if ((count = b - start - 1) > 0)
  1251.                sw->con_putcs(&vc_cons[currcons], start, count ,
  1252.                              y, x, DM_COPY);
  1253.            if (c != 13)
  1254.                lf(currcons);
  1255.            cr(currcons);
  1256.  
  1257.            if (c == 10 || c == 13) {
  1258.                myx = x ; start = b;    /* New line, starting afresh */
  1259.            } else {
  1260.                myx = x ; start = b-1;  /* Other need_wrap => got one */
  1261.            }
  1262.        } else if (myx++ >= cols)
  1263.            need_wrap = 1;
  1264.    }
  1265.  
  1266.    if ((count = b - start -1) > 0) {
  1267.        sw->con_putcs(&vc_cons[currcons], start, count ,
  1268.                      y, x, DM_COPY);
  1269.        x += count;
  1270.        if (x >= cols) {
  1271.            need_wrap = 1; x = cols;
  1272.        }
  1273.    }
  1274.  
  1275.    set_cursor(currcons);
  1276. }
  1277. #endif
  1278.  
  1279. #if 1   /* Arno's old putc based version */
  1280. void console_print(const char * b)
  1281. {
  1282.     int currcons = fg_console;
  1283.     unsigned char c;
  1284.  
  1285.     if (!printable || currcons<0 || currcons>=NR_CONSOLES)
  1286.         return;
  1287.     while ((c = *(b++)) != 0) {
  1288.         if (c == 10 || c == 13 || need_wrap) {
  1289.             if (c != 13)
  1290.                 lf(currcons);
  1291.             cr(currcons);
  1292.             if (c == 10 || c == 13)
  1293.                 continue;
  1294.         }
  1295.         sw->con_putc(&vc_cons[currcons],c,y,x,DM_COPY);
  1296.         if (x == video_num_columns - 1) {
  1297.             need_wrap = 1;
  1298.             continue;
  1299.         }
  1300.         x++;
  1301.     }
  1302.     set_cursor(currcons);
  1303.     return;
  1304.     if (vt_cons[fg_console].vc_mode == KD_GRAPHICS)
  1305.         return;
  1306. #if 0
  1307.     timer_active &= ~(1<<BLANK_TIMER);
  1308.     if (console_blanked) {
  1309.         timer_table[BLANK_TIMER].expires = 0;
  1310.         timer_active |= 1<<BLANK_TIMER;
  1311.     } else if (blankinterval) {
  1312.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  1313.         timer_active |= 1<<BLANK_TIMER;
  1314.     }
  1315. #endif
  1316. }
  1317. #endif
  1318.  
  1319.  
  1320. /*
  1321.  *  long con_init(long);
  1322.  *
  1323.  * This routine initalizes console interrupts, and does nothing
  1324.  * else. If you want the screen to clear, call tty_write with
  1325.  * the appropriate escape-sequece.
  1326.  *
  1327.  * Reads the information preserved by setup.s to determine the current display
  1328.  * type and sets everything accordingly.
  1329.  */
  1330. long con_init(long kmem_start)
  1331. {
  1332.     char *display_desc = "????";
  1333.     unsigned int currcons = 0;
  1334.  
  1335. /* 
  1336.  * Arno:
  1337.  * We really should move this to sw->con_init or some other platform
  1338.  * specific init code instead of hard-coding this...
  1339.  */
  1340.     display_desc="ECS";
  1341.     can_do_color=1;
  1342.  
  1343.     sw=conswitchp;
  1344.  
  1345. #if 0
  1346. /* 
  1347.  * Arno:
  1348.  * first working INIT code... 'Borrowed' from original 680x0 console
  1349.  * code.. (hi Hamish!)
  1350.  */
  1351.     kmem_start = sw->con_init(&vc_cons[currcons],kmem_start);
  1352.     sw->con_cursor(&vc_cons[currcons], CM_DRAW);
  1353.     reset_terminal(currcons, currcons);
  1354.     register_console(console_print);
  1355. #endif
  1356.  
  1357. #if 0
  1358.     timer_table[BLANK_TIMER].fn = blank_screen;
  1359.     timer_table[BLANK_TIMER].expires = 0;
  1360.     if (blankinterval) {
  1361.         timer_table[BLANK_TIMER].expires = jiffies+blankinterval;
  1362.         timer_active |= 1<<BLANK_TIMER;
  1363.     }
  1364. #endif
  1365.     kmem_start = sw->con_init(&vc_cons[currcons],kmem_start);
  1366.  
  1367. #if 0
  1368. /* 
  1369.  * Arno:
  1370.  * Strange things happen when more than 1 console is inited... 
  1371.  * 
  1372.  * TODO: extend low-level code for multi-console support.
  1373.  * Question: how are we going to do VC's? Save/restore bitplanes/copperlists
  1374.  * etc.? Can get memory expensive with 4 bitplane screens (in the future..)
  1375.  */
  1376.     for (currcons = 0; currcons<NR_CONSOLES; currcons++) {
  1377.         vcmode        = KD_TEXT;
  1378.         vtmode.mode    = VT_AUTO;
  1379.         vtmode.waitv    = 0;
  1380.         vtmode.relsig    = 0;
  1381.         vtmode.acqsig    = 0;
  1382.         vtmode.frsig    = 0;
  1383.         vtpid        = -1;
  1384.         vtnewvt        = -1;
  1385. /*
  1386.         clr_kbd(kbdraw);
  1387. */
  1388.         def_color    = 0x07;   /* white */
  1389.         ulcolor        = 0x0f;   /* bold white */
  1390.         halfcolor    = 0x08;   /* grey */
  1391.         reset_terminal(currcons, currcons);
  1392.  
  1393.  
  1394.     }
  1395. #endif
  1396.  
  1397.  
  1398.     currcons = fg_console = 0;
  1399.  
  1400.     def_color    = 0x07;   /* white */
  1401.     ulcolor        = 0x0f;   /* bold white */
  1402.     halfcolor    = 0x08;   /* grey */
  1403.     reset_terminal(currcons, currcons);
  1404.  
  1405.     gotoxy(currcons,0,0);
  1406.     save_cur(currcons);
  1407.     gotoxy(currcons,0,0);
  1408. /*
  1409.     gotoxy(currcons,orig_x,orig_y);
  1410. */
  1411.     update_screen(fg_console);
  1412.     sw->con_cursor(&vc_cons[currcons], CM_DRAW);
  1413.     printable = 1;
  1414.     register_console(console_print);
  1415.  
  1416.     printk("Console: %s %s %ldx%ld, %d virtual consoles\n",
  1417.         can_do_color?"colour":"mono",
  1418.         display_desc,
  1419.         video_num_columns,video_num_lines,
  1420.         NR_CONSOLES);
  1421.  
  1422.     return kmem_start;
  1423. }
  1424.  
  1425. /*
  1426.  * kbdsave doesn't need to do anything: it's all handled automatically
  1427.  * with the new data structures..
  1428.  */
  1429. void kbdsave(int new_console)
  1430. {
  1431. }
  1432.  
  1433. void blank_screen(void)
  1434. {
  1435.     if (console_blanked)
  1436.         return;
  1437.     return;
  1438. #if 0
  1439.     timer_table[BLANK_TIMER].fn = unblank_screen;
  1440.     get_scrmem(fg_console);
  1441.     hide_cursor(fg_console);
  1442.     console_blanked = 1;
  1443.     memsetw((void *)video_mem_base, 0x0020, video_mem_term-video_mem_base );
  1444. #endif
  1445. }
  1446.  
  1447. void unblank_screen(void)
  1448. {
  1449.     if (!console_blanked)
  1450.         return;
  1451.     return;
  1452. #if 0
  1453.     timer_table[BLANK_TIMER].fn = blank_screen;
  1454.     if (blankinterval) {
  1455.         timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
  1456.         timer_active |= 1<<BLANK_TIMER;
  1457.     }
  1458.     console_blanked = 0;
  1459.     set_scrmem(fg_console);
  1460.     set_origin(fg_console);
  1461.     set_cursor(fg_console);
  1462. #endif
  1463. }
  1464.  
  1465. void update_screen(int new_console)
  1466. {
  1467.     static int lock = 0;
  1468.  
  1469.     if (new_console == fg_console || lock)
  1470.         return;
  1471.     return;
  1472.     lock = 1;
  1473.     fg_console = new_console;
  1474.     lock = 0;
  1475. #if 0
  1476.     kbdsave(new_console);
  1477.     get_scrmem(fg_console); 
  1478.     set_scrmem(fg_console); 
  1479.     set_origin(fg_console);
  1480.     set_cursor(new_console);
  1481.     set_leds();
  1482.     compute_shiftstate();
  1483. #endif
  1484. }
  1485.  
  1486. #if 0
  1487. int do_screendump(int arg)
  1488. {
  1489.     char *sptr, *buf = (char *)arg;
  1490.     int currcons, l;
  1491.  
  1492.     if (!suser())
  1493.         return -EPERM;
  1494.     l = verify_area(VERIFY_WRITE, buf,2+video_num_columns*video_num_lines);
  1495.     if (l)
  1496.         return l;
  1497.     currcons = get_fs_byte(buf+1);
  1498.     if ((currcons<0) || (currcons>NR_CONSOLES))
  1499.         return -EIO;
  1500.     put_fs_byte((char)(video_num_lines),buf++);    
  1501.     put_fs_byte((char)(video_num_columns),buf++);
  1502.     currcons = (currcons ? currcons-1 : fg_console);
  1503.     sptr = (char *) origin;
  1504.     for (l=video_num_lines*video_num_columns; l>0 ; l--, sptr++)
  1505.         put_fs_byte(*sptr++,buf++);    
  1506.     return(0);
  1507. }
  1508. #endif
  1509.  
  1510. /*
  1511.  * All we do is set the write and ioctl subroutines; later on maybe we'll
  1512.  * dynamically allocate the console screen memory.
  1513.  */
  1514. int con_open(struct tty_struct *tty, struct file * filp)
  1515. {
  1516.     tty->write = con_write;
  1517.     tty->ioctl = vt_ioctl;
  1518.     if (tty->line > NR_CONSOLES)
  1519.         return -ENODEV;
  1520.  
  1521.     tty->winsize.ws_row = vc_cons[tty->line-1].vc_rows;
  1522.     tty->winsize.ws_col = vc_cons[tty->line-1].vc_cols;
  1523.  
  1524.     return 0;
  1525. }
  1526.  
  1527. #ifdef CONFIG_SELECTION
  1528. /* correction factor for when screen is hardware-scrolled */
  1529. #define    hwscroll_offset (currcons == fg_console ? ((__real_origin - __origin) << 1) : 0)
  1530.  
  1531. /* set reverse video on characters s-e of console with selection. */
  1532. static void highlight(const int currcons, const int s, const int e)
  1533. {
  1534.     unsigned char *p, *p1, *p2;
  1535.  
  1536.     p1 = (unsigned char *)origin - hwscroll_offset + s + 1;
  1537.     p2 = (unsigned char *)origin - hwscroll_offset + e + 1;
  1538.     if (p1 > p2)
  1539.     {
  1540.         p = p1;
  1541.         p1 = p2;
  1542.         p2 = p;
  1543.     }
  1544.     for (p = p1; p <= p2; p += 2)
  1545.         *p = (*p & 0x88) | ((*p << 4) & 0x70) | ((*p >> 4) & 0x07);
  1546. }
  1547.  
  1548. /* is c in range [a-zA-Z0-9_]? */
  1549. static inline int inword(const char c) { return (isalnum(c) || c == '_'); }
  1550.  
  1551. /* does screen address p correspond to character at LH/RH edge of screen? */
  1552. static inline int atedge(const int p)
  1553. {
  1554.     return (!(p % video_size_row) || !((p + 2) % video_size_row));
  1555. }
  1556.  
  1557. /* constrain v such that l <= v <= u */
  1558. static inline short limit(const int v, const int l, const int u)
  1559. {
  1560.     return (v < l) ? l : ((v > u) ? u : v);
  1561. }
  1562.  
  1563. /* set the current selection. Invoked by ioctl(). */
  1564. int set_selection(const int arg)
  1565. {
  1566.     unsigned short *args, xs, ys, xe, ye;
  1567.     int currcons = fg_console;
  1568.     int sel_mode, new_sel_start, new_sel_end, spc;
  1569.     char *bp, *obp, *spos;
  1570.     int i, ps, pe;
  1571.     char *off = (char *)origin - hwscroll_offset;
  1572.  
  1573.     unblank_screen();
  1574.     args = (unsigned short *)(arg + 1);
  1575.     xs = get_fs_word(args++) - 1;
  1576.     ys = get_fs_word(args++) - 1;
  1577.     xe = get_fs_word(args++) - 1;
  1578.     ye = get_fs_word(args++) - 1;
  1579.     sel_mode = get_fs_word(args);
  1580.  
  1581.     xs = limit(xs, 0, video_num_columns - 1);
  1582.     ys = limit(ys, 0, video_num_lines - 1);
  1583.     xe = limit(xe, 0, video_num_columns - 1);
  1584.     ye = limit(ye, 0, video_num_lines - 1);
  1585.     ps = ys * video_size_row + (xs << 1);
  1586.     pe = ye * video_size_row + (xe << 1);
  1587.  
  1588.     if (ps > pe)    /* make sel_start <= sel_end */
  1589.     {
  1590.         int tmp = ps;
  1591.         ps = pe;
  1592.         pe = tmp;
  1593.     }
  1594.  
  1595.     switch (sel_mode)
  1596.     {
  1597.         case 0:    /* character-by-character selection */
  1598.         default:
  1599.             new_sel_start = ps;
  1600.             new_sel_end = pe;
  1601.             break;
  1602.         case 1:    /* word-by-word selection */
  1603.             spc = isspace(*(off + ps));
  1604.             for (new_sel_start = ps; ; ps -= 2)
  1605.             {
  1606.                 if ((spc && !isspace(*(off + ps))) ||
  1607.                     (!spc && !inword(*(off + ps))))
  1608.                     break;
  1609.                 new_sel_start = ps;
  1610.                 if (!(ps % video_size_row))
  1611.                     break;
  1612.             }
  1613.             spc = isspace(*(off + pe));
  1614.             for (new_sel_end = pe; ; pe += 2)
  1615.             {
  1616.                 if ((spc && !isspace(*(off + pe))) ||
  1617.                     (!spc && !inword(*(off + pe))))
  1618.                     break;
  1619.                 new_sel_end = pe;
  1620.                 if (!((pe + 2) % video_size_row))
  1621.                     break;
  1622.             }
  1623.             break;
  1624.         case 2:    /* line-by-line selection */
  1625.             new_sel_start = ps - ps % video_size_row;
  1626.             new_sel_end = pe + video_size_row
  1627.                     - pe % video_size_row - 2;
  1628.             break;
  1629.     }
  1630.     /* select to end of line if on trailing space */
  1631.     if (new_sel_end > new_sel_start &&
  1632.         !atedge(new_sel_end) && isspace(*(off + new_sel_end)))
  1633.     {
  1634.         for (pe = new_sel_end + 2; ; pe += 2)
  1635.         {
  1636.             if (!isspace(*(off + pe)) || atedge(pe))
  1637.                 break;
  1638.         }
  1639.         if (isspace(*(off + pe)))
  1640.             new_sel_end = pe;
  1641.     }
  1642.     if (sel_cons != currcons)
  1643.     {
  1644.         clear_selection();
  1645.         sel_cons = currcons;
  1646.     }
  1647.     if (sel_start == -1)    /* no current selection */
  1648.         highlight(sel_cons, new_sel_start, new_sel_end);
  1649.     else if (new_sel_start == sel_start)
  1650.     {
  1651.         if (new_sel_end == sel_end)    /* no action required */
  1652.             return 0;
  1653.         else if (new_sel_end > sel_end)    /* extend to right */
  1654.             highlight(sel_cons, sel_end + 2, new_sel_end);
  1655.         else                /* contract from right */
  1656.             highlight(sel_cons, new_sel_end + 2, sel_end);
  1657.     }
  1658.     else if (new_sel_end == sel_end)
  1659.     {
  1660.         if (new_sel_start < sel_start)    /* extend to left */
  1661.             highlight(sel_cons, new_sel_start, sel_start - 2);
  1662.         else                /* contract from left */
  1663.             highlight(sel_cons, sel_start, new_sel_start - 2);
  1664.     }
  1665.     else    /* some other case; start selection from scratch */
  1666.     {
  1667.         clear_selection();
  1668.         highlight(sel_cons, new_sel_start, new_sel_end);
  1669.     }
  1670.     sel_start = new_sel_start;
  1671.     sel_end = new_sel_end;
  1672.     obp = bp = sel_buffer;
  1673.     for (i = sel_start; i <= sel_end; i += 2)
  1674.     {
  1675.         spos = (char *)off + i;
  1676.         *bp++ = *spos;
  1677.         if (!isspace(*spos))
  1678.             obp = bp;
  1679.         if (! ((i + 2) % video_size_row))
  1680.         {
  1681.             /* strip trailing blanks from line and add newline,
  1682.                unless non-space at end of line. */
  1683.             if (obp != bp)
  1684.             {
  1685.                 bp = obp;
  1686.                 *bp++ = '\r';
  1687.             }
  1688.             obp = bp;
  1689.         }
  1690.         /* check for space, leaving room for next character, possible
  1691.            newline, and null at end. */
  1692.         if (bp - sel_buffer > SEL_BUFFER_SIZE - 3)
  1693.             break;
  1694.     }
  1695.     *bp = '\0';
  1696.     return 0;
  1697. }
  1698.  
  1699. /* insert the contents of the selection buffer into the queue of the
  1700.    tty associated with the current console. Invoked by ioctl(). */
  1701. int paste_selection(struct tty_struct *tty)
  1702. {
  1703.     char *bp = sel_buffer;
  1704.  
  1705.     if (! *bp)
  1706.         return 0;
  1707.     unblank_screen();
  1708.     while (*bp)
  1709.     {
  1710.         put_tty_queue(*bp, &tty->read_q);
  1711.         bp++;
  1712.     }
  1713.     TTY_READ_FLUSH(tty);
  1714.     return 0;
  1715. }
  1716.  
  1717. /* remove the current selection highlight, if any, from the console holding
  1718.    the selection. */
  1719. static void clear_selection()
  1720. {
  1721.     if (sel_start != -1)
  1722.     {
  1723.         highlight(sel_cons, sel_start, sel_end);
  1724.         sel_start = -1;
  1725.     }
  1726. }
  1727. #endif /* CONFIG_SELECTION */
  1728.