This source file includes following definitions.
- kd_size_changed
- kd_nosound
- _kd_mksound
- vt_ioctl
1
2
3
4
5
6
7
8
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
27 #include "kbd_kern.h"
28 #include "vt_kern.h"
29 #include "diacr.h"
30 #include "selection.h"
31
32 extern char vt_dont_switch;
33 extern struct tty_driver console_driver;
34
35 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
36 #define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
52
53 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
54
55 extern int getkeycode(unsigned int scancode);
56 extern int setkeycode(unsigned int scancode, unsigned int keycode);
57 extern void compute_shiftstate(void);
58 extern void change_console(unsigned int new_console);
59 extern void complete_change_console(unsigned int new_console);
60 extern int vt_waitactive(void);
61 extern void do_blank_screen(int nopowersave);
62
63 extern unsigned int keymap_count;
64
65
66
67
68
69 extern int con_set_trans_old(unsigned char * table);
70 extern int con_get_trans_old(unsigned char * table);
71 extern int con_set_trans_new(unsigned short * table);
72 extern int con_get_trans_new(unsigned short * table);
73 extern void con_clear_unimap(struct unimapinit *ui);
74 extern int con_set_unimap(ushort ct, struct unipair *list);
75 extern int con_get_unimap(ushort ct, ushort *uct, struct unipair *list);
76 extern void con_set_default_unimap(void);
77 extern int con_set_font(char * fontmap, int ch512);
78 extern int con_get_font(char * fontmap);
79 extern int con_set_cmap(unsigned char *cmap);
80 extern int con_get_cmap(unsigned char *cmap);
81 extern void reset_palette(int currcons);
82 extern int con_adjust_height(unsigned long fontheight);
83
84 extern int video_mode_512ch;
85 extern unsigned long video_font_height;
86 extern unsigned long default_font_height;
87 extern unsigned long video_scan_lines;
88
89
90
91
92
93 #define GPFIRST 0x3b4
94 #define GPLAST 0x3df
95 #define GPNUM (GPLAST - GPFIRST + 1)
96
97
98
99
100
101
102
103
104
105 static int
106 kd_size_changed(int row, int col)
107 {
108 struct task_struct *p;
109 int i;
110
111 if ( !row && !col ) return 0;
112
113 for ( i = 0 ; i < MAX_NR_CONSOLES ; i++ )
114 {
115 if ( console_driver.table[i] )
116 {
117 if ( row ) console_driver.table[i]->winsize.ws_row = row;
118 if ( col ) console_driver.table[i]->winsize.ws_col = col;
119 }
120 }
121
122 for_each_task(p)
123 {
124 if ( p->tty && MAJOR(p->tty->device) == TTY_MAJOR &&
125 MINOR(p->tty->device) <= MAX_NR_CONSOLES && MINOR(p->tty->device) )
126 {
127 send_sig(SIGWINCH, p, 1);
128 }
129 }
130
131 return 0;
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149 static void
150 kd_nosound(unsigned long ignored)
151 {
152
153 outb(inb_p(0x61)&0xFC, 0x61);
154 return;
155 }
156
157 void
158 _kd_mksound(unsigned int hz, unsigned int ticks)
159 {
160 static struct timer_list sound_timer = { NULL, NULL, 0, 0,
161 kd_nosound };
162
163 unsigned int count = 0;
164
165 if (hz > 20 && hz < 32767)
166 count = 1193180 / hz;
167
168 cli();
169 del_timer(&sound_timer);
170 if (count) {
171
172 outb_p(inb_p(0x61)|3, 0x61);
173
174 outb_p(0xB6, 0x43);
175
176 outb_p(count & 0xff, 0x42);
177 outb((count >> 8) & 0xff, 0x42);
178
179 if (ticks) {
180 sound_timer.expires = jiffies+ticks;
181 add_timer(&sound_timer);
182 }
183 } else
184 kd_nosound(0);
185 sti();
186 return;
187 }
188
189 void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
190
191
192
193
194
195 int vt_ioctl(struct tty_struct *tty, struct file * file,
196 unsigned int cmd, unsigned long arg)
197 {
198 int i, perm;
199 unsigned int console;
200 unsigned char ucval;
201 struct kbd_struct * kbd;
202 struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
203
204 console = vt->vc_num;
205
206 if (!vc_cons_allocated(console))
207 return -ENOIOCTLCMD;
208
209
210
211
212
213 perm = 0;
214 if (current->tty == tty || suser())
215 perm = 1;
216
217 kbd = kbd_table + console;
218 switch (cmd) {
219 case KIOCSOUND:
220 if (!perm)
221 return -EPERM;
222 kd_mksound(1193180 / (unsigned int) arg, 0);
223 return 0;
224
225 case KDMKTONE:
226 if (!perm)
227 return -EPERM;
228 {
229 unsigned int ticks, count;
230
231
232
233
234
235 ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
236 count = ticks ? (1193180 / (arg & 0xffff)) : 0;
237 kd_mksound(count, ticks);
238 return 0;
239 }
240
241 case KDGKBTYPE:
242
243
244
245 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
246 if (!i)
247 put_user(KB_101, (char *) arg);
248 return i;
249
250 case KDADDIO:
251 case KDDELIO:
252
253
254
255
256 if (arg < GPFIRST || arg > GPLAST)
257 return -EINVAL;
258 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
259
260 case KDENABIO:
261 case KDDISABIO:
262 return sys_ioperm(GPFIRST, GPNUM,
263 (cmd == KDENABIO)) ? -ENXIO : 0;
264
265 case KDSETMODE:
266
267
268
269
270
271 if (!perm)
272 return -EPERM;
273 switch (arg) {
274 case KD_GRAPHICS:
275 break;
276 case KD_TEXT0:
277 case KD_TEXT1:
278 arg = KD_TEXT;
279 case KD_TEXT:
280 break;
281 default:
282 return -EINVAL;
283 }
284 if (vt_cons[console]->vc_mode == (unsigned char) arg)
285 return 0;
286 vt_cons[console]->vc_mode = (unsigned char) arg;
287 if (console != fg_console)
288 return 0;
289
290
291
292 if (arg == KD_TEXT)
293 do_unblank_screen();
294 else
295 do_blank_screen(1);
296 return 0;
297
298 case KDGETMODE:
299 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
300 if (!i)
301 put_user(vt_cons[console]->vc_mode, (int *) arg);
302 return i;
303
304 case KDMAPDISP:
305 case KDUNMAPDISP:
306
307
308
309
310 return -EINVAL;
311
312 case KDSKBMODE:
313 if (!perm)
314 return -EPERM;
315 switch(arg) {
316 case K_RAW:
317 kbd->kbdmode = VC_RAW;
318 break;
319 case K_MEDIUMRAW:
320 kbd->kbdmode = VC_MEDIUMRAW;
321 break;
322 case K_XLATE:
323 kbd->kbdmode = VC_XLATE;
324 compute_shiftstate();
325 break;
326 case K_UNICODE:
327 kbd->kbdmode = VC_UNICODE;
328 compute_shiftstate();
329 break;
330 default:
331 return -EINVAL;
332 }
333 if (tty->ldisc.flush_buffer)
334 tty->ldisc.flush_buffer(tty);
335 return 0;
336
337 case KDGKBMODE:
338 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
339 if (!i) {
340 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
341 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
342 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
343 K_XLATE);
344 put_user(ucval, (int *) arg);
345 }
346 return i;
347
348
349
350 case KDSKBMETA:
351 switch(arg) {
352 case K_METABIT:
353 clr_vc_kbd_mode(kbd, VC_META);
354 break;
355 case K_ESCPREFIX:
356 set_vc_kbd_mode(kbd, VC_META);
357 break;
358 default:
359 return -EINVAL;
360 }
361 return 0;
362
363 case KDGKBMETA:
364 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
365 if (!i) {
366 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
367 K_METABIT);
368 put_user(ucval, (int *) arg);
369 }
370 return i;
371
372 case KDGETKEYCODE:
373 {
374 struct kbkeycode * const a = (struct kbkeycode *)arg;
375 unsigned int sc;
376 int kc;
377
378 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbkeycode));
379 if (i)
380 return i;
381 sc = get_user(&a->scancode);
382 kc = getkeycode(sc);
383 if (kc < 0)
384 return kc;
385 put_user(kc, &a->keycode);
386 return 0;
387 }
388
389 case KDSETKEYCODE:
390 {
391 struct kbkeycode * const a = (struct kbkeycode *)arg;
392 unsigned int sc, kc;
393
394 if (!perm)
395 return -EPERM;
396 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbkeycode));
397 if (i)
398 return i;
399 sc = get_user(&a->scancode);
400 kc = get_user(&a->keycode);
401 return setkeycode(sc, kc);
402 }
403
404 case KDGKBENT:
405 {
406 struct kbentry * const a = (struct kbentry *)arg;
407 ushort *key_map, val;
408 u_char s;
409
410 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
411 if (i)
412 return i;
413 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
414 return -EINVAL;
415 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
416 return -EINVAL;
417 key_map = key_maps[s];
418 if (key_map) {
419 val = U(key_map[i]);
420 if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
421 val = K_HOLE;
422 } else
423 val = (i ? K_HOLE : K_NOSUCHMAP);
424 put_user(val, &a->kb_value);
425 return 0;
426 }
427
428 case KDSKBENT:
429 {
430 const struct kbentry * a = (struct kbentry *)arg;
431 ushort *key_map;
432 u_char s;
433 u_short v, ov;
434
435 if (!perm)
436 return -EPERM;
437 i = verify_area(VERIFY_READ, (const void *)a, sizeof(struct kbentry));
438 if (i)
439 return i;
440 if ((i = get_user(&a->kb_index)) >= NR_KEYS)
441 return -EINVAL;
442 if ((s = get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
443 return -EINVAL;
444 v = get_user(&a->kb_value);
445 if (!i && v == K_NOSUCHMAP) {
446
447 key_map = key_maps[s];
448 if (s && key_map) {
449 key_maps[s] = 0;
450 if (key_map[0] == U(K_ALLOCATED)) {
451 kfree_s(key_map, sizeof(plain_map));
452 keymap_count--;
453 }
454 }
455 return 0;
456 }
457
458 if (KTYP(v) < NR_TYPES) {
459 if (KVAL(v) > max_vals[KTYP(v)])
460 return -EINVAL;
461 } else
462 if (kbd->kbdmode != VC_UNICODE)
463 return -EINVAL;
464
465
466 if (!i)
467 return 0;
468
469 if (!(key_map = key_maps[s])) {
470 int j;
471
472 if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
473 return -EPERM;
474
475 key_map = (ushort *) kmalloc(sizeof(plain_map),
476 GFP_KERNEL);
477 if (!key_map)
478 return -ENOMEM;
479 key_maps[s] = key_map;
480 key_map[0] = U(K_ALLOCATED);
481 for (j = 1; j < NR_KEYS; j++)
482 key_map[j] = U(K_HOLE);
483 keymap_count++;
484 }
485 ov = U(key_map[i]);
486 if (v == ov)
487 return 0;
488
489
490
491
492 if (((ov == K_SAK) || (v == K_SAK)) && !suser())
493 return -EPERM;
494 key_map[i] = U(v);
495 if (!s && (KTYP(ov) == KT_SHIFT || KTYP(v) == KT_SHIFT))
496 compute_shiftstate();
497 return 0;
498 }
499
500 case KDGKBSENT:
501 {
502 struct kbsentry *a = (struct kbsentry *)arg;
503 char *p;
504 u_char *q;
505 int sz;
506
507 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
508 if (i)
509 return i;
510 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
511 return -EINVAL;
512 sz = sizeof(a->kb_string) - 1;
513
514 q = a->kb_string;
515 p = func_table[i];
516 if(p)
517 for ( ; *p && sz; p++, sz--)
518 put_user(*p, q++);
519 put_user('\0', q);
520 return ((p && *p) ? -EOVERFLOW : 0);
521 }
522
523 case KDSKBSENT:
524 {
525 struct kbsentry * const a = (struct kbsentry *)arg;
526 int delta;
527 char *first_free, *fj, *fnw;
528 int j, k, sz;
529 u_char *p;
530 char *q;
531
532 if (!perm)
533 return -EPERM;
534 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
535 if (i)
536 return i;
537 if ((i = get_user(&a->kb_func)) >= MAX_NR_FUNC)
538 return -EINVAL;
539 q = func_table[i];
540
541 first_free = funcbufptr + (funcbufsize - funcbufleft);
542 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
543 if (j < MAX_NR_FUNC)
544 fj = func_table[j];
545 else
546 fj = first_free;
547
548 delta = (q ? -strlen(q) : 1);
549 sz = sizeof(a->kb_string);
550
551 for (p = a->kb_string; get_user(p) && sz; p++,sz--)
552 delta++;
553 if (!sz)
554 return -EOVERFLOW;
555 if (delta <= funcbufleft) {
556 if (j < MAX_NR_FUNC) {
557 memmove(fj + delta, fj, first_free - fj);
558 for (k = j; k < MAX_NR_FUNC; k++)
559 if (func_table[k])
560 func_table[k] += delta;
561 }
562 if (!q)
563 func_table[i] = fj;
564 funcbufleft -= delta;
565 } else {
566 sz = 256;
567 while (sz < funcbufsize - funcbufleft + delta)
568 sz <<= 1;
569 fnw = (char *) kmalloc(sz, GFP_KERNEL);
570 if(!fnw)
571 return -ENOMEM;
572
573 if (!q)
574 func_table[i] = fj;
575 if (fj > funcbufptr)
576 memmove(fnw, funcbufptr, fj - funcbufptr);
577 for (k = 0; k < j; k++)
578 if (func_table[k])
579 func_table[k] = fnw + (func_table[k] - funcbufptr);
580
581 if (first_free > fj) {
582 memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
583 for (k = j; k < MAX_NR_FUNC; k++)
584 if (func_table[k])
585 func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
586 }
587 if (funcbufptr != func_buf)
588 kfree_s(funcbufptr, funcbufsize);
589 funcbufptr = fnw;
590 funcbufleft = funcbufleft - delta + sz - funcbufsize;
591 funcbufsize = sz;
592 }
593 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
594 if (!(*q = get_user(p)))
595 break;
596 return 0;
597 }
598
599 case KDGKBDIACR:
600 {
601 struct kbdiacrs *a = (struct kbdiacrs *)arg;
602
603 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
604 if (i)
605 return i;
606 put_user(accent_table_size, &a->kb_cnt);
607 memcpy_tofs(a->kbdiacr, accent_table,
608 accent_table_size*sizeof(struct kbdiacr));
609 return 0;
610 }
611
612 case KDSKBDIACR:
613 {
614 struct kbdiacrs *a = (struct kbdiacrs *)arg;
615 unsigned int ct;
616
617 if (!perm)
618 return -EPERM;
619 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
620 if (i)
621 return i;
622 ct = get_user(&a->kb_cnt);
623 if (ct >= MAX_DIACR)
624 return -EINVAL;
625 accent_table_size = ct;
626 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
627 return 0;
628 }
629
630
631
632 case KDGKBLED:
633 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
634 if (i)
635 return i;
636 put_user(kbd->ledflagstate |
637 (kbd->default_ledflagstate << 4), (char *) arg);
638 return 0;
639
640 case KDSKBLED:
641 if (!perm)
642 return -EPERM;
643 if (arg & ~0x77)
644 return -EINVAL;
645 kbd->ledflagstate = (arg & 7);
646 kbd->default_ledflagstate = ((arg >> 4) & 7);
647 set_leds();
648 return 0;
649
650
651
652 case KDGETLED:
653 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
654 if (i)
655 return i;
656 put_user(getledstate(), (char *) arg);
657 return 0;
658
659 case KDSETLED:
660 if (!perm)
661 return -EPERM;
662 setledstate(kbd, arg);
663 return 0;
664
665
666
667
668
669
670
671
672
673
674
675 case KDSIGACCEPT:
676 {
677 extern int spawnpid, spawnsig;
678 if (!perm)
679 return -EPERM;
680 if (arg < 1 || arg > NSIG || arg == SIGKILL)
681 return -EINVAL;
682 spawnpid = current->pid;
683 spawnsig = arg;
684 return 0;
685 }
686
687 case VT_SETMODE:
688 {
689 struct vt_mode *vtmode = (struct vt_mode *)arg;
690 char mode;
691
692 if (!perm)
693 return -EPERM;
694 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
695 if (i)
696 return i;
697 mode = get_user(&vtmode->mode);
698 if (mode != VT_AUTO && mode != VT_PROCESS)
699 return -EINVAL;
700 vt_cons[console]->vt_mode.mode = mode;
701 vt_cons[console]->vt_mode.waitv = get_user(&vtmode->waitv);
702 vt_cons[console]->vt_mode.relsig = get_user(&vtmode->relsig);
703 vt_cons[console]->vt_mode.acqsig = get_user(&vtmode->acqsig);
704
705 vt_cons[console]->vt_mode.frsig = 0;
706 vt_cons[console]->vt_pid = current->pid;
707 vt_cons[console]->vt_newvt = 0;
708 return 0;
709 }
710
711 case VT_GETMODE:
712 {
713 struct vt_mode *vtmode = (struct vt_mode *)arg;
714
715 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
716 if (i)
717 return i;
718 put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
719 put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
720 put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
721 put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
722 put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
723 return 0;
724 }
725
726
727
728
729
730
731 case VT_GETSTATE:
732 {
733 struct vt_stat *vtstat = (struct vt_stat *)arg;
734 unsigned short state, mask;
735
736 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
737 if (i)
738 return i;
739 put_user(fg_console + 1, &vtstat->v_active);
740 state = 1;
741 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
742 if (VT_IS_IN_USE(i))
743 state |= mask;
744 put_user(state, &vtstat->v_state);
745 return 0;
746 }
747
748
749
750
751 case VT_OPENQRY:
752 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(int));
753 if (i)
754 return i;
755 for (i = 0; i < MAX_NR_CONSOLES; ++i)
756 if (! VT_IS_IN_USE(i))
757 break;
758 put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int *) arg);
759 return 0;
760
761
762
763
764
765
766 case VT_ACTIVATE:
767 if (!perm)
768 return -EPERM;
769 if (arg == 0 || arg > MAX_NR_CONSOLES)
770 return -ENXIO;
771 arg--;
772 i = vc_allocate(arg);
773 if (i)
774 return i;
775 change_console(arg);
776 return 0;
777
778
779
780
781 case VT_WAITACTIVE:
782 if (!perm)
783 return -EPERM;
784 if (arg == 0 || arg > MAX_NR_CONSOLES)
785 return -ENXIO;
786 arg--;
787 while (fg_console != arg)
788 {
789 if (vt_waitactive() < 0)
790 return -EINTR;
791 }
792 return 0;
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 complete_change_console(newvt);
834 }
835 }
836
837
838
839
840 else
841 {
842
843
844
845 if (arg != VT_ACKACQ)
846 return -EINVAL;
847 }
848
849 return 0;
850
851
852
853
854 case VT_DISALLOCATE:
855 if (arg > MAX_NR_CONSOLES)
856 return -ENXIO;
857 if (arg == 0) {
858
859 for (i=1; i<MAX_NR_CONSOLES; i++)
860 if (! VT_BUSY(i))
861 vc_disallocate(i);
862 } else {
863
864 arg--;
865 if (VT_BUSY(arg))
866 return -EBUSY;
867 if (arg)
868 vc_disallocate(arg);
869 }
870 return 0;
871
872 case VT_RESIZE:
873 {
874 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
875 ushort ll,cc;
876 if (!perm)
877 return -EPERM;
878 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
879 if (i)
880 return i;
881 ll = get_user(&vtsizes->v_rows);
882 cc = get_user(&vtsizes->v_cols);
883 i = vc_resize(ll, cc);
884 return i ? i : kd_size_changed(ll, cc);
885 }
886
887 case VT_RESIZEX:
888 {
889 struct vt_consize *vtconsize = (struct vt_consize *) arg;
890 ushort ll,cc,vlin,clin,vcol,ccol;
891 if (!perm)
892 return -EPERM;
893 i = verify_area(VERIFY_READ, (void *)vtconsize, sizeof(struct vt_consize));
894 if (i)
895 return i;
896 ll = get_user(&vtconsize->v_rows);
897 cc = get_user(&vtconsize->v_cols);
898 vlin = get_user(&vtconsize->v_vlin);
899 clin = get_user(&vtconsize->v_clin);
900 vcol = get_user(&vtconsize->v_vcol);
901 ccol = get_user(&vtconsize->v_ccol);
902 vlin = vlin ? vlin : video_scan_lines;
903 if ( clin )
904 {
905 if ( ll )
906 {
907 if ( ll != vlin/clin )
908 return EINVAL;
909 }
910 else
911 ll = vlin/clin;
912 }
913 if ( vcol && ccol )
914 {
915 if ( cc )
916 {
917 if ( cc != vcol/ccol )
918 return EINVAL;
919 }
920 else
921 cc = vcol/ccol;
922 }
923
924 if ( clin > 32 )
925 return EINVAL;
926
927 if ( vlin )
928 video_scan_lines = vlin;
929 if ( clin )
930 video_font_height = clin;
931
932 i = vc_resize(ll, cc);
933 if (i)
934 return i;
935
936 kd_size_changed(ll, cc);
937 return 0;
938 }
939
940 case PIO_FONT:
941 if (!perm)
942 return -EPERM;
943 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
944 return -EINVAL;
945 return con_set_font((char *)arg, 0);
946
947
948 case GIO_FONT:
949 if (vt_cons[fg_console]->vc_mode != KD_TEXT ||
950 video_mode_512ch)
951 return -EINVAL;
952 return con_get_font((char *)arg);
953
954
955 case PIO_CMAP:
956 if (!perm)
957 return -EPERM;
958 return con_set_cmap((char *)arg);
959
960
961 case GIO_CMAP:
962 return con_get_cmap((char *)arg);
963
964
965 case PIO_FONTX:
966 {
967 struct consolefontdesc cfdarg;
968
969 if (!perm)
970 return -EPERM;
971 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
972 return -EINVAL;
973 i = verify_area(VERIFY_READ, (void *)arg,
974 sizeof(struct consolefontdesc));
975 if (i) return i;
976 memcpy_fromfs(&cfdarg, (void *)arg,
977 sizeof(struct consolefontdesc));
978
979 if ( cfdarg.charcount == 256 ||
980 cfdarg.charcount == 512 ) {
981 i = con_set_font(cfdarg.chardata,
982 cfdarg.charcount == 512);
983 if (i)
984 return i;
985 i = con_adjust_height(cfdarg.charheight);
986 return (i <= 0) ? i : kd_size_changed(i, 0);
987 } else
988 return -EINVAL;
989 }
990
991 case PIO_FONTRESET:
992 {
993 if (!perm)
994 return -EPERM;
995 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
996 return -EINVAL;
997
998 #ifdef BROKEN_GRAPHICS_PROGRAMS
999
1000
1001 return -ENOSYS;
1002 #else
1003
1004 i = con_set_font(NULL, 0);
1005 if (i) return i;
1006
1007 i = con_adjust_height(default_font_height);
1008 if ( i > 0 ) kd_size_changed(i, 0);
1009 con_set_default_unimap();
1010
1011 return 0;
1012 #endif
1013 }
1014
1015 case GIO_FONTX:
1016 {
1017 struct consolefontdesc cfdarg;
1018 int nchar;
1019
1020 if (vt_cons[fg_console]->vc_mode != KD_TEXT)
1021 return -EINVAL;
1022 i = verify_area(VERIFY_WRITE, (void *)arg,
1023 sizeof(struct consolefontdesc));
1024 if (i) return i;
1025 memcpy_fromfs(&cfdarg, (void *) arg,
1026 sizeof(struct consolefontdesc));
1027 i = cfdarg.charcount;
1028 cfdarg.charcount = nchar = video_mode_512ch ? 512 : 256;
1029 cfdarg.charheight = video_font_height;
1030 memcpy_tofs((void *) arg, &cfdarg,
1031 sizeof(struct consolefontdesc));
1032 if ( cfdarg.chardata )
1033 {
1034 if ( i < nchar )
1035 return -ENOMEM;
1036 return con_get_font(cfdarg.chardata);
1037 } else
1038 return 0;
1039 }
1040
1041 case PIO_SCRNMAP:
1042 if (!perm)
1043 return -EPERM;
1044 return con_set_trans_old((unsigned char *)arg);
1045
1046 case GIO_SCRNMAP:
1047 return con_get_trans_old((unsigned char *)arg);
1048
1049 case PIO_UNISCRNMAP:
1050 if (!perm)
1051 return -EPERM;
1052 return con_set_trans_new((unsigned short *)arg);
1053
1054 case GIO_UNISCRNMAP:
1055 return con_get_trans_new((unsigned short *)arg);
1056
1057 case PIO_UNIMAPCLR:
1058 { struct unimapinit ui;
1059 if (!perm)
1060 return -EPERM;
1061 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapinit));
1062 if (i)
1063 return i;
1064 memcpy_fromfs(&ui, (void *)arg, sizeof(struct unimapinit));
1065 con_clear_unimap(&ui);
1066 return 0;
1067 }
1068
1069 case PIO_UNIMAP:
1070 { struct unimapdesc *ud;
1071 u_short ct;
1072 struct unipair *list;
1073
1074 if (!perm)
1075 return -EPERM;
1076 i = verify_area(VERIFY_READ, (void *)arg, sizeof(struct unimapdesc));
1077 if (i == 0) {
1078 ud = (struct unimapdesc *) arg;
1079 ct = get_user(&ud->entry_ct);
1080 list = get_user(&ud->entries);
1081 i = verify_area(VERIFY_READ, (void *) list,
1082 ct*sizeof(struct unipair));
1083 }
1084 if (i)
1085 return i;
1086 return con_set_unimap(ct, list);
1087 }
1088
1089 case GIO_UNIMAP:
1090 { struct unimapdesc *ud;
1091 u_short ct;
1092 struct unipair *list;
1093
1094 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct unimapdesc));
1095 if (i == 0) {
1096 ud = (struct unimapdesc *) arg;
1097 ct = get_user(&ud->entry_ct);
1098 list = get_user(&ud->entries);
1099 if (ct)
1100 i = verify_area(VERIFY_WRITE, (void *) list,
1101 ct*sizeof(struct unipair));
1102 }
1103 if (i)
1104 return i;
1105 return con_get_unimap(ct, &(ud->entry_ct), list);
1106 }
1107 case VT_LOCKSWITCH:
1108 if (!suser())
1109 return -EPERM;
1110 vt_dont_switch = 1;
1111 return 0;
1112 case VT_UNLOCKSWITCH:
1113 if (!suser())
1114 return -EPERM;
1115 vt_dont_switch = 0;
1116 return 0;
1117 default:
1118 return -ENOIOCTLCMD;
1119 }
1120 }