tty_driver-data_struct
serial8250_init
使用的数据结构很多,按照自顶向下的顺序介绍,即从更一般的 TTY 层到更具体的 8250 层。
介绍这些数据结构时,以 serial8250_init
执行时设置的各个成员变量的值为例进行说明。
每个设备保存自己的 port 信息,用 struct tty_port 实现。
struct tty_port {
struct tty_bufhead buf; /* Locked internally */
struct tty_struct *tty; /* Back pointer */
struct tty_struct *itty; /* internal back ptr */
// static const struct tty_port_operations uart_port_ops ;
const struct tty_port_operations *ops; /* Port operations */
// static const struct tty_port_client_operations default_client_ops;
const struct tty_port_client_operations *client_ops; /* Port client operations */
spinlock_t lock; /* Lock protecting tty field */
int blocked_open; /* Waiting to open */
int count; /* Usage count */
// 打开 tty 设备文件时将进程添加到该等待队列
wait_queue_head_t open_wait; /* Open waiters */
wait_queue_head_t delta_msr_wait; /* Modem status change */
unsigned long flags; /* User TTY flags ASYNC_ */
unsigned long iflags; /* Internal flags TTY_PORT_ */
unsigned char console:1, /* port is a console */
low_latency:1; /* optional: tune for latency */
struct mutex mutex; /* Locking */
struct mutex buf_mutex; /* Buffer alloc lock */
unsigned char *xmit_buf; /* Optional buffer */
unsigned int close_delay; /* Close port delay */
unsigned int closing_wait; /* Delay for output */
int drain_delay; /* Set to zero if no pure time
based drain is needed else
set to size of fifo */
struct kref kref; /* Ref counter */
void *client_data;
};
和 TTY 相关的所有状态在 TTY 打开期间会一直有效; termios 在 tty 关闭后也保留 —— 比如波特率。这些信息都保存在 tty_struct 。
struct tty_struct {
int magic;
struct kref kref;
struct device *dev;
// 对应的 tty_driver
struct tty_driver *driver;
// static const struct tty_operations uart_ops;
const struct tty_operations *ops;
int index;
/* Protects ldisc changes: Lock tty not pty */
struct ld_semaphore ldisc_sem;
struct tty_ldisc *ldisc;
struct mutex atomic_write_lock;
struct mutex legacy_mutex;
struct mutex throttle_mutex;
struct rw_semaphore termios_rwsem;
struct mutex winsize_mutex;
spinlock_t ctrl_lock;
spinlock_t flow_lock;
/* Termios values are protected by the termios rwsem */
struct ktermios termios, termios_locked;
struct termiox *termiox; /* May be NULL for unsupported */
char name[64];
struct pid *pgrp; /* Protected by ctrl lock */
struct pid *session;
unsigned long flags;
int count;
struct winsize winsize; /* winsize_mutex */
unsigned long stopped:1, /* flow_lock */
flow_stopped:1,
unused:BITS_PER_LONG - 2;
int hw_stopped;
unsigned long ctrl_status:8, /* ctrl_lock */
packet:1,
unused_ctrl:BITS_PER_LONG - 9;
unsigned int receive_room; /* Bytes free for queue */
int flow_change;
// 与当前 tty 相连的 tty_struct ,比如 pty 设备
struct tty_struct *link;
struct fasync_struct *fasync;
// 对端口执行写操作的等待队列
wait_queue_head_t write_wait;
// 对端口执行读操作的等待队列
wait_queue_head_t read_wait;
struct work_struct hangup_work;
// tty 设备使用的 line discipline 数据
void *disc_data;
void *driver_data;
spinlock_t files_lock; /* protects tty_files list */
struct list_head tty_files;
#define N_TTY_BUF_SIZE 4096
int closing;
unsigned char *write_buf;
int write_cnt;
/* If the tty has a pending do_SAK, queue it here - akpm */
struct work_struct SAK_work;
struct tty_port *port;
} __randomize_layout;
TTY 驱动由 tty_driver 描述。
struct tty_driver {
int magic; /* magic number for this structure */
struct kref kref; /* Reference management */
// 驱动绑定到的字符设备数组
struct cdev **cdevs;
struct module *owner;
const char *driver_name;
const char *name;
int name_base; /* offset of printed name */
int major; /* major device number */
int minor_start; /* start of minor device number */
// 分配的设备文件的数量
unsigned int num; /* number of devices allocated */
short type; /* type of tty driver */
short subtype; /* subtype of tty driver */
struct ktermios init_termios; /* Initial termios */
unsigned long flags; /* tty driver flags */
struct proc_dir_entry *proc_entry; /* /proc fs entry */
// pty 设备有两个 tty driver
struct tty_driver *other; /* only used for the PTY driver */
/*
* Pointer to the tty data structures
*/
// ttys , ports , termios 是每个字符设备的数据
struct tty_struct **ttys;
struct tty_port **ports;
struct ktermios **termios;
void *driver_state;
/*
* Driver methods
*/
// static const struct tty_operations uart_ops;
const struct tty_operations *ops;
// 用于插入到 tty_drivers 表
struct list_head tty_drivers;
} __randomize_layout;
8250 串口设备有专用的数据结构 uart_8250_port 。
struct uart_8250_port {
// 对应的 uart_port
struct uart_port port;
// 没有 irq 功能的设备通过计时器收发数据
struct timer_list timer; /* "no irq" timer */
struct list_head list; /* ports on this IRQ */
u32 capabilities; /* port capabilities */
unsigned short bugs; /* port bugs */
bool fifo_bug; /* min RX trigger if enabled */
unsigned int tx_loadsz; /* transmit fifo load size */
unsigned char acr;
unsigned char fcr;
unsigned char ier;
unsigned char lcr;
unsigned char mcr;
unsigned char mcr_mask; /* mask of user bits */
unsigned char mcr_force; /* mask of forced bits */
unsigned char cur_iotype; /* Running I/O type */
unsigned int rpm_tx_active;
unsigned char canary; /* non-zero during system sleep
* if no_console_suspend
*/
unsigned char probe;
#define UART_PROBE_RSA (1 << 0)
/*
* Some bits in registers are cleared on a read, so they must
* be saved whenever the register is read but the bits will not
* be immediately processed.
*/
#define LSR_SAVE_FLAGS UART_LSR_BRK_ERROR_BITS
unsigned char lsr_saved_flags;
#define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA
unsigned char msr_saved_flags;
// dma 模式下的 dma 信息
struct uart_8250_dma *dma;
//static const struct uart_8250_ops univ8250_driver_ops;
const struct uart_8250_ops *ops;
/* 8250 specific callbacks */
int (*dl_read)(struct uart_8250_port *);
void (*dl_write)(struct uart_8250_port *, int);
struct uart_8250_em485 *em485;
};
通用的串口设备通过 uart_port 表示。
struct uart_port {
spinlock_t lock; /* port lock */
unsigned long iobase; /* in/out[bwl] */
unsigned char __iomem *membase; /* read/write[bwl] */
unsigned int irq; /* irq number */
unsigned long irqflags; /* irq flags */
unsigned int uartclk; /* base uart clock */
unsigned int fifosize; /* tx fifo size */
unsigned char x_char; /* xon/xoff char */
unsigned char regshift; /* reg offset shift */
unsigned char iotype; /* io access style */
struct uart_state *state; /* pointer to parent state */
// uart 设备收到数据的统计信息
struct uart_icount icount; /* statistics */
// uart 设备绑定到的 console
struct console *cons; /* struct console, if any */
/* flags must be updated while holding port mutex */
upf_t flags;
unsigned int type; /* port type */
// static const struct uart_ops serial8250_pops;
const struct uart_ops *ops;
unsigned int custom_divisor;
unsigned int line; /* port index */
unsigned int minor;
resource_size_t mapbase; /* for ioremap */
resource_size_t mapsize;
struct device *dev; /* parent device */
const char *name; /* port name */
void *private_data; /* generic platform data pointer */
}
每个 uart 设备都会绑定到一个 uart_driver 。
struct uart_driver {
struct module *owner;
const char *driver_name;
const char *dev_name;
int major;
int minor;
int nr;
struct console *cons;
/*
* these are private; the low level driver should not
* touch these; they should be initialised to NULL
*/
struct uart_state *state;
struct tty_driver *tty_driver;
};
每个 uart 设备打开后,会有状态信息与之绑定,在设备打开的阶段一直有效,通过 uart_state 描述。
struct uart_state {
struct tty_port port;
enum uart_pm_state pm_state;
// uart 设备的发送缓冲区
struct circ_buf xmit;
atomic_t refcount;
wait_queue_head_t remove_wait;
struct uart_port *uart_port;
};
作者:glob
出处:http://www.cnblogs.com/adera/
欢迎访问我的个人博客:https://blog.globs.site/
本文版权归作者和博客园共有,转载请注明出处。