⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 istallion.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/*****************************************************************************//* *	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. This is rather tricky really. We want *	to close the port as well. */static void stli_hangup(struct tty_struct *tty){	struct stliport *portp;	struct stlibrd *brdp;	unsigned long flags;	portp = tty->driver_data;	if (portp == NULL)		return;	if (portp->brdnr >= stli_nrbrds)		return;	brdp = stli_brds[portp->brdnr];	if (brdp == NULL)		return;	portp->flags &= ~ASYNC_INITIALIZED;	if (!test_bit(ST_CLOSING, &portp->state))		stli_rawclose(brdp, portp, 0, 0);	spin_lock_irqsave(&stli_lock, flags);	if (tty->termios->c_cflag & HUPCL) {		stli_mkasysigs(&portp->asig, 0, 0);		if (test_bit(ST_CMDING, &portp->state)) {			set_bit(ST_DOSIGS, &portp->state);			set_bit(ST_DOFLUSHTX, &portp->state);			set_bit(ST_DOFLUSHRX, &portp->state);		} else {			stli_sendcmd(brdp, portp, A_SETSIGNALSF,				&portp->asig, sizeof(asysigs_t), 0);		}	}	clear_bit(ST_TXBUSY, &portp->state);	clear_bit(ST_RXSTOP, &portp->state);	set_bit(TTY_IO_ERROR, &tty->flags);	portp->tty = NULL;	portp->flags &= ~ASYNC_NORMAL_ACTIVE;	portp->refcount = 0;	spin_unlock_irqrestore(&stli_lock, flags);	wake_up_interruptible(&portp->open_wait);}/*****************************************************************************//* *	Flush characters from the lower buffer. We may not have user context *	so we cannot sleep waiting for it to complete. Also we need to check *	if there is chars for this port in the TX cook buffer, and flush them *	as well. */static void stli_flushbuffer(struct tty_struct *tty){	struct stliport *portp;	struct stlibrd *brdp;	unsigned long ftype, flags;	portp = tty->driver_data;	if (portp == NULL)		return;	if (portp->brdnr >= stli_nrbrds)		return;	brdp = stli_brds[portp->brdnr];	if (brdp == NULL)		return;	spin_lock_irqsave(&brd_lock, flags);	if (tty == stli_txcooktty) {		stli_txcooktty = NULL;		stli_txcooksize = 0;		stli_txcookrealsize = 0;	}	if (test_bit(ST_CMDING, &portp->state)) {		set_bit(ST_DOFLUSHTX, &portp->state);	} else {		ftype = FLUSHTX;		if (test_bit(ST_DOFLUSHRX, &portp->state)) {			ftype |= FLUSHRX;			clear_bit(ST_DOFLUSHRX, &portp->state);		}		__stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);	}	spin_unlock_irqrestore(&brd_lock, flags);	tty_wakeup(tty);}/*****************************************************************************/static void stli_breakctl(struct tty_struct *tty, int state){	struct stlibrd	*brdp;	struct stliport	*portp;	long		arg;	portp = tty->driver_data;	if (portp == NULL)		return;	if (portp->brdnr >= stli_nrbrds)		return;	brdp = stli_brds[portp->brdnr];	if (brdp == NULL)		return;	arg = (state == -1) ? BREAKON : BREAKOFF;	stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);}/*****************************************************************************/static void stli_waituntilsent(struct tty_struct *tty, int timeout){	struct stliport *portp;	unsigned long tend;	if (tty == NULL)		return;	portp = tty->driver_data;	if (portp == NULL)		return;	if (timeout == 0)		timeout = HZ;	tend = jiffies + timeout;	while (test_bit(ST_TXBUSY, &portp->state)) {		if (signal_pending(current))			break;		msleep_interruptible(20);		if (time_after_eq(jiffies, tend))			break;	}}/*****************************************************************************/static void stli_sendxchar(struct tty_struct *tty, char ch){	struct stlibrd	*brdp;	struct stliport	*portp;	asyctrl_t	actrl;	portp = tty->driver_data;	if (portp == NULL)		return;	if (portp->brdnr >= stli_nrbrds)		return;	brdp = stli_brds[portp->brdnr];	if (brdp == NULL)		return;	memset(&actrl, 0, sizeof(asyctrl_t));	if (ch == STOP_CHAR(tty)) {		actrl.rxctrl = CT_STOPFLOW;	} else if (ch == START_CHAR(tty)) {		actrl.rxctrl = CT_STARTFLOW;	} else {		actrl.txctrl = CT_SENDCHR;		actrl.tximdch = ch;	}	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);}/*****************************************************************************/#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 stli_portinfo(struct stlibrd *brdp, struct stliport *portp, int portnr, char *pos){	char *sp, *uart;	int rc, cnt;	rc = stli_portcmdstats(portp);	uart = "UNKNOWN";	if (brdp->state & BST_STARTED) {		switch (stli_comstats.hwid) {		case 0:	uart = "2681"; break;		case 1:	uart = "SC26198"; break;		default:uart = "CD1400"; break;		}	}	sp = pos;	sp += sprintf(sp, "%d: uart:%s ", portnr, uart);	if ((brdp->state & BST_STARTED) && (rc >= 0)) {		sp += sprintf(sp, "tx:%d rx:%d", (int) stli_comstats.txtotal,			(int) stli_comstats.rxtotal);		if (stli_comstats.rxframing)			sp += sprintf(sp, " fe:%d",				(int) stli_comstats.rxframing);		if (stli_comstats.rxparity)			sp += sprintf(sp, " pe:%d",				(int) stli_comstats.rxparity);		if (stli_comstats.rxbreaks)			sp += sprintf(sp, " brk:%d",				(int) stli_comstats.rxbreaks);		if (stli_comstats.rxoverrun)			sp += sprintf(sp, " oe:%d",				(int) stli_comstats.rxoverrun);		cnt = sprintf(sp, "%s%s%s%s%s ",			(stli_comstats.signals & TIOCM_RTS) ? "|RTS" : "",			(stli_comstats.signals & TIOCM_CTS) ? "|CTS" : "",			(stli_comstats.signals & TIOCM_DTR) ? "|DTR" : "",			(stli_comstats.signals & TIOCM_CD) ? "|DCD" : "",			(stli_comstats.signals & 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 stli_readproc(char *page, char **start, off_t off, int count, int *eof, void *data){	struct stlibrd *brdp;	struct stliport *portp;	unsigned int brdnr, portnr, totalport;	int curoff, maxoff;	char *pos;	pos = page;	totalport = 0;	curoff = 0;	if (off == 0) {		pos += sprintf(pos, "%s: version %s", stli_drvtitle,			stli_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 < stli_nrbrds); brdnr++) {		brdp = stli_brds[brdnr];		if (brdp == NULL)			continue;		if (brdp->state == 0)			continue;		maxoff = curoff + (brdp->nrports * MAXLINE);		if (off >= maxoff) {			curoff = maxoff;			continue;		}		totalport = brdnr * STL_MAXPORTS;		for (portnr = 0; (portnr < brdp->nrports); portnr++,		    totalport++) {			portp = brdp->ports[portnr];			if (portp == NULL)				continue;			if (off >= (curoff += MAXLINE))				continue;			if ((pos - page + MAXLINE) > count)				goto stli_readdone;			pos += stli_portinfo(brdp, portp, totalport, pos);		}	}	*eof = 1;stli_readdone:	*start = page;	return(pos - page);}/*****************************************************************************//* *	Generic send command routine. This will send a message to the slave, *	of the specified type with the specified argument. Must be very *	careful of data that will be copied out from shared memory - *	containing command results. The command completion is all done from *	a poll routine that does not have user context. Therefore you cannot *	copy back directly into user space, or to the kernel stack of a *	process. This routine does not sleep, so can be called from anywhere. * *	The caller must hold the brd_lock (see also stli_sendcmd the usual *	entry point) */static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback){	cdkhdr_t __iomem *hdrp;	cdkctrl_t __iomem *cp;	unsigned char __iomem *bits;	if (test_bit(ST_CMDING, &portp->state)) {		printk(KERN_ERR "STALLION: command already busy, cmd=%x!\n",				(int) cmd);		return;	}	EBRDENABLE(brdp);	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;	if (size > 0) {		memcpy_toio((void __iomem *) &(cp->args[0]), arg, size);		if (copyback) {			portp->argp = arg;			portp->argsize = size;		}	}	writel(0, &cp->status);	writel(cmd, &cp->cmd);	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +		portp->portidx;	writeb(readb(bits) | portp->portbit, bits);	set_bit(ST_CMDING, &portp->state);	EBRDDISABLE(brdp);}static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback){	unsigned long		flags;	spin_lock_irqsave(&brd_lock, flags);	__stli_sendcmd(brdp, portp, cmd, arg, size, copyback);	spin_unlock_irqrestore(&brd_lock, flags);}/*****************************************************************************//* *	Read data from shared memory. This assumes that the shared memory *	is enabled and that interrupts are off. Basically we just empty out *	the shared memory buffer into the tty buffer. Must be careful to *	handle the case where we fill up the tty buffer, but still have *	more chars to unload. */static void stli_read(struct stlibrd *brdp, struct stliport *portp){	cdkasyrq_t __iomem *rp;	char __iomem *shbuf;	struct tty_struct	*tty;	unsigned int head, tail, size;	unsigned int len, stlen;	if (test_bit(ST_RXSTOP, &portp->state))		return;	tty = portp->tty;	if (tty == NULL)		return;	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;	head = (unsigned int) readw(&rp->head);	if (head != ((unsigned int) readw(&rp->head)))		head = (unsigned int) readw(&rp->head);	tail = (unsigned int) readw(&rp->tail);	size = portp->rxsize;	if (head >= tail) {		len = head - tail;		stlen = len;	} else {		len = size - (tail - head);		stlen = size - tail;	}	len = tty_buffer_request_room(tty, len);	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset);	while (len > 0) {		unsigned char *cptr;		stlen = min(len, stlen);		tty_prepare_flip_string(tty, &cptr, stlen);		memcpy_fromio(cptr, shbuf + tail, stlen);		len -= stlen;		tail += stlen;		if (tail >= size) {			tail = 0;			stlen = head;		}	}	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;	writew(tail, &rp->tail);	if (head != tail)		set_bit(ST_RXING, &portp->state);	tty_schedule_flip(tty);}/*****************************************************************************//* *	Set up and carry out any delayed commands. There is only a small set *	of slave commands that can be done "off-level". So it is not too *	difficult to deal with them here. */static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp){	int cmd;	if (test_bit(ST_DOSIGS, &portp->state)) {		if (test_bit(ST_DOFLUSHTX, &portp->state) &&		    test_bit(ST_DOFLUSHRX, &portp->state))			cmd = A_SETSIGNALSF;		else if (test_bit(ST_DOFLUSHTX, &portp->state))			cmd = A_SETSIGNALSFTX;		else if (test_bit(ST_DOFLUSHRX, &portp->state))			cmd = A_SETSIGNALSFRX;		else			cmd = A_SETSIGNALS;		clear_bit(ST_DOFLUSHTX, &portp->state);		clear_bit(ST_DOFLUSHRX, &portp->state);		clear_bit(ST_DOSIGS, &portp->state);		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig,			sizeof(asysigs_t));		writel(0, &cp->status);		writel(cmd, &cp->cmd);		set_bit(ST_CMDING, &portp->state);	} else if (test_bit(ST_DOFLUSHTX, &portp->state) ||	    test_bit(ST_DOFLUSHRX, &portp->state)) {		cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0);		cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0);		clear_bit(ST_DOFLUSHTX, &portp->state);		clear_bit(ST_DOFLUS

⌨️ 快捷键说明

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