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

Last change on this file since 6b54dcb was 6b54dcb, checked in by Pavel Pisa <pisa@…>, on Oct 12, 2016 at 7:40:41 AM

bsps/i386: replace global interrupt disable by SMP build supporting locking.

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