您的位置:首页 > 其它

s3c6410的UART设备驱动(2)

2012-05-17 15:50 309 查看
s3c6410的UART设备驱动(1)的链接地址

上一篇说到了第一部分,这一篇说第二部分,如下这部分:

在模块初始化是调用uart_register_driver和uart_add_port注册UART驱动并添加端口,在模块卸载时调用uart_unregister_driver和uart_remove_one_port以注销UART驱动并移除端口。

1、先说uart_register_driver函数,这个函数在

static int __init s3c24xx_serial_modinit(void) module_init(s3c24xx_serial_modinit);中被调用。

列出其源码,在Serial_core.c (linux2.6.28\drivers\serial)文件中:

/**

* uart_register_driver - register a driver with the uart core layer

* @drv: low level driver structure

*

* Register a uart driver with the core driver. We in turn register

* with the tty layer, and initialise the core driver per-port state.

*

* We have a proc file in /proc/tty/driver which is named after the

* normal driver.

*

* drv->port should be NULL, and the per-port structures should be

* registered using uart_add_one_port after this call has succeeded.

*/

这个函数进行驱动的注册,在其中包含了tty_register_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;

};

int uart_register_driver(struct uart_driver *drv)

{

struct tty_driver *normal = NULL;

int i, retval;

......

drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL);

retval = -ENOMEM;

if (!drv->state)

goto out;

这段可以看上面那段注释,在struct
uart_driver结构体中的注释。这里是申请内存的大小为sizeof(struct uart_state) * drv->nr,其中drv->nr是设备个数,因为可能有多个设备。

normal = alloc_tty_driver(drv->nr);

if (!normal)

goto out;

这个以前说过

drv->tty_driver = normal;

normal->owner
= drv->owner;

normal->driver_name= drv->driver_name;

normal->name
= drv->dev_name;

normal->major
= drv->major;

normal->minor_start= drv->minor;

normal->type
= TTY_DRIVER_TYPE_SERIAL;

normal->subtype= SERIAL_TYPE_NORMAL;

normal->init_termios= tty_std_termios;

normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;

normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;

normal->flags
= TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;

normal->driver_state = drv;注意这里,使struct tty_driver结构体和struct
uart_driver结构体联系起来了,在后面很重要,如 uart_open函数中。

tty_set_operations(normal, &uart_ops);在前面说过,把static const struct tty_operations uart_ops结构和struct
tty_driver结构绑定在一起,就不细说了。

这段对struct
tty_driver的normal结构体赋值,其实就是对struct uart_driver 中的成员struct
tty_driver*tty_driver赋值,因为都是指针。

/*

* Initialise the UART state(s).

*/

for (i = 0; i < drv->nr; i++) {

struct uart_state *state = drv->state + i;

state->close_delay = 500;/* .5 seconds */

state->closing_wait = 30000;/* 30 seconds */

mutex_init(&state->mutex);

}

retval = tty_register_driver(normal);这个函数在前面也说过,可以会前面查看。主要是关于终端设备顶层的设备注册。列出一个小片段:

cdev_init(&driver->cdev,
&tty_fops);

driver->cdev.owner = driver->owner;

error = cdev_add(&driver->cdev, dev, driver->num);

if (error) {

unregister_chrdev_region(dev, driver->num);

driver->ttys = NULL;

driver->termios = NULL;

kfree(p);

return error;

}

out:

if (retval < 0) {

put_tty_driver(normal);

kfree(drv->state);

}

return retval;

}

对应的uart_unregister_driver就比较简单了,做相反的事,就不说了,其内部调用了tty_unregister_driver(p)函数。

/**

* uart_unregister_driver - remove a driver from the uart core layer

* @drv: low level driver structure

*

* Remove all references to a driver from the core driver. The low

* level driver must have removed all its ports via the

* uart_remove_one_port() if it registered them with uart_add_one_port().

* (ie, drv->port == NULL)

*/

void uart_unregister_driver(struct uart_driver *drv)

{

struct tty_driver *p = drv->tty_driver;

tty_unregister_driver(p);

put_tty_driver(p);

kfree(drv->state);

drv->tty_driver = NULL;

}

s3c6410的UART设备驱动(3)的链接

s3c6410的UART设备驱动(4)的链接
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: