source: rtems/c/src/lib/libbsp/i386/pc386/console/vt.c @ d57c04e

4.104.114.84.95
Last change on this file since d57c04e was d57c04e, checked in by Joel Sherrill <joel.sherrill@…>, on 12/05/00 at 16:49:23

2000-12-05 Eric Valette <valette@…>

  • console/inch.c, console/keyboard.c, console/pc_keyb.c, console/vt.c, include/bsp.h: Correct incorrect interrupt level handling in new keyboard management code. Correct BSP_poll_char initialization routine.
  • start/start.S, startup/bspstart.c: Correct when the video is initialized.
  • timer/timer.c (Calibrate_1ms_loop): Address problem where this did not work correctly on all PC speeds. The new calibrate routine has been tested on Pentium 166, pentium II 200, pentium III 300 Mhz and does work as expected.
  • Property mode set to 100644
File size: 7.4 KB
Line 
1/*
2 *  linux/drivers/char/vt.c
3 *
4 *  Copyright (C) 1992 obz under the linux copyright
5 *
6 *  Dynamic diacritical handling - aeb@cwi.nl - Dec 1993
7 *  Dynamic keymap and string allocation - aeb@cwi.nl - May 1994
8 *  Restrict VT switching via ioctl() - grif@cs.ucr.edu - Dec 1995
9 *  Some code moved for less code duplication - Andi Kleen - Mar 1997
10 *
11 *
12 * by: Rosimildo da Silva --
13 * Ported to RTEMS to provide the basic interface to the console
14 * driver. Removed all stuff not required, such as VT_, Fonts, etc.
15 */
16
17#include <sys/types.h>
18#include <errno.h>
19
20#include <i386_io.h>
21#include <rtems/kd.h>
22#include <rtems/keyboard.h>
23
24/*
25 * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
26 * experimentation and study of X386 SYSV handling.
27 *
28 * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
29 * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
30 * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
31 * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
32 * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
33 * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
34 * to the current console is done by the main ioctl code.
35 */
36
37struct vt_struct *vt_cons[MAX_NR_CONSOLES];
38
39/* Keyboard type: Default is KB_101, but can be set by machine
40 * specific code.
41 */
42unsigned char keyboard_type = KB_101;
43
44/*
45 * Generates sound of some frequency for some number of clock ticks
46 *
47 * If freq is 0, will turn off sound, else will turn it on for that time.
48 * If msec is 0, will return immediately, else will sleep for msec time, then
49 * turn sound off.
50 *
51 * We also return immediately, which is what was implied within the X
52 * comments - KDMKTONE doesn't put the process to sleep.
53 */
54
55#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \
56    || (defined(__mips__) && !defined(CONFIG_SGI))
57
58static void
59kd_nosound(unsigned long ignored)
60{
61        /* disable counter 2 */
62        outb(inb_p(0x61)&0xFC, 0x61);
63        return;
64}
65
66void
67_kd_mksound(unsigned int hz, unsigned int ticks)
68{
69  unsigned int count = 0;
70  int level;
71
72        if (hz > 20 && hz < 32767)
73                count = 1193180 / hz;
74       
75         _CPU_ISR_Disable(level);
76/*      del_timer(&sound_timer);  */
77        if (count) {
78                /* enable counter 2 */
79                outb_p(inb_p(0x61)|3, 0x61);
80                /* set command for counter 2, 2 byte write */
81                outb_p(0xB6, 0x43);
82                /* select desired HZ */
83                outb_p(count & 0xff, 0x42);
84                outb((count >> 8) & 0xff, 0x42);
85
86/*
87                if (ticks) {
88                        sound_timer.expires = jiffies+ticks;
89                        add_timer(&sound_timer);
90                }
91*/
92        } else
93                kd_nosound(0);
94
95         _CPU_ISR_Enable (level);
96        return;
97}
98
99#else
100
101void
102_kd_mksound(unsigned int hz, unsigned int ticks)
103{
104}
105
106#endif
107
108void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
109
110
111#define i (tmp.kb_index)
112#define s (tmp.kb_table)
113#define v (tmp.kb_value)
114static inline int
115do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kbd)
116{
117        struct kbentry tmp;
118        ushort *key_map, val;
119
120        tmp = *user_kbe;
121        if (i >= NR_KEYS || s >= MAX_NR_KEYMAPS)
122                return -EINVAL;
123
124        switch (cmd) {
125        case KDGKBENT:
126                key_map = key_maps[s];
127                if (key_map) {
128                    val = U(key_map[i]);
129                    if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
130                        val = K_HOLE;
131                } else
132                    val = (i ? K_HOLE : K_NOSUCHMAP);
133                user_kbe->kb_value = val;
134                return 0;
135
136        case KDSKBENT:
137                return -EINVAL;
138        }
139        return 0;
140}
141#undef i
142#undef s
143#undef v
144
145
146#define  HZ  100
147
148static inline int
149do_kbkeycode_ioctl(int cmd, struct kbkeycode *user_kbkc, int perm)
150{
151        struct kbkeycode tmp;
152        int kc = 0;
153
154        tmp = *user_kbkc;
155        switch (cmd) {
156        case KDGETKEYCODE:
157                kc = getkeycode(tmp.scancode);
158                if (kc >= 0)
159                        user_kbkc->keycode = kc;
160                break;
161        case KDSETKEYCODE:
162                if (!perm)
163                        return -EPERM;
164                kc = setkeycode(tmp.scancode, tmp.keycode);
165                break;
166        }
167        return kc;
168}
169
170static inline int
171do_kdgkb_ioctl(int cmd, struct kbsentry *user_kdgkb, int perm)
172{
173        return -EINVAL;
174}
175
176/*
177 * We handle the console-specific ioctl's here.  We allow the
178 * capability to modify any console, not just the fg_console.
179 */
180int vt_ioctl( unsigned int cmd, unsigned long arg)
181{
182        int perm;
183        unsigned int console;
184        unsigned char ucval;
185        struct kbd_struct * kbd;
186
187   console = 0;
188        /*
189         * To have permissions to do most of the vt ioctls, we either have
190         * to be the owner of the tty, or super-user.
191         */
192        perm = 1;
193        kbd = kbd_table + console;
194        switch (cmd) {
195        case KIOCSOUND:
196                if (!perm)
197                        return -EPERM;
198                if (arg)
199                        arg = 1193180 / arg;
200                kd_mksound(arg, 0);
201                return 0;
202
203        case KDMKTONE:
204                if (!perm)
205                        return -EPERM;
206        {
207                unsigned int ticks, count;
208               
209                /*
210                 * Generate the tone for the appropriate number of ticks.
211                 * If the time is zero, turn off sound ourselves.
212                 */
213                ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
214                count = ticks ? (arg & 0xffff) : 0;
215                if (count)
216                        count = 1193180 / count;
217                kd_mksound(count, ticks);
218                return 0;
219        }
220
221        case KDGKBTYPE:
222                /*
223                 * this is naive.
224                 */
225                ucval = keyboard_type;
226                goto setchar;
227
228        case KDSETMODE:
229        case KDGETMODE:
230                return -EINVAL;
231
232        case KDSKBMODE:
233                if (!perm)
234                        return -EPERM;
235                switch(arg) {
236                  case K_RAW:
237                        kbd->kbdmode = VC_RAW;
238                        break;
239                  case K_MEDIUMRAW:
240                        kbd->kbdmode = VC_MEDIUMRAW;
241                        break;
242                  case K_XLATE:
243                        kbd->kbdmode = VC_XLATE;
244                        compute_shiftstate();
245                        break;
246                  case K_UNICODE:
247                        kbd->kbdmode = VC_UNICODE;
248                        compute_shiftstate();
249                        break;
250                  default:
251                        return -EINVAL;
252                }
253                return 0;
254
255        case KDGKBMODE:
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                goto setint;
261
262        /* this could be folded into KDSKBMODE, but for compatibility
263           reasons it is not so easy to fold KDGKBMETA into KDGKBMODE */
264        case KDSKBMETA:
265                switch(arg) {
266                  case K_METABIT:
267                        clr_vc_kbd_mode(kbd, VC_META);
268                        break;
269                  case K_ESCPREFIX:
270                        set_vc_kbd_mode(kbd, VC_META);
271                        break;
272                  default:
273                        return -EINVAL;
274                }
275                return 0;
276
277        case KDGKBMETA:
278                ucval = (vc_kbd_mode(kbd, VC_META) ? K_ESCPREFIX : K_METABIT);
279        setint:
280                *(int *)arg = ucval;
281                return 0;
282
283        case KDGETKEYCODE:
284        case KDSETKEYCODE:
285                return do_kbkeycode_ioctl(cmd, (struct kbkeycode *)arg, perm);
286
287        case KDGKBENT:
288        case KDSKBENT:
289                return do_kdsk_ioctl(cmd, (struct kbentry *)arg, perm, kbd);
290
291        case KDGKBDIACR:
292        {
293                struct kbdiacrs *a = (struct kbdiacrs *)arg;
294                a->kb_cnt = accent_table_size;
295                memcpy( a->kbdiacr, accent_table, accent_table_size*sizeof(struct kbdiacr) );
296                return 0;
297        }
298
299        case KDSKBDIACR:
300        {
301                struct kbdiacrs *a = (struct kbdiacrs *)arg;
302                unsigned int ct;
303
304                if (!perm)
305                        return -EPERM;
306                ct = a->kb_cnt;
307                if (ct >= MAX_DIACR)
308                        return -EINVAL;
309                accent_table_size = ct;
310                memcpy(accent_table, a->kbdiacr, ct*sizeof(struct kbdiacr));
311                return 0;
312        }
313
314        /* the ioctls below read/set the flags usually shown in the leds */
315        /* don't use them - they will go away without warning */
316        case KDGKBLED:
317                ucval = kbd->ledflagstate | (kbd->default_ledflagstate << 4);
318                goto setchar;
319
320        case KDSKBLED:
321                if (!perm)
322                        return -EPERM;
323                if (arg & ~0x77)
324                        return -EINVAL;
325                kbd->ledflagstate = (arg & 7);
326                kbd->default_ledflagstate = ((arg >> 4) & 7);
327                set_leds();
328                return 0;
329
330        /* the ioctls below only set the lights, not the functions */
331        /* for those, see KDGKBLED and KDSKBLED above */
332        case KDGETLED:
333                ucval = getledstate();
334        setchar:
335                *(char*)arg = ucval;
336      return 0;
337
338        case KDSETLED:
339                if (!perm)
340                  return -EPERM;
341                setledstate(kbd, arg);
342                return 0;
343
344        default:
345                return -EINVAL;
346        }
347}
348
Note: See TracBrowser for help on using the repository browser.