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

📄 istallion.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			set_bit(ST_DOSIGS, &portp->state);		else			stli_sendcmd(brdp, portp, A_SETSIGNALS, &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);	if (tty->ldisc.flush_buffer)		(tty->ldisc.flush_buffer)(tty);	set_bit(ST_DOFLUSHRX, &portp->state);	stli_flushbuffer(tty);	tty->closing = 0;	portp->tty = NULL;	if (portp->openwaitcnt) {		if (portp->close_delay)			msleep_interruptible(jiffies_to_msecs(portp->close_delay));		wake_up_interruptible(&portp->open_wait);	}	portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);	wake_up_interruptible(&portp->close_wait);}/*****************************************************************************//* *	Carry out first open operations on a port. This involves a number of *	commands to be sent to the slave. We need to open the port, set the *	notification events, set the initial port settings, get and set the *	initial signal values. We sleep and wait in between each one. But *	this still all happens pretty quickly. */static int stli_initopen(struct stlibrd *brdp, struct stliport *portp){	struct tty_struct *tty;	asynotify_t nt;	asyport_t aport;	int rc;	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)		return rc;	memset(&nt, 0, sizeof(asynotify_t));	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);	nt.signal = SG_DCD;	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,	    sizeof(asynotify_t), 0)) < 0)		return rc;	tty = portp->tty;	if (tty == NULL)		return -ENODEV;	stli_mkasyport(portp, &aport, tty->termios);	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,	    sizeof(asyport_t), 0)) < 0)		return rc;	set_bit(ST_GETSIGS, &portp->state);	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,	    sizeof(asysigs_t), 1)) < 0)		return rc;	if (test_and_clear_bit(ST_GETSIGS, &portp->state))		portp->sigs = stli_mktiocm(portp->asig.sigvalue);	stli_mkasysigs(&portp->asig, 1, 1);	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,	    sizeof(asysigs_t), 0)) < 0)		return rc;	return 0;}/*****************************************************************************//* *	Send an open message to the slave. This will sleep waiting for the *	acknowledgement, so must have user context. We need to co-ordinate *	with close events here, since we don't want open and close events *	to overlap. */static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait){	cdkhdr_t __iomem *hdrp;	cdkctrl_t __iomem *cp;	unsigned char __iomem *bits;	unsigned long flags;	int rc;/* *	Send a message to the slave to open this port. *//* *	Slave is already closing this port. This can happen if a hangup *	occurs on this port. So we must wait until it is complete. The *	order of opens and closes may not be preserved across shared *	memory, so we must wait until it is complete. */	wait_event_interruptible(portp->raw_wait,			!test_bit(ST_CLOSING, &portp->state));	if (signal_pending(current)) {		return -ERESTARTSYS;	}/* *	Everything is ready now, so write the open message into shared *	memory. Once the message is in set the service bits to say that *	this port wants service. */	spin_lock_irqsave(&brd_lock, flags);	EBRDENABLE(brdp);	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;	writel(arg, &cp->openarg);	writeb(1, &cp->open);	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +		portp->portidx;	writeb(readb(bits) | portp->portbit, bits);	EBRDDISABLE(brdp);	if (wait == 0) {		spin_unlock_irqrestore(&brd_lock, flags);		return 0;	}/* *	Slave is in action, so now we must wait for the open acknowledgment *	to come back. */	rc = 0;	set_bit(ST_OPENING, &portp->state);	spin_unlock_irqrestore(&brd_lock, flags);	wait_event_interruptible(portp->raw_wait,			!test_bit(ST_OPENING, &portp->state));	if (signal_pending(current))		rc = -ERESTARTSYS;	if ((rc == 0) && (portp->rc != 0))		rc = -EIO;	return rc;}/*****************************************************************************//* *	Send a close message to the slave. Normally this will sleep waiting *	for the acknowledgement, but if wait parameter is 0 it will not. If *	wait is true then must have user context (to sleep). */static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait){	cdkhdr_t __iomem *hdrp;	cdkctrl_t __iomem *cp;	unsigned char __iomem *bits;	unsigned long flags;	int rc;/* *	Slave is already closing this port. This can happen if a hangup *	occurs on this port. */	if (wait) {		wait_event_interruptible(portp->raw_wait,				!test_bit(ST_CLOSING, &portp->state));		if (signal_pending(current)) {			return -ERESTARTSYS;		}	}/* *	Write the close command into shared memory. */	spin_lock_irqsave(&brd_lock, flags);	EBRDENABLE(brdp);	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;	writel(arg, &cp->closearg);	writeb(1, &cp->close);	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +		portp->portidx;	writeb(readb(bits) |portp->portbit, bits);	EBRDDISABLE(brdp);	set_bit(ST_CLOSING, &portp->state);	spin_unlock_irqrestore(&brd_lock, flags);	if (wait == 0)		return 0;/* *	Slave is in action, so now we must wait for the open acknowledgment *	to come back. */	rc = 0;	wait_event_interruptible(portp->raw_wait,			!test_bit(ST_CLOSING, &portp->state));	if (signal_pending(current))		rc = -ERESTARTSYS;	if ((rc == 0) && (portp->rc != 0))		rc = -EIO;	return rc;}/*****************************************************************************//* *	Send a command to the slave and wait for the response. This must *	have user context (it sleeps). This routine is generic in that it *	can send any type of command. Its purpose is to wait for that command *	to complete (as opposed to initiating the command then returning). */static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback){	wait_event_interruptible(portp->raw_wait,			!test_bit(ST_CMDING, &portp->state));	if (signal_pending(current))		return -ERESTARTSYS;	stli_sendcmd(brdp, portp, cmd, arg, size, copyback);	wait_event_interruptible(portp->raw_wait,			!test_bit(ST_CMDING, &portp->state));	if (signal_pending(current))		return -ERESTARTSYS;	if (portp->rc != 0)		return -EIO;	return 0;}/*****************************************************************************//* *	Send the termios settings for this port to the slave. This sleeps *	waiting for the command to complete - so must have user context. */static int stli_setport(struct stliport *portp){	struct stlibrd *brdp;	asyport_t aport;	if (portp == NULL)		return -ENODEV;	if (portp->tty == NULL)		return -ENODEV;	if (portp->brdnr >= stli_nrbrds)		return -ENODEV;	brdp = stli_brds[portp->brdnr];	if (brdp == NULL)		return -ENODEV;	stli_mkasyport(portp, &aport, portp->tty->termios);	return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));}/*****************************************************************************//* *	Possibly need to wait for carrier (DCD signal) to come high. Say *	maybe because if we are clocal then we don't need to wait... */static int stli_waitcarrier(struct stlibrd *brdp, struct stliport *portp, struct file *filp){	unsigned long flags;	int rc, doclocal;	rc = 0;	doclocal = 0;	if (portp->tty->termios->c_cflag & CLOCAL)		doclocal++;	spin_lock_irqsave(&stli_lock, flags);	portp->openwaitcnt++;	if (! tty_hung_up_p(filp))		portp->refcount--;	spin_unlock_irqrestore(&stli_lock, flags);	for (;;) {		stli_mkasysigs(&portp->asig, 1, 1);		if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS,		    &portp->asig, sizeof(asysigs_t), 0)) < 0)			break;		if (tty_hung_up_p(filp) ||		    ((portp->flags & ASYNC_INITIALIZED) == 0)) {			if (portp->flags & ASYNC_HUP_NOTIFY)				rc = -EBUSY;			else				rc = -ERESTARTSYS;			break;		}		if (((portp->flags & ASYNC_CLOSING) == 0) &&		    (doclocal || (portp->sigs & TIOCM_CD))) {			break;		}		if (signal_pending(current)) {			rc = -ERESTARTSYS;			break;		}		interruptible_sleep_on(&portp->open_wait);	}	spin_lock_irqsave(&stli_lock, flags);	if (! tty_hung_up_p(filp))		portp->refcount++;	portp->openwaitcnt--;	spin_unlock_irqrestore(&stli_lock, flags);	return rc;}/*****************************************************************************//* *	Write routine. Take the data and put it in the shared memory ring *	queue. If port is not already sending chars then need to mark the *	service bits for this port. */static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count){	cdkasy_t __iomem *ap;	cdkhdr_t __iomem *hdrp;	unsigned char __iomem *bits;	unsigned char __iomem *shbuf;	unsigned char *chbuf;	struct stliport *portp;	struct stlibrd *brdp;	unsigned int len, stlen, head, tail, size;	unsigned long flags;	if (tty == stli_txcooktty)		stli_flushchars(tty);	portp = tty->driver_data;	if (portp == NULL)		return 0;	if (portp->brdnr >= stli_nrbrds)		return 0;	brdp = stli_brds[portp->brdnr];	if (brdp == NULL)		return 0;	chbuf = (unsigned char *) buf;/* *	All data is now local, shove as much as possible into shared memory. */	spin_lock_irqsave(&brd_lock, flags);	EBRDENABLE(brdp);	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);	head = (unsigned int) readw(&ap->txq.head);	tail = (unsigned int) readw(&ap->txq.tail);	if (tail != ((unsigned int) readw(&ap->txq.tail)))		tail = (unsigned int) readw(&ap->txq.tail);	size = portp->txsize;	if (head >= tail) {		len = size - (head - tail) - 1;		stlen = size - head;	} else {		len = tail - head - 1;		stlen = len;	}	len = min(len, (unsigned int)count);	count = 0;	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);	while (len > 0) {		stlen = min(len, stlen);		memcpy_toio(shbuf + head, chbuf, stlen);		chbuf += stlen;		len -= stlen;		count += stlen;		head += stlen;		if (head >= size) {			head = 0;			stlen = tail;		}	}	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);	writew(head, &ap->txq.head);	if (test_bit(ST_TXBUSY, &portp->state)) {		if (readl(&ap->changed.data) & DT_TXEMPTY)			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);	}	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_TXBUSY, &portp->state);	EBRDDISABLE(brdp);	spin_unlock_irqrestore(&brd_lock, flags);	return(count);}/*****************************************************************************//* *	Output a single character. We put it into a temporary local buffer *	(for speed) then write out that buffer when the flushchars routine *	is called. There is a safety catch here so that if some other port *	writes chars before the current buffer has been, then we write them *	first them do the new ports. */static void stli_putchar(struct tty_struct *tty, unsigned char ch){	if (tty != stli_txcooktty) {		if (stli_txcooktty != NULL)			stli_flushchars(stli_txcooktty);		stli_txcooktty = tty;	}	stli_txcookbuf[stli_txcooksize++] = ch;}/*****************************************************************************//* *	Transfer characters from the local TX cooking buffer to the board. *	We sort of ignore the tty that gets passed in here. We rely on the *	info stored with the TX cook buffer to tell us which port to flush *	the data on. In any case we clean out the TX cook buffer, for re-use *	by someone else. */static void stli_flushchars(struct tty_struct *tty){	cdkhdr_t __iomem *hdrp;	unsigned char __iomem *bits;	cdkasy_t __iomem *ap;	struct tty_struct *cooktty;	struct stliport *portp;	struct stlibrd *brdp;	unsigned int len, stlen, head, tail, size, count, cooksize;	unsigned char *buf;	unsigned char __iomem *shbuf;	unsigned long flags;	cooksize = stli_txcooksize;	cooktty = stli_txcooktty;	stli_txcooksize = 0;	stli_txcookrealsize = 0;	stli_txcooktty = NULL;	if (tty == NULL)		return;	if (cooktty == NULL)		return;

⌨️ 快捷键说明

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