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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [s390/] [char/] [tubtty.c] - Blame information for rev 1275

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  IBM/3270 Driver -- Copyright (C) 2000, 2001 UTS Global LLC
3
 *
4
 *  tubtty.c -- Linemode tty driver
5
 *
6
 *
7
 *
8
 *
9
 *
10
 *  Author:  Richard Hitt
11
 */
12
#include <linux/config.h>
13
#include "tubio.h"
14
 
15
/* Initialization & uninitialization for tubtty */
16
int tty3270_init(void);
17
void tty3270_fini(void);
18
 
19
/* Interface routines from the upper tty layer to the tty driver */
20
static int tty3270_open(struct tty_struct *, struct file *);
21
static void tty3270_close(struct tty_struct *, struct file *);
22
static int tty3270_write(struct tty_struct *, int,
23
        const unsigned char *, int);
24
static void tty3270_put_char(struct tty_struct *, unsigned char);
25
static void tty3270_flush_chars(struct tty_struct *);
26
static int tty3270_write_room(struct tty_struct *);
27
static int tty3270_chars_in_buffer(struct tty_struct *);
28
static int tty3270_ioctl(struct tty_struct *, struct file *,
29
        unsigned int cmd, unsigned long arg);
30
static void tty3270_set_termios(struct tty_struct *, struct termios *);
31
static void tty3270_hangup(struct tty_struct *);
32
static void tty3270_flush_buffer(struct tty_struct *);
33
static int tty3270_read_proc(char *, char **, off_t, int, int *, void *);
34
static int tty3270_write_proc(struct file *, const char *,
35
        unsigned long, void *);
36
 
37
/* tty3270 utility functions */
38
static void tty3270_bh(void *);
39
       void tty3270_sched_bh(tub_t *);
40
static int tty3270_wait(tub_t *, long *);
41
       void tty3270_int(tub_t *, devstat_t *);
42
       int tty3270_try_logging(tub_t *);
43
static void tty3270_start_input(tub_t *);
44
static void tty3270_do_input(tub_t *);
45
static void tty3270_do_enter(tub_t *, char *, int);
46
static void tty3270_do_showi(tub_t *, char *, int);
47
       int tty3270_io(tub_t *);
48
static int tty3270_show_tube(int, char *, int);
49
 
50
int tty3270_major = -1;
51
struct tty_driver tty3270_driver;
52
int tty3270_refcount;
53
struct tty_struct *tty3270_table[TUBMAXMINS];
54
struct termios *tty3270_termios[TUBMAXMINS];
55
struct termios *tty3270_termios_locked[TUBMAXMINS];
56
#ifdef CONFIG_TN3270_CONSOLE
57
int con3270_major = -1;
58
struct tty_driver con3270_driver;
59
int con3270_refcount;
60
struct tty_struct *con3270_table[1];
61
struct termios *con3270_termios[1];
62
struct termios *con3270_termios_locked[1];
63
#endif /* CONFIG_TN3270_CONSOLE */
64
 
65
int tty3270_proc_index;
66
int tty3270_proc_data;
67
int tty3270_proc_misc;
68
enum tubwhat tty3270_proc_what;
69
 
70
/*
71
 * tty3270_init() -- Register the tty3270 driver
72
 */
73
int
74
tty3270_init(void)
75
{
76
        struct tty_driver *td = &tty3270_driver;
77
        int rc;
78
 
79
        /* Initialize for tty driver */
80
        td->magic = TTY_DRIVER_MAGIC;
81
        td->driver_name = "tty3270";
82
        td->name = "tty3270";
83
        td->major = IBM_TTY3270_MAJOR;
84
        td->minor_start = 0;
85
        td->num = TUBMAXMINS;
86
        td->type = TTY_DRIVER_TYPE_SYSTEM;
87
        td->subtype = SYSTEM_TYPE_TTY;
88
        td->init_termios = tty_std_termios;
89
        td->flags = TTY_DRIVER_RESET_TERMIOS;
90
#ifdef CONFIG_DEVFS_FS
91
        td->flags |= TTY_DRIVER_NO_DEVFS;
92
#endif
93
        td->refcount = &tty3270_refcount;
94
        td->table = tty3270_table;
95
        td->termios = tty3270_termios;
96
        td->termios_locked = tty3270_termios_locked;
97
 
98
        td->open = tty3270_open;
99
        td->close = tty3270_close;
100
        td->write = tty3270_write;
101
        td->put_char = tty3270_put_char;
102
        td->flush_chars = tty3270_flush_chars;
103
        td->write_room = tty3270_write_room;
104
        td->chars_in_buffer = tty3270_chars_in_buffer;
105
        td->ioctl = tty3270_ioctl;
106
        td->ioctl = NULL;
107
        td->set_termios = tty3270_set_termios;
108
        td->throttle = NULL;
109
        td->unthrottle = NULL;
110
        td->stop = NULL;
111
        td->start = NULL;
112
        td->hangup = tty3270_hangup;
113
        td->break_ctl = NULL;
114
        td->flush_buffer = tty3270_flush_buffer;
115
        td->set_ldisc = NULL;
116
        td->wait_until_sent = NULL;
117
        td->send_xchar = NULL;
118
        td->read_proc = tty3270_read_proc;
119
        td->write_proc = tty3270_write_proc;
120
 
121
        rc = tty_register_driver(td);
122
        if (rc) {
123
                printk(KERN_ERR "tty3270 registration failed with %d\n", rc);
124
        } else {
125
                tty3270_major = IBM_TTY3270_MAJOR;
126
                if (td->proc_entry != NULL)
127
                        td->proc_entry->mode = S_IRUGO | S_IWUGO;
128
        }
129
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
130
#ifdef CONFIG_TN3270_CONSOLE
131
        if (CONSOLE_IS_3270) {
132
                tty3270_con_driver = *td;
133
                td = &tty3270_con_driver;
134
                td->driver_name = "con3270";
135
                td->name = "con3270";
136
                td->major = MAJOR(S390_CONSOLE_DEV);
137
                td->minor_start = MINOR(S390_CONSOLE_DEV);
138
                td->num = 1;
139
                td->refcount = &con3270_refcount;
140
                td->table = con3270_table;
141
                td->termios = con3270_termios;
142
                td->termios_locked = con3270_termios_locked;
143
 
144
                rc = tty_register_driver(td);
145
                if (rc) {
146
                        printk(KERN_ERR
147
                               "con3270 registration failed with %d\n", rc);
148
                } else {
149
                        con3270_major = MAJOR(S390_CONSOLE_DEV);
150
                        if (td->proc_entry != NULL)
151
                                td->proc_entry->mode = S_IRUGO | S_IWUGO;
152
                }
153
        }
154
#endif /* ifdef CONFIG_TN3270_CONSOLE */
155
#endif /* if LINUX_VERSION_CODE */
156
 
157
        return rc;
158
}
159
 
160
/*
161
 * tty3270_fini() -- Uninitialize linemode tubes
162
 */
163
void
164
tty3270_fini(void)
165
{
166
        if (tty3270_major != -1) {
167
                tty_unregister_driver(&tty3270_driver);
168
                tty3270_major = -1;
169
        }
170
#ifdef CONFIG_TN3270_CONSOLE
171
        if (CONSOLE_IS_3270 && con3270_major != -1) {
172
                tty_unregister_driver(&con3270_driver);
173
                con3270_major = -1;
174
        }
175
#endif
176
}
177
 
178
static int
179
tty3270_open(struct tty_struct *tty, struct file *filp)
180
{
181
        tub_t *tubp;
182
        long flags;
183
        int rc;
184
        int cmd;
185
 
186
        if ((tubp = TTY2TUB(tty)) == NULL) {
187
                return -ENODEV;
188
        }
189
 
190
        tub_inc_use_count();
191
        if ((rc = tty3270_wait(tubp, &flags)) != 0)
192
                goto do_fail;
193
        if (tubp->lnopen > 0) {
194
                tubp->lnopen++;
195
                TUBUNLOCK(tubp->irq, flags);
196
                return 0;
197
        }
198
        if (tubp->flags & TUB_OPEN_STET) {
199
                cmd = TBC_UPDLOG;
200
        } else {
201
                cmd = TBC_OPEN;
202
                tubp->flags &= ~TUB_SIZED;
203
        }
204
        if ((rc = tty3270_size(tubp, &flags)) != 0)
205
                goto do_fail;
206
        if ((rc = tty3270_rcl_init(tubp)) != 0)
207
                goto do_fail;
208
        if ((rc = tty3270_aid_init(tubp)) != 0)
209
                goto do_fail;
210
        if ((rc = tty3270_scl_init(tubp)) != 0)
211
                goto do_fail;
212
        tubp->mode = TBM_LN;
213
        tubp->intv = tty3270_int;
214
        tubp->tty = tty;
215
        tubp->lnopen = 1;
216
        tty->driver_data = tubp;
217
        tty->winsize.ws_row = tubp->geom_rows - 2;
218
        tty->winsize.ws_col = tubp->geom_cols;
219
        if (tubp->tty_input == NULL)
220
                tubp->tty_input = kmalloc(GEOM_INPLEN, GFP_KERNEL|GFP_DMA);
221
        tubp->tty_inattr = TF_INPUT;
222
        tubp->cmd = cmd;
223
        tty3270_build(tubp);
224
        TUBUNLOCK(tubp->irq, flags);
225
        return 0;
226
 
227
do_fail:
228
        tty3270_scl_fini(tubp);
229
        tty3270_aid_fini(tubp);
230
        tty3270_rcl_fini(tubp);
231
        TUBUNLOCK(tubp->irq, flags);
232
        tub_dec_use_count();
233
        return rc;
234
}
235
 
236
static void
237
tty3270_close(struct tty_struct *tty, struct file *filp)
238
{
239
        tub_t *tubp;
240
        long flags;
241
 
242
        if ((tubp = tty->driver_data) == NULL)
243
                return;
244
 
245
        tty3270_wait(tubp, &flags);
246
        if (--tubp->lnopen > 0)
247
                goto do_return;
248
        tubp->tty = NULL;
249
        tty->driver_data = NULL;
250
        tty3270_aid_fini(tubp);
251
        tty3270_rcl_fini(tubp);
252
        tty3270_scl_fini(tubp);
253
do_return:
254
        tub_dec_use_count();
255
        TUBUNLOCK(tubp->irq, flags);
256
}
257
 
258
static int
259
tty3270_write(struct tty_struct *tty, int fromuser,
260
                const unsigned char *buf, int count)
261
{
262
        tub_t *tubp;
263
        long flags;
264
        bcb_t obcb;
265
        int rc = 0;
266
 
267
        if ((tubp = tty->driver_data) == NULL)
268
                return -1;
269
 
270
#ifdef CONFIG_TN3270_CONSOLE
271
        if (CONSOLE_IS_3270 && tub3270_con_tubp == tubp)
272
                tub3270_con_copy(tubp);
273
#endif /* CONFIG_TN3270_CONSOLE */
274
 
275
        obcb.bc_buf = (char *)buf;
276
        obcb.bc_len = obcb.bc_cnt = obcb.bc_wr = count;
277
        obcb.bc_rd = 0;
278
 
279
        TUBLOCK(tubp->irq, flags);
280
        rc = tub3270_movedata(&obcb, &tubp->tty_bcb, fromuser);
281
        tty3270_try_logging(tubp);
282
        TUBUNLOCK(tubp->irq, flags);
283
        return rc;
284
}
285
 
286
static void
287
tty3270_put_char(struct tty_struct *tty, unsigned char ch)
288
{
289
        long flags;
290
        tub_t *tubp;
291
        bcb_t *ob;
292
 
293
        if ((tubp = tty->driver_data) == NULL)
294
                return;
295
 
296
        TUBLOCK(tubp->irq, flags);
297
        ob = &tubp->tty_bcb;
298
        if (ob->bc_cnt < ob->bc_len) {
299
                ob->bc_buf[ob->bc_wr++] = ch;
300
                if (ob->bc_wr == ob->bc_len)
301
                        ob->bc_wr = 0;
302
                ob->bc_cnt++;
303
        }
304
        tty3270_try_logging(tubp);
305
        TUBUNLOCK(tubp->irq, flags);
306
}
307
 
308
static void
309
tty3270_flush_chars(struct tty_struct *tty)
310
{
311
        tub_t *tubp;
312
        long flags;
313
 
314
        if ((tubp = tty->driver_data) == NULL)
315
                return;
316
 
317
        TUBLOCK(tubp->irq, flags);
318
        tty3270_try_logging(tubp);
319
        TUBUNLOCK(tubp->irq, flags);
320
}
321
 
322
static int
323
tty3270_write_room(struct tty_struct *tty)
324
{
325
        tub_t *tubp;
326
        bcb_t *ob;
327
 
328
        if ((tubp = tty->driver_data) == NULL)
329
                return -1;
330
 
331
        ob = &tubp->tty_bcb;
332
        return ob->bc_len - ob->bc_cnt;
333
}
334
 
335
static int
336
tty3270_chars_in_buffer(struct tty_struct *tty)
337
{
338
        tub_t *tubp;
339
        bcb_t *ob;
340
 
341
        if ((tubp = tty->driver_data) == NULL)
342
                return -1;
343
 
344
        ob = &tubp->tty_bcb;
345
        return ob->bc_cnt;
346
}
347
 
348
static int
349
tty3270_ioctl(struct tty_struct *tty, struct file *file,
350
                unsigned int cmd, unsigned long arg)
351
{
352
        tub_t *tubp;
353
        long flags;
354
        int ret = 0;
355
        struct termios termios;
356
 
357
        if ((tubp = tty->driver_data) == NULL)
358
                return -ENODEV;
359
 
360
        TUBLOCK(tubp->irq, flags);
361
        if (tty->flags * (1 << TTY_IO_ERROR)) {
362
                ret = -EIO;
363
                goto do_return;
364
        }
365
        switch(cmd) {
366
        case TCGETS:
367
                ret = -ENOIOCTLCMD;
368
                goto do_return;
369
        case TCFLSH:            /* arg:  2 or 0 */
370
                ret = -ENOIOCTLCMD;
371
                goto do_return;
372
        case TCSETSF:
373
                if (user_termios_to_kernel_termios(&termios,
374
                    (struct termios *)arg)) {
375
                        ret = -EFAULT;
376
                        goto do_return;
377
                }
378
                ret = -ENOIOCTLCMD;
379
                goto do_return;
380
        case TCGETA:
381
                ret = -ENOIOCTLCMD;
382
                goto do_return;
383
        case TCSETA:
384
                if (user_termio_to_kernel_termios(&termios,
385
                    (struct termio *)arg)) {
386
                        ret = -EFAULT;
387
                        goto do_return;
388
                }
389
                ret = -ENOIOCTLCMD;
390
                goto do_return;
391
        default:
392
                ret = -ENOIOCTLCMD;
393
                break;
394
        }
395
 
396
do_return:
397
        TUBUNLOCK(tubp->irq, flags);
398
        return ret;
399
}
400
 
401
static void
402
tty3270_set_termios(struct tty_struct *tty, struct termios *old)
403
{
404
        tub_t *tubp;
405
        long flags;
406
        int new;
407
 
408
        if ((tubp = tty->driver_data) == NULL)
409
                return;
410
 
411
        if (tty3270_wait(tubp, &flags) != 0) {
412
                TUBUNLOCK(tubp->irq, flags);
413
                return;
414
        }
415
        new = L_ICANON(tty)? L_ECHO(tty)? TF_INPUT: TF_INPUTN:
416
                tubp->tty_inattr;
417
        if (new != tubp->tty_inattr) {
418
                tubp->tty_inattr = new;
419
                tubp->cmd = TBC_CLRINPUT;
420
                tty3270_build(tubp);
421
        }
422
 
423
        TUBUNLOCK(tubp->irq, flags);
424
}
425
 
426
static void
427
tty3270_flush_buffer(struct tty_struct *tty)
428
{
429
        tub_t *tubp;
430
        bcb_t *ob;
431
        long flags;
432
 
433
        if ((tubp = tty->driver_data) == NULL)
434
                return;
435
 
436
        if (tubp->mode == TBM_FS && tubp->fs_pid != 0) {
437
                kill_proc(tubp->fs_pid, SIGHUP, 1);
438
        }
439
 
440
        if ((tubp->flags & TUB_OPEN_STET) == 0) {
441
                ob = &tubp->tty_bcb;
442
                TUBLOCK(tubp->irq, flags);
443
                ob->bc_rd = 0;
444
                ob->bc_wr = 0;
445
                ob->bc_cnt = 0;
446
                TUBUNLOCK(tubp->irq, flags);
447
        }
448
        wake_up_interruptible(&tty->write_wait);
449
        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
450
            tty->ldisc.write_wakeup)
451
                (tty->ldisc.write_wakeup)(tty);
452
}
453
 
454
static int
455
tty3270_read_proc(char *buf, char **start, off_t off, int count,
456
                int *eof, void *data)
457
{
458
        tub_t *tubp;
459
        int begin = 0;
460
        int i;
461
        int rc;
462
        int len = 0;
463
 
464
        if (tty3270_proc_what == TW_CONFIG) {
465
                /*
466
                 * Describe the 3270 configuration in ascii lines.
467
                 * Line 1:              0 <fsmajor> 0
468
                 * Console line:        <devnum> CONSOLE <minor>
469
                 * Other lines:         <devnum> <ttymajor> <minor>
470
                 */
471
                len += sprintf(buf + len, "0 %d 0\n", fs3270_major);
472
                for (i = 1; i <= tubnummins; i++) {
473
                        tubp = (*tubminors)[i];
474
#ifdef CONFIG_TN3270_CONSOLE
475
                        if (CONSOLE_IS_3270 && tubp == tub3270_con_tubp)
476
                                len += sprintf(buf + len, "%.4x CONSOLE %d\n",
477
                                               tubp->devno, i);
478
                        else
479
#endif
480
                                len += sprintf(buf + len, "%.4x %d %d\n",
481
                                               tubp->devno, tty3270_major, i);
482
                        if (begin + len > off + count)
483
                                break;
484
                        if (begin + len < off) {
485
                                begin += len;
486
                                len = 0;
487
                        }
488
                }
489
                if (i > tubnummins)
490
                        *eof = 1;
491
                if (off >= begin + len) {
492
                        rc = 0;
493
                } else {
494
                        *start = buf + off - begin;
495
                        rc = MIN(count, begin + len - off);
496
                }
497
                if (*eof && rc == 0)
498
                        tty3270_proc_what = TW_BOGUS;
499
                return rc;
500
        }
501
 
502
        len += sprintf(buf, "There are %d devices.  fs major is %d, "
503
                "tty major is %d.\n", tubnummins, fs3270_major,
504
                tty3270_major);
505
        len += sprintf(buf+len, "        index=%d data=%d misc=%d\n",
506
                tty3270_proc_index,
507
                tty3270_proc_data,
508
                tty3270_proc_misc);
509
 
510
        /*
511
         * Display info for the tube with minor nr in index
512
         */
513
        len += tty3270_show_tube(tty3270_proc_index, buf+len, count-len);
514
 
515
        *eof = 1;
516
        if (off >= begin + len)
517
                return 0;
518
        *start = buf + off - begin;
519
        return MIN(count, begin + len - off);
520
}
521
 
522
static int
523
tty3270_write_proc(struct file *file, const char *buffer,
524
                unsigned long count, void *data)
525
{
526
        char mybuf[GEOM_MAXINPLEN];
527
        int mycount;
528
        tub_t *tubp;
529
        struct tty_struct *tty;
530
        kdev_t device;
531
        int rc;
532
 
533
        mycount = MIN(count, sizeof mybuf - 1);
534
        if (copy_from_user(mybuf, buffer, mycount) != 0)
535
                return -EFAULT;
536
        mybuf[mycount] = '\0';
537
 
538
        /*
539
         * User-mode settings affect only the current tty ---
540
         */
541
        tubp = NULL;
542
        tty = current->tty;
543
        device = tty? tty->device: 0;
544
        if (device) {
545
                if (MAJOR(device) == IBM_TTY3270_MAJOR)
546
                        tubp = (*tubminors)[MINOR(device)];
547
#ifdef CONFIG_TN3270_CONSOLE
548
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0))
549
                if (CONSOLE_IS_3270 && device == S390_CONSOLE_DEV)
550
                        tubp = tub3270_con_tubp;
551
#endif /* LINUX_VERSION_CODE */
552
#endif /* CONFIG_TN3270_CONSOLE */
553
        }
554
        if (tubp) {
555
                if ((rc = tty3270_aid_set(tubp, mybuf, mycount + 1)))
556
                        return rc > 0? count: rc;
557
                if ((rc = tty3270_rcl_set(tubp, mybuf, mycount + 1)))
558
                        return rc > 0? count: rc;
559
                if ((rc = tty3270_scl_set(tubp, mybuf, mycount + 1)))
560
                        return rc > 0? count: rc;
561
        }
562
 
563
        /*
564
         * Superuser-mode settings affect the driver overall ---
565
         */
566
        if (!suser()) {
567
                return -EPERM;
568
        } else if (strncmp(mybuf, "index=", 6) == 0) {
569
                tty3270_proc_index = simple_strtoul(mybuf + 6, 0,0);
570
                return count;
571
        } else if (strncmp(mybuf, "data=", 5) == 0) {
572
                tty3270_proc_data = simple_strtoul(mybuf + 5, 0, 0);
573
                return count;
574
        } else if (strncmp(mybuf, "misc=", 5) == 0) {
575
                tty3270_proc_misc = simple_strtoul(mybuf + 5, 0, 0);
576
                return count;
577
        } else if (strncmp(mybuf, "what=", 5) == 0) {
578
                if (strcmp(mybuf+5, "bogus") == 0)
579
                        tty3270_proc_what = 0;
580
                else if (strncmp(mybuf+5, "config", 6) == 0)
581
                        tty3270_proc_what = TW_CONFIG;
582
                return count;
583
        } else {
584
                return -EINVAL;
585
        }
586
}
587
 
588
static void
589
tty3270_hangup(struct tty_struct *tty)
590
{
591
        tub_t *tubp;
592
        extern void fs3270_release(tub_t *);
593
 
594
        if ((tubp = tty->driver_data) == NULL)
595
                return;
596
        tty3270_rcl_purge(tubp);
597
        tty3270_aid_reinit(tubp);
598
        fs3270_release(tubp);
599
}
600
 
601
 
602
/*
603
 * tty3270_bh(tubp) -- Perform back-half processing
604
 */
605
static void
606
tty3270_bh(void *data)
607
{
608
        tub_t *tubp;
609
        ioinfo_t *ioinfop;
610
        long flags;
611
        struct tty_struct *tty;
612
 
613
        ioinfop = ioinfo[(tubp = data)->irq];
614
        while (TUBTRYLOCK(tubp->irq, flags) == 0) {
615
                if (ioinfop->ui.flags.unready == 1)
616
                        return;
617
        }
618
        if (ioinfop->ui.flags.unready == 1 ||
619
            ioinfop->ui.flags.ready == 0)
620
                goto do_unlock;
621
 
622
        tubp->flags &= ~TUB_BHPENDING;
623
        tty = tubp->tty;
624
 
625
        if (tubp->flags & TUB_UNSOL_DE) {
626
                tubp->flags &= ~TUB_UNSOL_DE;
627
                if (tty != NULL) {
628
                        tty_hangup(tty);
629
                        wake_up_interruptible(&tubp->waitq);
630
                        goto do_unlock;
631
                }
632
        }
633
 
634
        if (tubp->flags & TUB_IACTIVE) {        /* If read ended, */
635
                tty3270_do_input(tubp);
636
                tubp->flags &= ~TUB_IACTIVE;
637
        }
638
 
639
        if ((tubp->flags & TUB_WORKING) == 0) {
640
                if (tubp->flags & TUB_ATTN) {
641
                        tty3270_start_input(tubp);
642
                        tubp->flags &= ~TUB_ATTN;
643
                } else if (tty3270_try_logging(tubp) == 0) {
644
                        wake_up_interruptible(&tubp->waitq);
645
                }
646
        }
647
 
648
        if (tty != NULL) {
649
                if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
650
                    tty->ldisc.write_wakeup != NULL)
651
                        (tty->ldisc.write_wakeup)(tty);
652
                wake_up_interruptible(&tty->write_wait);
653
        }
654
do_unlock:
655
        TUBUNLOCK(tubp->irq, flags);
656
}
657
 
658
/*
659
 * tty3270_sched_bh(tubp) -- Schedule the back half
660
 * Irq lock must be held on entry and remains held on exit.
661
 */
662
void
663
tty3270_sched_bh(tub_t *tubp)
664
{
665
        if (tubp->flags & TUB_BHPENDING)
666
                return;
667
        tubp->flags |= TUB_BHPENDING;
668
        tubp->tqueue.routine = tty3270_bh;
669
        tubp->tqueue.data = tubp;
670
        queue_task(&tubp->tqueue, &tq_immediate);
671
        mark_bh(IMMEDIATE_BH);
672
}
673
 
674
/*
675
 * tty3270_io() -- Perform line-mode reads and writes here
676
 */
677
int
678
tty3270_io(tub_t *tubp)
679
{
680
        int rc;
681
        ccw1_t *ccwp;
682
 
683
        tubp->flags |= TUB_WORKING;
684
        tubp->dstat = 0;
685
        ccwp = &tubp->ttyccw;
686
 
687
        rc = do_IO(tubp->irq, ccwp, tubp->irq, 0, 0);
688
        return rc;
689
}
690
 
691
/*
692
 * tty3270_wait(tubp) -- Wait until TUB_WORKING is off
693
 * On entry the lock must not be held; on exit it is held.
694
 */
695
static int
696
tty3270_wait(tub_t *tubp, long *flags)
697
{
698
        DECLARE_WAITQUEUE(wait, current);
699
 
700
        TUBLOCK(tubp->irq, *flags);
701
        add_wait_queue(&tubp->waitq, &wait);
702
        while (!signal_pending(current) &&
703
            (tubp->flags & TUB_WORKING) != 0) {
704
                current->state = TASK_INTERRUPTIBLE;
705
                TUBUNLOCK(tubp->irq, *flags);
706
                schedule();
707
                current->state = TASK_RUNNING;
708
                TUBLOCK(tubp->irq, *flags);
709
        }
710
        remove_wait_queue(&tubp->waitq, &wait);
711
        return signal_pending(current)? -ERESTARTSYS: 0;
712
}
713
 
714
void
715
tty3270_int(tub_t *tubp, devstat_t *dsp)
716
{
717
#define DEV_UE_BUSY \
718
        (DEV_STAT_CHN_END | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP)
719
#define DEV_NOT_WORKING \
720
        (DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_CHECK)
721
 
722
        tubp->dstat = dsp->dstat;
723
 
724
        /* Handle CE-DE-UE and subsequent UDE */
725
        if (dsp->dstat == DEV_UE_BUSY) {
726
                tubp->flags |= TUB_UE_BUSY;
727
                return;
728
        } else if (tubp->flags & TUB_UE_BUSY) {
729
                tubp->flags &= ~TUB_UE_BUSY;
730
                if (dsp->dstat == DEV_STAT_DEV_END &&
731
                    (tubp->flags & TUB_WORKING) != 0) {
732
                        tty3270_io(tubp);
733
                        return;
734
                }
735
        }
736
 
737
        /* Handle ATTN */
738
        if (dsp->dstat & DEV_STAT_ATTENTION)
739
                tubp->flags |= TUB_ATTN;
740
 
741
        if (dsp->dstat & DEV_STAT_CHN_END) {
742
                tubp->cswl = dsp->rescnt;
743
                if ((dsp->dstat & DEV_STAT_DEV_END) == 0)
744
                        tubp->flags |= TUB_EXPECT_DE;
745
                else
746
                        tubp->flags &= ~TUB_EXPECT_DE;
747
        } else if (dsp->dstat & DEV_STAT_DEV_END) {
748
                if ((tubp->flags & TUB_EXPECT_DE) == 0)
749
                        tubp->flags |= TUB_UNSOL_DE;
750
                tubp->flags &= ~TUB_EXPECT_DE;
751
        }
752
        if (dsp->dstat & DEV_NOT_WORKING)
753
                tubp->flags &= ~TUB_WORKING;
754
        if (dsp->dstat & DEV_STAT_UNIT_CHECK)
755
                tubp->sense = dsp->ii.sense;
756
        if ((tubp->flags & TUB_WORKING) == 0)
757
                tty3270_sched_bh(tubp);
758
}
759
 
760
/*
761
 * tty3270_refresh(), called by fs3270_close() when tubp->fsopen == 0.
762
 * On entry, lock is held.
763
 */
764
void
765
tty3270_refresh(tub_t *tubp)
766
{
767
        if (tubp->lnopen) {
768
                tubp->mode = TBM_LN;
769
                tubp->intv = tty3270_int;
770
                tty3270_scl_resettimer(tubp);
771
                tubp->cmd = TBC_UPDATE;
772
                tty3270_build(tubp);
773
        }
774
}
775
 
776
int
777
tty3270_try_logging(tub_t *tubp)
778
{
779
        if (tubp->flags & TUB_WORKING)
780
                return 0;
781
        if (tubp->mode == TBM_FS)
782
                return 0;
783
        if (tubp->stat == TBS_HOLD)
784
                return 0;
785
        if (tubp->stat == TBS_MORE)
786
                return 0;
787
#ifdef CONFIG_TN3270_CONSOLE
788
        if (CONSOLE_IS_3270 && tub3270_con_tubp == tubp)
789
                tub3270_con_copy(tubp);
790
#endif /* CONFIG_TN3270_CONSOLE */
791
        if (tubp->tty_bcb.bc_cnt == 0)
792
                return 0;
793
        if (tubp->intv != tty3270_int)
794
                return 0;
795
        tubp->cmd = TBC_UPDLOG;
796
        return tty3270_build(tubp);
797
}
798
 
799
/* tty3270 utility functions */
800
 
801
static void
802
tty3270_start_input(tub_t *tubp)
803
{
804
        if (tubp->tty_input == NULL)
805
                return;
806
        tubp->ttyccw.cda = virt_to_phys(tubp->tty_input);
807
        tubp->ttyccw.cmd_code = TC_READMOD;
808
        tubp->ttyccw.count = GEOM_INPLEN;
809
        tubp->ttyccw.flags = CCW_FLAG_SLI;
810
        tty3270_io(tubp);
811
        tubp->flags |= TUB_IACTIVE;
812
}
813
 
814
static void
815
tty3270_do_input(tub_t *tubp)
816
{
817
        int count;
818
        char *in;
819
        int aidflags;
820
        char *aidstring;
821
 
822
        count = GEOM_INPLEN - tubp->cswl;
823
        if ((in = tubp->tty_input) == NULL)
824
                goto do_build;
825
        tty3270_aid_get(tubp, in[0], &aidflags, &aidstring);
826
 
827
        if (aidflags & TA_CLEARKEY) {
828
                tubp->stat = TBS_RUNNING;
829
                tty3270_scl_resettimer(tubp);
830
                tubp->cmd = TBC_UPDATE;
831
        } else if (aidflags & TA_CLEARLOG) {
832
                tubp->stat = TBS_RUNNING;
833
                tty3270_scl_resettimer(tubp);
834
                tubp->cmd = TBC_CLRUPDLOG;
835
        } else if (aidflags & TA_DOENTER) {
836
                if (count <= 6) {
837
                        switch(tubp->stat) {
838
                        case TBS_MORE:
839
                                tubp->stat = TBS_HOLD;
840
                                tty3270_scl_resettimer(tubp);
841
                                break;
842
                        case TBS_HOLD:
843
                                tubp->stat = TBS_MORE;
844
                                tty3270_scl_settimer(tubp);
845
                                break;
846
                        case TBS_RUNNING:
847
                                tty3270_do_enter(tubp, in + 6, 0);
848
                                break;
849
                        }
850
                        tubp->cmd = TBC_UPDSTAT;
851
                        goto do_build;
852
                }
853
                in += 6;
854
                count -= 6;
855
                TUB_EBCASC(in, count);
856
                tubp->cmd = TBC_CLRINPUT;
857
                tty3270_do_enter(tubp, in, count);
858
        } else if ((aidflags & TA_DOSTRING) != 0 && aidstring != NULL) {
859
                tubp->cmd = TBC_KRUPDLOG;
860
                tty3270_do_enter(tubp, aidstring, strlen(aidstring));
861
        } else if ((aidflags & TA_DOSTRINGD) != 0 && aidstring != NULL) {
862
                tty3270_do_showi(tubp, aidstring, strlen(aidstring));
863
                tubp->cmd = TBC_UPDINPUT;
864
        } else {
865
                if (in[0] != 0x60)
866
                        tubp->flags |= TUB_ALARM;
867
                tubp->cmd = TBC_KRUPDLOG;
868
        }
869
do_build:
870
        tty3270_build(tubp);
871
}
872
 
873
static void
874
tty3270_do_enter(tub_t *tubp, char *cp, int count)
875
{
876
        struct tty_struct *tty;
877
        int func = -1;
878
 
879
        if ((tty = tubp->tty) == NULL)
880
                return;
881
        if (count < 0)
882
                return;
883
        if (count == 2 && (cp[0] == '^' || cp[0] == '\252')) {
884
                switch(cp[1]) {
885
                case 'c':  case 'C':
886
                        func = INTR_CHAR(tty);
887
                        break;
888
                case 'd':  case 'D':
889
                        func = EOF_CHAR(tty);
890
                        break;
891
                case 'z':  case 'Z':
892
                        func = SUSP_CHAR(tty);
893
                        break;
894
                }
895
        } else if (count == 2 && cp[0] == 0x1b) {        /* if ESC */
896
                int inc = 0;
897
                char buf[GEOM_INPLEN + 1];
898
                int len;
899
 
900
                switch(cp[1]) {
901
                case 'k':  case 'K':
902
                        inc = -1;
903
                        break;
904
                case 'j':  case 'J':
905
                        inc = 1;
906
                        break;
907
                }
908
                if (inc == 0)
909
                        goto not_rcl;
910
                len = tty3270_rcl_get(tubp, buf, sizeof buf, inc);
911
                if (len == 0) {
912
                        tubp->flags |= TUB_ALARM;
913
                        return;
914
                }
915
                tty3270_do_showi(tubp, buf, len);
916
                tubp->cmd = TBC_UPDINPUT;
917
                return;
918
        }
919
not_rcl:
920
        if (func != -1) {
921
                *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
922
                *tty->flip.char_buf_ptr++ = func;
923
                tty->flip.count++;
924
        } else {
925
                tty3270_rcl_put(tubp, cp, count);
926
                memcpy(tty->flip.char_buf_ptr, cp, count);
927
                /* Add newline unless line ends with "^n" */
928
                if (count < 2 || cp[count - 1] != 'n' ||
929
                    (cp[count - 2] != '^' && cp[count - 2] != '\252')) {
930
                        tty->flip.char_buf_ptr[count] = '\n';
931
                        count++;
932
                } else {
933
                        count -= 2;     /* Lop trailing "^n" from text */
934
                }
935
                memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count);
936
                tty->flip.char_buf_ptr += count;
937
                tty->flip.flag_buf_ptr += count;
938
                tty->flip.count += count;
939
        }
940
        tty_flip_buffer_push(tty);
941
}
942
 
943
static void
944
tty3270_do_showi(tub_t *tubp, char *cp, int cl)
945
{
946
        if (cl > GEOM_INPLEN)
947
                cl = GEOM_INPLEN;
948
        memset(tubp->tty_input, 0, GEOM_INPLEN);
949
        memcpy(tubp->tty_input, cp, cl);
950
        TUB_ASCEBC(tubp->tty_input, cl);
951
}
952
 
953
 
954
 
955
/* Debugging routine */
956
static int
957
tty3270_show_tube(int minor, char *buf, int count)
958
{
959
        tub_t *tubp;
960
        struct tty_struct *tty;
961
        struct termios *mp;
962
        int len;
963
 
964
/*012345678901234567890123456789012345678901234567890123456789       */
965
/*Info for tub_t[dd] at xxxxxxxx:                                    */
966
/*    geom:  rows=dd cols=dd model=d                                 */
967
/*    lnopen=dd     fsopen=dd   waitq=xxxxxxxx                       */
968
/*    dstat=xx      mode=dd     stat=dd     flags=xxxx               */
969
/*    oucount=dddd  ourd=ddddd  ouwr=ddddd  nextlogx=ddddd           */
970
/*    tty=xxxxxxxx                                                   */
971
/*    write_wait=xxxxxxxx read_wait=xxxxxxxx                         */
972
/*    iflag=xxxxxxxx oflag=xxxxxxxx cflag=xxxxxxxx lflag=xxxxxxxx    */
973
 
974
        if (minor < 0 || minor > tubnummins ||
975
            (tubp = (*tubminors)[minor]) == NULL)
976
                return sprintf(buf, "No tube at index=%d\n", minor);
977
 
978
        tty = tubp->tty;
979
        len = 0;
980
 
981
        len += sprintf(buf+len, "Info for tub_t[%d] at %p:\n", minor, tubp);
982
 
983
        len += sprintf(buf+len, "inattr is at %p\n", &tubp->tty_inattr);
984
 
985
 
986
        len += sprintf(buf+len, "    geom:  rows=%.2d cols=%.2d model=%.1d\n",
987
                       tubp->geom_rows, tubp->geom_cols, tubp->tubiocb.model);
988
 
989
        len += sprintf(buf+len,
990
                       "    lnopen=%-2d     fsopen=%-2d   waitq=%p\n",
991
                       tubp->lnopen, tubp->fsopen, &tubp->waitq);
992
 
993
        len += sprintf(buf+len, "    dstat=%.2x      mode=%-2d     "
994
                       "stat=%-2d     flags=%-4x\n", tubp->dstat,
995
                       tubp->mode, tubp->stat, tubp->flags);
996
 
997
#ifdef RBH_FIXTHIS
998
        len += sprintf(buf+len,
999
                       "    oucount=%-4d  ourd=%-5d  ouwr=%-5d"
1000
                       "  nextlogx=%-5d\n", tubp->tty_oucount,
1001
                       tubp->tty_ourd, tubp->tty_ouwr, tubp->tty_nextlogx);
1002
#endif
1003
 
1004
        len += sprintf(buf+len, "    tty=%p\n",tubp->tty);
1005
 
1006
        if (tty)
1007
                len += sprintf(buf+len,
1008
                                "    write_wait=%p read_wait=%p\n",
1009
                                &tty->write_wait, &tty->read_wait);
1010
 
1011
        if (tty && ((mp = tty->termios)))
1012
                len += sprintf(buf+len,"    iflag=%.8x oflag=%.8x "
1013
                               "cflag=%.8x lflag=%.8x\n", mp->c_iflag,
1014
                               mp->c_oflag, mp->c_cflag, mp->c_lflag);
1015
 
1016
 
1017
        return len;
1018
}

powered by: WebSVN 2.1.0

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