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

📄 tylib.c

📁 VxWorks操作系统内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	    RNG_ELEM_GET (ringId, &pTyDev->lnBytesLeft, nn);	nbytes = min ((int)pTyDev->lnBytesLeft, maxbytes);	rngBufGet (ringId, buffer, nbytes);	pTyDev->lnBytesLeft -= nbytes;	}    else	nbytes = rngBufGet (ringId, buffer, maxbytes);    /* check if XON needs to be output */    if ((pTyDev->options & OPT_TANDEM) && pTyDev->rdState.xoff)	{	freeBytes = rngFreeBytes (ringId);	if (pTyDev->options & OPT_LINE)	    freeBytes -= pTyDev->lnNBytes + 1;	if (freeBytes > tyXonThreshold)	    tyRdXoff (pTyDev, FALSE);	}    /* If more characters in ring, enable next reader.     * This is necessary in case several tasks blocked when ring was empty -     * each must be awoken now     */    if (!rngIsEmpty (ringId))	semGive (&pTyDev->rdSyncSem);    semGive (&pTyDev->mutexSem);    return (nbytes);    }/********************************************************************************* tyITx - interrupt-level output** This routine gets a single character to be output to a device.  It looks at* the ring buffer for <pTyDev> and gives the caller the next available* character, if there is one.  The character to be output is copied to <pChar>.** RETURNS:* OK if there are more characters to send, or* ERROR if there are no more characters.*/STATUS tyITx    (    FAST TY_DEV_ID pTyDev,   /* pointer to tty device descriptor */    char *pChar              /* where to put character to be output */    )    {    FAST RING_ID	ringId = pTyDev->wrtBuf;    FAST int		nn;    /* check if we need to output XON/XOFF for the read side */    if (pTyDev->rdState.pending)	{	pTyDev->rdState.pending = FALSE;	*pChar = pTyDev->rdState.xoff ? XOFF : XON;	/* keep track of the max chars received after we sent xoff - see note	 * at declaration of tyXoffChars	 */	if (pTyDev->rdState.xoff)		/** TEMP **/	    {					/** TEMP **/	    if (tyXoffChars > tyXoffMax)	/** TEMP **/		tyXoffMax = tyXoffChars;	/** TEMP **/	    tyXoffChars = 0;			/** TEMP **/	    }					/** TEMP **/	}    /* if output is in XOFF, or task level is flushing output buffers,     * then just turn off xmitter and return */    else if (pTyDev->wrtState.xoff || pTyDev->wrtState.flushingWrtBuf)	pTyDev->wrtState.busy = FALSE;    /* check for linefeed needed after carriage return (SPR27682) */    /* formerly, this was a check for carriage return needed after      * linefeed */    else if (pTyDev->wrtState.cr)	{	*pChar = '\n';	pTyDev->wrtState.cr   = FALSE;	}    /* check for more characters to output */    else if (RNG_ELEM_GET (ringId, pChar, nn) == 0)	/* no more chars */	pTyDev->wrtState.busy = FALSE;    else	{	/* got a character to be output */	pTyDev->wrtState.busy = TRUE;	/* check for linefeed needs to be added after carriage return (SPR27682) */	/* formerly, this was a check for carriage return needs to be added after      * linefeed */	if ((pTyDev->options & OPT_CRMOD) && (*pChar == '\n'))    {        *pChar = '\r';	    pTyDev->wrtState.cr = TRUE;    }	/* when we pass the write threshhold, give write synchonization	 * and release tasks pended in select */	if (rngFreeBytes (ringId) == tyWrtThreshold)	    {	    semGive (&pTyDev->wrtSyncSem);	    if (_func_selWakeupAll != NULL)		(* _func_selWakeupAll) (&pTyDev->selWakeupList, SELWRITE);	    }	}    return (pTyDev->wrtState.busy ? OK : ERROR);    }/********************************************************************************* tyIRd - interrupt-level input** This routine handles interrupt-level character input for tty devices.  A* device driver calls this routine when it has received a character.  This* routine adds the character to the ring buffer for the specified device, and* gives a semaphore if a task is waiting for it.** This routine also handles all the special characters, as specified in* the option word for the device, such as X-on, X-off, NEWLINE, or backspace.** RETURNS: OK, or ERROR if the ring buffer is full.*/STATUS tyIRd    (    FAST TY_DEV_ID pTyDev,      /* ptr to tty device descriptor */    FAST char inchar            /* character read */    )    {    FAST RING_ID	ringId;    FAST int		nn;    int			freeBytes;    BOOL		releaseTaskLevel;    FAST int		options		= pTyDev->options;    BOOL		charEchoed	= FALSE;    STATUS		status		= OK;    /* if task level is flushing input buffers, then just return */    if (pTyDev->rdState.flushingRdBuf)	return (ERROR);    /* If there is an input hook routine to call, call it now.     * The hook routine will return TRUE if it doesn't want us     * to process the character further.     */    if (pTyDev->protoHook &&	(*pTyDev->protoHook)(pTyDev->protoArg, inchar) == TRUE)	{	return (status);	}    /* strip off parity bit if '7 bit' option set */    if (options & OPT_7_BIT)	inchar &= 0x7f;    /* check for abort */    if ((inchar == tyAbortChar) && (options & OPT_ABORT) && tyAbortFunc != NULL)	(*tyAbortFunc) ();    /* check for trap to rom monitor */    else if ((inchar == tyMonTrapChar) && (options & OPT_MON_TRAP))	{	/* attempt to do the reboot from task level, go down no matter what */	if (_func_excJobAdd != NULL)	    (* _func_excJobAdd) (reboot, BOOT_WARM_AUTOBOOT);	else	    reboot (BOOT_WARM_AUTOBOOT);	}    /* check for XON/XOFF received */    else if (((inchar == XOFF) || (inchar == XON)) && (options & OPT_TANDEM))	tyWrtXoff (pTyDev, (inchar == XOFF));    else	{	/* count number of chars received while in xoff - see note at	 * declaration of tyXoffChars	 */	if (pTyDev->rdState.xoff)	/** TEMP **/	    tyXoffChars++;		/** TEMP **/	/* check for carriage return needs to be turned into linefeed */	if ((options & OPT_CRMOD) && (inchar == '\r'))	    inchar = '\n';	/* check for output echo required	 * only echo if the write buffer isn't being deleted or	 * written to at task level - note that this implies that characters	 * aren't guaranteed to be echoed.	 */	if ((options & OPT_ECHO) &&	    (!pTyDev->wrtState.wrtBufBusy && !pTyDev->wrtState.flushingWrtBuf))	    {	    ringId = pTyDev->wrtBuf;	    /* echo the char.  some special chars are echoed differently */	    if (options & OPT_LINE)		{		if (inchar == tyDeleteLineChar)		    {		    /* echo a newline */		    RNG_ELEM_PUT (ringId, '\n', nn);		    charEchoed = TRUE;		    }		else if (inchar == tyBackspaceChar)		    {		    if (pTyDev->lnNBytes != 0)			{			/* echo BS-space-BS */			rngBufPut (ringId, " ", 3);			charEchoed = TRUE;			}		    }		else if ((inchar < 0x20) && (inchar != '\n'))		    {		    /* echo ^-char */		    RNG_ELEM_PUT (ringId, '^', nn);		    RNG_ELEM_PUT (ringId, inchar + '@', nn);		    charEchoed = TRUE;		    }		else		    {		    RNG_ELEM_PUT (ringId, inchar, nn);		    charEchoed = TRUE;		    }		}	    else		{		/* just echo the char */		RNG_ELEM_PUT (ringId, inchar, nn);		charEchoed = TRUE;		}	    if (charEchoed)		tyTxStartup (pTyDev);	    }	/* put the char in the read buffer. */	ringId = pTyDev->rdBuf;	releaseTaskLevel = FALSE;	if (!(options & OPT_LINE))	    {	    /* not line-mode;	     * just enter character and make immediately available to tasks */	    if (RNG_ELEM_PUT (ringId, inchar, nn) == 0)		status = ERROR;			/* buffer full, not entered */	    /* only give the sync sem on first char */	    if (rngNBytes (ringId) == 1)		releaseTaskLevel = TRUE;	    }	else	    {	    /* line-mode;	     * process backspace, line-delete, EOF, and newline chars special */	    freeBytes = rngFreeBytes (ringId);	    if (inchar == tyBackspaceChar)		{		if (pTyDev->lnNBytes != 0)		    pTyDev->lnNBytes--;		}	    else if (inchar == tyDeleteLineChar)		pTyDev->lnNBytes = 0;	    else if (inchar == tyEofChar)		{		/* EOF - check for at least one free byte so there is room		 * to put the line byte count below */		if (freeBytes > 0)		    releaseTaskLevel = TRUE;		}	    else		{		if (freeBytes >= 2)		    {		    if (freeBytes >= (pTyDev->lnNBytes + 2))			pTyDev->lnNBytes++;		    else			status = ERROR;	/* no room, overwriting last char */		    rngPutAhead (ringId, inchar, (int)pTyDev->lnNBytes);		    if ((inchar == '\n') || (pTyDev->lnNBytes == 255))			releaseTaskLevel = TRUE;		    }		else		    status = ERROR;	/* no room, not even for overwriting */		}	    /* if line termination indicated, put line byte count	     * in 0th character of line and advance ring buffer pointers */	    if (releaseTaskLevel)		{		rngPutAhead (ringId, (char) pTyDev->lnNBytes, 0);		rngMoveAhead (ringId, (int) pTyDev->lnNBytes + 1);		pTyDev->lnNBytes = 0;		}	    }	/* check if XON/XOFF needs to be output */	if (options & OPT_TANDEM)	    {	    freeBytes = rngFreeBytes (ringId);	    if (pTyDev->options & OPT_LINE)		freeBytes -= pTyDev->lnNBytes + 1;	    if (!pTyDev->rdState.xoff)		{		/* if input buffer is close to full, send XOFF */		if (freeBytes < tyXoffThreshold)		    tyRdXoff (pTyDev, TRUE);		}	    else		{		/* if input buffer has enough room now, send XON */		if (freeBytes > tyXonThreshold)		    tyRdXoff (pTyDev, FALSE);		}	    }	/* if task level has new input then give read semaphore and	 * release tasks pended in select	 */	if (releaseTaskLevel)	    {	    semGive (&pTyDev->rdSyncSem);	    if (_func_selWakeupAll != NULL)		(* _func_selWakeupAll) (&pTyDev->selWakeupList, SELREAD);	    }	}    return (status);    }/******************************************************************************** tyRdXoff - set read side xon/xoff** This routine sets the read side xon/xoff to the specified state.* A flag will be set indicating that the next character sent by the* transmit side should be the xon or xoff character.  If the transmitter* is idle, it is started.*/LOCAL void tyRdXoff    (    FAST TY_DEV_ID pTyDev,      /* pointer to device structure */    FAST BOOL xoff    )    {    FAST int oldlevel;    oldlevel = intLock ();				/* LOCK INTERRUPTS */    if (pTyDev->rdState.xoff != xoff)	{	pTyDev->rdState.xoff	= xoff;	pTyDev->rdState.pending = TRUE;	if (!pTyDev->wrtState.busy)	    {	    pTyDev->wrtState.busy = TRUE;	    intUnlock (oldlevel);			/* UNLOCK INTERRUPTS */	    (*pTyDev->txStartup) (pTyDev);	    return;	    }	}    intUnlock (oldlevel);                   		/* UNLOCK INTERRUPTS */    }/******************************************************************************** tyWrtXoff - set write side xon/xoff** This routine sets the write side xon/xoff to the specified state.* If the new state is xon and the transmitter is idle, it is started.**/LOCAL void tyWrtXoff    (    FAST TY_DEV_ID pTyDev,      /* pointer to device structure */    BOOL xoff    )    {    FAST int oldlevel;    /* restart an XOFF'd transmitter */    oldlevel = intLock ();				/* LOCK INTERRUPTS */    if (pTyDev->wrtState.xoff != xoff)	{	pTyDev->wrtState.xoff = xoff;	if (!xoff)	    {	    if (!pTyDev->wrtState.busy)		{		pTyDev->wrtState.busy = TRUE;		intUnlock (oldlevel);                  	/* UNLOCK INTERRUPTS */		(*pTyDev->txStartup) (pTyDev);		return;		}	    }	}    intUnlock (oldlevel);	                   	/* UNLOCK INTERRUPTS */    }/******************************************************************************** tyTxStartup - startup transmitter if necessary** This routine starts the transmitter if it is not already busy.* A flag is maintained so that starting the transmitter can be properly* interlocked with interrupt level, but the startup routine itself is* called at the interrupt level of the caller.*/LOCAL void tyTxStartup    (    FAST TY_DEV_ID pTyDev       /* pointer to device structure */    )    {    FAST int oldlevel;    /* if xmitter not busy, start it */    if (!pTyDev->wrtState.busy)	{	oldlevel = intLock ();				/* LOCK INTERRUPTS */	/* check xmitter busy again, now that we're locked out */	if (!pTyDev->wrtState.busy)	    {	    pTyDev->wrtState.busy = TRUE;	    intUnlock (oldlevel);                   	/* UNLOCK INTERRUPTS */	    (*pTyDev->txStartup) (pTyDev);	    return;	    }	intUnlock (oldlevel);                   	/* UNLOCK INTERRUPTS */	}    }

⌨️ 快捷键说明

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