`
dato0123
  • 浏览: 913669 次
文章分类
社区版块
存档分类
最新评论

Linux那些事儿之我是Hub(19)八大重量级函数闪亮登场(三)

 
阅读更多

在开始第三个函数前,2492行至2494行还有三行代码,udev中的speed,bus_mA,level进行赋值.

先说一下,bus_mA,struct usb_device中的成员,unsigned short bus_mA,记录的是能够从总线上获得的电流,毫无疑问就是咱们前面算出来的hub上的那个mA_per_port.上头能给多少咱们就要多少.

再说level,级别,表征usb设备树的级连关系.Root Hub当然其level就是0,其下面一层就是level 1,再下面一层就是level 2,依此类推.

然后说speed,include/linux/usb/ch9.h中定义了这么一个枚举类型的变量:

548 /* USB 2.0 defines three speeds, here's how Linux identifies them */

549

550 enum usb_device_speed {

551 USB_SPEED_UNKNOWN = 0, /* enumerating */

552 USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */

553 USB_SPEED_HIGH, /* usb 2.0 */

554 USB_SPEED_VARIABLE, /* wireless (usb 2.5) */

555 };

很明显的含义,用来标志设备的速度.众所周知,USB设备有三种速度,低速,全速,高速.USB1.1那会儿只有低速,全速,后来才出现了高速,高速就是所谓的480Mbps/s,不过细心的你或许注意到这里还有一个USB_SPEED_VARIABLE.两千零五年那个五月,Intel等公司推出了Wireless USB spec 1.0,即所谓的无线USB技术,江湖上也把这个usb技术称为usb 2.5.无线技术的推出必然会让设备的速度不再稳定,当年这个标准推出的时候是号称在3米范围内,能够提供480Mbps的理论传输速度,而在10米范围左右出现递减,据说是10米内110Mbps/s.那时正值英特尔中国20周年,所以中国这边的员工每人发了一个无线USB鼠标.其实就是一个USB接头,接在电脑的usb端口上,而鼠标这边没有线,鼠标和接头之间的通信是无线的,使用传说中蓝牙技术.我的那个无线鼠标基本上四五米之外就不能用了.总之,这里的变量usb_device_speed就是用来表征设备速度的,现阶段还不知道这个设备究竟是什么速度的,所以先设置为UNKNOWN.等到知道了以后再进行真正的设置.

第三个函数,choose_address().

这个函数的目的就是为设备选择一个地址.很显然,要通信就要有地址,你要给人写情书表白,你首先得知道人家的通信地址,或者电子邮箱地址.

1132 static void choose_address(struct usb_device *udev)

1133 {

1134 int devnum;

1135 struct usb_bus *bus = udev->bus;

1136

1137 /* If khubd ever becomes multithreaded, this will need a lock */

1138

1139 /* Try to allocate the next devnum beginning at bus->devnum_next. */

1140 devnum = find_next_zero_bit(bus->devmap.devicemap, 128,

1141 bus->devnum_next);

1142 if (devnum >= 128)

1143 devnum = find_next_zero_bit(bus->devmap.devicemap, 128, 1);

1144

1145 bus->devnum_next = ( devnum >= 127 ? 1 : devnum + 1);

1146

1147 if (devnum < 128) {

1148 set_bit(devnum, bus->devmap.devicemap);

1149 udev->devnum = devnum;

1150 }

1151 }

那么现在是时候让我们来认识一下usb子系统里面关于地址的游戏规则了.在悠悠岁月中,一个神话就是浪花一朵,一滴苦酒就是史书一册,而在usb世界里,一条总线就是大树一棵,一个设备就是叶子一片.为了记录这棵树上的每一个叶子节点,每条总线设有一个地址映射表,struct usb_bus结构体里有一个成员struct usb_devmap devmap,

268 /* USB device number allocation bitmap */

269 struct usb_devmap {

270 unsigned long devicemap[128 / (8*sizeof(unsigned long))];

271 };

同时struct usb_bus结构体里面还有一个成员,int devnum_next,在总线初始化的时候,devnum_next被设置为1,而在struct usb_device中有一个int devnum,咱们这个choose_address函数的基本思想就是一个轮询的算法.

我们来介绍一下这段代码背后的哲学.首先,bus上面不是有这么一张表嘛,假设unsigned long=4bytes,那么unsigned long devicemap[128/(8*sizeof(unsigned long)]]就等价于unsigned long devicemap[128/(8*4)],进而等价于unsigned long devicemap[4],4bytes就是32bits,因此这个数组最终表示的就是128bits.而这也对应于一条总线可以连接128usb设备.之所以这里使用sizeof(unsigned long),就是为了跨平台应用,不管unsigned long到底是几,总之这个devicemap数组最终可以表示128.

128bits,每当加入一个设备,就先找到下一位为0bit,然后把该bit设置为1,同时把struct usb_device中的devnum设置为该数字,比如我们找到第19位为0,那么就把devnum设置为19,同时把bit 19设置为1,struct usb_bus中的devnum_next就设置为20.

那么所谓轮询,即如果这个编号超过了128,那么就从1开始继续搜索,因为也许开始那段的号码原来分配给某个设备但后来这个设备撤掉了,所以这个号码将被设置为0,于是再次可用.

弄清楚了这些基本思想后,我们再来看代码就很简单了.这时候相信你可以自豪的和杨振宁先生一样,高呼:”我能!”当然,我不会像翁帆女士一样喊:”你不能,我能让你能!”

find_next_zero_bit()的意思很明显,名字解释了一切.不同的体系结构提供了自己不同的函数实现,比如i386,这个函数就定义于arch/i386/lib/bitops.c,x8664则对应于arch/x86_64/lib/bitops.c,利用这个函数我们就可以找到这128位中下一个为0的那一位.这个函数的第三个参数表征从哪里开始寻找,我们注意到第一次我们是从devnum_next开始找,如果最终返回值暴掉了(大于或者等于128),那么就从1开始再找一次.bus->devnum_next也是按我们说的那样设置,正常就是devnum+1,但如果devnum已经达到127,那么就从头再来,设置为1.

如果devnum正常,那么就把bus中的device map中的那一位设置为1.同时把udev->devnum设置为devnum.然后这个函数就可以返回了.如果128bits都被占用了,devnum就将是零或者负的错误码,于是choose_address返回之后我们就要进行判断,如果真的是满掉了,那么咱们有心杀贼无力回天,也就不用往下走了,不过你要真的能连满128个设备,那你也蛮狠的.不得不把陈小春的那首<<算你狠>>送给你!
分享到:
评论

相关推荐

    Linux那些事儿之我是Hub

    Linux那些事儿之我是Hub,是前面Linux那些事之我是U盘,usb等的姐妹篇

    Linux那些事儿之我是HUB.pdf

    非常不错的一本书,LinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinuxLinux

    Linux那些事儿

    Linux那些事儿之我是Hub Linux那些事儿之我是USB Core Linux那些事儿之我是UHCI Linux那些事儿之我是EHCI控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Block层 Linux那些事儿之我...

    Linux那些事儿1-9合集

    linux那些事儿之我是HUB linux那些事儿之我是USB Core linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Block层 linux那些事儿...

    Linux那些事儿之我是USB(第2版)

    Linux那些事儿第二版我是Hub一章,比较第一版修正了一些错误,增加了电源管理部分的分析,推荐阅读

    Linux那些事儿之全集

    导读.doc Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是Hub.pdf Linux那些事儿之我是USB_core.pdf Linux那些事儿之我是U盘.pdf等等 Linux那些事儿系列全在这里了

    Linux那些事儿系列.rar

    》包括《Linux那些事儿之我是Hub》、《Linux那些事儿之我是Sysfs》《Linux那些事儿之我是UHCI》、《Linux那些事儿之我是USB core》、《Linux那些事儿之我是U盘》,令人叹为观止的一个linux系列书籍。只能说,江山代...

    linux那些事儿之我是USB(包括第一版和第二版完整文字)

    本文件包括第一第二完成版,第二版基于2.6.22内核,对USB子系统的大部分源代码逐行进行分析,系统地阐释了Linux内核中USB子系统是如何运转的,子系统内部的各个模块之间是如何互相协作、配合的。本次改版修改了第1版...

    Linux那些事儿之我是USB(第2版).pdf

    本书基于2.6.22内核,对USB子系统的大部分源代码逐行进行分析,系统地阐释了Linux内核中USB子系统是如何运转的,子系统内部的各个模块之间是如何互相协作、配合的。本次改版修改了第1版中出现的错误,增加了一个附录...

    linux的那些事儿全集

    Linux那些事儿之我是Block层 ...Linux那些事儿之我是Hub Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Sysfs Linux那些事儿之我是UHCI Linux那些事儿之我是USB core Linux那些事儿之我是U盘

    linux那些事儿(EHCI Block SCSI Sysfs PCI USB U 盘 UHCI Hub)

    Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是Block层.pdf Linux那些事儿之我是SCSI硬盘.pdf Linux那些事儿之我是Sysfs.pdf ...Linux那些事儿之我是Hub.pdf Linux那些事儿之我是UHCI.pdf

    linux那些事全集

    Linux那些事儿之我是U盘 Linux那些事儿之我是USB_core Linux那些事儿之我是UHCI Linux那些事儿之我是Sysfs ...Linux那些事儿之我是Hub Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是Block层

    Linux那些事儿系列

    本人整理的fudan_abc的专栏中以完结的文章,在此向原作者表示感谢,给...内容包括:linux那些事儿之我是U盘,linux那些事儿之我是USB,linux那些事儿之我是HUB,linux那些事儿之我是UHCI,linux那些事儿之我是Sysfs。

    Linux那些事儿之我是XXX全集.rar

    Linux那些事儿之我是XXX全集 包含USB core U盘 UHCI PCI SCSI硬盘 Block Hub EHCI 。 想学驱动的童鞋,不妨看看。该书主要是进行源代码的分析

    Linux那些事儿 系列之2 Block+EHCI+PCI+SCSI

    Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是PCI.pdf Linux那些事儿之我是SCSI硬盘.pdf 注: 之前有人已经上传了《Linux那些事儿 系列》,其已经包含了:hub,sysfs...

    Linux那些事儿.rar

    包括:Linux那些Linux那些事儿之我是SCSI硬盘,Linux那些事儿之我是Block层,Linux那些事儿之我是EHCI主机控制器,Linux那些事儿之我是HUB,Linux那些事儿之我是PCI,Linux那些事儿之我是Sysfs,Linux那些事儿之我是...

    linux那些事儿之我是USB.zip

    里面包含Linux那些事的九个文档,Block层,ECHI主机控制,HUB,PCI,SCSI硬盘,Sysfs,UHCI,USB+core,U盘等九个文档,内容详细,而且全面都有书签,适合系统学习!

    Linux那些事系列

    Linux那些事儿之我是Hub Linux那些事儿之我是Sysfs Linux那些事儿之我是UHCI Linux那些事儿之我是USB core Linux那些事儿之我是U盘 Linux那些事之我是HUB1

Global site tag (gtag.js) - Google Analytics