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		(*serial_in)(struct uart_port *, int);
	void			(*serial_out)(struct uart_port *, int, int);
	void			(*set_termios)(struct uart_port *,
				               struct ktermios *new,
				               struct ktermios *old);
	void			(*set_ldisc)(struct uart_port *,
					     struct ktermios *);
	unsigned int		(*get_mctrl)(struct uart_port *);
	void			(*set_mctrl)(struct uart_port *, unsigned int);
	unsigned int		(*get_divisor)(struct uart_port *,
					       unsigned int baud,
					       unsigned int *frac);
	void			(*set_divisor)(struct uart_port *,
					       unsigned int baud,
					       unsigned int quot,
					       unsigned int quot_frac);
	int			(*startup)(struct uart_port *port);
	void			(*shutdown)(struct uart_port *port);
	void			(*throttle)(struct uart_port *port);
	void			(*unthrottle)(struct uart_port *port);
	int			(*handle_irq)(struct uart_port *);
	void			(*pm)(struct uart_port *, unsigned int state,
				      unsigned int old);
	void			(*handle_break)(struct uart_port *);
	int			(*rs485_config)(struct uart_port *,
						struct serial_rs485 *rs485);
	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 */
	unsigned char		quirks;			/* internal quirks */

#define UPIO_PORT		(SERIAL_IO_PORT)	/* 8b I/O port access */
#define UPIO_HUB6		(SERIAL_IO_HUB6)	/* Hub6 ISA card */
#define UPIO_MEM		(SERIAL_IO_MEM)		/* driver-specific */
#define UPIO_MEM32		(SERIAL_IO_MEM32)	/* 32b little endian */
#define UPIO_AU			(SERIAL_IO_AU)		/* Au1x00 and RT288x type IO */
#define UPIO_TSI		(SERIAL_IO_TSI)		/* Tsi108/109 type IO */
#define UPIO_MEM32BE		(SERIAL_IO_MEM32BE)	/* 32b big endian */
#define UPIO_MEM16		(SERIAL_IO_MEM16)	/* 16b little endian */

	/* quirks must be updated while holding port mutex */
#define UPQ_NO_TXEN_TEST	BIT(0)

	unsigned int		read_status_mask;	/* driver specific */
	unsigned int		ignore_status_mask;	/* driver specific */
	struct uart_state	*state;			/* pointer to parent state */
	struct uart_icount	icount;			/* statistics */

	struct console		*cons;			/* struct console, if any */
#if defined(CONFIG_SERIAL_CORE_CONSOLE) || defined(SUPPORT_SYSRQ)
	unsigned long		sysrq;			/* sysrq timeout */
	unsigned int		sysrq_ch;		/* char for sysrq */
#endif

	/* flags must be updated while holding port mutex */
	upf_t			flags;

	/*
	 * These flags must be equivalent to the flags defined in
	 * include/uapi/linux/tty_flags.h which are the userspace definitions
	 * assigned from the serial_struct flags in uart_set_info()
	 * [for bit definitions in the UPF_CHANGE_MASK]
	 *
	 * Bits [0..UPF_LAST_USER] are userspace defined/visible/changeable
	 * The remaining bits are serial-core specific and not modifiable by
	 * userspace.
	 */
#define UPF_FOURPORT		((__force upf_t) ASYNC_FOURPORT       /* 1  */ )
#define UPF_SAK			((__force upf_t) ASYNC_SAK            /* 2  */ )
#define UPF_SPD_HI		((__force upf_t) ASYNC_SPD_HI         /* 4  */ )
#define UPF_SPD_VHI		((__force upf_t) ASYNC_SPD_VHI        /* 5  */ )
#define UPF_SPD_CUST		((__force upf_t) ASYNC_SPD_CUST   /* 0x0030 */ )
#define UPF_SPD_WARP		((__force upf_t) ASYNC_SPD_WARP   /* 0x1010 */ )
#define UPF_SPD_MASK		((__force upf_t) ASYNC_SPD_MASK   /* 0x1030 */ )
#define UPF_SKIP_TEST		((__force upf_t) ASYNC_SKIP_TEST      /* 6  */ )
#define UPF_AUTO_IRQ		((__force upf_t) ASYNC_AUTO_IRQ       /* 7  */ )
#define UPF_HARDPPS_CD		((__force upf_t) ASYNC_HARDPPS_CD     /* 11 */ )
#define UPF_SPD_SHI		((__force upf_t) ASYNC_SPD_SHI        /* 12 */ )
#define UPF_LOW_LATENCY		((__force upf_t) ASYNC_LOW_LATENCY    /* 13 */ )
#define UPF_BUGGY_UART		((__force upf_t) ASYNC_BUGGY_UART     /* 14 */ )
#define UPF_MAGIC_MULTIPLIER	((__force upf_t) ASYNC_MAGIC_MULTIPLIER /* 16 */ )

#define UPF_NO_THRE_TEST	((__force upf_t) (1 << 19))
/* Port has hardware-assisted h/w flow control */
#define UPF_AUTO_CTS		((__force upf_t) (1 << 20))
#define UPF_AUTO_RTS		((__force upf_t) (1 << 21))
#define UPF_HARD_FLOW		((__force upf_t) (UPF_AUTO_CTS | UPF_AUTO_RTS))
/* Port has hardware-assisted s/w flow control */
#define UPF_SOFT_FLOW		((__force upf_t) (1 << 22))
#define UPF_CONS_FLOW		((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ		((__force upf_t) (1 << 24))
#define UPF_EXAR_EFR		((__force upf_t) (1 << 25))
#define UPF_BUG_THRE		((__force upf_t) (1 << 26))
/* The exact UART type is known and should not be probed.  */
#define UPF_FIXED_TYPE		((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF	((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT		((__force upf_t) (1 << 29))
#define UPF_DEAD		((__force upf_t) (1 << 30))
#define UPF_IOREMAP		((__force upf_t) (1 << 31))

#define __UPF_CHANGE_MASK	0x17fff
#define UPF_CHANGE_MASK		((__force upf_t) __UPF_CHANGE_MASK)
#define UPF_USR_MASK		((__force upf_t) (UPF_SPD_MASK|UPF_LOW_LATENCY))

#if __UPF_CHANGE_MASK > ASYNC_FLAGS
#error Change mask not equivalent to userspace-visible bit defines
#endif

	/*
	 * Must hold termios_rwsem, port mutex and port lock to change;
	 * can hold any one lock to read.
	 */
	upstat_t		status;

#define UPSTAT_CTS_ENABLE	((__force upstat_t) (1 << 0))
#define UPSTAT_DCD_ENABLE	((__force upstat_t) (1 << 1))
#define UPSTAT_AUTORTS		((__force upstat_t) (1 << 2))
#define UPSTAT_AUTOCTS		((__force upstat_t) (1 << 3))
#define UPSTAT_AUTOXOFF		((__force upstat_t) (1 << 4))
#define UPSTAT_SYNC_FIFO	((__force upstat_t) (1 << 5))

	int			hw_stopped;		/* sw-assisted CTS flow state */
	unsigned int		mctrl;			/* current modem ctrl settings */
	unsigned int		timeout;		/* character-based timeout */
	unsigned int		type;			/* port type */
	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 */
	unsigned char		hub6;			/* this should be in the 8250 driver */
	unsigned char		suspended;
	unsigned char		unused[2];
	const char		*name;			/* port name */
	struct attribute_group	*attr_group;		/* port specific attributes */
	const struct attribute_group **tty_groups;	/* all attributes (serial core use only) */
	struct serial_rs485     rs485;
	void			*private_data;		/* generic platform data pointer */
}

在 Linux 内核中,struct uart_port 是 UART(Universal Asynchronous Receiver/Transmitter,通用异步收发器)驱动的核心数据结构,用于表示一个 UART 端口的硬件和软件状态。以下是其常见成员变量及其用途的解析:


核心成员变量

  1. iobase (I/O 基地址)

    • 用途‌:表示 UART 端口的 I/O 地址(物理地址或虚拟地址),用于通过 inb/outb 等函数直接访问寄存器。
    • 示例‌:在 x86 平台,可能是 0x3F8(COM1 的默认地址)。
  2. membase (内存映射基地址)

    • 用途‌:如果 UART 寄存器通过内存映射访问(MMIO),此成员保存映射后的虚拟地址。
    • 示例‌:在嵌入式 SoC 中,可能通过 ioremap() 映射物理地址到 membase
  3. mapbase (物理地址基址)

    • 用途‌:UART 寄存器的物理基地址,用于内存映射或资源申请。
    • 示例‌:mapbase = 0xFE201000(某 ARM SoC 的 UART 物理地址)。
  4. irq (中断号)

    • 用途‌:UART 使用的中断号,用于注册中断处理函数。
    • 示例‌:irq = 5(某些平台的 COM2 中断号)。
  5. fifosize (FIFO 大小)

    • 用途‌:UART 硬件 FIFO 的深度,驱动根据此值优化数据传输。
    • 示例‌:fifosize = 16 表示 16 字节的发送/接收 FIFO。
  6. uartclk (UART 主时钟频率)

    • 用途‌:UART 的基准时钟频率(Hz),用于计算波特率分频系数。
    • 示例‌:uartclk = 24000000(24MHz 时钟)。

操作函数集 (ops)

  1. const struct uart_ops *ops
    • 用途‌:指向 UART 操作函数集的指针,定义了驱动与硬件交互的具体方法,例如:
      • startup():初始化 UART 硬件。
      • shutdown():关闭 UART 硬件。
      • set_mctrl():设置调制解调器控制线(如 RTS、DTR)。
      • get_mctrl():读取调制解调器状态线(如 CTS、DSR)。
      • set_termios():配置波特率、数据位、停止位等参数。
      • start_tx():启动数据传输。
      • stop_rx():停止接收数据。
      • serial_in()读写硬件寄存器的核心函数,抽象不同硬件的访问方式
      • get_divisor)()计算或设置波特率分频器
      • throttle)()流量控制:暂停/恢复数据接收
      • handle_irq()中断处理函数入口(如处理接收或发送中断)
    • 关键性‌:驱动开发者必须实现这些函数以适配具体硬件。

状态与配置

  1. flags (标志位)

    • 用途‌:描述 UART 端口的特性或状态,例如:
      • UPF_FIXED_TYPE:固定端口类型。
      • UPF_SKIP_TEST:跳过自检。
      • UPF_HARD_FLOW:支持硬件流控(RTS/CTS)。
    • 示例‌:port->flags = UPF_BOOT_AUTOCONF | UPF_HARD_FLOW;
  2. type (端口类型)

    • 用途‌:标识 UART 硬件类型(如 PORT_16550APORT_XSCALE),与驱动匹配。
    • 示例‌:type = PORT_16550A;
  3. icount (中断计数器)

    • 用途‌:统计接收/发送中断次数、帧错误等,用于调试和状态监控。
    • 成员‌:
      struct {
          unsigned int rx;
          unsigned int tx;
          unsigned int frame;
          unsigned int parity;
          // ...
      } icount;
      

  4. state (端口状态)

    • 用途‌:指向 struct uart_state,包含与 TTY 子系统相关的状态(如缓冲区和信号处理)。

其他重要成员

  1. dev (关联的设备)

    • 用途‌:指向关联的 struct device,用于设备模型、电源管理和 sysfs 接口。
    • 示例‌:port->dev = &pdev->dev;(与 Platform Device 绑定)。
  2. private_data (私有数据)

    • 用途‌:驱动私有数据指针,可用于存储硬件特定配置或上下文。
    • 示例‌:存储 DMA 通道或自定义结构体。
  3. line (串口线路号)

    • 用途‌:UART 的索引号(如 ttyS0、ttyS1),由内核分配。
    • 示例‌:line = 0 对应 /dev/ttyS0

高级功能相关

  1. pm (电源管理)

    • 用途‌:电源管理操作(如休眠、唤醒),需实现 uart_pm_ops 中的方法。
  2. handle_break (Break 条件处理)

    • 用途‌:自定义处理 BREAK 信号的函数指针(可选)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

打个工而已

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值