union xhci_trb *trbs;
/* private to HCD */
struct xhci_segment *next;
dma_addr_t dma;
/* Max packet sized bounce buffer for td-fragmant alignment */
dma_addr_t bounce_dma;
void *bounce_buf;
unsigned int bounce_offs;
unsigned int bounce_len;
};
第一个相关的数据结构,segment
1. union xhci_trb *trbs;
一个segment一般由多个trb构成,由于xhci定义了许多种trb,所以,linux driver定义了一个union
union xhci_trb *trbs; 即指向一段内存,该内存是连续的多个trb数据结构
2. struct xhci_segment *next;
硬件上,多个segment是通过link trb来串起来的
而软件上,则通过定义一个segment类型的指针来串起多个seg
3. dma_addr_t dma;
该段trbs的首总线地址,硬件通过该地址来取trbs
4. void *bounce_buf;
unsigned int bounce_offs;
unsigned int bounce_len;
这三个成员,是Linux driver最近针对XHCI SPEC 4.11.7.1 TD Fragments 加入的,本人还没有仔细研究,研究完了,再加到评论当中。
struct xhci_td {
struct list_head td_list;
struct list_head cancelled_td_list;
struct urb *urb;
struct xhci_segment *start_seg;
union xhci_trb *first_trb;
union xhci_trb *last_trb;
struct xhci_segment *bounce_seg;
/* actual_length of the URB has already been set */
bool urb_length_set;
};
1. struct list_head td_list;
硬件上,一个TD(transfer descriptor)是由CH bit来实现的,即一个TD中的所有TRB,除了最后一个的CH BIT置1,最后一个为0, 这样,RING当中的TD与TD之间,就分隔开了。
软件上则是通过list_head的形式来管理,TD。
2. struct list_head cancelled_td_list;
取消掉的TD LIST。
3. struct urb *urb;
URB USB REQUEST BLOCK
URB是比较上层的数据结构,最终,是被XHCI DRIVER分解为TRB的.
4. struct xhci_segment *start_seg;
一个TD中,对应的第一个SEGMENT。
5. union xhci_trb *first_trb;
union xhci_trb *last_trb;
一个起始TRB与一个结束TRB,他们及他们之间的TRB,构成了一个TD。
6. struct xhci_segment *bounce_seg;
没有研究,猜测与XHCI SPEC 4.11.7.1 TD Fragments,最近更新。
7. bool urb_length_set;
一个布尔变量,用来判断,URB中的actual transfer length是否已经被设置过了。
struct xhci_ring {
struct xhci_segment *first_seg;
struct xhci_segment *last_seg;
union xhci_trb *enqueue;
struct xhci_segment *enq_seg;
unsigned int enq_updates;
union xhci_trb *dequeue;
struct xhci_segment *deq_seg;
unsigned int deq_updates;
struct list_head td_list;
/*
* Write the cycle state into the TRB cycle field to give ownership of
* the TRB to the host controller (if we are the producer), or to check
* if we own the TRB (if we are the consumer). See section 4.9.1.
*/
u32 cycle_state;
unsigned int stream_id;
unsigned int num_segs;
unsigned int num_trbs_free;
unsigned int num_trbs_free_temp;
unsigned int bounce_buf_len;
enum xhci_ring_type type;
bool last_td_was_short;
struct radix_tree_root *trb_address_map;
};
RING由SEGMENT构成。
1. struct xhci_segment *first_seg;
struct xhci_segment *last_seg;
第一个与最后一个SEGMENT
2. union xhci_trb *enqueue;
struct xhci_segment *enq_seg;
unsigned int enq_updates;
union xhci_trb *dequeue;
struct xhci_segment *deq_seg;
unsigned int deq_updates;
针对RING当中的TRB,有生产与消费的关系。
生产者(SW)通过enqueue ptr来指定放入TRB的位置,消费者(HW)通过dequeue ptr来指定取得TRB的位置
3. struct list_head td_list;
一个RING当中,可能会存在多个TD
4. u32 cycle_state;
TRB中有一个CYCLE BIT, 生产者与消费者统一,这样,消费者就可以判断,当前dequeue ptr指向的TRB是有效需要执行的,还是不需要执行的无效TRB。
5. unsigned int stream_id;
与BULK STREAMING相关, 一个STREAM ID对应BULK EP的一个STREAMING。
6. unsigned int num_segs;
unsigned int num_trbs_free;
unsigned int num_trbs_free_temp;
seg, trb的统计数据
7. unsigned int bounce_buf_len;
可能还是与XHCI SPEC 4.11.7.1 TD Fragments ,最近更新
8. enum xhci_ring_type type;
枚举变量,为CMD, EVENT, TRANSFER中的一种
9. bool last_td_was_short;
布尔变量,表示一个TD是否为短包结束
10. struct radix_tree_root *trb_address_map;
RADIX TREE,方便查找TRB。