374行,us->proto_handler()其实是一个函数指针,知道它指向什么吗?我们早在storage_probe()中,确切地说,在get_protocol()就赋了值,当时只知道是get protocol,却不知道究竟干什么用,现在该用上了,一个指针要是没什么用人家才不会为它赋值呢。当初我们就讲了,对于U盘,proto_handler被赋值为usb_stor_transparent_scsi_command,所以我们来看后者吧。后者定义于drivers/usb/storage/protocol.c:

140 void usb_stor_transparent_scsi_command(structscsi_cmnd *srb,

141                                        structus_data *us)

142 {

143      /* send the command to the transport layer */

144     usb_stor_invoke_transport(srb, us);

145 }

usb_stor_invoke_transport()这个函数可不简单。咱们先做好思想准备, 接下来就去见识一下它的庐山真面目。它来自drivers/usb/storage/transport.c:

505 void usb_stor_invoke_transport(struct scsi_cmnd*srb, struct us_data *us)

506 {

507      int need_auto_sense;

508      intresult;

509

510      /* send the command to the transport layer */

511      srb->resid = 0;

512      result = us->transport(srb, us);

513

514      /* if the command gets aborted by the higherlayers, we need to

515       *short-circuit all other processing

516       */

517      if(test_bit(US_FLIDX_TIMED_OUT, &us->flags)) {

518      US_DEBUGP("-- command wasaborted\n");

519           srb->result = DID_ABORT << 16;

520           goto Handle_Errors;

521      }

522

523      /* if there is a transport error, reset anddon't auto-sense */

524      if (result == USB_STOR_TRANSPORT_ERROR) {

525           US_DEBUGP("-- transport indicates error,resetting\n");

526           srb->result = DID_ERROR << 16;

527           gotoHandle_Errors;

528      }

529

530      /* if the transport provided its own sense data,don't auto-sense */

531      if (result == USB_STOR_TRANSPORT_NO_SENSE) {

532           srb->result = SAM_STAT_CHECK_CONDITION;

533           return;

534      }

535

536      srb->result = SAM_STAT_GOOD;

537

538      /* Determine if we need to auto-sense

539       *

540      * Inormally don't use a flag like this, but it's almost impossible

541      * tounderstand what's going on here if I don't.

542       */

543      need_auto_sense = 0;

544

545      /*

546       * Ifwe're running the CB transport, which is incapable

547       * ofdetermining status on its own, we will auto-sense

548       *unless the operation involved a data-in transfer.  Devices

549       * cansignal most data-in errors by stalling the bulk-in pipe.

550      */

551      if ((us->protocol == US_PR_CB ||us->protocol == US_PR_DPCM_USB) &&

552                        srb->sc_data_direction != DMA_FROM_DEVICE) {

553      US_DEBUGP("-- CB transport devicerequiring auto-sense\n");

554           need_auto_sense = 1;

555      }

556

557      /*

558       * If wehave a failure, we're going to do a REQUEST_SENSE

559       *automatically.  Note that wedifferentiate between a command

560       *"failure" and an "error" in the transport mechanism.

561       */

562     if (result == USB_STOR_TRANSPORT_FAILED) {

563           US_DEBUGP("-- transport indicates commandfailure\n");

564           need_auto_sense = 1;

565      }

566

567      /*

568       * Ashort transfer on a command where we don't expect it

569       * isunusual, but it doesn't mean we need to auto-sense.

570       */

571      if ((srb->resid > 0) &&

572            !((srb->cmnd[0] == REQUEST_SENSE) ||

573              (srb->cmnd[0] == INQUIRY) ||

574              (srb->cmnd[0] == MODE_SENSE) ||

575              (srb->cmnd[0] == LOG_SENSE) ||

576              (srb->cmnd[0] == MODE_SENSE_10))) {

577           US_DEBUGP("-- unexpectedly shorttransfer\n");

578      }

579

580     /* Now, if we need to do the auto-sense, let'sdo it */

581      if (need_auto_sense) {

582           int temp_result;

583      void* old_request_buffer;

584           unsigned short old_sg;

585           unsigned old_request_bufflen;

586           unsigned char old_sc_data_direction;

587           unsigned char old_cmd_len;

588            unsigned char old_cmnd[MAX_COMMAND_SIZE];

589           int old_resid;

590

591           US_DEBUGP("Issuingauto-REQUEST_SENSE\n");

592

593           /* save the old command */

594           memcpy(old_cmnd, srb->cmnd,MAX_COMMAND_SIZE);

595           old_cmd_len = srb->cmd_len;

596

597           /* set the command and the LUN */

598           memset(srb->cmnd, 0, MAX_COMMAND_SIZE);

599           srb->cmnd[0] = REQUEST_SENSE;

600           srb->cmnd[1] = old_cmnd[1] & 0xE0;

601            srb->cmnd[4] = 18;

602

603           /* FIXME: we must do the protocol translationhere */

604      if (us->subclass == US_SC_RBC ||us->subclass == US_SC_SCSI)

605                 srb->cmd_len= 6;

606           else

607                srb->cmd_len= 12;

608

609           /* set the transfer direction */

610           old_sc_data_direction =srb->sc_data_direction;

611           srb->sc_data_direction = DMA_FROM_DEVICE;

612

613            /* use the new buffer we have */

614           old_request_buffer = srb->request_buffer;

615           srb->request_buffer = us->sensebuf;

616

617           /* set the buffer length for transfer */

618           old_request_bufflen = srb->request_bufflen;

619           srb->request_bufflen = US_SENSE_SIZE;

620

621           /* set up for no scatter-gather use */

622           old_sg = srb->use_sg;

623           srb->use_sg = 0;

624

625           /* issue the auto-sense command */

626           old_resid = srb->resid;

627           srb->resid = 0;

628           temp_result = us->transport(us->srb,us);

629

630           /*let's clean up right away */

631           memcpy(srb->sense_buffer, us->sensebuf,US_SENSE_SIZE);

632           srb->resid = old_resid;

633           srb->request_buffer = old_request_buffer;

634           srb->request_bufflen = old_request_bufflen;

635           srb->use_sg= old_sg;

636            srb->sc_data_direction =old_sc_data_direction;

637           srb->cmd_len = old_cmd_len;

638           memcpy(srb->cmnd, old_cmnd,MAX_COMMAND_SIZE);

639

640           if (test_bit(US_FLIDX_TIMED_OUT,&us->flags)) {

641               US_DEBUGP("-- auto-senseaborted\n");

642                srb->result = DID_ABORT<< 16;

643               goto Handle_Errors;

644           }

645           if (temp_result != USB_STOR_TRANSPORT_GOOD) {

646               US_DEBUGP("-- auto-sense failure\n");

647

648                /* we skip the reset if thishappens to be a

649                * multi-target device, since failure of an

650                 * auto-sense is perfectly valid

651                */

652                srb->result = DID_ERROR <<16;

653               if (!(us->flags &US_FL_SCM_MULT_TARG))

654                     goto Handle_Errors;

655                return;

656           }

657

658           US_DEBUGP("-- Result from auto-senseis %d\n", temp_result);

659           US_DEBUGP("-- code: 0x%x, key: 0x%x,ASC: 0x%x, ASCQ: 0x%x\n",

660                          srb->sense_buffer[0],

661                          srb->sense_buffer[2] & 0xf,

662                          srb->sense_buffer[12],

663                          srb->sense_buffer[13]);

664 #ifdef CONFIG_USB_STORAGE_DEBUG

665           usb_stor_show_sense(

666                          srb->sense_buffer[2] & 0xf,

667                          srb->sense_buffer[12],

668                          srb->sense_buffer[13]);

669 #endif

670

671            /*set the result so the higher layers expect this data */

672           srb->result = SAM_STAT_CHECK_CONDITION;

673

674           /* If things are really okay, then let's showthat.  Zero

675            * outthe sense buffer so the higher layers won't realize

676       * we didan unsolicited auto-sense. */

677           if (result == USB_STOR_TRANSPORT_GOOD&&

678                      /* Filemark 0, ignore EOM, ILI 0, no sense */

679                           (srb->sense_buffer[2] & 0xaf) == 0 &&

680                         /* No ASC or ASCQ */

681                           srb->sense_buffer[12] == 0 &&

682                           srb->sense_buffer[13] == 0) {

683               srb->result = SAM_STAT_GOOD;

684               srb->sense_buffer[0] = 0x0;

685           }

686      }

687

688      /* Did we transfer less than the minimumamount required? */

689      if (srb->result == SAM_STAT_GOOD&&

690                         srb->request_bufflen- srb->resid < srb->underflow)

691           srb->result = (DID_ERROR << 16) | (SUGGEST_RETRY<< 24);

692

693      return;

694

695      /* Error and abort processing: try toresynchronize with the device

696       * byissuing a port reset.  If that fails, trya class-specific

697       *device reset. */

698  Handle_Errors:

699

700      /* Set the RESETTING bit, and clear theABORTING bit so that

701       * thereset may proceed. */

702      scsi_lock(us_to_host(us));

703      set_bit(US_FLIDX_RESETTING,&us->flags);

704      clear_bit(US_FLIDX_ABORTING,&us->flags);

705      scsi_unlock(us_to_host(us));

706

707      /* We must release the device lock becausethe pre_reset routine

708       * willwant to acquire it. */

709      mutex_unlock(&us->dev_mutex);

710      result = usb_stor_port_reset(us);

711      mutex_lock(&us->dev_mutex);

712

713      if (result < 0) {

714           scsi_lock(us_to_host(us));

715           usb_stor_report_device_reset(us);

716           scsi_unlock(us_to_host(us));

717           us->transport_reset(us);

718      }

719      clear_bit(US_FLIDX_RESETTING,&us->flags);

720 }

这段代码的复杂,调用关系一层又一层,让很多新手看了感觉无可奈何。

《Linux那些事儿之我是USB》我是U盘(32)迷雾重重的批量传输(一)相关推荐

  1. 《Linux那些事儿之我是USB》我是U盘(37)迷雾重重的批量传输(六)

    usb_stor_bulk_transfer_sglist()函数有一定的"蛊惑性",我们前面说过,之所以采用sglist,就是为了提高传输效率.我们更知道,sg的目的就是让一堆不 ...

  2. 《Linux那些事儿之我是USB》我是U盘(34)迷雾重重的批量传输(三)

    在usb_stor_Bulk_transport()中,这个函数中调用的第一个最重要的函数,那就是usb_stor_bulk_transfer_buf().仍然是来自drivers/usb/stroa ...

  3. 《Linux那些事儿之我是USB》我是U盘(33)迷雾重重的批量传输(二)

    其实故事已经讲了很久,但如果你觉得到这里你已经把故事都看明白了,那么你错了.不仅仅是错了.不信,我们就继续看,先看512行,us->transport(),这个函数指针同样是在storage_p ...

  4. 《Linux那些事儿之我是USB》我是U盘(36)迷雾重重的批量传输(五)

    在讲数据传输阶段之前,先解决刚才的历史遗留问题.usb_stor_bulk_transfer_buf()中,406行,有一个很有趣的函数interpret_urb_result()被调用.这个函数同样 ...

  5. 《Linux那些事儿之我是USB》我是U盘(35)迷雾重重的批量传输(四)

    有时候我也被这个问题所困扰,我不知道是我不明白,还是这世界变化太快.连Linux中都引入了过期这么一个概念.设置一个时间,如果时间到了该做的事情还没有做完,那么某些事情就会发生. 比如需要烤蛋糕,现在 ...

  6. Linux那些事儿 之 戏说USB(3)我是一棵树

    从拓扑上来看,USB子系统并不以总线的方式来部署,它是一颗由几个点对点的连接构成的树. 它主要包括了USB连接.USB host controller和USB device三个部分.而USB devi ...

  7. Linux那些事儿 之 戏说USB(22)设备的生命线(五)

    下面接着看那三个基本点. 第一个基本点,usb_alloc_urb函数,创建urb的专用函数,为一个urb申请内存并做初始化,在drviers/usb/core/urb.c里定义. struct ur ...

  8. Linux那些事儿 之 戏说USB(15)设备

    struct usb_device结构冗长而又杂乱 include/linux/usb.h struct usb_device {int devnum;char devpath[16];u32 rou ...

  9. Linux那些事儿 之 戏说USB(25)设备的生命线(四)

    转载地址:http://blog.csdn.net/fudan_abc/article/details/1819919 洗澡是屁股享福,脑袋吃苦:看电影是脑袋享福,屁股吃苦:看内核代码是脑袋.屁股都吃 ...

最新文章

  1. 检测到包降级: Microsoft.Extensions.Configuration.Abstractions 从 2.1.1 降 2.1.0
  2. R语言限制性立方样条(RCS, Restricted cubic spline)分析:基于logistic回归模型、南非心脏病数据集(South African Heart Disease)
  3. No module named 'tf_extended'
  4. html复选框对齐文字,input【type=checkbox】标签与字体对齐
  5. 程序员减轻压力的十个建议
  6. Android @id和@+id区别
  7. 11g下如何查询trace文件名
  8. hive安装需要安装mysql区别_HIVE安装系列之一:在Linux中安装mysql,为其作为hive的metastore做准备...
  9. 使用Docker Swarm部署MinIO ​​​​​​​
  10. 网络基本概念之TCP, UDP, 单播(Unicast), 多播(组播)(Multicast)
  11. Android Studio(4)---开发人员工作流程基础
  12. Java JSP EL
  13. Tomcat学习总结(19)—— 为什么首选Tomcat作为JavaWeb应用服务器?
  14. java 类的域_Java类中对象域的初始化
  15. 2016版excel_憋了三年,整理出这些相见恨晚的Excel大神技巧,分分钟做出超赞Excel表格!...
  16. JUC并发编程超详细详解篇
  17. 漆远离职阿里加盟复旦!大牛纷纷回归学界,大厂AI名存实亡?
  18. JAVA运行内存的设置
  19. 【转】Chrome浏览器截全屏
  20. 使用12年的笔记本在本该退休的年纪被我再次启用

热门文章

  1. 微软暗讽谷歌封杀Windows
  2. 如何实现端到端加密,该如何设计
  3. foxmail文件导入服务器,Foxmail如何导入旧数据?Foxmail导入旧数据的方法
  4. uni-app 点击图标控制音乐播放
  5. Google云主机利用Docker镜像搭建各类服务器的实战教程
  6. 【迅为iMX6Q】开发板 Linux 5.15.71 RTL8211E 以太网驱动适配
  7. 1469D - Ceil Divisions (思维)
  8. iphone橡皮擦功能的实现
  9. 困扰我一周左右的semver
  10. 数据库——元组关系演算语言ALPHA