|
|
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>
18: #include <linux/kernel.h>
19:
20: #include "vt_kern.h"
21:
22: /*
23: * console (vt and kd) routines, as defined by usl svr4 manual
24: */
25:
26: struct vt_cons vt_cons[MAX_CONSOLES];
27:
28: extern int NR_CONSOLES;
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: }
124: vt_cons[console].vt_mode = arg;
125: return 0;
126: case KDGETMODE:
127: verify_area((void *) arg, sizeof(unsigned long));
128: put_fs_long(vt_cons[console].vt_mode, (unsigned long *) arg);
129: return 0;
130:
131: case KDMAPDISP:
132: case KDUNMAPDISP:
133: /*
134: * these work like a combination of mmap and KDENABIO.
135: * this could be easily finished.
136: */
137: return -EINVAL;
138:
139: case KDSKBMODE:
140: if (arg == K_RAW) {
141: if (console == fg_console) {
142: kraw = 1;
143: ke0 = 0;
144: } else {
145: vt_cons[console].vc_kbdraw = 1;
146: vt_cons[console].vc_kbde0 = 0;
147: }
148: }
149: else if (arg == K_XLATE) {
150: if (console == fg_console)
151: kraw = 0;
152: else
153: vt_cons[console].vc_kbdraw = 0;
154: }
155: else
156: return -EINVAL;
157: flush(tty->read_q);
158: flush(tty->secondary);
159: return 0;
160: case KDGKBMODE:
161: verify_area((void *) arg, sizeof(unsigned long));
162: ucval = (console == fg_console) ? kraw :
163: vt_cons[console].vc_kbdraw;
164: put_fs_long(ucval ? K_RAW : K_XLATE, (unsigned long *) arg);
165: return 0;
166:
167: case KDGETLED:
168: verify_area((void *) arg, sizeof(unsigned char));
169: ucval = (console == fg_console) ? kleds :
170: vt_cons[console].vc_kbdleds;
171: put_fs_byte((((ucval & 1) ? LED_SCR : 0) |
172: ((ucval & 2) ? LED_NUM : 0) |
173: ((ucval & 4) ? LED_CAP : 0)),
174: (unsigned char *) arg);
175: return 0;
176: case KDSETLED:
177: if (arg & ~7)
178: return -EINVAL;
179: ucval = (((arg & LED_SCR) ? 1 : 0) |
180: ((arg & LED_NUM) ? 2 : 0) |
181: ((arg & LED_CAP) ? 4 : 0));
182: if (console == fg_console) {
183: kleds = ucval;
184: set_leds();
185: }
186: else
187: vt_cons[console].vc_kbdleds = ucval;
188: return 0;
189:
190: default:
191: return -EINVAL;
192: }
193: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.