1139 /* Give the device some time to recover from the reset, 1140 * but don't delay disconnect processing. */ 1141 wait_event_interruptible_timeout(us->dev_reset_wait, 1142 test_bit(US_FLIDX_DISCONNECTING, &us->flags), 1143 HZ*6); 1144 if (test_bit(US_FLIDX_DISCONNECTING, &us->flags)) { 1145 US_DEBUGP("Reset interrupted by disconnect\n"); 1146 goto Done; 1147 } 1148 1149 US_DEBUGP("S<strong>of</strong>t reset: clearing bulk-in endpoint halt\n"); 1150 result = usb_stor_clear_halt(us, us->recv_bulk_pipe); 1151 1152 US_DEBUGP("S<strong>of</strong>t reset: clearing bulk-out endpoint halt\n"); 186 1153 result2 = usb_stor_clear_halt(us, us->send_bulk_pipe); 1154 1155 /* return a result code based on the result <strong>of</strong> the control message */ 1156 if (result < 0 || result2 < 0) { 1157 US_DEBUGP("S<strong>of</strong>t reset failed\n"); 1158 goto Done; 1159 } 1160 US_DEBUGP("S<strong>of</strong>t reset done\n"); 1161 rc = SUCCESS; 1162 1163 Done: 1164 clear_bit(US_FLIDX_RESETTING, &us->flags); 1165 return rc; 1166 } 前面几行是赋值,然后usb_stor_report_device_reset()被调用. usb_stor_report_device_reset() 定义于drivers/usb/storage/scsiglue.c 中, 308 /* Report a driver-initiated device reset to the SCSI layer. 309 * Calling this for a SCSI-initiated reset is unnecessary but harmless. 310 * The caller must own the SCSI host lock. */ 311 void usb_stor_report_device_reset(struct us_data *us) 312 { 313 int i; 314 315 scsi_report_device_reset(us->host, 0, 0); 316 if (us->flags & US_FL_SCM_MULT_TARG) { 317 for (i = 1; i < us->host->max_id; ++i) 318 scsi_report_device_reset(us->host, 0, i); 319 } 320 }
315 行,scsi_report_device_reset(),drivers/scsi/scsi_error.c 中定义的.这个函数scsi core 那边 要求我们调用的,我们身不由己.然而关于这个函数的细节,只能说,世界太大,我们只在乎我们需要在乎的冬 冬,其她的我们无暇顾及.我们只想在960 万平方千米的一个角落里,静静的为自己的理想打拼,为自己寻找 一份荣耀.usb 是我们care 的,而scsi 的核心,我们是不想去深究的,只有写scsi 核心的同志们会在乎.江 湖 中流传这么一句话:女孩在乎的是下半生的幸福,男孩关注的是下半身的幸福.同样,Linux 世界里,每一个人 在乎的冬冬是不一样的……言归正传,咱们是不需要关系这个函数怎么定义的,但是咱们需要知道什么时候 会调用她,调用她干嘛?需要传递什么参数?首先,要传递三个参数,第一个,<strong>Scsi</strong>_Host 指针,一块u 盘就有 一 个<strong>Scsi</strong>_Host,然后第二个参数,channel,然后第三个参数target,描述scsi 设备位置的四个参数就三缺一 了,缺的就是LUN,因为一个device 都reset 那么就不会管她上面有几个LUN了,有几个都一起给她reset. 那么调用这个函数的目的是什么?告诉scsi 核心,俺观察到某个设备reset 了.至于scsi 核心会如何处理 呢, 那咱管不着,也懒得去管.总而言之,言而总之,统而言之,言而统之,咱们的职责是在发现了一个设备reset 之 后立刻向上级汇报. 187 US_FL_SCM_MULT_TARG 这个flag,咱们也提过好几次,她代表的是支持多个target,这是设备本身的 属性,不是咱们的代码愣给设备设的.对于这种设备,scsi_report_device_reset()就会被多调用几次,针对 每一个target 要report 一次. 结束了scsi_report_device_reset(),自然又回到了usb_stor_reset_common(),1123 行,1124 行 设置一个flag,清除一个flag,设置的是US_FLIDX_RESETTING,清除的是US_FLIDX_ABORTING,关 于这两个flag,一会咱们结合command_abort()来讲. 1131 行,usb_stor_control_msg()被调用,再一次看到这个函数想必大家已经不再陌生了吧.她就是发 送一个控制命令,其实我们已经很久没有讲控制传输了.这里结合参数来看看传送的什么命令.首先,us 还是 那个us,不再多说.然后,pipe 是us->send_ctrl_pipe,就是发送控制管道.然后request,requesttype 这 些都是在调用usb_stor_reset_common()的时候传递进来的参数,在usb_stor_Bulk_reset()中可以 看到,request 是US_BULK_RESET_REQUEST,requesttype 是USB_TYPE_CLASS | USB_RECIP_INTERFACE. US_BULK_RESET_REQUEST 在drivers/usb/storage/transport.h 中被设置为0xff,这是和usb mass storage class-Bulk Only transport 协议相对应的.该协议专门为Bulk-Only Mass Storage 设 备定义了一个请求,即Reset.协议里说,this request is used to reset the mass storage device and its associated interface.协议中规定了,当usb host 要发送命令reset usb 设备的时候,需要通过发送 控 制管道发送一个请求,即前面提过的ctrlrequest,其格式如下图所示: 其中bReques 这一位须设置为255(FFh),wValue 设置为0,w<strong>Index</strong> 设置为interface number,wLength 设置为0.(而我们这里也确实这样做了,w<strong>Index</strong> 被赋值为us->ifnum,和上次咱们调 用usb_stor_control_msg 的时候传递的一样,显然interface 还是那个interface.江山会变,四季会变, 咱们心中的interface 始终不变.) 至于requesttype,和咱们在usb_stor_Bulk_max_lun()中讲的差不多,唯一的区别是控制数据传输方 向,当时是device to host,现在是host to device,所以当时多了一个USB_DIR_IN,而现在没有写 USB_DIR_OUT,原因很简单,USB_DIR_OUT 被定义为0,所以或不或她无所谓. 嗯,酱紫,就完成了向设备发送reset 命令的任务.返回值小于0 就是出错了. 没出错那么就1141 行,wait_event_interruptible_timeout()被调用.us->dev_reset_wait 咱们前
- 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 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: 1192 USB_TYPE_CLASS | USB_RECIP_INT
- 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