1
2
3
4
5
6
7
8
9
10
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
39
40char vt_dont_switch;
41extern 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
48
49
50
51
52
53
54
55
56
57
58
59struct vt_struct *vt_cons[MAX_NR_CONSOLES];
60
61
62
63
64unsigned char keyboard_type = KB_101;
65
66#if !defined(__alpha__) && !defined(__ia64__) && !defined(__mips__) && !defined(__arm__) && !defined(__sh__)
67asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int on);
68#endif
69
70unsigned int video_font_height;
71unsigned int default_font_height;
72unsigned int video_scan_lines;
73
74
75
76
77
78#define GPFIRST 0x3b4
79#define GPLAST 0x3df
80#define GPNUM (GPLAST - GPFIRST + 1)
81
82
83
84
85
86
87
88
89
90
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
98static void
99kd_nosound(unsigned long ignored)
100{
101
102 outb(inb_p(0x61)&0xFC, 0x61);
103 return;
104}
105
106void
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
121 outb_p(inb_p(0x61)|3, 0x61);
122
123 outb_p(0xB6, 0x43);
124
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
140void
141_kd_mksound(unsigned int hz, unsigned int ticks)
142{
143}
144
145#endif
146
147int _kbd_rate(struct kbd_repeat *rep)
148{
149 return -EINVAL;
150}
151
152void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
153int (*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)
158static inline int
159do_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
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
203#if !defined(__mc68000__) && !defined(__powerpc__)
204
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;
229
230
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
245static inline int
246do_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
268static inline int
269do_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
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;
290
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) {
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 {
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
358static inline int
359do_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
399static inline int
400do_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
425
426
427int 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))
439 return -ENOIOCTLCMD;
440
441
442
443
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
467
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
480
481 ucval = keyboard_type;
482 goto setchar;
483
484#if defined(CONFIG_X86)
485
486
487
488
489 case KDADDIO:
490 case KDDELIO:
491
492
493
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
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
528
529
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
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
566
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
603
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
665
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
681
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
695
696
697
698
699
700
701
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
727 vt_cons[console]->vt_mode.frsig = 0;
728 vt_cons[console]->vt_pid = current->pid;
729
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
740
741
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;
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
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
769
770
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
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
796
797
798
799
800
801
802
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
812
813 if (vt_cons[console]->vt_newvt >= 0)
814 {
815 if (arg == 0)
816
817
818
819
820 vt_cons[console]->vt_newvt = -1;
821
822 else
823 {
824
825
826
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
835
836
837
838 acquire_console_sem();
839 complete_change_console(newvt);
840 release_console_sem();
841 }
842 }
843
844
845
846
847 else
848 {
849
850
851
852 if (arg != VT_ACKACQ)
853 return -EINVAL;
854 }
855
856 return 0;
857
858
859
860
861 case VT_DISALLOCATE:
862 if (arg > MAX_NR_CONSOLES)
863 return -ENXIO;
864 if (arg == 0) {
865
866 for (i=1; i<MAX_NR_CONSOLES; i++)
867 if (! VT_BUSY(i))
868 vc_disallocate(i);
869 } else {
870
871 arg--;
872 if (VT_BUSY(arg))
873 return -EBUSY;
874 if (arg)
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;
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;
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
982
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
1086
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
1106 return -ENOIOCTLCMD;
1107 case VC_POWERMODE:
1108 if (!perm)
1109 return -EPERM;
1110 return console_powermode((int) arg);
1111#endif
1112 default:
1113 return -ENOIOCTLCMD;
1114 }
1115}
1116
1117
1118
1119
1120
1121
1122
1123
1124static DECLARE_WAIT_QUEUE_HEAD(vt_activate_queue);
1125
1126
1127
1128
1129
1130int 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
1153void 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())
1165 reset_palette(new_console) ;
1166}
1167
1168
1169
1170
1171void complete_change_console(unsigned int new_console)
1172{
1173 unsigned char old_vc_mode;
1174
1175 last_console = fg_console;
1176
1177
1178
1179
1180
1181
1182 old_vc_mode = vt_cons[fg_console]->vc_mode;
1183 switch_screen(new_console);
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
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
1205
1206
1207
1208 if (vt_cons[new_console]->vt_mode.mode == VT_PROCESS)
1209 {
1210
1211
1212
1213
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
1221
1222
1223
1224
1225
1226
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
1242
1243 vt_wake_waitactive();
1244 return;
1245}
1246
1247
1248
1249
1250void 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
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 if (vt_cons[fg_console]->vt_mode.mode == VT_PROCESS)
1273 {
1274
1275
1276
1277
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
1285
1286
1287
1288 vt_cons[fg_console]->vt_newvt = new_console;
1289 return;
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301 reset_vc(fg_console);
1302
1303
1304
1305
1306 }
1307
1308
1309
1310
1311 if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
1312 return;
1313
1314 complete_change_console(new_console);
1315}
1316
1317