📄 linux设备驱动之usb主机控制器驱动分析-(7)_linux技术文章_linux_操作系统7.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0072)http://www.diybl.com/course/6_system/linux/Linuxjs/2008923/144940_7.html -->
<HTML><HEAD><TITLE>linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统</TITLE>
<META http-equiv=Content-Type content=text/html;charset=gb2312>
<META content=www.diybl.com,DIY部落版权所有 name=Copyright>
<META content=linux设备驱动之USB主机控制器驱动分析_Linux技术文章_Linux_操作系统 name=keywords>
<META
content="linux设备驱动之USB主机控制器驱动分析_Linux技术文章_将用到skelqh[0]和skelqh[1]的地方.用间隔1ms的skelqh[9]代替.经过这个函数这后,uhci->frame[]中的各个QH都按照.."
name=description>
<META content=index,follow name=robots>
<META content=INDEX,FOLLOW name=GOOGLEBOT><LINK href="article2.css"
type=text/css rel=stylesheet><LINK
href="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/article2.css"
type=text/css rel=stylesheet>
<SCRIPT src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/article.js"
type=text/javascript></SCRIPT>
<SCRIPT src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/1060103.js"
type=text/javascript></SCRIPT>
<META content="MSHTML 6.00.2900.3395" name=GENERATOR></HEAD>
<BODY><INPUT type=hidden value=144940 name=passage_id><INPUT type=hidden
value=1060103 name=catalog_id>
<DIV id=wrap>
<DIV class=top_bar align=center>
<TABLE cellSpacing=0 width=935>
<TBODY>
<TR>
<TD><A href="http://www.diybl.com/">网站首页</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://news.diybl.com/" target=_blank>新闻首页</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/1_web/">网页设计</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/2_picdesign/">图形动画</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/3_program/">软件编程</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/4_webprogram/">网站开发</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/5_office/">办公软件</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/6_system/">操作系统</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/7_databases/">数据库</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/webjsh/">网络技术</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/comshiti/">认证考试</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/fwzl/">范文资料</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/course/hack/">黑客攻防</A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://www.diybl.com/chm/" target=_blank><FONT
color=red>书籍教程</FONT></A></TD>
<TD class=top_bar_sline></TD>
<TD><A href="http://bbs.diybl.com/"
target=_blank>进入论坛</A></TD></TR></TBODY></TABLE></DIV>
<TABLE class=adNone id=PublicRelation cellSpacing=0 cellPadding=0 width=950
border=0>
<TBODY>
<TR>
<TD vAlign=top width=864>
<DIV class=logo><A href="http://www.diybl.com/" target=_blank><IMG
height=60
src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/logo.gif"
width=200></A></DIV>
<DIV class=ad_f1 id=ad_f1>
<SCRIPT
src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/ad_f1.js"></SCRIPT>
</DIV><!--<div class="top_bar2">-->
<UL class=menu>
<LI><A href="http://www.diybl.com/course/6_system/linux/"
target=_blank><SPAN>Linux</SPAN></A>
<LI><A href="http://www.diybl.com/course/6_system/linux/Linuxxl/"
target=_blank><SPAN>Linux系列教程</SPAN></A>
<LI><A href="http://www.diybl.com/course/6_system/linux/linuxjq/"
target=_blank><SPAN>Linux应用技巧</SPAN></A>
<LI><A
href="http://www.diybl.com/course/6_system/linux/Linuxjs/7076ftksdtk.html"
target=_blank><SPAN>Linux技术文章</SPAN></A></LI></UL><!--</div>--></TD>
<TD width=6></TD>
<TD vAlign=top align=middle width=100>
<DIV class=hotNCout>
<DIV class=hotNC>
<UL>
<LI><A
href="javascript:window.external.addFavorite('http://www.diybl.com/','DIY部落');">加入收藏</A>
<LI><A href="http://www.diybl.com/map.html" target=_blank>网站地图</A>
<LI><A href="http://www.diybl.com/chm/" target=_blank>书籍教程</A>
<LI><A href="http://www.diybl.com/user/register.asp"
target=_blank>会员注册</A> </LI></UL></DIV></DIV></TD></TR></TBODY></TABLE>
<DIV class=split style="HEIGHT: 3px"></DIV>
<DIV class=ad_ftop id=ad_ftop>
<SCRIPT
src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/ad_ftop.js"></SCRIPT>
</DIV>
<DIV class=subNav>
<DIV style="FLOAT: right"><INPUT name=wd1> <INPUT onclick=tosearch(document.all.wd1); type=button value=" 千寻搜索 "></DIV><SPAN><A
href="http://www.diybl.com/">DIY部落</A> >> <A
href="http://www.diybl.com/course/6_system/">操作系统</A> >> <A
href="http://www.diybl.com/course/6_system/linux/">Linux</A> >> <A
href="http://www.diybl.com/course/6_system/linux/Linuxjs/7076ftksdtk.html">Linux技术文章</A>
>> 正文</SPAN></DIV>
<DIV class=split></DIV>
<DIV class=main>
<DIV class=lc_blue>
<DIV class=lcBlk>
<H1>linux设备驱动之USB主机控制器驱动分析</H1>
<DIV class=from_info>http://www.diybl.com/ 2008-9-23 网络 点击:<SPAN
style="FONT-WEIGHT: bold; COLOR: #ff0000">
<SCRIPT src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/p_count.htm"
lanuage="javascript"></SCRIPT>
</SPAN> <A
href="http://www.diybl.com/course/6_system/linux/Linuxjs/2008923/144940_7.html#comment">[
评论 ]</A></DIV>
<DIV class=artibody>
<DIV class=ad_f2 id=ad_f2>
<SCRIPT
src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/ad_f2.js"></SCRIPT>
</DIV>
<DIV class=ad_f3 id=ad_f3>
<SCRIPT
src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/ad_f3.js"></SCRIPT>
</DIV>文章搜索: <INPUT maxLength=255 size=30 name=wd2> <INPUT onclick=tosearch(document.all.wd2); type=button value=千寻搜索><A
class=redlink
href="javascript:self.location='/user/chm/rar.asp?c_id=48375'">【点击打包该文章】</A>
<SCRIPT
src="linux设备驱动之USB主机控制器驱动分析-(7)_Linux技术文章_Linux_操作系统7.files/art_top.js"></SCRIPT>
<P>将用到skelqh[0]和skelqh[1]的地方.用间隔1ms的skelqh[9]代替.<BR>经过这个函数这后,uhci->frame[]中的各个QH都按照对应的间隔存放到一起了.<BR> <BR>接着看下面的configure_hc()函数:<BR>static
void configure_hc(struct uhci_hcd *uhci)<BR>{<BR> /* Set
the frame length to the default: 1 ms exactly */<BR>
outb(USBSOF_DEFAULT, uhci->io_addr +
USBSOF);<BR> <BR> /* Store the frame list base
address */<BR>
//将frame指针地址写入基地址寄存器<BR> outl(uhci->frame_dma_handle,
uhci->io_addr + USBFLBASEADD);<BR> <BR> /* Set
the current frame number */<BR> //当前的frame
number<BR> outw(uhci->frame_number &
UHCI_MAX_SOF_NUMBER,<BR>
uhci->io_addr +
USBFRNUM);<BR> <BR> /* Mark controller as not
halted before we enable interrupts */<BR>
uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED;<BR>
mb();<BR> <BR> /* Enable PIRQ
*/<BR> pci_write_config_word(to_pci_dev(uhci_dev(uhci)),
USBLEGSUP,<BR>
USBLEGSUP_DEFAULT);<BR>}<BR>这个函数比较简单.首先将uhci->frame[
]的物理地址写到FRBASEADD寄存器中.再将起始帧号写入到FRNUM寄存器.再将状态置为HC_STATE_SUSPENDED.最后到USBLEGSUP中启用PIRQ.这样UHCI就可以产生中断了.<BR>到这里,UHCI已经初始化完成了.现在到了启用它的时候了.<BR> <BR>返回到uhci_start().流程转入到uhci_start().代码如下:<BR>static
void start_rh(struct uhci_hcd *uhci)<BR>{<BR>
//将UHCI的状态置为HC_STATE_RUNNING<BR>
uhci_to_hcd(uhci)->state = HC_STATE_RUNNING;<BR>
uhci->is_stopped = 0;<BR> <BR> /* Mark it
configured and running with a 64-byte max packet.<BR>
* All interrupts are enabled, even though RESUME won't do
anything.<BR> */<BR>
//启用UHCI,设置CF位,表示已经配置好了,指定最大的包长为64 byte<BR>
outw(USBCMD_RS | USBCMD_CF | USBCMD_MAXP, uhci->io_addr +
USBCMD);<BR>
//启用各种中断.包括传输超时或者CRC检验错误,RESUME状态中断.传输完成时产生中断<BR>
//短包中断<BR> outw(USBINTR_TIMEOUT | USBINTR_RESUME |
USBINTR_IOC |
USBINTR_SP,<BR>
uhci->io_addr + USBINTR);<BR>
mb();<BR>
//然后将UHCI的状态置为UHCI_RH_RUNNING状态.<BR> uhci->rh_state =
UHCI_RH_RUNNING;<BR> uhci_to_hcd(uhci)->poll_rh =
1;<BR>}<BR>对照代码中的注释和UHCI
spec,理解这段代码比较容易.在这里要特别提示一下,什么叫短包中断.<BR>在发送包的时候,如果一次不能够打包完.那就需要将包截短成小包.
一个个传输传输出去.另外,最后一个包可能传输数据会小于允许包大小的最大值.这个的包叫短包.我们在后面的中断处理函数中会有对于短包的处理.到时再详细分析它的处理.<BR>到这里.UHCI就开始调度了.不过这时候.整个调度系统中就只含有一个term_td.然而这个td的初始化如下(在uhci_start[
]函数中):<BR>uhci_fill_td(uhci->term_td, 0, uhci_explen(0)
|<BR>
(0x7f << TD_TOKEN_DEVADDR_SHIFT) | USB_PID_IN,
0);<BR>也就是它的status为空,也就是说,这个TD是一个INACTIVE的.实际这个UHCI是空负荷运行.<BR> <BR>运行到这里,hcd->start()运行完了.流程会返回到usb_add_hcd()到.的重要操作只剩余register_root_hub().probe过程也要接近尾声了.<BR> <BR>2.4:register_root_hub()的操作<BR>这个函数主要是对UHCI的root
hub进行处理.代码如下:<BR>static int register_root_hub(struct usb_hcd
*hcd)<BR>{<BR> struct device *parent_dev =
hcd->self.controller;<BR> struct usb_device *usb_dev
= hcd->self.root_hub;<BR> const int devnum =
1;<BR> int retval;<BR> <BR>
//root hub的devnum为1.下一个设备号从2开始.devnum也即设备地址<BR>
usb_dev->devnum = devnum;<BR>
usb_dev->bus->devnum_next = devnum +
1;<BR> <BR>
//usb_bus->devmap是一个位图.表示设备号的分配情况<BR> memset
(&usb_dev->bus->devmap.devicemap,
0,<BR>
sizeof usb_dev->bus->devmap.devicemap);<BR>
//将root hub占用位置1<BR> set_bit (devnum,
usb_dev->bus->devmap.devicemap);<BR>
//设置成Address 状态<BR> usb_set_device_state(usb_dev,
USB_STATE_ADDRESS);<BR> <BR>
mutex_lock(&usb_bus_list_lock);<BR> <BR>
//端点0的最大发送或者接收值<BR> usb_dev->ep0.desc.wMaxPacketSize
= __constant_cpu_to_le16(64);<BR> //取得root
hub的设备描述符<BR> retval =
usb_get_device_descriptor(usb_dev,
USB_DT_DEVICE_SIZE);<BR> if (retval != sizeof
usb_dev->descriptor) {<BR>
mutex_unlock(&usb_bus_list_lock);<BR>
dev_dbg (parent_dev, "can't read %s device descriptor
%d\n",<BR>
usb_dev->dev.bus_id,
retval);<BR> return (retval <
0) ? retval : -EMSGSIZE;<BR>
}<BR> <BR> //进一步初始化这个设备<BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -