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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 *  linux/drivers/char/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
 */
10
 
11
#include <linux/types.h>
12
#include <linux/errno.h>
13
#include <linux/sched.h>
14
#include <linux/tty.h>
15
#include <linux/timer.h>
16
#include <linux/kernel.h>
17
#include <linux/kd.h>
18
#include <linux/vt.h>
19
#include <linux/string.h>
20
#include <linux/malloc.h>
21
#include <linux/major.h>
22
#include <linux/fs.h>
23
 
24
#include <asm/io.h>
25
#include <asm/segment.h>
26
#include <asm/bitops.h>
27
 
28
#include "kbd_kern.h"
29
#include "vt_kern.h"
30
#include "diacr.h"
31
#include "selection.h"
32
 
33
extern char vt_dont_switch;
34
extern struct tty_driver console_driver;
35
 
36
#define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
37
#define VT_BUSY(i)      (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
38
 
39
/*
40
 * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
41
 * experimentation and study of X386 SYSV handling.
42
 *
43
 * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
44
 * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
45
 * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
46
 * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
47
 * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
48
 * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
49
 * to the current console is done by the main ioctl code.
50
 */
51
 
52
struct vt_struct *vt_cons[MAX_NR_CONSOLES];
53
 
54
#ifndef __alpha__
55
asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
56
#endif
57
 
58
extern int getkeycode(unsigned int scancode);
59
extern int setkeycode(unsigned int scancode, unsigned int keycode);
60
extern void compute_shiftstate(void);
61
extern void complete_change_console(unsigned int new_console);
62
extern int vt_waitactive(void);
63
extern void do_blank_screen(int nopowersave);
64
 
65
extern unsigned int keymap_count;
66
 
67
/*
68
 * routines to load custom translation table, EGA/VGA font and
69
 * VGA colour palette from console.c
70
 */
71
extern int con_set_trans_old(unsigned char * table);
72
extern int con_get_trans_old(unsigned char * table);
73
extern int con_set_trans_new(unsigned short * table);
74
extern int con_get_trans_new(unsigned short * table);
75
extern void con_clear_unimap(struct unimapinit *ui);
76
extern int con_set_unimap(ushort ct, struct unipair *list);
77
extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
78
extern void con_set_default_unimap(void);
79
extern int con_set_font(char * fontmap, int ch512);
80
extern int con_get_font(char * fontmap);
81
extern int con_set_cmap(unsigned char *cmap);
82
extern int con_get_cmap(unsigned char *cmap);
83
extern void reset_palette(int currcons);
84
extern int con_adjust_height(unsigned long fontheight);
85
 
86
extern int video_mode_512ch;
87
extern unsigned long video_font_height;
88
extern unsigned long default_font_height;
89
extern unsigned long video_scan_lines;
90
 
91
/*
92
 * these are the valid i/o ports we're allowed to change. they map all the
93
 * video ports
94
 */
95
#define GPFIRST 0x3b4
96
#define GPLAST 0x3df
97
#define GPNUM (GPLAST - GPFIRST + 1)
98
 
99
/*
100
 * This function is called when the size of the physical screen has been
101
 * changed.  If either the row or col argument is nonzero, set the appropriate
102
 * entry in each winsize structure for all the virtual consoles, then
103
 * send SIGWINCH to all processes with a virtual console as controlling
104
 * tty.
105
 */
106
 
107
static int
108
kd_size_changed(int row, int col)
109
{
110
  struct task_struct *p;
111
  int i;
112
 
113
  if ( !row && !col ) return 0;
114
 
115
  for ( i = 0 ; i < MAX_NR_CONSOLES ; i++ )
116
    {
117
      if ( console_driver.table[i] )
118
        {
119
          if ( row ) console_driver.table[i]->winsize.ws_row = row;
120
          if ( col ) console_driver.table[i]->winsize.ws_col = col;
121
        }
122
    }
123
 
124
  for_each_task(p)
125
    {
126
      if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR &&
127
           MINOR(p->tty->device) <= MAX_NR_CONSOLES && MINOR(p->tty->device) )
128
        {
129
          send_sig(SIGWINCH, p, 1);
130
        }
131
    }
132
 
133
  return 0;
134
}
135
 
136
/*
137
 * Generates sound of some count for some number of clock ticks
138
 * [count = 1193180 / frequency]
139
 *
140
 * If freq is 0, will turn off sound, else will turn it on for that time.
141
 * If msec is 0, will return immediately, else will sleep for msec time, then
142
 * turn sound off.
143
 *
144
 * We use the BEEP_TIMER vector since we're using the same method to
145
 * generate sound, and we'll overwrite any beep in progress. That may
146
 * be something to fix later, if we like.
147
 *
148
 * We also return immediately, which is what was implied within the X
149
 * comments - KDMKTONE doesn't put the process to sleep.
150
 */
151
 
152
static unsigned int mksound_lock = 0;
153
 
154
static void
155
kd_nosound(unsigned long ignored)
156
{
157
        /* if sound is being set up, don't turn it off */
158
        if (!mksound_lock)
159
               /* disable counter 2 */
160
               outb(inb_p(0x61)&0xFC, 0x61);
161
        return;
162
}
163
 
164
void
165
_kd_mksound(unsigned int hz, unsigned int ticks)
166
{
167
        static struct timer_list sound_timer = { NULL, NULL, 0, 0,
168
                                                 kd_nosound };
169
 
170
        unsigned int count = 0;
171
 
172
        if (hz > 20 && hz < 32767)
173
                count = 1193180 / hz;
174
 
175
        if (!count)
176
                kd_nosound(0);
177
        /* ignore multiple simultaneous requests for sound */
178
        else if (!set_bit(0, &mksound_lock)) {
179
        /* set_bit in 2.0.x is same as test-and-set in 2.1.x */
180
                del_timer(&sound_timer);
181
                if (count) {
182
                        /* enable counter 2 */
183
                        outb_p(inb_p(0x61)|3, 0x61);
184
                        /* set command for counter 2, 2 byte write */
185
                        outb_p(0xB6, 0x43);
186
                        /* select desired HZ */
187
                        outb_p(count & 0xff, 0x42);
188
                        outb((count >> 8) & 0xff, 0x42);
189
 
190
                        if (ticks) {
191
                                sound_timer.expires = jiffies+ticks;
192
                                add_timer(&sound_timer);
193
                        }
194
                }
195
                mksound_lock = 0;
196
        }
197
        return;
198
}
199
 
200
void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
201
 
202
/*
203
 * We handle the console-specific ioctl's here.  We allow the
204
 * capability to modify any console, not just the fg_console.
205
 */
206
int vt_ioctl(struct tty_struct *tty, struct file * file,
207
             unsigned int cmd, unsigned long arg)
208
{
209
        int i, perm;
210
        unsigned int console;
211
        unsigned char ucval;
212
        struct kbd_struct * kbd;
213
        struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
214
 
215
        console = vt->vc_num;
216
 
217
        if (!vc_cons_allocated(console))        /* impossible? */
218
                return -ENOIOCTLCMD;
219
 
220
        /*
221
         * To have permissions to do most of the vt ioctls, we either have
222
         * to be the owner of the tty, or super-user.
223
         */
224
        perm = 0;
225
        if (current->tty == tty || suser())
226
                perm = 1;
227
 
228
        kbd = kbd_table + console;
229
        switch (cmd) {
230
        case KIOCSOUND:
231
                if (!perm)
232
                        return -EPERM;
233
                if (arg)
234
                        arg = 1193180 / arg;
235
                kd_mksound(arg, 0);
236
                return 0;
237
 
238
        case KDMKTONE:
239
                if (!perm)
240
                        return -EPERM;
241
        {
242
                unsigned int ticks, count;
243
 
244
                /*
245
                 * Generate the tone for the appropriate number of ticks.
246
                 * If the time is zero, turn off sound ourselves.
247
                 */
248
                ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
249
                if ((arg & 0xffff) == 0 ) arg |= 1; /* jp: huh? */
250
                count = ticks ? (1193180 / (arg & 0xffff)) : 0;
251
                kd_mksound(count, ticks);
252
                return 0;
253
        }
254
 
255
        case KDGKBTYPE:
256
                /*
257
                 * this is naive.
258
                 */
259
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
260
                if (!i)
261
                        put_user(KB_101, (char *) arg);
262
                return i;
263
 
264
#ifndef __alpha__
265
                /*
266
                 * These cannot be implemented on any machine that implements
267
                 * ioperm() in user level (such as Alpha PCs).
268
                 */
269
        case KDADDIO:
270
        case KDDELIO:
271
                /*
272
                 * KDADDIO and KDDELIO may be able to add ports beyond what
273
                 * we reject here, but to be safe...
274
                 */
275
                if (arg < GPFIRST || arg > GPLAST)
276
                        return -EINVAL;
277
                return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
278
 
279
        case KDENABIO:
280
        case KDDISABIO:
281
                return sys_ioperm(GPFIRST, GPNUM,
282
                                  (cmd == KDENABIO)) ? -ENXIO : 0;
283
#endif
284
 
285
        case KDSETMODE:
286
                /*
287
                 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
288
                 * doesn't do a whole lot. i'm not sure if it should do any
289
                 * restoration of modes or what...
290
                 */
291
                if (!perm)
292
                        return -EPERM;
293
                switch (arg) {
294
                case KD_GRAPHICS:
295
                        break;
296
                case KD_TEXT0:
297
                case KD_TEXT1:
298
                        arg = KD_TEXT;
299
                case KD_TEXT:
300
                        break;
301
                default:
302
                        return -EINVAL;
303
                }
304
                if (vt_cons[console]->vc_mode == (unsigned char) arg)
305
                        return 0;
306
                vt_cons[console]->vc_mode = (unsigned char) arg;
307
                if (console != fg_console)
308
                        return 0;
309
                /*
310
                 * explicitly blank/unblank the screen if switching modes
311
                 */
312
                if (arg == KD_TEXT)
313
                        do_unblank_screen();
314
                else
315
                        do_blank_screen(1);
316
                return 0;
317
 
318
        case KDGETMODE:
319
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
320
                if (!i)
321
                        put_user(vt_cons[console]->vc_mode, (int *) arg);
322
                return i;
323
 
324
        case KDMAPDISP:
325
        case KDUNMAPDISP:
326
                /*
327
                 * these work like a combination of mmap and KDENABIO.
328
                 * this could be easily finished.
329
                 */
330
                return -EINVAL;
331
 
332
        case KDSKBMODE:
333
                if (!perm)
334
                        return -EPERM;
335
                switch(arg) {
336
                  case K_RAW:
337
                        kbd->kbdmode = VC_RAW;
338
                        break;
339
                  case K_MEDIUMRAW:
340
                        kbd->kbdmode = VC_MEDIUMRAW;
341
                        break;
342
                  case K_XLATE:
343
                        kbd->kbdmode = VC_XLATE;
344
                        compute_shiftstate();
345
                        break;
346
                  case K_UNICODE:
347
                        kbd->kbdmode = VC_UNICODE;
348
                        compute_shiftstate();
349
                        break;
350
                  default:
351
                        return -EINVAL;
352
                }
353
                if (tty->ldisc.flush_buffer)
354
                        tty->ldisc.flush_buffer(tty);
355
                return 0;
356
 
357
        case KDGKBMODE:
358
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
359
                if (!i) {
360
                        ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
361
                                 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
362
                                 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
363
                                 K_XLATE);
364
                        put_user(ucval, (int *) arg);
365
                }
366
                return i;
367
 
368
        /* this could be folded into KDSKBMODE, but for compatibility
369
           reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
370
        case KDSKBMETA:
371
                switch(arg) {
372
                  case K_METABIT:
373
                        clr_vc_kbd_mode(kbd, VC_META);
374
                        break;
375
                  case K_ESCPREFIX:
376
                        set_vc_kbd_mode(kbd, VC_META);
377
                        break;
378
                  default:
379
                        return -EINVAL;
380
                }
381
                return 0;
382
 
383
        case KDGKBMETA:
384
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
385
                if (!i) {
386
                        ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
387
                                 K_METABIT);
388
                        put_user(ucval, (int *) arg);
389
                }
390
                return i;
391
 
392
        case KDGETKEYCODE:
393
        {
394
                struct kbkeycode * const a = (struct kbkeycode *)arg;
395
                unsigned int sc;
396
                int kc;
397
 
398
                i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
399
                if (i)
400
                        return i;
401
                sc = get_user(&a->scancode);
402
                kc = getkeycode(sc);
403
                if (kc < 0)
404
                        return kc;
405
                put_user(kc, &a->keycode);
406
                return 0;
407
        }
408
 
409
        case KDSETKEYCODE:
410
        {
411
                struct kbkeycode * const a = (struct kbkeycode *)arg;
412
                unsigned int sc, kc;
413
 
414
                if (!perm)
415
                        return -EPERM;
416
                i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
417
                if (i)
418
                        return i;
419
                sc = get_user(&a->scancode);
420
                kc = get_user(&a->keycode);
421
                return setkeycode(sc, kc);
422
        }
423
 
424
        case KDGKBENT:
425
        {
426
                struct kbentry * const a = (struct kbentry *)arg;
427
                ushort *key_map, val;
428
                u_char s;
429
 
430
                i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
431
                if (i)
432
                        return i;
433
                if ((i = get_user(&a->kb_index)) >= NR_KEYS)
434
                        return -EINVAL;
435
                if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
436
                        return -EINVAL;
437
                key_map = key_maps[s];
438
                if (key_map) {
439
                    val = U(key_map[i]);
440
                    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
441
                        val = K_HOLE;
442
                } else
443
                    val = (i ? K_HOLE : K_NOSUCHMAP);
444
                put_user(val, &a->kb_value);
445
                return 0;
446
        }
447
 
448
        case KDSKBENT:
449
        {
450
                const struct kbentry * a = (struct kbentry *)arg;
451
                ushort *key_map;
452
                u_char s;
453
                u_short v, ov;
454
 
455
                if (!perm)
456
                        return -EPERM;
457
                i = verify_area(VERIFY_READ, (const void *)a, sizeof(struct kbentry));
458
                if (i)
459
                        return i;
460
                if ((i = get_user(&a->kb_index)) >= NR_KEYS)
461
                        return -EINVAL;
462
                if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
463
                        return -EINVAL;
464
                v = get_user(&a->kb_value);
465
                if (!i && v == K_NOSUCHMAP) {
466
                        /* disallocate map */
467
                        key_map = key_maps[s];
468
                        if (s && key_map) {
469
                            key_maps[s] = 0;
470
                            if (key_map[0] == U(K_ALLOCATED)) {
471
                                kfree_s(key_map, sizeof(plain_map));
472
                                keymap_count--;
473
                            }
474
                        }
475
                        return 0;
476
                }
477
 
478
                if (KTYP(v) < NR_TYPES) {
479
                    if (KVAL(v) > max_vals[KTYP(v)])
480
                        return -EINVAL;
481
                } else
482
                    if (kbd->kbdmode != VC_UNICODE)
483
                        return -EINVAL;
484
 
485
                /* assignment to entry 0 only tests validity of args */
486
                if (!i)
487
                        return 0;
488
 
489
                if (!(key_map = key_maps[s])) {
490
                        int j;
491
 
492
                        if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
493
                                return -EPERM;
494
 
495
                        key_map = (ushort *) kmalloc(sizeof(plain_map),
496
                                                     GFP_KERNEL);
497
                        if (!key_map)
498
                                return -ENOMEM;
499
                        key_maps[s] = key_map;
500
                        key_map[0] = U(K_ALLOCATED);
501
                        for (j = 1; j < NR_KEYS; j++)
502
                                key_map[j] = U(K_HOLE);
503
                        keymap_count++;
504
                }
505
                ov = U(key_map[i]);
506
                if (v == ov)
507
                        return 0;        /* nothing to do */
508
                /*
509
                 * Only the Superuser can set or unset the Secure
510
                 * Attention Key.
511
                 */
512
                if (((ov == K_SAK) || (v == K_SAK)) && !suser())
513
                        return -EPERM;
514
                key_map[i] = U(v);
515
                if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
516
                        compute_shiftstate();
517
                return 0;
518
        }
519
 
520
        case KDGKBSENT:
521
        {
522
                struct kbsentry *a = (struct kbsentry *)arg;
523
                char *p;
524
                u_char *q;
525
                int sz;
526
 
527
                i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
528
                if (i)
529
                        return i;
530
                if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
531
                        return -EINVAL;
532
                sz = sizeof(a->kb_string) - 1; /* sz should have been
533
                                                  a struct member */
534
                q = a->kb_string;
535
                p = func_table[i];
536
                if(p)
537
                        for ( ; *p && sz; p++, sz--)
538
                                put_user(*p, q++);
539
                put_user('\0', q);
540
                return ((p && *p) ? -EOVERFLOW : 0);
541
        }
542
 
543
        case KDSKBSENT:
544
        {
545
                struct kbsentry * const a = (struct kbsentry *)arg;
546
                int delta;
547
                char *first_free, *fj, *fnw;
548
                int j, k, sz;
549
                u_char *p;
550
                char *q;
551
 
552
                if (!perm)
553
                        return -EPERM;
554
                i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
555
                if (i)
556
                        return i;
557
                if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
558
                        return -EINVAL;
559
                q = func_table[i];
560
 
561
                first_free = funcbufptr + (funcbufsize - funcbufleft);
562
                for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
563
                if (j < MAX_NR_FUNC)
564
                        fj = func_table[j];
565
                else
566
                        fj = first_free;
567
 
568
                delta = (q ? -strlen(q) : 1);
569
                sz = sizeof(a->kb_string);      /* sz should have been
570
                                                   a struct member */
571
                for (p = a->kb_string; get_user(p) && sz; p++,sz--)
572
                        delta++;
573
                if (!sz)
574
                        return -EOVERFLOW;
575
                if (delta <= funcbufleft) {     /* it fits in current buf */
576
                    if (j < MAX_NR_FUNC) {
577
                        memmove(fj + delta, fj, first_free - fj);
578
                        for (k = j; k < MAX_NR_FUNC; k++)
579
                            if (func_table[k])
580
                                func_table[k] += delta;
581
                    }
582
                    if (!q)
583
                      func_table[i] = fj;
584
                    funcbufleft -= delta;
585
                } else {                        /* allocate a larger buffer */
586
                    sz = 256;
587
                    while (sz < funcbufsize - funcbufleft + delta)
588
                      sz <<= 1;
589
                    fnw = (char *) kmalloc(sz, GFP_KERNEL);
590
                    if(!fnw)
591
                      return -ENOMEM;
592
 
593
                    if (!q)
594
                      func_table[i] = fj;
595
                    if (fj > funcbufptr)
596
                        memmove(fnw, funcbufptr, fj - funcbufptr);
597
                    for (k = 0; k < j; k++)
598
                      if (func_table[k])
599
                        func_table[k] = fnw + (func_table[k] - funcbufptr);
600
 
601
                    if (first_free > fj) {
602
                        memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
603
                        for (k = j; k < MAX_NR_FUNC; k++)
604
                          if (func_table[k])
605
                            func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
606
                    }
607
                    if (funcbufptr != func_buf)
608
                      kfree_s(funcbufptr, funcbufsize);
609
                    funcbufptr = fnw;
610
                    funcbufleft = funcbufleft - delta + sz - funcbufsize;
611
                    funcbufsize = sz;
612
                }
613
                for (p = a->kb_string, q = func_table[i]; ; p++, q++)
614
                        if (!(*q = get_user(p)))
615
                                break;
616
                return 0;
617
        }
618
 
619
        case KDGKBDIACR:
620
        {
621
                struct kbdiacrs *a = (struct kbdiacrs *)arg;
622
 
623
                i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
624
                if (i)
625
                        return i;
626
                put_user(accent_table_size, &a->kb_cnt);
627
                memcpy_tofs(a->kbdiacr, accent_table,
628
                            accent_table_size*sizeof(struct kbdiacr));
629
                return 0;
630
        }
631
 
632
        case KDSKBDIACR:
633
        {
634
                struct kbdiacrs *a = (struct kbdiacrs *)arg;
635
                unsigned int ct;
636
 
637
                if (!perm)
638
                        return -EPERM;
639
                i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
640
                if (i)
641
                        return i;
642
                ct = get_user(&a->kb_cnt);
643
                if (ct >= MAX_DIACR)
644
                        return -EINVAL;
645
                accent_table_size = ct;
646
                memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
647
                return 0;
648
        }
649
 
650
        /* the ioctls below read/set the flags usually shown in the leds */
651
        /* don't use them - they will go away without warning */
652
        case KDGKBLED:
653
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
654
                if (i)
655
                        return i;
656
                put_user(kbd->ledflagstate |
657
                         (kbd->default_ledflagstate << 4), (char *) arg);
658
                return 0;
659
 
660
        case KDSKBLED:
661
                if (!perm)
662
                        return -EPERM;
663
                if (arg & ~0x77)
664
                        return -EINVAL;
665
                kbd->ledflagstate = (arg & 7);
666
                kbd->default_ledflagstate = ((arg >> 4) & 7);
667
                set_leds();
668
                return 0;
669
 
670
        /* the ioctls below only set the lights, not the functions */
671
        /* for those, see KDGKBLED and KDSKBLED above */
672
        case KDGETLED:
673
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
674
                if (i)
675
                        return i;
676
                put_user(getledstate(), (char *) arg);
677
                return 0;
678
 
679
        case KDSETLED:
680
                if (!perm)
681
                  return -EPERM;
682
                setledstate(kbd, arg);
683
                return 0;
684
 
685
        /*
686
         * A process can indicate its willingness to accept signals
687
         * generated by pressing an appropriate key combination.
688
         * Thus, one can have a daemon that e.g. spawns a new console
689
         * upon a keypress and then changes to it.
690
         * Probably init should be changed to do this (and have a
691
         * field ks (`keyboard signal') in inittab describing the
692
         * desired action), so that the number of background daemons
693
         * does not increase.
694
         */
695
        case KDSIGACCEPT:
696
        {
697
                extern int spawnpid, spawnsig;
698
                if (!perm)
699
                  return -EPERM;
700
                if (arg < 1 || arg > NSIG || arg == SIGKILL)
701
                  return -EINVAL;
702
                spawnpid = current->pid;
703
                spawnsig = arg;
704
                return 0;
705
        }
706
 
707
        case VT_SETMODE:
708
        {
709
                struct vt_mode *vtmode = (struct vt_mode *)arg;
710
                char mode;
711
 
712
                if (!perm)
713
                        return -EPERM;
714
                i = verify_area(VERIFY_READ, (void *)vtmode, sizeof(struct vt_mode));
715
                if (i)
716
                        return i;
717
                mode = get_user(&vtmode->mode);
718
                if (mode != VT_AUTO && mode != VT_PROCESS)
719
                        return -EINVAL;
720
                vt_cons[console]->vt_mode.mode = mode;
721
                vt_cons[console]->vt_mode.waitv = get_user(&vtmode->waitv);
722
                vt_cons[console]->vt_mode.relsig = get_user(&vtmode->relsig);
723
                vt_cons[console]->vt_mode.acqsig = get_user(&vtmode->acqsig);
724
                /* the frsig is ignored, so we set it to 0 */
725
                vt_cons[console]->vt_mode.frsig = 0;
726
                vt_cons[console]->vt_pid = current->pid;
727
                /* no switch is required -- saw@shade.msu.ru */
728
                vt_cons[console]->vt_newvt = -1;
729
                return 0;
730
        }
731
 
732
        case VT_GETMODE:
733
        {
734
                struct vt_mode *vtmode = (struct vt_mode *)arg;
735
 
736
                i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
737
                if (i)
738
                        return i;
739
                put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
740
                put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
741
                put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
742
                put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
743
                put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
744
                return 0;
745
        }
746
 
747
        /*
748
         * Returns global vt state. Note that VT 0 is always open, since
749
         * it's an alias for the current VT, and people can't use it here.
750
         * We cannot return state for more than 16 VTs, since v_state is short.
751
         */
752
        case VT_GETSTATE:
753
        {
754
                struct vt_stat *vtstat = (struct vt_stat *)arg;
755
                unsigned short state, mask;
756
 
757
                i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
758
                if (i)
759
                        return i;
760
                put_user(fg_console + 1, &vtstat->v_active);
761
                state = 1;      /* /dev/tty0 is always open */
762
                for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
763
                        if (VT_IS_IN_USE(i))
764
                                state |= mask;
765
                put_user(state, &vtstat->v_state);
766
                return 0;
767
        }
768
 
769
        /*
770
         * Returns the first available (non-opened) console.
771
         */
772
        case VT_OPENQRY:
773
                i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
774
                if (i)
775
                        return i;
776
                for (i = 0; i < MAX_NR_CONSOLES; ++i)
777
                        if (! VT_IS_IN_USE(i))
778
                                break;
779
                put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int *) arg);
780
                return 0;
781
 
782
        /*
783
         * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
784
         * with num >= 1 (switches to vt 0, our console, are not allowed, just
785
         * to preserve sanity).
786
         */
787
        case VT_ACTIVATE:
788
                if (!perm)
789
                        return -EPERM;
790
                if (arg == 0 || arg > MAX_NR_CONSOLES)
791
                        return -ENXIO;
792
                arg--;
793
                i = vc_allocate(arg);
794
                if (i)
795
                        return i;
796
                set_console(arg);
797
                return 0;
798
 
799
        /*
800
         * wait until the specified VT has been activated
801
         */
802
        case VT_WAITACTIVE:
803
                if (!perm)
804
                        return -EPERM;
805
                if (arg == 0 || arg > MAX_NR_CONSOLES)
806
                        return -ENXIO;
807
                arg--;
808
                while (fg_console != arg)
809
                {
810
                        if (vt_waitactive() < 0)
811
                                return -EINTR;
812
                }
813
                return 0;
814
 
815
        /*
816
         * If a vt is under process control, the kernel will not switch to it
817
         * immediately, but postpone the operation until the process calls this
818
         * ioctl, allowing the switch to complete.
819
         *
820
         * According to the X sources this is the behavior:
821
         *      0:      pending switch-from not OK
822
         *      1:      pending switch-from OK
823
         *      2:      completed switch-to OK
824
         */
825
        case VT_RELDISP:
826
                if (!perm)
827
                        return -EPERM;
828
                if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
829
                        return -EINVAL;
830
 
831
                /*
832
                 * Switching-from response
833
                 */
834
                if (vt_cons[console]->vt_newvt >= 0)
835
                {
836
                        if (arg == 0)
837
                                /*
838
                                 * Switch disallowed, so forget we were trying
839
                                 * to do it.
840
                                 */
841
                                vt_cons[console]->vt_newvt = -1;
842
 
843
                        else
844
                        {
845
                                /*
846
                                 * The current vt has been released, so
847
                                 * complete the switch.
848
                                 */
849
                                int newvt = vt_cons[console]->vt_newvt;
850
                                vt_cons[console]->vt_newvt = -1;
851
                                i = vc_allocate(newvt);
852
                                if (i)
853
                                        return i;
854
                                /*
855
                                 * When we actually do the console switch,
856
                                 * make sure we are atomic with respect to
857
                                 * other console switches..
858
                                 */
859
                                start_bh_atomic();
860
                                complete_change_console(newvt);
861
                                end_bh_atomic();
862
                        }
863
                }
864
 
865
                /*
866
                 * Switched-to response
867
                 */
868
                else
869
                {
870
                        /*
871
                         * If it's just an ACK, ignore it
872
                         */
873
                        if (arg != VT_ACKACQ)
874
                                return -EINVAL;
875
                }
876
 
877
                return 0;
878
 
879
         /*
880
          * Disallocate memory associated to VT (but leave VT1)
881
          */
882
         case VT_DISALLOCATE:
883
                if (arg > MAX_NR_CONSOLES)
884
                        return -ENXIO;
885
                if (arg == 0) {
886
                    /* disallocate all unused consoles, but leave 0 */
887
                    for (i=1; i<MAX_NR_CONSOLES; i++)
888
                      if (! VT_BUSY(i))
889
                        vc_disallocate(i);
890
                } else {
891
                    /* disallocate a single console, if possible */
892
                    arg--;
893
                    if (VT_BUSY(arg))
894
                      return -EBUSY;
895
                    if (arg)                          /* leave 0 */
896
                      vc_disallocate(arg);
897
                }
898
                return 0;
899
 
900
        case VT_RESIZE:
901
        {
902
                struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
903
                ushort ll,cc;
904
                if (!perm)
905
                        return -EPERM;
906
                i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
907
                if (i)
908
                        return i;
909
                ll = get_user(&vtsizes->v_rows);
910
                cc = get_user(&vtsizes->v_cols);
911
                i = vc_resize(ll, cc);
912
                return i ? i :  kd_size_changed(ll, cc);
913
        }
914
 
915
        case VT_RESIZEX:
916
        {
917
                struct vt_consize *vtconsize = (struct vt_consize *) arg;
918
                ushort ll,cc,vlin,clin,vcol,ccol;
919
                if (!perm)
920
                        return -EPERM;
921
                i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
922
                if (i)
923
                        return i;
924
                ll = get_user(&vtconsize->v_rows);
925
                cc = get_user(&vtconsize->v_cols);
926
                vlin = get_user(&vtconsize->v_vlin);
927
                clin = get_user(&vtconsize->v_clin);
928
                vcol = get_user(&vtconsize->v_vcol);
929
                ccol = get_user(&vtconsize->v_ccol);
930
                vlin = vlin ? vlin : video_scan_lines;
931
                if ( clin )
932
                  {
933
                    if ( ll )
934
                      {
935
                        if ( ll != vlin/clin )
936
                          return EINVAL; /* Parameters don't add up */
937
                      }
938
                    else
939
                      ll = vlin/clin;
940
                  }
941
                if ( vcol && ccol )
942
                  {
943
                    if ( cc )
944
                      {
945
                        if ( cc != vcol/ccol )
946
                          return EINVAL;
947
                      }
948
                    else
949
                      cc = vcol/ccol;
950
                  }
951
 
952
                if ( clin > 32 )
953
                  return EINVAL;
954
 
955
                if ( vlin )
956
                  video_scan_lines = vlin;
957
                if ( clin )
958
                  video_font_height = clin;
959
 
960
                i = vc_resize(ll, cc);
961
                if (i)
962
                        return i;
963
 
964
                kd_size_changed(ll, cc);
965
                return 0;
966
        }
967
 
968
        case PIO_FONT:
969
                if (!perm)
970
                        return -EPERM;
971
                if (vt_cons[fg_console]->vc_mode != KD_TEXT)
972
                        return -EINVAL;
973
                return con_set_font((char *)arg, 0);
974
                /* con_set_font() defined in console.c */
975
 
976
        case GIO_FONT:
977
                if (vt_cons[fg_console]->vc_mode != KD_TEXT ||
978
                    video_mode_512ch)
979
                        return -EINVAL;
980
                return con_get_font((char *)arg);
981
                /* con_get_font() defined in console.c */
982
 
983
        case PIO_CMAP:
984
                if (!perm)
985
                        return -EPERM;
986
                return con_set_cmap((char *)arg);
987
                /* con_set_cmap() defined in console.c */
988
 
989
        case GIO_CMAP:
990
                return con_get_cmap((char *)arg);
991
                /* con_get_cmap() defined in console.c */
992
 
993
        case PIO_FONTX:
994
        {
995
                struct consolefontdesc cfdarg;
996
 
997
                if (!perm)
998
                        return -EPERM;
999
                if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1000
                        return -EINVAL;
1001
                i = verify_area(VERIFY_READ, (void *)arg,
1002
                                sizeof(struct consolefontdesc));
1003
                if (i) return i;
1004
                memcpy_fromfs(&cfdarg, (void *)arg,
1005
                              sizeof(struct consolefontdesc));
1006
 
1007
                if ( cfdarg.charcount == 256 ||
1008
                     cfdarg.charcount == 512 ) {
1009
                        i = con_set_font(cfdarg.chardata,
1010
                                cfdarg.charcount == 512);
1011
                        if (i)
1012
                                return i;
1013
                        i = con_adjust_height(cfdarg.charheight);
1014
                        return (i <= 0) ? i : kd_size_changed(i, 0);
1015
                } else
1016
                        return -EINVAL;
1017
        }
1018
 
1019
        case PIO_FONTRESET:
1020
        {
1021
                if (!perm)
1022
                        return -EPERM;
1023
                if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1024
                        return -EINVAL;
1025
 
1026
#ifdef BROKEN_GRAPHICS_PROGRAMS
1027
                /* With BROKEN_GRAPHICS_PROGRAMS defined, the default
1028
                   font is not saved. */
1029
                return -ENOSYS;
1030
#else
1031
 
1032
                i = con_set_font(NULL, 0);       /* Set font to default */
1033
                if (i) return i;
1034
 
1035
                i = con_adjust_height(default_font_height);
1036
                if ( i > 0 ) kd_size_changed(i, 0);
1037
                con_set_default_unimap();
1038
 
1039
                return 0;
1040
#endif
1041
        }
1042
 
1043
        case GIO_FONTX:
1044
        {
1045
                struct consolefontdesc cfdarg;
1046
                int nchar;
1047
 
1048
                if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1049
                        return -EINVAL;
1050
                i = verify_area(VERIFY_WRITE, (void *)arg,
1051
                        sizeof(struct consolefontdesc));
1052
                if (i) return i;
1053
                memcpy_fromfs(&cfdarg, (void *) arg,
1054
                              sizeof(struct consolefontdesc));
1055
                i = cfdarg.charcount;
1056
                cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
1057
                cfdarg.charheight = video_font_height;
1058
                memcpy_tofs((void *) arg, &cfdarg,
1059
                            sizeof(struct consolefontdesc));
1060
                if ( cfdarg.chardata )
1061
                {
1062
                        if ( i < nchar )
1063
                                return -ENOMEM;
1064
                        return con_get_font(cfdarg.chardata);
1065
                } else
1066
                        return 0;
1067
        }
1068
 
1069
        case PIO_SCRNMAP:
1070
                if (!perm)
1071
                        return -EPERM;
1072
                return con_set_trans_old((unsigned char *)arg);
1073
 
1074
        case GIO_SCRNMAP:
1075
                return con_get_trans_old((unsigned char *)arg);
1076
 
1077
        case PIO_UNISCRNMAP:
1078
                if (!perm)
1079
                        return -EPERM;
1080
                return con_set_trans_new((unsigned short *)arg);
1081
 
1082
        case GIO_UNISCRNMAP:
1083
                return con_get_trans_new((unsigned short *)arg);
1084
 
1085
        case PIO_UNIMAPCLR:
1086
              { struct unimapinit ui;
1087
                if (!perm)
1088
                        return -EPERM;
1089
                i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
1090
                if (i)
1091
                  return i;
1092
                memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
1093
                con_clear_unimap(&ui);
1094
                return 0;
1095
              }
1096
 
1097
        case PIO_UNIMAP:
1098
              { struct unimapdesc *ud;
1099
                u_short ct;
1100
                struct unipair *list;
1101
 
1102
                if (!perm)
1103
                        return -EPERM;
1104
                i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
1105
                if (i == 0) {
1106
                    ud = (struct unimapdesc *) arg;
1107
                    ct = get_user(&ud->entry_ct);
1108
                    list = get_user(&ud->entries);
1109
                    i = verify_area(VERIFY_READ, (void *) list,
1110
                                    ct*sizeof(struct unipair));
1111
                }
1112
                if (i)
1113
                  return i;
1114
                return con_set_unimap(ct, list);
1115
              }
1116
 
1117
        case GIO_UNIMAP:
1118
              { struct unimapdesc *ud;
1119
                u_short ct;
1120
                struct unipair *list;
1121
 
1122
                i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
1123
                if (i == 0) {
1124
                    ud = (struct unimapdesc *) arg;
1125
                    ct = get_user(&ud->entry_ct);
1126
                    list = get_user(&ud->entries);
1127
                    if (ct)
1128
                      i = verify_area(VERIFY_WRITE, (void *) list,
1129
                                      ct*sizeof(struct unipair));
1130
                }
1131
                if (i)
1132
                  return i;
1133
                return con_get_unimap(ct, &(ud->entry_ct), list);
1134
              }
1135
        case VT_LOCKSWITCH:
1136
                if (!suser())
1137
                   return -EPERM;
1138
                vt_dont_switch = 1;
1139
                return 0;
1140
        case VT_UNLOCKSWITCH:
1141
                if (!suser())
1142
                   return -EPERM;
1143
                vt_dont_switch = 0;
1144
                return 0;
1145
        default:
1146
                return -ENOIOCTLCMD;
1147
        }
1148
}

powered by: WebSVN 2.1.0

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