ep 为3,那么就是得到了1000,然后取反,得到0111,(当然高位还有更多个1),然后(dev)->toggle[out] 和0111 相与,这就是使得toggle[out]的第3 位清零而其她位都不变.然后咱们这里bit 传递进来的是0, 所以就不起什么作用,还是reset 成0.总之,269 行做的事情就是把指定的Endpoint 的和指定的pipe 对 应的那位toggle 位给清零.) 当然细心的人会看一下spec,spec 里面说了,对于使用data toggle 的endpoint,不管其halt feature 是否被设置了,总之只要你调用Clear Feature,那么其data toggle 总是会被初始化为Data0).所以有人 就奇怪了,既然调用Clear Feature 就已经把data toggle 位初始化为0 了,那这里为什么还要再次作一次 set toggle 呢? 事实上是这样的,其实这个世界上有两个toggle bits,不是两个toggle bit,是两个toggle bit_s_,单复 数别看错了,其实设备里边是有一个toggle bits,而我们这里软件层次上,也定义了toggle bits,这个 toggle bits 是给host 用的,设备里边的那个toggle bits 在clear feature 之后,没错,是被初始化成 Data0 了,但是host这边他也想记录下这么一个序列,所以写代码的哥们儿就定义了这个一个数组,而这里调用set toggle 的目的无非就是想让这个数组和设备中物理上的那个toggle bits 保持同步. 到这里这个函数也就结束了,返回的是这次控制传输的结果,不过我们注意到调用这个函数的上下文,并没 有人会care 这个返回值,也许这里再判断返回值的意义不大了吧,本来就是在处理出错的代码中. 至此, usb_stor_Bulk_max_lun 这个函数也终于要返回了.于是我们终于,终于再一次回到了 usb_stor_acquire_resources 函数中,我容易吗?别说我了,歌神张学友在看到Linux 内核代码如此复杂 也不得不感慨说,这代码是一张无边无际的网,轻易就将我困在网中央,我越陷越深越迷惘,路越走越远越漫 长,如何我才能锁住这个函数... 776 行,令us->max_lun 等于刚才usb_stor_Bulk_max_lun()的返回值.接下来,我们将看到一行具 有划时代意义的代码.从此我们唱着东方红,走进新时代,这就是伟大的S-C-S-I. 横空出世的 scsi 世界上最遥远的距离, 不是生与死, 而是我就站在你面前, 你却不知道我爱你. 世界上最遥远的距离, 不是我就站在你面前, 你却不知道我爱你, 而是明明知道彼此相爱, 却不能在一起. 世界上最遥远的距离, 不是明明知道彼此相爱, 却不能在一起, 89 而是明明无法抵挡这股想念, 却还得故意装作丝毫没有把你放在心里. 世界上最遥远的距离, 不是明明无法抵挡这股想念, 却还得故意装作丝毫没有把你放在心里, 而是用自己冷默的心,
对爱你的人掘了一条无法跨越的沟渠. 曾经天真的以为代码看到这里,该出场的函数也都出场了,该出场的数据结构也都出场了,不会有什么新鲜 的冬冬了.曾经天真的以为我们即将知道整个驱动是如何工作的了.未曾想到,我们距离完全了解整个故事还 有一光年. 挡在我们面前的,是scsi. 的确,看一个U 盘驱动不仅仅是要了解usb 协议,还要懂scsi 协议,要 知道U 盘它不仅仅是usb 设备,它还是”盘”,它要存储数据,所以才叫它usb mass storage,所以才叫它海 量存储,而U 盘,它所遵循的传输协议叫bulk-only 传输,它所遵循的指令集叫做SCSI transparent command sets.换句话说,U 盘究竟怎么通信?使用scsi 命令.你不懂scsi 协议行吗? 没办法,如果你对scsi 协议完全不了解.那么对不起,先抽点空熟悉一下scsi 协议,熟悉一下scsi 命令集吧. 不要说你没有时间,雷锋同志说的好,时间就像乳沟,只要肯挤,总是有的.去google 一把吧,去百度一把吧. 我们在这里等你. 如果你真的不去看,那好吧,我假设你了解一点吧,什么是scsi?无非也是一类总线.不过我们通常大多数普 通人并不会接触scsi,公司里边用得多,比如scsi 硬盘,校园里边大学生通常不用scsi 硬盘,用ide 硬盘.每 种 硬盘都有它的市场.就像每个明星都有它的fans 一样.于是我们知道这个世界上有玉米,有凉粉,有盒饭.那 么常见的硬盘就是scsi 硬盘和ide 硬盘.scsi 硬盘属于scsi 设备中的一种,有设备就有总线,有总线就有协 议,所以我们知道了这个世界上有一种协议叫做scsi 协议,就好比我们usb 世界里有usb 协议一样.时下流 行的是SCSI-2 协议.Linux 内核代码中自然也按这个协议来为scsi 设备准备设备驱动程序. 关于scsi,drivers 目录下面当然也有一个子目录是属于它的,那就是drivers/scsi 目录.如果你有雅兴用 ls 命令看一下,你会发现这下面的文件那是相当的多.如果你真的很感兴趣,那么请从Kconfig 文件和 Makefile 文件开始看起.去深入了解一下Linux 整个scsi 子系统是怎么工作的.我就不奉陪了.不过正如 我 们曾经介绍过的2.6 中伟大的设备模型实现了这么一件事情,不管你是pci 还是usb 还是scsi,都给你定义 一条总线,然后总线上面两棵树,一棵是设备,一棵是驱动,对于设备这棵树,pci 有pci 的扫描方法,usb 有 usb 的扫描方法,scsi 有scsi 的扫描方法,总之这个过程被称为总线枚举,枚举完了之后设备这棵树就建立 好 了,同时drivers 这棵树也会一步一步建立.每类设备有它自己的比较方法,要是合适,就把一个设备和一个 驱动绑定起来,这样子,驱动程序提供的函数自然就会在需要的时候被调用,那么,谁来调用? Ok,如果你是代码设计者,你会怎么处理?你打算如何为整个scsi 系统规划代码?不知道?真的不知道?那 么我真的羡慕你这么年轻就认识我了.不过,可惜,我也不知道.经过在复旦四年的大学教育,我已经被训练成 了一名合格的人渣.这几年里我们关注的只是璩美凤的被偷拍事件,只是赵忠祥的录音事件,只是李金斗的嫖 娼事件,只是阿丘的包二奶事件,却从未曾关注过自己应该学点什么,作为一名生在红旗下长在新中国的共产 主义接班人,惭愧啊! 算了,不知道就不知道吧,让我们来思考一下.就像usb 子系统那边一样,usb 那边有一部分核心代码,被称 为usb core,那么scsi 这边自然也应该有这么一部分代码吧,也叫scsi core,这你没意见吧.usb 那边弄了 一个usb host 目录,然后各种设备也分了类,比如storage 设备,比如input 设备,比如serial 设备,比如 image 设备,那是因为usb 的世界里有两个角色,一个是host,一个是设备,那scsi 这边是不是也可以这样 90 呢?先不说可不可以这样,事实情况是,没有这样,所有的冬冬都一股脑儿堆在drivers/scsi/目录下面,有朝 一日你要是混入了开发队伍中,你不妨提议把这个目录整理一下,别像现在这样,至少看上去整齐一点,乱七 八糟不象话.不过也许开发者们有他们自己的理由吧,他们也许没有时间,那么你可以告诉他们雷锋同志是如 何说的.开发者们把scsi 设备分成了四类,于是他们写了四个模块来为这些设备做驱动程序.这四个模块是 sd_mod.ko,sr_mod.ko,st.ko,sg.ko.如果你正在Linux 下使用U 盘,那么用lsmod 查看一下当前安装 的模块,你一定会看到一个叫做sd_mod 的模块,一定会看到一个叫做scsi_mod 的模块,scsi_mod.ko 正
- Page 1 and 2:
摘要 ............................
- Page 3 and 4:
迷雾重重的Bulk 传输(二)....
- Page 5 and 6:
引子 也许是在复旦养成了
- Page 7 and 8:
usb.h datafab.h dpcm.h initializers
- Page 9 and 10:
的Linux 内核划分为许许多
- Page 11 and 12:
目录下执行make 了.Ok,make 之
- Page 13 and 14:
只 是一个usb 接口.这些口
- Page 15 and 16:
中也定义了这么一些数据
- Page 17 and 18:
511 * @driver: the driver model cor
- Page 19 and 20:
233 .owner = THIS_MODULE, 234 .name
- Page 21 and 22:
91 * construct these entries. Each
- Page 23 and 24:
324 struct usb_host_config *actconf
- Page 25 and 26:
22 88 * @class_dev: driver model's
- Page 27 and 28:
必须给各个地方取名,完了
- Page 29 and 30:
26 136 trans_cmnd transport; /* tra
- Page 31 and 32:
944 init_MUTEX_LOCKED(&(us->sema));
- Page 33 and 34:
147 #if !defined(CONFIG_BLK_DEV_UB)
- Page 35 and 36:
124 #define USB_DEVICE_ID_MATCH_DEV
- Page 37 and 38:
intf 来代替. us 之所以重要,
- Page 39 and 40: 睡眠,那就得用GPF_ATOMIC,这
- Page 41 and 42: 504 if (msg >= 0 && !(unusual_dev->
- Page 43 and 44: 179 } 180 181 static struct us_unus
- Page 45 and 46: 711 /* Submitted by Hartmut Wahl */
- Page 47 and 48: 3. useProtocol 为US_SC_DEVICE, use
- Page 49 and 50: Bus 004 Device 001: ID 0000:0000 Bu
- Page 51 and 52: 993 result = get_pipes(us); 994 if
- Page 53 and 54: 631 us->transport_reset = usb_stor_
- Page 55 and 56: 659 us->max_lun = 0; 660 break; 661
- Page 57 and 58: 740 /* Calculate and store the pipe
- Page 59 and 60: storage 会有两个bulk 端点,用
- Page 61 and 62: 比如说,复旦大学,有一个主
- Page 63 and 64: 1079 #define PIPE_ISOCHRONOUS 0 108
- Page 65 and 66: 782 us->unusual_dev->initFunction(u
- Page 67 and 68: 630 * each frame is in the fields o
- Page 69 and 70: 716 * Bulk URBs may 717 * use the U
- Page 71 and 72: 802 int number_of_packets; /* (in)
- Page 73 and 74: 先说互斥锁.它诞生于这样
- Page 75 and 76: 920 US_DEBUGP("GetMaxLUN command re
- Page 77 and 78: 148 /* set up data structures for t
- Page 79 and 80: 90 * @wValue: matches the USB wValu
- Page 81 and 82: 830 void *transfer_buffer, 831 int
- Page 83 and 84: 25 { 26 x->done = 0; 27 init_waitqu
- Page 85 and 86: 都会过期,我开始怀疑,在这
- Page 87 and 88: 是实际长度,要么就是不成
- Page 89: 87 258 行,usb_pipeendpoint,定义
- Page 93 and 94: Type: Direct-Access ANSI SCSI revis
- Page 95 and 96: 416 /* 417 * this defines our host
- Page 97 and 98: 69 * Ioctl interface 70 * 71 * Stat
- Page 99 and 100: 155 * "is this a new device" checks
- Page 101 and 102: 241 char *proc_name; 242 243 /* 244
- Page 103 and 104: 328 * True if the low-level driver
- Page 105 and 106: 可以看到这个函数的参数
- Page 107 and 108: 451 short unsigned int max_sectors;
- Page 109 and 110: 地 说明了为啥咱们要显式
- Page 111 and 112: usb_stor_acquire_resources()函数
- Page 113 and 114: 341 } 342 343 /* reject if target !
- Page 115 and 116: 内核的核心位置,kernel/exit.c
- Page 117 and 118: 1023 dissociate_dev(us); 1024 retur
- Page 119 and 120: 917 行,再次判断设备有没有
- Page 121 and 122: 181 182 /* fail the command if we a
- Page 123 and 124: 83 struct timer_list eh_timeout; /*
- Page 125 and 126: 123 两个scsi_done,一个是struct
- Page 127 and 128: 56 jiffie count on our counter, the
- Page 129 and 130: 中 看到如下的定义: UNUSUAL_
- Page 131 and 132: 269 memcpy(data+16, us->unusual_dev
- Page 133 and 134: 一切准备好了之后,我们就
- Page 135 and 136: 238 (sg->offset + *offset) & (PAGE_
- Page 137 and 138: 所以对于那些不能相应INQUI
- Page 139 and 140: 239 行对unsigned int sglen 赋值
- Page 141 and 142:
请求,所以这里就判断abort
- Page 143 and 144:
112 case GPCMD_READ_HEADER: what =
- Page 145 and 146:
到北京,每每只有在夜深人
- Page 147 and 148:
580 /* 581 * If we have a failure,
- Page 149 and 150:
666 memcpy(srb->cmnd, old_cmnd, MAX
- Page 151 and 152:
950 struct bulk_cb_wrap *bcb = (str
- Page 153 and 154:
1034 /* get the status again */ 103
- Page 155 and 156:
426 /* store the actual length of t
- Page 157 and 158:
后她会给host 返回一个CSW.CB
- Page 159 and 160:
296 } 297 298 US_DEBUGP("-- transfe
- Page 161 and 162:
491 * scatter-gather or not, and ac
- Page 163 and 164:
迷雾重重的 Bulk 传输(五) us
- Page 165 and 166:
然后把她赋给了result.而us->
- Page 167 and 168:
而bcs->Status,标志命令执行
- Page 169 and 170:
就必须设置US_FL_IGNORE_RESIDUE
- Page 171 and 172:
485 }; 486 这是一个字符数组
- Page 173 and 174:
srb->sense_buffer 里边的东西.S
- Page 175 and 176:
一个类似的函数,名叫usb_sto
- Page 177 and 178:
这种命令应该由mid level 来
- Page 179 and 180:
Disk /dev/sda: 146.1 GB, 1461631057
- Page 181 and 182:
through to the most significant bit
- Page 183 and 184:
1192 USB_TYPE_CLASS | USB_RECIP_INT
- Page 185 and 186:
315 行,scsi_report_device_reset(),
- Page 187 and 188:
285 US_DEBUGP("No reset during disc
- Page 189 and 190:
229 /* Wait for the aborted command
- Page 191 and 192:
两个函数中需要判断它,一
- Page 193 and 194:
associate_dev()相对应.我们来
- Page 195 and 196:
束for 死循环,从而usb_stor_con
- Page 197 and 198:
317 for (i = 1; i < us->host->max_i