然 要设置need_auto_sense 了.而704 行这里判断result 是否等于USB_STOR_TRANSPORT_GOOD, 那么很显然,如果result 等于USB_STOR_TRANSPORT_FAILED,那么它就不可能等于 USB_STOR_TRANSPORT_GOOD,因此,这里这个判断一定是针对第一种need_auto_sense 的情况, 正如我们曾经说过的,遵守US_PR_CB/US_PR_DPCM_USB协议的设备是不会自己返回命令执行之后的 Status,所以我们不管它执行到底成功与否,我们都会对它来一次REQUEST SENSE,就是为了尽可能多的 获取一些信息,这样一旦出了问题,我们至少能多一些辅助信息来帮我们判断问题出在哪.那么对于 USB_STOR_TRANSPORT_GOOD 的情况,首先这说明命令执行是没有问题的了,我们仔细看一下这个if 语句,除了这个条件以外还判断了另外三个条件,(srb->sense_buffer[2]&0xaf)结果为0,那么说明 srb->sense_buffer[2]的bit0~bit3 都为0,bit5 为0,bit7 也为0,而bit4 和bit6 是什么我们无所 谓.(如 果这个你还要问为什么那么我只能说你没救了.没办法,这个世界上只有10 种人,一种是懂二进制的,一种 是 不懂二进制的.)虽然我们没有兴趣熟悉每一个SCSI 命令的细节,但我们毕竟是共产主义接班人,应该对社 会主义建设的方方面面都有所了解,所以让我们来仔细看看这个sense_buffer[2].对照sense data 的格 式那张图,sense data 的第二个字节,bit0~bit3 是sense key,bit4 是Reserved,即保留的,不使用 的.bit5 是ILI,全称incorrect length indicator,bit6 是EOM,全称End <strong>of</strong> Medium,bit7 是Filemark, 伟大的不朽的金山词霸告诉我们这个词叫做卷标.关于sense key,<strong>Scsi</strong> 协议是这么规定的,如果sense key 为0h,那么这种情况表示NO SENSE.这种情况通常对应于命令的成功执行或者就是 Filemark/EOM/ILI bits 中的任一个被设置为了1.需要注意的是,scsi 协议里边定义了四样东 西,Filemark/EOM/ILI/Sense Key,它们都是为了提供错误信息的,只是前三者只要一个bit 就能表达明 确 的意思了,而最后一个包含很多信息,所以需要用4 个bits,并且还在后面附有很多额外信息,即 sense_buffer[12]和sense_buffer[13],这里也要求它们为0,即所谓的ASC 和ASCQ 都为0,在scsi 协议里面,这种情况称之为NO ADDITIONAL SENSE INFORMATION.关于这一点scsi 协议是这么说 的:”The REQUEST SENSE command requests that the target transfer sense data to the initiator. If the target has no other sense data available to return, it shall return a sense key <strong>of</strong> NO SENSE and an additional sense code <strong>of</strong> NO ADDITIONAL SENSE INFORMATION.”而这 正是我们这里的代码所表达的意思.(什么?你要我翻译这段话?有没有搞错啊,难道你没上过新东方,没听过 老罗的课?那么我代表人民代表党义正严辞的告诉你,同志,你真的落伍了耶!) (filemark 和eom 都是针对磁带设备的,跟磁盘设备无关.也就是说跟咱们无关.) 178 最后,满足了这四个条件的情况就表示刚才这次scsi 命令的传输确实是圆满完成了.应该说这次检测还是 蛮严格的,毕竟开源社区的同志们觉得写代码不像我们开会,每次看新闻,发现凡是会议必然是圆满成功的. 这里人家检查了这么多条件都满足然后就设置srb->result 为SAM_STAT_GOOD,并且把 srb->sense_buffer[0]也置为0.sense data 的byte 0 由两部分组成,Valid 和Error code,如果置为 0,首先就说明这整个sense data 是无效的, 用scsi 标准的说法叫invalid, 所以scsi core 自然没法识别 这么一个sense data,而我们既然认定这个命令是成功执行的,当然就没有必然让scsi core 再去理睬这么 一个sense data 了. 以上花了大量笔墨就讲了704 到712 这个if 语句段.需要重新强调一点,正如我们已经说过的,对于U 盘, 这段代码根本就不可能执行,理由我们已经说过了.但是既然它出现在我们眼前了,我们又有什么理由去逃避 呢?写代码,尤其是写这种通用的设备驱动程序,必然要考虑各种情况,不是完全跟着感觉走,也不是纯粹的追 求华丽的算法和数据结构,更应该接近实际,华丽的代码堆砌的东西缺乏骨质感. 这样,关于need_auto_sense 设置了的这一段就结束了.最后还想重复一点,说起来,REQUEST SENSE
这种命令应该由mid level 来发,不应该由底层驱动来发,不过通常mid-level 并不愿意发这个命令,因为 实 际上很多SCSI 主机适配卡(SCSI host adapter)会自动request the sense.所以为了让事情变得简单, 设计上要求底层驱动去对付这个问题.所以要么SCSi host adapters 自动获得sense data,要么就是咱们 LLD(底层驱动程序)去发送这个命令,对于咱们这个模拟的scsi 系统,当然只能是用软件去实现,即咱们必 须 在LLD 中用代码来发送request sense. 再然后,716 行,如果经过了这么一番折腾,srb->result 仍然等于SAM_STAT_GOOD,(我们在559 行, 即进行autosense 之前把srb->result 设置成了SAM_STAT_GOOD.)那么说明真金不怕火炼,我们再 判 断最后一个条件,即我们要求传输的数据长度是srb->request_bufflen,而实际上还剩下srb->resid个字 节没有被传送,这种情况本身没什么,但是struct scsi_cmnd 中有一个成员叫做underflow,其意思是如果 传输的数据连这个值都没有达到的话,不管其它条件如何,必须向上层反映,出错了.换句话说,有些scsi 命 令 有一个底线,你至少得达到我这个底线,否则我跟你急!所以这里就是判断这么一个条件是否满足,如果传输 的长度小于srb->underflow,那么不用废话,即便你其它条件判断下来都觉得这个命令是成功的,我还是要 汇报说你这个命令执行有误.而关于这种情况,我们反馈给scsi core 的result 是DID_ERROR
- 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 and 90:
87 258 行,usb_pipeendpoint,定义
- Page 91 and 92:
对爱你的人掘了一条无法
- 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: 一个类似的函数,名叫usb_sto
- 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