tty_driver-data_struct
阿新 • • 發佈:2020-08-07
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;
};