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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [vt.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/char/vt.c
3
 *
4
 *  Copyright (C) 1992 obz under the linux copyright
5
 *
6
 *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
7
 *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
8
 *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
9
 *  Some code moved for less code duplication - Andi Kleen - Mar 1997
10
 *  Check put/get_user, cleanups - acme@conectiva.com.br - Jun 2001
11
 */
12
 
13
#include <linux/config.h>
14
#include <linux/types.h>
15
#include <linux/errno.h>
16
#include <linux/sched.h>
17
#include <linux/tty.h>
18
#include <linux/timer.h>
19
#include <linux/kernel.h>
20
#include <linux/kd.h>
21
#include <linux/vt.h>
22
#include <linux/string.h>
23
#include <linux/slab.h>
24
#include <linux/major.h>
25
#include <linux/fs.h>
26
#include <linux/console.h>
27
 
28
#include <asm/io.h>
29
#include <asm/uaccess.h>
30
 
31
#include <linux/kbd_kern.h>
32
#include <linux/vt_kern.h>
33
#include <linux/kbd_diacr.h>
34
#include <linux/selection.h>
35
 
36
#ifdef CONFIG_FB_COMPAT_XPMAC
37
#include <asm/vc_ioctl.h>
38
#endif /* CONFIG_FB_COMPAT_XPMAC */
39
 
40
char vt_dont_switch;
41
extern struct tty_driver console_driver;
42
 
43
#define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
44
#define VT_BUSY(i)      (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
45
 
46
/*
47
 * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
48
 * experimentation and study of X386 SYSV handling.
49
 *
50
 * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
51
 * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
52
 * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
53
 * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
54
 * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
55
 * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
56
 * to the current console is done by the main ioctl code.
57
 */
58
 
59
struct vt_struct *vt_cons[MAX_NR_CONSOLES];
60
 
61
/* Keyboard type: Default is KB_101, but can be set by machine
62
 * specific code.
63
 */
64
unsigned char keyboard_type = KB_101;
65
 
66
#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__)
67
asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
68
#endif
69
 
70
unsigned int video_font_height;
71
unsigned int default_font_height;
72
unsigned int video_scan_lines;
73
 
74
/*
75
 * these are the valid i/o ports we're allowed to change. they map all the
76
 * video ports
77
 */
78
#define GPFIRST 0x3b4
79
#define GPLAST 0x3df
80
#define GPNUM (GPLAST - GPFIRST + 1)
81
 
82
/*
83
 * Generates sound of some frequency for some number of clock ticks
84
 *
85
 * If freq is 0, will turn off sound, else will turn it on for that time.
86
 * If msec is 0, will return immediately, else will sleep for msec time, then
87
 * turn sound off.
88
 *
89
 * We also return immediately, which is what was implied within the X
90
 * comments - KDMKTONE doesn't put the process to sleep.
91
 */
92
 
93
#if defined(__i386__) || defined(__alpha__) || defined(CONFIG_PPC_ISATIMER) \
94
    || (defined(__mips__) && defined(CONFIG_ISA)) \
95
    || (defined(__arm__) && defined(CONFIG_HOST_FOOTBRIDGE)) \
96
    || defined(__x86_64__)
97
 
98
static void
99
kd_nosound(unsigned long ignored)
100
{
101
        /* disable counter 2 */
102
        outb(inb_p(0x61)&0xFC, 0x61);
103
        return;
104
}
105
 
106
void
107
_kd_mksound(unsigned int hz, unsigned int ticks)
108
{
109
        static struct timer_list sound_timer = { function: kd_nosound };
110
        unsigned int count = 0;
111
        unsigned long flags;
112
 
113
        if (hz > 20 && hz < 32767)
114
                count = 1193180 / hz;
115
 
116
        save_flags(flags);
117
        cli();
118
        del_timer(&sound_timer);
119
        if (count) {
120
                /* enable counter 2 */
121
                outb_p(inb_p(0x61)|3, 0x61);
122
                /* set command for counter 2, 2 byte write */
123
                outb_p(0xB6, 0x43);
124
                /* select desired HZ */
125
                outb_p(count & 0xff, 0x42);
126
                outb((count >> 8) & 0xff, 0x42);
127
 
128
                if (ticks) {
129
                        sound_timer.expires = jiffies+ticks;
130
                        add_timer(&sound_timer);
131
                }
132
        } else
133
                kd_nosound(0);
134
        restore_flags(flags);
135
        return;
136
}
137
 
138
#else
139
 
140
void
141
_kd_mksound(unsigned int hz, unsigned int ticks)
142
{
143
}
144
 
145
#endif
146
 
147
int _kbd_rate(struct kbd_repeat *rep)
148
{
149
        return -EINVAL;
150
}
151
 
152
void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
153
int (*kbd_rate)(struct kbd_repeat *rep) = _kbd_rate;
154
 
155
#define i (tmp.kb_index)
156
#define s (tmp.kb_table)
157
#define v (tmp.kb_value)
158
static inline int
159
do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kbd)
160
{
161
        struct kbentry tmp;
162
        ushort *key_map, val, ov;
163
 
164
        if (copy_from_user(&tmp, user_kbe, sizeof(struct kbentry)))
165
                return -EFAULT;
166
        if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
167
                return -EINVAL;
168
 
169
        switch (cmd) {
170
        case KDGKBENT:
171
                key_map = key_maps[s];
172
                if (key_map) {
173
                    val = U(key_map[i]);
174
                    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
175
                        val = K_HOLE;
176
                } else
177
                    val = (i ? K_HOLE : K_NOSUCHMAP);
178
                return put_user(val, &user_kbe->kb_value);
179
        case KDSKBENT:
180
                if (!perm)
181
                        return -EPERM;
182
                if (!i && v == K_NOSUCHMAP) {
183
                        /* disallocate map */
184
                        key_map = key_maps[s];
185
                        if (s && key_map) {
186
                            key_maps[s] = 0;
187
                            if (key_map[0] == U(K_ALLOCATED)) {
188
                                        kfree(key_map);
189
                                        keymap_count--;
190
                            }
191
                        }
192
                        break;
193
                }
194
 
195
                if (KTYP(v) < NR_TYPES) {
196
                    if (KVAL(v) > max_vals[KTYP(v)])
197
                                return -EINVAL;
198
                } else
199
                    if (kbd->kbdmode != VC_UNICODE)
200
                                return -EINVAL;
201
 
202
                /* ++Geert: non-PC keyboards may generate keycode zero */
203
#if !defined(__mc68000__) && !defined(__powerpc__)
204
                /* assignment to entry 0 only tests validity of args */
205
                if (!i)
206
                        break;
207
#endif
208
 
209
                if (!(key_map = key_maps[s])) {
210
                        int j;
211
 
212
                        if (keymap_count >= MAX_NR_OF_USER_KEYMAPS &&
213
                            !capable(CAP_SYS_RESOURCE))
214
                                return -EPERM;
215
 
216
                        key_map = (ushort *) kmalloc(sizeof(plain_map),
217
                                                     GFP_KERNEL);
218
                        if (!key_map)
219
                                return -ENOMEM;
220
                        key_maps[s] = key_map;
221
                        key_map[0] = U(K_ALLOCATED);
222
                        for (j = 1; j < NR_KEYS; j++)
223
                                key_map[j] = U(K_HOLE);
224
                        keymap_count++;
225
                }
226
                ov = U(key_map[i]);
227
                if (v == ov)
228
                        break;  /* nothing to do */
229
                /*
230
                 * Attention Key.
231
                 */
232
                if (((ov == K_SAK) || (v == K_SAK)) && !capable(CAP_SYS_ADMIN))
233
                        return -EPERM;
234
                key_map[i] = U(v);
235
                if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
236
                        compute_shiftstate();
237
                break;
238
        }
239
        return 0;
240
}
241
#undef i
242
#undef s
243
#undef v
244
 
245
static inline int
246
do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm)
247
{
248
        struct kbkeycode tmp;
249
        int kc = 0;
250
 
251
        if (copy_from_user(&tmp, user_kbkc, sizeof(struct kbkeycode)))
252
                return -EFAULT;
253
        switch (cmd) {
254
        case KDGETKEYCODE:
255
                kc = getkeycode(tmp.scancode);
256
                if (kc >= 0)
257
                        kc = put_user(kc, &user_kbkc->keycode);
258
                break;
259
        case KDSETKEYCODE:
260
                if (!perm)
261
                        return -EPERM;
262
                kc = setkeycode(tmp.scancode, tmp.keycode);
263
                break;
264
        }
265
        return kc;
266
}
267
 
268
static inline int
269
do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
270
{
271
        struct kbsentry tmp;
272
        char *p;
273
        u_char *q;
274
        int sz;
275
        int delta;
276
        char *first_free, *fj, *fnw;
277
        int i, j, k;
278
 
279
        /* we mostly copy too much here (512bytes), but who cares ;) */
280
        if (copy_from_user(&tmp, user_kdgkb, sizeof(struct kbsentry)))
281
                return -EFAULT;
282
        tmp.kb_string[sizeof(tmp.kb_string)-1] = '\0';
283
        if (tmp.kb_func >= MAX_NR_FUNC)
284
                return -EINVAL;
285
        i = tmp.kb_func;
286
 
287
        switch (cmd) {
288
        case KDGKBSENT:
289
                sz = sizeof(tmp.kb_string) - 1; /* sz should have been
290
                                                  a struct member */
291
                q = user_kdgkb->kb_string;
292
                p = func_table[i];
293
                if(p)
294
                        for ( ; *p && sz; p++, sz--)
295
                                if (put_user(*p, q++))
296
                                        return -EFAULT;
297
                if (put_user('\0', q))
298
                        return -EFAULT;
299
                return ((p && *p) ? -EOVERFLOW : 0);
300
        case KDSKBSENT:
301
                if (!perm)
302
                        return -EPERM;
303
 
304
                q = func_table[i];
305
                first_free = funcbufptr + (funcbufsize - funcbufleft);
306
                for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
307
                        ;
308
                if (j < MAX_NR_FUNC)
309
                        fj = func_table[j];
310
                else
311
                        fj = first_free;
312
 
313
                delta = (q ? -strlen(q) : 1) + strlen(tmp.kb_string);
314
                if (delta <= funcbufleft) {     /* it fits in current buf */
315
                    if (j < MAX_NR_FUNC) {
316
                        memmove(fj + delta, fj, first_free - fj);
317
                        for (k = j; k < MAX_NR_FUNC; k++)
318
                            if (func_table[k])
319
                                func_table[k] += delta;
320
                    }
321
                    if (!q)
322
                      func_table[i] = fj;
323
                    funcbufleft -= delta;
324
                } else {                        /* allocate a larger buffer */
325
                    sz = 256;
326
                    while (sz < funcbufsize - funcbufleft + delta)
327
                      sz <<= 1;
328
                    fnw = (char *) kmalloc(sz, GFP_KERNEL);
329
                    if(!fnw)
330
                      return -ENOMEM;
331
 
332
                    if (!q)
333
                      func_table[i] = fj;
334
                    if (fj > funcbufptr)
335
                        memmove(fnw, funcbufptr, fj - funcbufptr);
336
                    for (k = 0; k < j; k++)
337
                      if (func_table[k])
338
                        func_table[k] = fnw + (func_table[k] - funcbufptr);
339
 
340
                    if (first_free > fj) {
341
                        memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
342
                        for (k = j; k < MAX_NR_FUNC; k++)
343
                          if (func_table[k])
344
                            func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
345
                    }
346
                    if (funcbufptr != func_buf)
347
                      kfree(funcbufptr);
348
                    funcbufptr = fnw;
349
                    funcbufleft = funcbufleft - delta + sz - funcbufsize;
350
                    funcbufsize = sz;
351
                }
352
                strcpy(func_table[i], tmp.kb_string);
353
                break;
354
        }
355
        return 0;
356
}
357
 
358
static inline int
359
do_fontx_ioctl(int cmd, struct consolefontdesc *user_cfd, int perm)
360
{
361
        struct consolefontdesc cfdarg;
362
        struct console_font_op op;
363
        int i;
364
 
365
        if (copy_from_user(&cfdarg, user_cfd, sizeof(struct consolefontdesc)))
366
                return -EFAULT;
367
 
368
        switch (cmd) {
369
        case PIO_FONTX:
370
                if (!perm)
371
                        return -EPERM;
372
                op.op = KD_FONT_OP_SET;
373
                op.flags = KD_FONT_FLAG_OLD;
374
                op.width = 8;
375
                op.height = cfdarg.charheight;
376
                op.charcount = cfdarg.charcount;
377
                op.data = cfdarg.chardata;
378
                return con_font_op(fg_console, &op);
379
        case GIO_FONTX: {
380
                op.op = KD_FONT_OP_GET;
381
                op.flags = KD_FONT_FLAG_OLD;
382
                op.width = 8;
383
                op.height = cfdarg.charheight;
384
                op.charcount = cfdarg.charcount;
385
                op.data = cfdarg.chardata;
386
                i = con_font_op(fg_console, &op);
387
                if (i)
388
                        return i;
389
                cfdarg.charheight = op.height;
390
                cfdarg.charcount = op.charcount;
391
                if (copy_to_user(user_cfd, &cfdarg, sizeof(struct consolefontdesc)))
392
                        return -EFAULT;
393
                return 0;
394
                }
395
        }
396
        return -EINVAL;
397
}
398
 
399
static inline int
400
do_unimap_ioctl(int cmd, struct unimapdesc *user_ud,int perm)
401
{
402
        struct unimapdesc tmp;
403
        int i = 0;
404
 
405
        if (copy_from_user(&tmp, user_ud, sizeof tmp))
406
                return -EFAULT;
407
        if (tmp.entries) {
408
                i = verify_area(VERIFY_WRITE, tmp.entries,
409
                                                tmp.entry_ct*sizeof(struct unipair));
410
                if (i) return i;
411
        }
412
        switch (cmd) {
413
        case PIO_UNIMAP:
414
                if (!perm)
415
                        return -EPERM;
416
                return con_set_unimap(fg_console, tmp.entry_ct, tmp.entries);
417
        case GIO_UNIMAP:
418
                return con_get_unimap(fg_console, tmp.entry_ct, &(user_ud->entry_ct), tmp.entries);
419
        }
420
        return 0;
421
}
422
 
423
/*
424
 * We handle the console-specific ioctl's here.  We allow the
425
 * capability to modify any console, not just the fg_console.
426
 */
427
int vt_ioctl(struct tty_struct *tty, struct file * file,
428
             unsigned int cmd, unsigned long arg)
429
{
430
        int i, perm;
431
        unsigned int console;
432
        unsigned char ucval;
433
        struct kbd_struct * kbd;
434
        struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
435
 
436
        console = vt->vc_num;
437
 
438
        if (!vc_cons_allocated(console))        /* impossible? */
439
                return -ENOIOCTLCMD;
440
 
441
        /*
442
         * To have permissions to do most of the vt ioctls, we either have
443
         * to be the owner of the tty, or super-user.
444
         */
445
        perm = 0;
446
        if (current->tty == tty || suser())
447
                perm = 1;
448
 
449
        kbd = kbd_table + console;
450
        switch (cmd) {
451
        case KIOCSOUND:
452
                if (!perm)
453
                        return -EPERM;
454
                if (arg)
455
                        arg = 1193180 / arg;
456
                kd_mksound(arg, 0);
457
                return 0;
458
 
459
        case KDMKTONE:
460
                if (!perm)
461
                        return -EPERM;
462
        {
463
                unsigned int ticks, count;
464
 
465
                /*
466
                 * Generate the tone for the appropriate number of ticks.
467
                 * If the time is zero, turn off sound ourselves.
468
                 */
469
                ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
470
                count = ticks ? (arg & 0xffff) : 0;
471
                if (count)
472
                        count = 1193180 / count;
473
                kd_mksound(count, ticks);
474
                return 0;
475
        }
476
 
477
        case KDGKBTYPE:
478
                /*
479
                 * this is naive.
480
                 */
481
                ucval = keyboard_type;
482
                goto setchar;
483
 
484
#if defined(CONFIG_X86)
485
                /*
486
                 * These cannot be implemented on any machine that implements
487
                 * ioperm() in user level (such as Alpha PCs).
488
                 */
489
        case KDADDIO:
490
        case KDDELIO:
491
                /*
492
                 * KDADDIO and KDDELIO may be able to add ports beyond what
493
                 * we reject here, but to be safe...
494
                 */
495
                if (arg < GPFIRST || arg > GPLAST)
496
                        return -EINVAL;
497
                return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
498
 
499
        case KDENABIO:
500
        case KDDISABIO:
501
                return sys_ioperm(GPFIRST, GPNUM,
502
                                  (cmd == KDENABIO)) ? -ENXIO : 0;
503
#endif
504
 
505
        /* Linux m68k/i386 interface for setting the keyboard delay/repeat rate */
506
 
507
        case KDKBDREP:
508
        {
509
                struct kbd_repeat kbrep;
510
 
511
                if (!capable(CAP_SYS_ADMIN))
512
                        return -EPERM;
513
 
514
                if (copy_from_user(&kbrep, (void *)arg,
515
                                   sizeof(struct kbd_repeat)))
516
                        return -EFAULT;
517
                if ((i = kbd_rate( &kbrep )))
518
                        return i;
519
                if (copy_to_user((void *)arg, &kbrep,
520
                                 sizeof(struct kbd_repeat)))
521
                        return -EFAULT;
522
                return 0;
523
        }
524
 
525
        case KDSETMODE:
526
                /*
527
                 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
528
                 * doesn't do a whole lot. i'm not sure if it should do any
529
                 * restoration of modes or what...
530
                 */
531
                if (!perm)
532
                        return -EPERM;
533
                switch (arg) {
534
                case KD_GRAPHICS:
535
                        break;
536
                case KD_TEXT0:
537
                case KD_TEXT1:
538
                        arg = KD_TEXT;
539
                case KD_TEXT:
540
                        break;
541
                default:
542
                        return -EINVAL;
543
                }
544
                if (vt_cons[console]->vc_mode == (unsigned char) arg)
545
                        return 0;
546
                vt_cons[console]->vc_mode = (unsigned char) arg;
547
                if (console != fg_console)
548
                        return 0;
549
                /*
550
                 * explicitly blank/unblank the screen if switching modes
551
                 */
552
                if (arg == KD_TEXT)
553
                        unblank_screen();
554
                else
555
                        do_blank_screen(1);
556
                return 0;
557
 
558
        case KDGETMODE:
559
                ucval = vt_cons[console]->vc_mode;
560
                goto setint;
561
 
562
        case KDMAPDISP:
563
        case KDUNMAPDISP:
564
                /*
565
                 * these work like a combination of mmap and KDENABIO.
566
                 * this could be easily finished.
567
                 */
568
                return -EINVAL;
569
 
570
        case KDSKBMODE:
571
                if (!perm)
572
                        return -EPERM;
573
                switch(arg) {
574
                  case K_RAW:
575
                        kbd->kbdmode = VC_RAW;
576
                        break;
577
                  case K_MEDIUMRAW:
578
                        kbd->kbdmode = VC_MEDIUMRAW;
579
                        break;
580
                  case K_XLATE:
581
                        kbd->kbdmode = VC_XLATE;
582
                        compute_shiftstate();
583
                        break;
584
                  case K_UNICODE:
585
                        kbd->kbdmode = VC_UNICODE;
586
                        compute_shiftstate();
587
                        break;
588
                  default:
589
                        return -EINVAL;
590
                }
591
                if (tty->ldisc.flush_buffer)
592
                        tty->ldisc.flush_buffer(tty);
593
                return 0;
594
 
595
        case KDGKBMODE:
596
                ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
597
                                 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
598
                                 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
599
                                 K_XLATE);
600
                goto setint;
601
 
602
        /* this could be folded into KDSKBMODE, but for compatibility
603
           reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
604
        case KDSKBMETA:
605
                switch(arg) {
606
                  case K_METABIT:
607
                        clr_vc_kbd_mode(kbd, VC_META);
608
                        break;
609
                  case K_ESCPREFIX:
610
                        set_vc_kbd_mode(kbd, VC_META);
611
                        break;
612
                  default:
613
                        return -EINVAL;
614
                }
615
                return 0;
616
 
617
        case KDGKBMETA:
618
                ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
619
        setint:
620
                return put_user(ucval, (int *)arg);
621
 
622
        case KDGETKEYCODE:
623
        case KDSETKEYCODE:
624
                if(!capable(CAP_SYS_ADMIN))
625
                        perm=0;
626
                return do_kbkeycode_ioctl(cmd, (struct kbkeycode *)arg, perm);
627
 
628
        case KDGKBENT:
629
        case KDSKBENT:
630
                return do_kdsk_ioctl(cmd, (struct kbentry *)arg, perm, kbd);
631
 
632
        case KDGKBSENT:
633
        case KDSKBSENT:
634
                return do_kdgkb_ioctl(cmd, (struct kbsentry *)arg, perm);
635
 
636
        case KDGKBDIACR:
637
        {
638
                struct kbdiacrs *a = (struct kbdiacrs *)arg;
639
 
640
                if (put_user(accent_table_size, &a->kb_cnt))
641
                        return -EFAULT;
642
                if (copy_to_user(a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr)))
643
                        return -EFAULT;
644
                return 0;
645
        }
646
 
647
        case KDSKBDIACR:
648
        {
649
                struct kbdiacrs *a = (struct kbdiacrs *)arg;
650
                unsigned int ct;
651
 
652
                if (!perm)
653
                        return -EPERM;
654
                if (get_user(ct,&a->kb_cnt))
655
                        return -EFAULT;
656
                if (ct >= MAX_DIACR)
657
                        return -EINVAL;
658
                accent_table_size = ct;
659
                if (copy_from_user(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr)))
660
                        return -EFAULT;
661
                return 0;
662
        }
663
 
664
        /* the ioctls below read/set the flags usually shown in the leds */
665
        /* don't use them - they will go away without warning */
666
        case KDGKBLED:
667
                ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
668
                goto setchar;
669
 
670
        case KDSKBLED:
671
                if (!perm)
672
                        return -EPERM;
673
                if (arg & ~0x77)
674
                        return -EINVAL;
675
                kbd->ledflagstate = (arg & 7);
676
                kbd->default_ledflagstate = ((arg >> 4) & 7);
677
                set_leds();
678
                return 0;
679
 
680
        /* the ioctls below only set the lights, not the functions */
681
        /* for those, see KDGKBLED and KDSKBLED above */
682
        case KDGETLED:
683
                ucval = getledstate();
684
        setchar:
685
                return put_user(ucval, (char*)arg);
686
 
687
        case KDSETLED:
688
                if (!perm)
689
                  return -EPERM;
690
                setledstate(kbd, arg);
691
                return 0;
692
 
693
        /*
694
         * A process can indicate its willingness to accept signals
695
         * generated by pressing an appropriate key combination.
696
         * Thus, one can have a daemon that e.g. spawns a new console
697
         * upon a keypress and then changes to it.
698
         * Probably init should be changed to do this (and have a
699
         * field ks (`keyboard signal') in inittab describing the
700
         * desired action), so that the number of background daemons
701
         * does not increase.
702
         */
703
        case KDSIGACCEPT:
704
        {
705
                extern int spawnpid, spawnsig;
706
                if (!perm || !capable(CAP_KILL))
707
                  return -EPERM;
708
                if (arg < 1 || arg > _NSIG || arg == SIGKILL)
709
                  return -EINVAL;
710
                spawnpid = current->pid;
711
                spawnsig = arg;
712
                return 0;
713
        }
714
 
715
        case VT_SETMODE:
716
        {
717
                struct vt_mode tmp;
718
 
719
                if (!perm)
720
                        return -EPERM;
721
                if (copy_from_user(&tmp, (void*)arg, sizeof(struct vt_mode)))
722
                        return -EFAULT;
723
                if (tmp.mode != VT_AUTO && tmp.mode != VT_PROCESS)
724
                        return -EINVAL;
725
                vt_cons[console]->vt_mode = tmp;
726
                /* the frsig is ignored, so we set it to 0 */
727
                vt_cons[console]->vt_mode.frsig = 0;
728
                vt_cons[console]->vt_pid = current->pid;
729
                /* no switch is required -- saw@shade.msu.ru */
730
                vt_cons[console]->vt_newvt = -1;
731
                return 0;
732
        }
733
 
734
        case VT_GETMODE:
735
                return copy_to_user((void*)arg, &(vt_cons[console]->vt_mode),
736
                                                        sizeof(struct vt_mode)) ? -EFAULT : 0;
737
 
738
        /*
739
         * Returns global vt state. Note that VT 0 is always open, since
740
         * it's an alias for the current VT, and people can't use it here.
741
         * We cannot return state for more than 16 VTs, since v_state is short.
742
         */
743
        case VT_GETSTATE:
744
        {
745
                struct vt_stat *vtstat = (struct vt_stat *)arg;
746
                unsigned short state, mask;
747
 
748
                if (put_user(fg_console + 1, &vtstat->v_active))
749
                        return -EFAULT;
750
                state = 1;      /* /dev/tty0 is always open */
751
                for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
752
                        if (VT_IS_IN_USE(i))
753
                                state |= mask;
754
                return put_user(state, &vtstat->v_state);
755
        }
756
 
757
        /*
758
         * Returns the first available (non-opened) console.
759
         */
760
        case VT_OPENQRY:
761
                for (i = 0; i < MAX_NR_CONSOLES; ++i)
762
                        if (! VT_IS_IN_USE(i))
763
                                break;
764
                ucval = i < MAX_NR_CONSOLES ? (i+1) : -1;
765
                goto setint;
766
 
767
        /*
768
         * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
769
         * with num >= 1 (switches to vt 0, our console, are not allowed, just
770
         * to preserve sanity).
771
         */
772
        case VT_ACTIVATE:
773
                if (!perm)
774
                        return -EPERM;
775
                if (arg == 0 || arg > MAX_NR_CONSOLES)
776
                        return -ENXIO;
777
                arg--;
778
                i = vc_allocate(arg);
779
                if (i)
780
                        return i;
781
                set_console(arg);
782
                return 0;
783
 
784
        /*
785
         * wait until the specified VT has been activated
786
         */
787
        case VT_WAITACTIVE:
788
                if (!perm)
789
                        return -EPERM;
790
                if (arg == 0 || arg > MAX_NR_CONSOLES)
791
                        return -ENXIO;
792
                return vt_waitactive(arg-1);
793
 
794
        /*
795
         * If a vt is under process control, the kernel will not switch to it
796
         * immediately, but postpone the operation until the process calls this
797
         * ioctl, allowing the switch to complete.
798
         *
799
         * According to the X sources this is the behavior:
800
         *      0:      pending switch-from not OK
801
         *      1:      pending switch-from OK
802
         *      2:      completed switch-to OK
803
         */
804
        case VT_RELDISP:
805
                if (!perm)
806
                        return -EPERM;
807
                if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
808
                        return -EINVAL;
809
 
810
                /*
811
                 * Switching-from response
812
                 */
813
                if (vt_cons[console]->vt_newvt >= 0)
814
                {
815
                        if (arg == 0)
816
                                /*
817
                                 * Switch disallowed, so forget we were trying
818
                                 * to do it.
819
                                 */
820
                                vt_cons[console]->vt_newvt = -1;
821
 
822
                        else
823
                        {
824
                                /*
825
                                 * The current vt has been released, so
826
                                 * complete the switch.
827
                                 */
828
                                int newvt = vt_cons[console]->vt_newvt;
829
                                vt_cons[console]->vt_newvt = -1;
830
                                i = vc_allocate(newvt);
831
                                if (i)
832
                                        return i;
833
                                /*
834
                                 * When we actually do the console switch,
835
                                 * make sure we are atomic with respect to
836
                                 * other console switches..
837
                                 */
838
                                acquire_console_sem();
839
                                complete_change_console(newvt);
840
                                release_console_sem();
841
                        }
842
                }
843
 
844
                /*
845
                 * Switched-to response
846
                 */
847
                else
848
                {
849
                        /*
850
                         * If it's just an ACK, ignore it
851
                         */
852
                        if (arg != VT_ACKACQ)
853
                                return -EINVAL;
854
                }
855
 
856
                return 0;
857
 
858
         /*
859
          * Disallocate memory associated to VT (but leave VT1)
860
          */
861
         case VT_DISALLOCATE:
862
                if (arg > MAX_NR_CONSOLES)
863
                        return -ENXIO;
864
                if (arg == 0) {
865
                    /* disallocate all unused consoles, but leave 0 */
866
                    for (i=1; i<MAX_NR_CONSOLES; i++)
867
                      if (! VT_BUSY(i))
868
                        vc_disallocate(i);
869
                } else {
870
                    /* disallocate a single console, if possible */
871
                    arg--;
872
                    if (VT_BUSY(arg))
873
                      return -EBUSY;
874
                    if (arg)                          /* leave 0 */
875
                      vc_disallocate(arg);
876
                }
877
                return 0;
878
 
879
        case VT_RESIZE:
880
        {
881
                struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
882
                ushort ll,cc;
883
                if (!perm)
884
                        return -EPERM;
885
                if (get_user(ll, &vtsizes->v_rows) ||
886
                    get_user(cc, &vtsizes->v_cols))
887
                        return -EFAULT;
888
                return vc_resize_all(ll, cc);
889
        }
890
 
891
        case VT_RESIZEX:
892
        {
893
                struct vt_consize *vtconsize = (struct vt_consize *) arg;
894
                ushort ll,cc,vlin,clin,vcol,ccol;
895
                if (!perm)
896
                        return -EPERM;
897
                if (verify_area(VERIFY_READ, (void *)vtconsize,
898
                                sizeof(struct vt_consize)))
899
                        return -EFAULT;
900
                __get_user(ll, &vtconsize->v_rows);
901
                __get_user(cc, &vtconsize->v_cols);
902
                __get_user(vlin, &vtconsize->v_vlin);
903
                __get_user(clin, &vtconsize->v_clin);
904
                __get_user(vcol, &vtconsize->v_vcol);
905
                __get_user(ccol, &vtconsize->v_ccol);
906
                vlin = vlin ? vlin : video_scan_lines;
907
                if ( clin )
908
                  {
909
                    if ( ll )
910
                      {
911
                        if ( ll != vlin/clin )
912
                          return -EINVAL; /* Parameters don't add up */
913
                      }
914
                    else
915
                      ll = vlin/clin;
916
                  }
917
                if ( vcol && ccol )
918
                  {
919
                    if ( cc )
920
                      {
921
                        if ( cc != vcol/ccol )
922
                          return -EINVAL;
923
                      }
924
                    else
925
                      cc = vcol/ccol;
926
                  }
927
 
928
                if ( clin > 32 )
929
                  return -EINVAL;
930
 
931
                if ( vlin )
932
                  video_scan_lines = vlin;
933
                if ( clin )
934
                  video_font_height = clin;
935
 
936
                return vc_resize_all(ll, cc);
937
        }
938
 
939
        case PIO_FONT: {
940
                struct console_font_op op;
941
                if (!perm)
942
                        return -EPERM;
943
                op.op = KD_FONT_OP_SET;
944
                op.flags = KD_FONT_FLAG_OLD | KD_FONT_FLAG_DONT_RECALC; /* Compatibility */
945
                op.width = 8;
946
                op.height = 0;
947
                op.charcount = 256;
948
                op.data = (char *) arg;
949
                return con_font_op(fg_console, &op);
950
        }
951
 
952
        case GIO_FONT: {
953
                struct console_font_op op;
954
                op.op = KD_FONT_OP_GET;
955
                op.flags = KD_FONT_FLAG_OLD;
956
                op.width = 8;
957
                op.height = 32;
958
                op.charcount = 256;
959
                op.data = (char *) arg;
960
                return con_font_op(fg_console, &op);
961
        }
962
 
963
        case PIO_CMAP:
964
                if (!perm)
965
                        return -EPERM;
966
                return con_set_cmap((char *)arg);
967
 
968
        case GIO_CMAP:
969
                return con_get_cmap((char *)arg);
970
 
971
        case PIO_FONTX:
972
        case GIO_FONTX:
973
                return do_fontx_ioctl(cmd, (struct consolefontdesc *)arg, perm);
974
 
975
        case PIO_FONTRESET:
976
        {
977
                if (!perm)
978
                        return -EPERM;
979
 
980
#ifdef BROKEN_GRAPHICS_PROGRAMS
981
                /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
982
                   font is not saved. */
983
                return -ENOSYS;
984
#else
985
                {
986
                struct console_font_op op;
987
                op.op = KD_FONT_OP_SET_DEFAULT;
988
                op.data = NULL;
989
                i = con_font_op(fg_console, &op);
990
                if (i) return i;
991
                con_set_default_unimap(fg_console);
992
                return 0;
993
                }
994
#endif
995
        }
996
 
997
        case KDFONTOP: {
998
                struct console_font_op op;
999
                if (copy_from_user(&op, (void *) arg, sizeof(op)))
1000
                        return -EFAULT;
1001
                if (!perm && op.op != KD_FONT_OP_GET)
1002
                        return -EPERM;
1003
                i = con_font_op(console, &op);
1004
                if (i) return i;
1005
                if (copy_to_user((void *) arg, &op, sizeof(op)))
1006
                        return -EFAULT;
1007
                return 0;
1008
        }
1009
 
1010
        case PIO_SCRNMAP:
1011
                if (!perm)
1012
                        return -EPERM;
1013
                return con_set_trans_old((unsigned char *)arg);
1014
 
1015
        case GIO_SCRNMAP:
1016
                return con_get_trans_old((unsigned char *)arg);
1017
 
1018
        case PIO_UNISCRNMAP:
1019
                if (!perm)
1020
                        return -EPERM;
1021
                return con_set_trans_new((unsigned short *)arg);
1022
 
1023
        case GIO_UNISCRNMAP:
1024
                return con_get_trans_new((unsigned short *)arg);
1025
 
1026
        case PIO_UNIMAPCLR:
1027
              { struct unimapinit ui;
1028
                if (!perm)
1029
                        return -EPERM;
1030
                i = copy_from_user(&ui, (void *)arg, sizeof(struct unimapinit));
1031
                if (i) return -EFAULT;
1032
                con_clear_unimap(fg_console, &ui);
1033
                return 0;
1034
              }
1035
 
1036
        case PIO_UNIMAP:
1037
        case GIO_UNIMAP:
1038
                return do_unimap_ioctl(cmd, (struct unimapdesc *)arg, perm);
1039
 
1040
        case VT_LOCKSWITCH:
1041
                if (!suser())
1042
                   return -EPERM;
1043
                vt_dont_switch = 1;
1044
                return 0;
1045
        case VT_UNLOCKSWITCH:
1046
                if (!suser())
1047
                   return -EPERM;
1048
                vt_dont_switch = 0;
1049
                return 0;
1050
#ifdef CONFIG_FB_COMPAT_XPMAC
1051
        case VC_GETMODE:
1052
                {
1053
                        struct vc_mode mode;
1054
 
1055
                        i = verify_area(VERIFY_WRITE, (void *) arg,
1056
                                        sizeof(struct vc_mode));
1057
                        if (i == 0)
1058
                                i = console_getmode(&mode);
1059
                        if (i)
1060
                                return i;
1061
                        if (copy_to_user((void *) arg, &mode, sizeof(mode)))
1062
                                return -EFAULT;
1063
                        return 0;
1064
                }
1065
        case VC_SETMODE:
1066
        case VC_INQMODE:
1067
                {
1068
                        struct vc_mode mode;
1069
 
1070
                        if (!perm)
1071
                                return -EPERM;
1072
                        if (copy_from_user(&mode, (void *) arg, sizeof(mode)))
1073
                                return -EFAULT;
1074
                        return console_setmode(&mode, cmd == VC_SETMODE);
1075
                }
1076
        case VC_SETCMAP:
1077
                {
1078
                        unsigned char cmap[3][256], *p;
1079
                        int n_entries, cmap_size, i, j;
1080
 
1081
                        if (!perm)
1082
                                return -EPERM;
1083
                        if (arg == (unsigned long) VC_POWERMODE_INQUIRY
1084
                            || arg <= VESA_POWERDOWN) {
1085
                                /* compatibility hack: VC_POWERMODE
1086
                                   was changed from 0x766a to 0x766c */
1087
                                return console_powermode((int) arg);
1088
                        }
1089
                        if (get_user(cmap_size, (int *) arg))
1090
                                return -EFAULT;
1091
                        if (cmap_size % 3)
1092
                                return -EINVAL;
1093
                        n_entries = cmap_size / 3;
1094
                        if ((unsigned) n_entries > 256)
1095
                                return -EINVAL;
1096
                        p = (unsigned char *) (arg + sizeof(int));
1097
                        for (j = 0; j < n_entries; ++j)
1098
                                for (i = 0; i < 3; ++i)
1099
                                        if (get_user(cmap[i][j], p++))
1100
                                                return -EFAULT;
1101
                        return console_setcmap(n_entries, cmap[0],
1102
                                               cmap[1], cmap[2]);
1103
                }
1104
        case VC_GETCMAP:
1105
                /* not implemented yet */
1106
                return -ENOIOCTLCMD;
1107
        case VC_POWERMODE:
1108
                if (!perm)
1109
                        return -EPERM;
1110
                return console_powermode((int) arg);
1111
#endif /* CONFIG_FB_COMPAT_XPMAC */
1112
        default:
1113
                return -ENOIOCTLCMD;
1114
        }
1115
}
1116
 
1117
/*
1118
 * Sometimes we want to wait until a particular VT has been activated. We
1119
 * do it in a very simple manner. Everybody waits on a single queue and
1120
 * get woken up at once. Those that are satisfied go on with their business,
1121
 * while those not ready go back to sleep. Seems overkill to add a wait
1122
 * to each vt just for this - usually this does nothing!
1123
 */
1124
static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
1125
 
1126
/*
1127
 * Sleeps until a vt is activated, or the task is interrupted. Returns
1128
 * 0 if activation, -EINTR if interrupted.
1129
 */
1130
int vt_waitactive(int vt)
1131
{
1132
        int retval;
1133
        DECLARE_WAITQUEUE(wait, current);
1134
 
1135
        add_wait_queue(&vt_activate_queue, &wait);
1136
        for (;;) {
1137
                set_current_state(TASK_INTERRUPTIBLE);
1138
                retval = 0;
1139
                if (vt == fg_console)
1140
                        break;
1141
                retval = -EINTR;
1142
                if (signal_pending(current))
1143
                        break;
1144
                schedule();
1145
        }
1146
        remove_wait_queue(&vt_activate_queue, &wait);
1147
        current->state = TASK_RUNNING;
1148
        return retval;
1149
}
1150
 
1151
#define vt_wake_waitactive() wake_up(&vt_activate_queue)
1152
 
1153
void reset_vc(unsigned int new_console)
1154
{
1155
        vt_cons[new_console]->vc_mode = KD_TEXT;
1156
        kbd_table[new_console].kbdmode = VC_XLATE;
1157
        vt_cons[new_console]->vt_mode.mode = VT_AUTO;
1158
        vt_cons[new_console]->vt_mode.waitv = 0;
1159
        vt_cons[new_console]->vt_mode.relsig = 0;
1160
        vt_cons[new_console]->vt_mode.acqsig = 0;
1161
        vt_cons[new_console]->vt_mode.frsig = 0;
1162
        vt_cons[new_console]->vt_pid = -1;
1163
        vt_cons[new_console]->vt_newvt = -1;
1164
        if (!in_interrupt())    /* Via keyboard.c:SAK() - akpm */
1165
                reset_palette(new_console) ;
1166
}
1167
 
1168
/*
1169
 * Performs the back end of a vt switch
1170
 */
1171
void complete_change_console(unsigned int new_console)
1172
{
1173
        unsigned char old_vc_mode;
1174
 
1175
        last_console = fg_console;
1176
 
1177
        /*
1178
         * If we're switching, we could be going from KD_GRAPHICS to
1179
         * KD_TEXT mode or vice versa, which means we need to blank or
1180
         * unblank the screen later.
1181
         */
1182
        old_vc_mode = vt_cons[fg_console]->vc_mode;
1183
        switch_screen(new_console);
1184
 
1185
        /*
1186
         * This can't appear below a successful kill_proc().  If it did,
1187
         * then the *blank_screen operation could occur while X, having
1188
         * received acqsig, is waking up on another processor.  This
1189
         * condition can lead to overlapping accesses to the VGA range
1190
         * and the framebuffer (causing system lockups).
1191
         *
1192
         * To account for this we duplicate this code below only if the
1193
         * controlling process is gone and we've called reset_vc.
1194
         */
1195
        if (old_vc_mode != vt_cons[new_console]->vc_mode)
1196
        {
1197
                if (vt_cons[new_console]->vc_mode == KD_TEXT)
1198
                        unblank_screen();
1199
                else
1200
                        do_blank_screen(1);
1201
        }
1202
 
1203
        /*
1204
         * If this new console is under process control, send it a signal
1205
         * telling it that it has acquired. Also check if it has died and
1206
         * clean up (similar to logic employed in change_console())
1207
         */
1208
        if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
1209
        {
1210
                /*
1211
                 * Send the signal as privileged - kill_proc() will
1212
                 * tell us if the process has gone or something else
1213
                 * is awry
1214
                 */
1215
                if (kill_proc(vt_cons[new_console]->vt_pid,
1216
                              vt_cons[new_console]->vt_mode.acqsig,
1217
                              1) != 0)
1218
                {
1219
                /*
1220
                 * The controlling process has died, so we revert back to
1221
                 * normal operation. In this case, we'll also change back
1222
                 * to KD_TEXT mode. I'm not sure if this is strictly correct
1223
                 * but it saves the agony when the X server dies and the screen
1224
                 * remains blanked due to KD_GRAPHICS! It would be nice to do
1225
                 * this outside of VT_PROCESS but there is no single process
1226
                 * to account for and tracking tty count may be undesirable.
1227
                 */
1228
                        reset_vc(new_console);
1229
 
1230
                        if (old_vc_mode != vt_cons[new_console]->vc_mode)
1231
                        {
1232
                                if (vt_cons[new_console]->vc_mode == KD_TEXT)
1233
                                        unblank_screen();
1234
                                else
1235
                                        do_blank_screen(1);
1236
                        }
1237
                }
1238
        }
1239
 
1240
        /*
1241
         * Wake anyone waiting for their VT to activate
1242
         */
1243
        vt_wake_waitactive();
1244
        return;
1245
}
1246
 
1247
/*
1248
 * Performs the front-end of a vt switch
1249
 */
1250
void change_console(unsigned int new_console)
1251
{
1252
        if ((new_console == fg_console) || (vt_dont_switch))
1253
                return;
1254
        if (!vc_cons_allocated(new_console))
1255
                return;
1256
 
1257
        /*
1258
         * If this vt is in process mode, then we need to handshake with
1259
         * that process before switching. Essentially, we store where that
1260
         * vt wants to switch to and wait for it to tell us when it's done
1261
         * (via VT_RELDISP ioctl).
1262
         *
1263
         * We also check to see if the controlling process still exists.
1264
         * If it doesn't, we reset this vt to auto mode and continue.
1265
         * This is a cheap way to track process control. The worst thing
1266
         * that can happen is: we send a signal to a process, it dies, and
1267
         * the switch gets "lost" waiting for a response; hopefully, the
1268
         * user will try again, we'll detect the process is gone (unless
1269
         * the user waits just the right amount of time :-) and revert the
1270
         * vt to auto control.
1271
         */
1272
        if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
1273
        {
1274
                /*
1275
                 * Send the signal as privileged - kill_proc() will
1276
                 * tell us if the process has gone or something else
1277
                 * is awry
1278
                 */
1279
                if (kill_proc(vt_cons[fg_console]->vt_pid,
1280
                              vt_cons[fg_console]->vt_mode.relsig,
1281
                              1) == 0)
1282
                {
1283
                        /*
1284
                         * It worked. Mark the vt to switch to and
1285
                         * return. The process needs to send us a
1286
                         * VT_RELDISP ioctl to complete the switch.
1287
                         */
1288
                        vt_cons[fg_console]->vt_newvt = new_console;
1289
                        return;
1290
                }
1291
 
1292
                /*
1293
                 * The controlling process has died, so we revert back to
1294
                 * normal operation. In this case, we'll also change back
1295
                 * to KD_TEXT mode. I'm not sure if this is strictly correct
1296
                 * but it saves the agony when the X server dies and the screen
1297
                 * remains blanked due to KD_GRAPHICS! It would be nice to do
1298
                 * this outside of VT_PROCESS but there is no single process
1299
                 * to account for and tracking tty count may be undesirable.
1300
                 */
1301
                reset_vc(fg_console);
1302
 
1303
                /*
1304
                 * Fall through to normal (VT_AUTO) handling of the switch...
1305
                 */
1306
        }
1307
 
1308
        /*
1309
         * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
1310
         */
1311
        if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
1312
                return;
1313
 
1314
        complete_change_console(new_console);
1315
}
1316
 

powered by: WebSVN 2.1.0

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