struct usb_hcd
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相关推荐
- Linux那些事儿 之 戏说USB(31)驱动的生命线(三)
准备工作该做的都做了,别嫌太麻烦,什么事情都要经过这么一个阶段,大家都明白.现在看看第二阶段的重头戏,看看设备是怎么从Address进入Configured的.1501行,如果已经在Configure ...
- Linux那些事儿 之 戏说USB(30)驱动的生命线(二)
core配置设备使用的是message.c里的usb_set_configuration函数 int usb_set_configuration(struct usb_device *dev, int ...
- Linux那些事儿 之 戏说USB(26)设备的生命线(九)
聊完了struct usb_hcd和struct usb_bus,算是已经向HCD片儿区的老大们拜过山头了,接下来就该看看usb_submit_urb()最后的那个遗留问题usb_hcd_submit ...
- Linux那些事儿 之 戏说USB(25)设备的生命线(八)
回到struct usb_hcd,继续努力的往下看. 7行,又见kref,usb主机控制器的引用计数.struct usb_hcd也有自己专用的引用计数函数,看drivers/usb/core/hcd ...
- Linux那些事儿 之 戏说USB(24)设备的生命线(七)
算是进入了HCD的片儿区,这里的老大不是帮派头目也不是巡逻片儿警,而是几个结构.在HCD这个片儿区,这个山头儿,王中之王就是include/linux/usb/hcd.h里定义的struct usb_ ...
- Linux那些事儿 之 戏说USB(18)设备的生命线(一)
首先当然是你将usb设备连接在hub的某个端口上,hub检测到有设备连接了进来,它会为设备分配一个struct usb_device结构的对象并初始化,并调用设备模型提供的接口将设备添加到usb总线的 ...
- linux设备驱动之USB主机控制器驱动分析
http://www.cnblogs.com/sdphome/archive/2011/09/29/2195791.html 一:前言 Usb是一个很复杂的系统.在usb2.0规范中,将其定义成了一个 ...
- 《Linux总线、设备与驱动》USB设备发现机制
http://blog.csdn.net/tankai19880619/article/details/11639185 说明:本分析基于mstar801平台Linux2.6.35.11内核,其他内核 ...
- Linux USB 驱动开发(一)—— USB设备基础概念
http://blog.csdn.net/zqixiao_09/article/details/50984074 在终端用户看来,USB设备为主机提供了多种多样的附加功能,如文件传输,声音播放等,但对 ...
最新文章
- UTF-8 CPP的使用
- poi 拆分带图片的word_学会这2招,再多的“表格编号”都能轻松解决!【Word教程】...
- Oracle学习:视图与索引
- [Node.js]get/post请求
- Ajax基本案例详解之$.get的实现
- 用了这么久,你真的真的明白 HttpClient 的实现原理了吗?
- php数组是否存在数组,php判断数组中是否存在某值
- java php 通讯录,基于ssh/bs/java/asp.net/php/web通讯录管理系统
- 基于Vue的单页面格式化数据高亮编辑器组件:兼容json/xml/html/txt多种格式
- 合法免费下载电子书的站点整理收藏
- QThread: Destroyed while thread is still running的处理方法
- 第四周-C语言 圆柱体表面积计算
- 论文笔记1 MOEFL Multi-objective Evolutionary Federated Learning
- python中Matplotlib、seaborn中英文乱码终极解决方案
- hdu 5535 Cake 构造+记忆化搜索
- 35 岁程序员,年后第一天被辞退
- oracle distinct 用法
- onkeyup输入框限制
- 02 Python的自我介绍(数字、字符串、列表)
- 学讲普通话水平测试软件,普通话智能学习软件