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

Subversion Repositories or1k

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

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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