📄 tylib.c
字号:
{ tyFlushRd (pTyDev); tyFlushWrt (pTyDev); }/********************************************************************************* tyFlushRd - clear out a tty device descriptor's read buffer*/LOCAL void tyFlushRd ( FAST TY_DEV_ID pTyDev /* ptr to tty dev descriptor to clear */ ) { int prevErrno; /* get exclusive access to the device */ semTake (&pTyDev->mutexSem, WAIT_FOREVER); /* mark as flushing so read interrupts won't attempt to manipulate ring */ pTyDev->rdState.flushingRdBuf = TRUE; rngFlush (pTyDev->rdBuf); prevErrno = errno; semTake (&pTyDev->rdSyncSem, NO_WAIT); if (errno == S_objLib_OBJ_UNAVAILABLE) /* OK if semaphore not avail. */ errno = prevErrno; pTyDev->lnNBytes = 0; pTyDev->lnBytesLeft = 0; tyRdXoff (pTyDev, FALSE); /* output an XON if necessary */ pTyDev->rdState.flushingRdBuf = FALSE; semGive (&pTyDev->mutexSem); }/********************************************************************************* tyFlushWrt - clear out a tty device descriptor's write buffer*/LOCAL void tyFlushWrt ( FAST TY_DEV_ID pTyDev /* ptr to tty dev descriptor to clear */ ) { /* get exclusive access to the device */ semTake (&pTyDev->mutexSem, WAIT_FOREVER); /* mark as flushing so tx interrupts won't attempt to manipulate ring */ pTyDev->wrtState.flushingWrtBuf = TRUE; rngFlush (pTyDev->wrtBuf); semGive (&pTyDev->wrtSyncSem); pTyDev->wrtState.flushingWrtBuf = FALSE; semGive (&pTyDev->mutexSem); if (_func_selWakeupAll != NULL) /* wake up any writers in select */ (* _func_selWakeupAll) (&pTyDev->selWakeupList, SELWRITE); }/********************************************************************************* tyAbortFuncSet - set the abort function** This routine sets the function that will be called when the abort* character is received on a tty. There is only one global abort function,* used for any tty on which OPT_ABORT is enabled. When the abort character is* received from a tty with OPT_ABORT set, the function specified in <func> will* be called, with no parameters, from interrupt level.** Setting an abort function of NULL will disable the abort function.** RETURNS: N/A** SEE ALSO: tyAbortSet()*/void tyAbortFuncSet ( FUNCPTR func /* routine to call when abort char received */ ) { tyAbortFunc = func; }/********************************************************************************* tyAbortSet - change the abort character** This routine sets the abort character to <ch>.* The default abort character is CTRL-C.** Typing the abort character to any device whose OPT_ABORT option is set* will cause the shell task to be killed and restarted.* Note that the character set by this routine applies to all devices* whose handlers use the standard tty package tyLib.** RETURNS: N/A** SEE ALSO: tyAbortFuncSet()*/void tyAbortSet ( char ch /* char to be abort */ ) { tyAbortChar = ch; }/********************************************************************************* tyBackspaceSet - change the backspace character** This routine sets the backspace character to <ch>.* The default backspace character is CTRL-H.** Typing the backspace character to any device operating in line protocol* mode (OPT_LINE set) will cause the previous character typed to be* deleted, up to the beginning of the current line.* Note that the character set by this routine applies to all devices* whose handlers use the standard tty package tyLib.*** RETURNS: N/A*/void tyBackspaceSet ( char ch /* char to be backspace */ ) { tyBackspaceChar = ch; }/********************************************************************************* tyDeleteLineSet - change the line-delete character** This routine sets the line-delete character to <ch>.* The default line-delete character is CTRL-U.** Typing the delete character to any device operating in line protocol* mode (OPT_LINE set) will cause all characters in the current* line to be deleted.* Note that the character set by this routine applies to all devices* whose handlers use the standard tty package tyLib.*** RETURNS: N/A*/void tyDeleteLineSet ( char ch /* char to be line-delete */ ) { tyDeleteLineChar = ch; }/********************************************************************************* tyEOFSet - change the end-of-file character** This routine sets the EOF character to <ch>.* The default EOF character is CTRL-D.** Typing the EOF character to any device operating in line protocol mode* (OPT_LINE set) will cause no character to be entered in the current* line, but will cause the current line to be terminated (thus without a newline* character). The line is made available to reading tasks. Thus, if the EOF* character is the first character input on a line, a line length of zero* characters is returned to the reader. This is the standard end-of-file* indication on a read call. Note that the EOF character set by this routine* will apply to all devices whose handlers use the standard tty package tyLib.*** RETURNS: N/A*/void tyEOFSet ( char ch /* char to be EOF */ ) { tyEofChar = ch; }/********************************************************************************* tyMonitorTrapSet - change the trap-to-monitor character** This routine sets the trap-to-monitor character to <ch>.* The default trap-to-monitor character is CTRL-X.** Typing the trap-to-monitor character to any device whose OPT_MON_TRAP option* is set will cause the resident ROM monitor to be entered, if one is present.* Once the ROM monitor is entered, the normal multitasking system is halted.** Note that the trap-to-monitor character set by this routine will apply to all* devices whose handlers use the standard tty package tyLib. Also note that* not all systems have a monitor trap available.** RETURNS: N/A*/void tyMonitorTrapSet ( char ch /* char to be monitor trap */ ) { tyMonTrapChar = ch; }/********************************************************************************* tyIoctl - handle device control requests** This routine handles ioctl() requests for tty devices. The I/O control* functions for tty devices are described in the manual entry for tyLib.** BUGS:* In line protocol mode (OPT_LINE option set), the FIONREAD function* actually returns the number of characters available plus the number of* lines in the buffer. Thus, if five lines consisting of just NEWLINEs were* in the input buffer, the FIONREAD function would return the value ten* (five characters + five lines).** RETURNS: OK or ERROR.** VARARGS2 - not all requests include an arg.*/STATUS tyIoctl ( FAST TY_DEV_ID pTyDev, /* ptr to device to control */ int request, /* request code */ int arg /* some argument */ ) { FAST int status = OK; int oldOptions; switch (request) { case FIONREAD: *((int *) arg) = rngNBytes (pTyDev->rdBuf); break; case FIONWRITE: *((int *) arg) = rngNBytes (pTyDev->wrtBuf); break; case FIOFLUSH: tyFlush (pTyDev); break; case FIOWFLUSH: tyFlushWrt (pTyDev); break; case FIORFLUSH: tyFlushRd (pTyDev); break; case FIOGETOPTIONS: return (pTyDev->options); case FIOSETOPTIONS: /* now same as FIOOPTIONS */ oldOptions = pTyDev->options; pTyDev->options = arg; if ((oldOptions & OPT_LINE) != (pTyDev->options & OPT_LINE)) tyFlushRd (pTyDev); if ((oldOptions & OPT_TANDEM) && !(pTyDev->options & OPT_TANDEM)) { /* TANDEM option turned off: XON receiver and transmitter */ tyRdXoff (pTyDev, FALSE); /* output XON if necessary */ tyWrtXoff (pTyDev, FALSE); /* restart xmitter if nec. */ } break; case FIOCANCEL: semTake (&pTyDev->mutexSem, WAIT_FOREVER); pTyDev->rdState.canceled = TRUE; semGive (&pTyDev->rdSyncSem); pTyDev->wrtState.canceled = TRUE; semGive (&pTyDev->wrtSyncSem); semGive (&pTyDev->mutexSem); break; case FIOISATTY: status = TRUE; break; case FIOPROTOHOOK: pTyDev->protoHook = (FUNCPTR) arg; break; case FIOPROTOARG: pTyDev->protoArg = arg; break; case FIORBUFSET: semTake (&pTyDev->mutexSem, WAIT_FOREVER); pTyDev->rdState.flushingRdBuf = TRUE; if (pTyDev->rdBuf) rngDelete (pTyDev->rdBuf); if ((pTyDev->rdBuf = rngCreate (arg)) == NULL) status = ERROR; pTyDev->rdState.flushingRdBuf = FALSE; semGive (&pTyDev->mutexSem); break; case FIOWBUFSET: semTake (&pTyDev->mutexSem, WAIT_FOREVER); pTyDev->wrtState.flushingWrtBuf = TRUE; if (pTyDev->wrtBuf) rngDelete (pTyDev->wrtBuf); if ((pTyDev->wrtBuf = rngCreate (arg)) == NULL) status = ERROR; pTyDev->wrtState.flushingWrtBuf = FALSE; semGive (&pTyDev->mutexSem); break; case FIOSELECT: if (_func_selTyAdd != NULL) (* _func_selTyAdd) (pTyDev, arg); break; case FIOUNSELECT: if (_func_selTyDelete != NULL) (* _func_selTyDelete) (pTyDev, arg); break; default: errnoSet (S_ioLib_UNKNOWN_REQUEST); status = ERROR; } return (status); }/* raw mode I/O routines *//********************************************************************************* tyWrite - do a task-level write for a tty device** This routine handles the task-level portion of the tty handler's* write function.** INTERNAL* This routine is not the only place characters are put into* the buffer: the read echo in tyIRd may put chars in output* ring as well. tyIRd is of course not blocked by the mutexSem,* and we don't want to lock out interrupts for the entire time* we are copying data to ring. So we we set wrtBufBusy while we* are putting into the ring buffer, and tyIRd drops echo chars* while this flag is set. The problem with this is that some* input chars may not get echoed. This shouldn't be a problem* for interactive stuff, since it only occurs when there is* output going on. But for a serial protocol that relied on* echo, like echoplex, it could be a problem.** RETURNS: The number of bytes actually written to the device.*/int tyWrite ( FAST TY_DEV_ID pTyDev, /* ptr to device structure */ char *buffer, /* buffer of data to write */ FAST int nbytes /* number of bytes in buffer */ ) { FAST int bytesput; int nbStart = nbytes; pTyDev->wrtState.canceled = FALSE; while (nbytes > 0) { /* XXX * mutexSem is "safe" from task deletion, but sync semaphore can't be; * if task is deleted after getting syncSem but before getting mutexSem, * tty channel will be hung. */ semTake (&pTyDev->wrtSyncSem, WAIT_FOREVER); semTake (&pTyDev->mutexSem, WAIT_FOREVER); if (pTyDev->wrtState.canceled) { semGive (&pTyDev->mutexSem); errnoSet (S_ioLib_CANCELLED); return (nbStart - nbytes); } /* set wrtBufBusy while are putting data into the ring buffer to * inhibit tyIRd echoing chars - see description of problem above */ pTyDev->wrtState.wrtBufBusy = TRUE; bytesput = rngBufPut (pTyDev->wrtBuf, buffer, nbytes); pTyDev->wrtState.wrtBufBusy = FALSE; tyTxStartup (pTyDev); /* if xmitter not busy, start it */ nbytes -= bytesput; buffer += bytesput; /* If more room in ringId, enable next writer. */ if (rngFreeBytes (pTyDev->wrtBuf) > 0) semGive (&pTyDev->wrtSyncSem); semGive (&pTyDev->mutexSem); } return (nbStart); }/********************************************************************************* tyRead - do a task-level read for a tty device** This routine handles the task-level portion of the tty handler's read* function. It reads into the buffer up to <maxbytes> available bytes.** This routine should only be called from serial device drivers.** RETURNS: The number of bytes actually read into the buffer.*/int tyRead ( FAST TY_DEV_ID pTyDev, /* device to read */ char *buffer, /* buffer to read into */ int maxbytes /* maximum length of read */ ) { FAST int nbytes; FAST RING_ID ringId; FAST int nn; int freeBytes; pTyDev->rdState.canceled = FALSE; FOREVER { /* XXX * mutexSem is "safe" from task deletion, but sync semaphore can't be; * if task is deleted after getting syncSem but before getting mutexSem, * tty channel will be hung. */ semTake (&pTyDev->rdSyncSem, WAIT_FOREVER); semTake (&pTyDev->mutexSem, WAIT_FOREVER); if (pTyDev->rdState.canceled) { semGive (&pTyDev->mutexSem); errnoSet (S_ioLib_CANCELLED); return (0); } ringId = pTyDev->rdBuf; if (!rngIsEmpty (ringId)) break; semGive (&pTyDev->mutexSem); } /* we exit the above loop with the mutex semaphore taken and certain * that the ring buffer is not empty */ /* get characters from ring buffer */ if (pTyDev->options & OPT_LINE) { if (pTyDev->lnBytesLeft == 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -