上一篇说到了第一部分,这一篇说第二部分,如下这部分:
在模块初始化是调用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.28driversserial)文件中:
/**
* 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设备驱动(5)
下一篇:Linux下s3c6410的GPIO操作(4)
推荐阅读最新更新时间:2024-11-12 10:18
设计资源 培训 开发板 精华推荐
- IP6518C copy
- [LM358]DC恒流控制器
- LDK130PU15R 1.5V、300 mA 低静态电流极低噪声 LDO 的典型应用可调版本电路
- 具有载波检测和接收器故障保护功能的 LTC1482 低功耗 RS485 收发器的典型应用
- ov7670
- LTC1261LIS8 5V 输入、-0.5V 输出 GaAs FET 偏置发生器的典型应用电路
- AD8657ARMZ-RL比较器A典型应用电路
- ARIS 网关,适用于 Synergy S7 微控制器的 ARIS 开发板,是物联网 HUB 和网状网络 Wi-Fi 应用的理想选择
- AM1D-2415SH30-RZ 15V 1 瓦 DC/DC 转换器的典型应用
- JW5068A-同步整流降压模块