`
dato0123
  • 浏览: 915032 次
文章分类
社区版块
存档分类
最新评论

Linux那些事儿之我是U盘(44)迷雾重重的Bulk传输(二)

 
阅读更多

其实故事已经讲了很久了,但如果你觉得到这里你已经把故事都看明白了,那么你错了.不仅仅是错了,你这种想法无异于就是,手里拿着一把刀,就以为自己是刀郎,手里举着一个窝头,就以为自己是托塔李天王.不信,我们就继续看,先看535,us->transport(),这个函数指针同样是在storage_probe的时候被赋值,对于咱们的u,她遵守的是Bulk-Only协议,因此us->transport()被赋值为usb_stor_Bulk_transport().来看usb_stor_Bulk_transport(),她同样来自drivers/usb/storage/transport.c:

948 int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
949 {
950 struct bulk_cb_wrap *bcb = (struct bulk_cb_wrap *) us->iobuf;
951 struct bulk_cs_wrap *bcs = (struct bulk_cs_wrap *) us->iobuf;
952 unsigned int transfer_length = srb->request_bufflen;
953 unsigned int residue;
954 int result;
955 int fake_sense = 0;
956 unsigned int cswlen;
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 = srb->serial_number;
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, US_BULK_CB_WRAP_LEN, NULL);
980 US_DEBUGP("Bulk command transfer result=%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 /* Genesys Logic interface chips need a 100us delay between the
988 * command phase and the data phase */
989 if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS)
990 udelay(100);
991
992 if (transfer_length) {
993 unsigned int pipe = srb->sc_data_direction == DMA_FROM_DEVICE ?
994 us->recv_bulk_pipe : us->send_bulk_pipe;
995 result = usb_stor_bulk_transfer_sg(us, pipe,
996 srb->request_buffer, transfer_length,
997 srb->use_sg, &srb->resid);
998 US_DEBUGP("Bulk data transfer result 0x%x/n", result);
999 if (result == USB_STOR_XFER_ERROR)
1000 return USB_STOR_TRANSPORT_ERROR;
1001
1002 /* If the device tried to send back more data than the
1003 * amount requested, the spec requires us to transfer
1004 * the CSW anyway. Since there's no point retrying the
1005 * the command, we'll return fake sense data indicating
1006 * Illegal Request, Invalid Field in CDB.
1007 */
1008 if (result == USB_STOR_XFER_LONG)
1009 fake_sense = 1;
1010 }
1011
1012 /* See flow chart on pg 15 of the Bulk Only Transport spec for
1013 * an explanation of how this code works.
1014 */
1015
1016 /* get CSW for device status */
1017 US_DEBUGP("Attempting to get CSW.../n");
1018 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
1019 bcs, US_BULK_CS_WRAP_LEN, &cswlen);
1020
1021 /* Some broken devices add unnecessary zero-length packets to the
1022 * end of their data transfers. Such packets show up as 0-length
1023 * CSWs. If we encounter such a thing, try to read the CSW again.
1024 */
1025 if (result == USB_STOR_XFER_SHORT && cswlen == 0) {
1026 US_DEBUGP("Received 0-length CSW; retrying.../n");
1027 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
1028 bcs, US_BULK_CS_WRAP_LEN, &cswlen);
1029 }
1030
1031 /* did the attempt to read the CSW fail? */
1032 if (result == USB_STOR_XFER_STALLED) {
1033
1034 /* get the status again */
1035 US_DEBUGP("Attempting to get CSW (2nd try).../n");
1036 result = usb_stor_bulk_transfer_buf(us, us->recv_bulk_pipe,
1037 bcs, US_BULK_CS_WRAP_LEN, NULL);
1038 }
1039
1040 /* if we still have a failure at this point, we're in trouble */
1041 US_DEBUGP("Bulk status result = %d/n", result);
1042 if (result != USB_STOR_XFER_GOOD)
1043 return USB_STOR_TRANSPORT_ERROR;
1044
1045 /* check bulk status */
1046 residue = le32_to_cpu(bcs->Residue);
1047 US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x/n",
1048 le32_to_cpu(bcs->Signature), bcs->Tag,
1049 residue, bcs->Status);
1050 if ((bcs->Signature != cpu_to_le32(US_BULK_CS_SIGN) &&
1051 bcs->Signature != cpu_to_le32(US_BULK_CS_OLYMPUS_SIGN)) ||
1052 bcs->Tag != srb->serial_number ||
1053 bcs->Status > US_BULK_STAT_PHASE) {
1054 US_DEBUGP("Bulk logical error/n");
1055 return USB_STOR_TRANSPORT_ERROR;
1056 }
1057
1058 /* try to compute the actual residue, based on how much data
1059 * was really transferred and what the device tells us */
1060 if (residue) {
1061 if (!(us->flags & US_FL_IGNORE_RESIDUE) ||
1062 srb->sc_data_direction == DMA_TO_DEVICE) {
1063 residue = min(residue, transfer_length);
1064 srb->resid = max(srb->resid, (int) residue);
1065 }
1066 }
1067
1068 /* based on the status code, we report good or bad */
1069 switch (bcs->Status) {
1070 case US_BULK_STAT_OK:
1071 /* device babbled -- return fake sense data */
1072 if (fake_sense) {
1073 memcpy(srb->sense_buffer,
1074 usb_stor_sense_invalidCDB,
1075 sizeof(usb_stor_sense_invalidCDB));
1076 return USB_STOR_TRANSPORT_NO_SENSE;
1077 }
1078
1079 /* command good -- note that data could be short */
1080 return USB_STOR_TRANSPORT_GOOD;
1081
1082 case US_BULK_STAT_FAIL:
1083 /* command failed */
1084 return USB_STOR_TRANSPORT_FAILED;
1085
1086 case US_BULK_STAT_PHASE:
1087 /* phase error -- note that a transport reset will be
1088 * invoked by the invoke_transport() function
1089 */
1090 return USB_STOR_TRANSPORT_ERROR;
1091 }
1092
1093 /* we should never get here, but if we do, we're in trouble */
1094 return USB_STOR_TRANSPORT_ERROR;
1095 }

看傻了吧,这个函数也不是好惹的.但正是这个函数掀开了我们bulk传输的新篇章.

分享到:
评论

相关推荐

    Linux那些事儿之我是U盘

    Linux那些事儿之我是U盘

    Linux那些事儿之我是U盘.pdf

    Linux那些事儿之我是U盘-有书签版.pdf

    Linux那些事儿

    Linux那些事儿之我是U盘 Linux那些事儿之我是Hub Linux那些事儿之我是USB Core Linux那些事儿之我是UHCI Linux那些事儿之我是EHCI控制器 Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是...

    Linux那些事儿1-9合集

    读过《linux那些事儿之我是U盘》的人,都知道其风格,我就不多说了。 导读: linux那些事儿之我是U盘 linux那些事儿之我是HUB linux那些事儿之我是USB Core linux那些事儿之我是UHCI Linux那些事儿之我是EHCI主机控制...

    Linux那些事儿之全集

    导读.doc Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是Hub.pdf Linux那些事儿之我是USB_core.pdf Linux那些事儿之我是U盘.pdf等等 Linux那些事儿系列全在这里了

    Linux那些事儿系列.rar

    》包括《Linux那些事儿之我是Hub》、《Linux那些事儿之我是Sysfs》《Linux那些事儿之我是UHCI》、《Linux那些事儿之我是USB core》、《Linux那些事儿之我是U盘》,令人叹为观止的一个linux系列书籍。只能说,江山代...

    Linux那些事儿(linux内核写的很详细)

    Linux那些事儿 Linux那些事儿之我是Block层 Linux那些事儿之我是Sysfs Linux那些事儿之我是U盘

    Linux那些事儿之我是USB(第2版).pdf

    本书基于2.6.22内核,对USB子系统的大部分源代码逐行进行分析,系统地阐释了Linux内核中USB子系统是如何运转的,子系统内部的各个模块之间是如何互相协作、配合的。本次改版修改了第1版中出现的错误,增加了一个附录...

    Linux那些事儿之我是Hub

    Linux那些事儿之我是Hub,是前面Linux那些事之我是U盘,usb等的姐妹篇

    linux那些事儿之我是U盘

    深入浅出学linux,linux那些事儿系列之我是U盘

    linux的那些事儿全集

    Linux那些事儿之我是Block层 Linux那些事儿之我是EHCI主机控制器 Linux那些事儿之我是Hub Linux那些事儿之我是PCI Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是Sysfs ...Linux那些事儿之我是U盘

    linux那些事全集

    Linux那些事儿之我是U盘 Linux那些事儿之我是USB_core Linux那些事儿之我是UHCI Linux那些事儿之我是Sysfs Linux那些事儿之我是SCSI硬盘 Linux那些事儿之我是PCI Linux那些事儿之我是Hub Linux那些事儿之我是EHCI...

    Linux那些事儿之我是XXX全集.rar

    Linux那些事儿之我是XXX全集 包含USB core U盘 UHCI PCI SCSI硬盘 Block Hub EHCI 。 想学驱动的童鞋,不妨看看。该书主要是进行源代码的分析

    Linux那些事儿 系列之2 Block+EHCI+PCI+SCSI

    Linux那些事儿之我是Block层.pdf Linux那些事儿之我是EHCI主机控制器.pdf Linux那些事儿之我是PCI.pdf Linux那些事儿之我是SCSI硬盘.pdf 注: 之前有人已经上传了《Linux那些事儿 系列》,其已经包含了:hub,sysfs...

Global site tag (gtag.js) - Google Analytics