You also want an ePaper? Increase the reach of your titles
YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.
217 (void) (&_x == &_y); \<br />
218 _x > _y ? _x : _y; })<br />
而208 行比较的是一个buflen,一个srb->request_bufflen-*<strong>of</strong>fset,咱们这次要传送的数据长度是<br />
buflen,但是显然也不能够超过后者,所以就取其中小的那个,调用memcpy copy,然后215 行*<strong>of</strong>fset 加<br />
上copy 的字节cnt,对于这种不采用scatter gather 方式的传输,那么到这里就可以返回了,直接就到278<br />
行,返回cnt 即可.<br />
但是对于使用scatter gather 方式的传输,情况当然不一样了.从224 行开始往下看,显然如咱们所说,<br />
得定义一个struct scatterlist 结构体的指针,由于struct scatterlist 是和体系结构有关的,作为曾经的<br />
Intel 人,我没有任何犹豫的应该以i386 的为例,include/i386/scatterlist.h:<br />
4 struct scatterlist {<br />
5 struct page *page;<br />
6 unsigned int <strong>of</strong>fset;<br />
7 dma_addr_t dma_address;<br />
8 unsigned int length;<br />
9 };<br />
这个结构并不复杂,其中page 指针通常指向将要进行scatter gather 操作的buffer.而length 表示<br />
buffer 的长度,<strong>of</strong>fset 表示buffer 在page 内的偏移量.225 行,定义一个struct scatterlist 指针sg,然<br />
后<br />
令她指向(struct scatterlist*)srb->request_buffer+*index,搜索一下内核代码就可以知道,每次<br />
*index 都是被初始化为0 然后才调用usb_stor_access_xfer_buf()的,233 行,cnt 设为0,234 行开<br />
始<br />
进入循环,循环的条件是cnt 小于buflen,同时*index 小于srb->use_sg, srb->use_sg 咱们刚才说过<br />
了,只要她不是0,那么她里边的冬冬就代表了scatter gather 传输时数组元素的个数.<br />
观众朋友们请注意,225 行这里让sg 等于srb->request_buffer,(当然还要加上*index,如果index 不<br />
为0 的话),那么request_buffer 究竟是什么?对于使用scatter/gather 传输的情况,request_buffer<br />
里<br />
边实际上是一个数组,每一个元素都是一个struct scatterlist 的指针,而每一个scatterlist 指针的page<br />
里边包含了一些page(而不是一个page),而<strong>of</strong>fset 里边包含的是每一个DMA buffer 的总的偏移量,她由<br />
两部分组成,高位部分标志着page 号,低位部分标志着具体某个page 中的偏移量,高位低位由<br />
PAGE_SHIFT 宏来划分,不同的硬件平台PAGE_SHIFT 值不一样,因为不同的硬件平台page 的大小也<br />
不<br />
一样,即这里的PAGE_SIZE 不一样,目前比较前卫的硬件平台其page size 有4k 或者8k 的,而<br />
PAGE_SHIFT 也就是12 或者13,换言之,sg-><strong>of</strong>fset 去掉低12 位或者低13 位就是page 号,而低12<br />
137<br />
位或者低13 位恰恰是在该page 内的偏移量.之所以可以把一个sg-><strong>of</strong>fset 起两个作用,正是因为page<br />
size 只需要12 位或者13 位就足够了,或者说偏移量本身只有12 位或者13 位,而一个int 型变量显然可<br />
以包含比12 位或13 位更多的信息.我们最终是要把buffer(即前面说的那个36 个bytes 的标准的<br />
INQUIRY data buffer)里边的冬冬copy 至DMA buffer 中,buffer 我们已经知道,她就是<br />
usb_stor_access_xfer_buf()函数传递进来的参数,而DMA buffer 在哪呢?只要我们知道她在哪个<br />
page 中,知道她的<strong>of</strong>fset,那么有一个函数可以帮助我们获得她对应的内核虚拟地址,而这个地址正是我们<br />
需要的,有了她,我们就能调用memcpy 函数来copy 数据了.所以235 行到238 行,就是计算出究竟是哪<br />
个page,究竟是多少<strong>of</strong>fset,后者用被赋给了unsigned int 变量p<strong>of</strong>f,*<strong>of</strong>fset 是<br />
usb_stor_access_xfer_buf()函数传递进来的参数,她也可以控制我们要传送数据的DMA buffer 对应<br />
的<strong>of</strong>fset,不过这里我们传递进来的是0.所以不去care.