📄 riotty.c
字号:
return -EIO; } if ( p->RIOHalted ) { RIOClearUp( PortP ); rio_spin_unlock_irqrestore(&PortP->portSem, flags); return -EIO; } /* ** Count ioctls for port statistics reporting */ if (PortP->statsGather) PortP->ioctls++; /* ** Specialix RIO Ioctl calls */ switch (cmd) { case TCRIOTRIAD: if ( arg ) PortP->State |= RIO_TRIAD_MODE; else PortP->State &= ~RIO_TRIAD_MODE; /* ** Normally, when istrip is set on a port, a config is ** sent to the RTA instructing the CD1400 to do the ** stripping. In TRIAD mode, the interrupt receive routine ** must do the stripping instead, since it has to detect ** an 8 bit function key sequence. If istrip is set with ** TRIAD mode on(off), and 8 bit data is being read by ** the port, the user then turns TRIAD mode off(on), the RTA ** must be reconfigured (not) to do the stripping. ** Hence we call RIOParam here. */ rio_spin_unlock_irqrestore(&PortP->portSem, flags); RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); return 0; case TCRIOTSTATE: rio_dprintk (RIO_DEBUG_TTY, "tbusy/tstop monitoring %sabled\n", arg ? "en" : "dis"); /* MonitorTstate = 0 ;*/ rio_spin_unlock_irqrestore(&PortP->portSem, flags); RIOParam(PortP, CONFIG, Modem, OK_TO_SLEEP); return 0; case TCRIOSTATE: /* current state of Modem input pins */ rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE\n"); if (RIOPreemptiveCmd(p, PortP, MGET) == RIO_FAIL) rio_dprintk (RIO_DEBUG_TTY, "TCRIOSTATE command failed\n"); PortP->State |= RIO_BUSY; current = PortP->ModemState; if ( copyout((caddr_t)¤t, (int)arg, sizeof(current))==COPYFAIL ) { rio_dprintk (RIO_DEBUG_TTY, "Copyout failed\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EFAULT); } rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOMBIS: /* Set modem lines */ case TCRIOMBIC: /* Clear modem lines */ rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIS/TCRIOMBIC\n"); if (cmd == TCRIOMBIS) { uint state; state = (uint)arg; PortP->ModemState |= (ushort)state; PortP->ModemLines = (ulong) arg; if (RIOPreemptiveCmd(p, PortP, MBIS) == RIO_FAIL) rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIS command failed\n"); } else { uint state; state = (uint)arg; PortP->ModemState &= ~(ushort)state; PortP->ModemLines = (ulong) arg; if (RIOPreemptiveCmd(p, PortP, MBIC) == RIO_FAIL) rio_dprintk (RIO_DEBUG_TTY, "TCRIOMBIC command failed\n"); } PortP->State |= RIO_BUSY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOXPON: /* set Xprint ON string */ rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPON\n"); if ( copyin((int)arg, (caddr_t)PortP->Xprint.XpOn, MAX_XP_CTRL_LEN)==COPYFAIL ) { rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n"); PortP->Xprint.XpOn[0] = '\0'; rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EFAULT); } PortP->Xprint.XpOn[MAX_XP_CTRL_LEN-1] = '\0'; PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+ strlen(PortP->Xprint.XpOff); rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOXPOFF: /* set Xprint OFF string */ rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPOFF\n"); if ( copyin( (int)arg, (caddr_t)PortP->Xprint.XpOff, MAX_XP_CTRL_LEN)==COPYFAIL ) { rio_dprintk (RIO_DEBUG_TTY, "Copyin failed\n"); PortP->Xprint.XpOff[0] = '\0'; rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EFAULT); } PortP->Xprint.XpOff[MAX_XP_CTRL_LEN-1] = '\0'; PortP->Xprint.XpLen = strlen(PortP->Xprint.XpOn)+ strlen(PortP->Xprint.XpOff); rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOXPCPS: /* set Xprint CPS string */ rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPCPS\n"); if ( (uint)arg > p->RIOConf.MaxXpCps || (uint)arg < p->RIOConf.MinXpCps ) { rio_dprintk (RIO_DEBUG_TTY, "%d CPS out of range\n",arg); rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EINVAL); return 0; } PortP->Xprint.XpCps = (uint)arg; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOXPRINT: rio_dprintk (RIO_DEBUG_TTY, "TCRIOXPRINT\n"); if ( copyout((caddr_t)&PortP->Xprint, (int)arg, sizeof(struct Xprint))==COPYFAIL ) { rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EFAULT); } rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOIXANYON: rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYON\n"); PortP->Config |= RIO_IXANY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOIXANYOFF: rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXANYOFF\n"); PortP->Config &= ~RIO_IXANY; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOIXONON: rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONON\n"); PortP->Config |= RIO_IXON; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0; case TCRIOIXONOFF: rio_dprintk (RIO_DEBUG_TTY, "TCRIOIXONOFF\n"); PortP->Config &= ~RIO_IXON; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0;/*** 15.10.1998 ARG - ESIL 0761 part fix** Added support for CTS and RTS flow control ioctls :*/ case TCRIOCTSFLOWEN: rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWEN\n"); PortP->Config |= RIO_CTSFLOW; rio_spin_unlock_irqrestore(&PortP->portSem, flags); RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); return 0; case TCRIOCTSFLOWDIS: rio_dprintk (RIO_DEBUG_TTY, "TCRIOCTSFLOWDIS\n"); PortP->Config &= ~RIO_CTSFLOW; rio_spin_unlock_irqrestore(&PortP->portSem, flags); RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); return 0; case TCRIORTSFLOWEN: rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWEN\n"); PortP->Config |= RIO_RTSFLOW; rio_spin_unlock_irqrestore(&PortP->portSem, flags); RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); return 0; case TCRIORTSFLOWDIS: rio_dprintk (RIO_DEBUG_TTY, "TCRIORTSFLOWDIS\n"); PortP->Config &= ~RIO_RTSFLOW; rio_spin_unlock_irqrestore(&PortP->portSem, flags); RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); return 0;/* end ESIL 0761 part fix */ } /* Lynx IOCTLS */ switch (cmd) { case TIOCSETP: case TIOCSETN: case OTIOCSETP: case OTIOCSETN: ioctl_processed++; ttyseth(PortP, tp, (struct old_sgttyb *)arg); break; case TCSETA: case TCSETAW: case TCSETAF: ioctl_processed++; rio_dprintk (RIO_DEBUG_TTY, "NON POSIX ioctl\n"); ttyseth_pv(PortP, tp, (struct termios *)arg, 0); break; case TCSETAP: /* posix tcsetattr() */ case TCSETAWP: /* posix tcsetattr() */ case TCSETAFP: /* posix tcsetattr() */ rio_dprintk (RIO_DEBUG_TTY, "NON POSIX SYSV ioctl\n"); ttyseth_pv(PortP, tp, (struct termios *)arg, 1); ioctl_processed++; break; } /* ** If its any of the commands that require the port to be in the ** non-busy state wait until all output has drained */ if (!ioctl_processed) switch(cmd) { case TCSETAW: case TCSETAF: case TCSETA: case TCSBRK:#define OLD_POSIX ('x' << 8)#define OLD_POSIX_SETA (OLD_POSIX | 2)#define OLD_POSIX_SETAW (OLD_POSIX | 3)#define OLD_POSIX_SETAF (OLD_POSIX | 4)#define NEW_POSIX (('i' << 24) | ('X' << 16))#define NEW_POSIX_SETA (NEW_POSIX | 2)#define NEW_POSIX_SETAW (NEW_POSIX | 3)#define NEW_POSIX_SETAF (NEW_POSIX | 4) case OLD_POSIX_SETA: case OLD_POSIX_SETAW: case OLD_POSIX_SETAF: case NEW_POSIX_SETA: case NEW_POSIX_SETAW: case NEW_POSIX_SETAF:#ifdef TIOCSETP case TIOCSETP:#endif case TIOCSETD: case TIOCSETN: rio_dprintk (RIO_DEBUG_TTY, "wait for non-BUSY, semaphore set\n"); /* ** Wait for drain here, at least as far as the double buffer ** being empty. */ /* XXX Does the above comment mean that this has still to be implemented? -- REW */ /* XXX Is the locking OK together with locking in txenable? (Deadlock?) -- REW */ RIOTxEnable((char *)PortP); break; default: break; } old_cflag = tp->tm.c_cflag; old_iflag = tp->tm.c_iflag; old_oflag = tp->tm.c_oflag; oldcook = PortP->CookMode; if ( p->RIOHalted ) { RIOClearUp( PortP ); rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EIO); return 0; } PortP->FlushCmdBodge = 0; /* ** If the port is locked, and it is reconfigured, we want ** to restore the state of the tty structure so the change is NOT ** made. */ if (PortP->Lock) { tp->tm.c_iflag = PortP->StoredTty.iflag; tp->tm.c_oflag = PortP->StoredTty.oflag; tp->tm.c_cflag = PortP->StoredTty.cflag; tp->tm.c_lflag = PortP->StoredTty.lflag; tp->tm.c_line = PortP->StoredTty.line; for (i = 0; i < NCC + 1; i++) tp->tm.c_cc[i] = PortP->StoredTty.cc[i]; } else { /* ** If the port is set to store the parameters, and it is ** reconfigured, we want to save the current tty struct so it ** may be restored on the next open. */ if (PortP->Store) { PortP->StoredTty.iflag = tp->tm.c_iflag; PortP->StoredTty.oflag = tp->tm.c_oflag; PortP->StoredTty.cflag = tp->tm.c_cflag; PortP->StoredTty.lflag = tp->tm.c_lflag; PortP->StoredTty.line = tp->tm.c_line; for (i = 0; i < NCC + 1; i++) PortP->StoredTty.cc[i] = tp->tm.c_cc[i]; } } changed = (tp->tm.c_cflag != old_cflag) || (tp->tm.c_iflag != old_iflag) || (tp->tm.c_oflag != old_oflag); PortP->CookMode = RIOCookMode(tp); /* Set new cooking mode */ rio_dprintk (RIO_DEBUG_TTY, "RIOIoctl changed %d newcook %d oldcook %d\n", changed,PortP->CookMode,oldcook);#ifdef MODEM_SUPPORT /* ** kludge to force CARR_ON if CLOCAL set */ if ((tp->tm.c_cflag & CLOCAL) || (PortP->ModemState & MSVR1_CD)) { tp->tm.c_state |= CARR_ON; wakeup ((caddr_t)&tp->tm.c_canq); }#endif if ( p->RIOHalted ) { RIOClearUp( PortP ); rio_spin_unlock_irqrestore(&PortP->portSem, flags); pseterr(EIO); return 0; } /* ** Re-configure if modes or cooking have changed */ if (changed || oldcook != PortP->CookMode || (ioctl_processed)) { rio_spin_unlock_irqrestore(&PortP->portSem, flags); rio_dprintk (RIO_DEBUG_TTY, "Ioctl changing the PORT settings\n"); RIOParam(PortP,CONFIG,Modem,OK_TO_SLEEP); rio_spin_lock_irqsave(&PortP->portSem, flags); } if (p->RIOHalted) { rio_spin_unlock_irqrestore(&PortP->portSem, flags); RIOClearUp( PortP ); pseterr(EIO); return 0; } rio_spin_unlock_irqrestore(&PortP->portSem, flags); return 0;}/* ttyseth -- set hardware dependent tty settings*/voidttyseth(PortP, s, sg)struct Port * PortP;struct ttystatics * s;struct old_sgttyb *sg;{ struct old_sgttyb * tsg; struct termios *tp = &s->tm; tsg = &s->sg; if (sg->sg_flags & (EVENP|ODDP)) { tp->c_cflag &= PARENB; if (sg->sg_flags & EVENP) { if (sg->sg_flags & ODDP) { tp->c_cflag &= V_CS7; tp->c_cflag &= ~PARENB; } else { tp->c_cflag &= V_CS7; tp->c_cflag &= PARENB; tp->c_cflag &= PARODD; } } else if (sg->sg_flags & ODDP) { tp->c_cflag &= V_CS7; tp->c_cflag &= PARENB; tp->c_cflag &= PARODD; } else { tp->c_cflag &= V_CS7; tp->c_cflag &= PARENB; } }/* * Use ispeed as the desired speed. Most implementations don't handle * separate input and output speeds very well. If the RIO handles this, * I will have to use separate sets of flags to store them in the * Port structure. */ if ( !sg->sg_ospeed ) sg->sg_ospeed = sg->sg_ispeed; else sg->sg_ispeed = sg->sg_ospeed; if (sg->sg_ispeed > V_EXTB ) sg->sg_ispeed = V_EXTB; if (sg->sg_ispeed < V_B0) sg->sg_ispeed = V_B0; *tsg = *sg; tp->c_cflag = (tp->c_cflag & ~V_CBAUD) | conv_bv[(int)sg->sg_ispeed];}/* ttyseth_pv -- set hardware dependent tty settings using either the POSIX termios structure or the System V termio structure. sysv = 0 => (POSIX): struct termios *sg sysv != 0 => (System V): struct termio *sg*/static voidttyseth_pv(PortP, s, sg, sysv)struct Port *PortP;struct ttystatics *s;struct termios *sg;int sysv;{ int speed; unsigned char csize; unsigned char cread; unsigned int lcr_flags; int ps; if (sysv) { /* sg points to a System V termio structure */ csize = ((struct termio *)sg)->c_cflag & CSIZE; cread = ((struct termio *)sg)->c_cflag & CREAD; speed = conv_vb[((struct termio *)sg)->c_cflag & V_CBAUD]; } else { /* sg points to a POSIX termios structure */ csize = sg->c_cflag & CSIZE; cread = sg->c_cflag & CREAD; speed = conv_vb[sg->c_cflag & V_CBAUD]; } if (s->sg.sg_ispeed != speed || s->sg.sg_ospeed != speed) { s->sg.sg_ispeed = speed; s->sg.sg_ospeed = speed; s->tm.c_cflag = (s->tm.c_cflag & ~V_CBAUD) | conv_bv[(int)s->sg.sg_ispeed]; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -