riotty.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 655 行 · 第 1/2 页

C
655
字号
				/*				   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;	if (p->RIOHalted)		goto bombout;	rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");	/*	 ** 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.*/int riotclose(void *ptr){	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 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 %p\n", PortP);	/* tp = PortP->TtyP; *//* Get tty */	tty = PortP->gs.tty;	rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty);	if (PortP->gs.closing_wait)		end_time = jiffies + PortP->gs.closing_wait;	else		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;	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 &= ~RIO_MOPEN;	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)) {			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);	/*	 ** 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;}static void RIOClearUp(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){	struct PKT *PacketP;	int retries = 20;	/* at 10 per second -> 2 seconds */	unsigned long flags;	rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");	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	 */	writeb(command, &PacketP->data[0]);	if (len == 2)		writeb(arg, &PacketP->data[1]);	/*	 ** set the length of the packet and set the command bit.	 */	writeb(PKT_CMD_BIT | len, &PacketP->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;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?