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

来源:互联网 发布:黑马java视频下载 编辑:程序博客网 时间:2024/05/18 21:42

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 }

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