http://www.wowotech.net/tty_framework/435.
html struct cdev[tty_driver->num]
struct cdev
[email protected]
struct kobject kobj;
struct module * owner;
struct file_operations *ops;
struct uart_driver struct tty_driver struct list_head list;
struct tty_driver *tty_driver struct cdev ** cdevs; dev_t dev;
const char *driver_name; const char *driver_name; unsigned int count;
const char *dev_name; const char *name;
int major; int major; struct tty_struct[tty_driver->num]
uart_state[uart_driver->nr] struct tty_struct
int minor; int minor_start;
int nr; unsigned int num; struct device *dev
struct console *cons short type; struct tty_driver *driver
struct uart_state *state; short subtype; struct tty_operations *ops
…… unsigned long flags; int index tty_ldiscs[]
struct tty_struct **ttys struct tty_ldisc *ldisc
struct tty_port **ports char name[64]
tty_port[tty_driver->num] struct ktermios termios
struct ktermios **termios
struct uart_state void *driver_state; unsigned long flags
struct tty_port port; const struct tty_operations *ops; int count
struct circ_buf xmit; struct list_head tty_drivers; struct work_struct hangup_work;
struct tty_port
wait_queue_head_t remove_wait; …… struct fasync_struct *fasync
struct tty_bufhead buf;
struct uart_port *uart_port; wait_queue_head_t write_wait;
struct tty_struct * tty;
…… struct tty_port_operations *ops; wait_queue_head_t read_wait;
wait_queue_head_t open_wait; tty_port_link_device() void *driver_data;
发送缓冲区 unsigned long flags; void *disc_data;
struct circ_buf unsigned char *xmit_buf; struct list_head tty_files;
由uart_register_driver()设置
char * buf …… unsigned char *write_buf;
int head struct tty_port *port;
int tail ……
由uart_register_driver()设置 struct tty_operations uart_ops
uart_add_one_port() struct tty_operations
.open = uart_open
struct tty_port_operations uart_port_ops = { .close = uart_close struct ktermios {
.carrier_raised = uart_carrier_raised, struct ktermios[ ] tcflag_t c_iflag; /* input mode flags */
.dtr_rts = uart_dtr_rts, .write = uart_write tcflag_t c_oflag; /* output mode flags */
.activate = uart_port_activate, .start = uart_start tcflag_t c_cflag; /* control mode flags */
.shutdown = uart_tty_port_shutdown, .set_ldisc = uart_set_ldisc tcflag_t c_lflag; /* local mode flags */
struct tty_bufhead }; cc_t c_line; /* line discipline */
.ioctl = uart_ioctl cc_t c_cc[NCCS]; /* control characters */
struct tty_buffer *head;
…… speed_t c_ispeed; /* input speed */
struct work_struct work; struct uart_port speed_t c_ospeed; /* output speed */
struct tty_buffer *tail; unsigned long iobase; /* in/out[bwl] */ };
…… struct uart_ops cdns_uart_ops = {
char *membase; /* read/write[bwl] */ .set_mctrl= cdns_uart_set_mctrl,
unsigned int irq; .get_mctrl = cdns_uart_get_mctrl,
unsigned long irqflags; .start_tx = cdns_uart_start_tx,
unsigned int uartclk; /* base uart clock */ .stop_tx = cdns_uart_stop_tx, struct n_tty_data
.stop_rx = cdns_uart_stop_rx, size_t read_head;
unsigned int fifosize; .tx_empty= cdns_uart_tx_empty,
char iotype; /* io access style */ .break_ctl = cdns_uart_break_ctl, size_t canon_head;
struct tty_buffer struct tty_buffer struct tty_buffer NULL
struct console *cons; .set_termios = cdns_uart_set_termios, size_t read_tail;
struct tty_buffer *next; struct tty_buffer *next; struct tty_buffer *next; .startup = cdns_uart_startup,
unsigned int type; /* port type */ DECLARE_BITMAP(char_map, 256);
int used; int used; int used; .shutdown = cdns_uart_shutdown,
struct uart_ops *ops; .pm = cdns_uart_pm, char read_buf[N_TTY_BUF_SIZE];
int size; int size; int size;
unsigned int line; /* port index */ .type = cdns_uart_type, ……
int commit; int commit; int commit;
unsigned int minor; .verify_port = cdns_uart_verify_port,
int read; int read; int read; .request_port = cdns_uart_request_port,
unsigned long data[0]; unsigned long data[0]; unsigned long data[0]; resource_size_t mapbase; /* for ioremap */ .release_port = cdns_uart_release_port, read_buf[N_TTY_BUF_SIZE]
…… …… …… resource_size_t mapsize; .config_port = cdns_uart_config_port,
struct device *dev; /* parent device */ #ifdef CONFIG_CONSOLE_POLL
.poll_get_char = cdns_uart_poll_get_char,
struct attribute_group *attr_group; .poll_put_char = cdns_uart_poll_put_char,
/* port specific attributes */ #endif
对于tty_buffer来说,当底层驱动接收 struct attribute_group **tty_groups; };
到“一包”总线数据后,往tty_buffer /* all attributes (serial core use only) */
里写数据时,先使用data[used++]来保
存这包数据(tty_insert_flip_char()), void *private_data;
该包数据结束,调用 struct uart_state *state;
tty_flip_buffer_push(&port->state->port)
来上报数据,此时就用used指针来更新
……
commit指针,因此右图中commit指针 struct tty_buffer
为虚线;当往上层投递数据时,使用
read指针(char_buf_ptr(head, head-
>read))来投递数据。
SIZE SIZE
用于保存正常字符 用于保存接收当前字符的状态