20.2.1  USB主机驱动的整体结构

USB主机控制器有3种规格:OHCI (Open Host Controller Interface)、UHCI (Universal Host Controller Interface) 和EHCI (Enhanced Host Controller Interface)。OHCI驱动程序用来为非PC 系统上以及带有SiS和ALi芯片组的 PC 主板上的USB芯片提供支持。UHCI驱动程序多用来为大多数其他PC主板(包括 Intel和Via)上的USB芯片提供支持。EHCI由USB 2.0规范所提出,它兼容于OHCI 和UHCI。UHCI的硬件线路比OHCI简单,所以成本较低,但需要较复杂的驱动程序,CPU负荷稍重。本节将重点介绍嵌入式系统中常用的OHCI主机控制器驱动。

1.主机控制器驱动

在Linux内核中,用usb_hcd结构体描述USB主机控制器驱动,它包含USB主机控制器的“家务”信息、硬件资源、状态描述和用于操作主机控制器的hc_driver等,其定义如代码清单20.6所示。

代码清单20.6  usb_hcd结构体

1  struct usb_hcd
2  {
3    /* 管理“家务” */
4    struct usb_bus self;
5    const char *product_desc; /* 产品/厂商字符串 */
6    char irq_descr[24]; /* 驱动 + 总线 # */
7
8    struct timer_list rh_timer; /* 根Hub轮询 */
9    struct urb *status_urb; /* 目前的状态urb */
10
11   /* 硬件信息/状态 */
12   const struct hc_driver *driver; /* 硬件特定的钩子函数 */
13
14   /* 需要维护的标志 */
15   unsigned long flags;
16   #define HCD_FLAG_HW_ACCESSIBLE  0x00000001
17   #define HCD_FLAG_SAW_IRQ        0x00000002
18
19   unsigned rh_registered: 1; /* 根Hub注册? */
20
21   /* 下一个标志的采用只是“权益之计”,当所有HCDs支持新的根Hub轮询机制后将移除 */
22   unsigned uses_new_polling: 1;
23   unsigned poll_rh: 1; /* 轮询根Hub状态? */
24   unsigned poll_pending: 1; /* 状态已经改变? */
25
26   int irq; /* 被分配的irq */
27   void _ _iomem *regs; /* 设备内存和I/O */
28   u64 rsrc_start; /* 内存和I/O资源开始位置 */
29   u64 rsrc_len; /* 内存和I/O资源长度 */
30   unsigned power_budget; /* mA, 0 = 无限制 */
31
32   #define HCD_BUFFER_POOLS        4
33   struct dma_pool *pool[HCD_BUFFER_POOLS];
34
35   int state;
36   #define _ _ACTIVE                0x01
37   #define _ _SUSPEND               0x04
38   #define _ _TRANSIENT             0x80
39
40   #define HC_STATE_HALT           0
41   #define HC_STATE_RUNNING        (_ _ACTIVE)
42   #define HC_STATE_QUIESCING   (_ _SUSPEND|_ _TRANSIENT|_ _ACTIVE)
43   #define HC_STATE_RESUMING       (_ _SUSPEND|_ _TRANSIENT)
44   #define HC_STATE_SUSPENDED      (_ _SUSPEND)
45
46   #define HC_IS_RUNNING(state) ((state) & _ _ACTIVE)
47   #define HC_IS_SUSPENDED(state) ((state) & _ _SUSPEND)
48   /* 主机控制器驱动的私有数据 */
49   unsigned long hcd_priv[0]_ _attribute_ _((aligned(sizeof(unsigned long))));
50 };

usb_hcd中的hc_driver成员非常重要,它包含具体的用于操作主机控制器的钩子函数,其定义如代码清单20.7所示。

代码清单20.7  hc_driver结构体

1  struct hc_driver
2  {
3    const char *description; /* "ehci-hcd" 等 */
4    const char *product_desc; /* 产品/厂商字符串 */
5    size_t hcd_priv_size; /* 私有数据的大小 */
6
7    /* 中断处理函数 */
8    irqreturn_t(*irq)(struct usb_hcd *hcd, struct pt_regs *regs);
9
10   int flags;
11   #define HCD_MEMORY      0x0001      /* HC寄存器使用的内存和I/O */
12   #define HCD_USB11       0x0010          /* USB 1.1 */
13   #define HCD_USB2        0x0020          /* USB 2.0 */
14
15   /* 被调用以初始化HCD和根Hub */
16   int(*reset)(struct usb_hcd *hcd);
17   int(*start)(struct usb_hcd *hcd);
18
19   /* 挂起Hub后,进入D3(etc)前被调用 */
20   int(*suspend)(struct usb_hcd *hcd, pm_message_t message);
21
22   /* 在进入D0(etc)后,恢复Hub前调用 */
23   int(*resume)(struct usb_hcd *hcd);
24
25   /* 使HCD停止写内存和进行I/O操作 */
26   void(*stop)(struct usb_hcd *hcd);
27
28   /* 返回目前的帧数 */
29   int(*get_frame_number)(struct usb_hcd *hcd);
30
31   /* 管理I/O请求和设备状态 */
32   int(*urb_enqueue)(struct usb_hcd *hcd, struct usb_host_endpoint *ep, struct
33     urb *urb, gfp_t mem_flags);
34   int(*urb_dequeue)(struct usb_hcd *hcd, struct urb *urb);
35
36   /* 释放endpoint资源 */
37   void(*endpoint_disable)(struct usb_hcd *hcd, struct usb_host_endpoint *ep);
38
39   /* 根Hub支持 */
40   int(*hub_status_data)(struct usb_hcd *hcd, char *buf);
41   int(*hub_control)(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
42     char *buf, u16 wLength);
43   int(*bus_suspend)(struct usb_hcd*);
44   int(*bus_resume)(struct usb_hcd*);
45   int(*start_port_reset)(struct usb_hcd *, unsigned port_num);
46   void(*hub_irq_enable)(struct usb_hcd*);
47 };

在Linux内核中,使用如下函数来创建HCD:

struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
struct device *dev, char *bus_name);

如下函数被用来增加和移除HCD:

int usb_add_hcd(struct usb_hcd *hcd,
unsigned int irqnum, unsigned long irqflags);
void usb_remove_hcd(struct usb_hcd *hcd);

2.OHCI主机控制器驱动

OHCI HCD驱动属于HCD驱动的实例,它定义了一个ohci_hcd结构体,作为代码清单20.6给出的usb_hcd结构体的私有数据,这个结构体的定义如代码清单20.8所示。

代码清单20.8  ohci_hcd结构体

1  struct ohci_hcd
2  {
3    spinlock_t lock;
4
5    /* 与主机控制器通信的I/O内存(DMA一致) */
6    struct ohci_regs _ _iomem *regs;
7
8    /* 与主机控制器通信的主存(DMA一致) */
9    struct ohci_hcca *hcca;
10   dma_addr_t hcca_dma;
11
12   struct ed *ed_rm_list; /* 将被移除 */
13   struct ed *ed_bulktail; /* 批量队列尾 */
14   struct ed *ed_controltail; /* 控制队列尾 */
15   struct ed *periodic[NUM_INTS]; /* int_table“影子” */
16
17   /* OTG控制器和收发器需要软件交互,其他的外部收发器应该是软件透明的 */
18   struct otg_transceiver *transceiver;
19
20   /* 队列数据的内存管理 */
21   struct dma_pool *td_cache;
22   struct dma_pool *ed_cache;
23   struct td *td_hash[TD_HASH_SIZE];
24   struct list_head pending;
25
26   /* driver状态 */
27   int num_ports;
28   int load[NUM_INTS];
29   u32 hc_control; /* 主机控制器控制寄存器的复制 */
30   unsigned long next_statechange; /* 挂起/恢复 */
31   u32 fminterval; /* 被保存的寄存器 */
32
33   struct notifier_block reboot_notifier;
34   unsigned long flags;
35 };

使用如下内联函数可实现usb_hcd和ohci_hcd的相互转换:

struct ohci_hcd *hcd_to_ohci (struct usb_hcd *hcd);
struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci);

从usb_hcd得到ohci_hcd只是取得“私有”数据,而从ohci_hcd得到usb_hcd则是通过container_of()从结构体成员获得结构体指针。

使用如下函数可初始化OHCI主机控制器:

int ohci_init (struct ohci_hcd *ohci);

如下函数分别用于开启、停止及复位OHCI控制器:

int ohci_run (struct ohci_hcd *ohci);
void ohci_stop (struct usb_hcd *hcd);
void ohci_usb_reset (struct ohci_hcd *ohci);

OHCI主机控制器驱动的主机工作仍然是实现代码清单20.7给出的hc_driver结构体中的成员函数。

struct usb_hcd相关推荐

  1. Linux那些事儿 之 戏说USB(31)驱动的生命线(三)

    准备工作该做的都做了,别嫌太麻烦,什么事情都要经过这么一个阶段,大家都明白.现在看看第二阶段的重头戏,看看设备是怎么从Address进入Configured的.1501行,如果已经在Configure ...

  2. Linux那些事儿 之 戏说USB(30)驱动的生命线(二)

    core配置设备使用的是message.c里的usb_set_configuration函数 int usb_set_configuration(struct usb_device *dev, int ...

  3. Linux那些事儿 之 戏说USB(26)设备的生命线(九)

    聊完了struct usb_hcd和struct usb_bus,算是已经向HCD片儿区的老大们拜过山头了,接下来就该看看usb_submit_urb()最后的那个遗留问题usb_hcd_submit ...

  4. Linux那些事儿 之 戏说USB(25)设备的生命线(八)

    回到struct usb_hcd,继续努力的往下看. 7行,又见kref,usb主机控制器的引用计数.struct usb_hcd也有自己专用的引用计数函数,看drivers/usb/core/hcd ...

  5. Linux那些事儿 之 戏说USB(24)设备的生命线(七)

    算是进入了HCD的片儿区,这里的老大不是帮派头目也不是巡逻片儿警,而是几个结构.在HCD这个片儿区,这个山头儿,王中之王就是include/linux/usb/hcd.h里定义的struct usb_ ...

  6. Linux那些事儿 之 戏说USB(18)设备的生命线(一)

    首先当然是你将usb设备连接在hub的某个端口上,hub检测到有设备连接了进来,它会为设备分配一个struct usb_device结构的对象并初始化,并调用设备模型提供的接口将设备添加到usb总线的 ...

  7. linux设备驱动之USB主机控制器驱动分析

    http://www.cnblogs.com/sdphome/archive/2011/09/29/2195791.html 一:前言 Usb是一个很复杂的系统.在usb2.0规范中,将其定义成了一个 ...

  8. 《Linux总线、设备与驱动》USB设备发现机制

    http://blog.csdn.net/tankai19880619/article/details/11639185 说明:本分析基于mstar801平台Linux2.6.35.11内核,其他内核 ...

  9. Linux USB 驱动开发(一)—— USB设备基础概念

    http://blog.csdn.net/zqixiao_09/article/details/50984074 在终端用户看来,USB设备为主机提供了多种多样的附加功能,如文件传输,声音播放等,但对 ...

最新文章

  1. UTF-8 CPP的使用
  2. poi 拆分带图片的word_学会这2招,再多的“表格编号”都能轻松解决!【Word教程】...
  3. Oracle学习:视图与索引
  4. [Node.js]get/post请求
  5. Ajax基本案例详解之$.get的实现
  6. 用了这么久,你真的真的明白 HttpClient 的实现原理了吗?
  7. php数组是否存在数组,php判断数组中是否存在某值
  8. java php 通讯录,基于ssh/bs/java/asp.net/php/web通讯录管理系统
  9. 基于Vue的单页面格式化数据高亮编辑器组件:兼容json/xml/html/txt多种格式
  10. 合法免费下载电子书的站点整理收藏
  11. QThread: Destroyed while thread is still running的处理方法
  12. 第四周-C语言 圆柱体表面积计算
  13. 论文笔记1 MOEFL Multi-objective Evolutionary Federated Learning
  14. python中Matplotlib、seaborn中英文乱码终极解决方案
  15. hdu 5535 Cake 构造+记忆化搜索
  16. 35 岁程序员,年后第一天被辞退
  17. oracle distinct 用法
  18. onkeyup输入框限制
  19. 02 Python的自我介绍(数字、字符串、列表)
  20. 学讲普通话水平测试软件,普通话智能学习软件

热门文章

  1. 安其拉开门最快的服务器,《魔兽世界怀旧服》安其拉开门进度表 各服务器安其拉开门进度一览...
  2. python turtle color_Python turtle.color方法代碼示例
  3. cefsharp 启动白屏处理,启动页白屏及黑屏解决
  4. 赛马娘日服下载登录问题详解,日服赛马娘怎么登录?
  5. mac 访问阿里云服务器(简单粗暴)
  6. 查看windows是否激活
  7. BT宝塔80端口被占用,完美解决
  8. chrome浏览器无法访问百度
  9. CPU一级缓存、二级缓存、缓存命中率
  10. 30岁自学嵌入式找工作,可行吗?前景怎么样?