</pre><pre name="code" class="cpp">
-
-
-
-
-
-
-
-
-
-
-
static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
-
loff_t *ppos)
-
{
-
int i;
-
struct inode *inode = file->f_path.dentry->d_inode;
-
struct tty_struct *tty = file_tty(file);
-
struct tty_ldisc *ld;
-
-
if (tty_paranoia_check(tty, inode, "tty_read"))
-
return -EIO;
-
if (!tty || (test_bit(TTY_IO_ERROR, &tty->flags)))
-
return -EIO;
-
-
-
-
ld = tty_ldisc_ref_wait(tty);
-
if (ld->ops->read)
-
i = (ld->ops->read)(tty, file, buf, count);
-
else
-
i = -EIO;
-
tty_ldisc_deref(ld);
-
if (i > 0)
-
inode->i_atime = current_fs_time(inode->i_sb);
-
return i;
-
}
-
-
-
-
-
-
-
static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,unsigned char __user *buf, size_t nr)
-
{
-
unsigned char __user *b = buf;
-
-
-
-
uncopied = copy_from_read_buf(tty, &b, &nr);
-
uncopied += copy_from_read_buf(tty, &b, &nr);
-
}
-
-
-
static int copy_from_read_buf(struct tty_struct *tty,unsigned char __user **b,size_t *nr)
-
{
-
-
-
-
if (n) {
-
retval = copy_to_user(*b, &tty->read_buf[tty->read_tail], n);
-
n -= retval;
-
tty_audit_add_data(tty, &tty->read_buf[tty->read_tail], n);
-
spin_lock_irqsave(&tty->read_lock, flags);
-
tty->read_tail = (tty->read_tail + n) & (N_TTY_BUF_SIZE-1);
-
tty->read_cnt -= n;
-
-
if (L_EXTPROC(tty) && tty->icanon && n == 1) {
-
if (!tty->read_cnt && (*b)[n-1] == EOF_CHAR(tty))
-
n--;
-
}
-
spin_unlock_irqrestore(&tty->read_lock, flags);
-
*b += n;
-
*nr -= n;
-
}
-
return retval;
-
}
-
-
-
-
-
-
-
static irqreturn_t s3c24xx_serial_rx_chars(int irq, void *dev_id)
-
{
-
struct s3c24xx_uart_port *ourport = dev_id;
-
struct uart_port *port = &ourport->port;
-
struct tty_struct *tty = port->state->port.tty;
-
unsigned int ufcon, ch, flag, ufstat, uerstat;
-
int max_count = 64;
-
-
while (max_count-- > 0) {
-
-
ufcon = rd_regl(port, S3C2410_UFCON);
-
-
ufstat = rd_regl(port, S3C2410_UFSTAT);
-
-
-
if (s3c24xx_serial_rx_fifocnt(ourport, ufstat) == 0)
-
break;
-
-
-
uerstat = rd_regl(port, S3C2410_UERSTAT);
-
-
ch = rd_regb(port, S3C2410_URXH);
-
-
-
if (port->flags & UPF_CONS_FLOW) {
-
int txe = s3c24xx_serial_txempty_nofifo(port);
-
-
if (rx_enabled(port)) {
-
if (!txe) {
-
rx_enabled(port) = 0;
-
continue;
-
}
-
} else {
-
if (txe) {
-
ufcon |= S3C2410_UFCON_RESETRX;
-
wr_regl(port, S3C2410_UFCON, ufcon);
-
rx_enabled(port) = 1;
-
goto out;
-
}
-
continue;
-
}
-
}
-
-
-
-
flag = TTY_NORMAL;
-
port->icount.rx++;
-
-
if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
-
dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
-
ch, uerstat);
-
-
-
if (uerstat & S3C2410_UERSTAT_BREAK) {
-
dbg("break!\n");
-
port->icount.brk++;
-
if (uart_handle_break(port))
-
goto ignore_char;
-
}
-
-
if (uerstat & S3C2410_UERSTAT_FRAME)
-
port->icount.frame++;
-
if (uerstat & S3C2410_UERSTAT_OVERRUN)
-
port->icount.overrun++;
-
-
uerstat &= port->read_status_mask;
-
-
if (uerstat & S3C2410_UERSTAT_BREAK)
-
flag = TTY_BREAK;
-
else if (uerstat & S3C2410_UERSTAT_PARITY)
-
flag = TTY_PARITY;
-
else if (uerstat & (S3C2410_UERSTAT_FRAME |
-
S3C2410_UERSTAT_OVERRUN))
-
flag = TTY_FRAME;
-
}
-
-
if (uart_handle_sysrq_char(port, ch))
-
goto ignore_char;
-
-
-
uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
-
ch, flag);
-
}
-
-
-
tty_flip_buffer_push(tty);
-
}
-
-
static inline int tty_insert_flip_char(struct tty_struct *tty,unsigned char ch, char flag)
-
{
-
struct tty_buffer *tb = tty->buf.tail;
-
if (tb && tb->used < tb->size) {
-
tb->flag_buf_ptr[tb->used] = flag;
-
tb->char_buf_ptr[tb->used++] = ch;
-
return 1;
-
}
-
return tty_insert_flip_string_flags(tty, &ch, &flag, 1);
-
}
-
-
static void flush_to_ldisc(struct work_struct *work)
-
{
-
char_buf = head->char_buf_ptr + head->read;
-
flag_buf = head->flag_buf_ptr + head->read;
-
head->read += count;
-
spin_unlock_irqrestore(&tty->buf.lock, flags);
-
disc->ops->receive_buf(tty, char_buf,
-
flag_buf, count);
-
}
-
-
static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,char *fp, int count)
-
{
-
-
if (tty->real_raw) {
-
spin_lock_irqsave(&tty->read_lock, cpuflags);
-
i = min(N_TTY_BUF_SIZE - tty->read_cnt,
-
N_TTY_BUF_SIZE - tty->read_head);
-
i = min(count, i);
-
memcpy(tty->read_buf + tty->read_head, cp, i);
-
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-
tty->read_cnt += i;
-
cp += i;
-
count -= i;
-
-
i = min(N_TTY_BUF_SIZE - tty->read_cnt,
-
N_TTY_BUF_SIZE - tty->read_head);
-
i = min(count, i);
-
memcpy(tty->read_buf + tty->read_head, cp, i);
-
tty->read_head = (tty->read_head + i) & (N_TTY_BUF_SIZE-1);
-
tty->read_cnt += i;
-
spin_unlock_irqrestore(&tty->read_lock, cpuflags);
-
}
-
}