您的位置:首页 > 运维架构 > Linux

linux串口终端驱动——s3c6410平台(三)

2012-04-29 16:23 381 查看
接着上一篇linux串口终端驱动——s3c6410平台(二)继续分析

上一篇关注的是tty上层字符层面的操作和注册,这一篇主要关注线程的注册,如何与上层建筑联系起来。

一、 tty_ldisc.c提供了tty_register_ldisc()接口用于注册线路规程,例如/driver/char/n_tty.c文件则针对N_TTY线路规程实现了具体的tty_disc结构体中的成员。

tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY)

其中有

#define N_TTY 0

struct tty_ldisc_ops tty_ldisc_N_TTY = {

.magic = TTY_LDISC_MAGIC,

.name = "n_tty",

.open = n_tty_open,

.close = n_tty_close,

.flush_buffer = n_tty_flush_buffer,

.chars_in_buffer = n_tty_chars_in_buffer,

.read = n_tty_read,

.write = n_tty_write,

.ioctl = n_tty_ioctl,

.set_termios = n_tty_set_termios,

.poll = n_tty_poll,

.receive_buf = n_tty_receive_buf,

.write_wakeup = n_tty_write_wakeup

};


对应的原型为

struct tty_ldisc_ops {

int magic;

char *name;

int num;

int flags;

/*

* The following routines are called from above.

*/

int (*open)(struct tty_struct *);

void (*close)(struct tty_struct *);

void (*flush_buffer)(struct tty_struct *tty);

ssize_t
(*chars_in_buffer)(struct tty_struct *tty);

ssize_t
(*read)(struct tty_struct * tty, struct file * file,

unsigned char __user * buf, size_t nr);

ssize_t
(*write)(struct tty_struct * tty, struct file * file,

const unsigned char * buf, size_t nr);

int (*ioctl)(struct tty_struct * tty, struct file * file,

unsigned int cmd, unsigned long arg);

long (*compat_ioctl)(struct tty_struct * tty, struct file * file,

unsigned int cmd, unsigned long arg);

void (*set_termios)(struct tty_struct *tty, struct ktermios * old);

unsigned int (*poll)(struct tty_struct *, struct file *,

struct poll_table_struct *);

int (*hangup)(struct tty_struct *tty);

/*

* The following routines are called from below.

*/

void (*receive_buf)(struct tty_struct *, const unsigned char *cp,

char *fp, int count);


void(*write_wakeup)(struct
tty_struct *);

struct module *owner;

int refcount;

};

struct tty_ldisc {

struct tty_ldisc_ops *ops;

int refcount;

};



二、而tty_register_ldisc函数则把具体的struct tty_disc添加到线程安装表中的对应编号处,本例为0出,因为N_TTY为0。注:这里还没有和tty上层连接起来,只是添加到了线程规划表中。

源码如下:
/* Line disc dispatch table */

static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS];


所有安装线程表
/**

*tty_register_ldisc-install
a line discipline安装一个线程规划

*@disc: ldisc number ldisc的编号

*@new_ldisc: pointer to the ldisc object指向新安装的ldsic的操作函数

*

*Installs a new line discipline into the kernel. The discipline

*is set up as unreferenced and then made available to the kernel

*from this point onwards.

*

*Locking:加锁保护

*takes tty_ldisc_lock to guard against ldisc races

*/

int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)

对照tty_register_ldisc(N_TTY,
&tty_ldisc_N_TTY)和

static
struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS]即可看明

{

unsigned long flags;

int ret = 0;

if (disc < N_TTY || disc >= NR_LDISCS)判断编号是否符合

return -EINVAL;

spin_lock_irqsave(&tty_ldisc_lock, flags);

tty_ldiscs[disc] = new_ldisc;

new_ldisc->num = disc;

new_ldisc->refcount = 0;

spin_unlock_irqrestore(&tty_ldisc_lock, flags);

return ret;

}

EXPORT_SYMBOL(tty_register_ldisc);

三、当然有注册,就有注销,只不过不常用。
/**

* tty_unregister_ldisc-unload a line discipline

* @disc: ldisc number

* @new_ldisc: pointer to the ldisc object

*

* Remove a line discipline from the kernel providing it is not

* currently in use.

*

* Locking:

* takes tty_ldisc_lock to guard against ldisc races

*/

int tty_unregister_ldisc(int disc)

{

unsigned long flags;

int ret = 0;



if (disc < N_TTY || disc >= NR_LDISCS)

return -EINVAL;



spin_lock_irqsave(&tty_ldisc_lock, flags);

if (tty_ldiscs[disc]->refcount)

ret = -EBUSY;

else

tty_ldiscs[disc] = NULL;

spin_unlock_irqrestore(&tty_ldisc_lock, flags);

return ret;

}

EXPORT_SYMBOL(tty_unregister_ldisc);


四:和上层tty连接
每个终端设备都有个struct tty_struct结构体,可能被包含在一个更大的结构体中。
/*

* Where all of the state associated with a tty is kept while the tty

* is open. Since the termios state should be kept even if the tty

* has been closed --- for things like the baud rate, etc --- it is

* not stored here, but rather a pointer to the real state is stored

* here. Possible the winsize structure should have the same

* treatment, but (1) the default 80x24 is usually right and (2) it's

* most often used by a windowing system, which will set the correct

* size each time the window is created or resized anyway.

* - TYT, 9/14/92

*/

struct tty_operations;

struct tty_struct {

int
magic;

struct kref kref;

struct tty_driver *driver;

const struct tty_operations *ops;

int index;

/* The ldisc objects are protected by tty_ldisc_lock at the moment */

struct tty_ldisc ldisc; 与具体线程的关联在这

struct mutex termios_mutex;

spinlock_t ctrl_lock;

/* Termios values are protected by the termios mutex */

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;
/* termios mutex */

unsigned char stopped:1, hw_stopped:1, flow_stopped:1, packet:1;

unsigned char low_latency:1, warned:1;

unsigned char ctrl_status;
/* ctrl_lock */

unsigned int receive_room;
/* Bytes free for queue */

struct tty_struct *link;

struct fasync_struct *fasync;

struct tty_bufhead buf;
/* Locked internally */

int alt_speed;
/* For magic substitution of 38400 bps */

wait_queue_head_t write_wait;

wait_queue_head_t read_wait;

struct work_struct hangup_work;

void *disc_data;

void *driver_data;

struct list_head tty_files;

#define N_TTY_BUF_SIZE 4096

/*

* The following is data for the N_TTY line discipline. For

* historical reasons, this is included in the tty structure.

* Mostly locked by the BKL.

*/

unsigned int column;

unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;

unsigned char closing:1;

unsigned short minimum_to_wake;

unsigned long overrun_time;

int num_overrun;

unsigned long process_char_map[256/(8*sizeof(unsigned long))];

char *read_buf;

int read_head;

int read_tail;

int read_cnt;

unsigned long read_flags[N_TTY_BUF_SIZE/(8*sizeof(unsigned long))];

int canon_data;

unsigned long canon_head;

unsigned int canon_column;

struct mutex atomic_read_lock;

struct mutex atomic_write_lock;

unsigned char *write_buf;

int write_cnt;

spinlock_t read_lock;

/* If the tty has a pending do_SAK, queue it here - akpm */

struct work_struct SAK_work;

struct tty_port *port;

};


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: