This source file includes following definitions.
- kd_nosound
- kd_mksound
- vt_ioctl
1
2
3
4
5
6
7
8
9
10 #include <linux/types.h>
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/tty.h>
14 #include <linux/timer.h>
15 #include <linux/kernel.h>
16 #include <linux/kd.h>
17 #include <linux/vt.h>
18 #include <linux/string.h>
19 #include <linux/malloc.h>
20
21 #include <asm/io.h>
22 #include <asm/segment.h>
23
24 #include "kbd_kern.h"
25 #include "vt_kern.h"
26 #include "diacr.h"
27
28 extern struct tty_driver console_driver;
29
30 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
46
47 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int on);
48
49 extern void compute_shiftstate(void);
50 extern void change_console(unsigned int new_console);
51 extern void complete_change_console(unsigned int new_console);
52 extern int vt_waitactive(void);
53
54 extern unsigned int keymap_count;
55
56
57
58
59 extern int con_set_trans(char * table);
60 extern int con_get_trans(char * table);
61 extern int con_set_font(char * fontmap);
62 extern int con_get_font(char * fontmap);
63
64
65
66
67
68 #define GPFIRST 0x3b4
69 #define GPLAST 0x3df
70 #define GPNUM (GPLAST - GPFIRST + 1)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87 static void
88 kd_nosound(unsigned long ignored)
89 {
90
91 outb(inb_p(0x61)&0xFC, 0x61);
92 return;
93 }
94
95 void
96 kd_mksound(unsigned int count, unsigned int ticks)
97 {
98 static struct timer_list sound_timer = { NULL, NULL, 0, 0, kd_nosound };
99
100 cli();
101 del_timer(&sound_timer);
102 if (count) {
103
104 outb_p(inb_p(0x61)|3, 0x61);
105
106 outb_p(0xB6, 0x43);
107
108 outb_p(count & 0xff, 0x42);
109 outb((count >> 8) & 0xff, 0x42);
110
111 if (ticks) {
112 sound_timer.expires = ticks;
113 add_timer(&sound_timer);
114 }
115 } else
116 kd_nosound(0);
117 sti();
118 return;
119 }
120
121
122
123
124
125 int vt_ioctl(struct tty_struct *tty, struct file * file,
126 unsigned int cmd, unsigned long arg)
127 {
128 int i;
129 unsigned int console;
130 unsigned char ucval;
131 struct kbd_struct * kbd;
132 struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
133
134 console = vt->vc_num;
135
136 if (!vc_cons_allocated(console))
137 return -ENOIOCTLCMD;
138
139 kbd = kbd_table + console;
140 switch (cmd) {
141 case KIOCSOUND:
142 kd_mksound((unsigned int)arg, 0);
143 return 0;
144
145 case KDMKTONE:
146 {
147 unsigned int ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
148
149
150
151
152
153 kd_mksound(arg & 0xffff, ticks);
154 if (ticks == 0)
155 kd_nosound(0);
156 return 0;
157 }
158
159 case KDGKBTYPE:
160
161
162
163 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
164 if (!i)
165 put_fs_byte(KB_101, (char *) arg);
166 return i;
167
168 case KDADDIO:
169 case KDDELIO:
170
171
172
173
174 if (arg < GPFIRST || arg > GPLAST)
175 return -EINVAL;
176 return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
177
178 case KDENABIO:
179 case KDDISABIO:
180 return sys_ioperm(GPFIRST, GPNUM,
181 (cmd == KDENABIO)) ? -ENXIO : 0;
182
183 case KDSETMODE:
184
185
186
187
188
189 switch (arg) {
190 case KD_GRAPHICS:
191 break;
192 case KD_TEXT0:
193 case KD_TEXT1:
194 arg = KD_TEXT;
195 case KD_TEXT:
196 break;
197 default:
198 return -EINVAL;
199 }
200 if (vt_cons[console]->vc_mode == (unsigned char) arg)
201 return 0;
202 vt_cons[console]->vc_mode = (unsigned char) arg;
203 if (console != fg_console)
204 return 0;
205
206
207
208 if (arg == KD_TEXT)
209 unblank_screen();
210 else {
211 timer_active &= ~(1<<BLANK_TIMER);
212 blank_screen();
213 }
214 return 0;
215
216 case KDGETMODE:
217 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
218 if (!i)
219 put_fs_long(vt_cons[console]->vc_mode, (unsigned long *) arg);
220 return i;
221
222 case KDMAPDISP:
223 case KDUNMAPDISP:
224
225
226
227
228 return -EINVAL;
229
230 case KDSKBMODE:
231 switch(arg) {
232 case K_RAW:
233 kbd->kbdmode = VC_RAW;
234 break;
235 case K_MEDIUMRAW:
236 kbd->kbdmode = VC_MEDIUMRAW;
237 break;
238 case K_XLATE:
239 kbd->kbdmode = VC_XLATE;
240 compute_shiftstate();
241 break;
242 case K_UNICODE:
243 kbd->kbdmode = VC_UNICODE;
244 compute_shiftstate();
245 break;
246 default:
247 return -EINVAL;
248 }
249 if (tty->ldisc.flush_buffer)
250 tty->ldisc.flush_buffer(tty);
251 return 0;
252
253 case KDGKBMODE:
254 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
255 if (!i) {
256 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
257 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
258 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
259 K_XLATE);
260 put_fs_long(ucval, (unsigned long *) arg);
261 }
262 return i;
263
264
265
266 case KDSKBMETA:
267 switch(arg) {
268 case K_METABIT:
269 clr_vc_kbd_mode(kbd, VC_META);
270 break;
271 case K_ESCPREFIX:
272 set_vc_kbd_mode(kbd, VC_META);
273 break;
274 default:
275 return -EINVAL;
276 }
277 return 0;
278
279 case KDGKBMETA:
280 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long));
281 if (!i) {
282 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
283 K_METABIT);
284 put_fs_long(ucval, (unsigned long *) arg);
285 }
286 return i;
287
288 case KDGKBENT:
289 {
290 struct kbentry * const a = (struct kbentry *)arg;
291 ushort *key_map, val;
292 u_char s;
293
294 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbentry));
295 if (i)
296 return i;
297 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
298 return -EINVAL;
299 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
300 return -EINVAL;
301 key_map = key_maps[s];
302 if (key_map) {
303 val = U(key_map[i]);
304 if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
305 val = K_HOLE;
306 } else
307 val = (i ? K_HOLE : K_NOSUCHMAP);
308 put_fs_word(val, (short *) &a->kb_value);
309 return 0;
310 }
311
312 case KDSKBENT:
313 {
314 const struct kbentry * a = (struct kbentry *)arg;
315 ushort *key_map;
316 u_char s;
317 u_short v;
318
319 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbentry));
320 if (i)
321 return i;
322 if ((i = get_fs_byte((char *) &a->kb_index)) >= NR_KEYS)
323 return -EINVAL;
324 if ((s = get_fs_byte((char *) &a->kb_table)) >= MAX_NR_KEYMAPS)
325 return -EINVAL;
326 v = get_fs_word(&a->kb_value);
327 if (!i && v == K_NOSUCHMAP) {
328
329 key_map = key_maps[s];
330 if (key_map) {
331 key_maps[s] = 0;
332 if (key_map[0] == U(K_ALLOCATED)) {
333 kfree_s(key_map, sizeof(plain_map));
334 keymap_count--;
335 }
336 }
337 return 0;
338 }
339
340 if (KTYP(v) < NR_TYPES) {
341 if (KVAL(v) > max_vals[KTYP(v)])
342 return -EINVAL;
343 } else
344 if (kbd->kbdmode != VC_UNICODE)
345 return -EINVAL;
346
347
348 if (!i)
349 return 0;
350
351 if (!(key_map = key_maps[s])) {
352 if (keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
353 return -EPERM;
354
355 key_map = (ushort *) kmalloc(sizeof(plain_map),
356 GFP_KERNEL);
357 if (!key_map)
358 return -ENOMEM;
359 key_maps[s] = key_map;
360 key_map[0] = U(K_ALLOCATED);
361 for (s = 1; s < NR_KEYS; s++)
362 key_map[s] = U(K_HOLE);
363 keymap_count++;
364 }
365
366
367
368
369 if (((key_map[i] == U(K_SAK)) || (v == K_SAK)) &&
370 !suser())
371 return -EPERM;
372 key_map[i] = U(v);
373 return 0;
374 }
375
376 case KDGKBSENT:
377 {
378 struct kbsentry *a = (struct kbsentry *)arg;
379 char *p;
380 u_char *q;
381 int sz;
382
383 i = verify_area(VERIFY_WRITE, (void *)a, sizeof(struct kbsentry));
384 if (i)
385 return i;
386 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC || i < 0)
387 return -EINVAL;
388 sz = sizeof(a->kb_string) - 1;
389
390 q = a->kb_string;
391 p = func_table[i];
392 if(p)
393 for ( ; *p && sz; p++, sz--)
394 put_fs_byte(*p, q++);
395 put_fs_byte(0, q);
396 return ((p && *p) ? -EOVERFLOW : 0);
397 }
398
399 case KDSKBSENT:
400 {
401 struct kbsentry * const a = (struct kbsentry *)arg;
402 int delta;
403 char *first_free, *fj, *fnw;
404 int j, k, sz;
405 u_char *p;
406 char *q;
407
408 i = verify_area(VERIFY_READ, (void *)a, sizeof(struct kbsentry));
409 if (i)
410 return i;
411 if ((i = get_fs_byte(&a->kb_func)) >= MAX_NR_FUNC)
412 return -EINVAL;
413 q = func_table[i];
414
415 first_free = funcbufptr + (funcbufsize - funcbufleft);
416 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
417 if (j < MAX_NR_FUNC)
418 fj = func_table[j];
419 else
420 fj = first_free;
421
422 delta = (q ? -strlen(q) : 1);
423 sz = sizeof(a->kb_string);
424
425 for (p = a->kb_string; get_fs_byte(p) && sz; p++,sz--)
426 delta++;
427 if (!sz)
428 return -EOVERFLOW;
429 if (delta <= funcbufleft) {
430 if (j < MAX_NR_FUNC) {
431 memmove(fj + delta, fj, first_free - fj);
432 for (k = j; k < MAX_NR_FUNC; k++)
433 if (func_table[k])
434 func_table[k] += delta;
435 }
436 if (!q)
437 func_table[i] = fj;
438 funcbufleft -= delta;
439 } else {
440 sz = 256;
441 while (sz < funcbufsize - funcbufleft + delta)
442 sz <<= 1;
443 fnw = (char *) kmalloc(sz, GFP_KERNEL);
444 if(!fnw)
445 return -ENOMEM;
446
447 if (!q)
448 func_table[i] = fj;
449 if (fj > funcbufptr)
450 memmove(fnw, funcbufptr, fj - funcbufptr);
451 for (k = 0; k < j; k++)
452 if (func_table[k])
453 func_table[k] = fnw + (func_table[k] - funcbufptr);
454
455 if (first_free > fj) {
456 memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
457 for (k = j; k < MAX_NR_FUNC; k++)
458 if (func_table[k])
459 func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
460 }
461 if (funcbufptr != func_buf)
462 kfree_s(funcbufptr, funcbufsize);
463 funcbufptr = fnw;
464 funcbufleft = funcbufleft - delta + sz - funcbufsize;
465 funcbufsize = sz;
466 }
467 for (p = a->kb_string, q = func_table[i]; ; p++, q++)
468 if (!(*q = get_fs_byte(p)))
469 break;
470 return 0;
471 }
472
473 case KDGKBDIACR:
474 {
475 struct kbdiacrs *a = (struct kbdiacrs *)arg;
476
477 i = verify_area(VERIFY_WRITE, (void *) a, sizeof(struct kbdiacrs));
478 if (i)
479 return i;
480 put_fs_long(accent_table_size, &a->kb_cnt);
481 memcpy_tofs(a->kbdiacr, accent_table,
482 accent_table_size*sizeof(struct kbdiacr));
483 return 0;
484 }
485
486 case KDSKBDIACR:
487 {
488 struct kbdiacrs *a = (struct kbdiacrs *)arg;
489 unsigned int ct;
490
491 i = verify_area(VERIFY_READ, (void *) a, sizeof(struct kbdiacrs));
492 if (i)
493 return i;
494 ct = get_fs_long(&a->kb_cnt);
495 if (ct >= MAX_DIACR)
496 return -EINVAL;
497 accent_table_size = ct;
498 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
499 return 0;
500 }
501
502
503
504 case KDGKBLED:
505 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
506 if (i)
507 return i;
508 put_fs_byte(kbd->ledflagstate |
509 (kbd->default_ledflagstate << 4), (char *) arg);
510 return 0;
511
512 case KDSKBLED:
513 if (arg & ~0x77)
514 return -EINVAL;
515 kbd->ledflagstate = (arg & 7);
516 kbd->default_ledflagstate = ((arg >> 4) & 7);
517 set_leds();
518 return 0;
519
520
521
522 case KDGETLED:
523 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned char));
524 if (i)
525 return i;
526 put_fs_byte(getledstate(), (char *) arg);
527 return 0;
528
529 case KDSETLED:
530 setledstate(kbd, arg);
531 return 0;
532
533 case VT_SETMODE:
534 {
535 struct vt_mode *vtmode = (struct vt_mode *)arg;
536 char mode;
537
538 i = verify_area(VERIFY_WRITE, (void *)vtmode, sizeof(struct vt_mode));
539 if (i)
540 return i;
541 mode = get_fs_byte(&vtmode->mode);
542 if (mode != VT_AUTO && mode != VT_PROCESS)
543 return -EINVAL;
544 vt_cons[console]->vt_mode.mode = mode;
545 vt_cons[console]->vt_mode.waitv = get_fs_byte(&vtmode->waitv);
546 vt_cons[console]->vt_mode.relsig = get_fs_word(&vtmode->relsig);
547 vt_cons[console]->vt_mode.acqsig = get_fs_word(&vtmode->acqsig);
548
549 vt_cons[console]->vt_mode.frsig = 0;
550 vt_cons[console]->vt_pid = current->pid;
551 vt_cons[console]->vt_newvt = 0;
552 return 0;
553 }
554
555 case VT_GETMODE:
556 {
557 struct vt_mode *vtmode = (struct vt_mode *)arg;
558
559 i = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct vt_mode));
560 if (i)
561 return i;
562 put_fs_byte(vt_cons[console]->vt_mode.mode, &vtmode->mode);
563 put_fs_byte(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
564 put_fs_word(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
565 put_fs_word(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
566 put_fs_word(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
567 return 0;
568 }
569
570
571
572
573
574
575 case VT_GETSTATE:
576 {
577 struct vt_stat *vtstat = (struct vt_stat *)arg;
578 unsigned short state, mask;
579
580 i = verify_area(VERIFY_WRITE,(void *)vtstat, sizeof(struct vt_stat));
581 if (i)
582 return i;
583 put_fs_word(fg_console + 1, &vtstat->v_active);
584 state = 1;
585 for (i = 0, mask = 2; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
586 if (console_driver.table[i] &&
587 console_driver.table[i]->count > 0)
588 state |= mask;
589 put_fs_word(state, &vtstat->v_state);
590 return 0;
591 }
592
593
594
595
596 case VT_OPENQRY:
597 i = verify_area(VERIFY_WRITE, (void *) arg, sizeof(long));
598 if (i)
599 return i;
600 for (i = 0; i < MAX_NR_CONSOLES; ++i)
601 if (! VT_IS_IN_USE(i))
602 break;
603 put_fs_long(i < MAX_NR_CONSOLES ? (i+1) : -1,
604 (unsigned long *)arg);
605 return 0;
606
607
608
609
610
611
612 case VT_ACTIVATE:
613 if (arg == 0 || arg > MAX_NR_CONSOLES)
614 return -ENXIO;
615 arg--;
616 i = vc_allocate(arg);
617 if (i)
618 return i;
619 change_console(arg);
620 return 0;
621
622
623
624
625 case VT_WAITACTIVE:
626 if (arg == 0 || arg > MAX_NR_CONSOLES)
627 return -ENXIO;
628 arg--;
629 while (fg_console != arg)
630 {
631 if (vt_waitactive() < 0)
632 return -EINTR;
633 }
634 return 0;
635
636
637
638
639
640
641
642
643
644
645
646 case VT_RELDISP:
647 if (vt_cons[console]->vt_mode.mode != VT_PROCESS)
648 return -EINVAL;
649
650
651
652
653 if (vt_cons[console]->vt_newvt >= 0)
654 {
655 if (arg == 0)
656
657
658
659
660 vt_cons[console]->vt_newvt = -1;
661
662 else
663 {
664
665
666
667
668 int newvt = vt_cons[console]->vt_newvt;
669 vt_cons[console]->vt_newvt = -1;
670 i = vc_allocate(newvt);
671 if (i)
672 return i;
673 complete_change_console(newvt);
674 }
675 }
676
677
678
679
680 else
681 {
682
683
684
685 if (arg != VT_ACKACQ)
686 return -EINVAL;
687 }
688
689 return 0;
690
691
692
693
694 case VT_DISALLOCATE:
695 if (arg > MAX_NR_CONSOLES)
696 return -ENXIO;
697 if (arg == 0) {
698
699 for (i=1; i<MAX_NR_CONSOLES; i++)
700 if (! VT_IS_IN_USE(i)) {
701 if (i == fg_console)
702 change_console(0);
703 vc_disallocate(i);
704 }
705 } else {
706
707 arg--;
708 if (VT_IS_IN_USE(arg))
709 return -EBUSY;
710 if (arg) {
711 if (arg == fg_console)
712 change_console(0);
713 vc_disallocate(arg);
714 }
715 }
716 return 0;
717
718 case VT_RESIZE:
719 {
720 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
721 ushort ll,cc;
722 i = verify_area(VERIFY_READ, (void *)vtsizes, sizeof(struct vt_sizes));
723 if (i)
724 return i;
725 ll = get_fs_word(&vtsizes->v_rows);
726 cc = get_fs_word(&vtsizes->v_cols);
727 return vc_resize(ll, cc);
728 }
729
730 case PIO_FONT:
731 return con_set_font((char *)arg);
732
733
734 case GIO_FONT:
735 return con_get_font((char *)arg);
736
737
738 case PIO_SCRNMAP:
739 return con_set_trans((char *)arg);
740
741
742 case GIO_SCRNMAP:
743 return con_get_trans((char *)arg);
744
745
746 default:
747 return -ENOIOCTLCMD;
748 }
749 }