三.HCD的初始化
There are a number of steps necessary for an OS to bring its Host Controller Driver to an operational state:
■Load Host Controller Driver and locate the Hc
■Verify the HC and allocate system resources
■Take control of HC(可以不要)
■Set up HC registers and HCCA
■Begin sending SOF tokens on the USB
前3步在hc_start中已经完成,第4步在将ED,TD相关寄存器填充好之后,可以
进行第五步。其中一些参数的配置,如帧频率设置为1ms,hc从suspend到resume时间至少2ms,中断使能SOF中断,hcPeriodicStart的值是90%*FrameInterval等。
ControlBulkServiceRatio
如果ControlBulkServiceRatio field被设置成4:1,则control ED和BULK ED在一帧
中发送的比例为4:1,同时,the host controller enforces the control Bulk Service Ratio regardless of the number of Control and Bulk Endpoint Descriptor present on their respective lists.If there is only 1 Control Endpoint Descriptor on the Control list and the control Bulk Ratio is 4:1,that control Endpoint Descriptor is serviced 4 times before a Bulk Ed is serviced.
List Enabled Check
If the list is enabled ,the host controller may service the list.If the list is disabled,the Host controller skips that list and moves on to the next list.而list的服务顺序可以通过OHCI文档得到.
四.OHCI的相关代码 对于OHCI而言,具体的到代码部分主要在函数submit_common_msg中,该函数由以下函数而最终调用
而usb_control_msg被大多的枚举过程相关函数所调用 具体的ROOT HUB的枚举过程在ohci_submit_rh_msg实现,与OHCI相关的在函 数submit_common_msg中。该函数主要调用两个函数,一个是sohci_submit_job,一个是hc_interrupt。 a) sohci_submit_job sohci_submit_job的调用情况如下图所示,
aa) ep_add_ed
该函数就是初始化一个ed_t *ed,该ed存放于对应的ohci_dev.ed[]中,数组对应下标由传输类型决定。若第一次使用4中类型的某一种ED,则对其初始化(包括创建dummy TD,链接dummy TD),否则只设置ed的hwINFO(就是第一个双字)
ab) td_alloc
分配TD,根据传输类型决定TD数,如BULK传输为2TD,control传输为3TD(SETUP,IN,OUT),将分配好的TD放置于结构purb_priv->td[]中
purb_priv=&urb_priv;
purb_priv->pipe=pipe;
purb_priv->length=size;
purb_priv->ed=ed;(ep_add_ed所返回的ed指针)
ac) ep_link(举PIPE_CONTROL为例)
如果ed->state不为ED_OPER则调用ep_link。此时ed->state为ED_UNLINK,将调用ed_link。该函数主要是将ED 链接到链中,状态设置为ED_OPER
对于PIPE_CONTROL,如果ohci->ed_controltail为空,则将上述的ed,写入ed_controlhead寄存器,作为ed_control的头ED,否则作为尾ED.使能OHCI_CTRL_CLE,重新定向ed_controltail尾指针
ad) td_submit_job(举PIPE_CONTROL为例)
对于control传输,至少有2个TD,第一个必然为setup包(对应长度为8),toggle=TD_T_DATA0,其余toggle=TD_T_DATA1,调用td_fill将这些TD连接到对应的ED中。这些TD可能是IN 或OUT 或者均有,由trans_len和pipe决定
同样第一个dword在代码中为hwINFO
根据第二部分的图,我们就能很好的编写td_fill函数,无非是链表的操作
最后,在该函数内如果OHCI没休眠,则
Writeln(OHCI_CLF,&ohci->regs->cmdstatus),start control list
(具体可以看cmdstatus寄存器)
b) hc_interrupt
等待传输结束,HCCA 相关中断
在函数hc_interrupt中主要处理三类中断,分别是writeback of done_head,start frame,overrun,对于后两者都是关闭中断后,重开中断(如果需要),而writeback of done_head则多添加了一个函数dl_done_list(&gohci,dl_reverse_done_list(&gohci))
由于TD是以一个FIFO基地址传输给don_head的,所以需要翻转td_list,这就是函数dl_reverse_done_list,而dl_done_list则是检查是否将所有的TD成功传输(依据传输的TD个数与接收的个数比较,如果一致则传输成功),最后调用ed_unlink将对应的ED从hptr上去除
五.总结
以上就是U-BOOT中的OHCI介绍,主要是对control传输有较详细的介绍,特别是ISO传输还不是特别了解,需要进一步学习。