s3c6410的UART设备驱动(3)

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


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

在模块初始化是调用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)的链接地址


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值