Import 1.3.16
[davej-history.git] / drivers / char / vt.c
blob5a50ef1655f539d7d185fdabfd860ebd32f46a92
1 /*
2 * linux/drivers/char/vt.c
4 * Copyright (C) 1992 obz under the linux copyright
6 * Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
7 * Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
8 */
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 #include <linux/major.h>
21 #include <linux/fs.h>
23 #include <asm/io.h>
24 #include <asm/segment.h>
26 #include"kbd_kern.h"
27 #include"vt_kern.h"
28 #include"diacr.h"
29 #include"selection.h"
31 externstruct tty_driver console_driver;
33 #define VT_IS_IN_USE(i) (console_driver.table[i] && console_driver.table[i]->count)
34 #define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || i == sel_cons)
37 * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
38 * experimentation and study of X386 SYSV handling.
40 * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
41 * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
42 * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
43 * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
44 * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
45 * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
46 * to the current console is done by the main ioctl code.
49 struct vt_struct *vt_cons[MAX_NR_CONSOLES];
51 asmlinkage intsys_ioperm(unsigned long from,unsigned long num,int on);
53 externintgetkeycode(unsigned int scancode);
54 externintsetkeycode(unsigned int scancode,unsigned int keycode);
55 externvoidcompute_shiftstate(void);
56 externvoidchange_console(unsigned int new_console);
57 externvoidcomplete_change_console(unsigned int new_console);
58 externintvt_waitactive(void);
59 externvoiddo_blank_screen(int nopowersave);
61 externunsigned int keymap_count;
64 * routines to load custom translation table, EGA/VGA font and
65 * VGA colour palette from console.c
67 externintcon_set_trans_old(unsigned char* table);
68 externintcon_get_trans_old(unsigned char* table);
69 externintcon_set_trans_new(unsigned short* table);
70 externintcon_get_trans_new(unsigned short* table);
71 externvoidcon_clear_unimap(struct unimapinit *ui);
72 externintcon_set_unimap(ushort ct,struct unipair *list);
73 externintcon_get_unimap(ushort ct, ushort *uct,struct unipair *list);
74 externintcon_set_font(char* fontmap,int ch512);
75 externintcon_get_font(char* fontmap);
76 externintcon_set_cmap(unsigned char*cmap);
77 externintcon_get_cmap(unsigned char*cmap);
78 externvoidreset_palette(int currcons);
79 externintcon_adjust_height(unsigned long fontheight);
81 externint video_mode_512ch;
82 externunsigned long video_font_height;
83 externunsigned long video_scan_lines;
86 * these are the valid i/o ports we're allowed to change. they map all the
87 * video ports
89 #define GPFIRST 0x3b4
90 #define GPLAST 0x3df
91 #define GPNUM (GPLAST - GPFIRST + 1)
94 * This function is called when the size of the physical screen has been
95 * changed. If either the row or col argument is nonzero, set the appropriate
96 * entry in each winsize structure for all the virtual consoles, then
97 * send SIGWINCH to all processes with a virtual console as controlling
98 * tty.
101 static int
102 kd_size_changed(int row,int col)
104 struct task_struct *p;
105 int i;
107 if( !row && !col )return0;
109 for( i =0; i < MAX_NR_CONSOLES ; i++ )
111 if( console_driver.table[i] )
113 if( row ) console_driver.table[i]->winsize.ws_row = row;
114 if( col ) console_driver.table[i]->winsize.ws_col = col;
118 for_each_task(p)
120 if( p->tty &&MAJOR(p->tty->device) == TTY_MAJOR &&
121 MINOR(p->tty->device) <= MAX_NR_CONSOLES &&MINOR(p->tty->device) )
123 send_sig(SIGWINCH, p,1);
127 return0;
131 * Generates sound of some count for some number of clock ticks
132 * [count = 1193180 / frequency]
134 * If freq is 0, will turn off sound, else will turn it on for that time.
135 * If msec is 0, will return immediately, else will sleep for msec time, then
136 * turn sound off.
138 * We use the BEEP_TIMER vector since we're using the same method to
139 * generate sound, and we'll overwrite any beep in progress. That may
140 * be something to fix later, if we like.
142 * We also return immediately, which is what was implied within the X
143 * comments - KDMKTONE doesn't put the process to sleep.
145 static void
146 kd_nosound(unsigned long ignored)
148 /* disable counter 2 */
149 outb(inb_p(0x61)&0xFC,0x61);
150 return;
153 void
154 kd_mksound(unsigned int count,unsigned int ticks)
156 static struct timer_list sound_timer = { NULL, NULL,0,0, kd_nosound };
158 cli();
159 del_timer(&sound_timer);
160 if(count) {
161 /* enable counter 2 */
162 outb_p(inb_p(0x61)|3,0x61);
163 /* set command for counter 2, 2 byte write */
164 outb_p(0xB6,0x43);
165 /* select desired HZ */
166 outb_p(count &0xff,0x42);
167 outb((count >>8) &0xff,0x42);
169 if(ticks) {
170 sound_timer.expires = jiffies+ticks;
171 add_timer(&sound_timer);
173 }else
174 kd_nosound(0);
175 sti();
176 return;
180 * We handle the console-specific ioctl's here. We allow the
181 * capability to modify any console, not just the fg_console.
183 intvt_ioctl(struct tty_struct *tty,struct file * file,
184 unsigned int cmd,unsigned long arg)
186 int i, perm;
187 unsigned int console;
188 unsigned char ucval;
189 struct kbd_struct * kbd;
190 struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
192 console = vt->vc_num;
194 if(!vc_cons_allocated(console))/* impossible? */
195 return-ENOIOCTLCMD;
198 * To have permissions to do most of the vt ioctls, we either have
199 * to be the owner of the tty, or super-user.
201 perm =0;
202 if(current->tty == tty ||suser())
203 perm =1;
205 kbd = kbd_table + console;
206 switch(cmd) {
207 case KIOCSOUND:
208 if(!perm)
209 return-EPERM;
210 kd_mksound((unsigned int)arg,0);
211 return0;
213 case KDMKTONE:
214 if(!perm)
215 return-EPERM;
217 unsigned int ticks = HZ * ((arg >>16) &0xffff) /1000;
220 * Generate the tone for the appropriate number of ticks.
221 * If the time is zero, turn off sound ourselves.
223 kd_mksound(arg &0xffff, ticks);
224 if(ticks ==0)
225 kd_nosound(0);
226 return0;
229 case KDGKBTYPE:
231 * this is naive.
233 i =verify_area(VERIFY_WRITE, (void*) arg,sizeof(unsigned char));
234 if(!i)
235 put_user(KB_101, (char*) arg);
236 return i;
238 case KDADDIO:
239 case KDDELIO:
241 * KDADDIO and KDDELIO may be able to add ports beyond what
242 * we reject here, but to be safe...
244 if(arg < GPFIRST || arg > GPLAST)
245 return-EINVAL;
246 returnsys_ioperm(arg,1, (cmd == KDADDIO)) ? -ENXIO :0;
248 case KDENABIO:
249 case KDDISABIO:
250 returnsys_ioperm(GPFIRST, GPNUM,
251 (cmd == KDENABIO)) ? -ENXIO :0;
253 case KDSETMODE:
255 * currently, setting the mode from KD_TEXT to KD_GRAPHICS
256 * doesn't do a whole lot. i'm not sure if it should do any
257 * restoration of modes or what...
259 if(!perm)
260 return-EPERM;
261 switch(arg) {
262 case KD_GRAPHICS:
263 break;
264 case KD_TEXT0:
265 case KD_TEXT1:
266 arg = KD_TEXT;
267 case KD_TEXT:
268 break;
269 default:
270 return-EINVAL;
272 if(vt_cons[console]->vc_mode == (unsigned char) arg)
273 return0;
274 vt_cons[console]->vc_mode = (unsigned char) arg;
275 if(console != fg_console)
276 return0;
278 * explicitly blank/unblank the screen if switching modes
280 if(arg == KD_TEXT)
281 do_unblank_screen();
282 else
283 do_blank_screen(1);
284 return0;
286 case KDGETMODE:
287 i =verify_area(VERIFY_WRITE, (void*) arg,sizeof(int));
288 if(!i)
289 put_user(vt_cons[console]->vc_mode, (int*) arg);
290 return i;
292 case KDMAPDISP:
293 case KDUNMAPDISP:
295 * these work like a combination of mmap and KDENABIO.
296 * this could be easily finished.
298 return-EINVAL;
300 case KDSKBMODE:
301 if(!perm)
302 return-EPERM;
303 switch(arg) {
304 case K_RAW:
305 kbd->kbdmode = VC_RAW;
306 break;
307 case K_MEDIUMRAW:
308 kbd->kbdmode = VC_MEDIUMRAW;
309 break;
310 case K_XLATE:
311 kbd->kbdmode = VC_XLATE;
312 compute_shiftstate();
313 break;
314 case K_UNICODE:
315 kbd->kbdmode = VC_UNICODE;
316 compute_shiftstate();
317 break;
318 default:
319 return-EINVAL;
321 if(tty->ldisc.flush_buffer)
322 tty->ldisc.flush_buffer(tty);
323 return0;
325 case KDGKBMODE:
326 i =verify_area(VERIFY_WRITE, (void*) arg,sizeof(int));
327 if(!i) {
328 ucval = ((kbd->kbdmode == VC_RAW) ? K_RAW :
329 (kbd->kbdmode == VC_MEDIUMRAW) ? K_MEDIUMRAW :
330 (kbd->kbdmode == VC_UNICODE) ? K_UNICODE :
331 K_XLATE);
332 put_user(ucval, (int*) arg);
334 return i;
336 /* this could be folded into KDSKBMODE, but for compatibility
337 reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
338 case KDSKBMETA:
339 switch(arg) {
340 case K_METABIT:
341 clr_vc_kbd_mode(kbd, VC_META);
342 break;
343 case K_ESCPREFIX:
344 set_vc_kbd_mode(kbd, VC_META);
345 break;
346 default:
347 return-EINVAL;
349 return0;
351 case KDGKBMETA:
352 i =verify_area(VERIFY_WRITE, (void*) arg,sizeof(int));
353 if(!i) {
354 ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX :
355 K_METABIT);
356 put_user(ucval, (int*) arg);
358 return i;
360 case KDGETKEYCODE:
362 struct kbkeycode *const a = (struct kbkeycode *)arg;
363 unsigned int sc;
364 int kc;
366 i =verify_area(VERIFY_WRITE, (void*)a,sizeof(struct kbkeycode));
367 if(i)
368 return i;
369 sc =get_user(&a->scancode);
370 kc =getkeycode(sc);
371 if(kc <0)
372 return kc;
373 put_user(kc, &a->keycode);
374 return0;
377 case KDSETKEYCODE:
379 struct kbkeycode *const a = (struct kbkeycode *)arg;
380 unsigned int sc, kc;
382 if(!perm)
383 return-EPERM;
384 i =verify_area(VERIFY_READ, (void*)a,sizeof(struct kbkeycode));
385 if(i)
386 return i;
387 sc =get_user(&a->scancode);
388 kc =get_user(&a->keycode);
389 returnsetkeycode(sc, kc);
392 case KDGKBENT:
394 struct kbentry *const a = (struct kbentry *)arg;
395 ushort *key_map, val;
396 u_char s;
398 i =verify_area(VERIFY_WRITE, (void*)a,sizeof(struct kbentry));
399 if(i)
400 return i;
401 if((i =get_user(&a->kb_index)) >= NR_KEYS)
402 return-EINVAL;
403 if((s =get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
404 return-EINVAL;
405 key_map = key_maps[s];
406 if(key_map) {
407 val =U(key_map[i]);
408 if(kbd->kbdmode != VC_UNICODE &&KTYP(val) >= NR_TYPES)
409 val = K_HOLE;
410 }else
411 val = (i ? K_HOLE : K_NOSUCHMAP);
412 put_user(val, &a->kb_value);
413 return0;
416 case KDSKBENT:
418 const struct kbentry * a = (struct kbentry *)arg;
419 ushort *key_map;
420 u_char s;
421 u_short v, ov;
423 if(!perm)
424 return-EPERM;
425 i =verify_area(VERIFY_READ, (const void*)a,sizeof(struct kbentry));
426 if(i)
427 return i;
428 if((i =get_user(&a->kb_index)) >= NR_KEYS)
429 return-EINVAL;
430 if((s =get_user(&a->kb_table)) >= MAX_NR_KEYMAPS)
431 return-EINVAL;
432 v =get_user(&a->kb_value);
433 if(!i && v == K_NOSUCHMAP) {
434 /* disallocate map */
435 key_map = key_maps[s];
436 if(s && key_map) {
437 key_maps[s] =0;
438 if(key_map[0] ==U(K_ALLOCATED)) {
439 kfree_s(key_map,sizeof(plain_map));
440 keymap_count--;
443 return0;
446 if(KTYP(v) < NR_TYPES) {
447 if(KVAL(v) > max_vals[KTYP(v)])
448 return-EINVAL;
449 }else
450 if(kbd->kbdmode != VC_UNICODE)
451 return-EINVAL;
453 /* assignment to entry 0 only tests validity of args */
454 if(!i)
455 return0;
457 if(!(key_map = key_maps[s])) {
458 int j;
460 if(keymap_count >= MAX_NR_OF_USER_KEYMAPS && !suser())
461 return-EPERM;
463 key_map = (ushort *)kmalloc(sizeof(plain_map),
464 GFP_KERNEL);
465 if(!key_map)
466 return-ENOMEM;
467 key_maps[s] = key_map;
468 key_map[0] =U(K_ALLOCATED);
469 for(j =1; j < NR_KEYS; j++)
470 key_map[j] =U(K_HOLE);
471 keymap_count++;
473 ov =U(key_map[i]);
474 if(v == ov)
475 return0;/* nothing to do */
477 * Only the Superuser can set or unset the Secure
478 * Attention Key.
480 if(((ov == K_SAK) || (v == K_SAK)) && !suser())
481 return-EPERM;
482 key_map[i] =U(v);
483 if(!s && (KTYP(ov) == KT_SHIFT ||KTYP(v) == KT_SHIFT))
484 compute_shiftstate();
485 return0;
488 case KDGKBSENT:
490 struct kbsentry *a = (struct kbsentry *)arg;
491 char*p;
492 u_char *q;
493 int sz;
495 i =verify_area(VERIFY_WRITE, (void*)a,sizeof(struct kbsentry));
496 if(i)
497 return i;
498 if((i =get_user(&a->kb_func)) >= MAX_NR_FUNC || i <0)
499 return-EINVAL;
500 sz =sizeof(a->kb_string) -1;/* sz should have been
501 a struct member */
502 q = a->kb_string;
503 p = func_table[i];
504 if(p)
505 for( ; *p && sz; p++, sz--)
506 put_user(*p, q++);
507 put_user('\0', q);
508 return((p && *p) ? -EOVERFLOW :0);
511 case KDSKBSENT:
513 struct kbsentry *const a = (struct kbsentry *)arg;
514 int delta;
515 char*first_free, *fj, *fnw;
516 int j, k, sz;
517 u_char *p;
518 char*q;
520 if(!perm)
521 return-EPERM;
522 i =verify_area(VERIFY_READ, (void*)a,sizeof(struct kbsentry));
523 if(i)
524 return i;
525 if((i =get_user(&a->kb_func)) >= MAX_NR_FUNC)
526 return-EINVAL;
527 q = func_table[i];
529 first_free = funcbufptr + (funcbufsize - funcbufleft);
530 for(j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) ;
531 if(j < MAX_NR_FUNC)
532 fj = func_table[j];
533 else
534 fj = first_free;
536 delta = (q ? -strlen(q) :1);
537 sz =sizeof(a->kb_string);/* sz should have been
538 a struct member */
539 for(p = a->kb_string;get_user(p) && sz; p++,sz--)
540 delta++;
541 if(!sz)
542 return-EOVERFLOW;
543 if(delta <= funcbufleft) {/* it fits in current buf */
544 if(j < MAX_NR_FUNC) {
545 memmove(fj + delta, fj, first_free - fj);
546 for(k = j; k < MAX_NR_FUNC; k++)
547 if(func_table[k])
548 func_table[k] += delta;
550 if(!q)
551 func_table[i] = fj;
552 funcbufleft -= delta;
553 }else{/* allocate a larger buffer */
554 sz =256;
555 while(sz < funcbufsize - funcbufleft + delta)
556 sz <<=1;
557 fnw = (char*)kmalloc(sz, GFP_KERNEL);
558 if(!fnw)
559 return-ENOMEM;
561 if(!q)
562 func_table[i] = fj;
563 if(fj > funcbufptr)
564 memmove(fnw, funcbufptr, fj - funcbufptr);
565 for(k =0; k < j; k++)
566 if(func_table[k])
567 func_table[k] = fnw + (func_table[k] - funcbufptr);
569 if(first_free > fj) {
570 memmove(fnw + (fj - funcbufptr) + delta, fj, first_free - fj);
571 for(k = j; k < MAX_NR_FUNC; k++)
572 if(func_table[k])
573 func_table[k] = fnw + (func_table[k] - funcbufptr) + delta;
575 if(funcbufptr != func_buf)
576 kfree_s(funcbufptr, funcbufsize);
577 funcbufptr = fnw;
578 funcbufleft = funcbufleft - delta + sz - funcbufsize;
579 funcbufsize = sz;
581 for(p = a->kb_string, q = func_table[i]; ; p++, q++)
582 if(!(*q =get_user(p)))
583 break;
584 return0;
587 case KDGKBDIACR:
589 struct kbdiacrs *a = (struct kbdiacrs *)arg;
591 i =verify_area(VERIFY_WRITE, (void*) a,sizeof(struct kbdiacrs));
592 if(i)
593 return i;
594 put_user(accent_table_size, &a->kb_cnt);
595 memcpy_tofs(a->kbdiacr, accent_table,
596 accent_table_size*sizeof(struct kbdiacr));
597 return0;
600 case KDSKBDIACR:
602 struct kbdiacrs *a = (struct kbdiacrs *)arg;
603 unsigned int ct;
605 if(!perm)
606 return-EPERM;
607 i =verify_area(VERIFY_READ, (void*) a,sizeof(struct kbdiacrs));
608 if(i)
609 return i;
610 ct =get_user(&a->kb_cnt);
611 if(ct >= MAX_DIACR)
612 return-EINVAL;
613 accent_table_size = ct;
614 memcpy_fromfs(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
615 return0;
618 /* the ioctls below read/set the flags usually shown in the leds */
619 /* don't use them - they will go away without warning */
620 case KDGKBLED:
621 i =verify_area(VERIFY_WRITE, (void*) arg,sizeof(unsigned char));
622 if(i)
623 return i;
624 put_user(kbd->ledflagstate |
625 (kbd->default_ledflagstate <<4), (char*) arg);
626 return0;
628 case KDSKBLED:
629 if(!perm)
630 return-EPERM;
631 if(arg & ~0x77)
632 return-EINVAL;
633 kbd->ledflagstate = (arg &7);
634 kbd->default_ledflagstate = ((arg >>4) &7);
635 set_leds();
636 return0;
638 /* the ioctls below only set the lights, not the functions */
639 /* for those, see KDGKBLED and KDSKBLED above */
640 case KDGETLED:
641 i =verify_area(VERIFY_WRITE, (void*) arg,sizeof(unsigned char));
642 if(i)
643 return i;
644 put_user(getledstate(), (char*) arg);
645 return0;
647 case KDSETLED:
648 if(!perm)
649 return-EPERM;
650 setledstate(kbd, arg);
651 return0;
654 * A process can indicate its willingness to accept signals
655 * generated by pressing an appropriate key combination.
656 * Thus, one can have a daemon that e.g. spawns a new console
657 * upon a keypress and then changes to it.
658 * Probably init should be changed to do this (and have a
659 * field ks (`keyboard signal') in inittab describing the
660 * desired action), so that the number of background daemons
661 * does not increase.
663 case KDSIGACCEPT:
665 externint spawnpid, spawnsig;
666 if(!perm)
667 return-EPERM;
668 if(arg <1|| arg > NSIG || arg == SIGKILL)
669 return-EINVAL;
670 spawnpid = current->pid;
671 spawnsig = arg;
672 return0;
675 case VT_SETMODE:
677 struct vt_mode *vtmode = (struct vt_mode *)arg;
678 char mode;
680 if(!perm)
681 return-EPERM;
682 i =verify_area(VERIFY_WRITE, (void*)vtmode,sizeof(struct vt_mode));
683 if(i)
684 return i;
685 mode =get_user(&vtmode->mode);
686 if(mode != VT_AUTO && mode != VT_PROCESS)
687 return-EINVAL;
688 vt_cons[console]->vt_mode.mode = mode;
689 vt_cons[console]->vt_mode.waitv =get_user(&vtmode->waitv);
690 vt_cons[console]->vt_mode.relsig =get_user(&vtmode->relsig);
691 vt_cons[console]->vt_mode.acqsig =get_user(&vtmode->acqsig);
692 /* the frsig is ignored, so we set it to 0 */
693 vt_cons[console]->vt_mode.frsig =0;
694 vt_cons[console]->vt_pid = current->pid;
695 vt_cons[console]->vt_newvt =0;
696 return0;
699 case VT_GETMODE:
701 struct vt_mode *vtmode = (struct vt_mode *)arg;
703 i =verify_area(VERIFY_WRITE, (void*)arg,sizeof(struct vt_mode));
704 if(i)
705 return i;
706 put_user(vt_cons[console]->vt_mode.mode, &vtmode->mode);
707 put_user(vt_cons[console]->vt_mode.waitv, &vtmode->waitv);
708 put_user(vt_cons[console]->vt_mode.relsig, &vtmode->relsig);
709 put_user(vt_cons[console]->vt_mode.acqsig, &vtmode->acqsig);
710 put_user(vt_cons[console]->vt_mode.frsig, &vtmode->frsig);
711 return0;
715 * Returns global vt state. Note that VT 0 is always open, since
716 * it's an alias for the current VT, and people can't use it here.
717 * We cannot return state for more than 16 VTs, since v_state is short.
719 case VT_GETSTATE:
721 struct vt_stat *vtstat = (struct vt_stat *)arg;
722 unsigned short state, mask;
724 i =verify_area(VERIFY_WRITE,(void*)vtstat,sizeof(struct vt_stat));
725 if(i)
726 return i;
727 put_user(fg_console +1, &vtstat->v_active);
728 state =1;/* /dev/tty0 is always open */
729 for(i =0, mask =2; i < MAX_NR_CONSOLES && mask; ++i, mask <<=1)
730 if(VT_IS_IN_USE(i))
731 state |= mask;
732 put_user(state, &vtstat->v_state);
733 return0;
737 * Returns the first available (non-opened) console.
739 case VT_OPENQRY:
740 i =verify_area(VERIFY_WRITE, (void*) arg,sizeof(int));
741 if(i)
742 return i;
743 for(i =0; i < MAX_NR_CONSOLES; ++i)
744 if(!VT_IS_IN_USE(i))
745 break;
746 put_user(i < MAX_NR_CONSOLES ? (i+1) : -1, (int*) arg);
747 return0;
750 * ioctl(fd, VT_ACTIVATE, num) will cause us to switch to vt # num,
751 * with num >= 1 (switches to vt 0, our console, are not allowed, just
752 * to preserve sanity).
754 case VT_ACTIVATE:
755 if(!perm)
756 return-EPERM;
757 if(arg ==0|| arg > MAX_NR_CONSOLES)
758 return-ENXIO;
759 arg--;
760 i =vc_allocate(arg);
761 if(i)
762 return i;
763 change_console(arg);
764 return0;
767 * wait until the specified VT has been activated
769 case VT_WAITACTIVE:
770 if(!perm)
771 return-EPERM;
772 if(arg ==0|| arg > MAX_NR_CONSOLES)
773 return-ENXIO;
774 arg--;
775 while(fg_console != arg)
777 if(vt_waitactive() <0)
778 return-EINTR;
780 return0;
783 * If a vt is under process control, the kernel will not switch to it
784 * immediately, but postpone the operation until the process calls this
785 * ioctl, allowing the switch to complete.
787 * According to the X sources this is the behavior:
788 * 0: pending switch-from not OK
789 * 1: pending switch-from OK
790 * 2: completed switch-to OK
792 case VT_RELDISP:
793 if(!perm)
794 return-EPERM;
795 if(vt_cons[console]->vt_mode.mode != VT_PROCESS)
796 return-EINVAL;
799 * Switching-from response
801 if(vt_cons[console]->vt_newvt >=0)
803 if(arg ==0)
805 * Switch disallowed, so forget we were trying
806 * to do it.
808 vt_cons[console]->vt_newvt = -1;
810 else
813 * The current vt has been released, so
814 * complete the switch.
816 int newvt = vt_cons[console]->vt_newvt;
817 vt_cons[console]->vt_newvt = -1;
818 i =vc_allocate(newvt);
819 if(i)
820 return i;
821 complete_change_console(newvt);
826 * Switched-to response
828 else
831 * If it's just an ACK, ignore it
833 if(arg != VT_ACKACQ)
834 return-EINVAL;
837 return0;
840 * Disallocate memory associated to VT (but leave VT1)
842 case VT_DISALLOCATE:
843 if(arg > MAX_NR_CONSOLES)
844 return-ENXIO;
845 if(arg ==0) {
846 /* disallocate all unused consoles, but leave 0 */
847 for(i=1; i<MAX_NR_CONSOLES; i++)
848 if(!VT_BUSY(i))
849 vc_disallocate(i);
850 }else{
851 /* disallocate a single console, if possible */
852 arg--;
853 if(VT_BUSY(arg))
854 return-EBUSY;
855 if(arg)/* leave 0 */
856 vc_disallocate(arg);
858 return0;
860 case VT_RESIZE:
862 struct vt_sizes *vtsizes = (struct vt_sizes *) arg;
863 ushort ll,cc;
864 if(!perm)
865 return-EPERM;
866 i =verify_area(VERIFY_READ, (void*)vtsizes,sizeof(struct vt_sizes));
867 if(i)
868 return i;
869 ll =get_user(&vtsizes->v_rows);
870 cc =get_user(&vtsizes->v_cols);
871 i =vc_resize(ll, cc);
872 return i ? i :kd_size_changed(ll, cc);
875 case VT_RESIZEX:
877 struct vt_consize *vtconsize = (struct vt_consize *) arg;
878 ushort ll,cc,vlin,clin,vcol,ccol;
879 if(!perm)
880 return-EPERM;
881 i =verify_area(VERIFY_READ, (void*)vtconsize,sizeof(struct vt_consize));
882 if(i)
883 return i;
884 ll =get_user(&vtconsize->v_rows);
885 cc =get_user(&vtconsize->v_cols);
886 vlin =get_user(&vtconsize->v_vlin);
887 clin =get_user(&vtconsize->v_clin);
888 vcol =get_user(&vtconsize->v_vcol);
889 ccol =get_user(&vtconsize->v_ccol);
890 vlin = vlin ? vlin : video_scan_lines;
891 if( clin )
893 if( ll )
895 if( ll != vlin/clin )
896 return EINVAL;/* Parameters don't add up */
898 else
899 ll = vlin/clin;
901 if( vcol && ccol )
903 if( cc )
905 if( cc != vcol/ccol )
906 return EINVAL;
908 else
909 cc = vcol/ccol;
912 if( clin >32)
913 return EINVAL;
915 if( vlin )
916 video_scan_lines = vlin;
917 if( clin )
918 video_font_height = clin;
920 i =vc_resize(ll, cc);
921 if(i)
922 return i;
924 kd_size_changed(ll, cc);
925 return0;
928 case PIO_FONT:
929 if(!perm)
930 return-EPERM;
931 if(vt_cons[fg_console]->vc_mode != KD_TEXT)
932 return-EINVAL;
933 returncon_set_font((char*)arg,0);
934 /* con_set_font() defined in console.c */
936 case GIO_FONT:
937 if(vt_cons[fg_console]->vc_mode != KD_TEXT ||
938 video_mode_512ch)
939 return-EINVAL;
940 returncon_get_font((char*)arg);
941 /* con_get_font() defined in console.c */
943 case PIO_CMAP:
944 if(!perm)
945 return-EPERM;
946 returncon_set_cmap((char*)arg);
947 /* con_set_cmap() defined in console.c */
949 case GIO_CMAP:
950 returncon_get_cmap((char*)arg);
951 /* con_get_cmap() defined in console.c */
953 case PIO_FONTX:
955 struct consolefontdesc cfdarg;
957 if(!perm)
958 return-EPERM;
959 if(vt_cons[fg_console]->vc_mode != KD_TEXT)
960 return-EINVAL;
961 i =verify_area(VERIFY_READ, (void*)arg,
962 sizeof(struct consolefontdesc));
963 if(i)return i;
964 memcpy_fromfs(&cfdarg, (void*)arg,
965 sizeof(struct consolefontdesc));
967 if( cfdarg.charcount ==256||
968 cfdarg.charcount ==512) {
969 i =con_set_font(cfdarg.chardata,
970 cfdarg.charcount ==512);
971 if(i)
972 return i;
973 i =con_adjust_height(cfdarg.charheight);
974 return(i <=0) ? i :kd_size_changed(i,0);
975 }else
976 return-EINVAL;
979 case GIO_FONTX:
981 struct consolefontdesc cfdarg;
982 int nchar;
984 if(vt_cons[fg_console]->vc_mode != KD_TEXT)
985 return-EINVAL;
986 i =verify_area(VERIFY_WRITE, (void*)arg,
987 sizeof(struct consolefontdesc));
988 if(i)return i;
989 memcpy_fromfs(&cfdarg, (void*) arg,
990 sizeof(struct consolefontdesc));
991 i = cfdarg.charcount;
992 cfdarg.charcount = nchar = video_mode_512ch ?512:256;
993 cfdarg.charheight = video_font_height;
994 memcpy_tofs((void*) arg, &cfdarg,
995 sizeof(struct consolefontdesc));
996 if( cfdarg.chardata )
998 if( i < nchar )
999 return-ENOMEM;
1000 returncon_get_font(cfdarg.chardata);
1001 }else
1002 return0;
1005 case PIO_SCRNMAP:
1006 if(!perm)
1007 return-EPERM;
1008 returncon_set_trans_old((unsigned char*)arg);
1010 case GIO_SCRNMAP:
1011 returncon_get_trans_old((unsigned char*)arg);
1013 case PIO_UNISCRNMAP:
1014 if(!perm)
1015 return-EPERM;
1016 returncon_set_trans_new((unsigned short*)arg);
1018 case GIO_UNISCRNMAP:
1019 returncon_get_trans_new((unsigned short*)arg);
1021 case PIO_UNIMAPCLR:
1022 {struct unimapinit ui;
1023 if(!perm)
1024 return-EPERM;
1025 i =verify_area(VERIFY_READ, (void*)arg,sizeof(struct unimapinit));
1026 if(i)
1027 return i;
1028 memcpy_fromfs(&ui, (void*)arg,sizeof(struct unimapinit));
1029 con_clear_unimap(&ui);
1030 return0;
1033 case PIO_UNIMAP:
1034 {struct unimapdesc *ud;
1035 u_short ct;
1036 struct unipair *list;
1038 if(!perm)
1039 return-EPERM;
1040 i =verify_area(VERIFY_READ, (void*)arg,sizeof(struct unimapdesc));
1041 if(i ==0) {
1042 ud = (struct unimapdesc *) arg;
1043 ct =get_user(&ud->entry_ct);
1044 list =get_user(&ud->entries);
1045 i =verify_area(VERIFY_READ, (void*) list,
1046 ct*sizeof(struct unipair));
1048 if(i)
1049 return i;
1050 returncon_set_unimap(ct, list);
1053 case GIO_UNIMAP:
1054 {struct unimapdesc *ud;
1055 u_short ct;
1056 struct unipair *list;
1058 i =verify_area(VERIFY_WRITE, (void*)arg,sizeof(struct unimapdesc));
1059 if(i ==0) {
1060 ud = (struct unimapdesc *) arg;
1061 ct =get_user(&ud->entry_ct);
1062 list =get_user(&ud->entries);
1063 if(ct)
1064 i =verify_area(VERIFY_WRITE, (void*) list,
1065 ct*sizeof(struct unipair));
1067 if(i)
1068 return i;
1069 returncon_get_unimap(ct, &(ud->entry_ct), list);
1072 default:
1073 return-ENOIOCTLCMD;
close