s3c6410的UART设备驱动(2)

来源:互联网 发布:美团大数据 编辑:程序博客网 时间:2024/06/05 13:26

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)的链接