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

Subversion Repositories or1k

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

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

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

powered by: WebSVN 2.1.0

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