基于Linux操作系统的视频采集卡驱动程序设计
4.2 驱动程序的实现
4.2.1 PCI驱动程序
本文采用的视频采集卡是基于PCI总线的,因此在这里首先讨论PCI驱动程序的结构。
PCI设备是无跳线设备,可在引导阶段自动配置。这样设备驱动程序必须能够访问设备中的配置信息以便完成初始化。对于PCI设备来说,这些工作无需探测就可以完成[1][5]。
所有的PCI设备都有至少256字节的地址空间,前64字节是标准化的,其余的是设备相关的。这个空间也叫做PCI配置空间,它包含厂商标识,设备标识,设备类别,基地址寄存器,中断引脚等等,编写PCI的驱动程序就是利用这些域与设备进行“沟通”。
尽管PCI设备千差万别,但是控制他们的结构基本是类似的。
1)为了正确注册到内核,所有的PCI驱动程序需要创建pci_driver结构体,该结构体由许多回调函数和变量组成。初始化该结构体如下:
struct pci_driver saa7146_v4l2_driver = {
name: "saa7146 v4l2",
id_table: saa7146_v4l2_pci_tbl,
probe: saa7146_v4l2_init_one,
remove: saa7146_v4l2_remove_one,
suspend: saa7146_v4l2_suspend,
resume: saa7146_v4l2_resume,
};
为了把struct pci_driver注册到PCI核心,需要调用以其为参数的pci_module_init函数:
pci_module_init(saa7146_v4l2_driver);
2)如果上述函数返回为0,表示初始化成功,此时在驱动程序可以访问PCI设备的任何设备资源之前(I/O区域或中断),驱动程序必须调用pci_enable_device函数:
int pci_enable_device(struct pci_dev *dev);
3)上述函数将激活设备,此时驱动程序就需要读取或写入三个地址空间:内存,I/O端口,配置空间。Linux把I/O空间和内存空间都看作是系统的资源,使用前必须申请,即在系统中进行登记,避免资源使用的混乱。简述如下:
首先调用pci_resource_start()和pci_resource_len()函数获取资源信息,然后调用 request_mem_region()函数分配I/O内存区域,为了确保该内存对内核而言是可访问的,必须还要建立映射,映射的建立由 ioremap()函数完成,这样设备驱动程序就可以访问任意的I/O内存地址。
4)与设备通信,即通过访问I/O内存的函数,诸如writel(),readl()等;以及进行I2C操作的函数对SAA7111a进行初始化。
4.2.2 驱动模块的设计与实现
采集卡驱动程序主要由saa7146_v4l2,v4l2_extension,saa7111a三个模块构成,这三个模块都要调用i2c- core模块(Kernel提供)中的函数,即它们依赖于i2c-core模块;saa7111a模块具体负责通过I2C控制SAA7111a芯片,v4l2_extension模块依赖于saa7146_v4l2模块,它把自己注册到saa7146核心模块中。
重要数据结构声明
采集设备的扩展部分结构:
struct saa7146_v4l2_extension{
char name[64]; /* 设备名 */
struct saa7146_v4l2_extension_ioctls* ioctls;
u32 irq_mask; /* 扩展部分处理的IRQ */
void (*irq_func)(struct capture_device*, u32* irq_mask);
/* 扩展部分的函数主要就是ioctl()用于实现各种类型硬件控制 */
int (*ioctl)(void *id, unsigned int cmd, void *arg);
};
采集设备核心结构:
struct capture_device{
struct v4l2_device v4l2;
struct v4l2_capability capability;
struct pci_dev *pci_device;
……
}
linux操作系统文章专题:linux操作系统详解(linux不再难懂)linux相关文章:linux教程
评论