Chinaunix首页 | 论坛 | 博客
  • 博客访问: 321997
  • 博文数量: 67
  • 博客积分: 668
  • 博客等级: 上士
  • 技术积分: 1591
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-16 22:08
文章分类

全部博文(67)

文章存档

2015年(1)

2014年(13)

2013年(28)

2012年(23)

2011年(2)

分类: LINUX

2013-06-03 14:44:52

在分析tty层时,tty_driver中有一个ttys成员保存每个设备的tty_struct列表,在uart层uart_driver和uart_state的关系也类似,如图

1.uart_driver的注册


  1. int uart_register_driver(struct uart_driver *drv)
  2. {
  3.     struct tty_driver *normal = NULL;
  4.     int i, retval;

  5.     BUG_ON(drv->state);

  6.     /*
  7.      * Maybe we should be using a slab cache for this, especially if
  8.      * we have a large number of ports to handle.
  9.      */
  10.     drv->state = kzalloc(sizeof(struct uart_state) * drv->nr, GFP_KERNEL); //根据设备数申请uart_stata
  11.     retval = -ENOMEM;
  12.     if (!drv->state)
  13.         goto out;

  14.     normal = alloc_tty_driver(drv->nr);        //分配tty_driver空间
  15.     if (!normal)
  16.         goto out;

  17.     drv->tty_driver = normal;    //将申请的tty_driver,关联给uart_driver中的tty_driver成员

  18.     //像tty驱动程序那样设置tty_driver的成员参数,从uart_driver中复制给tty_driver
  19.     normal->owner        = drv->owner;
  20.     normal->driver_name    = drv->driver_name;
  21.     normal->name        = drv->dev_name;
  22.     normal->major        = drv->major;
  23.     normal->minor_start    = drv->minor;
  24.     normal->type        = TTY_DRIVER_TYPE_SERIAL;
  25.     normal->subtype        = SERIAL_TYPE_NORMAL;
  26.     normal->init_termios    = tty_std_termios;
  27.     normal->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
  28.     normal->init_termios.c_ispeed = normal->init_termios.c_ospeed = 9600;
  29.     normal->flags        = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; //TTY_DRIVER_DYNAMIC_DEV标志使得不会再tty_register_driver时注册device
  30.     normal->driver_state = drv;
  31.     tty_set_operations(normal, &uart_ops); //tty的操作函数设置成uart_ops

  32.     /*
  33.      * Initialise the UART state(s). 初始化uart_state
  34.      */
  35.     for (i = 0; i < drv->nr; i++) {
  36.         struct uart_state *state = drv->state + i;
  37.         struct tty_port *port = &state->port;

  38.         tty_port_init(port); //初始化tty_port
  39.         port->close_delay = 500;    /* .5 seconds */
  40.         port->closing_wait = 30000;    /* 30 seconds */
  41.         tasklet_init(&state->tlet, uart_tasklet_action,
  42.              (unsigned long)state);
  43.     }

  44.     retval = tty_register_driver(normal); //注册tty_driver,最重要的环节
  45.  out:
  46.     if (retval < 0) {
  47.         put_tty_driver(normal);
  48.         kfree(drv->state);
  49.     }
  50.     return retval;
  51. }

2.添加一个串口信息uart_add_one_port函数


  1. int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
  2. {
  3.     struct uart_state *state;
  4.     struct tty_port *port;
  5.     int ret = 0;
  6.     struct device *tty_dev;

  7.     BUG_ON(in_interrupt());

  8.     if (uport->line >= drv->nr) //当然,uport的设备号,不能大于这个驱动中次设备数量
  9.         return -EINVAL;

  10.     state = drv->state + uport->line; //此uport对应的driver中的state
  11.     port = &state->port;    //对应state中的tty_port

  12.     mutex_lock(&port_mutex);
  13.     mutex_lock(&port->mutex);
  14.     if (state->uart_port) { //此state不能已经关联了uport
  15.         ret = -EINVAL;
  16.         goto out;
  17.     }

  18.     state->uart_port = uport; //将此uport关联给此state的uport指针
  19.     state->pm_state = -1;    //默认电源状态关闭

  20.     uport->cons = drv->cons; //驱动的控制台
  21.     uport->state = state;    //互联uport的state成员

  22.     /*
  23.      * If this port is a console, then the spinlock is already
  24.      * initialised. 是控制台,则自旋锁已经初始化过,无需初始化
  25.      */
  26.     if (!(uart_console(uport) && (uport->cons->flags & CON_ENABLED))) {
  27.         spin_lock_init(&uport->lock);
  28.         lockdep_set_class(&uport->lock, &port_lock_key);
  29.     }

  30.     uart_configure_port(drv, state, uport); //配置一下串口
  31.     

    点击(此处)折叠或打开

    1. static void
    2. uart_configure_port(struct uart_driver *drv, struct uart_state *state,
    3.          struct uart_port *port)
    4. {
    5.     unsigned int flags;

    6.     /*
    7.      * If there isn't a port here, don't do anything further.
    8.      */
    9.     if (!port->iobase && !port->mapbase && !port->membase) //必须有iobase,mapbase,membase
    10.         return;

    11.     /*
    12.      * Now do the auto configuration stuff. Note that config_port
    13.      * is expected to claim the resources and map the port for us.
    14.      */
    15.     flags = 0;
    16.     if (port->flags & UPF_AUTO_IRQ)
    17.         flags |= UART_CONFIG_IRQ;
    18.     if (port->flags & UPF_BOOT_AUTOCONF) {
    19.         if (!(port->flags & UPF_FIXED_TYPE)) {
    20.             port->type = PORT_UNKNOWN;
    21.             flags |= UART_CONFIG_TYPE;
    22.         }
    23.         port->ops->config_port(port, flags); //调用操作集中的config_port函数
    24.     }

    25.     if (port->type != PORT_UNKNOWN) {
    26.         unsigned long flags;

    27.         uart_report_port(drv, port); //打印一些串口的信息

    28.         /* Power up port for set_mctrl() */
    29.         uart_change_pm(state, 0); //调用ops中驱动的pm函数上电

    30.         /*
    31.          * Ensure that the modem control lines are de-activated.
    32.          * keep the DTR setting that is set in uart_set_options()
    33.          * We probably don't need a spinlock around this, but
    34.          */
    35.         spin_lock_irqsave(&port->lock, flags);
    36.         port->ops->set_mctrl(port, port->mctrl & TIOCM_DTR); //调用驱动的set_mctrl
    37.         spin_unlock_irqrestore(&port->lock, flags);

    38.         /*
    39.          * If this driver supports console, and it hasn't been
    40.          * successfully registered yet, try to re-register it.
    41.          * It may be that the port was not available.
    42.          */
    43.         if (port->cons && !(port->cons->flags & CON_ENABLED))
    44.             register_console(port->cons);    //如果是控制台 注册控制台

    45.         /*
    46.          * Power down all ports by default, except the
    47.          * console if we have one.
    48.          */
    49.         if (!uart_console(port))
    50.             uart_change_pm(state, 3); //不是控制台,Power down
    51.     }
    52. }

  32.     /*
  33.      * Register the port whether it's detected or not. This allows
  34.      * setserial to be used to alter this ports parameters.
  35.      */
  36.     tty_dev = tty_register_device(drv->tty_driver, uport->line, uport->dev); //产生一个device设备,若有udev则将产生设备节点
  37.     if (likely(!IS_ERR(tty_dev))) {
  38.         device_init_wakeup(tty_dev, 1);
  39.         device_set_wakeup_enable(tty_dev, 0);
  40.     } else
  41.         printk(KERN_ERR "Cannot register tty device on line %dn",
  42.          uport->line);

  43.     /*
  44.      * Ensure UPF_DEAD is not set.
  45.      */
  46.     uport->flags &= ~UPF_DEAD;

  47.  out:
  48.     mutex_unlock(&port->mutex);
  49.     mutex_unlock(&port_mutex);

  50.     return ret;
  51. }

3.uart函数操作集

uart_ops是uart层实现tty层提供的需要实现的操作,即实现一个tty_operations。

  1. static const struct tty_operations uart_ops = {
  2.     .open        = uart_open,
  3.     .close        = uart_close,
  4.     .write        = uart_write,
  5.     .put_char    = uart_put_char,
  6.     .flush_chars    = uart_flush_chars,
  7.     .write_room    = uart_write_room,
  8.     .chars_in_buffer= uart_chars_in_buffer,
  9.     .flush_buffer    = uart_flush_buffer,
  10.     .ioctl        = uart_ioctl,
  11.     .throttle    = uart_throttle,
  12.     .unthrottle    = uart_unthrottle,
  13.     .send_xchar    = uart_send_xchar,
  14.     .set_termios    = uart_set_termios,
  15.     .set_ldisc    = uart_set_ldisc,
  16.     .stop        = uart_stop,
  17.     .start        = uart_start,
  18.     .hangup        = uart_hangup,
  19.     .break_ctl    = uart_break_ctl,
  20.     .wait_until_sent= uart_wait_until_sent,
  21. #ifdef CONFIG_PROC_FS
  22.     .proc_fops    = &uart_proc_fops,
  23. #endif
  24.     .tiocmget    = uart_tiocmget,
  25.     .tiocmset    = uart_tiocmset,
  26. #ifdef CONFIG_CONSOLE_POLL
  27.     .poll_init    = uart_poll_init,
  28.     .poll_get_char    = uart_poll_get_char,
  29.     .poll_put_char    = uart_poll_put_char,
  30. #endif
  31. };
下一节我们将分析这其中的一些函数





阅读(849) | 评论(0) | 转发(0) |
0

上一篇:gcc内联汇编函数语法

下一篇:没有了

给主人留下些什么吧!~~