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

Linux那些事儿之我是U盘(46)迷雾重重的Bulk传输(四)

 
阅读更多

在讲数据传输阶段之前,先解决刚才的历史遗留问题. usb_stor_bulk_transfer_buf(),429,有一个很有趣的函数interpret_urb_result()被调用.这个函数同样来自drivers/usb/storage/transport.c:

277 /*
278 * Interpret the results of a URB transfer
279 *
280 * This function prints appropriate debugging messages, clears halts on
281 * non-control endpoints, and translates the status to the corresponding
282 * USB_STOR_XFER_xxx return code.
283 */
284 static int interpret_urb_result(struct us_data *us, unsigned int pipe,
285 unsigned int length, int result, unsigned int partial)
286 {
287 US_DEBUGP("Status code %d; transferred %u/%u/n",
288 result, partial, length);
289 switch (result) {
290
291 /* no error code; did we send all the data? */
292 case 0:
293 if (partial != length) {
294 US_DEBUGP("-- short transfer/n");
295 return USB_STOR_XFER_SHORT;
296 }
297
298 US_DEBUGP("-- transfer complete/n");
299 return USB_STOR_XFER_GOOD;
300
301 /* stalled */
302 case -EPIPE:
303 /* for control endpoints, (used by CB[I]) a stall indicates
304 * a failed command */
305 if (usb_pipecontrol(pipe)) {
306 US_DEBUGP("-- stall on control pipe/n");
307 return USB_STOR_XFER_STALLED;
308 }
309
310 /* for other sorts of endpoint, clear the stall */
311 US_DEBUGP("clearing endpoint halt for pipe 0x%x/n", pipe);
312 if (usb_stor_clear_halt(us, pipe) < 0)
313 return USB_STOR_XFER_ERROR;
314 return USB_STOR_XFER_STALLED;
315
316 /* timeout or excessively long NAK */
317 case -ETIMEDOUT:
318 US_DEBUGP("-- timeout or NAK/n");
319 return USB_STOR_XFER_ERROR;
320
321 /* babble - the device tried to send more than we wanted to read */
322 case -EOVERFLOW:
323 US_DEBUGP("-- babble/n");
324 return USB_STOR_XFER_LONG;
325
326 /* the transfer was cancelled by abort, disconnect, or timeout */
327 case -ECONNRESET:
328 US_DEBUGP("-- transfer cancelled/n");
329 return USB_STOR_XFER_ERROR;
330
331 /* short scatter-gather read transfer */
332 case -EREMOTEIO:
333 US_DEBUGP("-- short read transfer/n");
334 return USB_STOR_XFER_SHORT;
335
336 /* abort or disconnect in progress */
337 case -EIO:
338 US_DEBUGP("-- abort or disconnect in progress/n");
339 return USB_STOR_XFER_ERROR;
340
341 /* the catch-all error case */
342 default:
343 US_DEBUGP("-- unknown error/n");
344 return USB_STOR_XFER_ERROR;
345 }
346 }

应该说这个函数的作用是一目了然的.就是根据传进来的参数result进行判断,从而采取相应的行动.partial是实际传输的长度,length是期望传输的长度,传输结束了当然要比较这两者,因为有所期待,才会失望.resultusb_stor_msg_common()函数的返回值,其实就是状态代码,如果为0说明一切都很顺利,结果也是成功的,287这行,打印出result,同时打印出partiallength的比,注意两个%u中间那个”/”,就是除号,或者说分割分子和分母的符号.然后通过一个switch语句判断result,0,说明至少数据有传输,然后有两种情况,于是返回不同的值,一个是USB_STOR_XFER_SHORT,另一个是USB_STOR_XFER_GOOD.至于返回这些值之后会得到什么反应,让我们边走边看.目前只需要知道的是,对于真正传输完全令人满意的情况,返回值只能是USB_STOR_XFER_GOOD.返回其它值都说明有问题.而这里作为传递给switchresult,实际上是usb core那一层传过来的值.而我们注意到,interpret_urb_result这个函数整个是被作为一个返回值出现在usb_stor_bulk_transfer_buf()中的,换言之,前者返回之后,后者也马上就返回了,即再次返回到了usb_stor_Bulk_transport()中来了.因此,我们把视线拉回usb_stor_Bulk_transport(),981,如果result不为USB_STOR_XFER_GOOD,就说明多少有些问题,于是索性usb_stor_Bulk_transport()也返回,没必要再进行下一阶段的传输了.否则,才可以进行下一阶段.

什么下一阶段?所谓的Bulk Only传输,总共就是三个阶段,命令传输阶段,数据传输阶段,状态传输阶段.很显然,真正最有意义的阶段就是数据传输阶段,而在此之前,我们已经讲了第一阶段,即命令传输阶段.下面我们可以来看数据阶段.

989,990,实在没话可说,USB_VENDOR_ID_GENESYS代表某公司,这公司的产品在命令阶段和数据阶段居然还得延时100微秒.没办法,谁要我们生活在一个宣扬个性的时代呢.体谅他们吧,没有哪一种胭脂能涂抹时间,没有哪一件服装能掩饰灵魂,没有哪一套古籍能装潢空虚,没有哪一家公司能说自己的产品是完美的,是没有缺陷的.

992,transfer_length可能为0,因为有的命令她并不需要您传输数据,所以她没有数据阶段.而对于那些有数据阶段的情况,咱们进入if这一段.

993,没什么可说的,就是根据数据传输方向确定用接收pipe还是发送pipe.

然后,995,usb_stor_bulk_transfer_sg()这个函数是真正的执行bulk数据传输了.这个函数来自drivers/usb/storage/transport.c:

484 /*
485 * Transfer an entire SCSI command's worth of data payload over the bulk
486 * pipe.
487 *
488 * Note that this uses usb_stor_bulk_transfer_buf() and
489 * usb_stor_bulk_transfer_sglist() to achieve its goals --
490 * this function simply determines whether we're going to use
491 * scatter-gather or not, and acts appropriately.
492 */
493 int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe,
494 void *buf, unsigned int length_left, int use_sg, int *residual)
495 {
496 int result;
497 unsigned int partial;
498
499 /* are we scatter-gathering? */
500 if (use_sg) {
501 /* use the usb core scatter-gather primitives */
502 result = usb_stor_bulk_transfer_sglist(us, pipe,
503 (struct scatterlist *) buf, use_sg,
504 length_left, &partial);
505 length_left -= partial;
506 } else {
507 /* no scatter-gather, just make the request */
508 result = usb_stor_bulk_transfer_buf(us, pipe, buf,
509 length_left, &partial);
510 length_left -= partial;
511 }
512
513 /* store the residual and return the error code */
514 if (residual)
515 *residual = length_left;
516 return result;
517 }

注释说得很清楚,这个函数是一个壳,真正干活的是她所调用或者说利用的那两个函数.usb_stor_bulk_transfer_sglist()usb_stor_bulk_transfer_buf().后者咱们刚才已经遇到过了,而前者是专门为scatter-gather传输准备的函数,她也来自drivers/usb/storage/transport.c:

433 /*
434 * Transfer a scatter-gather list via bulk transfer
435 *
436 * This function does basically the same thing as usb_stor_bulk_transfer_buf()
437 * above, but it uses the usbcore scatter-gather library.
438 */
439 int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe,
440 struct scatterlist *sg, int num_sg, unsigned int length,
441 unsigned int *act_len)
442 {
443 int result;
444
445 /* don't submit s-g requests during abort/disconnect processing */
446 if (us->flags & ABORTING_OR_DISCONNECTING)
447 return USB_STOR_XFER_ERROR;
448
449 /* initialize the scatter-gather request block */
450 US_DEBUGP("%s: xfer %u bytes, %d entries/n", __FUNCTION__,
451 length, num_sg);
452 result = usb_sg_init(&us->current_sg, us->pusb_dev, pipe, 0,
453 sg, num_sg, length, SLAB_NOIO);
454 if (result) {
455 US_DEBUGP("usb_sg_init returned %d/n", result);
456 return USB_STOR_XFER_ERROR;
457 }
458
459 /* since the block has been initialized successfully, it's now
460 * okay to cancel it */
461 set_bit(US_FLIDX_SG_ACTIVE, &us->flags);
462
463 /* did an abort/disconnect occur during the submission? */
464 if (us->flags & ABORTING_OR_DISCONNECTING) {
465
466 /* cancel the request, if it hasn't been cancelled already */
467 if (test_and_clear_bit(US_FLIDX_SG_ACTIVE, &us->flags)) {
468 US_DEBUGP("-- cancelling sg request/n");
469 usb_sg_cancel(&us->current_sg);
470 }
471 }
472
473 /* wait for the completion of the transfer */
474 usb_sg_wait(&us->current_sg);
475 clear_bit(US_FLIDX_SG_ACTIVE, &us->flags);
476
477 result = us->current_sg.status;
478 if (act_len)
479 *act_len = us->current_sg.bytes;
480 return interpret_urb_result(us, pipe, length, result,
481 us->current_sg.bytes);
482 }
usb_stor_bulk_transfer_sg()函数中,判断use_sg是否为0,从而确定是否用scatter-gather.对于use_sg等于0的情况,表示不用scatter-gather,那么调用usb_stor_bulk_transfer_buf()发送scsi命令.实际传递的数据长度用partial记录,然后length_left就记录还剩下多少没传递,初值当然就是期望传递的那个长度.每次减去实际传递的长度即可.对于use_sg不等于0的情况,usb_stor_bulk_transfer_sglist()函数被调用.我们来看这个函数.

分享到:
评论

相关推荐

    Linux那些事儿之我是U盘

    Linux那些事儿之我是U盘

    Linux那些事儿之我是U盘.pdf

    Linux那些事儿之我是U盘-有书签版.pdf

    Linux那些事儿

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

    Linux那些事儿1-9合集

    读过《linux那些事儿之我是U盘》的人,都知道其风格,我就不多说了。 导读: linux那些事儿之我是U盘 linux那些事儿之我是HUB linux那些事儿之我是USB Core linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制...

    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那些事儿(linux内核写的很详细)

    Linux那些事儿 Linux那些事儿之我是Block层 Linux那些事儿之我是Sysfs Linux那些事儿之我是U盘

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

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

    Linux那些事儿之我是Hub

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

    linux那些事儿之我是U盘

    深入浅出学linux,linux那些事儿系列之我是U盘

    linux的那些事儿全集

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

    linux那些事全集

    Linux那些事儿之我是U盘 Linux那些事儿之我是USB_core Linux那些事儿之我是UHCI Linux那些事儿之我是Sysfs Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是PCI Linux那些事儿之我是Hub Linux那些事儿之我是EHCI...

    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...

Global site tag (gtag.js) - Google Analytics