Linux usb主机控制器HC阅读
intel的UHCI
一种usb主机控制器的接口规范,遵守它的硬件称为UHCI主机控制器,Linux中,把这种硬件叫做HC,host controller,与之对应的软件,叫做HCD,hc driver,
depends on usb & pci:
它的内核软件模块代码是uhci-hcd.c
uhci_hcd_init初始化开始:
usb_disable函数:在启动参数cmdline,加入nousb参数可以禁止usb模块
kmalloc和kmem_cache_creat:slab分配器的接口函数,用于创建一个cache,之后可以使用kmem_cache_zalloc申请内存了
debugfs_creat_dir:虚拟的一个文件系统,挂载在/sys/kernel/debug下面
pci_register_driver:注册一个pci驱动
usb_hcd_pci_probe:pci驱动的开始
hcd的代码,一部分在core下,hcd-pci.c、hcd.c,公共的代码,,另一部分在host下面,具体的控制器代码,如uhci,xhci等
pci_enable_device:pci设备使用之前必须调用的,激活pci设备上的IO资源和内存资源
图中寄存器有必须也有非必须的,class就是必选的,usb的class code就是0x0C03
usb_creat_hcd:正式进入hcd,主要就是为了给struct usb_hcd申请内存空间并且初始化
struct hc_driver结构体描述一个主机控制器设备
struct usb_hcd结构体描述一个主机控制器驱动
一个主机控制器意味着一条总线,所以还有一个结构体:struct usb_bus
IO内存和IO端口
有处理器,内存和IO是独立编址独立寻址的,所以有了内存空间和IO空间,访问内存和IO空间要使用不同的指令,IO端口的物理地址被映射到IO地址空间,IO映射
嵌入式处理器中,只有一个地址空间,内存空间,那IO端口的物理地址就要被映射到内存地址空间中,内存映射
Linux中,IO Memory和IO ports都被视作一种资源,分别被记录在/proc/iomem和/proc/ioports中
要使用IO内存首先要申请(request_mem_region),然后再映射(ioremap或者ioremap_nocache)
usb_add_hcd:
1、hcd_buffer_creat:初始化一个buffer池,
DMA:直接内存访问,cpu直接和设备数据传输
usb主机控制器控制着一条usb总线,总线一项工作就是在内存和usb总线之间传输数据,这个过程不适用DMA就是PIO方式,使用DMA就似乎HCD这边先创建一个内存池,然后设备驱动可以直接使用
在hcd_buffer_creat中调用dma_pool_creat函数,去创建DMA池,结构体是struct dma_pool
2、使用dma_pool_alloc和dma_pool_free去从dma池中使用和释放,usb中对应usb_buffer_alloc和usb_buffer_free
控制器是否支持DMA操作,看dma_mask的值不为NULL
3、usb_register_bus: bus_map,一共有64位,可以有64条usb总线
class_device_create,/sys/class下创建了usb_host类
usb_notify_add_bus:牵涉内核的notify机制,常用的一种事件回调处理机制
主机控制器初始化
usb_alloc_dev:为root_hub申请一个struct usb_device结构体并初始化,root_hub的parent指针指向了controller本身
device_init_wakeup:第二个参数是1意味着把root_hub的wakeup能力打开,0可以关闭
uhci_init:struct uhci_hcd
hcd_to_uhci:uhci_hcd和usb_hcd之间的转换,
然后决定root_hub有几个端口了,端口号从0开始,UHCI的root_hub最多不能超过8个端口,最少有2个端口
继续回到usb_add_hcd中:
hcd->irq记录中断号,使用request_irq请求中断,中断句柄