📄 riotty.c
字号:
** ACTION: verify that this is a good thing ** to do here. -- ??? ** I think it's OK. -- REW */ rio_dprintk (RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort); RIOPreemptiveCmd( p, PortP, FCLOSE ); /* tp->tm.c_state &= ~WOPEN; */ PortP->State &= ~RIO_WOPEN; rio_spin_unlock_irqrestore(&PortP->portSem, flags); func_exit (); return -EINTR; } } PortP->State &= ~RIO_WOPEN; } if ( p->RIOHalted ) goto bombout; rio_dprintk (RIO_DEBUG_TTY, "Setting RIO_MOPEN\n"); PortP->State |= RIO_MOPEN; } else#endif { /* ** ACTION ** Direct line open - force carrier (will probably mean ** that sleeping Modem line fubar) */ PortP->State |= RIO_LOPEN; } if ( p->RIOHalted ) { goto bombout; } rio_dprintk (RIO_DEBUG_TTY, "high level open done\n");#ifdef STATS PortP->Stat.OpenCnt++;#endif /* ** Count opens for port statistics reporting */ if (PortP->statsGather) PortP->opens++; rio_spin_unlock_irqrestore(&PortP->portSem, flags); rio_dprintk (RIO_DEBUG_TTY, "Returning from open\n"); func_exit (); return 0;}/*** RIOClose the port.** The operating system thinks that this is last close for the device.** As there are two interfaces to the port (Modem and tty), we need to** check that both are closed before we close the device.*/ intriotclose(void *ptr){#if 0 register uint SysPort = dev; struct ttystatics *tp; /* pointer to our ttystruct */#endif struct Port *PortP = ptr; /* pointer to the port structure */ int deleted = 0; int try = -1; /* Disable the timeouts by setting them to -1 */ int repeat_this = -1; /* Congrats to those having 15 years of uptime! (You get to break the driver.) */ unsigned long end_time; struct tty_struct * tty; unsigned long flags; int Modem; int rv = 0; rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum); /* PortP = p->RIOPortp[SysPort]; */ rio_dprintk (RIO_DEBUG_TTY, "Port is at address 0x%x\n",(int)PortP); /* tp = PortP->TtyP;*/ /* Get tty */ tty = PortP->gs.tty; rio_dprintk (RIO_DEBUG_TTY, "TTY is at address 0x%x\n",(int)tty); if (PortP->gs.closing_wait) end_time = jiffies + PortP->gs.closing_wait; else end_time = jiffies + MAX_SCHEDULE_TIMEOUT; Modem = rio_ismodem(tty);#if 0 /* What F.CKING cache? Even then, a higly idle multiprocessor, system with large caches this won't work . Better find out when this doesn't work asap, and fix the cause. -- REW */ RIODelay(PortP, HUNDRED_MS*10); /* To flush the cache */#endif rio_spin_lock_irqsave(&PortP->portSem, flags); /* ** Setting this flag will make any process trying to open ** this port block until we are complete closing it. */ PortP->State |= RIO_CLOSING; if ( (PortP->State & RIO_DELETED) ) { rio_dprintk (RIO_DEBUG_TTY, "Close on deleted RTA\n"); deleted = 1; } if ( p->RIOHalted ) { RIOClearUp( PortP ); rv = -EIO; goto close_end; } rio_dprintk (RIO_DEBUG_TTY, "Clear bits\n"); /* ** clear the open bits for this device */ PortP->State &= (Modem ? ~RIO_MOPEN : ~RIO_LOPEN); PortP->State &= ~RIO_CARR_ON; PortP->ModemState &= ~MSVR1_CD; /* ** If the device was open as both a Modem and a tty line ** then we need to wimp out here, as the port has not really ** been finally closed (gee, whizz!) The test here uses the ** bit for the OTHER mode of operation, to see if THAT is ** still active! */ if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) { /* ** The port is still open for the other task - ** return, pretending that we are still active. */ rio_dprintk (RIO_DEBUG_TTY, "Channel %d still open !\n",PortP->PortNum); PortP->State &= ~RIO_CLOSING; if (PortP->firstOpen) PortP->firstOpen--; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return -EIO; } rio_dprintk (RIO_DEBUG_TTY, "Closing down - everything must go!\n"); PortP->State &= ~RIO_DYNOROD; /* ** This is where we wait for the port ** to drain down before closing. Bye-bye.... ** (We never meant to do this) */ rio_dprintk (RIO_DEBUG_TTY, "Timeout 1 starts\n"); if (!deleted) while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut) ) { cprintf("Need to flush the ttyport\n"); if (repeat_this -- <= 0) { rv = -EINTR; rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); RIOPreemptiveCmd(p, PortP, FCLOSE); goto close_end; } rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (RIODelay_ni(PortP, HUNDRED_MS*10) == RIO_FAIL) { rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); rv = -EINTR; rio_spin_lock_irqsave(&PortP->portSem, flags); goto close_end; } rio_spin_lock_irqsave(&PortP->portSem, flags); } PortP->TxBufferIn = PortP->TxBufferOut = 0; repeat_this = 0xff; PortP->InUse = 0; if ( (PortP->State & (RIO_LOPEN|RIO_MOPEN)) ) { /* ** The port has been re-opened for the other task - ** return, pretending that we are still active. */ rio_dprintk (RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum); PortP->State &= ~RIO_CLOSING; rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (PortP->firstOpen) PortP->firstOpen--; return -EIO; } if ( p->RIOHalted ) { RIOClearUp( PortP ); goto close_end; } /* Can't call RIOShortCommand with the port locked. */ rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) { RIOPreemptiveCmd(p, PortP, FCLOSE); goto close_end; } if (!deleted) while (try && (PortP->PortState & PORT_ISOPEN)) { try--; if (time_after (jiffies, end_time)) { rio_dprintk (RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n" ); RIOPreemptiveCmd(p, PortP,FCLOSE); break; } rio_dprintk (RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN); if ( p->RIOHalted ) { RIOClearUp( PortP ); goto close_end; } if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) { rio_dprintk (RIO_DEBUG_TTY, "RTA EINTR in delay \n"); RIOPreemptiveCmd(p, PortP,FCLOSE); break; } } rio_spin_lock_irqsave(&PortP->portSem, flags); rio_dprintk (RIO_DEBUG_TTY, "Close: try was %d on completion\n", try ); /* RIOPreemptiveCmd(p, PortP, FCLOSE); *//*** 15.10.1998 ARG - ESIL 0761 part fix** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.*/ PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);#ifdef STATS PortP->Stat.CloseCnt++;#endif /* ** Count opens for port statistics reporting */ if (PortP->statsGather) PortP->closes++;close_end: /* XXX: Why would a "DELETED" flag be reset here? I'd have thought that a "deleted" flag means that the port was permanently gone, but here we can make it reappear by it being in close during the "deletion". */ PortP->State &= ~(RIO_CLOSING|RIO_DELETED); if (PortP->firstOpen) PortP->firstOpen--; rio_spin_unlock_irqrestore(&PortP->portSem, flags); rio_dprintk (RIO_DEBUG_TTY, "Return from close\n"); return rv;}/*** decide if we need to use the line discipline.** This routine can return one of three values:** COOK_RAW if no processing has to be done by the line discipline or the card** COOK_WELL if the line discipline must be used to do the processing** COOK_MEDIUM if the card can do all the processing necessary.*/#if 0static intRIOCookMode(struct ttystatics *tp){ /* ** We can't handle tm.c_mstate != 0 on SCO ** We can't handle mapping ** We can't handle non-ttwrite line disc. ** We can't handle lflag XCASE ** We can handle oflag OPOST & (OCRNL, ONLCR, TAB3) */#ifdef CHECK CheckTtyP( tp );#endif if (!(tp->tm.c_oflag & OPOST)) /* No post processing */ return COOK_RAW; /* Raw mode o/p */ if ( tp->tm.c_lflag & XCASE ) return COOK_WELL; /* Use line disc */ if (tp->tm.c_oflag & ~(OPOST | ONLCR | OCRNL | TAB3 ) ) return COOK_WELL; /* Use line disc for strange modes */ if ( tp->tm.c_oflag == OPOST ) /* If only OPOST is set, do RAW */ return COOK_RAW; /* ** So, we need to output process! */ return COOK_MEDIUM;}#endifstatic voidRIOClearUp(PortP)struct Port *PortP;{ rio_dprintk (RIO_DEBUG_TTY, "RIOHalted set\n"); PortP->Config = 0; /* Direct semaphore */ PortP->PortState = 0; PortP->firstOpen = 0; PortP->FlushCmdBodge = 0; PortP->ModemState = PortP->CookMode = 0; PortP->Mapped = 0; PortP->WflushFlag = 0; PortP->MagicFlags = 0; PortP->RxDataStart = 0; PortP->TxBufferIn = 0; PortP->TxBufferOut = 0;}/*** Put a command onto a port.** The PortPointer, command, length and arg are passed.** The len is the length *inclusive* of the command byte,** and so for a command that takes no data, len==1.** The arg is a single byte, and is only used if len==2.** Other values of len aren't allowed, and will cause** a panic.*/int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg){ PKT *PacketP; int retries = 20; /* at 10 per second -> 2 seconds */ unsigned long flags; rio_dprintk (RIO_DEBUG_TTY, "entering shortcommand.\n");#ifdef CHECK CheckPortP( PortP ); if ( len < 1 || len > 2 ) cprintf(("STUPID LENGTH %d\n",len));#endif if ( PortP->State & RIO_DELETED ) { rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); return RIO_FAIL; } rio_spin_lock_irqsave(&PortP->portSem, flags); /* ** If the port is in use for pre-emptive command, then wait for it to ** be free again. */ while ( (PortP->InUse != NOT_INUSE) && !p->RIOHalted ) { rio_dprintk (RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries); rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (retries-- <= 0) { return RIO_FAIL; } if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) { return RIO_FAIL; } rio_spin_lock_irqsave(&PortP->portSem, flags); } if ( PortP->State & RIO_DELETED ) { rio_dprintk (RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n"); rio_spin_unlock_irqrestore(&PortP->portSem, flags); return RIO_FAIL; } while ( !can_add_transmit(&PacketP,PortP) && !p->RIOHalted ) { rio_dprintk (RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries); rio_spin_unlock_irqrestore(&PortP->portSem, flags); if (retries-- <= 0) { rio_dprintk (RIO_DEBUG_TTY, "out of tries. Failing\n"); return RIO_FAIL; } if ( RIODelay_ni(PortP, HUNDRED_MS)==RIO_FAIL ) { return RIO_FAIL; } rio_spin_lock_irqsave(&PortP->portSem, flags); } if ( p->RIOHalted ) { rio_spin_unlock_irqrestore(&PortP->portSem, flags); return RIO_FAIL; } /* ** set the command byte and the argument byte */ WBYTE(PacketP->data[0] , command); if ( len==2 ) WBYTE(PacketP->data[1] , arg); /* ** set the length of the packet and set the command bit. */ WBYTE(PacketP->len , PKT_CMD_BIT | len); add_transmit(PortP); /* ** Count characters transmitted for port statistics reporting */ if (PortP->statsGather) PortP->txchars += len; rio_spin_unlock_irqrestore(&PortP->portSem, flags); return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;}#if 0/*** This is an ioctl interface. This is the twentieth century. You know what** its all about.*/intriotioctl(struct rio_info *p, struct tty_struct *tty, int cmd, caddr_t arg){ register struct Port *PortP; register struct ttystatics *tp; int current; int ParamSemIncremented = 0; int old_oflag, old_cflag, old_iflag, changed, oldcook; int i; unsigned char sio_regs[5]; /* Here be magic */ short vpix_cflag; short divisor; int baud; uint SysPort = rio_minor(tty); int Modem = rio_ismodem(tty); int ioctl_processed; rio_dprintk (RIO_DEBUG_TTY, "port ioctl SysPort %d command 0x%x argument 0x%x %s\n", SysPort, cmd, arg, Modem?"Modem":"tty") ; if ( SysPort >= RIO_PORTS ) { rio_dprintk (RIO_DEBUG_TTY, "Bad port number %d\n", SysPort); return -ENXIO; } PortP = p->RIOPortp[SysPort]; tp = PortP->TtyP; rio_spin_lock_irqsave(&PortP->portSem, flags);#ifdef STATS PortP->Stat.IoctlCnt++;#endif if ( PortP->State & RIO_DELETED ) { rio_spin_unlock_irqrestore(&PortP->portSem, flags);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -