免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: projl
打印 上一主题 下一主题

《Linux 那些事儿之我是U盘》 [复制链接]

论坛徽章:
0
61 [报告]
发表于 2008-06-06 14:06 |只看该作者
1065 * - device: bits 8-14 ... bit positions known to uhci-hcd
1066 * - endpoint: bits 15-18 ... bit positions known to uhci-hcd
1067 * - Data0/1: bit 19 [Historical; now gone.
]
1068 * - lowspeed: bit 26 [Historical; now gone.
]
1069 * - pipe type: bits 30-31 (00 = isochronous, 01 = interrupt,
1070 * 10 = control, 11 = bulk)
1071
*
1072 * Why? Because it's arbitrary, and whatever encoding we select is really
1073 * up to us. This one happens to share a lot of bit positions with the UHCI
1074 * specification, so that much of the uhci driver can just mask the bits
1075 * appropriately.
1076 *
/
1077
1078 /* NOTE: these are not the standard USB_ENDPOINT_XFER_* values!! *
/
1079 #define PIPE_ISOCHRONOUS
0
1080 #define PIPE_INTERRUPT
1
1081 #define PIPE_CONTROL
2
1082 #define PIPE_BULK
3


咱们知道usb 有四种传输方式,等时传输,中断传输,控制传输,批量传输.一个设备能支持这四种传输中的
哪一种或者哪几种是设备本身的属性,在硬件设计的时候就确定了,比如一个纯粹的u 盘,她肯定是支持
Bulk 传输和Control 传输的.不同的传输要求有不同的端点,所以对于u 盘来说,她一定会有Bulk 端点和
Control 端点,于是就得使用相应的pipe 来跟不同的端点联系.在这里我们看到了四个宏,其
中,PIPE_ISOCHRONOUS 就是标志等时通道,PIPE_INTERRUPT 就是中断通道,PIPE_CONTROL 就是
控制通道,PIPE_BULK 就是BULK 通道.

另外__create_pipe 也是一个宏,由上面她的定义可以看出她为构造一个宏提供了设备号和端点号.在内
核里使用一个unsigned int 类型的变量来表征一个pipe, 其中8~14 位是设备号,即devnum,15~18 位
是端点号,即endpoint. 而咱们还看到有这么一个宏,USB_DIR_IN, 她是用来在pipe 里面标志数据传输方
向的,一个管道要么是只能输入要么是只能输出,鱼和熊掌不可兼得也.在include/linux/usb_ch9.h 中有
的:

24
25 /
*
26 * USB directions
27
*
28 * This bit flag is used in endpoint descriptors' bEndpointAddress field.
29 * It's also one of three fields in control requests bRequestType.
30 *
/
31 #define USB_DIR_OUT 0 /* to device *
/
32 #define USB_DIR_IN 0x80 /* to host *
/


在pipe 里面,第7 位(bit 7) 是表征方向的.所以这里0x80 也就是说让bit 7 为1,这就表示传输方向是
由设备向主机的,也就是所谓的in, 而如果这一位是0,就表示传输方向是由主机向设备的,也就是所谓的out.
而正是因为USB_DIR_OUT 是0,而USB_DIR_IN 是1,所以我们看到定义管道的时候只有用到了
USB_DIR_IN,而没有用到USB_DIR_OUT,因为她是0,任何数和0 相或都没有意义.

论坛徽章:
0
62 [报告]
发表于 2008-06-06 14:06 |只看该作者
这样,咱们就知道了,get_pipes 函数里741,742 行就是为us 的控制输入和控制输出管道赋了值,管道是
单向的,但是有一个例外,那就是控制端点,控制端点是双向的,比如你36号楼201这个端点既可以是往外寄
东西,也可以是别人给你寄东西而作为收件人地址.而usb 规范规定了,每一个usb 设备至少得有一个控制
端点,其端点号为0.其它端点有没有得看具体设备而定,但这个端点是放之四海而皆准的,不管你是什么设
备,只要你是usb 这条道上的,那你就得遵守这么一个规矩,没得商量.所以我们看到741,742 行里传递的
endpoint 变量值为0.显然其构造的两个管道就是对应这个0 号控制端点的.而接下来几行,就是构造bulk
管道和中断管道(如果有中断端点的话).

对于bulk 端点和中断端点(如果有的话),在她们的端点描述符里有这么一个字段,bEndpointAddress,
这个字段共八位,但是她包含了挺多信息的,比如这个端点是输入端点还是输出端点,比如这个端点的地
址,(总线枚举的时候给她分配的),以及这个端点的端点号,不过要取得她的端点号得用一个掩码
USB_ENDPOINT_NUMBER_MASK,让bEndpointAddress 和USB_ENDPOINT_NUMBER_MASK 相
与就能得到她的端点号.(就好比一份藏头诗,你得按着特定的方法才能读懂她,而这里特定的方法就是和
USB_ENDPOINT_NUMBER_MASK 这个掩码相与就行了.)

750 行,对于中断端点,您还得使用端点描述符中的bInterval 字段,表示端点的中断请求间隔时间.

至此,get_pipes 函数结束了,信息都保存到了us里面.下面us该发挥她的作用了.回到storage_probe()
函数,998 行,把us作为参数传递给了usb_stor_acquire_resources() 函数.而这个函数才是故事的高潮.
每一个有识之士在看过这个函数之后就会豁然开朗,都会感慨,一下子就看到了春天,看到了光明,原来
Linux 中的设备驱动程序就是这么工作的啊!

996
997 /* Acquire all the other resources and add the host *
/
998 result = usb_stor_acquire_resources(us)
;
999 if (result)


1000 goto BadDevice;
1001 result = scsi_add_host(us->host, &intf->dev)
;
1002 if (result)
{
1003 printk(KERN_WARNING USB_STORAGE
1004 "Unable to add the scsi host\n")
;
1005 goto BadDevice;
1006
}


我们来看usb_stor_acquire_resources 函数.它被定义于drivers/usb/storage/usb.c 中:

755 /* Initialize all the dynamic resources we need *
/
756 static int usb_stor_acquire_resources(struct us_data *us)
757
{
758 int p;
759
760


us->current_urb = usb_alloc_urb(0, GFP_KERNEL)
;
761


if (!us->current_urb)
{
762


US_DEBUGP("URB allocation failed\n")
;
763


return -ENOMEM;

论坛徽章:
0
63 [报告]
发表于 2008-06-06 14:07 |只看该作者
764
}
765
766 /* Lock the device while we carry out the next two operations *
/
767 down(&us->dev_semaphore)
;
768
769 /* For bulk-only devices, determine the max LUN value *
/
770 if (us->protocol == US_PR_BULK)
{
771 p = usb_stor_Bulk_max_lun(us)
;
772 if (p < 0)
{
773 up(&us->dev_semaphore)
;
774 return p;
775
}
776 us->max_lun = p;
777
}
778
779 /* Just before we start our control thread, initialize
780 * the device if it needs initialization *
/
781 if (us->unusual_dev->initFunction)
782 us->unusual_dev->initFunction(us)
;
783
784 up(&us->dev_semaphore)
;
785
786 /
*
787 * Since this is a new device, we need to register a SCSI
788 * host definition with the higher SCSI layers.
789 *
/
790 us->host = scsi_host_alloc(&usb_stor_host_template, sizeof(us))
;
791 if (!us->host)
{
792 printk(KERN_WARNING USB_STORAGE
793 "Unable to allocate the scsi host\n")
;
794 return -EBUSY;
795
}
796
797 /* Set the hostdata to prepare for scanning *
/
798 us->host->hostdata[0] = (unsigned long) us;
799
800 /* Start up our control thread *
/
801 p = kernel_thread(usb_stor_control_thread, us, CLONE_VM)
;
802 if (p < 0)
{
803 printk(KERN_WARNING USB_STORAGE
804 "Unable to start control thread\n")
;
805 return p;
806
}
807 us->pid = p;

论坛徽章:
0
64 [报告]
发表于 2008-06-06 14:08 |只看该作者
808

809

/* Wait for the thread to start *
/
810


wait_for_completion(&(us->notify))
;
811
812 return 0;
813
}


待到山花浪漫时,她在丛中笑.一个悟性高的人应该一眼就能从这个函数中找出那行在丛中笑的代码来,
没错,她就是801 行,kernel_thread, 这个函数造就了许多的经典的Linux 内核模块,正是因为她的存
在,Linux 中某些设备驱动程序的编写变得非常简单.可以说,对某些设备驱动程序来说,kernel_thread 几
乎是整个driver 的灵魂,或者说是该Linux 内核模块的灵魂.不管她隐藏的多么深,她总像漆黑中的萤火虫,
那样的鲜明,那样的出众.甚至不夸张的说,对于很多模块来说,只要找到kernel_thread 这一行,基本上你就
知道这个模块是怎么工作的了.

传说中的URB

有人问,怎么写个驱动写这么久啊?有完没完啊?此水何时休?此恨何时已?

的确,一路走来,大家都不容易,但既然已经走到今天,我们能做的也只有是坚持下去.十年之前,我不认识
你,你不属于我,但十年之后我依然记得那一年(1997 年),我的一个中学校友的那一句:不管前面是地雷阵还
是万丈深渊,我(们)都将一往无前,义无反顾,鞠躬尽瘁,死而后已.这个人叫朱镕基,毕业于长沙市一中.

usb_stor_acquire_resources, 从名字上来看,获取资源.什么资源?网名为爬上墙头等红杏的朋友不禁
表示出了一些好奇,之前不是申请了一大堆内存了吗?写个usb 设备驱动程序怎么那么麻烦啊?不是专门为
usb mass storage 设备准备了一个struct us_data 这么一个结构体了吗?不是说故事已经到高潮了吗?

周润发说得好,我还刚上路呢.没错,如果你以为看到这里你已经对usb 设备驱动程序有了足够的认识,认
为接下来的代码已经没有必要再分析了,那么,我只想说,上帝创造世界的计划中,未必包括使你会写usb 设
备驱动程序.

的确,别看usb_stor_acquire_resources 的代码不多,每一行都有每一行的故事.本节我们只讲其中的
一行代码,没错,就是一行代码,因为我们需要隆重推出一个名词,一个响当当的名字,她就是传说中的urb,全
称usb request block.usb 设备需要通信,要传递数据,就需要使用urb,确切的说,应该是usb 设备驱动程
序使用urb.实际上,作为usb 设备驱动,它本身并不能直接操纵数据的传输,在usb 这个大观园里,外接设备
永远都是配角,真正的核心只是usb core,而真正负责调度的是usb host controller, 这个您通常看不见的
usb 主机控制器芯片,他俨然是usb 大观园中的大管家.设备驱动要发送信息,所需要做的是建立一个urb 数
据结构,并把这个数据结构交给核心层,而核心层会为所有设备统一完成调度,而设备在提交了urb 之后需要
做的,只是等待,等待,在那漫漫长夜中等待.别急,我们慢慢来.

760 行,一条赋值语句,等号左边,us->current_urb,等号右边,usb_alloc_urb 函数被调用.如果说
struct us_data 是usb mass storage 中的主角,那么struct urb 将毫无争议的成为整个usb 子系统中
的主角. Linux 中所有的usb 设备驱动,都必然也必须要使用urb.那么urb 究竟长成什么样呢?她是如芙蓉
姐姐那么婀娜多姿呢,又亦或是如林志玲那般无公害性感呢?在include/linux/usb.h 中能找到她的靓照:

论坛徽章:
0
65 [报告]
发表于 2008-06-06 14:08 |只看该作者
614 /**
615 * struct urb - USB Request Block
616 * @urb_list: For use by current owner of the URB.
617 * @pipe: Holds endpoint number, direction, type, and more.
618 * Create these values with the eight macros available;
619 * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl"
620 * (control), "bulk", "int" (interrupt), or "iso" (isochronous).
621 * For example usb_sndbulkpipe() or usb_rcvintpipe(). Endpoint
622 * numbers range from zero to fifteen. Note that "in" endpoint two
623 * is a different endpoint (and pipe) from "out" endpoint two.
624 * The current configuration controls the existence, type, and
625 * maximum packet size of any given endpoint.
626 * @dev: Identifies the USB device to perform the request.
627 * @status: This is read in non-iso completion functions to get the
628 * status of the particular request. ISO requests only use it
629 * to tell whether the URB was unlinked; detailed status for
630 * each frame is in the fields of the iso_frame-desc.
631 * @transfer_flags: A variety of flags may be used to affect how URB
632 * submission, unlinking, or operation are handled. Different
633 * kinds of URB can use different flags.
634 * @transfer_buffer: This identifies the buffer to (or from) which
635 * the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP
636 * is set). This buffer must be suitable for DMA; allocate it with
637 * kmalloc() or equivalent. For transfers to "in" endpoints, contents
638 * of this buffer will be modified. This buffer is used for the data
639 * stage of control transfers.
640 * @transfer_dma: When transfer_flags includes URB_NO_TRANSFER_DMA_MAP,
641 * the device driver is saying that it provided this DMA address,
642 * which the host controller driver should use in preference to the
643 * transfer_buffer.
644 * @transfer_buffer_length: How big is transfer_buffer. The transfer may
645 * be broken up into chunks according to the current maximum packet
646 * size for the endpoint, which is a function of the configuration
647 * and is encoded in the pipe. When the length is zero, neither
648 * transfer_buffer nor transfer_dma is used.
649 * @actual_length: This is read in non-iso completion functions, and
650 * it tells how many bytes (out of transfer_buffer_length) were
651 * transferred. It will normally be the same as requested, unless
652 * either an error was reported or a short read was performed.
653 * The URB_SHORT_NOT_OK transfer flag may be used to make such
654 * short reads be reported as errors.
655 * @setup_packet: Only used for control transfers, this points to eight bytes
656 * of setup data. Control transfers always start by sending this data
657 * to the device. Then transfer_buffer is read or written, if needed.

论坛徽章:
0
66 [报告]
发表于 2008-06-06 14:09 |只看该作者
658 * @setup_dma: For control transfers with URB_NO_SETUP_DMA_MAP set, the
659 * device driver has provided this DMA address for the setup packet.
660 * The host controller driver should use this in preference to
661 * setup_packet.
662 * @start_frame: Returns the initial frame for isochronous transfers.
663 * @number_of_packets: Lists the number of ISO transfer buffers.
664 * @interval: Specifies the polling interval for interrupt or isochronous
665 * transfers. The units are frames (milliseconds) for for full and low
666 * speed devices, and microframes (1/8 millisecond) for highspeed ones.
667 * @error_count: Returns the number of ISO transfers that reported errors.
668 * @context: For use in completion functions. This normally points to
669 * request-specific driver context.
670 * @complete: Completion handler. This URB is passed as the parameter to the
671 * completion function. The completion function may then do what
672 * it likes with the URB, including resubmitting or freeing it.
673 * @iso_frame_desc: Used to provide arrays of ISO transfer buffers and to
674 * collect the transfer status for each buffer.
675
*
676 * This structure identifies USB transfer requests. URBs must be allocated by
677 * calling usb_alloc_urb() and freed with a call to usb_free_urb()
.
678 * Initialization may be done using various usb_fill_*_urb() functions. URBs
679 * are submitted using usb_submit_urb(), and pending requests may be canceled
680 * using usb_unlink_urb() or usb_kill_urb()
.
681
*
682 * Data Transfer Buffers:
683
*
684 * Normally drivers provide I/O buffers allocated with kmalloc() or otherwise
685 * taken from the general page pool. That is provided by transfer_buffer
686 * (control requests also use setup_packet), and host controller drivers
687 * perform a dma mapping (and unmapping) for each buffer transferred. Those
688 * mapping operations can be expensive on some platforms (perhaps using a dma
689 * bounce buffer or talking to an IOMMU)
,
690 * although they're cheap on commodity x86 and ppc hardware.
691
*
692 * Alternatively, drivers may pass the URB_NO_xxx_DMA_MAP transfer flags,
693 * which tell the host controller driver that no such mapping is needed since
694 * the device driver is DMA-aware. For example, a device driver might
695 * allocate a DMA buffer with usb_buffer_alloc() or call usb_buffer_map()
.
696 * When these transfer flags are provided, host controller drivers will
697 * attempt to use the dma addresses found in the transfer_dma and/or
698 * setup_dma fields rather than determining a dma address themselves. (Note
699 * that transfer_buffer and setup_packet must still be set because not all
700 * host controllers use DMA, nor do virtual root hubs)
.
701
*

论坛徽章:
0
67 [报告]
发表于 2008-06-06 14:09 |只看该作者
702 * Initialization:
703 *
704 * All URBs submitted must initialize the dev, pipe, transfer_flags (may be
705 * zero), and complete fields.
706 * The URB_ASYNC_UNLINK transfer flag affects later invocations of
707 * the usb_unlink_urb() routine. Note: Failure to set URB_ASYNC_UNLINK
708 * with usb_unlink_urb() is deprecated. For synchronous unlinks use
709 * usb_kill_urb() instead.
710 *
711 * All URBs must also initialize
712 * transfer_buffer and transfer_buffer_length. They may provide the
713 * URB_SHORT_NOT_OK transfer flag, indicating that short reads are
714 * to be treated as errors; that flag is invalid for write requests.
715 *
716 * Bulk URBs may
717 * use the URB_ZERO_PACKET transfer flag, indicating that bulk OUT transfers
718 * should always terminate with a short packet, even if it means adding an
719 * extra zero length packet.
720 *
721 * Control URBs must provide a setup_packet. The setup_packet and
722 * transfer_buffer may each be mapped for DMA or not, independently of
723 * the other. The transfer_flags bits URB_NO_TRANSFER_DMA_MAP and
724 * URB_NO_SETUP_DMA_MAP indicate which buffers have already been mapped.
725 * URB_NO_SETUP_DMA_MAP is ignored for non-control URBs.
726 *
727 * Interrupt URBs must provide an interval, saying how often (in milliseconds
728 * or, for highspeed devices, 125 microsecond units)
729 * to poll for transfers. After the URB has been submitted, the interval
730 * field reflects how the transfer was actually scheduled.
731 * The polling interval may be more frequent than requested.
732 * For example, some controllers have a maximum interval of 32 microseconds,
733 * while others support intervals of up to 1024 microseconds.
734 * Isochronous URBs also have transfer intervals. (Note that for isochronous
735 * endpoints, as well as high speed interrupt endpoints, the encoding of
736 * the transfer interval in the endpoint descriptor is logarithmic.
737 * Device drivers must convert that value to linear units themselves.)
738 *
739 * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling
740 * the host controller to schedule the transfer as soon as bandwidth
741 * utilization allows, and then set start_frame to reflect the actual frame
742 * selected during submission. Otherwise drivers must specify the start_frame
743 * and handle the case where the transfer can't begin then. However, drivers
744 * won't know how bandwidth is currently allocated, and while they can
745 * find the current frame using usb_get_current_frame_number () they can't

论坛徽章:
0
68 [报告]
发表于 2008-06-06 14:10 |只看该作者
746 * know the range for that frame number. (Ranges for frame counter values
747 * are HC-specific, and can go from 256 to 65536 frames from "now".
)
748
*
749 * Isochronous URBs have a different data transfer model, in part because
750 * the quality of service is only "best effort". Callers provide specially
751 * allocated URBs, with number_of_packets worth of iso_frame_desc structures
752 * at the end. Each such packet is an individual ISO transfer. Isochronous
753 * URBs are normally queued, submitted by drivers to arrange that
754 * transfers are at least double buffered, and then explicitly resubmitted
755 * in completion handlers, so
756 * that data (such as audio or video) streams at as constant a rate as the
757 * host controller scheduler can support.
758
*
759 * Completion Callbacks:
760
*
761 * The completion callback is made in_interrupt(), and one of the first
762 * things that a completion handler should do is check the status field.
763 * The status field is provided for all URBs. It is used to report
764 * unlinked URBs, and status for all non-ISO transfers. It should not
765 * be examined before the URB is returned to the completion handler.
766
*
767 * The context field is normally used to link URBs back to the relevant
768 * driver or request state.
769
*
770 * When the completion callback is invoked for non-isochronous URBs, the
771 * actual_length field tells how many bytes were transferred. This field
772 * is updated even when the URB terminated with an error or was unlinked.
773
*
774 * ISO transfer status is reported in the status and actual_length fields
775 * of the iso_frame_desc array, and the number of errors is reported in
776 * error_count. Completion callbacks for ISO transfers will normally
777 * (re)submit URBs to ensure a constant transfer rate.
778 *
/
779 struct urb
780
{
781 /* private, usb core and host controller only fields in the urb *
/
782 struct kref kref; /* reference count of the URB *
/
783 spinlock_t lock; /* lock for the URB *
/
784 void *hcpriv; /* private data for host controller *
/
785 struct list_head urb_list; /* list pointer to all active urbs *
/
786 int bandwidth; /* bandwidth for INT/ISO request *
/
787 atomic_t use_count; /* concurrent submissions counter *
/
788 u8 reject; /* submissions will fail *
/

论坛徽章:
0
69 [报告]
发表于 2008-06-06 14:10 |只看该作者
790 /* public, documented fields in the urb that can be used by drivers */
791 struct usb_device *dev; /* (in) pointer to associated device */
792 unsigned int pipe; /* (in) pipe information */
793 int status; /* (return) non-ISO status */
794 unsigned int transfer_flags; /* (in) URB_SHORT_NOT_OK | ...*/
795 void *transfer_buffer; /* (in) associated data buffer */
796 dma_addr_t transfer_dma; /* (in) dma addr for transfer_buffer */
797 int transfer_buffer_length; /* (in) data buffer length */
798 int actual_length; /* (return) actual transfer length */
799 unsigned char *setup_packet; /* (in) setup packet (control only) */
800 dma_addr_t setup_dma; /* (in) dma addr for setup_packet */
801 int start_frame; /* (modify) start frame (ISO) */
802 int number_of_packets; /* (in) number of ISO packets */
803 int interval; /* (modify) transfer interval (INT/ISO) */
804 int error_count; /* (return) number of ISO errors */
805 void *context; /* (in) context for completion */
806 usb_complete_t complete; /* (in) completion routine */
807 struct usb_iso_packet_descriptor iso_frame_desc[0]; /* (in) ISO ONLY

*/
808 };

我们常常抱怨,Linux 内核源代码中注释太少了,以至于我们常常看不懂那些代码究竟是什么含义.
但,urb 让开发人员做足了文章,结构体struct urb 的定义不过30 行,而说明文字却用了足足160 余行.可
见urb 的江湖地位.有时候我真的怀疑这些写代码的人是不是以为自己的代码是按行计费的,这么一大串的
注释他写得不累我们看得还累呢.当然我们这里贴出来主要还是为了保持原汁原味,另一方面这个注释也说
得很清楚,对于每一个成员都解释了,而我们接下来将必然要用到urb 的许多个成员.

此刻,我们暂时不去理会这个结构体每一个元素的作用,只需要知道,一个urb包含了执行usb传输所需
要的所有信息.而作为驱动程序,要通信,就必须创建这么一个数据结构,并且为她赋好值,显然不同类型的传
输,需要对urb赋不同的值,然后将她提交给底层,完了底层的usb core会找到相应的usb host controller,
从而具体去实现数据的传输,传输完了之后,usb host controller 会通知设备驱动程序.

总之我们知道,760 行就是调用usb_alloc_urb() 申请了一个struct urb 结构体.关于
usb_alloc_urb() 这个函数,我们不打算讲,它是usb core 所提供的一个函数,来自
drivers/usb/core/urb.c,usb 开发人员的确是给足了urb 的面子,专门把和这个数据结构相关的代码整理
在这么一个文件中了.我们可以在include/linux/usb.h 中找到这个函数的声明,

917 extern struct urb *usb_alloc_urb(int iso_packets, int mem_flags);

这个函数的作用很明显,就是为一个urb结构体申请内存,它有两个参数,其中第一个iso_packets 用来
在等时传输的方式下指定你需要传输多少个包,对于非等时模式来说,这个参数直接使用0.另一个参数
mem_flags 就是一个flag,表征申请内存的方式,这个flag 将最终传递给kmalloc 函数,我们这里传递的
是GFP_KERNEL, 这个flag 是内存申请中最常用的,我们之前也用过,在为us 申请内存的时
候.usb_alloc_urb 最终将返回一个urb 指针,而us 的成员current_urb 也是一个struct urb 的指针,所
以就赋给它了,不过需要记住,usb_alloc_urb 除了申请内存以外,还对结构体作了初始化,结构体urb 被初

论坛徽章:
0
70 [报告]
发表于 2008-06-06 14:11 |只看该作者
始化为0,虽然这里我们没有把这个函数的代码贴出来,但你也千万不要以为写代码的人跟你我似的,申请变
量还能忘了初始化.同时,struct urb 中还有一个引用计数,以及一个自旋锁,这些也同样被初始化了.

所以,接下来我们就将和us->current_urb 打交道了.如果你对urb 究竟怎么用还有些困惑的话,可以
看看host controller 的代码,如果你不想看,那么我可以用一种你最能接受的方式告诉你,usb 是一种总线,
是总线它就要通信,我们现实生活中真正要使用的是设备,但是光有设备还不足以实现usb通信,于是世界上
有了usb host controller(usb 主机控制器),它来负责统一调度,这就好比北京的交警,北京这个城市里真
正需要的本来是车辆和行人,而光有车辆和行人,没有交警,那么这个城市里的车辆和行人必将乱套,于是诞
生了交警这么一个行业,交警站在路口统一来管理调度那混乱的交通.假如车辆和行人可以完全自觉遵守某
种规矩而来来往往于这个城市的每一个角落,每一个路口,那么交警就没有必要存在了.同样,假如设备能够
完全自觉的传递信息,每一个数据包都能到达它应该去的地方,那么我们根本就不需要有主机控制器这么一
个东西.然而,事实是,在北京,遵守交通规则的人不多,我相信每一个来过北京的人都会发现,在北京,闯红灯
是一种时尚.我常常对自己说,如果哪一天我没有闯红灯,那么由此可以推导出来,这一天我一定没有出门.同
样,在usb 的世界中,设备也总是那么的不守规矩,我们必须要设计一个东西出来管理来控制所有的usb 设
备的通信,这样,主机控制器就横空出世了.

那么设备和主机控制器的分工又是如何呢?硬件实现上我们就不说了,说点具体的,Linux 中,设备驱动
程序只要为每一次请求准备一个urb 结构体变量,把它填充好,(就是说赋上该赋的值)然后它调用usb core
提供的函数,把这个urb 传递给host controller,host controller 就会把各个设备驱动程序所提交的urb
统一规划,去执行每一个操作.而这期间,usb 设备驱动程序通常会进入睡眠,而一旦host controller 把urb
要做的事情给做完了,它会调用一个函数去唤醒usb 设备驱动程序,然后usb 设备驱动程序就可以继续往下
走了.这又好比我们学校里的师生关系.考试的时候,我们只管把试卷填好,然后我们交给老师,然后老师拿去
批改试卷,这期间我们除了等待别无选择,等待老师改完了试卷,告诉了我们分数,我们又继续我们的生活.当
然了,如果成绩不好,也许有些人的生活就不会继续了,在复旦,我们可以选择去曾经的绝情谷上吊,可以选择
去第四教学楼顶层跳下来,在交大,则可以去跳思源湖.同样,usb 设备驱动程序也是如此,如果urb 提交给
usb host 了,但是最终却没有成功执行,那么也许该usb 设备驱动程序的生命也就提前结束.不过这都是后
话,现在只要有个感性认识即可,稍后看到了就能更深刻的体会了,这种岗位分工的方式给我们编写设备驱动
程序带来了巨大的方便.

心锁

如果大家没意见的话,我们继续usb_stor_acquire_resources 函数.

761 至764 行,这没啥好说的吧.就是刚才urb 申请了之后判断是否申请成功了,如果指针为NULL 那么
就是失败了.直接返回-ENOMEM.别往下了.

767 行,哦,又一个家伙闪亮登场了,dev_semaphore, 这是一个信号量,在storage_probe 的最初始阶
段我们曾经见过,当时有这么一句话,这就是调用一个宏init_MUTEX 来初始化一个信号量,

943 init_MUTEX(&(us->dev_semaphore));

我们当时说了,等到用的时候再讲.不过现在的确是到用的时候了,不过,我还不想讲.曾经我天真的以为,
只要学了谭浩强的那本C 程序设计,即便不能写代码,也应该能够看懂代码.然而,后来我发现事实并非如此,
世界没错,我错了.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP