OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [arch/] [armnommu/] [drivers/] [char/] [vt.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1622 jcastillo
/*
2
 * linux/arch/arm/drivers/char/vt.c
3
 *
4
 * VT routines
5
 *
6
 * Changelog:
7
 *  05-Sep-1996 RMK     Fixed race condition between VT switch & initialisation
8
 *  08-Sep-1996 RMK     Adapted Brad Pepers (ramparts@agt.net) console buffering code
9
 *                      (vt_put_char & vt_flush_chars).
10
 *  02-Sep-1997 RMK     Added in VT switch disable
11
 */
12
 
13
#include <linux/config.h>
14
#include <linux/sched.h>
15
#include <linux/tty.h>
16
#include <linux/kd.h>
17
#include <linux/errno.h>
18
#include <linux/malloc.h>
19
#include <linux/mm.h>
20
#include <linux/tty.h>
21
#include <linux/major.h>
22
 
23
#include <asm/segment.h>
24
#include <asm/hardware.h>
25
 
26
#include "kbd_kern.h"
27
#include "vt_kern.h"
28
 
29
#define CON_XMIT_SIZE   2048
30
 
31
#ifndef MIN
32
#define MIN(a,b)        ((a) < (b) ? (a) : (b))
33
#endif
34
 
35
/*
36
 * VCD functions
37
 */
38
extern void             vcd_blankscreen (int nopowersave);
39
extern void             vcd_disallocate (struct vt *);
40
extern int              vcd_init (struct vt *, int kmallocok, unsigned long *kmem);
41
extern int              vcd_ioctl (struct vt *, int cmd, unsigned long arg);
42
extern unsigned long    vcd_pre_init (unsigned long kmem, struct vt *);
43
extern int              vcd_resize (int rows, int columns);
44
extern void             vcd_restorestate (const struct vt *);
45
extern void             vcd_savestate (const struct vt *, int blanked);
46
extern void             vcd_unblankscreen (void);
47
extern int              vcd_write (const struct vt *, int from_user, const unsigned char *buf, int count);
48
extern void             vcd_setup_graphics (const struct vt *);
49
 
50
/*
51
 * Console functions
52
 */
53
extern void con_reset_palette (const struct vt *vt);
54
extern void con_set_palette (const struct vt *vt);
55
extern int con_init (void);
56
 
57
static int vt_refcount;
58
int do_poke_blanked_console;
59
static struct tty_driver vt_driver;
60
static struct tty_struct *vt_table[MAX_NR_CONSOLES];
61
static struct termios *vt_termios[MAX_NR_CONSOLES];
62
static struct termios *vt_termios_locked[MAX_NR_CONSOLES];
63
 
64
struct vt_data vtdata;
65
struct vt vt_con_data[MAX_NR_CONSOLES];
66
 
67
extern void vt_do_blankscreen (int nopowersave);
68
extern void vt_do_unblankscreen (void);
69
 
70
/* set this to the sound driver's wave output trigger */
71
void (*mksound_hook)(unsigned int freq, unsigned int vol, unsigned int duration);
72
/*
73
 * last_console is the last used console
74
 */
75
struct vt *last_console;
76
struct vt *want_console;
77
static char vt_dont_switch = 0;
78
 
79
/*
80
 * Sometimes we want to wait until a particular VT has been activated. We
81
 * do it in a very simple manner. Everybody waits on a single queue and
82
 * get woken up at once. Those that are satisfied go on with their business,
83
 * while those not ready go back to sleep. Seems overkill to add a wait
84
 * to each vt just for this - usually this does nothing!
85
 */
86
static struct wait_queue *vt_activate_queue = NULL;
87
 
88
/*
89
 * Sleeps until a vt is activated, or the task is interrupted. Returns
90
 * 0 if activation, -1 if interrupted.
91
 */
92
static int vt_waitonactivate (void)
93
{
94
    interruptible_sleep_on (&vt_activate_queue);
95
    return (current->signal & ~current->blocked) ? -1 : 0;
96
}
97
 
98
#define vt_wake_waitactive() wake_up(&vt_activate_queue)
99
 
100
void vt_reset (const struct vt *vt)
101
{
102
    vt->kbd->kbdmode            = VC_XLATE;
103
    vt->vtd->vc_mode            = KD_TEXT;
104
    vt->vtd->vt_mode.mode       = VT_AUTO;
105
    vt->vtd->vt_mode.waitv      = 0;
106
    vt->vtd->vt_mode.relsig     = 0;
107
    vt->vtd->vt_mode.acqsig     = 0;
108
    vt->vtd->vt_mode.frsig      = 0;
109
    vt->vtd->vt_pid             = -1;
110
    vt->vtd->vt_newvt           = NULL;
111
    con_reset_palette (vt);
112
}
113
 
114
static int vt_allocate (struct vt *vt)
115
{
116
    if (!vt_allocated(vt)) {
117
        void *data, *p;
118
        int r;
119
 
120
        data = kmalloc (sizeof (*vt->vcd) +
121
                        sizeof (*vt->kbd) +
122
                        sizeof (*vt->vtd) + CON_XMIT_SIZE, GFP_KERNEL);
123
        if (!data)
124
            return -ENOMEM;
125
 
126
        vt->vcd = data;  p = ((struct con_struct *)data + 1);
127
        vt->kbd = p;     p = ((struct kbd_struct *)p + 1);
128
        vt->vtd = p;     p = ((struct vt_struct *)p + 1);
129
        vt->vtd->xmit_buf = p;
130
 
131
        if ((r = kbd_struct_init (vt, 1)) < 0) {
132
            vt->vcd = NULL;
133
            vt->kbd = NULL;
134
            vt->vtd = NULL;
135
            kfree (data);
136
            return r;
137
        }
138
 
139
        if ((r = vcd_init (vt, 1, NULL)) < 0) {
140
            vt->vcd = NULL;
141
            vt->kbd = NULL;
142
            vt->vtd = NULL;
143
            kfree (data);
144
            return r;
145
        }
146
        vt_reset (vt);
147
        vt->vtd->xmitting = vt->vtd->xmit_cnt =
148
        vt->vtd->xmit_out = vt->vtd->xmit_in = 0;
149
        vt->allocinit = 1;
150
    }
151
    return 0;
152
}
153
 
154
static int vt_disallocate (struct vt *vt)
155
{
156
    if (vt_allocated (vt)) {
157
        void *data = vt->vcd;
158
 
159
        vt->allocinit = 0;
160
        vcd_disallocate (vt);
161
        vt->vcd = NULL;
162
        vt->kbd = NULL;
163
        vt->vtd = NULL;
164
 
165
        kfree (data);
166
    }
167
    return 0;
168
}
169
 
170
void vt_updatescreen (const struct vt *newvt)
171
{
172
    static int lock = 0;
173
 
174
    if (newvt == vtdata.fgconsole || lock)
175
        return;
176
 
177
    if (!vt_allocated (newvt)) {
178
        printk ("updatescreen: tty %d not allocated ??\n", newvt->num);
179
        return;
180
    }
181
 
182
    lock = 1;
183
 
184
    vcd_savestate (vtdata.fgconsole, vtdata.blanked != NULL);
185
 
186
    vtdata.fgconsole = (struct vt *)newvt;
187
 
188
    vcd_restorestate (vtdata.fgconsole);
189
    compute_shiftstate ();
190
 
191
    lock = 0;
192
}
193
 
194
/*
195
 * Performs the back end of a vt switch
196
 */
197
void vt_completechangeconsole (const struct vt *new_console)
198
{
199
    unsigned char old_vt_mode;
200
    struct vt *old_vt = vtdata.fgconsole;
201
 
202
    if (new_console == old_vt || (vt_dont_switch))
203
        return;
204
    if (!vt_allocated (new_console))
205
        return;
206
    last_console = old_vt;
207
 
208
    /*
209
     * If we're switching, we could be going from KD_GRAPHICS to
210
     * KD_TEXT mode or vice versa, which means we need to blank or
211
     * unblank the screen later.
212
     */
213
    old_vt_mode = old_vt->vtd->vc_mode;
214
    vt_updatescreen (new_console);
215
 
216
    /*
217
     * If this new console is under process control, send it a signal
218
     * telling it that it has acquired. Also check if it has died and
219
     * clean up (similar to logic employed in vt_changeconsole())
220
     */
221
    if (new_console->vtd->vt_mode.mode == VT_PROCESS) {
222
        /*
223
         * Send the signal as privileged - kill_proc() will
224
         * tell us if the process has gone or something else
225
         * is awry
226
         */
227
        if (kill_proc(new_console->vtd->vt_pid,
228
                              new_console->vtd->vt_mode.acqsig,
229
                              1) != 0) {
230
            /*
231
             * The controlling process has died, so we revert back to
232
             * normal operation. In this case, we'll also change back
233
             * to KD_TEXT mode. I'm not sure if this is strictly correct
234
             * but it saves the agony when the X server dies and the screen
235
             * remains blanked due to KD_GRAPHICS! It would be nice to do
236
             * this outside of VT_PROCESS but there is no single process
237
             * to account for and tracking tty count may be undesirable.
238
             */
239
            vt_reset (new_console);
240
        }
241
    }
242
 
243
    /*
244
     * We do this here because the controlling process above may have
245
     * gone, and so there is now a new vc_mode
246
     */
247
    if (old_vt_mode != new_console->vtd->vc_mode) {
248
        if (new_console->vtd->vc_mode == KD_TEXT)
249
            vt_do_unblankscreen ();
250
        else {
251
            vt_do_blankscreen (1);
252
            vcd_setup_graphics (new_console);
253
        }
254
    }
255
 
256
    /* Set the colour palette for this VT */
257
    if (new_console->vtd->vc_mode == KD_TEXT)
258
        con_set_palette (new_console);
259
 
260
    /*
261
     * Wake anyone waiting for their VT to activate
262
     */
263
    vt_wake_waitactive();
264
    return;
265
}
266
 
267
/*
268
 * Performs the front-end of a vt switch
269
 */
270
void vt_changeconsole (struct vt *new_console)
271
{
272
    struct vt *old_vt = vtdata.fgconsole;
273
 
274
    if (new_console == old_vt || (vt_dont_switch))
275
        return;
276
    if (!vt_allocated (new_console))
277
        return;
278
 
279
    /*
280
     * If this vt is in process mode, then we need to handshake with
281
     * that process before switching. Essentially, we store where that
282
     * vt wants to switch to and wait for it to tell us when it's done
283
     * (via VT_RELDISP ioctl).
284
     *
285
     * We also check to see if the controlling process still exists.
286
     * If it doesn't, we reset this vt to auto mode and continue.
287
     * This is a cheap way to track process control. The worst thing
288
     * that can happen is: we send a signal to a process, it dies, and
289
     * the switch gets "lost" waiting for a response; hopefully, the
290
     * user will try again, we'll detect the process is gone (unless
291
     * the user waits just the right amount of time :-) and revert the
292
     * vt to auto control.
293
     */
294
    if (old_vt->vtd->vt_mode.mode == VT_PROCESS) {
295
        /*
296
         * Send the signal as privileged - kill_proc() will
297
         * tell us if the process has gone or something else
298
         * is awry
299
         */
300
        if (kill_proc(old_vt->vtd->vt_pid, old_vt->vtd->vt_mode.relsig, 1) == 0) {
301
            /*
302
             * It worked. Mark the vt to switch to and
303
             * return. The process needs to send us a
304
             * VT_RELDISP ioctl to complete the switch.
305
             */
306
            old_vt->vtd->vt_newvt = new_console;
307
            return;
308
        }
309
 
310
        /*
311
         * The controlling process has died, so we revert back to
312
         * normal operation. In this case, we'll also change back
313
         * to KD_TEXT mode. I'm not sure if this is strictly correct
314
         * but it saves the agony when the X server dies and the screen
315
         * remains blanked due to KD_GRAPHICS! It would be nice to do
316
         * this outside of VT_PROCESS but there is no single process
317
         * to account for and tracking tty count may be undesirable.
318
         */
319
        vt_reset (old_vt);
320
 
321
        /*
322
         * Fall through to normal (VT_AUTO) handling of the switch...
323
         */
324
    }
325
 
326
    /*
327
     * Ignore all switches in KD_GRAPHICS+VT_AUTO mode
328
     */
329
    if (old_vt->vtd->vc_mode == KD_GRAPHICS)
330
        return;
331
 
332
    vt_completechangeconsole (new_console);
333
}
334
 
335
/*
336
 * If a vt is under process control, the kernel will not switch to it
337
 * immediately, but postpone the operation until the process calls this
338
 * ioctl, allowing the switch to complete.
339
 *
340
 * According to the X sources this is the behavior:
341
 *      0:      pending switch-from not OK
342
 *      1:      pending switch-from OK
343
 *      2:      completed switch-to OK
344
 */
345
static inline int vt_reldisp (const struct vt *old_vt, int arg)
346
{
347
    int i;
348
 
349
    if (old_vt->vtd->vt_mode.mode != VT_PROCESS)
350
        return -EINVAL;
351
 
352
    if (old_vt->vtd->vt_newvt) {
353
        /*
354
         * Switching-from response
355
         */
356
        if (arg == 0)
357
            /*
358
             * Switch disallowed, so forget we were trying
359
             * to do it.
360
             */
361
            old_vt->vtd->vt_newvt = NULL;
362
        else {
363
            /*
364
             * The current vt has been released, so complete the
365
             * switch.
366
             */
367
            struct vt *new_vt = old_vt->vtd->vt_newvt;
368
            old_vt->vtd->vt_newvt = NULL;
369
            i = vt_allocate (new_vt);
370
            if (i)
371
                return i;
372
            vt_completechangeconsole (new_vt);
373
        }
374
    } else {
375
        /*
376
         * Switched-to response
377
         */
378
        if (arg != VT_ACKACQ)
379
            return -EINVAL;
380
    }
381
    return 0;
382
}
383
 
384
/*
385
 * Set the mode of a VT.
386
 */
387
static inline int vt_kdsetmode (const struct vt *vt, int mode)
388
{
389
    /*
390
     * Currently, setting the mode from KD_TEXT to KD_GRAPHICS
391
     * doesn't do a whole lot. I'm not sure if it should do any
392
     * restoration of modes or what...
393
     */
394
    switch (mode) {
395
    case KD_TEXT0:
396
    case KD_TEXT1:
397
        mode = KD_TEXT;
398
    case KD_GRAPHICS:
399
    case KD_TEXT:
400
        break;
401
    default:
402
        return -EINVAL;
403
    }
404
 
405
    if (vt->vtd->vc_mode == mode)
406
        return 0;
407
 
408
    vt->vtd->vc_mode = mode;
409
    if (vt != vtdata.fgconsole)
410
        return 0;
411
 
412
    /*
413
     * explicitly blank/unblank the screen if switching modes
414
     */
415
    if (mode == KD_TEXT) {
416
        vt_do_unblankscreen ();
417
        vcd_restorestate (vt);
418
    } else {
419
        vt_do_blankscreen (1);
420
        vcd_setup_graphics (vt);
421
    }
422
    return 0;
423
}
424
 
425
static inline int vt_setmode (const struct vt *vt, struct vt_mode *vtmode)
426
{
427
    if (vtmode->mode != VT_AUTO && vtmode->mode != VT_PROCESS)
428
        return -EINVAL;
429
 
430
    vt->vtd->vt_mode = *vtmode;
431
    vt->vtd->vt_mode.frsig = 0;
432
    vt->vtd->vt_pid = current->pid;
433
    vt->vtd->vt_newvt = NULL;
434
    return 0;
435
}
436
 
437
void vt_mksound (unsigned int freq, unsigned int vol, unsigned int ticks)
438
{
439
    if (mksound_hook)
440
        mksound_hook (freq, vol, ticks);
441
}
442
 
443
/*
444
 * Deallocate memory associated to VT (but leave VT1)
445
 */
446
int vt_deallocate (int arg)
447
{
448
    int i;
449
 
450
    if (arg == 0) {
451
        /*
452
         * deallocate all unused consoles, but leave 0
453
         */
454
        for (i = 1; i < MAX_NR_CONSOLES; i++)
455
            if (!VT_BUSY (i))
456
                vt_disallocate (vt_con_data + i);
457
    } else {
458
        arg -= 1;
459
        if (VT_BUSY (arg))
460
            return -EBUSY;
461
        if (arg)
462
            vt_disallocate (vt_con_data + arg);
463
    }
464
    return 0;
465
}
466
 
467
int vt_resize (int columns, int rows)
468
{
469
    return vcd_resize (rows, columns);
470
}
471
 
472
void vt_pokeblankedconsole (void)
473
{
474
    timer_active &= ~(1 << BLANK_TIMER);
475
    if (vtdata.fgconsole->vtd->vc_mode == KD_GRAPHICS)
476
        return;
477
    if (vtdata.blanked) {
478
        timer_table[BLANK_TIMER].expires = 0;
479
        timer_active |= 1 << BLANK_TIMER;
480
    } else if (vtdata.screen.blankinterval) {
481
        timer_table[BLANK_TIMER].expires = jiffies + vtdata.screen.blankinterval;
482
        timer_active |= 1 << BLANK_TIMER;
483
    }
484
}
485
 
486
static void vt_blankscreen (void);
487
 
488
void vt_do_unblankscreen (void)
489
{
490
    if (!vtdata.blanked)
491
        return;
492
 
493
    if (!vt_allocated (vtdata.fgconsole)) {
494
        /* impossible... */
495
        printk ("unblank_screen: tty %d not allocated ??\n", vtdata.fgconsole->num);
496
        return;
497
    }
498
 
499
    timer_table[BLANK_TIMER].fn = vt_blankscreen;
500
 
501
    if (vtdata.screen.blankinterval) {
502
        timer_table[BLANK_TIMER].expires = jiffies + vtdata.screen.blankinterval;
503
        timer_active |= 1 << BLANK_TIMER;
504
    }
505
 
506
    vtdata.blanked = NULL;
507
 
508
    vcd_unblankscreen ();
509
}
510
 
511
/*
512
 * for panic.c
513
 */
514
void do_unblank_screen (void)
515
{
516
    vt_do_unblankscreen ();
517
}
518
 
519
void vt_do_blankscreen (int nopowersave)
520
{
521
    if (vtdata.blanked)
522
        return;
523
 
524
    timer_active &= ~(1 << BLANK_TIMER);
525
    timer_table[BLANK_TIMER].fn = do_unblank_screen;
526
 
527
    vtdata.blanked = vtdata.fgconsole;
528
 
529
    vcd_blankscreen (nopowersave);
530
}
531
 
532
static void vt_blankscreen (void)
533
{
534
    vt_do_blankscreen (0);
535
}
536
 
537
static int vt_open (struct tty_struct *tty, struct file *filp)
538
{
539
    struct vt *vt;
540
    unsigned int idx;
541
    int i;
542
 
543
    idx = MINOR(tty->device) - tty->driver.minor_start;
544
 
545
    vt = vt_con_data + idx;
546
 
547
    if ((i = vt_allocate (vt)) < 0)
548
        return i;
549
 
550
    tty->driver_data = vt;
551
 
552
    if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
553
        tty->winsize.ws_row = vtdata.numrows;
554
        tty->winsize.ws_col = vtdata.numcolumns;
555
    }
556
    return 0;
557
}
558
 
559
static void vt_vtd_flush_chars (const struct vt *vt, struct vt_struct *vtd)
560
{
561
    unsigned long flags;
562
 
563
    save_flags (flags);
564
    if (vtd->xmitting)
565
        return;
566
 
567
    vtd->xmitting = 1;
568
 
569
    while (1) {
570
        int c;
571
 
572
        cli ();
573
        c = MIN(vtd->xmit_cnt, CON_XMIT_SIZE - vtd->xmit_out);
574
 
575
        if (c <= 0)
576
            break;
577
 
578
        restore_flags (flags);
579
 
580
        c = vcd_write (vt, 0, vtd->xmit_buf + vtd->xmit_out, c);
581
 
582
        cli ();
583
 
584
        if (c <= 0)
585
            break;
586
        vtd->xmit_out = (vtd->xmit_out + c) & (CON_XMIT_SIZE - 1);
587
        vtd->xmit_cnt -= c;
588
    }
589
 
590
    vtd->xmitting = 0;
591
    restore_flags (flags);
592
    if (*vt->tty)
593
        wake_up_interruptible (&(*vt->tty)->write_wait);
594
}
595
 
596
static int vt_write (struct tty_struct *tty, int from_user,
597
                        const unsigned char *buf, int count)
598
{
599
    static unsigned long last_error = 0;
600
    const struct vt *vt = (struct vt *)tty->driver_data;
601
 
602
    if (vt_allocated (vt)) {
603
        if (vt->vtd->xmit_cnt)
604
            vt_vtd_flush_chars (vt, vt->vtd);
605
        return vcd_write (vt, from_user, buf, count);
606
    }
607
 
608
    if (jiffies > last_error + 10*HZ) {
609
        printk ("vt_write: tty %d not allocated\n", vt->num);
610
        last_error = jiffies;
611
    }
612
    return 0;
613
}
614
 
615
static void vt_put_char (struct tty_struct *tty, unsigned char ch)
616
{
617
    const struct vt *vt = (struct vt *)tty->driver_data;
618
    unsigned long flags;
619
 
620
    if (!vt_allocated (vt))
621
        return;
622
 
623
    save_flags_cli (flags);
624
    if (vt->vtd->xmit_cnt < CON_XMIT_SIZE - 1) {
625
        vt->vtd->xmit_buf[vt->vtd->xmit_in++] = ch;
626
        vt->vtd->xmit_in &= CON_XMIT_SIZE - 1;
627
        vt->vtd->xmit_cnt ++;
628
    }
629
    restore_flags (flags);
630
}
631
 
632
static void vt_flush_chars (struct tty_struct *tty)
633
{
634
    const struct vt *vt = (struct vt *)tty->driver_data;
635
 
636
    if (!vt_allocated (vt) || !vt->vtd->xmit_cnt || tty->stopped)
637
        return;
638
 
639
    vt_vtd_flush_chars (vt, vt->vtd);
640
}
641
 
642
static int vt_write_room (struct tty_struct *tty)
643
{
644
    const struct vt *vt = (struct vt *)tty->driver_data;
645
    int r;
646
 
647
    if (!vt_allocated (vt))
648
        return 0;
649
 
650
    r = CON_XMIT_SIZE - vt->vtd->xmit_cnt - 8; /* allow 8 char overflow */
651
    if (r < 0)
652
        return 0;
653
    else
654
        return r;
655
}
656
 
657
static int vt_chars_in_buffer (struct tty_struct *tty)
658
{
659
    const struct vt *vt = (struct vt *)tty->driver_data;
660
 
661
    if (!vt_allocated (vt))
662
        return CON_XMIT_SIZE;
663
    return vt->vtd->xmit_cnt;
664
}
665
#if 0
666
static void vt_flush_buffer (struct tty_struct *tty)
667
{
668
    const struct vt *vt = (struct vt *)tty->driver_data;
669
 
670
    if (!vt_allocated (vt))
671
        return;
672
 
673
    cli ();
674
    vt->vtd->xmit_cnt = vt->vtd->xmit_out = vt->vtd->xmit_in = 0;
675
    sti ();
676
}
677
#endif
678
static int vt_ioctl (struct tty_struct *tty, struct file *filp,
679
                        unsigned int cmd, unsigned long arg)
680
{
681
    struct vt *vt = tty->driver_data;
682
    int perm, i;
683
 
684
    if (!vt_allocated (vt))     /* impossible ? */
685
        return -ENOIOCTLCMD;
686
    /*
687
     * To have permissions to do most of the vt ioctls, we either
688
     * have to be the owner of the tty, or super-user.
689
     */
690
    perm = 0;
691
    if (current->tty == tty || suser ())
692
        perm = 1;
693
 
694
#define PERM if (!perm) return -EPERM
695
 
696
    switch (cmd) {
697
    case KDGETMODE:
698
        i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (unsigned long));
699
        if (!i)
700
            put_user (vt->vtd->vc_mode, (unsigned long *)arg);
701
        return i;
702
 
703
    case KDSETMODE:
704
        PERM;
705
        return vt_kdsetmode (vt, arg);
706
 
707
    case VT_GETMODE:
708
        i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (struct vt_mode));
709
        if (i)
710
            return i;
711
        memcpy_tofs ((void *)arg, &vt->vtd->vt_mode, sizeof (struct vt_mode));
712
        return 0;
713
 
714
    case VT_SETMODE: {
715
        struct vt_mode vtmode;
716
 
717
        PERM;
718
        i = verify_area (VERIFY_READ, (void *)arg, sizeof (struct vt_mode));
719
        if (i)
720
            return i;
721
        memcpy_fromfs (&vtmode, (void *)arg, sizeof (struct vt_mode));
722
        return vt_setmode (vt, &vtmode);
723
        }
724
 
725
    case VT_GETSTATE: {
726
        /*
727
         * Returns global VT state.  Note that VT 0 is always open, since
728
         * it's an alias for the current VT, and people can't use it here.
729
         * We cannot return state for more than 16 VTs, since v_state is short.
730
         */
731
        struct vt_stat *vtstat = (struct vt_stat *)arg;
732
        unsigned short state = 1, mask = 2;
733
 
734
        i = verify_area (VERIFY_WRITE, vtstat, sizeof (struct vt_stat));
735
        if (i)
736
            return i;
737
 
738
        for (i = 0; i < MAX_NR_CONSOLES && mask; ++i, mask <<= 1)
739
            if (VT_IS_IN_USE(i))
740
                state |= mask;
741
 
742
        put_user (vtdata.fgconsole->num, &vtstat->v_active);
743
        put_user (state, &vtstat->v_state);
744
        return 0;
745
        }
746
 
747
    case VT_OPENQRY:
748
        /*
749
         * Returns the first available (non-open) console
750
         */
751
        i = verify_area (VERIFY_WRITE, (void *)arg, sizeof (unsigned long));
752
        if (i)
753
            return i;
754
 
755
        for (i = 0; i < MAX_NR_CONSOLES; i++)
756
            if (!VT_IS_IN_USE(i))
757
                break;
758
        if (i < MAX_NR_CONSOLES)
759
            put_user (i + 1, (unsigned long *)arg);
760
        else
761
            put_user (-1, (unsigned long *)arg);
762
        return 0;
763
 
764
    case VT_ACTIVATE:
765
        PERM;
766
        /*
767
         * VT activate will cause us to switch to vt #num with num >= 1
768
         * (switches to vt0, our console, are not allowed, just to preserve
769
         * sanity)
770
         */
771
        if (arg == 0 || arg > MAX_NR_CONSOLES)
772
            return -ENXIO;
773
        vt = vt_con_data + (arg - 1);
774
        i = vt_allocate (vt);
775
        if (i)
776
            return i;
777
 
778
        vt_changeconsole (vt);
779
        return 0;
780
 
781
    case VT_WAITACTIVE:
782
        PERM;
783
        /*
784
         * wait until the specified VT has been activated
785
         */
786
        if (arg == 0 || arg > MAX_NR_CONSOLES)
787
            return -ENXIO;
788
        vt = vt_con_data + (arg - 1);
789
        while (vt != vtdata.fgconsole) {
790
            if (vt_waitonactivate () < 0)
791
                return -EINTR;
792
        }
793
        return 0;
794
 
795
    case VT_RELDISP:
796
        PERM;
797
        return vt_reldisp (vt, arg);
798
 
799
    case VT_RESIZE: {
800
        struct vt_sizes *vtsizes = (struct vt_sizes *)arg;
801
        ushort ll, cc;
802
 
803
        PERM;
804
 
805
        i = verify_area (VERIFY_READ, (void *)vtsizes, sizeof (struct vt_sizes));
806
        if (i)
807
            return i;
808
        ll = get_user (&vtsizes->v_rows);
809
        cc = get_user (&vtsizes->v_cols);
810
        return vt_resize (cc, ll);
811
        }
812
 
813
    case KIOCSOUND:
814
        PERM;
815
        vt_mksound (arg, 72, 5);
816
        return 0;
817
 
818
    case KDMKTONE: {
819
        unsigned int freq  = get_user ((unsigned long *)arg);
820
        unsigned int vol   = get_user ((unsigned long *)(arg + 4));
821
        unsigned int ticks = get_user ((unsigned long *)(arg + 8));
822
 
823
        PERM;
824
        /*
825
         * Generate the tone for the apropriate number of ticks.
826
         * If time is zero, turn off sound ourselves.
827
         */
828
        vt_mksound (freq, vol, ticks);
829
        return 0;
830
        }
831
 
832
    case VT_DISALLOCATE:
833
        if (arg > MAX_NR_CONSOLES)
834
            return -ENXIO;
835
        return vt_deallocate (arg);
836
 
837
    case VT_GETSCRINFO:
838
        /*
839
         * Get screen dimentions
840
         */
841
        i = verify_area (VERIFY_WRITE, (void *)arg, 5 * sizeof (unsigned long));
842
        if (!i) {
843
            put_user (0, (unsigned long *)arg);
844
            put_user (vtdata.numcolumns * 8, (unsigned long *)(arg + 4));
845
            put_user (vtdata.numrows * 8, (unsigned long *)(arg + 8));
846
            put_user (vtdata.screen.bitsperpix, (unsigned long *)(arg + 12)); /* bpp */
847
#ifndef HAS_VIDC20
848
            put_user (4, (unsigned long *)(arg + 16)); /* depth */
849
#else
850
            put_user (8, (unsigned long *)(arg + 16)); /* depth */
851
#endif
852
        }
853
        return i;
854
 
855
    case VT_LOCKSWITCH:
856
        if (!suser())
857
            return -EPERM;
858
        vt_dont_switch = 1;
859
        return 0;
860
 
861
    case VT_UNLOCKSWITCH:
862
        if (!suser())
863
            return -EPERM;
864
        vt_dont_switch = 0;
865
        return 0;
866
 
867
    case KDMAPDISP:
868
    case KDUNMAPDISP:
869
    case KDSKBMODE:
870
    case KDSKBMETA:
871
    case KDSETKEYCODE:
872
    case KDSKBENT:
873
    case KDSKBSENT:
874
    case KDSKBDIACR:
875
    case KDSKBLED:
876
    case KDSETLED:
877
    case KDSIGACCEPT:
878
        PERM;
879
 
880
    case KDGKBTYPE:
881
    case KDADDIO:
882
    case KDDELIO:
883
    case KDENABIO:
884
    case KDDISABIO:
885
    case KDGKBMODE:
886
    case KDGKBMETA:
887
    case KDGETKEYCODE:
888
    case KDGKBENT:
889
    case KDGKBSENT:
890
    case KDGKBDIACR:
891
    case KDGKBLED:
892
    case KDGETLED:
893
        return kbd_ioctl (vt, cmd, arg);
894
 
895
    case VT_SETPALETTE:
896
    case PIO_FONT:
897
    case PIO_SCRNMAP:
898
    case PIO_UNISCRNMAP:
899
    case PIO_UNIMAPCLR:
900
    case PIO_UNIMAP:
901
        PERM;
902
 
903
    case VT_GETPALETTE:
904
    case GIO_FONT:
905
    case GIO_SCRNMAP:
906
    case GIO_UNISCRNMAP:
907
    case GIO_UNIMAP:
908
        return vcd_ioctl (vt, cmd, arg);
909
    }
910
    return -ENOIOCTLCMD;
911
}
912
/*
913
 * Turn the Scroll-Lock LED on when the tty is stopped
914
 */
915
static void vt_stop (struct tty_struct *tty)
916
{
917
    if (tty) {
918
        const struct vt *vt = (struct vt *)tty->driver_data;
919
        if (vt_allocated (vt)) {
920
            set_vc_kbd_led (vt->kbd, VC_SCROLLOCK);
921
            set_leds ();
922
        }
923
    }
924
}
925
 
926
/*
927
 * Turn the Scroll-Lock LED off when the tty is started
928
 */
929
static void vt_start (struct tty_struct *tty)
930
{
931
    if (tty) {
932
        const struct vt *vt = (struct vt *)tty->driver_data;
933
        if (vt_allocated (vt)) {
934
            clr_vc_kbd_led (vt->kbd, VC_SCROLLOCK);
935
            set_leds ();
936
        }
937
        if (vt->vtd->xmit_cnt)
938
            vt_vtd_flush_chars (vt, vt->vtd);
939
    }
940
}
941
 
942
/*
943
 * vt_throttle and vt_unthrottle are only used for
944
 * paste_selection(), which has to stuff in a large number
945
 * of characters...
946
 */
947
static void vt_throttle (struct tty_struct *tty)
948
{
949
}
950
 
951
static void vt_unthrottle (struct tty_struct *tty)
952
{
953
    const struct vt *vt = (struct vt *)tty->driver_data;
954
 
955
    if (vt_allocated (vt))
956
        wake_up_interruptible (&vt->vtd->paste_wait);
957
}
958
 
959
/*
960
 * This is the console switching bottom half handler.
961
 *
962
 * Doing console switching in a bottom half handler allows
963
 * us to do ths switches asynchronously (needed when we want
964
 * to switch due to a keyboard interrupt), while still giving
965
 * us the option to easily disable it to avoid races when we
966
 * need to write to the console.
967
 */
968
static void console_bh(void)
969
{
970
        if (want_console) {
971
                if (want_console != vtdata.fgconsole) {
972
                        vt_changeconsole(want_console);
973
                        /* we only changed when the console had already
974
                           been allocated - a new console is not created
975
                           in an interrupt routine */
976
                }
977
                want_console = NULL;
978
        }
979
        if (do_poke_blanked_console) { /* do not unblank for a LED change */
980
                do_poke_blanked_console = 0;
981
                vt_pokeblankedconsole();
982
        }
983
}
984
 
985
/*
986
 * We don't have kmalloc setup yet.  We just want to get enough up so that printk
987
 * can work.
988
 *
989
 * Basically, we setup the VT structures for tty1.
990
 */
991
unsigned long vt_pre_init (unsigned long kmem)
992
{
993
    struct vt *vt = vt_con_data;
994
 
995
    memset (vt_con_data, 0, sizeof (vt_con_data));
996
 
997
    vtdata.numcolumns           = ORIG_VIDEO_COLS;
998
    vtdata.numrows              = ORIG_VIDEO_LINES;
999
    vtdata.blanked              = NULL;
1000
    vtdata.fgconsole            = vt_con_data;
1001
    vtdata.screen.blankinterval = 10*60*HZ;
1002
    vtdata.select.vt            = NULL;
1003
    vtdata.select.start         = -1;
1004
    vtdata.select.end           = 0;
1005
    vtdata.select.buffer        = NULL;
1006
 
1007
    vt->vcd             = (struct con_struct *)kmem;    kmem += sizeof (struct con_struct);
1008
    vt->kbd             = (struct kbd_struct *)kmem;    kmem += sizeof (struct kbd_struct);
1009
    vt->vtd             = (struct vt_struct *)kmem;     kmem += sizeof (struct vt_struct);
1010
    vt->vtd->xmit_buf   = (unsigned char *)kmem;        kmem += CON_XMIT_SIZE;
1011
    vt->vtd->xmitting   = vt->vtd->xmit_cnt =
1012
    vt->vtd->xmit_out   = vt->vtd->xmit_in = 0;
1013
    vt->tty = &vt_table[0];
1014
    vt->num = 1;
1015
 
1016
    /*
1017
     * vcd_init is called inside vcd_pre_init
1018
     */
1019
    kbd_struct_init (vt, 0);
1020
    vt_reset (vt);
1021
    vt->allocinit = 1;
1022
 
1023
    kmem = vcd_pre_init (kmem, vt);
1024
 
1025
    init_bh(CONSOLE_BH, console_bh);
1026
 
1027
    return kmem;
1028
}
1029
 
1030
/*
1031
 * This is the post initialisation.  We have kmalloc setup so we can use it...
1032
 */
1033
void vt_post_init (void)
1034
{
1035
    int i;
1036
 
1037
    memset (&vt_driver, 0, sizeof (struct tty_driver));
1038
    vt_driver.magic             = TTY_DRIVER_MAGIC;
1039
    vt_driver.name              = "tty";
1040
    vt_driver.name_base         = 1;
1041
    vt_driver.major             = TTY_MAJOR;
1042
    vt_driver.minor_start       = 1;
1043
    vt_driver.num               = MAX_NR_CONSOLES;
1044
    vt_driver.type              = TTY_DRIVER_TYPE_CONSOLE;
1045
    vt_driver.init_termios      = tty_std_termios;
1046
    vt_driver.flags             = TTY_DRIVER_REAL_RAW;
1047
    vt_driver.refcount          = &vt_refcount;
1048
    vt_driver.table             = vt_table;
1049
    vt_driver.termios           = vt_termios;
1050
    vt_driver.termios_locked    = vt_termios_locked;
1051
    vt_driver.open              = vt_open;
1052
    vt_driver.write             = vt_write;
1053
    vt_driver.put_char          = vt_put_char;
1054
    vt_driver.flush_chars       = vt_flush_chars;
1055
    vt_driver.write_room        = vt_write_room;
1056
    vt_driver.chars_in_buffer   = vt_chars_in_buffer;
1057
#if 0
1058
    vt_driver.flush_buffer      = vt_flush_buffer;
1059
#endif
1060
    vt_driver.ioctl             = vt_ioctl;
1061
    vt_driver.stop              = vt_stop;
1062
    vt_driver.start             = vt_start;
1063
    vt_driver.throttle          = vt_throttle;
1064
    vt_driver.unthrottle        = vt_unthrottle;
1065
 
1066
    for (i = 1; i < MAX_NR_CONSOLES; i++) {
1067
        struct vt *vt = vt_con_data + i;
1068
        vt->tty = &vt_table[i];
1069
        vt->num = i + 1;
1070
        vt->allocinit = 0;
1071
        if (i < MIN_NR_CONSOLES)
1072
            vt_allocate (vt);
1073
    }
1074
 
1075
    if (tty_register_driver (&vt_driver))
1076
        panic ("Couldn't register console driver");
1077
 
1078
    timer_table[BLANK_TIMER].fn = vt_blankscreen;
1079
    if (vtdata.screen.blankinterval) {
1080
        timer_table[BLANK_TIMER].expires = jiffies + vtdata.screen.blankinterval;
1081
        timer_active |= 1 << BLANK_TIMER;
1082
    } else
1083
        timer_table[BLANK_TIMER].expires = 0;
1084
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.