Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15498946
  • 博文数量: 2005
  • 博客积分: 11986
  • 博客等级: 上将
  • 技术积分: 22535
  • 用 户 组: 普通用户
  • 注册时间: 2007-05-17 13:56
文章分类

全部博文(2005)

文章存档

2014年(2)

2013年(2)

2012年(16)

2011年(66)

2010年(368)

2009年(743)

2008年(491)

2007年(317)

分类: LINUX

2009-07-01 09:49:53

uart_register_driver(&serial_pxa_reg);
tty_driver->fops = uart_ops; // 设置本tty_driver的方法集

tty_driver->driver_state = &serial_pxa_reg;
所以open将首先
cdev->ops = tty_fops;
tty_fops.open即tty_open==>从tty_drivers挂接的所有tty_driver中摘下管理该dev major和minor的tty_driver,这里就是
上面的tty_driver->fops = uart_ops;
同时
(tty->ldisc.open)(tty);
// ldisc线路规程就是initialize_tty_struct中由console_init==>tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);

// 初始化的tty_ldisc_N_TTY[luther.gliethttp]

filp->private_data = tty; // 这里tty->driver就是tty_driver

tty->driver->open(tty, filp);
所以流程为
tty_fops.tty_open==>tty_ldisc_N_TTY.n_tty_open
                 ==>tty_driver->fops->uart_open
之后filp->private_data = tty;

tty_fops==>tty_ldisc_N_TTY==>tty_driver->fops即uart_ops;==>tty->driver_data
即uart_state==>state->port->ops即在serial_pxa_probe()中创建的sport->port.ops = &serial_pxa_pops;
struct uart_ops serial_pxa_pops = {
    .tx_empty    = serial_pxa_tx_empty,
    .set_mctrl    = serial_pxa_set_mctrl,
    .get_mctrl    = serial_pxa_get_mctrl,
    .stop_tx    = serial_pxa_stop_tx,
    .start_tx    = serial_pxa_start_tx,
    .stop_rx    = serial_pxa_stop_rx,
    .enable_ms    = serial_pxa_enable_ms,
    .break_ctl    = serial_pxa_break_ctl,
    .startup    = serial_pxa_startup,
    .shutdown    = serial_pxa_shutdown,
    .set_termios    = serial_pxa_set_termios,
    .pm        = serial_pxa_pm,
    .type        = serial_pxa_type,
    .release_port    = serial_pxa_release_port,
    .request_port    = serial_pxa_request_port,
    .config_port    = serial_pxa_config_port,
    .verify_port    = serial_pxa_verify_port,
};


serial_pxa_probe
==>uart_add_one_port
==>uart_configure_port
==>register_console(port->cons); // 注册console,serial_pxa_reg的PXA_CONSOLE

void register_console(struct console *console)
{
    int i;
    unsigned long flags;
    struct console *bootconsole = NULL;

/*
serial_pxa_reg
==>
static struct console serial_pxa_console = {
    .name        = "ttyS",
    .write        = serial_pxa_console_write,
    .device        = uart_console_device,
    .setup        = serial_pxa_console_setup,
    .flags        = CON_PRINTBUFFER,
    .index        = -1,
    .data        = &serial_pxa_reg,
};
*/

    if (console_drivers) {
        if (console->flags & CON_BOOT)
            return;
        if (console_drivers->flags & CON_BOOT)
            bootconsole = console_drivers;
    }

    if (preferred_console < 0 || bootconsole || !console_drivers)
        preferred_console = selected_console;

    if (console->early_setup)
        console->early_setup();

    /*
     *    See if we want to use this console driver. If we
     *    didn't select a console we take the first one
     *    that registers here.
     */

    if (preferred_console < 0) {
        if (console->index < 0)
            console->index = 0;
        if (console->setup == NULL ||
         console->setup(console, NULL) == 0) { // 调用serial_pxa_console_setup

            console->flags |= CON_ENABLED | CON_CONSDEV;
            preferred_console = 0;
        }
    }

    /*
     *    See if this console matches one we selected on
     *    the command line.
     */

    for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];
            i++) {
        if (strcmp(console_cmdline[i].name, console->name) != 0)
            continue;
        if (console->index >= 0 &&
         console->index != console_cmdline[i].index)
            continue;
        if (console->index < 0)
            console->index = console_cmdline[i].index;
        if (console->setup &&
         console->setup(console, console_cmdline[i].options) != 0)
            break;
        console->flags |= CON_ENABLED;
        console->index = console_cmdline[i].index;
        if (i == selected_console) {
            console->flags |= CON_CONSDEV;
            preferred_console = selected_console;
        }
        break;serial_pxa_pops
    }

    if (!(console->flags & CON_ENABLED))
        return;

    if (bootconsole && (console->flags & CON_CONSDEV)) {
        printk(KERN_INFO "console handover: boot [%s%d] -> real [%s%d]\n",
         bootconsole->name, bootconsole->index,
         console->name, console->index);
        unregister_console(bootconsole);
        console->flags &= ~CON_PRINTBUFFER;
    } else {
        printk(KERN_INFO "console [%s%d] enabled\n",
         console->name, console->index);
    }

    /*
     *    Put this console in the list - keep theserial_pxa_pops
     *    preferred driver at the head of the list.
     */

    acquire_console_sem();
    if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
        // 将该console添加到console_drivers链表头[luther.gliethttp]

        console->next = console_drivers;
        console_drivers = console;
        if (console->next)
            console->next->flags &= ~CON_CONSDEV;
    } else {
        // 将console_drivers追加到它的后面

        console->next = console_drivers->next;
        console_drivers->next = console;
    }
    if (console->flags & CON_PRINTBUFFER) {
        /*
         * release_console_sem() will print out the buffered messages
         * for us.
         */

        spin_lock_irqsave(&logbuf_lock, flags);
        con_start = log_start;
        spin_unlock_irqrestore(&logbuf_lock, flags);
    }
#ifdef CONFIG_DEBUG_EARLY_PRINTK
    disable_early_printk = 1;
#endif
    release_console_sem(); // 向console_drivers链表上的挂接的所有console发送字符串log.

}

serial_pxa_init
==>uart_register_driver(&serial_pxa_reg);
==>platform_driver_register(&serial_pxa_driver);
然后
arch\arm\mach-pxa\generic.c
arch\arm\mach-pxa\generic.c
struct platform_device pxa_device_ffuart= {
    .name = "pxa2xx-uart",
    .id = 0,//对应的line号,所以这个串口在/dev下的名字为ttyS0

    .resource = pxa_resource_ffuart,
    .num_resources = ARRAY_SIZE(pxa_resource_ffuart),
};
struct platform_device pxa_device_btuart = {
    .name = "pxa2xx-uart",
    .id = 1,
    .resource = pxa_resource_btuart,
    .num_resources = ARRAY_SIZE(pxa_resource_btuart),
};
struct platform_device pxa_device_stuart = {
    .name = "pxa2xx-uart",
    .id = 2,
    .resource = pxa_resource_stuart,
    .num_resources = ARRAY_SIZE(pxa_resource_stuart),
};
以上三个在arch\arm\mach-pxa\pxa3xx.c=>pxa3xx_init=>
static struct platform_device *devices[] __initdata = {
    ...
    &pxa_device_ffuart,
    &pxa_device_btuart,
    &pxa_device_stuart,
    ...
};
platform_add_devices(devices, ARRAY_SIZE(devices));
//批量添加arch\arm\mach-pxa\generic.c下定义的platform_device设备

struct platform_device pxa_device_hwuart = {
    .name = "pxa2xx-uart",
    .id = 3,
    .resource = pxa_resource_hwuart,
    .num_resources = ARRAY_SIZE(pxa_resource_hwuart),
};
以上三个在arch\arm\mach-pxa\pxa3xx.c=>pxa3xx_init=>
static struct platform_device *devices[] __initdata = {
    ...
    &pxa_device_ffuart,
    &pxa_device_btuart,
    &pxa_device_stuart,
    ...
};
platform_add_devices(devices, ARRAY_SIZE(devices));

阅读(1803) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~