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;
};
posted @ 2020-08-07 11:17  glob  阅读(229)  评论(0编辑  收藏  举报