diff options
author | Joel Sherrill <joel.sherrill@OARcorp.com> | 2010-06-28 18:48:32 +0000 |
---|---|---|
committer | Joel Sherrill <joel.sherrill@OARcorp.com> | 2010-06-28 18:48:32 +0000 |
commit | 6cc69f188baf99a6a1c28c0106d6ebb8d727c9ea (patch) | |
tree | 4414b3aa2b09ee22acb9dc8b2a58d215c919490e /cpukit/libcsupport/src/termios.c | |
parent | 2010-06-28 Joel Sherrill <joel.sherrill@oarcorp.com> (diff) | |
download | rtems-6cc69f188baf99a6a1c28c0106d6ebb8d727c9ea.tar.bz2 |
2010-06-28 Joel Sherrill <joel.sherrilL@OARcorp.com>
* libcsupport/src/termios.c: Formatting.
Diffstat (limited to 'cpukit/libcsupport/src/termios.c')
-rw-r--r-- | cpukit/libcsupport/src/termios.c | 2337 |
1 files changed, 1167 insertions, 1170 deletions
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c index 894d870ec9..fd84133b46 100644 --- a/cpukit/libcsupport/src/termios.c +++ b/cpukit/libcsupport/src/termios.c @@ -34,15 +34,15 @@ /* * The size of the cooked buffer */ -#define CBUFSIZE (rtems_termios_cbufsize) +#define CBUFSIZE (rtems_termios_cbufsize) /* * The sizes of the raw message buffers. * On most architectures it is quite a bit more * efficient if these are powers of two. */ -#define RAW_INPUT_BUFFER_SIZE (rtems_termios_raw_input_size) -#define RAW_OUTPUT_BUFFER_SIZE (rtems_termios_raw_output_size) +#define RAW_INPUT_BUFFER_SIZE (rtems_termios_raw_input_size) +#define RAW_OUTPUT_BUFFER_SIZE (rtems_termios_raw_output_size) /* fields for "flow_ctrl" status */ #define FL_IREQXOF 1 /* input queue requests stop of incoming data */ @@ -57,24 +57,24 @@ #define FL_MDXOF 0x400 /* output controlled with XON/XOFF protocol */ #define NODISC(n) \ - { NULL, NULL, NULL, NULL, \ - NULL, NULL, NULL, NULL } + { NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL } /* * FIXME: change rtems_termios_linesw entries consistant with rtems_termios_linesw entry usage... */ -struct rtems_termios_linesw rtems_termios_linesw[MAXLDISC] = +struct rtems_termios_linesw rtems_termios_linesw[MAXLDISC] = { - NODISC(0), /* 0- termios-built-in */ - NODISC(1), /* 1- defunct */ - NODISC(2), /* 2- NTTYDISC */ - NODISC(3), /* TABLDISC */ - NODISC(4), /* SLIPDISC */ - NODISC(5), /* PPPDISC */ - NODISC(6), /* loadable */ - NODISC(7), /* loadable */ + NODISC(0), /* 0- termios-built-in */ + NODISC(1), /* 1- defunct */ + NODISC(2), /* 2- NTTYDISC */ + NODISC(3), /* TABLDISC */ + NODISC(4), /* SLIPDISC */ + NODISC(5), /* PPPDISC */ + NODISC(6), /* loadable */ + NODISC(7), /* loadable */ }; -int rtems_termios_nlinesw = sizeof (rtems_termios_linesw) / sizeof (rtems_termios_linesw[0]); +int rtems_termios_nlinesw = sizeof (rtems_termios_linesw) / sizeof (rtems_termios_linesw[0]); extern struct rtems_termios_tty *rtems_termios_ttyHead; extern struct rtems_termios_tty *rtems_termios_ttyTail; @@ -113,219 +113,220 @@ rtems_termios_open ( const rtems_termios_callbacks *callbacks ) { - rtems_status_code sc; - rtems_libio_open_close_args_t *args = arg; - struct rtems_termios_tty *tty; - - /* - * See if the device has already been opened - */ - sc = rtems_semaphore_obtain (rtems_termios_ttyMutex, - RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - return sc; - for (tty = rtems_termios_ttyHead ; tty != NULL ; tty = tty->forw) { - if ((tty->major == major) && (tty->minor == minor)) - break; - } - if (tty == NULL) { - static char c = 'a'; - - /* - * Create a new device - */ - tty = calloc (1, sizeof (struct rtems_termios_tty)); - if (tty == NULL) { - rtems_semaphore_release (rtems_termios_ttyMutex); - return RTEMS_NO_MEMORY; - } - /* - * allocate raw input buffer - */ - tty->rawInBuf.Size = RAW_INPUT_BUFFER_SIZE; - tty->rawInBuf.theBuf = malloc (tty->rawInBuf.Size); - if (tty->rawInBuf.theBuf == NULL) { - free(tty); - rtems_semaphore_release (rtems_termios_ttyMutex); - return RTEMS_NO_MEMORY; - } - /* - * allocate raw output buffer - */ - tty->rawOutBuf.Size = RAW_OUTPUT_BUFFER_SIZE; - tty->rawOutBuf.theBuf = malloc (tty->rawOutBuf.Size); - if (tty->rawOutBuf.theBuf == NULL) { - free((void *)(tty->rawInBuf.theBuf)); - free(tty); - rtems_semaphore_release (rtems_termios_ttyMutex); - return RTEMS_NO_MEMORY; - } - /* - * allocate cooked buffer - */ - tty->cbuf = malloc (CBUFSIZE); - if (tty->cbuf == NULL) { - free((void *)(tty->rawOutBuf.theBuf)); - free((void *)(tty->rawInBuf.theBuf)); - free(tty); - rtems_semaphore_release (rtems_termios_ttyMutex); - return RTEMS_NO_MEMORY; - } - /* - * Initialize wakeup callbacks - */ - tty->tty_snd.sw_pfn = NULL; - tty->tty_snd.sw_arg = NULL; - tty->tty_rcv.sw_pfn = NULL; - tty->tty_rcv.sw_arg = NULL; - tty->tty_rcvwakeup = 0; - - /* - * link tty - */ - tty->forw = rtems_termios_ttyHead; - tty->back = NULL; - if (rtems_termios_ttyHead != NULL) - rtems_termios_ttyHead->back = tty; - rtems_termios_ttyHead = tty; - if (rtems_termios_ttyTail == NULL) - rtems_termios_ttyTail = tty; - - tty->minor = minor; - tty->major = major; - - /* - * Set up mutex semaphores - */ - sc = rtems_semaphore_create ( - rtems_build_name ('T', 'R', 'i', c), - 1, - RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, - RTEMS_NO_PRIORITY, - &tty->isem); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - sc = rtems_semaphore_create ( - rtems_build_name ('T', 'R', 'o', c), - 1, - RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, - RTEMS_NO_PRIORITY, - &tty->osem); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - sc = rtems_semaphore_create ( - rtems_build_name ('T', 'R', 'x', c), - 0, - RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO, - RTEMS_NO_PRIORITY, - &tty->rawOutBuf.Semaphore); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - tty->rawOutBufState = rob_idle; - - /* - * Set callbacks - */ - tty->device = *callbacks; - - /* - * Create I/O tasks - */ - if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { - sc = rtems_task_create ( + rtems_status_code sc; + rtems_libio_open_close_args_t *args = arg; + struct rtems_termios_tty *tty; + + /* + * See if the device has already been opened + */ + sc = rtems_semaphore_obtain (rtems_termios_ttyMutex, + RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + return sc; + for (tty = rtems_termios_ttyHead ; tty != NULL ; tty = tty->forw) { + if ((tty->major == major) && (tty->minor == minor)) + break; + } + if (tty == NULL) { + static char c = 'a'; + + /* + * Create a new device + */ + tty = calloc (1, sizeof (struct rtems_termios_tty)); + if (tty == NULL) { + rtems_semaphore_release (rtems_termios_ttyMutex); + return RTEMS_NO_MEMORY; + } + /* + * allocate raw input buffer + */ + tty->rawInBuf.Size = RAW_INPUT_BUFFER_SIZE; + tty->rawInBuf.theBuf = malloc (tty->rawInBuf.Size); + if (tty->rawInBuf.theBuf == NULL) { + free(tty); + rtems_semaphore_release (rtems_termios_ttyMutex); + return RTEMS_NO_MEMORY; + } + /* + * allocate raw output buffer + */ + tty->rawOutBuf.Size = RAW_OUTPUT_BUFFER_SIZE; + tty->rawOutBuf.theBuf = malloc (tty->rawOutBuf.Size); + if (tty->rawOutBuf.theBuf == NULL) { + free((void *)(tty->rawInBuf.theBuf)); + free(tty); + rtems_semaphore_release (rtems_termios_ttyMutex); + return RTEMS_NO_MEMORY; + } + /* + * allocate cooked buffer + */ + tty->cbuf = malloc (CBUFSIZE); + if (tty->cbuf == NULL) { + free((void *)(tty->rawOutBuf.theBuf)); + free((void *)(tty->rawInBuf.theBuf)); + free(tty); + rtems_semaphore_release (rtems_termios_ttyMutex); + return RTEMS_NO_MEMORY; + } + /* + * Initialize wakeup callbacks + */ + tty->tty_snd.sw_pfn = NULL; + tty->tty_snd.sw_arg = NULL; + tty->tty_rcv.sw_pfn = NULL; + tty->tty_rcv.sw_arg = NULL; + tty->tty_rcvwakeup = 0; + + /* + * link tty + */ + tty->forw = rtems_termios_ttyHead; + tty->back = NULL; + if (rtems_termios_ttyHead != NULL) + rtems_termios_ttyHead->back = tty; + rtems_termios_ttyHead = tty; + if (rtems_termios_ttyTail == NULL) + rtems_termios_ttyTail = tty; + + tty->minor = minor; + tty->major = major; + + /* + * Set up mutex semaphores + */ + sc = rtems_semaphore_create ( + rtems_build_name ('T', 'R', 'i', c), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &tty->isem); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + sc = rtems_semaphore_create ( + rtems_build_name ('T', 'R', 'o', c), + 1, + RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &tty->osem); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + sc = rtems_semaphore_create ( + rtems_build_name ('T', 'R', 'x', c), + 0, + RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_FIFO, + RTEMS_NO_PRIORITY, + &tty->rawOutBuf.Semaphore); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + tty->rawOutBufState = rob_idle; + + /* + * Set callbacks + */ + tty->device = *callbacks; + + /* + * Create I/O tasks + */ + if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { + sc = rtems_task_create ( rtems_build_name ('T', 'x', 'T', c), - TERMIOS_TXTASK_PRIO, - TERMIOS_TXTASK_STACKSIZE, - RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | - RTEMS_NO_ASR, - RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, - &tty->txTaskId); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - sc = rtems_task_create ( + TERMIOS_TXTASK_PRIO, + TERMIOS_TXTASK_STACKSIZE, + RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | + RTEMS_NO_ASR, + RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, + &tty->txTaskId); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + sc = rtems_task_create ( rtems_build_name ('R', 'x', 'T', c), - TERMIOS_RXTASK_PRIO, - TERMIOS_RXTASK_STACKSIZE, - RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | - RTEMS_NO_ASR, - RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, - &tty->rxTaskId); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - - } - if ((tty->device.pollRead == NULL) || - (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)){ - sc = rtems_semaphore_create ( - rtems_build_name ('T', 'R', 'r', c), - 0, - RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY, - RTEMS_NO_PRIORITY, - &tty->rawInBuf.Semaphore); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - } - - /* - * Set default parameters - */ - tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; - tty->termios.c_oflag = OPOST | ONLCR | XTABS; - tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; - tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; - - tty->termios.c_cc[VINTR] = '\003'; - tty->termios.c_cc[VQUIT] = '\034'; - tty->termios.c_cc[VERASE] = '\177'; - tty->termios.c_cc[VKILL] = '\025'; - tty->termios.c_cc[VEOF] = '\004'; - tty->termios.c_cc[VEOL] = '\000'; - tty->termios.c_cc[VEOL2] = '\000'; - tty->termios.c_cc[VSTART] = '\021'; - tty->termios.c_cc[VSTOP] = '\023'; - tty->termios.c_cc[VSUSP] = '\032'; - tty->termios.c_cc[VREPRINT] = '\022'; - tty->termios.c_cc[VDISCARD] = '\017'; - tty->termios.c_cc[VWERASE] = '\027'; - tty->termios.c_cc[VLNEXT] = '\026'; - - /* start with no flow control, clear flow control flags */ - tty->flow_ctrl = 0; - /* - * set low/highwater mark for XON/XOFF support - */ - tty->lowwater = tty->rawInBuf.Size * 1/2; - tty->highwater = tty->rawInBuf.Size * 3/4; - /* - * Bump name characer - */ - if (c++ == 'z') - c = 'a'; - - } - args->iop->data1 = tty; - if (!tty->refcount++) { - if (tty->device.firstOpen) - (*tty->device.firstOpen)(major, minor, arg); - /* - * start I/O tasks, if needed - */ - if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { - sc = rtems_task_start(tty->rxTaskId, - rtems_termios_rxdaemon, - (rtems_task_argument)tty); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - - sc = rtems_task_start(tty->txTaskId, - rtems_termios_txdaemon, - (rtems_task_argument)tty); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - } - } - rtems_semaphore_release (rtems_termios_ttyMutex); - return RTEMS_SUCCESSFUL; + TERMIOS_RXTASK_PRIO, + TERMIOS_RXTASK_STACKSIZE, + RTEMS_NO_PREEMPT | RTEMS_NO_TIMESLICE | + RTEMS_NO_ASR, + RTEMS_NO_FLOATING_POINT | RTEMS_LOCAL, + &tty->rxTaskId); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + + } + if ((tty->device.pollRead == NULL) || + (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)){ + sc = rtems_semaphore_create ( + rtems_build_name ('T', 'R', 'r', c), + 0, + RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_PRIORITY, + RTEMS_NO_PRIORITY, + &tty->rawInBuf.Semaphore); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + } + + /* + * Set default parameters + */ + tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL; + tty->termios.c_oflag = OPOST | ONLCR | XTABS; + tty->termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL; + tty->termios.c_lflag = + ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL; + + tty->termios.c_cc[VINTR] = '\003'; + tty->termios.c_cc[VQUIT] = '\034'; + tty->termios.c_cc[VERASE] = '\177'; + tty->termios.c_cc[VKILL] = '\025'; + tty->termios.c_cc[VEOF] = '\004'; + tty->termios.c_cc[VEOL] = '\000'; + tty->termios.c_cc[VEOL2] = '\000'; + tty->termios.c_cc[VSTART] = '\021'; + tty->termios.c_cc[VSTOP] = '\023'; + tty->termios.c_cc[VSUSP] = '\032'; + tty->termios.c_cc[VREPRINT] = '\022'; + tty->termios.c_cc[VDISCARD] = '\017'; + tty->termios.c_cc[VWERASE] = '\027'; + tty->termios.c_cc[VLNEXT] = '\026'; + + /* start with no flow control, clear flow control flags */ + tty->flow_ctrl = 0; + /* + * set low/highwater mark for XON/XOFF support + */ + tty->lowwater = tty->rawInBuf.Size * 1/2; + tty->highwater = tty->rawInBuf.Size * 3/4; + /* + * Bump name characer + */ + if (c++ == 'z') + c = 'a'; + + } + args->iop->data1 = tty; + if (!tty->refcount++) { + if (tty->device.firstOpen) + (*tty->device.firstOpen)(major, minor, arg); + /* + * start I/O tasks, if needed + */ + if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { + sc = rtems_task_start(tty->rxTaskId, + rtems_termios_rxdaemon, + (rtems_task_argument)tty); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + + sc = rtems_task_start(tty->txTaskId, + rtems_termios_txdaemon, + (rtems_task_argument)tty); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + } + } + rtems_semaphore_release (rtems_termios_ttyMutex); + return RTEMS_SUCCESSFUL; } /* @@ -334,102 +335,103 @@ rtems_termios_open ( static void drainOutput (struct rtems_termios_tty *tty) { - rtems_interrupt_level level; - rtems_status_code sc; - - if (tty->device.outputUsesInterrupts != TERMIOS_POLLED) { - rtems_interrupt_disable (level); - while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) { - tty->rawOutBufState = rob_wait; - rtems_interrupt_enable (level); - sc = rtems_semaphore_obtain (tty->rawOutBuf.Semaphore, - RTEMS_WAIT, - RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - rtems_interrupt_disable (level); - } - rtems_interrupt_enable (level); - } + rtems_interrupt_level level; + rtems_status_code sc; + + if (tty->device.outputUsesInterrupts != TERMIOS_POLLED) { + rtems_interrupt_disable (level); + while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) { + tty->rawOutBufState = rob_wait; + rtems_interrupt_enable (level); + sc = rtems_semaphore_obtain (tty->rawOutBuf.Semaphore, + RTEMS_WAIT, + RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + rtems_interrupt_disable (level); + } + rtems_interrupt_enable (level); + } } rtems_status_code rtems_termios_close (void *arg) { - rtems_libio_open_close_args_t *args = arg; - struct rtems_termios_tty *tty = args->iop->data1; - rtems_status_code sc; - - sc = rtems_semaphore_obtain (rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - if (--tty->refcount == 0) { - if (rtems_termios_linesw[tty->t_line].l_close != NULL) { - /* - * call discipline-specific close - */ - sc = rtems_termios_linesw[tty->t_line].l_close(tty); - } - else { - /* - * default: just flush output buffer - */ - sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred (sc); - } - drainOutput (tty); - } - - if (tty->device.outputUsesInterrupts - == TERMIOS_TASK_DRIVEN) { - /* - * send "terminate" to I/O tasks - */ - sc = rtems_event_send( + rtems_libio_open_close_args_t *args = arg; + struct rtems_termios_tty *tty = args->iop->data1; + rtems_status_code sc; + + sc = rtems_semaphore_obtain( + rtems_termios_ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + if (--tty->refcount == 0) { + if (rtems_termios_linesw[tty->t_line].l_close != NULL) { + /* + * call discipline-specific close + */ + sc = rtems_termios_linesw[tty->t_line].l_close(tty); + } + else { + /* + * default: just flush output buffer + */ + sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) { + rtems_fatal_error_occurred (sc); + } + drainOutput (tty); + } + + if (tty->device.outputUsesInterrupts + == TERMIOS_TASK_DRIVEN) { + /* + * send "terminate" to I/O tasks + */ + sc = rtems_event_send( tty->rxTaskId, - TERMIOS_RX_TERMINATE_EVENT); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - sc = rtems_event_send( + TERMIOS_RX_TERMINATE_EVENT); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + sc = rtems_event_send( tty->txTaskId, - TERMIOS_TX_TERMINATE_EVENT); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - } - if (tty->device.lastClose) - (*tty->device.lastClose)(tty->major, tty->minor, arg); - if (tty->forw == NULL) { - rtems_termios_ttyTail = tty->back; - if ( rtems_termios_ttyTail != NULL ) { - rtems_termios_ttyTail->forw = NULL; - } - } - else { - tty->forw->back = tty->back; - } - if (tty->back == NULL) { - rtems_termios_ttyHead = tty->forw; - if ( rtems_termios_ttyHead != NULL ) { - rtems_termios_ttyHead->back = NULL; - } - } - else { - tty->back->forw = tty->forw; - } - rtems_semaphore_delete (tty->isem); - rtems_semaphore_delete (tty->osem); - rtems_semaphore_delete (tty->rawOutBuf.Semaphore); - if ((tty->device.pollRead == NULL) || - (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)) - rtems_semaphore_delete (tty->rawInBuf.Semaphore); - free (tty->rawInBuf.theBuf); - free (tty->rawOutBuf.theBuf); - free (tty->cbuf); - free (tty); - } - rtems_semaphore_release (rtems_termios_ttyMutex); - return RTEMS_SUCCESSFUL; + TERMIOS_TX_TERMINATE_EVENT); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + } + if (tty->device.lastClose) + (*tty->device.lastClose)(tty->major, tty->minor, arg); + if (tty->forw == NULL) { + rtems_termios_ttyTail = tty->back; + if ( rtems_termios_ttyTail != NULL ) { + rtems_termios_ttyTail->forw = NULL; + } + } + else { + tty->forw->back = tty->back; + } + if (tty->back == NULL) { + rtems_termios_ttyHead = tty->forw; + if ( rtems_termios_ttyHead != NULL ) { + rtems_termios_ttyHead->back = NULL; + } + } + else { + tty->back->forw = tty->forw; + } + rtems_semaphore_delete (tty->isem); + rtems_semaphore_delete (tty->osem); + rtems_semaphore_delete (tty->rawOutBuf.Semaphore); + if ((tty->device.pollRead == NULL) || + (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN)) + rtems_semaphore_delete (tty->rawInBuf.Semaphore); + free (tty->rawInBuf.theBuf); + free (tty->rawOutBuf.theBuf); + free (tty->cbuf); + free (tty); + } + rtems_semaphore_release (rtems_termios_ttyMutex); + return RTEMS_SUCCESSFUL; } rtems_status_code rtems_termios_bufsize ( @@ -465,9 +467,9 @@ termios_set_flowctrl(struct rtems_termios_tty *tty) tty->flow_ctrl &= ~FL_OSTOP; /* check for chars in output buffer (or rob_state?) */ if (tty->rawOutBufState != rob_idle) { - /* if chars available, call write function... */ - (*tty->device.write)(tty->minor, - &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1); + /* if chars available, call write function... */ + (*tty->device.write)(tty->minor, + &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1); } /* reenable interrupts */ rtems_interrupt_enable(level); @@ -483,14 +485,12 @@ termios_set_flowctrl(struct rtems_termios_tty *tty) } /* check for incoming RTS/CTS flow control switched off */ - if (( tty->flow_ctrl & FL_MDRTS) && - !(tty->termios.c_cflag & CRTSCTS)) { + if (( tty->flow_ctrl & FL_MDRTS) && !(tty->termios.c_cflag & CRTSCTS)) { /* clear related flags in flow_ctrl */ tty->flow_ctrl &= ~(FL_MDRTS); /* restart remote Tx, if it was stopped */ - if ((tty->flow_ctrl & FL_IRTSOFF) && - (tty->device.startRemoteTx != NULL)) { + if ((tty->flow_ctrl & FL_IRTSOFF) && (tty->device.startRemoteTx != NULL)) { tty->device.startRemoteTx(tty->minor); } tty->flow_ctrl &= ~(FL_IRTSOFF); @@ -516,118 +516,118 @@ termios_set_flowctrl(struct rtems_termios_tty *tty) rtems_status_code rtems_termios_ioctl (void *arg) { - rtems_libio_ioctl_args_t *args = arg; - struct rtems_termios_tty *tty = args->iop->data1; - struct ttywakeup *wakeup = (struct ttywakeup *)args->buffer; - rtems_status_code sc; - - args->ioctl_return = 0; - sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) { - args->ioctl_return = sc; - return sc; - } - switch (args->command) { - default: - if (rtems_termios_linesw[tty->t_line].l_ioctl != NULL) { - sc = rtems_termios_linesw[tty->t_line].l_ioctl(tty,args); - } - else { - sc = RTEMS_INVALID_NUMBER; - } - break; - - case RTEMS_IO_GET_ATTRIBUTES: - *(struct termios *)args->buffer = tty->termios; - break; - - case RTEMS_IO_SET_ATTRIBUTES: - tty->termios = *(struct termios *)args->buffer; - - /* check for and process change in flow control options */ - termios_set_flowctrl(tty); - - if (tty->termios.c_lflag & ICANON) { - tty->rawInBufSemaphoreOptions = RTEMS_WAIT; - tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; - tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; - } - else { - tty->vtimeTicks = tty->termios.c_cc[VTIME] * - rtems_clock_get_ticks_per_second() / 10; - if (tty->termios.c_cc[VTIME]) { - tty->rawInBufSemaphoreOptions = RTEMS_WAIT; - tty->rawInBufSemaphoreTimeout = tty->vtimeTicks; - if (tty->termios.c_cc[VMIN]) - tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; - else - tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks; - } - else { - if (tty->termios.c_cc[VMIN]) { - tty->rawInBufSemaphoreOptions = RTEMS_WAIT; - tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; - tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; - } - else { - tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT; - } - } - } - if (tty->device.setAttributes) - (*tty->device.setAttributes)(tty->minor, &tty->termios); - break; - - case RTEMS_IO_TCDRAIN: - drainOutput (tty); - break; - - case RTEMS_IO_SNDWAKEUP: - tty->tty_snd = *wakeup; - break; - - case RTEMS_IO_RCVWAKEUP: - tty->tty_rcv = *wakeup; - break; - - /* - * FIXME: add various ioctl code handlers - */ + rtems_libio_ioctl_args_t *args = arg; + struct rtems_termios_tty *tty = args->iop->data1; + struct ttywakeup *wakeup = (struct ttywakeup *)args->buffer; + rtems_status_code sc; + + args->ioctl_return = 0; + sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) { + args->ioctl_return = sc; + return sc; + } + switch (args->command) { + default: + if (rtems_termios_linesw[tty->t_line].l_ioctl != NULL) { + sc = rtems_termios_linesw[tty->t_line].l_ioctl(tty,args); + } + else { + sc = RTEMS_INVALID_NUMBER; + } + break; + + case RTEMS_IO_GET_ATTRIBUTES: + *(struct termios *)args->buffer = tty->termios; + break; + + case RTEMS_IO_SET_ATTRIBUTES: + tty->termios = *(struct termios *)args->buffer; + + /* check for and process change in flow control options */ + termios_set_flowctrl(tty); + + if (tty->termios.c_lflag & ICANON) { + tty->rawInBufSemaphoreOptions = RTEMS_WAIT; + tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; + tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; + } + else { + tty->vtimeTicks = tty->termios.c_cc[VTIME] * + rtems_clock_get_ticks_per_second() / 10; + if (tty->termios.c_cc[VTIME]) { + tty->rawInBufSemaphoreOptions = RTEMS_WAIT; + tty->rawInBufSemaphoreTimeout = tty->vtimeTicks; + if (tty->termios.c_cc[VMIN]) + tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; + else + tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks; + } + else { + if (tty->termios.c_cc[VMIN]) { + tty->rawInBufSemaphoreOptions = RTEMS_WAIT; + tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT; + tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT; + } + else { + tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT; + } + } + } + if (tty->device.setAttributes) + (*tty->device.setAttributes)(tty->minor, &tty->termios); + break; + + case RTEMS_IO_TCDRAIN: + drainOutput (tty); + break; + + case RTEMS_IO_SNDWAKEUP: + tty->tty_snd = *wakeup; + break; + + case RTEMS_IO_RCVWAKEUP: + tty->tty_rcv = *wakeup; + break; + + /* + * FIXME: add various ioctl code handlers + */ #if 1 /* FIXME */ - case TIOCSETD: - /* - * close old line discipline - */ - if (rtems_termios_linesw[tty->t_line].l_close != NULL) { - sc = rtems_termios_linesw[tty->t_line].l_close(tty); - } - tty->t_line=*(int*)(args->buffer); - tty->t_sc = NULL; /* ensure that no more valid data */ - /* - * open new line discipline - */ - if (rtems_termios_linesw[tty->t_line].l_open != NULL) { - sc = rtems_termios_linesw[tty->t_line].l_open(tty); - } - break; - case TIOCGETD: - *(int*)(args->buffer)=tty->t_line; - break; + case TIOCSETD: + /* + * close old line discipline + */ + if (rtems_termios_linesw[tty->t_line].l_close != NULL) { + sc = rtems_termios_linesw[tty->t_line].l_close(tty); + } + tty->t_line=*(int*)(args->buffer); + tty->t_sc = NULL; /* ensure that no more valid data */ + /* + * open new line discipline + */ + if (rtems_termios_linesw[tty->t_line].l_open != NULL) { + sc = rtems_termios_linesw[tty->t_line].l_open(tty); + } + break; + case TIOCGETD: + *(int*)(args->buffer)=tty->t_line; + break; #endif - case FIONREAD: - { - int rawnc = tty->rawInBuf.Tail - tty->rawInBuf.Head; - if ( rawnc < 0 ) - rawnc += tty->rawInBuf.Size; - /* Half guess that this is the right operation */ - *(int *)args->buffer = tty->ccount - tty->cindex + rawnc; - } - break; - } - rtems_semaphore_release (tty->osem); - args->ioctl_return = sc; - return sc; + case FIONREAD: + { + int rawnc = tty->rawInBuf.Tail - tty->rawInBuf.Head; + if ( rawnc < 0 ) + rawnc += tty->rawInBuf.Size; + /* Half guess that this is the right operation */ + *(int *)args->buffer = tty->ccount - tty->cindex + rawnc; + } + break; + } + rtems_semaphore_release (tty->osem); + args->ioctl_return = sc; + return sc; } /* @@ -637,58 +637,58 @@ void rtems_termios_puts ( const void *_buf, int len, struct rtems_termios_tty *tty) { - const unsigned char *buf = _buf; - unsigned int newHead; - rtems_interrupt_level level; - rtems_status_code sc; - - if (tty->device.outputUsesInterrupts == TERMIOS_POLLED) { - (*tty->device.write)(tty->minor, (void *)buf, len); - return; - } - newHead = tty->rawOutBuf.Head; - while (len) { - /* - * Performance improvement could be made here. - * Copy multiple bytes to raw buffer: - * if (len > 1) && (space to buffer end, or tail > 1) - * ncopy = MIN (len, space to buffer end or tail) - * memcpy (raw buffer, buf, ncopy) - * buf += ncopy - * len -= ncopy - * - * To minimize latency, the memcpy should be done - * with interrupts enabled. - */ - newHead = (newHead + 1) % tty->rawOutBuf.Size; - rtems_interrupt_disable (level); - while (newHead == tty->rawOutBuf.Tail) { - tty->rawOutBufState = rob_wait; - rtems_interrupt_enable (level); - sc = rtems_semaphore_obtain (tty->rawOutBuf.Semaphore, - RTEMS_WAIT, - RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - rtems_interrupt_disable (level); - } - tty->rawOutBuf.theBuf[tty->rawOutBuf.Head] = *buf++; - tty->rawOutBuf.Head = newHead; - if (tty->rawOutBufState == rob_idle) { - /* check, whether XOFF has been received */ - if (!(tty->flow_ctrl & FL_ORCVXOF)) { - (*tty->device.write)(tty->minor, - (char *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1); - } - else { - /* remember that output has been stopped due to flow ctrl*/ - tty->flow_ctrl |= FL_OSTOP; - } - tty->rawOutBufState = rob_busy; - } - rtems_interrupt_enable (level); - len--; - } + const unsigned char *buf = _buf; + unsigned int newHead; + rtems_interrupt_level level; + rtems_status_code sc; + + if (tty->device.outputUsesInterrupts == TERMIOS_POLLED) { + (*tty->device.write)(tty->minor, (void *)buf, len); + return; + } + newHead = tty->rawOutBuf.Head; + while (len) { + /* + * Performance improvement could be made here. + * Copy multiple bytes to raw buffer: + * if (len > 1) && (space to buffer end, or tail > 1) + * ncopy = MIN (len, space to buffer end or tail) + * memcpy (raw buffer, buf, ncopy) + * buf += ncopy + * len -= ncopy + * + * To minimize latency, the memcpy should be done + * with interrupts enabled. + */ + newHead = (newHead + 1) % tty->rawOutBuf.Size; + rtems_interrupt_disable (level); + while (newHead == tty->rawOutBuf.Tail) { + tty->rawOutBufState = rob_wait; + rtems_interrupt_enable (level); + sc = rtems_semaphore_obtain (tty->rawOutBuf.Semaphore, + RTEMS_WAIT, + RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + rtems_interrupt_disable (level); + } + tty->rawOutBuf.theBuf[tty->rawOutBuf.Head] = *buf++; + tty->rawOutBuf.Head = newHead; + if (tty->rawOutBufState == rob_idle) { + /* check, whether XOFF has been received */ + if (!(tty->flow_ctrl & FL_ORCVXOF)) { + (*tty->device.write)(tty->minor, + (char *)&tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1); + } + else { + /* remember that output has been stopped due to flow ctrl*/ + tty->flow_ctrl |= FL_OSTOP; + } + tty->rawOutBufState = rob_busy; + } + rtems_interrupt_enable (level); + len--; + } } /* @@ -697,85 +697,85 @@ rtems_termios_puts ( static void oproc (unsigned char c, struct rtems_termios_tty *tty) { - int i; - - if (tty->termios.c_oflag & OPOST) { - switch (c) { - case '\n': - if (tty->termios.c_oflag & ONLRET) - tty->column = 0; - if (tty->termios.c_oflag & ONLCR) { - rtems_termios_puts ("\r", 1, tty); - tty->column = 0; - } - break; - - case '\r': - if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0)) - return; - if (tty->termios.c_oflag & OCRNL) { - c = '\n'; - if (tty->termios.c_oflag & ONLRET) - tty->column = 0; - break; - } - tty->column = 0; - break; - - case '\t': - i = 8 - (tty->column & 7); - if ((tty->termios.c_oflag & TABDLY) == XTABS) { - tty->column += i; - rtems_termios_puts ( " ", i, tty); - return; - } - tty->column += i; - break; - - case '\b': - if (tty->column > 0) - tty->column--; - break; - - default: - if (tty->termios.c_oflag & OLCUC) - c = toupper(c); - if (!iscntrl(c)) - tty->column++; - break; - } - } - rtems_termios_puts (&c, 1, tty); + int i; + + if (tty->termios.c_oflag & OPOST) { + switch (c) { + case '\n': + if (tty->termios.c_oflag & ONLRET) + tty->column = 0; + if (tty->termios.c_oflag & ONLCR) { + rtems_termios_puts ("\r", 1, tty); + tty->column = 0; + } + break; + + case '\r': + if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0)) + return; + if (tty->termios.c_oflag & OCRNL) { + c = '\n'; + if (tty->termios.c_oflag & ONLRET) + tty->column = 0; + break; + } + tty->column = 0; + break; + + case '\t': + i = 8 - (tty->column & 7); + if ((tty->termios.c_oflag & TABDLY) == XTABS) { + tty->column += i; + rtems_termios_puts ( " ", i, tty); + return; + } + tty->column += i; + break; + + case '\b': + if (tty->column > 0) + tty->column--; + break; + + default: + if (tty->termios.c_oflag & OLCUC) + c = toupper(c); + if (!iscntrl(c)) + tty->column++; + break; + } + } + rtems_termios_puts (&c, 1, tty); } rtems_status_code rtems_termios_write (void *arg) { - rtems_libio_rw_args_t *args = arg; - struct rtems_termios_tty *tty = args->iop->data1; - rtems_status_code sc; - - sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - return sc; - if (rtems_termios_linesw[tty->t_line].l_write != NULL) { - sc = rtems_termios_linesw[tty->t_line].l_write(tty,args); - rtems_semaphore_release (tty->osem); - return sc; - } - if (tty->termios.c_oflag & OPOST) { - uint32_t count = args->count; - char *buffer = args->buffer; - while (count--) - oproc (*buffer++, tty); - args->bytes_moved = args->count; - } - else { - rtems_termios_puts (args->buffer, args->count, tty); - args->bytes_moved = args->count; - } - rtems_semaphore_release (tty->osem); - return sc; + rtems_libio_rw_args_t *args = arg; + struct rtems_termios_tty *tty = args->iop->data1; + rtems_status_code sc; + + sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + return sc; + if (rtems_termios_linesw[tty->t_line].l_write != NULL) { + sc = rtems_termios_linesw[tty->t_line].l_write(tty,args); + rtems_semaphore_release (tty->osem); + return sc; + } + if (tty->termios.c_oflag & OPOST) { + uint32_t count = args->count; + char *buffer = args->buffer; + while (count--) + oproc (*buffer++, tty); + args->bytes_moved = args->count; + } + else { + rtems_termios_puts (args->buffer, args->count, tty); + args->bytes_moved = args->count; + } + rtems_semaphore_release (tty->osem); + return sc; } /* @@ -784,17 +784,17 @@ rtems_termios_write (void *arg) static void echo (unsigned char c, struct rtems_termios_tty *tty) { - if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) { - char echobuf[2]; - - echobuf[0] = '^'; - echobuf[1] = c ^ 0x40; - rtems_termios_puts (echobuf, 2, tty); - tty->column += 2; - } - else { - oproc (c, tty); - } + if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) { + char echobuf[2]; + + echobuf[0] = '^'; + echobuf[1] = c ^ 0x40; + rtems_termios_puts (echobuf, 2, tty); + tty->column += 2; + } + else { + oproc (c, tty); + } } /* @@ -805,73 +805,73 @@ echo (unsigned char c, struct rtems_termios_tty *tty) static void erase (struct rtems_termios_tty *tty, int lineFlag) { - if (tty->ccount == 0) - return; - if (lineFlag) { - if (!(tty->termios.c_lflag & ECHO)) { - tty->ccount = 0; - return; - } - if (!(tty->termios.c_lflag & ECHOE)) { - tty->ccount = 0; - echo (tty->termios.c_cc[VKILL], tty); - if (tty->termios.c_lflag & ECHOK) - echo ('\n', tty); - return; - } - } - while (tty->ccount) { - unsigned char c = tty->cbuf[--tty->ccount]; - - if (tty->termios.c_lflag & ECHO) { - if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) { - echo (tty->termios.c_cc[VERASE], tty); - } - else if (c == '\t') { - int col = tty->read_start_column; - int i = 0; - - /* - * Find the character before the tab - */ - while (i != tty->ccount) { - c = tty->cbuf[i++]; - if (c == '\t') { - col = (col | 7) + 1; - } - else if (iscntrl (c)) { - if (tty->termios.c_lflag & ECHOCTL) - col += 2; - } - else { - col++; - } - } - - /* - * Back up over the tab - */ - while (tty->column > col) { - rtems_termios_puts ("\b", 1, tty); - tty->column--; - } - } - else { - if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) { - rtems_termios_puts ("\b \b", 3, tty); - if (tty->column) - tty->column--; - } - if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) { - rtems_termios_puts ("\b \b", 3, tty); - if (tty->column) - tty->column--; - } - } - } - if (!lineFlag) - break; - } + if (tty->ccount == 0) + return; + if (lineFlag) { + if (!(tty->termios.c_lflag & ECHO)) { + tty->ccount = 0; + return; + } + if (!(tty->termios.c_lflag & ECHOE)) { + tty->ccount = 0; + echo (tty->termios.c_cc[VKILL], tty); + if (tty->termios.c_lflag & ECHOK) + echo ('\n', tty); + return; + } + } + while (tty->ccount) { + unsigned char c = tty->cbuf[--tty->ccount]; + + if (tty->termios.c_lflag & ECHO) { + if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) { + echo (tty->termios.c_cc[VERASE], tty); + } + else if (c == '\t') { + int col = tty->read_start_column; + int i = 0; + + /* + * Find the character before the tab + */ + while (i != tty->ccount) { + c = tty->cbuf[i++]; + if (c == '\t') { + col = (col | 7) + 1; + } + else if (iscntrl (c)) { + if (tty->termios.c_lflag & ECHOCTL) + col += 2; + } + else { + col++; + } + } + + /* + * Back up over the tab + */ + while (tty->column > col) { + rtems_termios_puts ("\b", 1, tty); + tty->column--; + } + } + else { + if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) { + rtems_termios_puts ("\b \b", 3, tty); + if (tty->column) + tty->column--; + } + if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) { + rtems_termios_puts ("\b \b", 3, tty); + if (tty->column) + tty->column--; + } + } + } + if (!lineFlag) + break; + } } /* @@ -880,55 +880,55 @@ erase (struct rtems_termios_tty *tty, int lineFlag) static int iproc (unsigned char c, struct rtems_termios_tty *tty) { - if (tty->termios.c_iflag & ISTRIP) - c &= 0x7f; - if (tty->termios.c_iflag & IUCLC) - c = tolower (c); - if (c == '\r') { - if (tty->termios.c_iflag & IGNCR) - return 0; - if (tty->termios.c_iflag & ICRNL) - c = '\n'; - } - else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) { - c = '\r'; - } - if ((c != '\0') && (tty->termios.c_lflag & ICANON)) { - if (c == tty->termios.c_cc[VERASE]) { - erase (tty, 0); - return 0; - } - else if (c == tty->termios.c_cc[VKILL]) { - erase (tty, 1); - return 0; - } - else if (c == tty->termios.c_cc[VEOF]) { - return 1; - } - else if (c == '\n') { - if (tty->termios.c_lflag & (ECHO | ECHONL)) - echo (c, tty); - tty->cbuf[tty->ccount++] = c; - return 1; - } - else if ((c == tty->termios.c_cc[VEOL]) - || (c == tty->termios.c_cc[VEOL2])) { - if (tty->termios.c_lflag & ECHO) - echo (c, tty); - tty->cbuf[tty->ccount++] = c; - return 1; - } - } - - /* - * FIXME: Should do IMAXBEL handling somehow - */ - if (tty->ccount < (CBUFSIZE-1)) { - if (tty->termios.c_lflag & ECHO) - echo (c, tty); - tty->cbuf[tty->ccount++] = c; - } - return 0; + if (tty->termios.c_iflag & ISTRIP) + c &= 0x7f; + if (tty->termios.c_iflag & IUCLC) + c = tolower (c); + if (c == '\r') { + if (tty->termios.c_iflag & IGNCR) + return 0; + if (tty->termios.c_iflag & ICRNL) + c = '\n'; + } + else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) { + c = '\r'; + } + if ((c != '\0') && (tty->termios.c_lflag & ICANON)) { + if (c == tty->termios.c_cc[VERASE]) { + erase (tty, 0); + return 0; + } + else if (c == tty->termios.c_cc[VKILL]) { + erase (tty, 1); + return 0; + } + else if (c == tty->termios.c_cc[VEOF]) { + return 1; + } + else if (c == '\n') { + if (tty->termios.c_lflag & (ECHO | ECHONL)) + echo (c, tty); + tty->cbuf[tty->ccount++] = c; + return 1; + } + else if ((c == tty->termios.c_cc[VEOL]) + || (c == tty->termios.c_cc[VEOL2])) { + if (tty->termios.c_lflag & ECHO) + echo (c, tty); + tty->cbuf[tty->ccount++] = c; + return 1; + } + } + + /* + * FIXME: Should do IMAXBEL handling somehow + */ + if (tty->ccount < (CBUFSIZE-1)) { + if (tty->termios.c_lflag & ECHO) + echo (c, tty); + tty->cbuf[tty->ccount++] = c; + } + return 0; } /* @@ -937,20 +937,20 @@ iproc (unsigned char c, struct rtems_termios_tty *tty) static int siproc (unsigned char c, struct rtems_termios_tty *tty) { - int i; - - /* - * Obtain output semaphore if character will be echoed - */ - if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) { - rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - i = iproc (c, tty); - rtems_semaphore_release (tty->osem); - } - else { - i = iproc (c, tty); - } - return i; + int i; + + /* + * Obtain output semaphore if character will be echoed + */ + if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) { + rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + i = iproc (c, tty); + rtems_semaphore_release (tty->osem); + } + else { + i = iproc (c, tty); + } + return i; } /* @@ -959,54 +959,54 @@ siproc (unsigned char c, struct rtems_termios_tty *tty) static rtems_status_code fillBufferPoll (struct rtems_termios_tty *tty) { - int n; - - if (tty->termios.c_lflag & ICANON) { - for (;;) { - n = (*tty->device.pollRead)(tty->minor); - if (n < 0) { - rtems_task_wake_after (1); - } - else { - if (siproc (n, tty)) - break; - } - } - } - else { - rtems_interval then, now; - then = rtems_clock_get_ticks_since_boot(); - for (;;) { - n = (*tty->device.pollRead)(tty->minor); - if (n < 0) { - if (tty->termios.c_cc[VMIN]) { - if (tty->termios.c_cc[VTIME] && tty->ccount) { - now = rtems_clock_get_ticks_since_boot(); - if ((now - then) > tty->vtimeTicks) { - break; - } - } - } - else { - if (!tty->termios.c_cc[VTIME]) - break; - now = rtems_clock_get_ticks_since_boot(); - if ((now - then) > tty->vtimeTicks) { - break; - } - } - rtems_task_wake_after (1); - } - else { - siproc (n, tty); - if (tty->ccount >= tty->termios.c_cc[VMIN]) - break; - if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) - then = rtems_clock_get_ticks_since_boot(); - } - } - } - return RTEMS_SUCCESSFUL; + int n; + + if (tty->termios.c_lflag & ICANON) { + for (;;) { + n = (*tty->device.pollRead)(tty->minor); + if (n < 0) { + rtems_task_wake_after (1); + } + else { + if (siproc (n, tty)) + break; + } + } + } + else { + rtems_interval then, now; + then = rtems_clock_get_ticks_since_boot(); + for (;;) { + n = (*tty->device.pollRead)(tty->minor); + if (n < 0) { + if (tty->termios.c_cc[VMIN]) { + if (tty->termios.c_cc[VTIME] && tty->ccount) { + now = rtems_clock_get_ticks_since_boot(); + if ((now - then) > tty->vtimeTicks) { + break; + } + } + } + else { + if (!tty->termios.c_cc[VTIME]) + break; + now = rtems_clock_get_ticks_since_boot(); + if ((now - then) > tty->vtimeTicks) { + break; + } + } + rtems_task_wake_after (1); + } + else { + siproc (n, tty); + if (tty->ccount >= tty->termios.c_cc[VMIN]) + break; + if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME]) + then = rtems_clock_get_ticks_since_boot(); + } + } + } + return RTEMS_SUCCESSFUL; } /* @@ -1015,109 +1015,109 @@ fillBufferPoll (struct rtems_termios_tty *tty) static rtems_status_code fillBufferQueue (struct rtems_termios_tty *tty) { - rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout; - rtems_status_code sc; - int wait = (int)1; - - while ( wait ) { - /* - * Process characters read from raw queue - */ - while ((tty->rawInBuf.Head != tty->rawInBuf.Tail) && + rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout; + rtems_status_code sc; + int wait = (int)1; + + while ( wait ) { + /* + * Process characters read from raw queue + */ + while ((tty->rawInBuf.Head != tty->rawInBuf.Tail) && (tty->ccount < (CBUFSIZE-1))) { - unsigned char c; - unsigned int newHead; - - newHead = (tty->rawInBuf.Head + 1) % tty->rawInBuf.Size; - c = tty->rawInBuf.theBuf[newHead]; - tty->rawInBuf.Head = newHead; - if(((tty->rawInBuf.Tail-newHead+tty->rawInBuf.Size) - % tty->rawInBuf.Size) - < tty->lowwater) { - tty->flow_ctrl &= ~FL_IREQXOF; - /* if tx stopped and XON should be sent... */ - if (((tty->flow_ctrl & (FL_MDXON | FL_ISNTXOF)) - == (FL_MDXON | FL_ISNTXOF)) - && ((tty->rawOutBufState == rob_idle) - || (tty->flow_ctrl & FL_OSTOP))) { - /* XON should be sent now... */ - (*tty->device.write)(tty->minor, - (void *)&(tty->termios.c_cc[VSTART]), - 1); - } - else if (tty->flow_ctrl & FL_MDRTS) { - tty->flow_ctrl &= ~FL_IRTSOFF; - /* activate RTS line */ - if (tty->device.startRemoteTx != NULL) { - tty->device.startRemoteTx(tty->minor); - } - } - } - - /* continue processing new character */ - if (tty->termios.c_lflag & ICANON) { - if (siproc (c, tty)) - wait = 0; - } - else { - siproc (c, tty); - if (tty->ccount >= tty->termios.c_cc[VMIN]) - wait = 0; - } - timeout = tty->rawInBufSemaphoreTimeout; - } - - /* - * Wait for characters - */ - if ( wait ) { - sc = rtems_semaphore_obtain (tty->rawInBuf.Semaphore, - tty->rawInBufSemaphoreOptions, - timeout); - if (sc != RTEMS_SUCCESSFUL) - break; - } - } - return RTEMS_SUCCESSFUL; + unsigned char c; + unsigned int newHead; + + newHead = (tty->rawInBuf.Head + 1) % tty->rawInBuf.Size; + c = tty->rawInBuf.theBuf[newHead]; + tty->rawInBuf.Head = newHead; + if(((tty->rawInBuf.Tail-newHead+tty->rawInBuf.Size) + % tty->rawInBuf.Size) + < tty->lowwater) { + tty->flow_ctrl &= ~FL_IREQXOF; + /* if tx stopped and XON should be sent... */ + if (((tty->flow_ctrl & (FL_MDXON | FL_ISNTXOF)) + == (FL_MDXON | FL_ISNTXOF)) + && ((tty->rawOutBufState == rob_idle) + || (tty->flow_ctrl & FL_OSTOP))) { + /* XON should be sent now... */ + (*tty->device.write)(tty->minor, + (void *)&(tty->termios.c_cc[VSTART]), + 1); + } + else if (tty->flow_ctrl & FL_MDRTS) { + tty->flow_ctrl &= ~FL_IRTSOFF; + /* activate RTS line */ + if (tty->device.startRemoteTx != NULL) { + tty->device.startRemoteTx(tty->minor); + } + } + } + + /* continue processing new character */ + if (tty->termios.c_lflag & ICANON) { + if (siproc (c, tty)) + wait = 0; + } + else { + siproc (c, tty); + if (tty->ccount >= tty->termios.c_cc[VMIN]) + wait = 0; + } + timeout = tty->rawInBufSemaphoreTimeout; + } + + /* + * Wait for characters + */ + if ( wait ) { + sc = rtems_semaphore_obtain (tty->rawInBuf.Semaphore, + tty->rawInBufSemaphoreOptions, + timeout); + if (sc != RTEMS_SUCCESSFUL) + break; + } + } + return RTEMS_SUCCESSFUL; } rtems_status_code rtems_termios_read (void *arg) { - rtems_libio_rw_args_t *args = arg; - struct rtems_termios_tty *tty = args->iop->data1; - uint32_t count = args->count; - char *buffer = args->buffer; - rtems_status_code sc; - - sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (sc != RTEMS_SUCCESSFUL) - return sc; - if (rtems_termios_linesw[tty->t_line].l_read != NULL) { - sc = rtems_termios_linesw[tty->t_line].l_read(tty,args); - tty->tty_rcvwakeup = 0; - rtems_semaphore_release (tty->isem); - return sc; - } - if (tty->cindex == tty->ccount) { - tty->cindex = tty->ccount = 0; - tty->read_start_column = tty->column; - if (tty->device.pollRead != NULL - && tty->device.outputUsesInterrupts == TERMIOS_POLLED) - sc = fillBufferPoll (tty); - else - sc = fillBufferQueue (tty); - if (sc != RTEMS_SUCCESSFUL) - tty->cindex = tty->ccount = 0; - } - while (count && (tty->cindex < tty->ccount)) { - *buffer++ = tty->cbuf[tty->cindex++]; - count--; - } - args->bytes_moved = args->count - count; - tty->tty_rcvwakeup = 0; - rtems_semaphore_release (tty->isem); - return sc; + rtems_libio_rw_args_t *args = arg; + struct rtems_termios_tty *tty = args->iop->data1; + uint32_t count = args->count; + char *buffer = args->buffer; + rtems_status_code sc; + + sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + if (sc != RTEMS_SUCCESSFUL) + return sc; + if (rtems_termios_linesw[tty->t_line].l_read != NULL) { + sc = rtems_termios_linesw[tty->t_line].l_read(tty,args); + tty->tty_rcvwakeup = 0; + rtems_semaphore_release (tty->isem); + return sc; + } + if (tty->cindex == tty->ccount) { + tty->cindex = tty->ccount = 0; + tty->read_start_column = tty->column; + if (tty->device.pollRead != NULL + && tty->device.outputUsesInterrupts == TERMIOS_POLLED) + sc = fillBufferPoll (tty); + else + sc = fillBufferQueue (tty); + if (sc != RTEMS_SUCCESSFUL) + tty->cindex = tty->ccount = 0; + } + while (count && (tty->cindex < tty->ccount)) { + *buffer++ = tty->cbuf[tty->cindex++]; + count--; + } + args->bytes_moved = args->count - count; + tty->tty_rcvwakeup = 0; + rtems_semaphore_release (tty->isem); + return sc; } /* @@ -1127,10 +1127,10 @@ rtems_termios_read (void *arg) */ void rtems_termios_rxirq_occured(struct rtems_termios_tty *tty) { - /* - * send event to rx daemon task - */ - rtems_event_send(tty->rxTaskId,TERMIOS_RX_PROC_EVENT); + /* + * send event to rx daemon task + */ + rtems_event_send(tty->rxTaskId,TERMIOS_RX_PROC_EVENT); } /* @@ -1142,125 +1142,123 @@ void rtems_termios_rxirq_occured(struct rtems_termios_tty *tty) int rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len) { - struct rtems_termios_tty *tty = ttyp; - unsigned int newTail; - char c; - int dropped = 0; - bool flow_rcv = false; /* true, if flow control char received */ - rtems_interrupt_level level; - - if (rtems_termios_linesw[tty->t_line].l_rint != NULL) { - while (len--) { - c = *buf++; - rtems_termios_linesw[tty->t_line].l_rint(c,tty); - } - - /* - * check to see if rcv wakeup callback was set - */ - if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) { - (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg); - tty->tty_rcvwakeup = 1; - } - return 0; - } - - while (len--) { - c = *buf++; - /* FIXME: implement IXANY: any character restarts output */ - /* if incoming XON/XOFF controls outgoing stream: */ - if (tty->flow_ctrl & FL_MDXON) { - /* if received char is V_STOP and V_START (both are equal value) */ - if (c == tty->termios.c_cc[VSTOP]) { - if (c == tty->termios.c_cc[VSTART]) { - /* received VSTOP and VSTART==VSTOP? */ - /* then toggle "stop output" status */ - tty->flow_ctrl = tty->flow_ctrl ^ FL_ORCVXOF; - } - else { - /* VSTOP received (other code than VSTART) */ - /* stop output */ - tty->flow_ctrl |= FL_ORCVXOF; - } - flow_rcv = true; - } - else if (c == tty->termios.c_cc[VSTART]) { - /* VSTART received */ - /* restart output */ - tty->flow_ctrl &= ~FL_ORCVXOF; - flow_rcv = true; - } - } - if (flow_rcv) { - /* restart output according to FL_ORCVXOF flag */ - if ((tty->flow_ctrl & (FL_ORCVXOF | FL_OSTOP)) == FL_OSTOP) { - /* disable interrupts */ - rtems_interrupt_disable(level); - tty->flow_ctrl &= ~FL_OSTOP; - /* check for chars in output buffer (or rob_state?) */ - if (tty->rawOutBufState != rob_idle) { - /* if chars available, call write function... */ - (*tty->device.write)(tty->minor, - &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1); - } - /* reenable interrupts */ - rtems_interrupt_enable(level); - } - } - else { - newTail = (tty->rawInBuf.Tail + 1) % tty->rawInBuf.Size; - /* if chars_in_buffer > highwater */ - rtems_interrupt_disable(level); - if ((((newTail - tty->rawInBuf.Head + tty->rawInBuf.Size) - % tty->rawInBuf.Size) - > tty->highwater) && - !(tty->flow_ctrl & FL_IREQXOF)) { - /* incoming data stream should be stopped */ - tty->flow_ctrl |= FL_IREQXOF; - if ((tty->flow_ctrl & (FL_MDXOF | FL_ISNTXOF)) - == (FL_MDXOF ) ){ - if ((tty->flow_ctrl & FL_OSTOP) || - (tty->rawOutBufState == rob_idle)) { - /* if tx is stopped due to XOFF or out of data */ - /* call write function here */ - tty->flow_ctrl |= FL_ISNTXOF; - (*tty->device.write)(tty->minor, - (void *)&(tty->termios.c_cc[VSTOP]), - 1); - } - } - else if ((tty->flow_ctrl & (FL_MDRTS | FL_IRTSOFF)) - == (FL_MDRTS ) ) { - tty->flow_ctrl |= FL_IRTSOFF; - /* deactivate RTS line */ - if (tty->device.stopRemoteTx != NULL) { - tty->device.stopRemoteTx(tty->minor); - } - } - } - /* reenable interrupts */ - rtems_interrupt_enable(level); - - if (newTail == tty->rawInBuf.Head) { - dropped++; - } - else { - tty->rawInBuf.theBuf[newTail] = c; - tty->rawInBuf.Tail = newTail; - - /* - * check to see if rcv wakeup callback was set - */ - if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) { - (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg); - tty->tty_rcvwakeup = 1; - } - } - } - } - tty->rawInBufDropped += dropped; - rtems_semaphore_release (tty->rawInBuf.Semaphore); - return dropped; + struct rtems_termios_tty *tty = ttyp; + unsigned int newTail; + char c; + int dropped = 0; + bool flow_rcv = false; /* true, if flow control char received */ + rtems_interrupt_level level; + + if (rtems_termios_linesw[tty->t_line].l_rint != NULL) { + while (len--) { + c = *buf++; + rtems_termios_linesw[tty->t_line].l_rint(c,tty); + } + + /* + * check to see if rcv wakeup callback was set + */ + if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) { + (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg); + tty->tty_rcvwakeup = 1; + } + return 0; + } + + while (len--) { + c = *buf++; + /* FIXME: implement IXANY: any character restarts output */ + /* if incoming XON/XOFF controls outgoing stream: */ + if (tty->flow_ctrl & FL_MDXON) { + /* if received char is V_STOP and V_START (both are equal value) */ + if (c == tty->termios.c_cc[VSTOP]) { + if (c == tty->termios.c_cc[VSTART]) { + /* received VSTOP and VSTART==VSTOP? */ + /* then toggle "stop output" status */ + tty->flow_ctrl = tty->flow_ctrl ^ FL_ORCVXOF; + } + else { + /* VSTOP received (other code than VSTART) */ + /* stop output */ + tty->flow_ctrl |= FL_ORCVXOF; + } + flow_rcv = true; + } + else if (c == tty->termios.c_cc[VSTART]) { + /* VSTART received */ + /* restart output */ + tty->flow_ctrl &= ~FL_ORCVXOF; + flow_rcv = true; + } + } + if (flow_rcv) { + /* restart output according to FL_ORCVXOF flag */ + if ((tty->flow_ctrl & (FL_ORCVXOF | FL_OSTOP)) == FL_OSTOP) { + /* disable interrupts */ + rtems_interrupt_disable(level); + tty->flow_ctrl &= ~FL_OSTOP; + /* check for chars in output buffer (or rob_state?) */ + if (tty->rawOutBufState != rob_idle) { + /* if chars available, call write function... */ + (*tty->device.write)(tty->minor, + &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1); + } + /* reenable interrupts */ + rtems_interrupt_enable(level); + } + } + else { + newTail = (tty->rawInBuf.Tail + 1) % tty->rawInBuf.Size; + /* if chars_in_buffer > highwater */ + rtems_interrupt_disable(level); + if ((((newTail - tty->rawInBuf.Head + tty->rawInBuf.Size) + % tty->rawInBuf.Size) > tty->highwater) && + !(tty->flow_ctrl & FL_IREQXOF)) { + /* incoming data stream should be stopped */ + tty->flow_ctrl |= FL_IREQXOF; + if ((tty->flow_ctrl & (FL_MDXOF | FL_ISNTXOF)) + == (FL_MDXOF ) ) { + if ((tty->flow_ctrl & FL_OSTOP) || + (tty->rawOutBufState == rob_idle)) { + /* if tx is stopped due to XOFF or out of data */ + /* call write function here */ + tty->flow_ctrl |= FL_ISNTXOF; + (*tty->device.write)(tty->minor, + (void *)&(tty->termios.c_cc[VSTOP]), 1); + } + } + else if ((tty->flow_ctrl & (FL_MDRTS | FL_IRTSOFF)) == (FL_MDRTS) ) { + tty->flow_ctrl |= FL_IRTSOFF; + /* deactivate RTS line */ + if (tty->device.stopRemoteTx != NULL) { + tty->device.stopRemoteTx(tty->minor); + } + } + } + + /* reenable interrupts */ + rtems_interrupt_enable(level); + + if (newTail == tty->rawInBuf.Head) { + dropped++; + } + else { + tty->rawInBuf.theBuf[newTail] = c; + tty->rawInBuf.Tail = newTail; + + /* + * check to see if rcv wakeup callback was set + */ + if (( !tty->tty_rcvwakeup ) && ( tty->tty_rcv.sw_pfn != NULL )) { + (*tty->tty_rcv.sw_pfn)(&tty->termios, tty->tty_rcv.sw_arg); + tty->tty_rcvwakeup = 1; + } + } + } + } + tty->rawInBufDropped += dropped; + rtems_semaphore_release (tty->rawInBuf.Semaphore); + return dropped; } /* @@ -1270,119 +1268,118 @@ rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len) int rtems_termios_refill_transmitter (struct rtems_termios_tty *tty) { - unsigned int newTail; - int nToSend; - rtems_interrupt_level level; - int len; - - /* check for XOF/XON to send */ - if ((tty->flow_ctrl & (FL_MDXOF | FL_IREQXOF | FL_ISNTXOF)) - == (FL_MDXOF | FL_IREQXOF)) { - /* XOFF should be sent now... */ - (*tty->device.write)(tty->minor, - (void *)&(tty->termios.c_cc[VSTOP]), 1); - - rtems_interrupt_disable(level); - tty->t_dqlen--; - tty->flow_ctrl |= FL_ISNTXOF; - rtems_interrupt_enable(level); - - nToSend = 1; - } - else if ((tty->flow_ctrl & (FL_IREQXOF | FL_ISNTXOF)) - == FL_ISNTXOF) { - /* NOTE: send XON even, if no longer in XON/XOFF mode... */ - /* XON should be sent now... */ - /* - * FIXME: this .write call will generate another - * dequeue callback. This will advance the "Tail" in the data - * buffer, although the corresponding data is not yet out! - * Therefore the dequeue "length" should be reduced by 1 - */ - (*tty->device.write)(tty->minor, - (void *)&(tty->termios.c_cc[VSTART]), 1); - - rtems_interrupt_disable(level); - tty->t_dqlen--; - tty->flow_ctrl &= ~FL_ISNTXOF; - rtems_interrupt_enable(level); - - nToSend = 1; - } - else { - if ( tty->rawOutBuf.Head == tty->rawOutBuf.Tail ) { - /* - * buffer was empty - */ - if (tty->rawOutBufState == rob_wait) { - /* - * this should never happen... - */ - rtems_semaphore_release (tty->rawOutBuf.Semaphore); - } - return 0; - } - - rtems_interrupt_disable(level); - len = tty->t_dqlen; - tty->t_dqlen = 0; - rtems_interrupt_enable(level); - - newTail = (tty->rawOutBuf.Tail + len) % tty->rawOutBuf.Size; - tty->rawOutBuf.Tail = newTail; - if (tty->rawOutBufState == rob_wait) { - /* - * wake up any pending writer task - */ - rtems_semaphore_release (tty->rawOutBuf.Semaphore); - } - if (newTail == tty->rawOutBuf.Head) { - /* - * Buffer has become empty - */ - tty->rawOutBufState = rob_idle; - nToSend = 0; - - /* - * check to see if snd wakeup callback was set - */ - if ( tty->tty_snd.sw_pfn != NULL) { - (*tty->tty_snd.sw_pfn)(&tty->termios, tty->tty_snd.sw_arg); - } - } - /* check, whether output should stop due to received XOFF */ - else if ((tty->flow_ctrl & (FL_MDXON | FL_ORCVXOF)) - == (FL_MDXON | FL_ORCVXOF)) { - /* Buffer not empty, but output stops due to XOFF */ - /* set flag, that output has been stopped */ - rtems_interrupt_disable(level); - tty->flow_ctrl |= FL_OSTOP; - tty->rawOutBufState = rob_busy; /*apm*/ - rtems_interrupt_enable(level); - nToSend = 0; - } - else { - /* - * Buffer not empty, start tranmitter - */ - if (newTail > tty->rawOutBuf.Head) - nToSend = tty->rawOutBuf.Size - newTail; - else - nToSend = tty->rawOutBuf.Head - newTail; - /* when flow control XON or XOF, don't send blocks of data */ - /* to allow fast reaction on incoming flow ctrl and low latency*/ - /* for outgoing flow control */ - if (tty->flow_ctrl & (FL_MDXON | FL_MDXOF)) { - nToSend = 1; - } - tty->rawOutBufState = rob_busy; /*apm*/ - (*tty->device.write)(tty->minor, - &tty->rawOutBuf.theBuf[newTail], - nToSend); - } - tty->rawOutBuf.Tail = newTail; /*apm*/ - } - return nToSend; + unsigned int newTail; + int nToSend; + rtems_interrupt_level level; + int len; + + /* check for XOF/XON to send */ + if ((tty->flow_ctrl & (FL_MDXOF | FL_IREQXOF | FL_ISNTXOF)) + == (FL_MDXOF | FL_IREQXOF)) { + /* XOFF should be sent now... */ + (*tty->device.write)(tty->minor, + (void *)&(tty->termios.c_cc[VSTOP]), 1); + + rtems_interrupt_disable(level); + tty->t_dqlen--; + tty->flow_ctrl |= FL_ISNTXOF; + rtems_interrupt_enable(level); + + nToSend = 1; + } + else if ((tty->flow_ctrl & (FL_IREQXOF | FL_ISNTXOF)) == FL_ISNTXOF) { + /* NOTE: send XON even, if no longer in XON/XOFF mode... */ + /* XON should be sent now... */ + /* + * FIXME: this .write call will generate another + * dequeue callback. This will advance the "Tail" in the data + * buffer, although the corresponding data is not yet out! + * Therefore the dequeue "length" should be reduced by 1 + */ + (*tty->device.write)(tty->minor, + (void *)&(tty->termios.c_cc[VSTART]), 1); + + rtems_interrupt_disable(level); + tty->t_dqlen--; + tty->flow_ctrl &= ~FL_ISNTXOF; + rtems_interrupt_enable(level); + + nToSend = 1; + } + else { + if ( tty->rawOutBuf.Head == tty->rawOutBuf.Tail ) { + /* + * buffer was empty + */ + if (tty->rawOutBufState == rob_wait) { + /* + * this should never happen... + */ + rtems_semaphore_release (tty->rawOutBuf.Semaphore); + } + return 0; + } + + rtems_interrupt_disable(level); + len = tty->t_dqlen; + tty->t_dqlen = 0; + rtems_interrupt_enable(level); + + newTail = (tty->rawOutBuf.Tail + len) % tty->rawOutBuf.Size; + tty->rawOutBuf.Tail = newTail; + if (tty->rawOutBufState == rob_wait) { + /* + * wake up any pending writer task + */ + rtems_semaphore_release (tty->rawOutBuf.Semaphore); + } + if (newTail == tty->rawOutBuf.Head) { + /* + * Buffer has become empty + */ + tty->rawOutBufState = rob_idle; + nToSend = 0; + + /* + * check to see if snd wakeup callback was set + */ + if ( tty->tty_snd.sw_pfn != NULL) { + (*tty->tty_snd.sw_pfn)(&tty->termios, tty->tty_snd.sw_arg); + } + } + /* check, whether output should stop due to received XOFF */ + else if ((tty->flow_ctrl & (FL_MDXON | FL_ORCVXOF)) + == (FL_MDXON | FL_ORCVXOF)) { + /* Buffer not empty, but output stops due to XOFF */ + /* set flag, that output has been stopped */ + rtems_interrupt_disable(level); + tty->flow_ctrl |= FL_OSTOP; + tty->rawOutBufState = rob_busy; /*apm*/ + rtems_interrupt_enable(level); + nToSend = 0; + } + else { + /* + * Buffer not empty, start tranmitter + */ + if (newTail > tty->rawOutBuf.Head) + nToSend = tty->rawOutBuf.Size - newTail; + else + nToSend = tty->rawOutBuf.Head - newTail; + /* when flow control XON or XOF, don't send blocks of data */ + /* to allow fast reaction on incoming flow ctrl and low latency*/ + /* for outgoing flow control */ + if (tty->flow_ctrl & (FL_MDXON | FL_MDXOF)) { + nToSend = 1; + } + tty->rawOutBufState = rob_busy; /*apm*/ + (*tty->device.write)(tty->minor, + &tty->rawOutBuf.theBuf[newTail], + nToSend); + } + tty->rawOutBuf.Tail = newTail; /*apm*/ + } + return nToSend; } /* @@ -1397,36 +1394,36 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty) int rtems_termios_dequeue_characters (void *ttyp, int len) { - struct rtems_termios_tty *tty = ttyp; - rtems_status_code sc; - - /* - * sum up character count already sent - */ - tty->t_dqlen += len; - - if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { - /* - * send wake up to transmitter task - */ - sc = rtems_event_send(tty->txTaskId, - TERMIOS_TX_START_EVENT); - if (sc != RTEMS_SUCCESSFUL) - rtems_fatal_error_occurred (sc); - return 0; /* nothing to output in IRQ... */ - } - else if (tty->t_line == PPPDISC ) { - /* - * call any line discipline start function - */ - if (rtems_termios_linesw[tty->t_line].l_start != NULL) { - rtems_termios_linesw[tty->t_line].l_start(tty); - } - return 0; /* nothing to output in IRQ... */ - } - else { - return rtems_termios_refill_transmitter(tty); - } + struct rtems_termios_tty *tty = ttyp; + rtems_status_code sc; + + /* + * sum up character count already sent + */ + tty->t_dqlen += len; + + if (tty->device.outputUsesInterrupts == TERMIOS_TASK_DRIVEN) { + /* + * send wake up to transmitter task + */ + sc = rtems_event_send(tty->txTaskId, + TERMIOS_TX_START_EVENT); + if (sc != RTEMS_SUCCESSFUL) + rtems_fatal_error_occurred (sc); + return 0; /* nothing to output in IRQ... */ + } + + if (tty->t_line == PPPDISC ) { + /* + * call any line discipline start function + */ + if (rtems_termios_linesw[tty->t_line].l_start != NULL) { + rtems_termios_linesw[tty->t_line].l_start(tty); + } + return 0; /* nothing to output in IRQ... */ + } + + return rtems_termios_refill_transmitter(tty); } /* @@ -1434,35 +1431,35 @@ rtems_termios_dequeue_characters (void *ttyp, int len) */ static rtems_task rtems_termios_txdaemon(rtems_task_argument argument) { - struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument; - rtems_event_set the_event; - - while (1) { - /* - * wait for rtems event - */ - rtems_event_receive((TERMIOS_TX_START_EVENT | - TERMIOS_TX_TERMINATE_EVENT), - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &the_event); - if ((the_event & TERMIOS_TX_TERMINATE_EVENT) != 0) { - tty->txTaskId = 0; - rtems_task_delete(RTEMS_SELF); - } - else { - /* - * call any line discipline start function - */ - if (rtems_termios_linesw[tty->t_line].l_start != NULL) { - rtems_termios_linesw[tty->t_line].l_start(tty); - } - /* - * try to push further characters to device - */ - rtems_termios_refill_transmitter(tty); - } - } + struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument; + rtems_event_set the_event; + + while (1) { + /* + * wait for rtems event + */ + rtems_event_receive((TERMIOS_TX_START_EVENT | + TERMIOS_TX_TERMINATE_EVENT), + RTEMS_EVENT_ANY | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, + &the_event); + if ((the_event & TERMIOS_TX_TERMINATE_EVENT) != 0) { + tty->txTaskId = 0; + rtems_task_delete(RTEMS_SELF); + } + else { + /* + * call any line discipline start function + */ + if (rtems_termios_linesw[tty->t_line].l_start != NULL) { + rtems_termios_linesw[tty->t_line].l_start(tty); + } + /* + * try to push further characters to device + */ + rtems_termios_refill_transmitter(tty); + } + } } /* @@ -1470,36 +1467,36 @@ static rtems_task rtems_termios_txdaemon(rtems_task_argument argument) */ static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument) { - struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument; - rtems_event_set the_event; - int c; - char c_buf; - while (1) { - /* - * wait for rtems event - */ - rtems_event_receive((TERMIOS_RX_PROC_EVENT | - TERMIOS_RX_TERMINATE_EVENT), - RTEMS_EVENT_ANY | RTEMS_WAIT, - RTEMS_NO_TIMEOUT, - &the_event); - if ((the_event & TERMIOS_RX_TERMINATE_EVENT) != 0) { - tty->rxTaskId = 0; - rtems_task_delete(RTEMS_SELF); - } - else { - /* - * do something - */ - c = tty->device.pollRead(tty->minor); - if (c != EOF) { - /* - * pollRead did call enqueue on its own - */ - c_buf = c; - rtems_termios_enqueue_raw_characters ( - tty,&c_buf,1); - } - } - } + struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument; + rtems_event_set the_event; + int c; + char c_buf; + while (1) { + /* + * wait for rtems event + */ + rtems_event_receive((TERMIOS_RX_PROC_EVENT | + TERMIOS_RX_TERMINATE_EVENT), + RTEMS_EVENT_ANY | RTEMS_WAIT, + RTEMS_NO_TIMEOUT, + &the_event); + if ((the_event & TERMIOS_RX_TERMINATE_EVENT) != 0) { + tty->rxTaskId = 0; + rtems_task_delete(RTEMS_SELF); + } + else { + /* + * do something + */ + c = tty->device.pollRead(tty->minor); + if (c != EOF) { + /* + * pollRead did call enqueue on its own + */ + c_buf = c; + rtems_termios_enqueue_raw_characters ( + tty,&c_buf,1); + } + } + } } |