linux kernel X-tranx-Y : TTY to sdio


  今天我们来看看linux kernel driver中的glue:sdio_uart.c。
  顾名思义,这个文件把以TTY和sdio设备驱动贴合在一起,实现了TTY(一般为串口)到sdio设备的转

换,也就是TTY over sdio。该文件实现的功能框图如下:


      +-------------------+---------------------+
      |                        |                           |
      |                        | TTY device        |
      |                        |                           |
      | sdio_uart.c    +---------------------+
      |                       |                            |
      |                       | sdio device         | 
      |                       |                            |
      +------------------+---------------------+

  我们先来看一下sdio_uart_port这个结构:

 67 struct sdio_uart_port {
 68         struct tty_port         port;             //TTY port
 69         unsigned int            index;
 70         struct sdio_func        *func;            //sdio device
 71         struct mutex            func_lock;
 72         struct task_struct      *in_sdio_uart_irq;
 73         unsigned int            regs_offset;
 74         struct kfifo            xmit_fifo;
 75         spinlock_t              write_lock;
 76         struct uart_icount      icount;
 77         unsigned int            uartclk;
 78         unsigned int            mctrl;
 79         unsigned int            rx_mctrl;
 80         unsigned int            read_status_mask;
 81         unsigned int            ignore_status_mask;
 82         unsigned char           x_char;
 83         unsigned char           ier;
 84         unsigned char           lcr;
 85 };


  在这个结构中,我们可以看到两个很重要的成员:struct tty_port port;和 struct sdio_func     

  *func;由此可知,这个结构是TTY到sdio func的枢纽,它是胶水层的主要结构。
 
 
  我们简单来看看,这两个结构之间设备和对应的驱动序列chart:

 

    sdio_uart_init   
       +   
       | 
       +---> alloc_tty_driver  
       |
       | 
       ++--> tty_register_driver  
       |
       |  
       +---> sdio_register_driver

   可以看到,在init中,就是向tty core和sdio core分别注册了driver,驱动的名字都是

叫“sdio_uart”;接下去,就是在BUS(不是公交车)上等待另一半的到来了。。。。

   若有sdio func设备调用了:
302 /*
303  * Register a new SDIO function with the driver model.
304  */
305 int sdio_add_func(struct sdio_func *func)
306 {
307         int ret;
308
309         dev_set_name(&func->dev, "%s:%d", mmc_card_id(func->card), func->num);
310
311         ret = device_add(&func->dev);
312         if (ret == 0)
313                 sdio_func_set_present(func);
314
315         return ret;
316 }

   那么,sdio的driver中的probe将被调用

1069 static int sdio_uart_probe(struct sdio_func *func,
1070                            const struct sdio_device_id *id)
1071 {
1072         struct sdio_uart_port *port;
1073         int ret;
1074
             //媒人婆出现了
1075         port = kzalloc(sizeof(struct sdio_uart_port), GFP_KERNEL);
1076         if (!port)
1077                 return -ENOMEM;

      //一手拉住了sdio function
1123         port->func = func;
1124         sdio_set_drvdata(func, port);

             //一手拉住了tty port
1125         tty_port_init(&port->port);
1126         port->port.ops = &sdio_uart_port_ops;


1127
1128         ret = sdio_uart_add_port(port);
1129         if (ret) {
1130                 kfree(port);
1131         } else {
1132                 struct device *dev;
                    
                     //在这里增加了TTY device的注册
1133                 dev = tty_port_register_device(&port->port,
1134                                 sdio_uart_tty_driver, port->index, &func->dev);
1135                 if (IS_ERR(dev)) {
1136                         sdio_uart_port_remove(port);
1137                         ret = PTR_ERR(dev);
1138                 }
1139         }
1140
1141         return ret;
1142 }

   接下来,我们简单来看看,tty 调用后,如何转换为sdio操作的。

1048 static const struct tty_operations sdio_uart_ops = {
1049         .open                   = sdio_uart_open,
1050         .close                  = sdio_uart_close,
1051         .write                  = sdio_uart_write,
1052         .write_room             = sdio_uart_write_room,
1053         .chars_in_buffer        = sdio_uart_chars_in_buffer,
1054         .send_xchar             = sdio_uart_send_xchar,
1055         .throttle               = sdio_uart_throttle,
1056         .unthrottle             = sdio_uart_unthrottle,
1057         .set_termios            = sdio_uart_set_termios,
1058         .hangup                 = sdio_uart_hangup,
1059         .break_ctl              = sdio_uart_break_ctl,
1060         .tiocmget               = sdio_uart_tiocmget,
1061         .tiocmset               = sdio_uart_tiocmset,
1062         .install                = sdio_uart_install,
1063         .cleanup                = sdio_uart_cleanup,
1064         .proc_fops              = &sdio_uart_proc_fops,
1065 };

    sdio_uart_write         
       +   
       | 
       +---> sdio_uart_start_tx       
                 |  
                 |
                 ++--> sdio_out        
                         |
                         |
                         +---> sdio_writeb
                                   |
                                   |
                                   +---> mmc_io_rw_direct
                                              |
                                              |
                                              +---> mmc_io_rw_direct_host
                                                     |
                                                     |
                                                     +---> mmc_wait_for_cmd(host, &cmd, 0);
                                                           选择好host,封装好cmd,GO

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值