知识屋:更实用的电脑技术知识网站
所在位置:首页 > 操作系统 > linux

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

发布时间:2014-09-05 16:40:44作者:知识屋

 

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 }

www.zhishiwu.com

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 }

 

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

(免责声明:文章内容如涉及作品内容、版权和其它问题,请及时与我们联系,我们将在第一时间删除内容,文章内容仅供参考)
收藏
  • 人气文章
  • 最新文章
  • 下载排行榜
  • 热门排行榜