|
|
1.1 root 1: /*
2: * kernel/chr_drv/vt.c
3: *
4: * (C) 1992 obz under the linux copyright
5: */
6:
7: #include <errno.h>
8:
9: #include <sys/types.h>
10: #include <sys/kd.h>
11: #include <sys/vt.h>
12:
13: #include <asm/io.h>
14: #include <asm/segment.h>
15:
16: #include <linux/sched.h>
17: #include <linux/tty.h>
1.1.1.2 ! root 18: #include <linux/timer.h>
1.1 root 19: #include <linux/kernel.h>
20:
21: #include "vt_kern.h"
22:
23: /*
24: * console (vt and kd) routines, as defined by usl svr4 manual
25: */
26:
1.1.1.2 ! root 27: struct vt_cons vt_cons[NR_CONSOLES];
1.1 root 28:
29: extern unsigned char kleds;
30: extern unsigned char kraw;
31: extern unsigned char ke0;
32:
33: extern int sys_ioperm(unsigned long from, unsigned long num, int on);
34: extern void set_leds(void);
35:
36: /*
37: * these are the valid i/o ports we're allowed to change. they map all the
38: * video ports
39: */
40: #define GPFIRST 0x3b4
41: #define GPLAST 0x3df
42: #define GPNUM (GPLAST - GPFIRST + 1)
43:
44: /*
45: * turns on sound of some freq. 0 turns it off.
46: * stolen from console.c, so i'm not sure if its the correct interpretation
47: */
48: static int
49: kiocsound(unsigned int freq)
50: {
51: if (freq == 0) {
52: /* disable counter 2 */
53: outb(inb_p(0x61)&0xFC, 0x61);
54: }
55: else {
56: /* enable counter 2 */
57: outb_p(inb_p(0x61)|3, 0x61);
58: /* set command for counter 2, 2 byte write */
59: outb_p(0xB6, 0x43);
60: /* select desired HZ */
61: outb_p(freq & 0xff, 0x42);
62: outb((freq >> 8) & 0xff, 0x42);
63: }
64: return 0;
65: }
66:
67: /*
68: * all the vt ioctls affect only consoles, so we reject all other ttys.
69: * we also have the capability to modify any console, not just the fg_console.
70: */
71: int
72: vt_ioctl(struct tty_struct *tty, int dev, int cmd, int arg)
73: {
74: int console = dev ? dev - 1 : fg_console;
75: unsigned char ucval;
76:
77: if (!IS_A_CONSOLE(dev) || console < 0 || console >= NR_CONSOLES)
78: return -EINVAL;
79:
80: switch (cmd) {
81: case KIOCSOUND:
82: return kiocsound((unsigned int)arg);
83:
84: case KDGKBTYPE:
85: /*
86: * this is naive.
87: */
88: verify_area((void *) arg, sizeof(unsigned char));
89: put_fs_byte(KB_101, (unsigned char *) arg);
90: return 0;
91:
92: case KDADDIO:
93: case KDDELIO:
94: /*
95: * KDADDIO and KDDELIO may be able to add ports beyond what
96: * we reject here, but to be safe...
97: */
98: if (arg < GPFIRST || arg > GPLAST)
99: return -EINVAL;
100: return sys_ioperm(arg, 1, (cmd == KDADDIO)) ? -ENXIO : 0;
101:
102: case KDENABIO:
103: case KDDISABIO:
104: return sys_ioperm(GPFIRST, GPNUM,
105: (cmd == KDENABIO)) ? -ENXIO : 0;
106:
107: case KDSETMODE:
108: /*
109: * currently, setting the mode from KD_TEXT to KD_GRAPHICS
110: * doesn't do a whole lot. i'm not sure if it should do any
111: * restoration of modes or what...
112: */
113: switch (arg) {
114: case KD_GRAPHICS:
115: break;
116: case KD_TEXT0:
117: case KD_TEXT1:
118: arg = KD_TEXT;
119: case KD_TEXT:
120: break;
121: default:
122: return -EINVAL;
123: }
1.1.1.2 ! root 124: if (vt_cons[console].vt_mode == (unsigned char) arg)
! 125: return 0;
! 126: vt_cons[console].vt_mode = (unsigned char) arg;
! 127: if (console != fg_console)
! 128: return 0;
! 129: if (arg == KD_TEXT)
! 130: unblank_screen();
! 131: else {
! 132: timer_active &= 1<<BLANK_TIMER;
! 133: blank_screen();
! 134: }
1.1 root 135: return 0;
136: case KDGETMODE:
137: verify_area((void *) arg, sizeof(unsigned long));
138: put_fs_long(vt_cons[console].vt_mode, (unsigned long *) arg);
139: return 0;
140:
141: case KDMAPDISP:
142: case KDUNMAPDISP:
143: /*
144: * these work like a combination of mmap and KDENABIO.
145: * this could be easily finished.
146: */
147: return -EINVAL;
148:
149: case KDSKBMODE:
150: if (arg == K_RAW) {
151: if (console == fg_console) {
152: kraw = 1;
153: ke0 = 0;
154: } else {
155: vt_cons[console].vc_kbdraw = 1;
156: vt_cons[console].vc_kbde0 = 0;
157: }
158: }
159: else if (arg == K_XLATE) {
160: if (console == fg_console)
161: kraw = 0;
162: else
163: vt_cons[console].vc_kbdraw = 0;
164: }
165: else
166: return -EINVAL;
1.1.1.2 ! root 167: flush_input(tty);
1.1 root 168: return 0;
169: case KDGKBMODE:
170: verify_area((void *) arg, sizeof(unsigned long));
171: ucval = (console == fg_console) ? kraw :
172: vt_cons[console].vc_kbdraw;
173: put_fs_long(ucval ? K_RAW : K_XLATE, (unsigned long *) arg);
174: return 0;
175:
176: case KDGETLED:
177: verify_area((void *) arg, sizeof(unsigned char));
178: ucval = (console == fg_console) ? kleds :
179: vt_cons[console].vc_kbdleds;
180: put_fs_byte((((ucval & 1) ? LED_SCR : 0) |
181: ((ucval & 2) ? LED_NUM : 0) |
182: ((ucval & 4) ? LED_CAP : 0)),
183: (unsigned char *) arg);
184: return 0;
185: case KDSETLED:
186: if (arg & ~7)
187: return -EINVAL;
188: ucval = (((arg & LED_SCR) ? 1 : 0) |
189: ((arg & LED_NUM) ? 2 : 0) |
190: ((arg & LED_CAP) ? 4 : 0));
191: if (console == fg_console) {
192: kleds = ucval;
193: set_leds();
194: }
195: else
196: vt_cons[console].vc_kbdleds = ucval;
197: return 0;
198:
199: default:
200: return -EINVAL;
201: }
202: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.