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