第四十三篇:U-BOOT中,USB相关两个数据结构解说

不说没用的

直接上两个重要的数据结构:

第一个:

struct xhci_ctrl {
#ifdef CONFIG_DM_USB
struct udevice *dev;
#endif
struct xhci_hccr *hccr; /* R/O registers, not need for volatile */
struct xhci_hcor *hcor;
struct xhci_doorbell_array *dba;
struct xhci_run_regs *run_regs;
struct xhci_device_context_array *dcbaa \
__attribute__ ((aligned(ARCH_DMA_MINALIGN)));
struct xhci_ring *event_ring;
struct xhci_ring *cmd_ring;
struct xhci_ring *transfer_ring;
struct xhci_segment *seg;
struct xhci_intr_reg *ir_set;
struct xhci_erst erst;
struct xhci_erst_entry entry[ERST_NUM_SEGS];
struct xhci_virt_device *devs[MAX_HC_SLOTS];
int rootdev;
};


没有研究DM(driver model)的代码,而且,本人感觉,将LINUX中本来就不完善的DRIVER MODE搬到U-BOOT中,就是浪费自己与他人的时间与精力,把一件原本就需要简单,明了的事情,弄得复杂。

其实,除了rootdev这个成员,前面的这些成员,只要是熟悉XHCI的工程师,都应该非常快地知道代表了什么意思,

寄存器组,设备CONTEXT组,event, command rinng以及transfer ring.

ERST: event ring segment table

devs是该USB HOST下面的设备实例


rootdev是需要绕一绕才知道起什么作用的,看俺的前一篇吧。


第二个:


struct usb_device {
int devnum; /* Device number on USB bus */
int speed; /* full/low/high */
char mf[32]; /* manufacturer */
char prod[32]; /* product */
char serial[32]; /* serial number */


/* Maximum packet size; one of: PACKET_SIZE_* */
int maxpacketsize;
/* one bit for each endpoint ([0] = IN, [1] = OUT) */
unsigned int toggle[2];
/* endpoint halts; one bit per endpoint # & direction;
* [0] = IN, [1] = OUT
*/
unsigned int halted[2];
int epmaxpacketin[16]; /* INput endpoint specific maximums */
int epmaxpacketout[16]; /* OUTput endpoint specific maximums */


int configno; /* selected config number */
/* Device Descriptor */
struct usb_device_descriptor descriptor
__attribute__((aligned(ARCH_DMA_MINALIGN)));
struct usb_config config; /* config descriptor */


int have_langid; /* whether string_langid is valid yet */
int string_langid; /* language ID for strings */
int (*irq_handle)(struct usb_device *dev);
unsigned long irq_status;
int irq_act_len; /* transfered bytes */
void *privptr;
/*
* Child devices -  if this is a hub device
* Each instance needs its own set of data structures.
*/
unsigned long status;
unsigned long int_pending; /* 1 bit per ep, used by int_queue */
int act_len; /* transfered bytes */
int maxchild; /* Number of ports if hub */
int portnr; /* Port number, 1=first */
#ifndef CONFIG_DM_USB
/* parent hub, or NULL if this is the root hub */
struct usb_device *parent;
struct usb_device *children[USB_MAXCHILDREN];
void *controller; /* hardware controller private data */
#endif
/* slot_id - for xHCI enabled devices */
unsigned int slot_id;
#ifdef CONFIG_DM_USB
struct udevice *dev; /* Pointer to associated device */
struct udevice *controller_dev; /* Pointer to associated controller */
#endif
};


devnum其实,就是一组设备的编号,初始化的时候,从1到max

但是,为了将ROOT HUB也当作一个HUB来用,这里就得结合rootdev一起看代码,否则,保证让你看得云里雾里,也搞不清楚rootdev的作用。


usb_device这个数据结构基本贯穿了整个U-BOOT中USB子系统。

有一些成员,一看就知道,不多解释了。

主要解说几个影响代码执行流程的地方:

1. devnum见前文

2. struct usb_device *parent;上一级HUB的指针,ROOT HUB设置为NULL

3. struct usb_device *children[USB_MAXCHILDREN]; HUB下面的设备指针

4. controller, 指向struct xhci_ctrl 的实例

5. unsigned int slot_id;, 每个设备对应一个SLOT。

6. int maxchild; /* Number of ports if hub */, HUB所包含的DS PORT的个数
7. int portnr; /* Port number, 1=first */, 设备所连接接的HUB的DS PORT的编号, 即使是ROOT HUB,也有对应的PORT NUMBER


usb_hub_port_connect_change函数中有一段代码:

是在检测到HUB DS PORT下面有设备连上后,调用该函数。


其中,代码如下:

struct usb_device *usb; <--------------------------------------------------------------为检测到的新设备,准备一个数据结构实例


ret = usb_alloc_new_device(dev->controller, &usb);
if (ret) {
printf("cannot create new device: ret=%d", ret);
return ret;
}


dev->children[port] = usb; <--------------------------------------------------------------将HUB与USB DEV的上下游关系建立
usb->speed = speed;
usb->parent = dev;  <-------------------------------------------------------------- 建立HUB与USB DEV的上下游关系 
usb->portnr = port + 1;   <--------------------------------------------------------------设置该USB DEV对应的上游HUB的DS PORT NUMBER
/* Run it through the hoops (find a driver, etc) */
ret = usb_new_device(usb);
if (ret < 0) {
/* Woops, disable the port */
usb_free_device(dev->controller);
dev->children[port] = NULL;
}


大家可以发现,该代码的设备检测是深度优先。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值