07.06.2013 Views

Scsi - Index of

Scsi - Index of

Scsi - Index of

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

25 {<br />

26 x->done = 0;<br />

27 init_waitqueue_head(&x->wait);<br />

28 }<br />

她只是调用了init_waitqueue_head 去初始化一个等待队列.而struct completion 的定义也在上面已<br />

经列出.关于init_waitqueue_head 咱们将在下面的故事中专门进行描述.<br />

而接下来,都是在设置us 的current_urb 结构,咱们看161 行,transfer_flags 被设置成了<br />

URB_ASYNC_UNLINK | URB_NO_SETUP_DMA_MAP,其中URB_ASYNC_UNLINK 表明<br />

usb_unlink_urb()函数将被异步调用,不懂异步调用也没有关系,因为内核的发展是如此的迅速,这一点完<br />

全可以和上海的发展速度有得一拼,最新的内核中,人们已经很少用这个宏了,因为usb_unlink_urb已经是<br />

81<br />

异步调用的函数了,如果是同步调用,则可以使用另一个函数usb_kill_urb().这两个函数的作用就是取消<br />

一个urb 请求.同步调用用于这样一种情况,即函数执行过程中可以进入睡眠,满足一定条件再醒来继续执<br />

行,<br />

而异步调用则不会睡眠,那么这里之所以要设置URB_ASYNC_UNLINK,其目的就在于让<br />

usb_unlink_urb 是异步的执行,原因是,有的时候我们取消一个urb request 的时候是处在一种不能睡<br />

眠<br />

的上下文,比如后面我们会看到的处理超时的函数.我们在互联网上下载一个很大文件的时候,常常会遇到超<br />

时的情况,然后我们的请求就被中止了.对于usb 系统同样有这个问题,我们会给一个urb 设置超时,提交上<br />

去到了一定时间还没能传输好的话就意味着可能传输有问题,这种情况我们通常也会把这个urb 给取消掉.<br />

于是这里有两种情况,第一,我们提交了urb 之后就不管事了,我们等待,怎么等待?睡眠,我们的进程进入睡<br />

眠,换句话说在我们这个上下文情景中也就是storage_probe 函数睡了.如果不超时,那么万事大吉,urb<br />

执<br />

行完了之后我们的进程被唤醒,继续往下走.那么天下平安.但是第二种情况是,我们进入了睡眠,可是时间到<br />

了,urb 还没有执行完,那么超时函数会被执行,它就会去取消这个urb,如果说这个超时函数也可以睡眠,那<br />

就不得了了,天下大乱了,都睡了,谁干活?整个驱动不就瘫痪了!所以,这种情况下我们要调用的函数是不能<br />

睡眠的,也就是说必须是异步的.而usb_unlink_urb 内部会通过判断是否有URB_ASYNC_UNLINK 这<br />

么<br />

一个flag 被设置在了urb->transfer_flags 中,来选择是异步执行还是同步执行,实际上它的同步执行就<br />

是<br />

调用usb_kill_urb 而已.不过刚才说的,最新版的内核,比如2.6.21,它里边就把这两个函数彻底分开了,不<br />

用设这么一个flag,usb_unlink_urb 就是异步,usb_kill_urb 就是同步.<br />

而URB_NO_SETUP_DMA_MAP 表明,如果使用DMA 传输,则urb 中setup_dma 指针所指向的缓冲<br />

区是DMA 缓冲区,而不是setup_packet 所指向的缓冲区.接下来再或上<br />

URB_NO_TRANSFER_DMA_MAP 则表明,如果本urb 有一个DMA 缓冲区需要传输,则该缓冲区是<br />

transfer_dma 指针所指向的那个缓冲区,而不是transfer_buffer 指针所指向的那一个缓冲区.换句话<br />

说,<br />

如果没设置这两个DMA 的flag,那么usb core 就会使用setup_packet 和transfer_buffer 作为数据传<br />

输的缓冲区,然后下面两行就是把us 的iobuf_dma 和cr_dma 赋给了urb 的transfer_dma 和<br />

setup_dma.(157至160的注释表明,只要transfer_buffer 被赋了值,那就假设有DMA缓冲区需要传输,<br />

于是就去设URB_NO_TRANSFER_DMA_MAP.)关于DMA 这一段,因为比较难理解,所以我们多说几句.<br />

首先,这里是两个DMA 相关的flag,一个是URB_NO_SETUP_DMA_MAP,而另一个是<br />

URB_NO_TRANSFER_DMA_MAP.主意这两个是不一样的,前一个是专门为控制传输准备的,因为只有控<br />

制传输需要有这么一个setup 阶段需要准备一个setup packet.而我们把让setup_packet 指向了

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!