static Cyg_ErrNo altera_avalon_jtag_uart_set_config(serial_channel *chan, 
                                                    cyg_uint32 key,
                                                    const void *xbuf, 
                                                    cyg_uint32 *len)
{
  altera_avalon_jtag_uart_dev *jtag_uart_chan = 
                            (altera_avalon_jtag_uart_dev *)chan->dev_priv;
  cyg_addrword_t port = jtag_uart_chan->base;
  Cyg_ErrNo ret_code;
  cyg_uint32     control;

  switch (key)
  {
  case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE:
    { 
      if(*len != 4)
      {
        ret_code = -EINVAL;
      }
      else 
      {
        if (*(char*)xbuf == 1) 
        {
          /*
           * Throttle Rx
           */
          control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(port);
          control &= ~ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK;
          IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(port, control);
          ret_code = ENOERR;
        }
        else if (*(char*)xbuf == 0)
        {
          /*
           * Restart Rx
           */
          control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(port);
          control |= ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK;
          IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(port, control);
          ret_code = ENOERR;
        }
        else
        {
          ret_code = -EINVAL;
        }
      }
      break;
    }
  default:
    {
      ret_code = -EINVAL;
      break;
    }
  }

  return ret_code;
}
static void altera_avalon_jtag_uart_stop_xmit(serial_channel *chan)
{
  altera_avalon_jtag_uart_dev *jtag_uart_chan = 
                                (altera_avalon_jtag_uart_dev *)chan->dev_priv;
  cyg_addrword_t port               = jtag_uart_chan->base;
  cyg_uint32     control;
  unsigned int  status;
  
  control = IORD_ALTERA_AVALON_JTAG_UART_CONTROL(port);
  control &= ~ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK;
  IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(port, control);

  return;
}
Example #3
0
//-------------------------------------------------------------------------------
int alt_avn_jtag_uart_read(alt_avn_jtag_uart_state* sp, 
		char * buffer, int space, int flags)
{
	char * ptr = buffer;

	alt_irq_context context;
	unsigned int n;

	/*
	 * When running in a multi threaded environment, obtain the "read_lock"
	 * semaphore. This ensures that reading from the device is thread-safe.
	 */
	ALT_SEM_PEND (sp->read_lock, 0);

	while (space > 0)
	{
		unsigned int in, out;

		/* Read as much data as possible */
		do
		{
			in  = sp->rx_in;
			out = sp->rx_out;

			if (in >= out)
				n = in - out;
			else
				n = ALTERA_AVALON_JTAG_UART_BUF_LEN - out;

			if (n == 0)
				break; /* No more data available */

			if (n > space)
				n = space;

			memcpy(ptr, sp->rx_buf + out, n);
			ptr   += n;
			space -= n;

			sp->rx_out = (out + n) % ALTERA_AVALON_JTAG_UART_BUF_LEN;
		}
		while (space > 0);

		/* If we read any data then return it */
		if (ptr != buffer)
			break;

		/* If in non-blocking mode then return error */
		if (flags & O_NONBLOCK)
			break;

		/* OS Present: Pend on a flag if the OS is running, otherwise spin */
		if(OSRunning == OS_TRUE) {
			/*
			 * When running in a multi-threaded mode, we pend on the read event
			 * flag set and timeout event flag set in the isr. This avoids wasting CPU
			 * cycles waiting in this thread, when we could be doing something more
			 * profitable elsewhere.
			 */
			ALT_FLAG_PEND (sp->events,
					ALT_JTAG_UART_READ_RDY | ALT_JTAG_UART_TIMEOUT,
					OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
					0);
		}
		else {
			/* Spin until more data arrives or until host disconnects */
			while (in == sp->rx_in && sp->host_inactive < sp->timeout)
				;
		}


		if (in == sp->rx_in)
			break;
	}

	/*
	 * Now that access to the circular buffer is complete, release the read
	 * semaphore so that other threads can access the buffer.
	 */

	ALT_SEM_POST (sp->read_lock);

	if (ptr != buffer)
	{
		/* If we read any data then there is space in the buffer so enable interrupts */
		context = alt_irq_disable_all();
		sp->irq_enable |= ALTERA_AVALON_JTAG_UART_CONTROL_RE_MSK;
		IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable);
		alt_irq_enable_all(context);
	}

	if (ptr != buffer)
		return ptr - buffer;
	else if (flags & O_NONBLOCK)
		return -EWOULDBLOCK;
	else
		return -EIO;
}
Example #4
0
int alt_avn_jtag_uart_write(alt_avn_jtag_uart_state* sp, 
		const char * ptr, int count, int flags)
{
	/* Remove warning at optimisation level 03 by seting out to 0 */
	unsigned int in, out=0;
	unsigned int n;
	alt_irq_context context;

	const char * start = ptr;

	/*
	 * When running in a multi threaded environment, obtain the "write_lock"
	 * semaphore. This ensures that writing to the device is thread-safe.
	 */
	ALT_SEM_PEND (sp->write_lock, 0);

	do
	{
		/* Copy as much as we can into the transmit buffer */
		while (count > 0)
		{
			/* We need a stable value of the out pointer to calculate the space available */
			in  = sp->tx_in;
			out = sp->tx_out;

			if (in < out)
				n = out - 1 - in;
			else if (out > 0)
				n = ALTERA_AVALON_JTAG_UART_BUF_LEN - in;
			else
				n = ALTERA_AVALON_JTAG_UART_BUF_LEN - 1 - in;

			if (n == 0)
				break;

			if (n > count)
				n = count;

			memcpy(sp->tx_buf + in, ptr, n);
			ptr   += n;
			count -= n;

			sp->tx_in = (in + n) % ALTERA_AVALON_JTAG_UART_BUF_LEN;
		}

		/*
		 * If interrupts are disabled then we could transmit here, we only need 
		 * to enable interrupts if there is no space left in the FIFO
		 *
		 * For now kick the interrupt routine every time to make it transmit 
		 * the data 
		 */
		context = alt_irq_disable_all();
		sp->irq_enable |= ALTERA_AVALON_JTAG_UART_CONTROL_WE_MSK;
		IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(sp->base, sp->irq_enable);
		alt_irq_enable_all(context);

		/* 
		 * If there is any data left then either return now or block until 
		 * some has been sent 
		 */
		/* consider: test whether there is anything there while doing this and delay for at most 2s. */
		if (count > 0)
		{
			if (flags & O_NONBLOCK)
				break;

			/* OS Present: Pend on a flag if the OS is running, otherwise spin */
			if(OSRunning == OS_TRUE) {
				/*
				 * When running in a multi-threaded mode, we pend on the write event
				 * flag set or the timeout flag in the isr. This avoids wasting CPU
				 * cycles waiting in this thread, when we could be doing something
				 * more profitable elsewhere.
				 */
				ALT_FLAG_PEND (sp->events,
						ALT_JTAG_UART_WRITE_RDY | ALT_JTAG_UART_TIMEOUT,
						OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME,
						0);
			}
			else {
				/*
				 * OS not running: Wait for data to be removed from buffer.
				 * Once the interrupt routine has removed some data then we
				 * will be able to insert some more.
				 */
				while (out == sp->tx_out && sp->host_inactive < sp->timeout)
					;
			}

			if (out == sp->tx_out)
				break;
		}
	}
	while (count > 0);

	/*
	 * Now that access to the circular buffer is complete, release the write
	 * semaphore so that other threads can access the buffer.
	 */
	ALT_SEM_POST (sp->write_lock);

	if (ptr != start)
		return ptr - start;
	else if (flags & O_NONBLOCK)
		return -EWOULDBLOCK;
	else
		return -EIO; /* Host not connected */
}