linux ehci hcd之qh_urb_transaction()分析(二)

本文深入剖析Linux EHCI USB控制器驱动中的qh_urb_transaction()函数,详细解释了如何处理控制类传输的qtd填充、数据传输阶段的缓冲区设置,以及对 urb 的不同传输特性的处理。通过对 urb->num_mapped_sgs 的检查,决定是否使用分散/聚集 DMA 映射,并展示了如何构建和连接qtd列表以支持数据传输。
摘要由CSDN通过智能技术生成

接下来从qtd_fill()中返回到qh_urb_transaction(),再贴一下返回处的代码,如下

1. if (usb_pipecontrol (urb->pipe)) {

2.  /* SETUP pid */

3.  qtd_fill(ehci, qtd, urb->setup_dma,

4.  sizeof (struct usb_ctrlrequest),

5.  token | (2 /* "setup" */ << 8), 8);

 

6.  /* ... and always at least one more pid */

7.  token ^= QTD_TOGGLE;

8.  qtd_prev = qtd;

9.  qtd = ehci_qtd_alloc (ehci, flags);

10.  if (unlikely (!qtd))

11.  goto cleanup;

12.  qtd->urb = urb;

13.  qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma);

14.  list_add_tail (&qtd->qtd_list, head);

 

15.  /* for zero length DATA stages, STATUS is always IN */

16.  if (len == 0)

17.  token |= (1 /* "in" */ << 8);

18.  }

刚才假设了我们的urb属于控制类传输的参数类型,进入到了if语句中,并主要分析了qtd_fill()函数,知道它把由urb上数据传输相关的内存交换区的地址长度等信息写入到一个qtd中。

上述if语句中第6行到最后,在经过qtd_fill()填充过后的qtd就已经能用于实际的数据传输了,并用qtd_prev指针暂时维持对其的引用,接着在用ehci_qtd_alloc()分配新的qtd,刚才经填充的qtdhw_next中写入这个新分配的qtd的物理地址,并把新分配的qtd联入head队列中。接着if判断len的值,为零说明当前的urb仅用于Control的命令传输,而没有数据传输,反之urb中还有数据要传输。变量len的值来至urbtransfer_buffer_length,表示了数据传输交换区的长度。

结束了if判断语言的相关内容后,进入到“data transfer stage:  buffer setup”,即数据传输阶段,如下代码。

1. /*

2. data transfer stage:  buffer setup

3. */

4. i = urb->num_mapped_sgs;

5. if (len > 0 && i > 0) {

6. sg = urb->sg;

7. buf = sg_dma_address(sg);

 

8. /* urb->transfer_buffer_length may be smaller than the

9. size of the scatterlist (or vice versa)

10. */

11. this_sg_len = min_t(int, sg_dma_len(sg), len);

12. } else {

13. sg = NULL;

14. buf = urb->transfer_dma;

15. this_sg_len = len;

16. }

 

17. if (is_input)

18. token |= (1 /* "in" */ << 8);

19. /* else it&

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值