s3c6410的UART设备驱动(2)

来源:互联网 发布:剑三万花成男捏脸数据 编辑:程序博客网 时间:2024/06/08 19:13

转自:http://blog.csdn.net/tianxiawuzhei/article/details/7558451

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

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

1、先说uart_register_driver函数

这个函数在samsung.c 中被调用。

static int __init s3c24xx_serial_modinit(void)

{

int ret;
ret = uart_register_driver(&s3c24xx_uart_drv);//register uart_driver
if (ret < 0) {
printk(KERN_ERR "failed to register UART driver\n");
return -1;
}
return 0;

}

 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;
intmajor;
intminor;
intnr;
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);//硬件几个port,就开辟几个state
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;

}

0 0
原创粉丝点击