stallion.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,504 行 · 第 1/5 页

C
2,504
字号
		    (sio.close_delay != portp->close_delay) ||		    ((sio.flags & ~ASYNC_USR_MASK) !=		    (portp->flags & ~ASYNC_USR_MASK)))			return(-EPERM);	} 	portp->flags = (portp->flags & ~ASYNC_USR_MASK) |		(sio.flags & ASYNC_USR_MASK);	portp->baud_base = sio.baud_base;	portp->close_delay = sio.close_delay;	portp->closing_wait = sio.closing_wait;	portp->custom_divisor = sio.custom_divisor;	stl_setport(portp, portp->tty->termios);	return(0);}/*****************************************************************************/static int stl_tiocmget(struct tty_struct *tty, struct file *file){	stlport_t	*portp;	if (tty == (struct tty_struct *) NULL)		return(-ENODEV);	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return(-ENODEV);	if (tty->flags & (1 << TTY_IO_ERROR))		return(-EIO);	return stl_getsignals(portp);}static int stl_tiocmset(struct tty_struct *tty, struct file *file,			unsigned int set, unsigned int clear){	stlport_t	*portp;	int rts = -1, dtr = -1;	if (tty == (struct tty_struct *) NULL)		return(-ENODEV);	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return(-ENODEV);	if (tty->flags & (1 << TTY_IO_ERROR))		return(-EIO);	if (set & TIOCM_RTS)		rts = 1;	if (set & TIOCM_DTR)		dtr = 1;	if (clear & TIOCM_RTS)		rts = 0;	if (clear & TIOCM_DTR)		dtr = 0;	stl_setsignals(portp, dtr, rts);	return 0;}static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){	stlport_t	*portp;	unsigned int	ival;	int		rc;	void __user *argp = (void __user *)arg;#ifdef DEBUG	printk("stl_ioctl(tty=%x,file=%x,cmd=%x,arg=%x)\n",		(int) tty, (int) file, cmd, (int) arg);#endif	if (tty == (struct tty_struct *) NULL)		return(-ENODEV);	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return(-ENODEV);	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {		if (tty->flags & (1 << TTY_IO_ERROR))			return(-EIO);	}	rc = 0;	switch (cmd) {	case TIOCGSOFTCAR:		rc = put_user(((tty->termios->c_cflag & CLOCAL) ? 1 : 0),			(unsigned __user *) argp);		break;	case TIOCSSOFTCAR:		if (get_user(ival, (unsigned int __user *) arg))			return -EFAULT;		tty->termios->c_cflag =				(tty->termios->c_cflag & ~CLOCAL) |				(ival ? CLOCAL : 0);		break;	case TIOCGSERIAL:		rc = stl_getserial(portp, argp);		break;	case TIOCSSERIAL:		rc = stl_setserial(portp, argp);		break;	case COM_GETPORTSTATS:		rc = stl_getportstats(portp, argp);		break;	case COM_CLRPORTSTATS:		rc = stl_clrportstats(portp, argp);		break;	case TIOCSERCONFIG:	case TIOCSERGWILD:	case TIOCSERSWILD:	case TIOCSERGETLSR:	case TIOCSERGSTRUCT:	case TIOCSERGETMULTI:	case TIOCSERSETMULTI:	default:		rc = -ENOIOCTLCMD;		break;	}	return(rc);}/*****************************************************************************/static void stl_settermios(struct tty_struct *tty, struct termios *old){	stlport_t	*portp;	struct termios	*tiosp;#ifdef DEBUG	printk("stl_settermios(tty=%x,old=%x)\n", (int) tty, (int) old);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	tiosp = tty->termios;	if ((tiosp->c_cflag == old->c_cflag) &&	    (tiosp->c_iflag == old->c_iflag))		return;	stl_setport(portp, tiosp);	stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),		-1);	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {		tty->hw_stopped = 0;		stl_start(tty);	}	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))		wake_up_interruptible(&portp->open_wait);}/*****************************************************************************//* *	Attempt to flow control who ever is sending us data. Based on termios *	settings use software or/and hardware flow control. */static void stl_throttle(struct tty_struct *tty){	stlport_t	*portp;#ifdef DEBUG	printk("stl_throttle(tty=%x)\n", (int) tty);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	stl_flowctrl(portp, 0);}/*****************************************************************************//* *	Unflow control the device sending us data... */static void stl_unthrottle(struct tty_struct *tty){	stlport_t	*portp;#ifdef DEBUG	printk("stl_unthrottle(tty=%x)\n", (int) tty);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	stl_flowctrl(portp, 1);}/*****************************************************************************//* *	Stop the transmitter. Basically to do this we will just turn TX *	interrupts off. */static void stl_stop(struct tty_struct *tty){	stlport_t	*portp;#ifdef DEBUG	printk("stl_stop(tty=%x)\n", (int) tty);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	stl_startrxtx(portp, -1, 0);}/*****************************************************************************//* *	Start the transmitter again. Just turn TX interrupts back on. */static void stl_start(struct tty_struct *tty){	stlport_t	*portp;#ifdef DEBUG	printk("stl_start(tty=%x)\n", (int) tty);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	stl_startrxtx(portp, -1, 1);}/*****************************************************************************//* *	Hangup this port. This is pretty much like closing the port, only *	a little more brutal. No waiting for data to drain. Shutdown the *	port and maybe drop signals. */static void stl_hangup(struct tty_struct *tty){	stlport_t	*portp;#ifdef DEBUG	printk("stl_hangup(tty=%x)\n", (int) tty);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	portp->flags &= ~ASYNC_INITIALIZED;	stl_disableintrs(portp);	if (tty->termios->c_cflag & HUPCL)		stl_setsignals(portp, 0, 0);	stl_enablerxtx(portp, 0, 0);	stl_flushbuffer(tty);	portp->istate = 0;	set_bit(TTY_IO_ERROR, &tty->flags);	if (portp->tx.buf != (char *) NULL) {		kfree(portp->tx.buf);		portp->tx.buf = (char *) NULL;		portp->tx.head = (char *) NULL;		portp->tx.tail = (char *) NULL;	}	portp->tty = (struct tty_struct *) NULL;	portp->flags &= ~ASYNC_NORMAL_ACTIVE;	portp->refcount = 0;	wake_up_interruptible(&portp->open_wait);}/*****************************************************************************/static void stl_flushbuffer(struct tty_struct *tty){	stlport_t	*portp;#ifdef DEBUG	printk("stl_flushbuffer(tty=%x)\n", (int) tty);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	stl_flush(portp);	tty_wakeup(tty);}/*****************************************************************************/static void stl_breakctl(struct tty_struct *tty, int state){	stlport_t	*portp;#ifdef DEBUG	printk("stl_breakctl(tty=%x,state=%d)\n", (int) tty, state);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	stl_sendbreak(portp, ((state == -1) ? 1 : 2));}/*****************************************************************************/static void stl_waituntilsent(struct tty_struct *tty, int timeout){	stlport_t	*portp;	unsigned long	tend;#ifdef DEBUG	printk("stl_waituntilsent(tty=%x,timeout=%d)\n", (int) tty, timeout);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	if (timeout == 0)		timeout = HZ;	tend = jiffies + timeout;	while (stl_datastate(portp)) {		if (signal_pending(current))			break;		stl_delay(2);		if (time_after_eq(jiffies, tend))			break;	}}/*****************************************************************************/static void stl_sendxchar(struct tty_struct *tty, char ch){	stlport_t	*portp;#ifdef DEBUG	printk("stl_sendxchar(tty=%x,ch=%x)\n", (int) tty, ch);#endif	if (tty == (struct tty_struct *) NULL)		return;	portp = tty->driver_data;	if (portp == (stlport_t *) NULL)		return;	if (ch == STOP_CHAR(tty))		stl_sendflow(portp, 0);	else if (ch == START_CHAR(tty))		stl_sendflow(portp, 1);	else		stl_putchar(tty, ch);}/*****************************************************************************/#define	MAXLINE		80/* *	Format info for a specified port. The line is deliberately limited *	to 80 characters. (If it is too long it will be truncated, if too *	short then padded with spaces). */static int stl_portinfo(stlport_t *portp, int portnr, char *pos){	char	*sp;	int	sigs, cnt;	sp = pos;	sp += sprintf(sp, "%d: uart:%s tx:%d rx:%d",		portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",		(int) portp->stats.txtotal, (int) portp->stats.rxtotal);	if (portp->stats.rxframing)		sp += sprintf(sp, " fe:%d", (int) portp->stats.rxframing);	if (portp->stats.rxparity)		sp += sprintf(sp, " pe:%d", (int) portp->stats.rxparity);	if (portp->stats.rxbreaks)		sp += sprintf(sp, " brk:%d", (int) portp->stats.rxbreaks);	if (portp->stats.rxoverrun)		sp += sprintf(sp, " oe:%d", (int) portp->stats.rxoverrun);	sigs = stl_getsignals(portp);	cnt = sprintf(sp, "%s%s%s%s%s ",		(sigs & TIOCM_RTS) ? "|RTS" : "",		(sigs & TIOCM_CTS) ? "|CTS" : "",		(sigs & TIOCM_DTR) ? "|DTR" : "",		(sigs & TIOCM_CD) ? "|DCD" : "",		(sigs & TIOCM_DSR) ? "|DSR" : "");	*sp = ' ';	sp += cnt;	for (cnt = (sp - pos); (cnt < (MAXLINE - 1)); cnt++)		*sp++ = ' ';	if (cnt >= MAXLINE)		pos[(MAXLINE - 2)] = '+';	pos[(MAXLINE - 1)] = '\n';	return(MAXLINE);}/*****************************************************************************//* *	Port info, read from the /proc file system. */static int stl_readproc(char *page, char **start, off_t off, int count, int *eof, void *data){	stlbrd_t	*brdp;	stlpanel_t	*panelp;	stlport_t	*portp;	int		brdnr, panelnr, portnr, totalport;	int		curoff, maxoff;	char		*pos;#ifdef DEBUG	printk("stl_readproc(page=%x,start=%x,off=%x,count=%d,eof=%x,"		"data=%x\n", (int) page, (int) start, (int) off, count,		(int) eof, (int) data);#endif	pos = page;	totalport = 0;	curoff = 0;	if (off == 0) {		pos += sprintf(pos, "%s: version %s", stl_drvtitle,			stl_drvversion);		while (pos < (page + MAXLINE - 1))			*pos++ = ' ';		*pos++ = '\n';	}	curoff =  MAXLINE;/* *	We scan through for each board, panel and port. The offset is *	calculated on the fly, and irrelevant ports are skipped. */	for (brdnr = 0; (brdnr < stl_nrbrds); brdnr++) {		brdp = stl_brds[brdnr];		if (brdp == (stlbrd_t *) NULL)			continue;		if (brdp->state == 0)			continue;		maxoff = curoff + (brdp->nrports * MAXLINE);		if (off >= maxoff) {			curoff = maxoff;			continue;		}		totalport = brdnr * STL_MAXPORTS;		for (panelnr = 0; (panelnr < brdp->nrpanels); panelnr++) {			panelp = brdp->panels[panelnr];			if (panelp == (stlpanel_t *) NULL)				continue;			maxoff = curoff + (panelp->nrports * MAXLINE);			if (off >= maxoff) {				curoff = maxoff;				totalport += panelp->nrports;				continue;			}			for (portnr = 0; (portnr < panelp->nrports); portnr++,			    totalport++) {				portp = panelp->ports[portnr];				if (portp == (stlport_t *) NULL)					continue;				if (off >= (curoff += MAXLINE))

⌨️ 快捷键说明

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