Exemplo n.º 1
0
static int uart_do_autoconfig(struct tty_struct *tty,struct uart_state *state)
{
	struct uart_port *uport = state->uart_port;
	struct tty_port *port = &state->port;
	int flags, ret;

	if (!capable(CAP_SYS_ADMIN))
		return -EPERM;

	if (mutex_lock_interruptible(&port->mutex))
		return -ERESTARTSYS;

	ret = -EBUSY;
	if (tty_port_users(port) == 1) {
		uart_shutdown(tty, state);

		if (uport->type != PORT_UNKNOWN)
			uport->ops->release_port(uport);

		flags = UART_CONFIG_TYPE;
		if (uport->flags & UPF_AUTO_IRQ)
			flags |= UART_CONFIG_IRQ;

		uport->ops->config_port(uport, flags);

		ret = uart_startup(tty, state, 1);
	}
	mutex_unlock(&port->mutex);
	return ret;
}
Exemplo n.º 2
0
static int uart_close(FAR struct file *filep)
{
    FAR struct inode *inode = filep->f_inode;
    FAR uart_dev_t   *dev   = inode->i_private;
    irqstate_t        flags;

    uart_takesem(&dev->closesem);
    if (dev->open_count > 1)
    {
        dev->open_count--;
        uart_givesem(&dev->closesem);
        return OK;
    }

    /* There are no more references to the port */

    dev->open_count = 0;

    /* Stop accepting input */

    uart_disablerxint(dev);

    /* Now we wait for the transmit buffer to clear */

    while (dev->xmit.head != dev->xmit.tail)
    {
#ifndef CONFIG_DISABLE_SIGNALS
        usleep(HALF_SECOND_USEC);
#else
        up_mdelay(HALF_SECOND_MSEC);
#endif
    }

    /* And wait for the TX fifo to drain */

    while (!uart_txempty(dev))
    {
#ifndef CONFIG_DISABLE_SIGNALS
        usleep(HALF_SECOND_USEC);
#else
        up_mdelay(HALF_SECOND_MSEC);
#endif
    }

    /* Free the IRQ and disable the UART */

    flags = irqsave();       /* Disable interrupts */
    uart_detach(dev);        /* Detach interrupts */
    if (!dev->isconsole)     /* Check for the serial console UART */
    {
        uart_shutdown(dev);  /* Disable the UART */
    }
    irqrestore(flags);

    uart_givesem(&dev->closesem);
    return OK;
}
Exemplo n.º 3
0
static void uart_close(struct tty_struct *tty, struct file *filp)
{
	struct uart_state *state = tty->driver_data;
	struct tty_port *port;
	struct uart_port *uport;
	unsigned long flags;

	if (!state)
		return;

	uport = state->uart_port;
	port = &state->port;

	pr_debug("uart_close(%d) called\n", uport->line);

	if (tty_port_close_start(port, tty, filp) == 0)
		return;

	if (port->flags & ASYNC_INITIALIZED) {
		unsigned long flags;
		spin_lock_irqsave(&uport->lock, flags);
		uport->ops->stop_rx(uport);
		spin_unlock_irqrestore(&uport->lock, flags);
		uart_wait_until_sent(tty, uport->timeout);
	}

	mutex_lock(&port->mutex);
	uart_shutdown(tty, state);
	uart_flush_buffer(tty);

	tty_ldisc_flush(tty);

	tty_port_tty_set(port, NULL);
	spin_lock_irqsave(&port->lock, flags);
	tty->closing = 0;

	if (port->blocked_open) {
		spin_unlock_irqrestore(&port->lock, flags);
		if (port->close_delay)
			msleep_interruptible(
					jiffies_to_msecs(port->close_delay));
		spin_lock_irqsave(&port->lock, flags);
	} else if (!uart_console(uport)) {
		spin_unlock_irqrestore(&port->lock, flags);
		uart_change_pm(state, 3);
		spin_lock_irqsave(&port->lock, flags);
	}

	clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
	clear_bit(ASYNCB_CLOSING, &port->flags);
	spin_unlock_irqrestore(&port->lock, flags);
	wake_up_interruptible(&port->open_wait);
	wake_up_interruptible(&port->close_wait);

	mutex_unlock(&port->mutex);
}
Exemplo n.º 4
0
struct debug_t *debug_init(void)
{
	struct debug_t *debug;

	uart_init();
	debug = malloc(sizeof(struct debug_t));
	debug->line = malloc(MAX_LINE_LENGHT);
	debug->string = malloc(MAX_STRING_LENGHT);
	debug->active = 1;
	hello(debug);
	debug_print_P(PSTR("\nActivate debug? (y/N): "), debug);

	if (!debug_wait_for_y(debug)) {
		uart_shutdown();
		debug->active = 0;
		free(debug->line);
		free(debug->string);
	}

	return(debug);
}
Exemplo n.º 5
0
static void uart_hangup(struct tty_struct *tty)
{
	struct uart_state *state = tty->driver_data;
	struct tty_port *port = &state->port;
	unsigned long flags;

	pr_debug("uart_hangup(%d)\n", state->uart_port->line);

	mutex_lock(&port->mutex);
	if (port->flags & ASYNC_NORMAL_ACTIVE) {
		uart_flush_buffer(tty);
		uart_shutdown(tty, state);
		spin_lock_irqsave(&port->lock, flags);
		port->count = 0;
		clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
		spin_unlock_irqrestore(&port->lock, flags);
		tty_port_tty_set(port, NULL);
		wake_up_interruptible(&port->open_wait);
		wake_up_interruptible(&port->delta_msr_wait);
	}
	mutex_unlock(&port->mutex);
}
Exemplo n.º 6
0
static int uart_open(FAR struct file *filep)
{
    struct inode *inode = filep->f_inode;
    uart_dev_t   *dev   = inode->i_private;
    uint8_t       tmp;
    int           ret   = OK;

    /* If the port is the middle of closing, wait until the close is finished */

    uart_takesem(&dev->closesem);

    /* Start up serial port */
    /* Increment the count of references to the device. */

    tmp = dev->open_count + 1;
    if (tmp == 0)
    {
        /* More than 255 opens; uint8_t overflows to zero */

        ret = -EMFILE;
        goto errout_with_sem;
    }

    /* Check if this is the first time that the driver has been opened. */

    if (tmp == 1)
    {
        irqstate_t flags = irqsave();

        /* If this is the console, then the UART has already been initialized. */

        if (!dev->isconsole)
        {
            /* Perform one time hardware initialization */

            ret = uart_setup(dev);
            if (ret < 0)
            {
                irqrestore(flags);
                goto errout_with_sem;
            }
        }

        /* In any event, we do have to configure for interrupt driven mode of
         * operation.  Attach the hardware IRQ(s). Hmm.. should shutdown() the
         * the device in the rare case that uart_attach() fails, tmp==1, and
         * this is not the console.
         */

        ret = uart_attach(dev);
        if (ret < 0)
        {
            uart_shutdown(dev);
            irqrestore(flags);
            goto errout_with_sem;
        }

        /* Mark the io buffers empty */

        dev->xmit.head = 0;
        dev->xmit.tail = 0;
        dev->recv.head = 0;
        dev->recv.tail = 0;

        /* Enable the RX interrupt */

        uart_enablerxint(dev);
        irqrestore(flags);
    }

    /* Save the new open count on success */

    dev->open_count = tmp;

errout_with_sem:
    uart_givesem(&dev->closesem);
    return ret;
}
Exemplo n.º 7
0
static int uart_set_info(struct tty_struct *tty, struct uart_state *state,
			 struct serial_struct __user *newinfo)
{
	struct serial_struct new_serial;
	struct uart_port *uport = state->uart_port;
	struct tty_port *port = &state->port;
	unsigned long new_port;
	unsigned int change_irq, change_port, closing_wait;
	unsigned int old_custom_divisor, close_delay;
	upf_t old_flags, new_flags;
	int retval = 0;

	if (copy_from_user(&new_serial, newinfo, sizeof(new_serial)))
		return -EFAULT;

	new_port = new_serial.port;
	if (HIGH_BITS_OFFSET)
		new_port += (unsigned long) new_serial.port_high << HIGH_BITS_OFFSET;

	new_serial.irq = irq_canonicalize(new_serial.irq);
	close_delay = msecs_to_jiffies(new_serial.close_delay * 10);
	closing_wait = new_serial.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
			ASYNC_CLOSING_WAIT_NONE :
			msecs_to_jiffies(new_serial.closing_wait * 10);

	mutex_lock(&port->mutex);

	change_irq  = !(uport->flags & UPF_FIXED_PORT)
		&& new_serial.irq != uport->irq;

	change_port = !(uport->flags & UPF_FIXED_PORT)
		&& (new_port != uport->iobase ||
		    (unsigned long)new_serial.iomem_base != uport->mapbase ||
		    new_serial.hub6 != uport->hub6 ||
		    new_serial.io_type != uport->iotype ||
		    new_serial.iomem_reg_shift != uport->regshift ||
		    new_serial.type != uport->type);

	old_flags = uport->flags;
	new_flags = new_serial.flags;
	old_custom_divisor = uport->custom_divisor;

	if (!capable(CAP_SYS_ADMIN)) {
		retval = -EPERM;
		if (change_irq || change_port ||
		    (new_serial.baud_base != uport->uartclk / 16) ||
		    (close_delay != port->close_delay) ||
		    (closing_wait != port->closing_wait) ||
		    (new_serial.xmit_fifo_size &&
		     new_serial.xmit_fifo_size != uport->fifosize) ||
		    (((new_flags ^ old_flags) & ~UPF_USR_MASK) != 0))
			goto exit;
		uport->flags = ((uport->flags & ~UPF_USR_MASK) |
			       (new_flags & UPF_USR_MASK));
		uport->custom_divisor = new_serial.custom_divisor;
		goto check_and_exit;
	}

	if (uport->ops->verify_port)
		retval = uport->ops->verify_port(uport, &new_serial);

	if ((new_serial.irq >= nr_irqs) || (new_serial.irq < 0) ||
	    (new_serial.baud_base < 9600))
		retval = -EINVAL;

	if (retval)
		goto exit;

	if (change_port || change_irq) {
		retval = -EBUSY;

		if (tty_port_users(port) > 1)
			goto exit;

		uart_shutdown(tty, state);
	}

	if (change_port) {
		unsigned long old_iobase, old_mapbase;
		unsigned int old_type, old_iotype, old_hub6, old_shift;

		old_iobase = uport->iobase;
		old_mapbase = uport->mapbase;
		old_type = uport->type;
		old_hub6 = uport->hub6;
		old_iotype = uport->iotype;
		old_shift = uport->regshift;

		if (old_type != PORT_UNKNOWN)
			uport->ops->release_port(uport);

		uport->iobase = new_port;
		uport->type = new_serial.type;
		uport->hub6 = new_serial.hub6;
		uport->iotype = new_serial.io_type;
		uport->regshift = new_serial.iomem_reg_shift;
		uport->mapbase = (unsigned long)new_serial.iomem_base;

		if (uport->type != PORT_UNKNOWN) {
			retval = uport->ops->request_port(uport);
		} else {
			
			retval = 0;
		}

		if (retval && old_type != PORT_UNKNOWN) {
			uport->iobase = old_iobase;
			uport->type = old_type;
			uport->hub6 = old_hub6;
			uport->iotype = old_iotype;
			uport->regshift = old_shift;
			uport->mapbase = old_mapbase;
			retval = uport->ops->request_port(uport);
			if (retval)
				uport->type = PORT_UNKNOWN;

			retval = -EBUSY;
			
			goto exit;
		}
	}

	if (change_irq)
		uport->irq      = new_serial.irq;
	if (!(uport->flags & UPF_FIXED_PORT))
		uport->uartclk  = new_serial.baud_base * 16;
	uport->flags            = (uport->flags & ~UPF_CHANGE_MASK) |
				 (new_flags & UPF_CHANGE_MASK);
	uport->custom_divisor   = new_serial.custom_divisor;
	port->close_delay     = close_delay;
	port->closing_wait    = closing_wait;
	if (new_serial.xmit_fifo_size)
		uport->fifosize = new_serial.xmit_fifo_size;
	if (port->tty)
		port->tty->low_latency =
			(uport->flags & UPF_LOW_LATENCY) ? 1 : 0;

 check_and_exit:
	retval = 0;
	if (uport->type == PORT_UNKNOWN)
		goto exit;
	if (port->flags & ASYNC_INITIALIZED) {
		if (((old_flags ^ uport->flags) & UPF_SPD_MASK) ||
		    old_custom_divisor != uport->custom_divisor) {
			if (uport->flags & UPF_SPD_MASK) {
				char buf[64];
				printk(KERN_NOTICE
				       "%s sets custom speed on %s. This "
				       "is deprecated.\n", current->comm,
				       tty_name(port->tty, buf));
			}
			uart_change_speed(tty, state, NULL);
		}
	} else
		retval = uart_startup(tty, state, 1);
 exit:
	mutex_unlock(&port->mutex);
	return retval;
}
Exemplo n.º 8
0
int uart_resume_port(struct uart_driver *drv, struct uart_port *uport)
{
	struct uart_state *state = drv->state + uport->line;
	struct tty_port *port = &state->port;
	struct device *tty_dev;
	struct uart_match match = {uport, drv};
	struct ktermios termios;

	mutex_lock(&port->mutex);

	tty_dev = device_find_child(uport->dev, &match, serial_match_port);
	if (!uport->suspended && device_may_wakeup(tty_dev)) {
		if (uport->irq_wake) {
			disable_irq_wake(uport->irq);
			uport->irq_wake = 0;
		}
		put_device(tty_dev);
		mutex_unlock(&port->mutex);
		return 0;
	}
	put_device(tty_dev);
	uport->suspended = 0;

	if (uart_console(uport)) {
		memset(&termios, 0, sizeof(struct ktermios));
		termios.c_cflag = uport->cons->cflag;

		if (port->tty && port->tty->termios && termios.c_cflag == 0)
			termios = *(port->tty->termios);
		if (console_suspend_enabled)
			uart_change_pm(state, 0);
		uport->ops->set_termios(uport, &termios, NULL);
		if (console_suspend_enabled)
			console_start(uport->cons);
	}

	if (port->flags & ASYNC_SUSPENDED) {
		const struct uart_ops *ops = uport->ops;
		int ret;

		uart_change_pm(state, 0);
		spin_lock_irq(&uport->lock);
		ops->set_mctrl(uport, 0);
		spin_unlock_irq(&uport->lock);
		if (console_suspend_enabled || !uart_console(uport)) {
			
			struct tty_struct *tty = port->tty;
			ret = ops->startup(uport);
			if (ret == 0) {
				if (tty)
					uart_change_speed(tty, state, NULL);
				spin_lock_irq(&uport->lock);
				ops->set_mctrl(uport, uport->mctrl);
				ops->start_tx(uport);
				spin_unlock_irq(&uport->lock);
				set_bit(ASYNCB_INITIALIZED, &port->flags);
			} else {
				uart_shutdown(tty, state);
			}
		}

		clear_bit(ASYNCB_SUSPENDED, &port->flags);
	}

	mutex_unlock(&port->mutex);

	return 0;
}
Exemplo n.º 9
0
static int uart_close(FAR struct file *filep)
{
  FAR struct inode *inode = filep->f_inode;
  FAR uart_dev_t   *dev   = inode->i_private;
  irqstate_t        flags;

  /* Get exclusive access to the close semaphore (to synchronize open/close operations.
   * NOTE: that we do not let this wait be interrupted by a signal.  Technically, we
   * should, but almost no one every checks the return value from close() so we avoid
   * a potential memory leak by ignoring signals in this case.
   */

  (void)uart_takesem(&dev->closesem, false);
  if (dev->open_count > 1)
    {
      dev->open_count--;
      uart_givesem(&dev->closesem);
      return OK;
    }

  /* There are no more references to the port */

  dev->open_count = 0;

  /* Stop accepting input */

  uart_disablerxint(dev);

  /* Now we wait for the transmit buffer to clear */

  while (dev->xmit.head != dev->xmit.tail)
    {
#ifndef CONFIG_DISABLE_SIGNALS
      usleep(HALF_SECOND_USEC);
#else
      up_mdelay(HALF_SECOND_MSEC);
#endif
    }

  /* And wait for the TX fifo to drain */

  while (!uart_txempty(dev))
    {
#ifndef CONFIG_DISABLE_SIGNALS
      usleep(HALF_SECOND_USEC);
#else
      up_mdelay(HALF_SECOND_MSEC);
#endif
    }

  /* Free the IRQ and disable the UART */

  flags = irqsave();       /* Disable interrupts */
  uart_detach(dev);        /* Detach interrupts */
  if (!dev->isconsole)     /* Check for the serial console UART */
    {
      uart_shutdown(dev);  /* Disable the UART */
    }
  irqrestore(flags);

  uart_givesem(&dev->closesem);
  return OK;
 }
Exemplo n.º 10
0
static int uart_open(FAR struct file *filep)
{
    struct inode *inode = filep->f_inode;
    uart_dev_t   *dev   = inode->i_private;
    uint8_t       tmp;
    int           ret;

    /* If the port is the middle of closing, wait until the close is finished.
     * If a signal is received while we are waiting, then return EINTR.
     */

    ret = uart_takesem(&dev->closesem, true);
    if (ret < 0)
    {
        /* A signal received while waiting for the last close operation. */

        return ret;
    }

#ifdef CONFIG_SERIAL_REMOVABLE
    /* If the removable device is no longer connected, refuse to open the
     * device.  We check this after obtaining the close semaphore because
     * we might have been waiting when the device was disconnected.
     */

    if (dev->disconnected)
    {
        ret = -ENOTCONN;
        goto errout_with_sem;
    }
#endif

    /* Start up serial port */
    /* Increment the count of references to the device. */

    tmp = dev->open_count + 1;
    if (tmp == 0)
    {
        /* More than 255 opens; uint8_t overflows to zero */

        ret = -EMFILE;
        goto errout_with_sem;
    }

    /* Check if this is the first time that the driver has been opened. */

    if (tmp == 1)
    {
        irqstate_t flags = irqsave();

        /* If this is the console, then the UART has already been initialized. */

        if (!dev->isconsole)
        {
            /* Perform one time hardware initialization */

            ret = uart_setup(dev);
            if (ret < 0)
            {
                irqrestore(flags);
                goto errout_with_sem;
            }
        }

        /* In any event, we do have to configure for interrupt driven mode of
         * operation.  Attach the hardware IRQ(s). Hmm.. should shutdown() the
         * the device in the rare case that uart_attach() fails, tmp==1, and
         * this is not the console.
         */

        ret = uart_attach(dev);
        if (ret < 0)
        {
            uart_shutdown(dev);
            irqrestore(flags);
            goto errout_with_sem;
        }

        /* Mark the io buffers empty */

        dev->xmit.head = 0;
        dev->xmit.tail = 0;
        dev->recv.head = 0;
        dev->recv.tail = 0;

        /* Initialise termios state */

#ifdef CONFIG_SERIAL_TERMIOS
        dev->tc_iflag = 0;
        if (dev->isconsole == true)
        {
            /* Enable \n -> \r\n translation for the console */

            dev->tc_oflag = OPOST | ONLCR;
        }
        else
        {
            dev->tc_oflag = 0;
        }
#endif

        /* Enable the RX interrupt */

        uart_enablerxint(dev);
        irqrestore(flags);
    }

    /* Save the new open count on success */

    dev->open_count = tmp;

errout_with_sem:
    uart_givesem(&dev->closesem);
    return ret;
}
Exemplo n.º 11
0
static int uart_close(FAR struct file *filep)
{
  FAR struct inode *inode = filep->f_inode;
  FAR uart_dev_t   *dev   = inode->i_private;
  irqstate_t        flags;

  /* Get exclusive access to the close semaphore (to synchronize open/close operations.
   * NOTE: that we do not let this wait be interrupted by a signal.  Technically, we
   * should, but almost no one every checks the return value from close() so we avoid
   * a potential memory leak by ignoring signals in this case.
   */

  (void)uart_takesem(&dev->closesem, false);
  if (dev->open_count > 1)
    {
      dev->open_count--;
      uart_givesem(&dev->closesem);
      return OK;
    }

  /* There are no more references to the port */

  dev->open_count = 0;

  /* Stop accepting input */

  uart_disablerxint(dev);

  /* Now we wait for the transmit buffer to clear */

  while (dev->xmit.head != dev->xmit.tail)
    {
#ifndef CONFIG_DISABLE_SIGNALS
      usleep(HALF_SECOND_USEC);
#else
      up_mdelay(HALF_SECOND_MSEC);
#endif
    }

  /* And wait for the TX fifo to drain */

  while (!uart_txempty(dev))
    {
#ifndef CONFIG_DISABLE_SIGNALS
      usleep(HALF_SECOND_USEC);
#else
      up_mdelay(HALF_SECOND_MSEC);
#endif
    }

  /* Free the IRQ and disable the UART */

  flags = irqsave();       /* Disable interrupts */
  uart_detach(dev);        /* Detach interrupts */
  if (!dev->isconsole)     /* Check for the serial console UART */
    {
      uart_shutdown(dev);  /* Disable the UART */
    }

  irqrestore(flags);

  /* We need to re-initialize the semaphores if this is the last close
   * of the device, as the close might be caused by pthread_cancel() of
   * a thread currently blocking on any of them.
   *
   * REVISIT:  This logic *only* works in the case where the cancelled
   * thread had the only reference to the serial driver.  If there other
   * references, then the this logic will not be executed and the
   * semaphore count will still be incorrect.
   */

  sem_reinit(&dev->xmitsem,  0, 0);
  sem_reinit(&dev->recvsem,  0, 0);
  sem_reinit(&dev->xmit.sem, 0, 1);
  sem_reinit(&dev->recv.sem, 0, 1);
#ifndef CONFIG_DISABLE_POLL
  sem_reinit(&dev->pollsem,  0, 1);
#endif

  uart_givesem(&dev->closesem);
  return OK;
}