/* * Open a tty line. Note that this can be called multiple times, so ->open can * be >1. Only set up the tty struct if this is a "new" open, e.g. ->open was * zero */ static int duart_open(struct tty_struct *tty, struct file *filp) { uart_state_t *us; unsigned int line = tty->index; unsigned long flags; if ((line >= tty->driver->num) || !sb1250_duart_present[line]) return -ENODEV; #ifdef DUART_SPEW printk("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n", current->pid, current->comm, tty, tty->read_wait, tty->write_wait); #endif us = uart_states + line; tty->driver_data = us; spin_lock_irqsave(&open_lock, flags); if (!us->open) { us->tty = tty; us->tty->termios->c_cflag = us->last_cflags; } us->open++; us->flags &= ~TX_INTEN; duart_unmask_ints(line, M_DUART_IMR_RX); spin_unlock_irqrestore(&open_lock, flags); return 0; }
/* * Open a tty line. Note that this can be called multiple times, so ->open can * be >1. Only set up the tty struct if this is a "new" open, e.g. ->open was * zero */ static int duart_open(struct tty_struct *tty, struct file *filp) { uart_state_t *us; unsigned int line = MINOR(tty->device) - tty->driver.minor_start; unsigned long flags; MOD_INC_USE_COUNT; if ((line < 0) || (line >= DUART_MAX_LINE) || !sb1250_duart_present[line]) { MOD_DEC_USE_COUNT; return -ENODEV; } #ifdef DUART_SPEW printk("duart_open called by %i (%s), tty is %p, rw is %p, ww is %p\n", current->pid, current->comm, tty, tty->read_wait, tty->write_wait); #endif us = uart_states + line; tty->driver_data = us; spin_lock_irqsave(&open_lock, flags); if (!us->open) { us->tty = tty; us->tty->termios->c_cflag = us->last_cflags; } us->open++; us->flags &= ~TX_INTEN; duart_unmask_ints(line, M_DUART_IMR_RX); spin_unlock_irqrestore(&open_lock, flags); return 0; }
/* * Buffer up to count characters from buf to be written. If we don't have * other characters buffered, enable the tx interrupt to start sending */ static int duart_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count) { uart_state_t *us; int c, t, total = 0; unsigned long flags; if (!tty) return 0; us = tty->driver_data; if (!us) return 0; #ifdef DUART_SPEW printk("duart_write called for %i chars by %i (%s)\n", count, current->pid, current->comm); #endif spin_lock_irqsave(&us->outp_lock, flags); for (;;) { c = count; t = SERIAL_XMIT_SIZE - us->outp_tail; if (t < c) c = t; t = SERIAL_XMIT_SIZE - 1 - us->outp_count; if (t < c) c = t; if (c <= 0) break; if (from_user) { spin_unlock_irqrestore(&us->outp_lock, flags); if (copy_from_user(us->outp_buf + us->outp_tail, buf, c)) { return -EFAULT; } spin_lock_irqsave(&us->outp_lock, flags); } else { memcpy(us->outp_buf + us->outp_tail, buf, c); } us->outp_count += c; us->outp_tail = (us->outp_tail + c) & (SERIAL_XMIT_SIZE - 1); buf += c; count -= c; total += c; } spin_unlock_irqrestore(&us->outp_lock, flags); if (us->outp_count && !tty->stopped && !tty->hw_stopped && !(us->flags & TX_INTEN)) { us->flags |= TX_INTEN; duart_unmask_ints(us->line, M_DUART_IMR_TX); } return total; }
/* XXXKW locking? */ static void duart_start(struct tty_struct *tty) { uart_state_t *us = (uart_state_t *) tty->driver_data; #ifdef DUART_SPEW printk("duart_start called\n"); #endif if (us->outp_count && !(us->flags & TX_INTEN)) { us->flags |= TX_INTEN; duart_unmask_ints(us->line, M_DUART_IMR_TX); } }
static void duart_flush_chars(struct tty_struct * tty) { uart_state_t *port; if (!tty) return; port = tty->driver_data; if (!port) return; if (port->outp_count <= 0 || tty->stopped || tty->hw_stopped) { return; } port->flags |= TX_INTEN; duart_unmask_ints(port->line, M_DUART_IMR_TX); }