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

4.104.114.84.95
Last change on this file since bd51a63 was bd51a63, checked in by Joel Sherrill <joel.sherrill@…>, on Sep 12, 2007 at 3:16:00 PM

2007-09-12 Joel Sherrill <joel.sherrill@…>

PR 1257/bsps

  • console/inch.c, console/keyboard.c, console/pc_keyb.c, console/vt.c: Code outside of cpukit should use the public API for rtems_interrupt_disable/rtems_interrupt_enable. By bypassing the public API and directly accessing _CPU_ISR_Disable and _CPU_ISR_Enable, they were bypassing the compiler memory barrier directive which could lead to problems. This patch also changes the type of the variable passed into these routines and addresses minor style issues.
  • Property mode set to 100644
File size: 7.8 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 <string.h>  /* memcpy */
18#include <sys/types.h>
19#include <errno.h>
20
21#include <i386_io.h>
22#include <rtems.h>
23#include <rtems/kd.h>
24#include <rtems/keyboard.h>
25
26/*
27 * Console (vt and kd) routines, as defined by USL SVR4 manual, and by
28 * experimentation and study of X386 SYSV handling.
29 *
30 * One point of difference: SYSV vt's are /dev/vtX, which X >= 0, and
31 * /dev/console is a separate ttyp. Under Linux, /dev/tty0 is /dev/console,
32 * and the vc start at /dev/ttyX, X >= 1. We maintain that here, so we will
33 * always treat our set of vt as numbered 1..MAX_NR_CONSOLES (corresponding to
34 * ttys 0..MAX_NR_CONSOLES-1). Explicitly naming VT 0 is illegal, but using
35 * /dev/tty0 (fg_console) as a target is legal, since an implicit aliasing
36 * to the current console is done by the main ioctl code.
37 */
38
39struct vt_struct *vt_cons[MAX_NR_CONSOLES];
40
41/* Keyboard type: Default is KB_101, but can be set by machine
42 * specific code.
43 */
44unsigned char keyboard_type = KB_101;
45
46/*
47 * Generates sound of some frequency for some number of clock ticks
48 *
49 * If freq is 0, will turn off sound, else will turn it on for that time.
50 * If msec is 0, will return immediately, else will sleep for msec time, then
51 * turn sound off.
52 *
53 * We also return immediately, which is what was implied within the X
54 * comments - KDMKTONE doesn't put the process to sleep.
55 */
56
57#if defined(__i386__) || defined(__alpha__) || defined(__powerpc__) \
58    || (defined(__mips__) && !defined(CONFIG_SGI))
59
60static void
61kd_nosound(unsigned long ignored)
62{
63  /* disable counter 2 */
64  outb(inb_p(0x61)&0xFC, 0x61);
65  return;
66}
67
68void
69_kd_mksound(unsigned int hz, unsigned int ticks)
70{
71  unsigned int          count = 0;
72  rtems_interrupt_level level;
73
74  if (hz > 20 && hz < 32767)
75    count = 1193180 / hz;
76
77   rtems_interrupt_disable(level);
78/*  del_timer(&sound_timer);  */
79  if (count) {
80    /* enable counter 2 */
81    outb_p(inb_p(0x61)|3, 0x61);
82    /* set command for counter 2, 2 byte write */
83    outb_p(0xB6, 0x43);
84    /* select desired HZ */
85    outb_p(count & 0xff, 0x42);
86    outb((count >> 8) & 0xff, 0x42);
87
88/*
89    if (ticks) {
90      sound_timer.expires = jiffies+ticks;
91      add_timer(&sound_timer);
92    }
93*/
94  } else
95    kd_nosound(0);
96
97   rtems_interrupt_enable(level);
98  return;
99}
100
101#else
102
103void
104_kd_mksound(unsigned int hz, unsigned int ticks)
105{
106}
107
108#endif
109
110void (*kd_mksound)(unsigned int hz, unsigned int ticks) = _kd_mksound;
111
112#define i (tmp.kb_index)
113#define s (tmp.kb_table)
114#define v (tmp.kb_value)
115static inline int
116do_kdsk_ioctl(int cmd, struct kbentry *user_kbe, int perm, struct kbd_struct *kbd)
117{
118  struct kbentry tmp;
119  ushort *key_map, val;
120
121  tmp = *user_kbe;
122  if (i >= NR_KEYS)  /*  s cannot be >= MAX_NR_KEYMAPS */
123    return -EINVAL;
124
125  switch (cmd) {
126  case KDGKBENT:
127    key_map = key_maps[s];
128    if (key_map) {
129        val = U(key_map[i]);
130        if (kbd->kbdmode != VC_UNICODE && KTYP(val) >= NR_TYPES)
131      val = K_HOLE;
132    } else
133        val = (i ? K_HOLE : K_NOSUCHMAP);
134    user_kbe->kb_value = val;
135    return 0;
136
137  case KDSKBENT:
138    return -EINVAL;
139  }
140  return 0;
141}
142#undef i
143#undef s
144#undef v
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}
Note: See TracBrowser for help on using the repository browser.