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

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

发布时间:2014-09-05 16:39:50作者:知识屋

 

其实故事已经讲了很久,但如果你觉得到这里你已经把故事都看明白了,那么你错了。不仅仅是错了。不信,我们就继续看,先看512行,us->transport(),这个函数指针同样是在storage_probe时被赋值,对于U盘,它遵守的是Bulk-Only协议,因此us->transport()被赋值为usb_stor_Bulk_transport()。来看usb_stor_Bulk_transport(),它同样来自drivers/usb/storage/transport.c:

 

941 int usb_stor_Bulk_transport(struct scsi_cmnd*srb, struct us_data *us)

 

942 {

 

943      struct bulk_cb_wrap *bcb = (structbulk_cb_wrap *) us->iobuf;

 

944      struct bulk_cs_wrap *bcs = (structbulk_cs_wrap *) us->iobuf;

 

945      unsigned int transfer_length =srb->request_bufflen;

 

946      unsigned int residue;

 

947     int result;

 

948      int fake_sense = 0;

 

949      unsigned int cswlen;

 

950      unsigned int cbwlen = US_BULK_CB_WRAP_LEN;

 

951

 

952      /* Take care of BULK32 devices; set extra Byteto 0 */

 

953      if ( unlikely(us->flags &US_FL_BULK32)) {

 

954           cbwlen = 32;

 

955           us->iobuf[31] = 0;

 

956      }

 

957

 

958      /* set up the command wrapper */

 

959      bcb->Signature =cpu_to_le32(US_BULK_CB_SIGN);

 

960      bcb->DataTransferLength =cpu_to_le32(transfer_length);

 

961      bcb->Flags = srb->sc_data_direction ==DMA_FROM_DEVICE ? 1 <<7 : 0;

 

962      bcb->Tag= ++us->tag;

 

963      bcb->Lun= srb->device->lun;

 

964      if (us->flags & US_FL_SCM_MULT_TARG)

 

965           bcb->Lun |= srb->device->id <<4;

 

966      bcb->Length = srb->cmd_len;

 

967

 

968      /* copy the command payload */

 

969      memset(bcb->CDB, 0, sizeof(bcb->CDB));

 

970      memcpy(bcb->CDB, srb->cmnd,bcb->Length);

 

971

 

972      /* send it to out endpoint */

 

973      US_DEBUGP("Bulk Command S 0x%x T 0x%x L%d F %d Trg %d LUN %d CL %d/n",

 

974                        le32_to_cpu(bcb->Signature), bcb->Tag,

 

975                         le32_to_cpu(bcb->DataTransferLength),bcb->Flags,

 

976                         (bcb->Lun >>4), (bcb->Lun & 0x0F),

 

977                         bcb->Length);

 

978      result = usb_stor_bulk_transfer_buf(us,us->send_bulk_pipe,

 

979                                 bcb, cbwlen,NULL);

 

980      US_DEBUGP("Bulk command transferresult=%d/n", result);

 

981      if (result != USB_STOR_XFER_GOOD)

 

982           return USB_STOR_TRANSPORT_ERROR;

 

983

 

984      /* DATA STAGE */

 

985      /* send/receive data payload, if there is any*/

 

986

 

987      /* Some USB-IDE converter chips need a 100usdelay between the

 

988       *command phase and the data phase.  Somedevices need a little

 

989       * morethan that, probably because of clock rate inaccuracies. */

 

990      if (unlikely(us->flags &US_FL_GO_SLOW))

 

991           udelay(125);

 

992

 

993      if (transfer_length) {

 

994      unsigned int pipe = srb->sc_data_direction== DMA_FROM_DEVICE ?

 

995                                us->recv_bulk_pipe : us->send_bulk_pipe;

 

996      result = usb_stor_bulk_transfer_sg(us, pipe,

 

997                                srb->request_buffer, transfer_length,

 

998                                 srb->use_sg, &srb->resid);

 

999           US_DEBUGP("Bulk data transfer result0x%x/n", result);

 

1000          if (result == USB_STOR_XFER_ERROR)

 

1001              return USB_STOR_TRANSPORT_ERROR;

 

1002

 

1003          /* If the device tried to send back more datathan the

 

1004           *amount requested, the spec requires us to transfer

 

1005            * theCSW anyway.  Since there's no pointretrying the

 

1006           * thecommand, we'll return fake sense data indicating

 

1007           * IllegalRequest, Invalid Field in CDB.

 

1008           */

 

1009         if (result == USB_STOR_XFER_LONG)

 

1010              fake_sense = 1;

 

1011    }

 

1012

 

1013    /* See flow chart on pg 15 of the Bulk OnlyTransport spec for

 

1014      * anexplanation of how this code works.

 

1015      */

 

1016

 

1017     /* get CSW for device status */

 

1018    US_DEBUGP("Attempting to getCSW.../n");

 

1019     result = usb_stor_bulk_transfer_buf(us,us->recv_bulk_pipe,

 

1020                                 bcs,US_BULK_CS_WRAP_LEN, &cswlen);

 

1021

 

1022    /* Some broken devices add unnecessaryzero-length packets to the

 

1023      * endof their data transfers.  Such packetsshow up as 0-length

 

1024      *CSWs.  If we encounter such a thing, tryto read the CSW again.

 

1025     */

 

1026     if (result == USB_STOR_XFER_SHORT &&cswlen == 0) {

 

1027          US_DEBUGP("Received 0-length CSW;retrying.../n");

 

1028         result = usb_stor_bulk_transfer_buf(us,us->recv_bulk_pipe,

 

1029                                 bcs,US_BULK_CS_WRAP_LEN, &cswlen);

 

1030     }

 

1031

 

1032     /* did the attempt to read the CSW fail? */

 

1033     if (result == USB_STOR_XFER_STALLED) {

 

1034

 

1035          /* get the status again */

 

1036          US_DEBUGP("Attempting to get CSW (2ndtry).../n");

 

1037         result = usb_stor_bulk_transfer_buf(us,us->recv_bulk_pipe,

 

1038                                 bcs,US_BULK_CS_WRAP_LEN, NULL);

 

1039     }

 

1040

 

1041     /* if we still have a failure at this point,we're in trouble */

 

1042     US_DEBUGP("Bulk status result =%d/n", result);

 

1043     if(result != USB_STOR_XFER_GOOD)

 

1044          return USB_STOR_TRANSPORT_ERROR;

 

1045

 

1046     /* check bulk status */

 

1047    residue = le32_to_cpu(bcs->Residue);

 

1048     US_DEBUGP("Bulk Status S 0x%x T 0x%x R%u Stat 0x%x/n",

 

1049                         le32_to_cpu(bcs->Signature), bcs->Tag,

 

1050                         residue,bcs->Status);

 

1051     if (bcs->Tag != us->tag ||bcs->Status > US_BULK_STAT_PHASE) {

 

1052          US_DEBUGP("Bulk logical error/n");

 

1053          return USB_STOR_TRANSPORT_ERROR;

 

1054     }

 

1055

 

1056     /* Some broken devices report odd signatures,so we do not check them

 

1057      * forvalidity against the spec. We store the first one we see,

 

1058      * andcheck subsequent transfers for validity against this signature.

 

1059      */

 

1060     if (!us->bcs_signature) {

 

1061          us->bcs_signature = bcs->Signature;

 

1062          if (us->bcs_signature !=cpu_to_le32(US_BULK_CS_SIGN))

 

1063              US_DEBUGP("Learnt BCSsignature 0x%08X/n",

 

1064                                         le32_to_cpu(us->bcs_signature));

 

1065     } else if (bcs->Signature !=us->bcs_signature) {

 

1066          US_DEBUGP("Signature mismatch: got %08X,expecting %08X/n",

 

1067                          le32_to_cpu(bcs->Signature),

 

1068                           le32_to_cpu(us->bcs_signature));

 

1069          return USB_STOR_TRANSPORT_ERROR;

 

1070     }

 

1071

 

1072     /* try to compute the actual residue, basedon how much data

 

1073      * wasreally transferred and what the device tells us */

 

1074     if (residue) {

 

1075          if(!(us->flags & US_FL_IGNORE_RESIDUE)) {

 

1076          residue = min(residue,transfer_length);

 

1077              srb->resid =max(srb->resid, (int) residue);

 

1078          }

 

1079     }

 

1080

 

1081     /* based on the status code, we report goodor bad */

 

1082    switch (bcs->Status) {

 

1083    case US_BULK_STAT_OK:

 

1084         /* device babbled -- return fake sense data */

 

1085          if (fake_sense) {

 

1086              memcpy(srb->sense_buffer,

 

1087                               usb_stor_sense_invalidCDB,

 

1088                               sizeof(usb_stor_sense_invalidCDB));

 

1089          returnUSB_STOR_TRANSPORT_NO_SENSE;

 

1090          }

 

1091

 

1092         /* command good -- note that data could beshort */

 

1093          return USB_STOR_TRANSPORT_GOOD;

 

1094

 

1095    case US_BULK_STAT_FAIL:

 

1096          /* command failed */

 

1097         return USB_STOR_TRANSPORT_FAILED;

 

1098

 

1099    case US_BULK_STAT_PHASE:

 

1100          /* phase error -- note that a transport resetwill be

 

1101          *invoked by the invoke_transport() function

 

1102          */

 

1103         return USB_STOR_TRANSPORT_ERROR;

 

1104    }

 

1105

 

1106    /* we should never get here, but if we do,we're in trouble */

 

1107     return USB_STOR_TRANSPORT_ERROR;

 

1108 }

 

这个函数也不是好“惹”的。但正是这个函数掀开了我们批量传输的新篇章

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