分类: LINUX
2012-03-30 14:29:00
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 }