下面讲一下usb_stor_control_thread()函数。唤醒它的是来自queuecommand的up(&(us->sema)),us->srb被赋值为srb,而srb是来自SCSI核心层在调用queuecommand时候传递进来的参数。聚焦usb_stor_control_thread()。314行,前面说过,关于dev_mutex这把锁我们必须在看完整个模块之后再来从较高的角度来看。
312行,如果设了US_FLIDX_DISCONNECTING,这个不用多说了,是判断设备有没有被拔出,要是你的U盘插进去了永远不拔出来,那么你可以把这个flag相关的代码都删了,当然事实上是你不可能不拔出来,热插拔本来就是USB设备的一大特性。
324行,host也是一把锁,这把锁我们也到最后再来看。
326行到330行,又是判断另一个flag有没有被设置,US_FLDX_TIMED_OUT这个flag的含义也如其字面意义一样,即超时了。超时的概念在计算机的世界里比比皆是。不过对于这个flag,设置它的函数是command_abort,这个函数也是咱们提供的,由SCSI核心层去调用,由它那边负责计时,到了超时的时间它就调用command_abort。我们稍后会看,先不急。
337行,判断srb的一个成员sc_data_direction,先看DMA_BIDIRECTIONAL这个宏。这个宏定义于include/linux/dma-mapping.h中:
7 /* These definitions mirror those in pci.h, sothey can be used
8 *interchangeably with their PCI_ counterparts */
9 enum dma_data_direction {
10 DMA_BIDIRECTIONAL= 0,
11 DMA_TO_DEVICE= 1,
12 DMA_FROM_DEVICE = 2,
13 DMA_NONE= 3,
14 };
这些代码被用来表示数据阶段数据传输的方向。DMA_TO_DEVICE表示从主存到设备,DMA_FROM_DEVICE表示从设备到主存。有传闻说,DMA_NONE则只被用于调试,一般不能使用否则将有可能导致内核崩溃。不过更准确一点的是,USB Mass Storage协议中边规定了双向传输是非法的,而一个命令传输零数据是合法的,比如TEST_UNIT_READY命令就不用传输数据。
DMA_BIDIRECTIONAL表示两个方向都有可能,换而言之也就是不知道究竟是哪个方向。同理,338行看到srb的sc_data_direction是DMA_BIDIRECTIONAL时,自然就当做出错了。因为不确定方向的话也就没法传输数据了。
345行,US_FL_SCM_MULT_TARG这个flag,表示设备支持多个target,这里的意思很明显,对于那些不支持多个target的设备,其us->srb->device->id必须为0,否则就有问题了。struct us_data结构体中的成员struct scsi_cmnd * srb,struct scsi_cmnd结构体中有一成员struct scsi_device * device,而struct scsi_device顾名思义,描述一个SCSI设备,就像过去的struct usb_device用来描述USB设备一样。struct
scsi_device来自include/scsi/scsi_device.h中:
49struct scsi_device {
50 struct Scsi_Host *host;
51 struct request_queue *request_queue;
52
53 /* the next two are protected by thehost->host_lock */
54 struct list_head siblings;/* list of all devices on this host*/
55 struct list_head same_target_siblings;
56
57 /* this is now protected by therequest_queue->queue_lock */
58 unsigned int device_busy; /* commands actually active on
59 *low-level. protected by queue_lock.*/
60 spinlock_t list_lock;
61 struct list_head cmd_list; /* queue of in useSCSI Command structures*/
62 struct list_head starved_entry;
63 struct scsi_cmnd *current_cmnd; /* currentlyactive command */
64 unsigned short queue_depth; /* How deep of aqueue we want */
65 unsigned short last_queue_full_depth; /* Thesetwo are used by */
66 unsigned short last_queue_full_count; /*scsi_track_queue_full() */
67unsigned long last_queue_full_time;/*don't let QUEUE_FULLs on the same
68jiffie count on our counter, they
69could all be from the same event.*/
70
71 unsigned int id, lun, channel;
72
73 unsigned int manufacturer; /* Manufacturerof device, for using
74*vendor-specific cmd's */
75 unsigned sector_size; /* size in Bytes */
76
77 void *hostdata;/* available to low-level driver */
78 char type;
79 char scsi_level;
80 char inq_periph_qual; /* PQ from INQUIRY data */
81 unsigned char inquiry_len; /* valid Bytesin 'inquiry' */
82 unsigned char * inquiry; /*INQUIRY response data */
83 const char * vendor; /* [back_compat] point into 'inquiry' ... */
84 const char * model; /* ... after scan; point to static string*/
85 const char * rev; /* ..."nullnullnullnull" before scan */
86 unsigned char current_tag; /* current tag*/
87 struct scsi_target *sdev_target;/* used only forsingle_lun*/
88
89 unsigned int sdev_bflags; /* black/white flags as also foundin
90* scsi_devinfo.[hc]. For now used only to
91* pass settings from slave_alloc to scsi
92*core. */
93 unsigned writeable:1;
94 unsigned removable:1;
95 unsigned changed:1; /* Data invalid due to media change */
96 unsigned busy:1; /* Used to prevent races*/
97 unsigned lockable:1; /* Able to prevent media removal */
98 unsigned locked:1; /* Media removal disabled */
99 unsigned borken:1; /* Tell the Seagate driver to be
100* painfully slow on this device */
101 unsigned disconnect:1; /* can disconnect */
102 unsignedsoft_reset:1; /* Uses soft resetoption */
103 unsigned sdtr:1; /*Device supports SDTR messages */
104 unsignedwdtr:1; /* Device supports WDTRmessages */
105 unsigned ppr:1;/* Device supports PPR messages */
106 unsignedtagged_supported:1;/* Supports SCSI-II tagged queuing */
107 unsignedsimple_tags:1; /* simple queue tag messages are enabled*/
108 unsignedordered_tags:1;/* ordered queue tag messages are enabled */
109 unsigned single_lun:1;/* Indicates we should only allow I/O to
110* one of the luns for the device at a
111* time. */
112 unsignedwas_reset:1; /* There was abus reset on the bus for
113* this device */
114 unsigned expecting_cc_ua:1; /* Expecting aCHECK_CONDITION/UNIT_ATTN
115* because we did a bus reset. */
116 unsigneduse_10_for_rw:1; /* first try 10-Byte read / write */
117 unsigneduse_10_for_ ms:1; /* first try 10-Byte mode sense/select*/
118 unsignedskip_ ms_page_8:1; /* do not use MODE SENSE page 0x08*/
119 unsignedskip_ ms_page_3f:1; /* do not use MODE SENSE page 0x3f */
120 unsigneduse_192_Bytes_for_3f:1;/* ask for 192 Bytes from page 0x3f*/
121 unsigned no_start_on_add:1; /* do not issue starton add */
122 unsignedallow_restart:1; /* issue START_UNIT in error handler */
123 unsignedmanage_start_stop:1;/* Let HLD (sd) manage start/stop */
124 unsigned no_uld_attach:1;/*disable connecting toupper level drivers*/
125 unsigned select_no_atn:1;
126 unsignedfix_capacity:1; /*READ_CAPACITY is too high by 1 */
127 unsignedguess_capacity:1;/* READ_CAPACITY might be too high by 1 */
128 unsignedretry_hwerror:1; /* Retry HARDWARE_ERROR */
129
130 unsigned int device_blocked; /* Device returnedQUEUE_FULL. */
131
132 unsigned int max_device_blocked;
133 #define SCSI_DEFAULT_DEVICE_BLOCKED 3
134
135 atomic_t iorequest_cnt;
136 atomic_t iodone_cnt;
137 atomic_tioerr_cnt;
138
139 inttimeout;
140
141 struct devicesdev_gendev;
142 structclass_devicesdev_classdev;
143
144 struct execute_work ew; /* used to getprocess context on put*/
145
146 enumscsi_device_state sdev_state;
147 unsigned longsdev_data[0];
148 } __attribute__((aligned(sizeof(unsignedlong))));
这个结构体将在后面多次被提到。当然,此刻,我们只需要注意到unsigned int id,lun,channel这三个成员,这正是定位一个SCSI设备必要的三个成员,一个SCSI卡所控制的设备被划分为几层,先是若干个channel,然后每个channel上有若干个target,每个target用一个target id来表示,然后一个target可以有若干个lun,而这里判断的是target id。对于不支持多个target的设备,必须为0。对于绝大多数USB Mass Storage设备来说,它们的target
id肯定为0。有些设备厂家就是要标新立异,它就是要让设备支持多个target,于是它就可以设置US_FL_SCM_MULT_TARG这么一个flag,比如我们可以在drivers/usb/storage/unusual_devs.h中看到如下的定义:
416 UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100,
417"Shuttle",
418"eUSCSI Bridge",
419US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init,
420US_FL_SCM_MULT_TARG ),
然后352行,us->srb->device->lun不应该大于us->max_lun,这两个东西是什么区别?us->max_lun是咱们早期在usb_stor_scan_thread()中调用usb_stor_Bulk_max_lun()函数来向usb mass storage设备获得的最大LUN,比如MAX LUN等于3,那么这个设备支持的就是4个LUN,即0,1,2,3。而us->srb->device->lun则可以是这四个值中的任意一个,看传递进来的命令是要访问谁了。但它显然不可能超过MAX
LUN。
然后就是358行了。看到这么一个flag-US_FL_FIX_INQUIRY,这又是us->flags中众多flag中的一个,我们前面已经介绍过这个flag,一些定义于drivers/usb/storage/unusal_devs.h中的设备有这个flag。事实上,通常大多数设备的厂商名(Vendor Name)和产品名(Product Name)是通过INQUIRY命令来获得的,而这个flag表明,这些设备的厂商名和产品名不需要查询,或者根本就不支持查询,它们的厂商名和产品名直接就定义好了,在unusal_devs.h中就设好了。那么358行这里这个cmnd[0]是什么?struct
scsi_cmnd里边有这么一个成员,
65 #define MAX_COMMAND_SIZE 16
66 unsigned charcmnd[MAX_COMMAND_SIZE];
这个数组16个元素,它包含的就是SCSI命令,要看懂这个条件判断,得先看下边那句fill_inquiry_response()函数调用。
最后“贴”几个设了US_FL_FIX_INQUIRY这个flag的设备,这几个都是Sony的PEG记忆棒,或者叫记忆卡,可以用在PDA里边。drivers/usb/storage/unusual_devs.h中:
635 /* Submitted by Nathan Babb<nathan@lexi.com> */
636 UNUSUAL_DEV( 0x054c, 0x006d, 0x0000, 0x9999,
637"Sony",
638 "PEGMass Storage",
639US_SC_DEVICE, US_PR_DEVICE, NULL,
640US_FL_FIX_INQUIRY ),
641
642 /* Submitted by Mike Alborn<malborn@deandra.homeip.net> */
643 UNUSUAL_DEV( 0x054c, 0x016a, 0x0000, 0x9999,
644 "Sony",
645"PEG Mass Storage",
646US_SC_DEVICE, US_PR_DEVICE, NULL,
647US_FL_FIX_INQUIRY ),
648
649 /* Submitted by Frank Engel<frankie@cse.unsw.edu.au> */
650 UNUSUAL_DEV( 0x054c, 0x0099, 0x0000, 0x9999,
651"Sony",
652"PEG Mass Storage",
653US_SC_DEVICE, US_PR_DEVICE, NULL,
654US_FL_FIX_INQUIRY ),
655
分享到:
相关推荐
### Linux那些事儿之我是USB —— USB技术在Linux下的实现与探索 #### 引言 在探讨《Linux那些事儿之我是USB》这篇文章之前,我们先简单回顾一下文章的背景及主要内容。该文由一位自称对Linux并无太多好感的作者...
### Linux那些事儿之我是U盘 - **USB技术简介**:作者以幽默的方式回顾了2005年的一次毕业答辩经历,当时被要求用一句话介绍USB技术。这段经历反映出作者对于技术细节的重视以及对USB技术复杂性的理解。 - **关键词...
轴类零件加工工艺设计.zip
资源内项目源码是来自个人的毕业设计,代码都测试ok,包含源码、数据集、可视化页面和部署说明,可产生核心指标曲线图、混淆矩阵、F1分数曲线、精确率-召回率曲线、验证集预测结果、标签分布图。都是运行成功后才上传资源,毕设答辩评审绝对信服的保底85分以上,放心下载使用,拿来就能用。包含源码、数据集、可视化页面和部署说明一站式服务,拿来就能用的绝对好资源!!! 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、大作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.txt文件,仅供学习参考, 切勿用于商业用途。
seaborn基本绘图人力资源数据集
移动机器人(sw三维)
自制html网页源代码查看器
3吨叉车的液压系统设计().zip
1_实验三 扰码、卷积编码及交织.ppt
北京交通大学软件学院自命题科目考试大纲.pdf
雅鲁藏布江流域 shp矢量数据 (范围+DEM).zip
基于RUST的数据结构代码示例,栈、队列、图等
NIFD:2024Q1房地产金融报告
详细介绍及样例数据:https://blog.csdn.net/li514006030/article/details/146916652
【工业机器视觉定位软件Vision-Detect】基于C#的WPF与Halcon开发的工业机器视觉定位软件(整套源码),开箱即用 有用户登录,图片加载,模板创建,通讯工具,抓边抓圆,良率统计,LOG日志,异常管理,九点标定和流程加载保存等模块,功能不是很完善,适合初学者参考学习。 资源介绍请查阅:https://blog.csdn.net/m0_37302966/article/details/146912206 更多视觉框架资源:https://blog.csdn.net/m0_37302966/article/details/146583453
内容概要:本文档详细介绍了Java虚拟机(JVM)的相关知识点,涵盖Java内存模型、垃圾回收机制及算法、垃圾收集器、内存分配策略、虚拟机类加载机制和JVM调优等内容。首先阐述了Java代码的编译和运行过程,以及JVM的基本组成部分及其运行流程。接着深入探讨了JVM的各个运行时数据区,如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区等的作用和特点。随后,文档详细解析了垃圾回收机制,包括GC的概念、工作原理、优点和缺点,并介绍了几种常见的垃圾回收算法。此外,文档还讲解了JVM的分代收集策略,新生代和老年代的区别,以及不同垃圾收集器的工作方式。最后,文档介绍了类加载机制、JVM调优的方法和工具,以及常用的JVM调优参数。 适合人群:具备一定Java编程基础的研发人员,尤其是希望深入了解JVM内部机制、优化程序性能的技术人员。 使用场景及目标:①帮助开发人员理解Java代码的编译和执行过程;②掌握JVM内存管理机制,包括内存分配、垃圾回收等;③熟悉类加载机制,了解类加载器的工作原理;④学会使用JVM调优工具,掌握常用调优参数,提升应用程序性能。 其他说明:本文档内容详尽,适合用作面试准备材料和技术学习资料,有助于提高开发人员对JVM的理解和应用能力。
Android项目原生java语言课程设计,包含LW+ppt
戴德梁行&中国房地产协会:2021亚洲房地产投资信托基金研究报告
Android项目原生java语言课程设计,包含LW+ppt
Thinkphp6.0+vue个人虚拟物品发卡网站源码 支持码支付对接 扫码自动发货 源码一共包含两个部分thinkphp6.0后端文件,以及vue前端文件.zip