您的位置:首页 > 其它

s3c6410的UART设备驱动(3)

2012-05-17 16:43 316 查看


s3c6410的UART设备驱动(1)的链接地址


s3c6410的UART设备驱动(2)的链接地址







上一篇说到了第二部分,但没说完,这一篇接着说第二部分,如下这部分:

在模块初始化是调用uart_register_driver和uart_add_port注册UART驱动并添加端口,在模块卸载时调用uart_unregister_driver和uart_remove_one_port以注销UART驱动并移除端口。
1、先来看uart_add_one_port函数,源码如下:
/**

* uart_add_one_port - attach a driver-defined port structure

* @drv: pointer to the uart low level driver structure for this port

* @port: uart port structure to use for this port.

*

* This allows the driver to register its own uart_port structure

* with the core driver. The main purpose is to allow the low

* level uart drivers to expand uart_port, rather than having yet

* more levels of structures.

*/
这个函数在int s3c24xx_serial_probe(struct
platform_device *dev,

struct s3c24xx_uart_info *info)函数中被调用,和平台设备有关的函数。

int uart_add_one_port(struct uart_driver *drv, struct uart_port *port)

{

struct uart_state *state;

int ret = 0;

struct device *tty_dev;

........

if (port->line >= drv->nr)

return -EINVAL;

state = drv->state + port->line;

mutex_lock(&port_mutex);

mutex_lock(&state->mutex);

if (state->port) {

ret = -EINVAL;

goto out;

}

state->port = port;对state结构体中的成员port赋值,部分源码如下:
struct uart_state {

........

struct uart_info*info;

struct uart_port*port;

struct mutex
mutex;

};

state->pm_state = -1;

port->cons = drv->cons;

port->info = state->info;
info这个数据结构我们就不列出了,看下他的注释:
/*

* This is the state information which is only valid when the port

* is open; it may be freed by the core driver once the device has

* been closed. Either the low level driver or the core can modify

* stuff here.

*/

......

uart_configure_port(drv, state, port);看函数名就知道了干什么的。源码如下:先说下 struct uart_port *port结构体有什么用?在我看来,一个此种结构体的实例,就表示有一个串口可供我们使用。在列出在第一篇中列出的这个结构体的实例(其中的一部分),如下所示:
static
struct s3c24xx_uart_ports3c24xx_serial_ports[CONFIG_SERIAL_SAMSUNG_UARTS]
= {

[0] = {

.port = {

.lock = __SPIN_LOCK_UNLOCKED(s3c24xx_serial_ports[0].port.lock),

.iotype
= UPIO_MEM,

.irq = IRQ_S3CUART_RX0,

.uartclk
= 0,

.fifosize
= 16,

.ops = &s3c24xx_serial_ops,

.flags
= UPF_BOOT_AUTOCONF,

.line = 0,

}

}看这些都是什么?是不是和一个具体的串口很相关,如中断等等。

static void

uart_configure_port(struct uart_driver *drv, struct uart_state *state,

struct uart_port *port)

{

unsigned int flags;

/*

* If there isn't a port here, don't do anything further.

*/

if (!port->iobase && !port->mapbase && !port->membase)

return;

/*

* Now do the auto configuration stuff. Note that config_port

* is expected to claim the resources and map the port for us.

*/
有关的一些标志位,通过port->ops->config_port(port,
flags)这个函数进行。是在下面这个结构中的函数,和具体硬件有关。这个结构体在第一篇中,也有说明。
/*

* This structure describes all the operations that can be

* done on the physical hardware.

*/

struct uart_ops {

unsigned int
(*tx_empty)(struct uart_port *);

void (*set_mctrl)(struct uart_port *, unsigned int mctrl);

......

void (*set_ldisc)(struct uart_port *);

void (*pm)(struct uart_port *, unsigned int state,

unsigned int oldstate);

int (*set_wake)(struct uart_port *, unsigned int state);

.....

/*

* Request IO and memory resources used by the port.

* This includes iomapping the port if necessary.

*/

int (*request_port)(struct uart_port *);

void (*config_port)(struct uart_port *, int);

int (*verify_port)(struct uart_port *, struct serial_struct *);

........

};

};

flags = UART_CONFIG_TYPE;

if (port->flags & UPF_AUTO_IRQ)

flags |= UART_CONFIG_IRQ;

if (port->flags & UPF_BOOT_AUTOCONF) {

port->type = PORT_UNKNOWN;

port->ops->config_port(port, flags);

}

if (port->type != PORT_UNKNOWN) {

unsigned long flags;

......

/*Power up port for set_mctrl() */

uart_change_pm(state, 0);和电源管理有关

/*

*Ensure that the modem control lines are de-activated.

* keep the DTR setting that is set in uart_set_options()

* We probably don't need a spinlock around this, but

*/和流控制有关

spin_lock_irqsave(&port->lock, flags);

port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR);

spin_unlock_irqrestore(&port->lock, flags);

.........

}

}

/*

* Register the port whether it's detected or not. This allows

* setserial to be used to alter this ports parameters.

*/

tty_dev = tty_register_device(drv->tty_driver, port->line, port->dev);这个函数以前也说过,主要和sysfs文件系统有关。

.........

return ret;

}
对应的uart_remove_one_port函数就不讲了。源码如下:
/**

* uart_remove_one_port - detach a driver defined port structure

* @drv: pointer to the uart low level driver structure for this port

* @port: uart port structure for this port

*



int uart_remove_one_port(struct uart_driver *drv, struct uart_port *port)

{

......

/*

* Remove the devices from the tty layer

*/

tty_unregister_device(drv->tty_driver, port->line);

info = state->info;

if (info && info->port.tty)

tty_vhangup(info->port.tty);

/*

* All users of this port should now be disconnected from

* this driver, and the port shut down. We should be the

* only thread fiddling with this port from now on.

*/

state->info = NULL;

/*

* Free the port IO and memory resources, if any.

*/

if (port->type != PORT_UNKNOWN)

port->ops->release_port(port);

/*

* Indicate that there isn't a port here anymore.

*/

port->type = PORT_UNKNOWN;

/*

* Kill the tasklet, and free resources.

*/

.......

}
看这些注释,就可以明白个大概。


s3c6410的UART设备驱动(4)的链接地址

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