示例#1
0
static void
rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
{
  rtems_status_code sc;

  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 if (last_close) {
    /*
     * 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);
    rtems_semaphore_release (tty->osem);
  }

  if (tty->handler.mode == 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( tty->txTaskId, TERMIOS_TX_TERMINATE_EVENT );
    if (sc != RTEMS_SUCCESSFUL)
      rtems_fatal_error_occurred (sc);
  }
  if (last_close && tty->handler.last_close)
     (*tty->handler.last_close)(tty, arg);

  if (tty->device_node != NULL)
    tty->device_node->tty = NULL;

  rtems_semaphore_delete (tty->isem);
  rtems_semaphore_delete (tty->osem);
  rtems_semaphore_delete (tty->rawOutBuf.Semaphore);
  if ((tty->handler.poll_read == NULL) ||
      (tty->handler.mode == TERMIOS_TASK_DRIVEN))
    rtems_semaphore_delete (tty->rawInBuf.Semaphore);
  rtems_interrupt_lock_destroy (&tty->interrupt_lock);
  free (tty->rawInBuf.theBuf);
  free (tty->rawOutBuf.theBuf);
  free (tty->cbuf);
  free (tty);
}
示例#2
0
文件: termios.c 项目: epicsdeb/rtems
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
		 */

#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;
#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;
}
示例#3
0
文件: termios.c 项目: epicsdeb/rtems
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(
                                  tty->rxTaskId,
				  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;
}