📄 tubtty.c
字号:
tty3270_proc_index, tty3270_proc_data, tty3270_proc_misc); /* * Display info for the tube with minor nr in index */ len += tty3270_show_tube(tty3270_proc_index, buf+len, count-len); *eof = 1; if (off >= begin + len) return 0; *start = buf + off - begin; return MIN(count, begin + len - off);}static inttty3270_write_proc(struct file *file, const char *buffer, unsigned long count, void *data){ char mybuf[GEOM_MAXINPLEN]; int mycount; tub_t *tubp; struct tty_struct *tty; kdev_t device; int rc; mycount = MIN(count, sizeof mybuf - 1); if (copy_from_user(mybuf, buffer, mycount) != 0) return -EFAULT; mybuf[mycount] = '\0'; /* * User-mode settings affect only the current tty --- */ tubp = NULL; tty = current->tty; device = tty? tty->device: 0; if (device) { if (MAJOR(device) == IBM_TTY3270_MAJOR) tubp = (*tubminors)[MINOR(device)];#ifdef CONFIG_TN3270_CONSOLE#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)) if (CONSOLE_IS_3270 && device == S390_CONSOLE_DEV) tubp = tub3270_con_tubp;#endif /* LINUX_VERSION_CODE */#endif /* CONFIG_TN3270_CONSOLE */ } if (tubp) { if ((rc = tty3270_aid_set(tubp, mybuf, mycount + 1))) return rc > 0? count: rc; if ((rc = tty3270_rcl_set(tubp, mybuf, mycount + 1))) return rc > 0? count: rc; if ((rc = tty3270_scl_set(tubp, mybuf, mycount + 1))) return rc > 0? count: rc; } /* * Superuser-mode settings affect the driver overall --- */ if (!suser()) { return -EPERM; } else if (strncmp(mybuf, "index=", 6) == 0) { tty3270_proc_index = simple_strtoul(mybuf + 6, 0,0); return count; } else if (strncmp(mybuf, "data=", 5) == 0) { tty3270_proc_data = simple_strtoul(mybuf + 5, 0, 0); return count; } else if (strncmp(mybuf, "misc=", 5) == 0) { tty3270_proc_misc = simple_strtoul(mybuf + 5, 0, 0); return count; } else if (strncmp(mybuf, "what=", 5) == 0) { if (strcmp(mybuf+5, "bogus") == 0) tty3270_proc_what = 0; else if (strncmp(mybuf+5, "config", 6) == 0) tty3270_proc_what = TW_CONFIG; return count; } else { return -EINVAL; }}static voidtty3270_hangup(struct tty_struct *tty){ tub_t *tubp; extern void fs3270_release(tub_t *); if ((tubp = tty->driver_data) == NULL) return; tty3270_rcl_purge(tubp); tty3270_aid_reinit(tubp); fs3270_release(tubp);}/* * tty3270_bh(tubp) -- Perform back-half processing */static voidtty3270_bh(void *data){ long flags; tub_t *tubp; struct tty_struct *tty; tubp = data; TUBLOCK(tubp->irq, flags); tubp->flags &= ~TUB_BHPENDING; tty = tubp->tty; if (tubp->flags & TUB_UNSOL_DE) { tubp->flags &= ~TUB_UNSOL_DE; if (tty != NULL) { tty_hangup(tty); wake_up_interruptible(&tubp->waitq); goto do_unlock; } } if (tubp->flags & TUB_IACTIVE) { /* If read ended, */ tty3270_do_input(tubp); tubp->flags &= ~TUB_IACTIVE; } if ((tubp->flags & TUB_WORKING) == 0) { if (tubp->flags & TUB_ATTN) { tty3270_start_input(tubp); tubp->flags &= ~TUB_ATTN; } else if (tty3270_try_logging(tubp) == 0) { wake_up_interruptible(&tubp->waitq); } } if (tty != NULL) { if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup != NULL) (tty->ldisc.write_wakeup)(tty); wake_up_interruptible(&tty->write_wait); }do_unlock: TUBUNLOCK(tubp->irq, flags);}/* * tty3270_sched_bh(tubp) -- Schedule the back half * Irq lock must be held on entry and remains held on exit. */voidtty3270_sched_bh(tub_t *tubp){ if (tubp->flags & TUB_BHPENDING) return; tubp->flags |= TUB_BHPENDING; tubp->tqueue.routine = tty3270_bh; tubp->tqueue.data = tubp; queue_task(&tubp->tqueue, &tq_immediate); mark_bh(IMMEDIATE_BH);}/* * tty3270_io() -- Perform line-mode reads and writes here */int tty3270_io(tub_t *tubp){ int rc; ccw1_t *ccwp; tubp->flags |= TUB_WORKING; tubp->dstat = 0; ccwp = &tubp->ttyccw; rc = do_IO(tubp->irq, ccwp, tubp->irq, 0, 0); return rc;}/* * tty3270_wait(tubp) -- Wait until TUB_WORKING is off * On entry the lock must not be held; on exit it is held. */static inttty3270_wait(tub_t *tubp, long *flags){ DECLARE_WAITQUEUE(wait, current); TUBLOCK(tubp->irq, *flags); add_wait_queue(&tubp->waitq, &wait); while (!signal_pending(current) && (tubp->flags & TUB_WORKING) != 0) { current->state = TASK_INTERRUPTIBLE; TUBUNLOCK(tubp->irq, *flags); schedule(); current->state = TASK_RUNNING; TUBLOCK(tubp->irq, *flags); } remove_wait_queue(&tubp->waitq, &wait); return signal_pending(current)? -ERESTARTSYS: 0;}voidtty3270_int(tub_t *tubp, devstat_t *dsp){#define DEV_UE_BUSY \ (DEV_STAT_CHN_END | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP)#define DEV_NOT_WORKING \ (DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_CHECK) tubp->dstat = dsp->dstat; /* Handle CE-DE-UE and subsequent UDE */ if (dsp->dstat == DEV_UE_BUSY) { tubp->flags |= TUB_UE_BUSY; return; } else if (tubp->flags & TUB_UE_BUSY) { tubp->flags &= ~TUB_UE_BUSY; if (dsp->dstat == DEV_STAT_DEV_END && (tubp->flags & TUB_WORKING) != 0) { tty3270_io(tubp); return; } } /* Handle ATTN */ if (dsp->dstat & DEV_STAT_ATTENTION) tubp->flags |= TUB_ATTN; if (dsp->dstat & DEV_STAT_CHN_END) { tubp->cswl = dsp->rescnt; if ((dsp->dstat & DEV_STAT_DEV_END) == 0) tubp->flags |= TUB_EXPECT_DE; else tubp->flags &= ~TUB_EXPECT_DE; } else if (dsp->dstat & DEV_STAT_DEV_END) { if ((tubp->flags & TUB_EXPECT_DE) == 0) tubp->flags |= TUB_UNSOL_DE; tubp->flags &= ~TUB_EXPECT_DE; } if (dsp->dstat & DEV_NOT_WORKING) tubp->flags &= ~TUB_WORKING; if (dsp->dstat & DEV_STAT_UNIT_CHECK) tubp->sense = dsp->ii.sense; if ((tubp->flags & TUB_WORKING) == 0) tty3270_sched_bh(tubp);}/* * tty3270_refresh(), called by fs3270_close() when tubp->fsopen == 0. * On entry, lock is held. */voidtty3270_refresh(tub_t *tubp){ if (tubp->lnopen) { tubp->mode = TBM_LN; tubp->intv = tty3270_int; tty3270_scl_resettimer(tubp); tubp->cmd = TBC_UPDATE; tty3270_build(tubp); }}inttty3270_try_logging(tub_t *tubp){ if (tubp->flags & TUB_WORKING) return 0; if (tubp->mode == TBM_FS) return 0; if (tubp->stat == TBS_HOLD) return 0; if (tubp->stat == TBS_MORE) return 0;#ifdef CONFIG_TN3270_CONSOLE if (CONSOLE_IS_3270 && tub3270_con_tubp == tubp) tub3270_con_copy(tubp);#endif /* CONFIG_TN3270_CONSOLE */ if (tubp->tty_bcb.bc_cnt == 0) return 0; if (tubp->intv != tty3270_int) return 0; tubp->cmd = TBC_UPDLOG; return tty3270_build(tubp);}/* tty3270 utility functions */static voidtty3270_start_input(tub_t *tubp){ tubp->ttyccw.cda = virt_to_phys(&tubp->tty_input); tubp->ttyccw.cmd_code = TC_READMOD; tubp->ttyccw.count = GEOM_INPLEN; tubp->ttyccw.flags = CCW_FLAG_SLI; tty3270_io(tubp); tubp->flags |= TUB_IACTIVE;}static voidtty3270_do_input(tub_t *tubp){ int count; char *in; int aidflags; char *aidstring; count = GEOM_INPLEN - tubp->cswl; in = tubp->tty_input; tty3270_aid_get(tubp, in[0], &aidflags, &aidstring); if (aidflags & TA_CLEARKEY) { tubp->stat = TBS_RUNNING; tty3270_scl_resettimer(tubp); tubp->cmd = TBC_UPDATE; } else if (aidflags & TA_CLEARLOG) { tubp->stat = TBS_RUNNING; tty3270_scl_resettimer(tubp); tubp->cmd = TBC_CLRUPDLOG; } else if (aidflags & TA_DOENTER) { if (count <= 6) { switch(tubp->stat) { case TBS_MORE: tubp->stat = TBS_HOLD; tty3270_scl_resettimer(tubp); break; case TBS_HOLD: tubp->stat = TBS_MORE; tty3270_scl_settimer(tubp); break; case TBS_RUNNING: tty3270_do_enter(tubp, in + 6, 0); break; } tubp->cmd = TBC_UPDSTAT; goto do_build; } in += 6; count -= 6; TUB_EBCASC(in, count); tubp->cmd = TBC_CLRINPUT; tty3270_do_enter(tubp, in, count); } else if ((aidflags & TA_DOSTRING) != 0 && aidstring != NULL) { tubp->cmd = TBC_KRUPDLOG; tty3270_do_enter(tubp, aidstring, strlen(aidstring)); } else if ((aidflags & TA_DOSTRINGD) != 0 && aidstring != NULL) { tty3270_do_showi(tubp, aidstring, strlen(aidstring)); tubp->cmd = TBC_UPDINPUT; } else { if (in[0] != 0x60) tubp->flags |= TUB_ALARM; tubp->cmd = TBC_KRUPDLOG; }do_build: tty3270_build(tubp);}static voidtty3270_do_enter(tub_t *tubp, char *cp, int count){ struct tty_struct *tty; int func = -1; if ((tty = tubp->tty) == NULL) return; if (count < 0) return; if (count == 2 && (cp[0] == '^' || cp[0] == '\252')) { switch(cp[1]) { case 'c': case 'C': func = INTR_CHAR(tty); break; case 'd': case 'D': func = EOF_CHAR(tty); break; case 'z': case 'Z': func = SUSP_CHAR(tty); break; } } else if (count == 2 && cp[0] == 0x1b) { /* if ESC */ int inc = 0; char buf[GEOM_INPLEN + 1]; int len; switch(cp[1]) { case 'k': case 'K': inc = -1; break; case 'j': case 'J': inc = 1; break; } if (inc == 0) goto not_rcl; len = tty3270_rcl_get(tubp, buf, sizeof buf, inc); if (len == 0) { tubp->flags |= TUB_ALARM; return; } tty3270_do_showi(tubp, buf, len); tubp->cmd = TBC_UPDINPUT; return; }not_rcl: if (func != -1) { *tty->flip.flag_buf_ptr++ = TTY_NORMAL; *tty->flip.char_buf_ptr++ = func; tty->flip.count++; } else { tty3270_rcl_put(tubp, cp, count); memcpy(tty->flip.char_buf_ptr, cp, count); /* Add newline unless line ends with "^n" */ if (count < 2 || cp[count - 1] != 'n' || (cp[count - 2] != '^' && cp[count - 2] != '\252')) { tty->flip.char_buf_ptr[count] = '\n'; count++; } else { count -= 2; /* Lop trailing "^n" from text */ } memset(tty->flip.flag_buf_ptr, TTY_NORMAL, count); tty->flip.char_buf_ptr += count; tty->flip.flag_buf_ptr += count; tty->flip.count += count; } tty_flip_buffer_push(tty);}static voidtty3270_do_showi(tub_t *tubp, char *cp, int cl){ if (cl > GEOM_INPLEN) cl = GEOM_INPLEN; memset(tubp->tty_input, 0, GEOM_INPLEN); memcpy(tubp->tty_input, cp, cl); TUB_ASCEBC(tubp->tty_input, cl);}/* Debugging routine */static inttty3270_show_tube(int minor, char *buf, int count){ tub_t *tubp; struct tty_struct *tty; struct termios *mp; int len;/*012345678901234567890123456789012345678901234567890123456789 *//*Info for tub_t[dd] at xxxxxxxx: *//* geom: rows=dd cols=dd model=d *//* lnopen=dd fsopen=dd waitq=xxxxxxxx *//* dstat=xx mode=dd stat=dd flags=xxxx *//* oucount=dddd ourd=ddddd ouwr=ddddd nextlogx=ddddd *//* tty=xxxxxxxx *//* write_wait=xxxxxxxx read_wait=xxxxxxxx *//* iflag=xxxxxxxx oflag=xxxxxxxx cflag=xxxxxxxx lflag=xxxxxxxx */ if (minor < 0 || minor > tubnummins || (tubp = (*tubminors)[minor]) == NULL) return sprintf(buf, "No tube at index=%d\n", minor); tty = tubp->tty; len = 0; len += sprintf(buf+len, "Info for tub_t[%d] at %p:\n", minor, tubp); len += sprintf(buf+len, "inattr is at %p\n", &tubp->tty_inattr); len += sprintf(buf+len, " geom: rows=%.2d cols=%.2d model=%.1d\n", tubp->geom_rows, tubp->geom_cols, tubp->tubiocb.model); len += sprintf(buf+len, " lnopen=%-2d fsopen=%-2d waitq=%p\n", tubp->lnopen, tubp->fsopen, &tubp->waitq); len += sprintf(buf+len, " dstat=%.2x mode=%-2d " "stat=%-2d flags=%-4x\n", tubp->dstat, tubp->mode, tubp->stat, tubp->flags);#ifdef RBH_FIXTHIS len += sprintf(buf+len, " oucount=%-4d ourd=%-5d ouwr=%-5d" " nextlogx=%-5d\n", tubp->tty_oucount, tubp->tty_ourd, tubp->tty_ouwr, tubp->tty_nextlogx);#endif len += sprintf(buf+len, " tty=%p\n",tubp->tty); if (tty) len += sprintf(buf+len, " write_wait=%p read_wait=%p\n", &tty->write_wait, &tty->read_wait); if (tty && ((mp = tty->termios))) len += sprintf(buf+len," iflag=%.8x oflag=%.8x " "cflag=%.8x lflag=%.8x\n", mp->c_iflag, mp->c_oflag, mp->c_cflag, mp->c_lflag); return len;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -