OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [m68knommu/] [kernel/] [console.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1625 jcastillo
 
2
/*
3
 *  linux/drivers/char/console.c
4
 *
5
 *  Copyright (C) 1991, 1992  Linus Torvalds
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
 *     'int vc_resize_con(unsigned long lines, unsigned long cols,
18
 *                        unsigned int currcons)'
19
 *     'void vc_disallocate(unsigned int currcons)'
20
 *
21
 *     'unsigned long con_init(unsigned long)'
22
 *     'int con_open(struct tty_struct *tty, struct file * filp)'
23
 *     'void con_write(struct tty_struct * tty)'
24
 *     'void console_print(const char * b)'
25
 *     'void update_screen(int new_console)'
26
 *
27
 *     'void do_blank_screen(int)'
28
 *     'void do_unblank_screen(void)'
29
 *     'void poke_blanked_console(void)'
30
 *
31
 *     'unsigned short *screen_pos(int currcons, int w_offset, int viewed)'
32
 *     'void complement_pos(int currcons, int offset)'
33
 *     'void invert_screen(int currcons, int offset, int count, int shift)'
34
 *
35
 *     'void scrollback(int lines)'
36
 *     'void scrollfront(int lines)'
37
 *
38
 *     'int con_get_font(char *)'
39
 *     'int con_set_font(char *)'
40
 *
41
 *     'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)'
42
 *     'int mouse_reporting(void)'
43
 *
44
 *     'unsigned long get_video_num_lines(unsigned int console)'
45
 *     'unsigned long get_video_num_columns(unsigned int console)'
46
 *     'unsigned long get_video_size_row(unsigned int console)'
47
 *
48
 * Hopefully this will be a rather complete VT102 implementation.
49
 *
50
 * Beeping thanks to John T Kohl.
51
 *
52
 * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
53
 *   Chars, and VT100 enhancements by Peter MacDonald.
54
 *
55
 * Copy and paste function by Andrew Haylett,
56
 *   some enhancements by Alessandro Rubini.
57
 *
58
 * User definable mapping table and font loading by Eugene G. Crosser,
59
 * <crosser@pccross.msk.su>
60
 *
61
 * Code to check for different video-cards mostly by Galen Hunt,
62
 * <g-hunt@ee.utah.edu>
63
 *
64
 * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
65
 * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
66
 *
67
 * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
68
 * Resizing of consoles, aeb, 940926
69
 *
70
 * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
71
 * <poe@daimi.aau.dk>
72
 *
73
 * 680x0 LINUX support by Arno Griffioen (arno@usn.nl)
74
 *
75
 * 9-Apr-94:  Arno Griffioen: fixed scrolling and delete-char bug.
76
 *            Scrolling code moved to amicon.c
77
 *
78
 * 18-Apr-94: David Carter [carter@cs.bris.ac.uk]. 680x0 LINUX modified
79
 *            Integrated support for new low level driver `amicon_ocs.c'
80
 *
81
 */
82
 
83
#define BLANK 0x0020
84
#define CAN_LOAD_EGA_FONTS    /* undefine if the user must not do this */
85
 
86
/* A bitmap for codes <32. A bit of 1 indicates that the code
87
 * corresponding to that bit number invokes some special action
88
 * (such as cursor movement) and should not be displayed as a
89
 * glyph unless the disp_ctrl mode is explicitly enabled.
90
 */
91
#define CTRL_ACTION 0x0d00ff81
92
#define CTRL_ALWAYS 0x0800f501  /* Cannot be overridden by disp_ctrl */
93
 
94
/*
95
 * Here is the default bell parameters: 750HZ, 1/8th of a second
96
 */
97
#define DEFAULT_BELL_PITCH      750
98
#define DEFAULT_BELL_DURATION   (HZ/8)
99
 
100
/*
101
 *  NOTE!!! We sometimes disable and enable interrupts for a short while
102
 * (to put a word in video IO), but this will work even for keyboard
103
 * interrupts. We know interrupts aren't enabled when getting a keyboard
104
 * interrupt, as we use trap-gates. Hopefully all is well.
105
 */
106
 
107
#include <linux/config.h>
108
#include <linux/sched.h>
109
#include <linux/timer.h>
110
#include <linux/interrupt.h>
111
#include <linux/tty.h>
112
#include <linux/tty_flip.h>
113
#include <linux/kernel.h>
114
#include <linux/string.h>
115
#include <linux/errno.h>
116
#include <linux/console.h>
117
#include <linux/kd.h>
118
#include <linux/malloc.h>
119
#include <linux/major.h>
120
#include <linux/mm.h>
121
#include <linux/ioport.h>
122
 
123
#include <asm/io.h>
124
#include <asm/segment.h>
125
#include <asm/system.h>
126
#include <asm/bitops.h>
127
 
128
#include "../../../drivers/char/kbd_kern.h"
129
#include "../../../drivers/char/vt_kern.h"
130
#include "../../../drivers/char/consolemap.h"
131
#include "../../../drivers/char/selection.h"
132
 
133
 
134
#ifndef MIN
135
#define MIN(a,b)        ((a) < (b) ? (a) : (b))
136
#endif
137
 
138
struct tty_driver console_driver;
139
static int console_refcount;
140
static struct tty_struct *console_table[MAX_NR_CONSOLES];
141
static struct termios *console_termios[MAX_NR_CONSOLES];
142
static struct termios *console_termios_locked[MAX_NR_CONSOLES];
143
 
144
static void vc_init(unsigned int console, int do_clear);
145
 
146
static void update_attr(int currcons);
147
static void gotoxy(int currcons, int new_x, int new_y);
148
static void save_cur(int currcons);
149
static void blank_screen(void);
150
static void unblank_screen(void);
151
extern void change_console(unsigned int);
152
static inline void set_cursor(int currcons);
153
static void reset_terminal(int currcons, int do_clear);
154
extern void reset_vc(unsigned int new_console);
155
extern void vt_init(void);
156
extern void register_console(void (*proc)(const char *));
157
extern void vesa_blank(void);
158
extern void vesa_unblank(void);
159
extern void compute_shiftstate(void);
160
void poke_blanked_console(void);
161
void do_blank_screen(int);
162
 
163
unsigned long   video_num_lines;
164
unsigned long   video_num_columns;
165
unsigned long   video_size_row;
166
 
167
static int printable = 0;                        /* Is console ready for printing? */
168
unsigned long video_font_height;        /* Height of current screen font */
169
unsigned long video_scan_lines;         /* Number of scan lines on screen */
170
unsigned long default_font_height;      /* Height of default screen font */
171
int           video_mode_512ch = 0;      /* 512-character mode */
172
static unsigned short console_charmask = 0x0ff;
173
 
174
static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
175
 
176
/* used by kbd_bh - set by keyboard_interrupt */
177
       int do_poke_blanked_console = 0;
178
       int console_blanked = 0;
179
static int blankinterval = 10*60*HZ;
180
static int vesa_off_interval = 0;
181
static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
182
 
183
static struct vc {
184
        struct vc_data *d;
185
 
186
        /* might add  scrmem, vt_struct, kbd  at some time,
187
           to have everything in one place - the disadvantage
188
           would be that vc_cons etc can no longer be static */
189
} vc_cons [MAX_NR_CONSOLES];
190
struct consw *conswitchp;
191
 
192
#define cols            (vc_cons[currcons].d->vc_cols)
193
#define rows            (vc_cons[currcons].d->vc_rows)
194
#define size_row        (vc_cons[currcons].d->vc_size_row)
195
#define screenbuf_size  (vc_cons[currcons].d->vc_screenbuf_size)
196
#define cons_num        (vc_cons[currcons].d->vc_num)
197
#define origin          (vc_cons[currcons].d->vc_origin)
198
#define scr_end         (vc_cons[currcons].d->vc_scr_end)
199
#define pos             (vc_cons[currcons].d->vc_pos)
200
#define top             (vc_cons[currcons].d->vc_top)
201
#define bottom          (vc_cons[currcons].d->vc_bottom)
202
#define x               (vc_cons[currcons].d->vc_x)
203
#define y               (vc_cons[currcons].d->vc_y)
204
#define vc_state        (vc_cons[currcons].d->vc_state)
205
#define npar            (vc_cons[currcons].d->vc_npar)
206
#define par             (vc_cons[currcons].d->vc_par)
207
#define ques            (vc_cons[currcons].d->vc_ques)
208
#define attr            (vc_cons[currcons].d->vc_attr)
209
#define saved_x         (vc_cons[currcons].d->vc_saved_x)
210
#define saved_y         (vc_cons[currcons].d->vc_saved_y)
211
#define translate       (vc_cons[currcons].d->vc_translate)
212
#define G0_charset      (vc_cons[currcons].d->vc_G0_charset)
213
#define G1_charset      (vc_cons[currcons].d->vc_G1_charset)
214
#define saved_G0        (vc_cons[currcons].d->vc_saved_G0)
215
#define saved_G1        (vc_cons[currcons].d->vc_saved_G1)
216
#define utf             (vc_cons[currcons].d->vc_utf)
217
#define utf_count       (vc_cons[currcons].d->vc_utf_count)
218
#define utf_char        (vc_cons[currcons].d->vc_utf_char)
219
#define video_mem_start (vc_cons[currcons].d->vc_video_mem_start)
220
#define video_mem_end   (vc_cons[currcons].d->vc_video_mem_end)
221
#define video_erase_char (vc_cons[currcons].d->vc_video_erase_char)     
222
#define disp_ctrl       (vc_cons[currcons].d->vc_disp_ctrl)
223
#define toggle_meta     (vc_cons[currcons].d->vc_toggle_meta)
224
#define decscnm         (vc_cons[currcons].d->vc_decscnm)
225
#define decom           (vc_cons[currcons].d->vc_decom)
226
#define decawm          (vc_cons[currcons].d->vc_decawm)
227
#define deccm           (vc_cons[currcons].d->vc_deccm)
228
#define decim           (vc_cons[currcons].d->vc_decim)
229
#define deccolm         (vc_cons[currcons].d->vc_deccolm)
230
#define need_wrap       (vc_cons[currcons].d->vc_need_wrap)
231
#define has_scrolled    (vc_cons[currcons].d->vc_has_scrolled)
232
#define kmalloced       (vc_cons[currcons].d->vc_kmalloced)
233
#define report_mouse    (vc_cons[currcons].d->vc_report_mouse)
234
#define can_do_color    (vc_cons[currcons].d->vc_can_do_color)
235
#define color           (vc_cons[currcons].d->vc_color)
236
#define s_color         (vc_cons[currcons].d->vc_s_color)
237
#define def_color       (vc_cons[currcons].d->vc_def_color)
238
#define foreground      (color & 0x0f)
239
#define background      (color & 0xf0)
240
#define charset         (vc_cons[currcons].d->vc_charset)
241
#define s_charset       (vc_cons[currcons].d->vc_s_charset)
242
#define intensity       (vc_cons[currcons].d->vc_intensity)
243
#define underline       (vc_cons[currcons].d->vc_underline)
244
#define blink           (vc_cons[currcons].d->vc_blink)
245
#define reverse         (vc_cons[currcons].d->vc_reverse)
246
#define s_intensity     (vc_cons[currcons].d->vc_s_intensity)
247
#define s_underline     (vc_cons[currcons].d->vc_s_underline)
248
#define s_blink         (vc_cons[currcons].d->vc_s_blink)
249
#define s_reverse       (vc_cons[currcons].d->vc_s_reverse)
250
#define ulcolor         (vc_cons[currcons].d->vc_ulcolor)
251
#define halfcolor       (vc_cons[currcons].d->vc_halfcolor)
252
#define tab_stop        (vc_cons[currcons].d->vc_tab_stop)
253
#define bell_pitch      (vc_cons[currcons].d->vc_bell_pitch)
254
#define bell_duration   (vc_cons[currcons].d->vc_bell_duration)
255
#define sw              (vc_cons[currcons].d->vc_sw)
256
 
257
#define vcmode          (vt_cons[currcons]->vc_mode)
258
#if 0 /* XXX */
259
#define vtmode          (vt_cons[currcons]->vt_mode)
260
#define vtpid           (vt_cons[currcons]->vt_pid)
261
#define vtnewvt         (vt_cons[currcons]->vt_newvt)
262
#endif
263
 
264
#define structsize      (sizeof(struct vc_data) + sizeof(struct vt_struct))
265
 
266
int vc_cons_allocated(unsigned int i)
267
{
268
        return (i < MAX_NR_CONSOLES && vc_cons[i].d);
269
}
270
 
271
int vc_allocate(unsigned int currcons)          /* return 0 on success */
272
{
273
        if (currcons >= MAX_NR_CONSOLES)
274
          return -ENODEV;
275
        if (!vc_cons[currcons].d) {
276
            long p, q;
277
 
278
            /* prevent users from taking too much memory */
279
            if (currcons >= MAX_NR_USER_CONSOLES && !suser())
280
              return -EPERM;
281
 
282
            /* due to the granularity of kmalloc, we waste some memory here */
283
            /* the alloc is done in two steps, to optimize the common situation
284
               of a 25x80 console (structsize=216, screenbuf_size=4000) */
285
            p = (long) kmalloc(structsize, GFP_KERNEL);
286
            if (!p)
287
                return -ENOMEM;
288
            vc_cons[currcons].d = (struct vc_data *) p;
289
            vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
290
 
291
            /* ++Geert: sw->con_init determines console size */
292
            sw = conswitchp;
293
            cons_num = currcons;
294
            sw->con_init (vc_cons[currcons].d);
295
            size_row = cols<<1;
296
            screenbuf_size = rows*size_row;
297
 
298
            q = (long) kmalloc(screenbuf_size, GFP_KERNEL);
299
            if (!q) {
300
                kfree_s((char *) p, structsize);
301
                vc_cons[currcons].d = NULL;
302
                return -ENOMEM;
303
            }
304
            vc_scrbuf[currcons] = (unsigned short *) q;
305
            kmalloced = 1;
306
            vc_init (currcons, 1);
307
        }
308
        return 0;
309
}
310
 
311
/*
312
 * Change # of rows and columns (0 means the size of fg_console)
313
 * [this is to be used together with some user program
314
 * like resize that changes the hardware videomode]
315
 */
316
int vc_resize(unsigned long lines, unsigned long columns)
317
{
318
        unsigned long cc, ll, ss, sr;
319
        unsigned long occ, oll, oss, osr;
320
        unsigned short *p;
321
        unsigned int currcons = fg_console, i;
322
        unsigned short *newscreens[MAX_NR_CONSOLES];
323
        long ol, nl, rlth, rrem;
324
 
325
        cc = (columns ? columns : cols);
326
        ll = (lines ? lines : rows);
327
        sr = cc << 1;
328
        ss = sr * ll;
329
 
330
        /*
331
         * Some earlier version had all consoles of potentially
332
         * different sizes, but that was really messy.
333
         * So now we only change if there is room for all consoles
334
         * of the same size.
335
         */
336
        for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
337
            if (!vc_cons_allocated(currcons))
338
              newscreens[currcons] = 0;
339
            else {
340
                p = (unsigned short *) kmalloc(ss, GFP_USER);
341
                if (!p) {
342
                    for (i = 0; i< currcons; i++)
343
                      if (newscreens[i])
344
                        kfree_s(newscreens[i], ss);
345
                    return -ENOMEM;
346
                }
347
                newscreens[currcons] = p;
348
            }
349
        }
350
 
351
#if 0 /* XXX */
352
        get_scrmem(fg_console);
353
#endif
354
 
355
        for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
356
            if (!vc_cons_allocated(currcons))
357
              continue;
358
 
359
            oll = rows;
360
            occ = cols;
361
            osr = size_row;
362
            oss = screenbuf_size;
363
 
364
            rows = ll;
365
            cols = cc;
366
            size_row = sr;
367
            screenbuf_size = ss;
368
 
369
            rlth = MIN(osr, sr);
370
            rrem = sr - rlth;
371
            ol = origin;
372
            nl = (long) newscreens[currcons];
373
            if (ll < oll)
374
              ol += (oll - ll) * osr;
375
 
376
            update_attr(currcons);
377
            while (ol < scr_end) {
378
                /* ++Geert: TODO: Because the attributes have different meanings
379
                   on monochrome and color, they should really be converted if
380
                   can_do_color changes... */
381
                memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
382
                if (rrem)
383
                  memsetw((void *)(nl + rlth), video_erase_char, rrem);
384
                ol += osr;
385
                nl += sr;
386
            }
387
 
388
            if (kmalloced)
389
              kfree_s(vc_scrbuf[currcons], oss);
390
            vc_scrbuf[currcons] = newscreens[currcons];
391
            kmalloced = 1;
392
            screenbuf_size = ss;
393
 
394
            origin = (long) video_mem_start = vc_scrbuf[currcons];
395
            scr_end = video_mem_end = ((long) video_mem_start) + ss;
396
 
397
            if (scr_end > nl)
398
              memsetw((void *) nl, video_erase_char, scr_end - nl);
399
 
400
            /* do part of a reset_terminal() */
401
            top = 0;
402
            bottom = rows;
403
            gotoxy(currcons, x, y);
404
            save_cur(currcons);
405
        }
406
 
407
#if 0 /* XXX */
408
        set_scrmem(fg_console, 0);
409
        set_origin(fg_console);
410
#endif /* XXX */
411
        update_screen(fg_console);
412
        set_cursor(fg_console);
413
 
414
        return 0;
415
}
416
 
417
/*
418
 * ++Geert: Change # of rows and columns for one specific console.
419
 * Of course it's not messy to have all consoles of potentially different sizes,
420
 * except on PCish hardware :-)
421
 *
422
 * This is called by the low level console driver (arch/m68k/console/fbcon.c or
423
 * arch/m68k/console/txtcon.c)
424
 */
425
void vc_resize_con(unsigned long lines, unsigned long columns,
426
                   unsigned int currcons)
427
{
428
        unsigned long cc, ll, ss, sr;
429
        unsigned long occ, oll, oss, osr;
430
        unsigned short *newscreen;
431
        long ol, nl, rlth, rrem;
432
        struct winsize ws;
433
 
434
        if (!columns || !lines || currcons >= MAX_NR_CONSOLES)
435
            return;
436
 
437
        cc = columns;
438
        ll = lines;
439
        sr = cc << 1;
440
        ss = sr * ll;
441
 
442
        if (!vc_cons_allocated(currcons))
443
            newscreen = 0;
444
        else if (!(newscreen = (unsigned short *) kmalloc(ss, GFP_USER)))
445
            return;
446
 
447
        if (vc_cons_allocated(currcons)) {
448
            oll = rows;
449
            occ = cols;
450
            osr = size_row;
451
            oss = screenbuf_size;
452
 
453
            rows = ll;
454
            cols = cc;
455
            size_row = sr;
456
            screenbuf_size = ss;
457
 
458
            rlth = MIN(osr, sr);
459
            rrem = sr - rlth;
460
            ol = origin;
461
            nl = (long) newscreen;
462
            if (ll < oll)
463
              ol += (oll - ll) * osr;
464
 
465
            update_attr(currcons);
466
            while (ol < scr_end) {
467
                /* ++Geert: TODO: Because the attributes have different meanings
468
                   on monochrome and color, they should really be converted if
469
                   can_do_color changes... */
470
                memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
471
                if (rrem)
472
                  memsetw((void *)(nl + rlth), video_erase_char, rrem);
473
                ol += osr;
474
                nl += sr;
475
            }
476
 
477
            if (kmalloced)
478
              kfree_s(vc_scrbuf[currcons], oss);
479
            vc_scrbuf[currcons] = newscreen;
480
            kmalloced = 1;
481
            screenbuf_size = ss;
482
 
483
            origin = (long) video_mem_start = vc_scrbuf[currcons];
484
            scr_end = video_mem_end = ((long)video_mem_start) + ss;
485
 
486
            if (scr_end > nl)
487
              memsetw((void *) nl, video_erase_char, scr_end - nl);
488
 
489
            /* do part of a reset_terminal() */
490
            top = 0;
491
            bottom = rows;
492
            gotoxy(currcons, x, y);
493
            save_cur(currcons);
494
 
495
            ws.ws_row = rows;
496
            ws.ws_col = cols;
497
            if (memcmp(&ws, &console_table[currcons]->winsize, sizeof (struct winsize)) &&
498
                console_table[currcons]->pgrp > 0)
499
                kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1);
500
            console_table[currcons]->winsize = ws;
501
        }
502
 
503
   if (currcons == fg_console && vt_cons[fg_console]->vc_mode == KD_TEXT)
504
      update_screen(fg_console);
505
}
506
 
507
void vc_disallocate(unsigned int currcons)
508
{
509
        if (vc_cons_allocated(currcons)) {
510
            if (kmalloced)
511
              kfree_s(vc_scrbuf[currcons], screenbuf_size);
512
            if (currcons >= MIN_NR_CONSOLES)
513
              kfree_s(vc_cons[currcons].d, structsize);
514
            vc_cons[currcons].d = 0;
515
        }
516
}
517
 
518
 
519
#define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
520
#define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
521
#define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
522
 
523
#define decarm          VC_REPEAT
524
#define decckm          VC_CKMODE
525
#define kbdapplic       VC_APPLIC
526
#define lnm             VC_CRLF
527
 
528
/*
529
 * this is what the terminal answers to a ESC-Z or csi0c query.
530
 */
531
#define VT100ID "\033[?1;2c"
532
#define VT102ID "\033[?6c"
533
 
534
static unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
535
                                       8,12,10,14, 9,13,11,15 };
536
 
537
/*
538
 * gotoxy() must verify all boundaries, because the arguments
539
 * might also be negative. If the given position is out of
540
 * bounds, the cursor is placed at the nearest margin.
541
 */
542
static void gotoxy(int currcons, int new_x, int new_y)
543
{
544
        int min_y, max_y;
545
 
546
        if (new_x < 0)
547
                x = 0;
548
        else
549
                if (new_x >= cols)
550
                        x = cols - 1;
551
                else
552
                        x = new_x;
553
        if (decom) {
554
                min_y = top;
555
                max_y = bottom;
556
        } else {
557
                min_y = 0;
558
                max_y = rows;
559
        }
560
        if (new_y < min_y)
561
                y = min_y;
562
        else if (new_y >= max_y)
563
                y = max_y - 1;
564
        else
565
                y = new_y;
566
        pos = video_mem_start + y * cols + x;
567
        need_wrap = 0;
568
}
569
 
570
/* for absolute user moves, when decom is set */
571
static void gotoxay(int currcons, int new_x, int new_y)
572
{
573
        gotoxy(currcons, new_x, decom ? (top+new_y) : new_y);
574
}
575
 
576
static void hide_cursor(int currcons)
577
{
578
        sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
579
        return;
580
}
581
 
582
static void set_cursor(int currcons)
583
{
584
        if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
585
                return;
586
        if (deccm)
587
                sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
588
        else
589
                hide_cursor(currcons);
590
        return;
591
}
592
 
593
void no_scroll(char *str, int *ints)
594
{
595
  /*
596
   * no_scroll currently does nothing on the m68k.
597
   */
598
}
599
 
600
/*
601
 * Arno:
602
 * Why do we need these? The keyboard code doesn't seem to do anything
603
 * with them either...
604
 */
605
void scrollfront(int l)
606
{
607
        return;
608
}
609
 
610
void scrollback(int l)
611
{
612
        return;
613
}
614
 
615
static void scrup(int currcons, unsigned int t, unsigned int b,
616
                  int nr)
617
{
618
        unsigned short *p;
619
        int i;
620
 
621
        if (b > rows || t >= b)
622
                return;
623
 
624
        memmove (video_mem_start + t * cols,
625
                 video_mem_start + (t + nr) * cols,
626
                 (b - t - nr) * cols * 2);
627
 
628
        p = video_mem_start + (b - nr) * cols;
629
        for (i = nr * cols; i > 0; i--)
630
          *p++ = video_erase_char;
631
 
632
        if (currcons != fg_console)
633
          return;
634
/*
635
 * Arno:
636
 * Scrolling has now been moved to amicon.c where it should have
637
 * been all along.
638
 */
639
        sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr);
640
 
641
        return;
642
 
643
}
644
 
645
static void scrdown(int currcons, unsigned int t, unsigned int b,
646
                    int nr)
647
{
648
        unsigned short *p;
649
        int i;
650
 
651
        if (b > rows || t >= b)
652
                return;
653
 
654
        memmove (video_mem_start + (t + nr) * cols,
655
                 video_mem_start + t * cols,
656
                 (b - t - nr) * cols * 2);
657
 
658
        p = video_mem_start + t * cols;
659
        for (i = nr * cols; i > 0; i--)
660
          *p++ = video_erase_char;
661
 
662
        if (currcons != fg_console)
663
          return;
664
/*
665
 * Arno:
666
 * Scrolling has now been moved to amicon.c where it should have
667
 * been all along.
668
 */
669
        sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr);
670
 
671
        return;
672
}
673
 
674
static void lf(int currcons)
675
{
676
        /* don't scroll if above bottom of scrolling region, or
677
         * if below scrolling region
678
         */
679
        if (y+1 == bottom)
680
                scrup(currcons,top,bottom, 1);
681
        else if (y < rows-1) {
682
                y++;
683
                pos += cols;
684
        }
685
        need_wrap = 0;
686
}
687
 
688
static void ri(int currcons)
689
{
690
        /* don't scroll if below top of scrolling region, or
691
         * if above scrolling region
692
         */
693
        if (y == top)
694
                scrdown(currcons,top,bottom, 1);
695
        else if (y > 0) {
696
                y--;
697
                pos -= cols;
698
        }
699
        need_wrap = 0;
700
}
701
 
702
static inline void cr(int currcons)
703
{
704
        pos -= x;
705
        need_wrap = x = 0;
706
}
707
 
708
static inline void bs(int currcons)
709
{
710
        if (x) {
711
                pos--;
712
                x--;
713
                need_wrap = 0;
714
        }
715
}
716
 
717
static inline void del(int currcons)
718
{
719
        /* ignored */
720
}
721
 
722
static void csi_J(int currcons, int vpar)
723
{
724
        unsigned long count;
725
        unsigned short *start;
726
 
727
        switch (vpar) {
728
                case 0:  /* erase from cursor to end of display */
729
                        count = (video_mem_start
730
                                 + cols * rows
731
                                 - pos);
732
                        start = pos;
733
                        if (currcons != fg_console)
734
                          break;
735
                        /* 680x0 do in two stages */
736
                        sw->con_clear(vc_cons[currcons].d,y,x,1,cols-x);
737
                        sw->con_clear(vc_cons[currcons].d,y+1,0,rows-y-1, cols);
738
                        break;
739
                case 1: /* erase from start to cursor */
740
                        count = pos - video_mem_start + 1;
741
                        start = video_mem_start;
742
                        if (currcons != fg_console)
743
                          break;
744
                        /* 680x0 do in two stages */
745
                        sw->con_clear(vc_cons[currcons].d,0,0,y, cols);
746
                        sw->con_clear(vc_cons[currcons].d,y,0,1,x + 1);
747
                        break;
748
                case 2: /* erase whole display */
749
                        count = cols * rows;
750
                        start = video_mem_start;
751
                        if (currcons != fg_console)
752
                          break;
753
                        sw->con_clear(vc_cons[currcons].d,0,0,rows, cols);
754
                        break;
755
                default:
756
                        return;
757
        }
758
        while (count-- > 0)
759
          *start++ = video_erase_char;
760
        need_wrap = 0;
761
}
762
 
763
static void csi_K(int currcons, int vpar)
764
{
765
        unsigned long count;
766
        unsigned short *start;
767
 
768
        switch (vpar) {
769
                case 0:  /* erase from cursor to end of line */
770
                        count = cols - x;
771
                        start = pos;
772
                        if (currcons != fg_console)
773
                          break;
774
                        sw->con_clear(vc_cons[currcons].d,y,x,1,cols-x);
775
                        break;
776
                case 1: /* erase from start of line to cursor */
777
                        start = pos - x;
778
                        count = x + 1;
779
                        if (currcons != fg_console)
780
                          break;
781
                        sw->con_clear(vc_cons[currcons].d,y,0,1,x + 1);
782
                        break;
783
                case 2: /* erase whole line */
784
                        start = pos - x;
785
                        count = cols;
786
                        if (currcons != fg_console)
787
                          break;
788
                        sw->con_clear(vc_cons[currcons].d,y,0,1,cols);
789
                        break;
790
                default:
791
                        return;
792
        }
793
        while (count-- > 0)
794
          *start++ = video_erase_char;
795
        need_wrap = 0;
796
}
797
 
798
static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
799
{                                         /* not vt100? */
800
        unsigned long count;
801
        unsigned short * start;
802
 
803
        if (!vpar)
804
                vpar++;
805
 
806
        start=pos;
807
        count=(vpar > cols-x) ? (cols-x) : vpar;
808
 
809
        if (currcons == fg_console)
810
                sw->con_clear(vc_cons[currcons].d,y,x,1,count);
811
 
812
        while (count-- > 0)
813
                *start++ = video_erase_char;
814
        need_wrap = 0;
815
}
816
 
817
/*
818
 * Arno:
819
 * On 680x0 attributes are currently not used. This piece of code
820
 * seems hardware independent, but uses the EGA/VGA way of representing
821
 * attributes.
822
 * TODO: modify for 680x0 and add attribute processing to putc code.
823
 *
824
 * ++roman: I completely changed the attribute format for monochrome
825
 * mode (!can_do_color). The formerly used MDA (monochrome display
826
 * adapter) format didn't allow the combination of certain effects.
827
 * Now the attribute is just a bit vector:
828
 *  Bit 0..1: intensity (0..2)
829
 *  Bit 2   : underline
830
 *  Bit 3   : reverse
831
 *  Bit 7   : blink
832
 */
833
static void update_attr(int currcons)
834
{
835
        if (!can_do_color) {
836
                /* Special treatment for monochrome */
837
                attr = intensity |
838
                        (underline ? 4 : 0) |
839
                        ((reverse ^ decscnm) ? 8 : 0) |
840
                        (blink ? 0x80 : 0);
841
                video_erase_char = ' ' | ((reverse ^ decscnm) ? 0x800 : 0);
842
                return;
843
        }
844
 
845
        attr = color;
846
        if (underline)
847
                attr = (attr & 0xf0) | ulcolor;
848
        else if (intensity == 0)
849
                attr = (attr & 0xf0) | halfcolor;
850
        if (reverse ^ decscnm)
851
                attr = reverse_video_char(attr);
852
        if (blink)
853
                attr ^= 0x80;
854
        if (intensity == 2)
855
                attr ^= 0x08;
856
        if (decscnm)
857
                video_erase_char = (reverse_video_char(color) << 8) | ' ';
858
        else
859
                video_erase_char = (color << 8) | ' ';
860
}
861
 
862
static void default_attr(int currcons)
863
{
864
        intensity = 1;
865
        underline = 0;
866
        reverse = 0;
867
        blink = 0;
868
        color = def_color;
869
}
870
 
871
static void csi_m(int currcons)
872
{
873
        int i;
874
 
875
        for (i=0;i<=npar;i++)
876
                switch (par[i]) {
877
                        case 0:  /* all attributes off */
878
                                default_attr(currcons);
879
                                break;
880
                        case 1:
881
                                intensity = 2;
882
                                break;
883
                        case 2:
884
                                intensity = 0;
885
                                break;
886
                        case 4:
887
                                underline = 1;
888
                                break;
889
                        case 5:
890
                                blink = 1;
891
                                break;
892
                        case 7:
893
                                reverse = 1;
894
                                break;
895
                        case 10: /* ANSI X3.64-1979 (SCO-ish?)
896
                                  * Select primary font, don't display
897
                                  * control chars if defined, don't set
898
                                  * bit 8 on output.
899
                                  */
900
                                translate = set_translate(charset == 0
901
                                                ? G0_charset
902
                                                : G1_charset);
903
                                disp_ctrl = 0;
904
                                toggle_meta = 0;
905
                                break;
906
                        case 11: /* ANSI X3.64-1979 (SCO-ish?)
907
                                  * Select first alternate font, let's
908
                                  * chars < 32 be displayed as ROM chars.
909
                                  */
910
                                translate = set_translate(IBMPC_MAP);
911
                                disp_ctrl = 1;
912
                                toggle_meta = 0;
913
                                break;
914
                        case 12: /* ANSI X3.64-1979 (SCO-ish?)
915
                                  * Select second alternate font, toggle
916
                                  * high bit before displaying as ROM char.
917
                                  */
918
                                translate = set_translate(IBMPC_MAP);
919
                                disp_ctrl = 1;
920
                                toggle_meta = 1;
921
                                break;
922
                        case 21:
923
                        case 22:
924
                                intensity = 1;
925
                                break;
926
                        case 24:
927
                                underline = 0;
928
                                break;
929
                        case 25:
930
                                blink = 0;
931
                                break;
932
                        case 27:
933
                                reverse = 0;
934
                                break;
935
                        case 38: /* ANSI X3.64-1979 (SCO-ish?)
936
                                  * Enables underscore, white foreground
937
                                  * with white underscore (Linux - use
938
                                  * default foreground).
939
                                  */
940
                                color = (def_color & 0x0f) | background;
941
                                underline = 1;
942
                                break;
943
                        case 39: /* ANSI X3.64-1979 (SCO-ish?)
944
                                  * Disable underline option.
945
                                  * Reset colour to default? It did this
946
                                  * before...
947
                                  */
948
                                color = (def_color & 0x0f) | background;
949
                                underline = 0;
950
                                break;
951
                        case 49:
952
                                color = (def_color & 0xf0) | foreground;
953
                                break;
954
                        default:
955
                                if (par[i] >= 30 && par[i] <= 37)
956
                                        color = color_table[par[i]-30]
957
                                                | background;
958
                                else if (par[i] >= 40 && par[i] <= 47)
959
                                        color = (color_table[par[i]-40]<<4)
960
                                                | foreground;
961
                                break;
962
                }
963
        update_attr(currcons);
964
}
965
 
966
static void respond_string(const char * p, struct tty_struct * tty)
967
{
968
        while (*p) {
969
                tty_insert_flip_char(tty, *p, 0);
970
                p++;
971
        }
972
        tty_schedule_flip(tty);
973
}
974
 
975
static void cursor_report(int currcons, struct tty_struct * tty)
976
{
977
        char buf[40];
978
 
979
        sprintf(buf, "\033[%ld;%ldR", y + (decom ? top+1 : 1), x+1);
980
        respond_string(buf, tty);
981
}
982
 
983
static inline void status_report(struct tty_struct * tty)
984
{
985
        respond_string("\033[0n", tty); /* Terminal ok */
986
}
987
 
988
static inline void respond_ID(struct tty_struct * tty)
989
{
990
        respond_string(VT102ID, tty);
991
}
992
 
993
void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
994
{
995
        char buf[8];
996
 
997
        sprintf(buf, "\033[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
998
                (char)('!' + mry));
999
        respond_string(buf, tty);
1000
}
1001
 
1002
/* invoked via ioctl(TIOCLINUX) */
1003
int mouse_reporting(void)
1004
{
1005
        int currcons = fg_console;
1006
 
1007
        return report_mouse;
1008
}
1009
 
1010
static inline unsigned short *screenpos(int currcons, int offset, int viewed)
1011
{
1012
        unsigned short *p = (unsigned short *)(origin + offset);
1013
#if 0
1014
        if (viewed && currcons == fg_console)
1015
                p -= (__real_origin - __origin);
1016
#endif
1017
        return p;
1018
}
1019
 
1020
/* Note: inverting the screen twice should revert to the original state */
1021
void invert_screen(int currcons, int offset, int count, int viewed)
1022
{
1023
        unsigned short *p;
1024
        unsigned short xx, yy, oldattr;
1025
 
1026
        count /= 2;
1027
        p = screenpos(currcons, offset, viewed);
1028
        xx = (offset >> 1) % cols;
1029
        yy = (offset >> 1) / cols;
1030
        oldattr = attr;
1031
        if (can_do_color)
1032
                while (count--) {
1033
                        unsigned short old = scr_readw(p);
1034
                        unsigned short new = reverse_video_short(old);
1035
                        scr_writew(new, p);
1036
                        p++;
1037
                        if (currcons != fg_console)
1038
                                continue;
1039
                        attr = new >> 8;
1040
                        sw->con_putc(vc_cons[currcons].d, new & 0xff, yy, xx);
1041
                        if (++xx == cols)
1042
                                xx = 0, ++yy;
1043
                }
1044
        else
1045
                while (count--) {
1046
                        unsigned short old = scr_readw(p);
1047
                        unsigned short new = old ^ 0x800;
1048
                        scr_writew(new, p);
1049
                        p++;
1050
                        if (currcons != fg_console)
1051
                                continue;
1052
                        attr = new >> 8;
1053
                        sw->con_putc(vc_cons[currcons].d, new & 0xff, yy, xx);
1054
                        if (++xx == cols)
1055
                                xx = 0, ++yy;
1056
                }
1057
        attr = oldattr;
1058
}
1059
 
1060
/* used by selection: complement pointer position */
1061
void complement_pos(int currcons, int offset)
1062
{
1063
        static unsigned short *p = NULL;
1064
        static unsigned short old = 0;
1065
        static unsigned short oldx = 0, oldy = 0;
1066
        unsigned short new, oldattr;
1067
 
1068
        oldattr = attr;
1069
        if (p) {
1070
                scr_writew(old, p);
1071
                if (currcons == fg_console) {
1072
                        attr = old >> 8;
1073
                        sw->con_putc(vc_cons[currcons].d, old & 0xff, oldy, oldx);
1074
                        attr = oldattr;
1075
                }
1076
        }
1077
        if (offset == -1)
1078
                p = NULL;
1079
        else {
1080
                p = screenpos(currcons, offset, 1);
1081
                old = scr_readw(p);
1082
                oldx = (offset >> 1) % cols;
1083
                oldy = (offset >> 1) / cols;
1084
                if (can_do_color)
1085
                        new = old ^ 0x7700;
1086
                else
1087
                        new = old ^ 0x800;
1088
                scr_writew(new, p);
1089
                if (currcons == fg_console) {
1090
                        attr = new >> 8;
1091
                        sw->con_putc(vc_cons[currcons].d, new & 0xff, oldy, oldx);
1092
                        attr = oldattr;
1093
                }
1094
        }
1095
}
1096
 
1097
/* used by selection */
1098
unsigned short screen_word(int currcons, int offset, int viewed)
1099
{
1100
        return scr_readw(screenpos(currcons, offset, viewed));
1101
}
1102
 
1103
/* used by selection - convert a screen word to a glyph number */
1104
int scrw2glyph(unsigned short scr_word)
1105
{
1106
        return ( video_mode_512ch )
1107
                ? ((scr_word & 0x0800) >> 3) + (scr_word & 0x00ff)
1108
                : scr_word & 0x00ff;
1109
}
1110
 
1111
/* used by vcs - note the word offset */
1112
unsigned short *screen_pos(int currcons, int w_offset, int viewed)
1113
{
1114
        return screenpos(currcons, 2 * w_offset, viewed);
1115
}
1116
 
1117
void getconsxy(int currcons, char *p)
1118
{
1119
        p[0] = x;
1120
        p[1] = y;
1121
}
1122
 
1123
void putconsxy(int currcons, char *p)
1124
{
1125
        gotoxy(currcons, p[0], p[1]);
1126
        set_cursor(currcons);
1127
}
1128
 
1129
static void set_mode(int currcons, int on_off)
1130
{
1131
        int i;
1132
 
1133
        for (i=0; i<=npar; i++)
1134
                if (ques) switch(par[i]) {      /* DEC private modes set/reset */
1135
                        case 1:                 /* Cursor keys send ^[Ox/^[[x */
1136
                                if (on_off)
1137
                                        set_kbd(decckm);
1138
                                else
1139
                                        clr_kbd(decckm);
1140
                                break;
1141
                        case 3: /* 80/132 mode switch unimplemented */
1142
                                deccolm = on_off;
1143
#if 0
1144
                                (void) vc_resize(rows, deccolm ? 132 : 80);
1145
                                /* this alone does not suffice; some user mode
1146
                                   utility has to change the hardware regs */
1147
#endif
1148
                                break;
1149
                        case 5:                 /* Inverted screen on/off */
1150
                                if (decscnm != on_off) {
1151
                                        decscnm = on_off;
1152
                                        invert_screen(currcons, 0, screenbuf_size, 0);
1153
                                        update_attr(currcons);
1154
                                }
1155
                                break;
1156
                        case 6:                 /* Origin relative/absolute */
1157
                                decom = on_off;
1158
                                gotoxay(currcons,0,0);
1159
                                break;
1160
                        case 7:                 /* Autowrap on/off */
1161
                                decawm = on_off;
1162
                                break;
1163
                        case 8:                 /* Autorepeat on/off */
1164
                                if (on_off)
1165
                                        set_kbd(decarm);
1166
                                else
1167
                                        clr_kbd(decarm);
1168
                                break;
1169
                        case 9:
1170
                                report_mouse = on_off ? 1 : 0;
1171
                                break;
1172
                        case 25:                /* Cursor on/off */
1173
                                deccm = on_off;
1174
                                set_cursor(currcons);
1175
                                break;
1176
                        case 1000:
1177
                                report_mouse = on_off ? 2 : 0;
1178
                                break;
1179
                } else switch(par[i]) {         /* ANSI modes set/reset */
1180
                        case 3:                 /* Monitor (display ctrls) */
1181
                                disp_ctrl = on_off;
1182
                                break;
1183
                        case 4:                 /* Insert Mode on/off */
1184
                                decim = on_off;
1185
                                break;
1186
                        case 20:                /* Lf, Enter == CrLf/Lf */
1187
                                if (on_off)
1188
                                        set_kbd(lnm);
1189
                                else
1190
                                        clr_kbd(lnm);
1191
                                break;
1192
                }
1193
}
1194
 
1195
static void setterm_command(int currcons)
1196
{
1197
        switch(par[0]) {
1198
                case 1: /* set color for underline mode */
1199
                        if (can_do_color && par[1] < 16) {
1200
                                ulcolor = color_table[par[1]];
1201
                                if (underline)
1202
                                        update_attr(currcons);
1203
                        }
1204
                        break;
1205
                case 2: /* set color for half intensity mode */
1206
                        if (can_do_color && par[1] < 16) {
1207
                                halfcolor = color_table[par[1]];
1208
                                if (intensity == 0)
1209
                                        update_attr(currcons);
1210
                        }
1211
                        break;
1212
                case 8: /* store colors as defaults */
1213
                        def_color = attr;
1214
                        default_attr(currcons);
1215
                        update_attr(currcons);
1216
                        break;
1217
                case 9: /* set blanking interval */
1218
                        blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
1219
                        poke_blanked_console();
1220
                        break;
1221
                case 10: /* set bell frequency in Hz */
1222
                        if (npar >= 1)
1223
                                bell_pitch = par[1];
1224
                        else
1225
                                bell_pitch = DEFAULT_BELL_PITCH;
1226
                        break;
1227
                case 11: /* set bell duration in msec */
1228
                        if (npar >= 1)
1229
                                bell_duration = (par[1] < 2000) ?
1230
                                        par[1]*HZ/1000 : 0;
1231
                        else
1232
                                bell_duration = DEFAULT_BELL_DURATION;
1233
                        break;
1234
                case 12: /* bring specified console to the front */
1235
                        if (par[1] >= 1 && vc_cons_allocated(par[1]-1))
1236
                                update_screen(par[1]-1);
1237
                        break;
1238
                case 13: /* unblank the screen */
1239
                        unblank_screen();
1240
                        break;
1241
                case 14: /* set vesa powerdown interval */
1242
                        vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
1243
                        break;
1244
        }
1245
}
1246
 
1247
static void insert_char(int currcons)
1248
{
1249
        int i;
1250
        unsigned short *p = pos;
1251
 
1252
        for (i = cols - x - 2; i >= 0; i--)
1253
          p[i + 1] = p[i];
1254
        *pos = video_erase_char;
1255
        need_wrap = 0;
1256
 
1257
        if (currcons != fg_console)
1258
          return;
1259
 
1260
        /* Arno:
1261
         * Move the remainder of the line (-1 character) one spot to the right
1262
         */
1263
        sw->con_bmove(vc_cons[currcons].d,y,x,y,x+1,1,(cols-x-1));
1264
        /*
1265
         * Print the erase char on the current position
1266
         */
1267
        sw->con_putc(vc_cons[currcons].d,(video_erase_char & 0x00ff),y,x);
1268
}
1269
 
1270
static void csi_at(int currcons, unsigned int nr)
1271
{
1272
        int i;
1273
        unsigned short *p;
1274
 
1275
        if (nr > cols - x)
1276
                nr = cols - x;
1277
        else if (!nr)
1278
                nr = 1;
1279
 
1280
        p = pos + cols - x - nr;
1281
        while (--p >= pos)
1282
          p[nr] = *p;
1283
        for (i = 0; i < nr; i++)
1284
          *++p = video_erase_char;
1285
        need_wrap = 0;
1286
 
1287
        if (currcons != fg_console)
1288
          return;
1289
 
1290
        sw->con_bmove (vc_cons[currcons].d, y, x, y, x + nr,
1291
                       1, cols - x - nr);
1292
        while (nr--)
1293
          sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
1294
                        y, x + nr);
1295
}
1296
 
1297
static void csi_L(int currcons, unsigned int nr)
1298
{
1299
        if (nr > rows)
1300
                nr = rows;
1301
        else if (!nr)
1302
                nr = 1;
1303
        scrdown (currcons, y, bottom, nr);
1304
        need_wrap = 0;
1305
}
1306
 
1307
static void csi_P(int currcons, unsigned int nr)
1308
{
1309
        int i;
1310
        unsigned short *p, *end;
1311
 
1312
        if (nr > cols - x)
1313
                nr = cols - x;
1314
        else if (!nr)
1315
                nr = 1;
1316
 
1317
        p = pos;
1318
        end = pos + cols - x - nr;
1319
        while (p < end)
1320
          *p = p[nr], p++;
1321
        for (i = 0; i < nr; i++)
1322
          *p++ = video_erase_char;
1323
        need_wrap = 0;
1324
 
1325
        if (currcons != fg_console)
1326
          return;
1327
 
1328
        sw->con_bmove (vc_cons[currcons].d, y, x + nr, y, x,
1329
                       1, cols - x - nr);
1330
 
1331
        while (nr--)
1332
          sw->con_putc (vc_cons[currcons].d, video_erase_char & 0x00ff,
1333
                        y, cols - 1 - nr);
1334
}
1335
 
1336
static void csi_M(int currcons, unsigned int nr)
1337
{
1338
        if (nr > rows)
1339
                nr = rows;
1340
        else if (!nr)
1341
                nr=1;
1342
        scrup (currcons, y, bottom, nr);
1343
        need_wrap = 0;
1344
}
1345
 
1346
static void save_cur(int currcons)
1347
{
1348
        saved_x         = x;
1349
        saved_y         = y;
1350
        s_intensity     = intensity;
1351
        s_underline     = underline;
1352
        s_blink         = blink;
1353
        s_reverse       = reverse;
1354
        s_charset       = charset;
1355
        s_color         = color;
1356
        saved_G0        = G0_charset;
1357
        saved_G1        = G1_charset;
1358
}
1359
 
1360
static void restore_cur(int currcons)
1361
{
1362
        gotoxy(currcons,saved_x,saved_y);
1363
        intensity       = s_intensity;
1364
        underline       = s_underline;
1365
        blink           = s_blink;
1366
        reverse         = s_reverse;
1367
        charset         = s_charset;
1368
        color           = s_color;
1369
        G0_charset      = saved_G0;
1370
        G1_charset      = saved_G1;
1371
        translate       = set_translate(charset ? G1_charset : G0_charset);
1372
        update_attr(currcons);
1373
        need_wrap = 0;
1374
}
1375
 
1376
enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
1377
        EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
1378
        ESpalette };
1379
 
1380
static void reset_terminal(int currcons, int do_clear)
1381
{
1382
        top             = 0;
1383
        bottom          = rows;
1384
        vc_state        = ESnormal;
1385
        ques            = 0;
1386
        translate       = set_translate(LAT1_MAP);
1387
        G0_charset      = LAT1_MAP;
1388
        G1_charset      = GRAF_MAP;
1389
        charset         = 0;
1390
        need_wrap       = 0;
1391
        report_mouse    = 0;
1392
        utf             = 0;
1393
        utf_count       = 0;
1394
 
1395
        disp_ctrl       = 0;
1396
        toggle_meta     = 0;
1397
 
1398
        decscnm         = 0;
1399
        decom           = 0;
1400
        decawm          = 1;
1401
        deccm           = 1;
1402
        decim           = 0;
1403
 
1404
        set_kbd(decarm);
1405
        clr_kbd(decckm);
1406
        clr_kbd(kbdapplic);
1407
        clr_kbd(lnm);
1408
        kbd_table[currcons].lockstate = 0;
1409
        kbd_table[currcons].slockstate = 0;
1410
        kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
1411
        kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
1412
        set_leds();
1413
 
1414
        default_attr(currcons);
1415
        update_attr(currcons);
1416
 
1417
        tab_stop[0]      = 0x01010100;
1418
        tab_stop[1]     =
1419
        tab_stop[2]     =
1420
        tab_stop[3]     =
1421
        tab_stop[4]     = 0x01010101;
1422
 
1423
        bell_pitch = DEFAULT_BELL_PITCH;
1424
        bell_duration = DEFAULT_BELL_DURATION;
1425
 
1426
        gotoxy(currcons,0,0);
1427
        save_cur(currcons);
1428
        if (do_clear)
1429
            csi_J(currcons,2);
1430
}
1431
 
1432
/*
1433
 * Turn the Scroll-Lock LED on when the tty is stopped
1434
 */
1435
static void con_stop(struct tty_struct *tty)
1436
{
1437
        int console_num;
1438
        if (!tty)
1439
                return;
1440
        console_num = MINOR(tty->device) - (tty->driver.minor_start);
1441
        if (!vc_cons_allocated(console_num))
1442
                return;
1443
        set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1444
        set_leds();
1445
}
1446
 
1447
/*
1448
 * Turn the Scroll-Lock LED off when the console is started
1449
 */
1450
static void con_start(struct tty_struct *tty)
1451
{
1452
        int console_num;
1453
        if (!tty)
1454
                return;
1455
        console_num = MINOR(tty->device) - (tty->driver.minor_start);
1456
        if (!vc_cons_allocated(console_num))
1457
                return;
1458
        clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
1459
        set_leds();
1460
}
1461
 
1462
static int con_write(struct tty_struct * tty, int from_user,
1463
                     const unsigned char *buf, int count)
1464
{
1465
        int c, tc, ok, n = 0;
1466
        unsigned int currcons;
1467
        struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
1468
 
1469
        currcons = vt->vc_num;
1470
        if (!vc_cons_allocated(currcons)) {
1471
                /* could this happen? */
1472
                static int error = 0;
1473
                if (!error) {
1474
                        error = 1;
1475
                        printk("con_write: tty %d not allocated\n", currcons+1);
1476
                }
1477
                return 0;
1478
        }
1479
 
1480
        /* undraw cursor first */
1481
        if (currcons == fg_console)
1482
                hide_cursor(currcons);
1483
 
1484
        /* clear the selection */
1485
        if (currcons == sel_cons)
1486
                clear_selection();
1487
 
1488
        disable_bh(CONSOLE_BH);
1489
        while (count) {
1490
                enable_bh(CONSOLE_BH);
1491
                c = from_user ? get_user(buf) : *buf;
1492
                buf++; n++; count--;
1493
                disable_bh(CONSOLE_BH);
1494
 
1495
                if (utf) {
1496
                    /* Combine UTF-8 into Unicode */
1497
                    /* Incomplete characters silently ignored */
1498
                    if(c > 0x7f) {
1499
                        if (utf_count > 0 && (c & 0xc0) == 0x80) {
1500
                                utf_char = (utf_char << 6) | (c & 0x3f);
1501
                                utf_count--;
1502
                                if (utf_count == 0)
1503
                                    tc = c = utf_char;
1504
                                else continue;
1505
                        } else {
1506
                                if ((c & 0xe0) == 0xc0) {
1507
                                    utf_count = 1;
1508
                                    utf_char = (c & 0x1f);
1509
                                } else if ((c & 0xf0) == 0xe0) {
1510
                                    utf_count = 2;
1511
                                    utf_char = (c & 0x0f);
1512
                                } else if ((c & 0xf8) == 0xf0) {
1513
                                    utf_count = 3;
1514
                                    utf_char = (c & 0x07);
1515
                                } else if ((c & 0xfc) == 0xf8) {
1516
                                    utf_count = 4;
1517
                                    utf_char = (c & 0x03);
1518
                                } else if ((c & 0xfe) == 0xfc) {
1519
                                    utf_count = 5;
1520
                                    utf_char = (c & 0x01);
1521
                                } else
1522
                                    utf_count = 0;
1523
                                continue;
1524
                        }
1525
                    } else {
1526
                        tc = c;
1527
                        utf_count = 0;
1528
                    }
1529
                } else {        /* no utf */
1530
                    tc = translate[toggle_meta ? (c|0x80) : c];
1531
                }
1532
 
1533
                /* If the original code was a control character we
1534
                 * only allow a glyph to be displayed if the code is
1535
                 * not normally used (such as for cursor movement) or
1536
                 * if the disp_ctrl mode has been explicitly enabled.
1537
                 * Certain characters (as given by the CTRL_ALWAYS
1538
                 * bitmap) are always displayed as control characters,
1539
                 * as the console would be pretty useless without
1540
                 * them; to display an arbitrary font position use the
1541
                 * direct-to-font zone in UTF-8 mode.
1542
                 */
1543
                ok = tc && (c >= 32 ||
1544
                            (!utf && !(((disp_ctrl ? CTRL_ALWAYS
1545
                                         : CTRL_ACTION) >> c) & 1)))
1546
                        && (c != 127 || disp_ctrl);
1547
 
1548
                if (vc_state == ESnormal && ok) {
1549
                        /* Now try to find out how to display it */
1550
                        tc = conv_uni_to_pc(tc);
1551
                        if ( tc == -4 ) {
1552
                                /* If we got -4 (not found) then see if we have
1553
                                   defined a replacement character (U+FFFD) */
1554
                                tc = conv_uni_to_pc(0xfffd);
1555
                        } else if ( tc == -3 ) {
1556
                                /* Bad hash table -- hope for the best */
1557
                                tc = c;
1558
                        }
1559
                        if (tc & ~console_charmask)
1560
                                continue; /* Conversion failed */
1561
 
1562
                        if (need_wrap) {
1563
                                cr(currcons);
1564
                                lf(currcons);
1565
                        }
1566
 
1567
#if 1 /* XXX */
1568
                        /* DPC: 1994-04-12
1569
                         *   Speed up overstrike mode, using new putcs.
1570
                         *
1571
                         * P.S. I hate 8 spaces per tab! Use Emacs!
1572
                         */
1573
 
1574
                        /* Only use this for the foreground console,
1575
                           where we really draw the chars */
1576
 
1577
                        if (count > 2 &&
1578
                            !decim && !utf && currcons == fg_console) {
1579
                                static char putcs_buf[256];
1580
                                char   *p     = putcs_buf;
1581
                                int putcs_count  = 1;
1582
                                ushort nextx  = x + 1;
1583
 
1584
                                *p++ = tc;
1585
                                *pos++ = tc | (attr << 8);
1586
 
1587
                                if (nextx == cols) {
1588
                                        sw->con_putc(vc_cons[currcons].d,
1589
                                                     *putcs_buf, y, x);
1590
                                        pos--;
1591
                                        need_wrap = decawm;
1592
                                        continue;
1593
                                }
1594
 
1595
                                /* TAB TAB TAB - Arghh!!!! */
1596
 
1597
                                while (count)
1598
                                {
1599
                                        enable_bh(CONSOLE_BH);
1600
                                        c = from_user ? get_user(buf) : *buf;
1601
                                        disable_bh(CONSOLE_BH);
1602
                                        tc = translate[toggle_meta ? (c|0x80) : c];
1603
                                        if (!tc ||
1604
                                            !(c >= 32
1605
                                              || !(((disp_ctrl ? CTRL_ALWAYS
1606
                                                   : CTRL_ACTION) >> c) & 1)))
1607
                                          break;
1608
                                        tc = conv_uni_to_pc(tc);
1609
                                        if (tc == -4)
1610
                                          tc = conv_uni_to_pc(0xfffd);
1611
                                        else if (tc == -3)
1612
                                          tc = c;
1613
 
1614
                                        buf++; n++; count--;
1615
                                        if (tc & ~console_charmask)
1616
                                          continue; /* Conversion failed */
1617
 
1618
                                        *p++ = tc;
1619
                                        *pos++ = tc | (attr << 8);
1620
                                        ++putcs_count;
1621
                                        ++nextx;
1622
                                        if (nextx == cols ||
1623
                                            putcs_count == sizeof (putcs_buf))
1624
                                                break;
1625
                                }
1626
 
1627
                                sw->con_putcs(vc_cons[currcons].d,
1628
                                              putcs_buf, putcs_count, y, x);
1629
                                if (nextx == cols) {
1630
                                        pos--;
1631
                                        x         = cols-1;
1632
                                        need_wrap = decawm;
1633
                                } else
1634
                                        x += putcs_count;
1635
                                continue;
1636
                        }
1637
 
1638
                        /* DPC: End of putcs support */
1639
#endif
1640
 
1641
                        if (decim)
1642
                                insert_char(currcons);
1643
                        *pos = (attr << 8) + tc;
1644
                        if (currcons == fg_console)
1645
                                sw->con_putc(vc_cons[currcons].d,tc,y,x);
1646
                        if (x == cols - 1)
1647
                                need_wrap = decawm;
1648
                        else {
1649
                                pos++;
1650
                                x++;
1651
                        }
1652
                        continue;
1653
                }
1654
 
1655
                /*
1656
                 *  Control characters can be used in the _middle_
1657
                 *  of an escape sequence.
1658
                 */
1659
                switch (c) {
1660
                    case 7:
1661
                        if (bell_duration)
1662
                            kd_mksound(bell_pitch, bell_duration);
1663
                        continue;
1664
                    case 8:
1665
                        bs(currcons);
1666
                        continue;
1667
                    case 9:
1668
                        pos -= x;
1669
                        while (x < cols - 1) {
1670
                                x++;
1671
                                if (tab_stop[x >> 5] & (1 << (x & 31)))
1672
                                        break;
1673
                        }
1674
                        pos += x;
1675
                        continue;
1676
                    case 10: case 11: case 12:
1677
                        lf(currcons);
1678
                        if (!is_kbd(lnm))
1679
                                continue;
1680
                    case 13:
1681
                        cr(currcons);
1682
                        continue;
1683
                        case 14:
1684
                        charset = 1;
1685
                        translate = set_translate(G1_charset);
1686
                        disp_ctrl = 1;
1687
                        continue;
1688
                    case 15:
1689
                        charset = 0;
1690
                        translate = set_translate(G0_charset);
1691
                        disp_ctrl = 0;
1692
                        continue;
1693
                    case 24: case 26:
1694
                        vc_state = ESnormal;
1695
                        continue;
1696
                    case 27:
1697
                        vc_state = ESesc;
1698
                        continue;
1699
                    case 127:
1700
                        del(currcons);
1701
                        continue;
1702
                    case 128+27:
1703
                        vc_state = ESsquare;
1704
                        continue;
1705
                }
1706
                switch(vc_state) {
1707
                    case ESesc:
1708
                        vc_state = ESnormal;
1709
                        switch (c) {
1710
                            case '[':
1711
                                vc_state = ESsquare;
1712
                                continue;
1713
                            case ']':
1714
                                vc_state = ESnonstd;
1715
                                continue;
1716
                            case '%':
1717
                                vc_state = ESpercent;
1718
                                continue;
1719
                            case 'E':
1720
                                cr(currcons);
1721
                                lf(currcons);
1722
                                continue;
1723
                            case 'M':
1724
                                ri(currcons);
1725
                                continue;
1726
                            case 'D':
1727
                                lf(currcons);
1728
                                continue;
1729
                            case 'H':
1730
                                tab_stop[x >> 5] |= (1 << (x & 31));
1731
                                continue;
1732
                            case 'Z':
1733
                                respond_ID(tty);
1734
                                continue;
1735
                            case '7':
1736
                                save_cur(currcons);
1737
                                continue;
1738
                            case '8':
1739
                                restore_cur(currcons);
1740
                                continue;
1741
                            case '(':
1742
                                vc_state = ESsetG0;
1743
                                continue;
1744
                            case ')':
1745
                                vc_state = ESsetG1;
1746
                                continue;
1747
                            case '#':
1748
                                vc_state = EShash;
1749
                                continue;
1750
                            case 'c':
1751
                                reset_terminal(currcons,1);
1752
                                continue;
1753
                            case '>':  /* Numeric keypad */
1754
                                clr_kbd(kbdapplic);
1755
                                continue;
1756
                            case '=':  /* Appl. keypad */
1757
                                set_kbd(kbdapplic);
1758
                                continue;
1759
                        }
1760
                        continue;
1761
                    case ESnonstd:
1762
                        if (c=='P') {   /* palette escape sequence */
1763
                            for (npar=0; npar<NPAR; npar++)
1764
                                par[npar] = 0 ;
1765
                            npar = 0 ;
1766
                            vc_state = ESpalette;
1767
                            continue;
1768
                        } else if (c=='R') {   /* reset palette */
1769
#if 0
1770
                            reset_palette (currcons);
1771
#endif
1772
                            vc_state = ESnormal;
1773
                        } else
1774
                            vc_state = ESnormal;
1775
                        continue;
1776
                case ESpalette:
1777
                        if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
1778
                            par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
1779
                            if (npar==7) {
1780
#if 0
1781
                                int i = par[0]*3, j = 1;
1782
                                palette[i] = 16*par[j++];
1783
                                palette[i++] += par[j++];
1784
                                palette[i] = 16*par[j++];
1785
                                palette[i++] += par[j++];
1786
                                palette[i] = 16*par[j++];
1787
                                palette[i] += par[j];
1788
                                set_palette() ;
1789
#endif
1790
                                vc_state = ESnormal;
1791
                            }
1792
                        } else
1793
                            vc_state = ESnormal;
1794
                        continue;
1795
                    case ESsquare:
1796
                        for(npar = 0 ; npar < NPAR ; npar++)
1797
                                par[npar] = 0;
1798
                        npar = 0;
1799
                        vc_state = ESgetpars;
1800
                        if (c == '[') { /* Function key */
1801
                                vc_state=ESfunckey;
1802
                                continue;
1803
                        }
1804
                        ques = (c=='?');
1805
                        if (ques)
1806
                                continue;
1807
                    case ESgetpars:
1808
                        if (c==';' && npar<NPAR-1) {
1809
                                npar++;
1810
                                continue;
1811
                        } else if (c>='0' && c<='9') {
1812
                                par[npar] *= 10;
1813
                                par[npar] += c-'0';
1814
                                continue;
1815
                        } else vc_state=ESgotpars;
1816
                    case ESgotpars:
1817
                        vc_state = ESnormal;
1818
                        switch(c) {
1819
                            case 'h':
1820
                                set_mode(currcons,1);
1821
                                continue;
1822
                            case 'l':
1823
                                set_mode(currcons,0);
1824
                                continue;
1825
                            case 'n':
1826
                                if (!ques)
1827
                                        if (par[0] == 5)
1828
                                                status_report(tty);
1829
                                        else if (par[0] == 6)
1830
                                                cursor_report(currcons,tty);
1831
                                continue;
1832
                        }
1833
                        if (ques) {
1834
                                ques = 0;
1835
                                continue;
1836
                        }
1837
                        switch(c) {
1838
                            case 'G': case '`':
1839
                                if (par[0]) par[0]--;
1840
                                gotoxy(currcons,par[0],y);
1841
                                continue;
1842
                            case 'A':
1843
                                if (!par[0]) par[0]++;
1844
                                gotoxy(currcons,x,y-par[0]);
1845
                                continue;
1846
                            case 'B': case 'e':
1847
                                if (!par[0]) par[0]++;
1848
                                gotoxy(currcons,x,y+par[0]);
1849
                                continue;
1850
                            case 'C': case 'a':
1851
                                if (!par[0]) par[0]++;
1852
                                gotoxy(currcons,x+par[0],y);
1853
                                continue;
1854
                            case 'D':
1855
                                if (!par[0]) par[0]++;
1856
                                gotoxy(currcons,x-par[0],y);
1857
                                continue;
1858
                            case 'E':
1859
                                if (!par[0]) par[0]++;
1860
                                gotoxy(currcons,0,y+par[0]);
1861
                                continue;
1862
                            case 'F':
1863
                                if (!par[0]) par[0]++;
1864
                                gotoxy(currcons,0,y-par[0]);
1865
                                continue;
1866
                            case 'd':
1867
                                if (par[0]) par[0]--;
1868
                                gotoxay(currcons,x,par[0]);
1869
                                continue;
1870
                            case 'H': case 'f':
1871
                                if (par[0]) par[0]--;
1872
                                if (par[1]) par[1]--;
1873
                                gotoxay(currcons,par[1],par[0]);
1874
                                continue;
1875
                            case 'J':
1876
                                csi_J(currcons,par[0]);
1877
                                continue;
1878
                            case 'K':
1879
                                csi_K(currcons,par[0]);
1880
                                continue;
1881
                            case 'L':
1882
                                csi_L(currcons,par[0]);
1883
                                continue;
1884
                            case 'M':
1885
                                csi_M(currcons,par[0]);
1886
                                continue;
1887
                            case 'P':
1888
                                csi_P(currcons,par[0]);
1889
                                continue;
1890
                            case 'c':
1891
                                if (!par[0])
1892
                                        respond_ID(tty);
1893
                                continue;
1894
                            case 'g':
1895
                                if (!par[0])
1896
                                        tab_stop[x >> 5] &= ~(1 << (x & 31));
1897
                                else if (par[0] == 3) {
1898
                                        tab_stop[0] =
1899
                                                tab_stop[1] =
1900
                                                        tab_stop[2] =
1901
                                                                tab_stop[3] =
1902
                                                                        tab_stop[4] = 0;
1903
                                }
1904
                                continue;
1905
                            case 'm':
1906
                                csi_m(currcons);
1907
                                continue;
1908
                            case 'q': /* DECLL - but only 3 leds */
1909
                                /* map 0,1,2,3 to 0,1,2,4 */
1910
                                if (par[0] < 4)
1911
                                        setledstate(kbd_table + currcons,
1912
                                                    (par[0] < 3) ? par[0] : 4);
1913
                                continue;
1914
                            case 'r':
1915
                                if (!par[0])
1916
                                        par[0]++;
1917
                                if (!par[1])
1918
                                        par[1] = rows;
1919
                                /* Minimum allowed region is 2 lines */
1920
                                if (par[0] < par[1] &&
1921
                                    par[1] <= rows) {
1922
                                        top=par[0]-1;
1923
                                        bottom=par[1];
1924
                                        gotoxay(currcons,0,0);
1925
                                }
1926
                                continue;
1927
                            case 's':
1928
                                save_cur(currcons);
1929
                                continue;
1930
                            case 'u':
1931
                                restore_cur(currcons);
1932
                                continue;
1933
                            case 'X':
1934
                                csi_X(currcons, par[0]);
1935
                                continue;
1936
                            case '@':
1937
                                csi_at(currcons,par[0]);
1938
                                continue;
1939
                            case ']': /* setterm functions */
1940
                                setterm_command(currcons);
1941
                                continue;
1942
                        }
1943
                        continue;
1944
                    case ESpercent:
1945
                        vc_state = ESnormal;
1946
                        switch (c) {
1947
                            case '@':  /* defined in ISO 2022 */
1948
                                utf = 0;
1949
                                continue;
1950
                            case 'G':  /* prelim official escape code */
1951
                            case '8':  /* retained for compatibility */
1952
                                utf = 1;
1953
                                continue;
1954
                        }
1955
                        continue;
1956
                    case ESfunckey:
1957
                        vc_state = ESnormal;
1958
                        continue;
1959
                    case EShash:
1960
                        vc_state = ESnormal;
1961
                        if (c == '8') {
1962
                                /* DEC screen alignment test. kludge :-) */
1963
                                video_erase_char =
1964
                                        (video_erase_char & 0xff00) | 'E';
1965
                                /* Arno:
1966
                                 * Doesn't work, because csi_J(c,2)
1967
                                 * calls con_clear and doesn't print
1968
                                 * the erase char..
1969
                                 */
1970
                                csi_J(currcons, 2);
1971
                                video_erase_char =
1972
                                        (video_erase_char & 0xff00) | ' ';
1973
                        }
1974
                        continue;
1975
                    case ESsetG0:
1976
                        if (c == '0')
1977
                                G0_charset = GRAF_MAP;
1978
                        else if (c == 'B')
1979
                                G0_charset = LAT1_MAP;
1980
                        else if (c == 'U')
1981
                                G0_charset = IBMPC_MAP;
1982
                        else if (c == 'K')
1983
                                G0_charset = USER_MAP;
1984
                        if (charset == 0)
1985
                                translate = set_translate(G0_charset);
1986
                        vc_state = ESnormal;
1987
                        continue;
1988
                    case ESsetG1:
1989
                        if (c == '0')
1990
                                G1_charset = GRAF_MAP;
1991
                        else if (c == 'B')
1992
                                G1_charset = LAT1_MAP;
1993
                        else if (c == 'U')
1994
                                G1_charset = IBMPC_MAP;
1995
                        else if (c == 'K')
1996
                                G1_charset = USER_MAP;
1997
                        if (charset == 1)
1998
                                translate = set_translate(G1_charset);
1999
                        vc_state = ESnormal;
2000
                        continue;
2001
                    default:
2002
                        vc_state = ESnormal;
2003
                }
2004
        }
2005
        if (vcmode != KD_GRAPHICS)
2006
                set_cursor(currcons);
2007
        enable_bh(CONSOLE_BH);
2008
        return n;
2009
}
2010
 
2011
static int con_write_room(struct tty_struct *tty)
2012
{
2013
        if (tty->stopped)
2014
                return 0;
2015
        return 4096;            /* No limit, really; we're not buffering */
2016
}
2017
 
2018
static int con_chars_in_buffer(struct tty_struct *tty)
2019
{
2020
        return 0;                /* we're not buffering */
2021
}
2022
 
2023
void poke_blanked_console(void)
2024
{
2025
        timer_active &= ~(1<<BLANK_TIMER);
2026
        if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
2027
                return;
2028
        if (console_blanked) {
2029
                timer_table[BLANK_TIMER].fn = unblank_screen;
2030
                timer_table[BLANK_TIMER].expires = 0;
2031
                timer_active |= 1<<BLANK_TIMER;
2032
        } else if (blankinterval) {
2033
                timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2034
                timer_active |= 1<<BLANK_TIMER;
2035
        }
2036
}
2037
 
2038
/* DPC: New version of console_print using putcs */
2039
 
2040
void console_print(const char * b)
2041
{
2042
   int currcons = fg_console;
2043
   unsigned char c;
2044
   const char *start = b;
2045
   ushort count      = 0;
2046
   ushort myx        = x;
2047
   static int printing = 0;
2048
 
2049
   if (!printable || printing)
2050
           return;       /* console not yet initialized */
2051
   printing = 1;
2052
 
2053
   if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
2054
           currcons = kmsg_redirect - 1;
2055
 
2056
   if (!vc_cons_allocated(currcons)) {
2057
           /* impossible */
2058
           printk("console_print: tty %d not allocated ??\n", currcons+1);
2059
           printing = 0;
2060
           return;
2061
   }
2062
 
2063
   /* undraw cursor first */
2064
   hide_cursor(currcons);
2065
 
2066
   /* Contrived structure to try to emulate original need_wrap behaviour
2067
    * Problems caused when we have need_wrap set on '\n' character */
2068
 
2069
   while ((c = *(b++)) != 0) {
2070
       if (c == 10 || c == 13 || c == 8 || need_wrap) {
2071
           if ((count = b - start - 1) > 0) {
2072
               sw->con_putcs(vc_cons[currcons].d, start, count ,
2073
                             y, x);
2074
               x += count;
2075
               if (need_wrap)
2076
                 x--;
2077
           }
2078
 
2079
           if (c == 8) {        /* backspace */
2080
               bs(currcons);
2081
               start = b;
2082
               myx = x;
2083
               continue;
2084
           }
2085
           if (c != 13)
2086
               lf(currcons);
2087
           cr(currcons);
2088
 
2089
           if (c == 10 || c == 13) {
2090
               start = b; myx = x; continue;
2091
           }
2092
 
2093
           start = b-1; myx = x;
2094
       }
2095
 
2096
       *pos = c | (attr << 8);
2097
       if (myx == cols - 1) {
2098
           need_wrap = 1;
2099
           continue;
2100
       }
2101
       pos++;
2102
       myx++;
2103
   }
2104
 
2105
   if ((count = b - start -1) > 0) {
2106
       sw->con_putcs(vc_cons[currcons].d, start, count ,
2107
                     y, x);
2108
       x += count;
2109
       if (x == cols)
2110
         {
2111
           x--;
2112
           need_wrap = 1;
2113
         }
2114
   }
2115
 
2116
   set_cursor(currcons);
2117
   poke_blanked_console();
2118
   printing = 0;
2119
}
2120
 
2121
/* You didn't see this... */
2122
void console_printn(const char * b, int n)
2123
{
2124
   int i;
2125
   char buf[2];
2126
 
2127
 
2128
   buf[1] = '\0';
2129
   for(i=0;i<n;i++) {
2130
     buf[0] = *b++;
2131
     console_print(buf);
2132
   }
2133
}
2134
 
2135
/*
2136
 * con_throttle and con_unthrottle are only used for
2137
 * paste_selection(), which has to stuff in a large number of
2138
 * characters...
2139
 */
2140
static void con_throttle(struct tty_struct *tty)
2141
{
2142
}
2143
 
2144
static void con_unthrottle(struct tty_struct *tty)
2145
{
2146
        struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
2147
 
2148
        wake_up_interruptible(&vt->paste_wait);
2149
}
2150
 
2151
static void vc_init(unsigned int currcons, int do_clear)
2152
{
2153
        long base = (long) vc_scrbuf[currcons];
2154
 
2155
        pos = (unsigned short *)(origin = (ulong)video_mem_start = base);
2156
        scr_end = base + screenbuf_size;
2157
        video_mem_end = base + screenbuf_size;
2158
        reset_vc(currcons);
2159
        def_color       = 0x07;   /* white */
2160
        ulcolor         = 0x0f;   /* bold white */
2161
        halfcolor       = 0x08;   /* grey */
2162
        vt_cons[currcons]->paste_wait = 0;
2163
        reset_terminal(currcons, do_clear);
2164
}
2165
 
2166
/*
2167
 * This is the console switching bottom half handler.
2168
 *
2169
 * Doing console switching in a bottom half handler allows
2170
 * us to do the switches asynchronously (needed when we want
2171
 * to switch due to a keyboard interrupt), while still giving
2172
 * us the option to easily disable it to avoid races when we
2173
 * need to write to the console.
2174
 */
2175
static void console_bh(void)
2176
{
2177
        if (want_console >= 0) {
2178
                if (want_console != fg_console) {
2179
                        change_console(want_console);
2180
                        /* we only changed when the console had already
2181
                           been allocated - a new console is not created
2182
                           in an interrupt routine */
2183
                }
2184
                want_console = -1;
2185
        }
2186
        if (do_poke_blanked_console) { /* do not unblank for a LED change */
2187
                do_poke_blanked_console = 0;
2188
                poke_blanked_console();
2189
        }
2190
}
2191
 
2192
/*
2193
 *  unsigned long con_init(unsigned long);
2194
 *
2195
 * This routine initializes console interrupts, and does nothing
2196
 * else. If you want the screen to clear, call tty_write with
2197
 * the appropriate escape-sequence.
2198
 *
2199
 * Reads the information preserved by setup.s to determine the current display
2200
 * type and sets everything accordingly.
2201
 */
2202
unsigned long con_init(unsigned long kmem_start)
2203
{
2204
 
2205
#ifdef CONFIG_FRAMEBUFFER
2206
 
2207
#if 0 /* Disable console unless some buttons are pressed */
2208
        {
2209
                int i;
2210
                for(i=0;i<200000;i++) {
2211
                        __asm__("nop");
2212
                        if ((*(volatile unsigned char*)0xFFFFF419) & (8|1))
2213
                                break;
2214
                }
2215
 
2216
                if (!((*(volatile unsigned char*)0xFFFFF419) & (8|1)))
2217
                        return;
2218
                }
2219
        }
2220
#endif  
2221
        char *display_desc = "????";
2222
        unsigned int currcons = 0;
2223
        extern int serial_debug;
2224
 
2225
 
2226
 
2227
        memset(&console_driver, 0, sizeof(struct tty_driver));
2228
        console_driver.magic = TTY_DRIVER_MAGIC;
2229
        console_driver.name = "tty";
2230
        console_driver.name_base = 1;
2231
        console_driver.major = TTY_MAJOR;
2232
#ifdef CONFIG_PILOT_CONSOLE
2233
        console_driver.minor_start = 1;
2234
#else
2235
        console_driver.minor_start = 2;
2236
#endif
2237
        console_driver.num = MAX_NR_CONSOLES;
2238
        console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
2239
        console_driver.init_termios = tty_std_termios;
2240
        console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
2241
        console_driver.refcount = &console_refcount;
2242
        console_driver.table = console_table;
2243
        console_driver.termios = console_termios;
2244
        console_driver.termios_locked = console_termios_locked;
2245
 
2246
        console_driver.open = con_open;
2247
        console_driver.write = con_write;
2248
        console_driver.write_room = con_write_room;
2249
        console_driver.chars_in_buffer = con_chars_in_buffer;
2250
        console_driver.ioctl = vt_ioctl;
2251
        console_driver.stop = con_stop;
2252
        console_driver.start = con_start;
2253
        console_driver.throttle = con_throttle;
2254
        console_driver.unthrottle = con_unthrottle;
2255
 
2256
        if (tty_register_driver(&console_driver))
2257
                panic("Couldn't register console driver\n");
2258
 
2259
        kmem_start = conswitchp->con_startup (kmem_start, &display_desc);
2260
        /*conswitchp->con_set_font (&display_desc, 0, 0, "MINI4x6");*/
2261
 
2262
        timer_table[BLANK_TIMER].fn = blank_screen;
2263
        timer_table[BLANK_TIMER].expires = 0;
2264
        if (blankinterval) {
2265
                timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2266
                timer_active |= 1<<BLANK_TIMER;
2267
        }
2268
 
2269
        /* Due to kmalloc roundup allocating statically is more efficient -
2270
           so provide MIN_NR_CONSOLES for people with very little memory */
2271
        for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
2272
                vc_cons[currcons].d = (struct vc_data *) kmem_start;
2273
                kmem_start += sizeof(struct vc_data);
2274
                vt_cons[currcons] = (struct vt_struct *) kmem_start;
2275
                kmem_start += sizeof(struct vt_struct);
2276
 
2277
                /* ++Geert: sw->con_init determines console size */
2278
                sw = conswitchp;
2279
                cons_num = currcons;
2280
                sw->con_init (vc_cons[currcons].d);
2281
                size_row = cols<<1;
2282
                screenbuf_size = rows*size_row;
2283
 
2284
                vc_scrbuf[currcons] = (unsigned short *) kmem_start;
2285
                kmem_start += screenbuf_size;
2286
                kmalloced = 0;
2287
                vc_init(currcons, currcons);
2288
        }
2289
 
2290
        currcons = fg_console = 0;
2291
 
2292
#ifdef CONFIG_PILOT_CONSOLE
2293
 
2294
        gotoxy(currcons,0,rows-1);
2295
 
2296
        csi_J(currcons, 0);
2297
        printable = 1;
2298
        /*update_screen(fg_console);*/
2299
        sw->con_cursor(vc_cons[currcons].d, CM_DRAW);
2300
        printable = 1;
2301
 
2302
        /* If "serdebug" cmd line option was present, don't register for printk */
2303
        if (!serial_debug)
2304
                register_console(console_print);
2305
 
2306
        printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
2307
                can_do_color ? "colour":"mono",
2308
                display_desc,
2309
                cols,rows,
2310
                MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
2311
#else
2312
        gotoxy(currcons,0, 0);
2313
        printable = 1;
2314
        sw->con_cursor(vc_cons[currcons].d, CM_DRAW);
2315
        printable = 1;
2316
 
2317
        printk("Console driver (without boot console): %s %s %ldx%ld, %d virtual console%s (max %d)\n",
2318
                can_do_color ? "colour":"mono",
2319
                display_desc,
2320
                cols,rows,
2321
                MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s", MAX_NR_CONSOLES);
2322
#endif
2323
        init_bh(CONSOLE_BH, console_bh);
2324
#endif
2325
        return kmem_start;
2326
}
2327
 
2328
void vesa_powerdown_screen(void)
2329
{
2330
        int currcons = fg_console;
2331
 
2332
        timer_active &= ~(1<<BLANK_TIMER);
2333
        timer_table[BLANK_TIMER].fn = unblank_screen;
2334
 
2335
        /* Power down if currently suspended (1 or 2),
2336
         * suspend if currently blanked (0),
2337
         * else do nothing (i.e. already powered down (3)).
2338
         * Called only if powerdown features are allowed.
2339
         */
2340
        switch (vesa_blank_mode) {
2341
        case 0:
2342
                sw->con_blank(2);
2343
                break;
2344
        case 1:
2345
        case 2:
2346
                sw->con_blank(4);
2347
                break;
2348
        }
2349
}
2350
 
2351
void do_blank_screen(int nopowersave)
2352
{
2353
#if 0
2354
        int currcons;
2355
 
2356
        if (console_blanked)
2357
                return;
2358
 
2359
        if (!vc_cons_allocated(fg_console)) {
2360
                /* impossible */
2361
                printk("blank_screen: tty %d not allocated ??\n", fg_console+1);
2362
                return;
2363
        }
2364
 
2365
        /* don't blank graphics */
2366
        if (vt_cons[fg_console]->vc_mode == KD_TEXT) {
2367
                if (vesa_off_interval && !nopowersave) {
2368
                        timer_table[BLANK_TIMER].fn = vesa_powerdown_screen;
2369
                        timer_table[BLANK_TIMER].expires = jiffies + vesa_off_interval;
2370
                        timer_active |= (1<<BLANK_TIMER);
2371
                } else {
2372
                        timer_active &= ~(1<<BLANK_TIMER);
2373
                        timer_table[BLANK_TIMER].fn = unblank_screen;
2374
                }
2375
 
2376
                /* try not to lose information by blanking,
2377
                   and not to waste memory */
2378
                currcons = fg_console;
2379
                has_scrolled = 0;
2380
                sw->con_blank(1);
2381
                if (!nopowersave)
2382
                        sw->con_blank(vesa_blank_mode + 1);
2383
        }
2384
        else
2385
                hide_cursor(fg_console);
2386
        console_blanked = fg_console + 1;
2387
#endif
2388
}
2389
 
2390
void do_unblank_screen(void)
2391
{
2392
#if 0
2393
        int currcons;
2394
 
2395
        if (!console_blanked)
2396
                return;
2397
        if (!vc_cons_allocated(fg_console)) {
2398
                /* impossible */
2399
                printk("unblank_screen: tty %d not allocated ??\n", fg_console+1);
2400
                return;
2401
        }
2402
        timer_table[BLANK_TIMER].fn = blank_screen;
2403
        if (blankinterval) {
2404
                timer_table[BLANK_TIMER].expires = jiffies + blankinterval;
2405
                timer_active |= 1<<BLANK_TIMER;
2406
        }
2407
 
2408
        currcons = fg_console;
2409
        console_blanked = 0;
2410
        if (sw->con_blank (0))
2411
                /* Low-level driver cannot restore -> do it ourselves */
2412
                update_screen( fg_console );
2413
        set_cursor (fg_console);
2414
#endif
2415
}
2416
 
2417
void update_screen(int new_console)
2418
{
2419
        int currcons = fg_console;
2420
        int xx, yy, startx, attr_save;
2421
        char buf[256], *bufp;
2422
        unsigned short *p;
2423
        static int lock = 0;
2424
 
2425
        if (/* new_console == fg_console || */ lock)
2426
                return;
2427
        if (!vc_cons_allocated(new_console)) {
2428
                /* strange ... */
2429
                printk("update_screen: tty %d not allocated ??\n", new_console+1);
2430
                return;
2431
        }
2432
        lock = 1;
2433
 
2434
        clear_selection();
2435
 
2436
        currcons = fg_console = new_console;
2437
        sw->con_cursor (vc_cons[currcons].d, CM_ERASE);
2438
        sw->con_switch (vc_cons[new_console].d);
2439
        /* Update the screen contents */
2440
        p = video_mem_start;
2441
        attr_save = attr;
2442
        for (yy = 0; yy < rows; yy++)
2443
          {
2444
            bufp = buf;
2445
            for (startx = xx = 0; xx < cols; xx++)
2446
              {
2447
                if (attr != ((*p >> 8) & 0xff))
2448
                  {
2449
                    if (bufp > buf)
2450
                      sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
2451
                                     yy, startx);
2452
                    startx = xx;
2453
                    bufp = buf;
2454
                    attr = (*p >> 8) & 0xff;
2455
                  }
2456
                *bufp++ = *p++;
2457
                if (bufp == buf + sizeof (buf))
2458
                  {
2459
                    sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
2460
                                   yy, startx);
2461
                    startx = xx + 1;
2462
                    bufp = buf;
2463
                  }
2464
              }
2465
            if (bufp > buf)
2466
              sw->con_putcs (vc_cons[currcons].d, buf, bufp - buf,
2467
                             yy, startx);
2468
          }
2469
        set_cursor (currcons);
2470
        attr = attr_save;
2471
        set_leds();
2472
        compute_shiftstate();
2473
        lock = 0;
2474
}
2475
 
2476
/*
2477
 * If a blank_screen is due to a timer, then a power save is allowed.
2478
 * If it is related to console_switching, then avoid vesa_blank().
2479
 */
2480
static void blank_screen(void)
2481
{
2482
        do_blank_screen(0);
2483
}
2484
 
2485
static void unblank_screen(void)
2486
{
2487
        do_unblank_screen();
2488
}
2489
 
2490
/*
2491
 * Allocate the console screen memory.
2492
 */
2493
int con_open(struct tty_struct *tty, struct file * filp)
2494
{
2495
        unsigned int currcons;
2496
        int i;
2497
 
2498
        currcons = MINOR(tty->device) - tty->driver.minor_start;
2499
 
2500
        i = vc_allocate(currcons);
2501
        if (i)
2502
                return i;
2503
 
2504
        vt_cons[currcons]->vc_num = currcons;
2505
        tty->driver_data = vt_cons[currcons];
2506
 
2507
        if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
2508
                tty->winsize.ws_row = rows;
2509
                tty->winsize.ws_col = cols;
2510
        }
2511
 
2512
        return 0;
2513
}
2514
 
2515
/*
2516
 * PIO_FONT support.
2517
 *
2518
 * Currently we only support 8 pixels wide fonts, at a maximum height
2519
 * of 32 pixels. Userspace fontdata is stored with 32 bytes reserved
2520
 * for each character which is kinda wasty, but this is done in order
2521
 * to maintain compatibility with the EGA/VGA fonts. It is upto the
2522
 * actual low-level console-driver convert data into its favorite
2523
 * format (maybe we should add a `fontoffset' field to the `display'
2524
 * structure so we wont have to convert the fontdata all the time.
2525
 * /Jes
2526
 */
2527
 
2528
#define cmapsz 8192
2529
 
2530
static int set_get_font(char * arg, int set, int ch512)
2531
{
2532
#ifdef CAN_LOAD_EGA_FONTS
2533
        int i, unit, size;
2534
        char *charmap;
2535
 
2536
        if (arg){
2537
                i = verify_area(set ? VERIFY_READ : VERIFY_WRITE,
2538
                                (void *)arg, ch512 ? 2*cmapsz : cmapsz);
2539
                if (i)
2540
                        return i;
2541
        }else
2542
                return -EINVAL;
2543
 
2544
 
2545
        size = ch512 ? 2*cmapsz : cmapsz;
2546
 
2547
        charmap = (char *)kmalloc(size, GFP_USER);
2548
 
2549
        if (set){
2550
                memcpy_fromfs(charmap, arg, size);
2551
 
2552
                for (unit = 32; unit > 0; unit--)
2553
                        for (i = 0; i < (ch512 ? 512 : 256); i++)
2554
                                if (charmap[32*i+unit-1])
2555
                                        goto nonzero;
2556
        nonzero:
2557
                i = conswitchp->con_set_font(vc_cons[fg_console].d, 8,
2558
                                             unit, charmap);
2559
        }else{
2560
                memset(charmap, 0, size);
2561
                i = conswitchp->con_get_font(vc_cons[fg_console].d,
2562
                                             &unit, &unit, charmap);
2563
                memcpy_tofs(arg, charmap, size);
2564
        }
2565
        kfree(charmap);
2566
 
2567
        return i;
2568
#else
2569
        return -EINVAL;
2570
#endif
2571
}
2572
 
2573
/*
2574
 * Load palette into the EGA/VGA DAC registers. arg points to a colour
2575
 * map, 3 bytes per colour, 16 colours, range from 0 to 255.
2576
 */
2577
 
2578
int con_set_cmap (unsigned char *arg)
2579
{
2580
        return -EINVAL;
2581
}
2582
 
2583
int con_get_cmap (unsigned char *arg)
2584
{
2585
        return -EINVAL;
2586
}
2587
 
2588
void reset_palette(int currcons)
2589
{
2590
}
2591
 
2592
void set_palette(void)
2593
{
2594
}
2595
 
2596
/*
2597
 * Load font into the EGA/VGA character generator. arg points to a 8192
2598
 * byte map, 32 bytes per character. Only first H of them are used for
2599
 * 8xH fonts (0 < H <= 32).
2600
 */
2601
 
2602
int con_set_font (char *arg, int ch512)
2603
{
2604
        int i;
2605
 
2606
        i = set_get_font (arg,1,ch512);
2607
        if ( !i ) {
2608
                hashtable_contents_valid = 0;
2609
                video_mode_512ch = ch512;
2610
                console_charmask = ch512 ? 0x1ff : 0x0ff;
2611
        }
2612
        return i;
2613
}
2614
 
2615
int con_get_font (char *arg)
2616
{
2617
        return set_get_font (arg,0,video_mode_512ch);
2618
}
2619
 
2620
/*
2621
 * Adjust the screen to fit a font of a certain height
2622
 *
2623
 * Returns < 0 for error, 0 if nothing changed, and the number
2624
 * of lines on the adjusted console if changed.
2625
 */
2626
int con_adjust_height(unsigned long fontheight)
2627
{
2628
        return -EINVAL;
2629
}
2630
 
2631
void set_vesa_blanking(int arg)
2632
{
2633
        char *argp = (char *)arg + 1;
2634
        unsigned int mode = get_fs_byte(argp);
2635
        vesa_blank_mode = (mode < 4) ? mode : 0;
2636
}
2637
 
2638
unsigned long get_video_num_lines(unsigned int currcons)
2639
{
2640
        return(rows);
2641
}
2642
 
2643
unsigned long get_video_num_columns(unsigned int currcons)
2644
{
2645
        return(cols);
2646
}
2647
 
2648
unsigned long get_video_size_row(unsigned int currcons)
2649
{
2650
        return(size_row);
2651
}
2652
 
2653
/*
2654
 * Report the current status of the vc. This is exported to modules (ARub)
2655
 */
2656
 
2657
int con_get_info(int *mode, int *shift, int *col, int *row,
2658
                        struct tty_struct **tty)
2659
{
2660
        extern int shift_state;
2661
        extern struct tty_driver console_driver;
2662
        struct tty_struct **console_table=console_driver.table;
2663
 
2664
        if (mode) *mode = vt_cons[fg_console]->vc_mode;
2665
        if (shift) *shift = shift_state;
2666
        if (col) *col = video_num_columns;
2667
        if (row) *row = video_num_lines;
2668
        if (tty) *tty = console_table[fg_console];
2669
        return fg_console;
2670
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.