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; }
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; }
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); }
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); }
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); }
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; }
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; }
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; }
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; }
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; }
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; }