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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [char/] [console.c] - Blame information for rev 1777

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

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

powered by: WebSVN 2.1.0

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