深入浅出Linux设备驱动编程--复杂设备驱动
作者 佚名技术
来源 Linux系统
浏览
发布时间 2012-05-16
这里所说的复杂设备驱动涉及到PCI、USB、网络设备、块设备等(严格意义而言,这些设备在概念上并不并列,例如与块设备并列的是字符设备,而PCI、USB设备等都可能属于字符设备),这些设备的驱动中又涉及到一些与特定设备类型相关的较为复杂的数据结构和程序结构.本文将不对这些设备驱动的细节进行过多的介绍,仅仅进行轻描淡写的叙述. PCI 是The Peripheral Component Interconnect –Bus的缩写,CPU使用PCI桥chipset与PCI设备通信,PCI桥chipset处理了PCI子系统与内存子系统间的所有数据交互,PCI设备完全被从内存子系统分离出来.下图呈现了PCI子系统的原理: 每个PCI设备都有一个256字节的设备配置块,其中前64字节作为设备的ID和基本配置信息,Linux中提供了一组函数来处理PCI配置块.在PCI设备能得以使用前,Linux驱动程序需要从PCI设备配置块中的信息决定设备的特定参数,进行相关设置以便能正确操作该PCI设备. 一般的PCI设备初始化函数处理流程为: (1)检查内核是否支持PCI-Bios; (2)检查设备是否存在,获得设备的配置信息; 1~2这两步的例子如下: int pcidata_read_proc(char *buf, char **start, off_t offset, int len, int *eof, void *data) { int i, pos = 0; int bus, devfn; if (!pcibios_present()) return sprintf(buf, "No PCI bios presentn"); /* * This code is derived from "drivers/pci/pci.c". This means that * the GPL applies to this source file and credit is due to the * original authors (Drew Eckhardt, Frederic Potter, David * Mosberger-Tang) */ for (bus = 0; !bus; bus ) { /* only bus 0 :-) */ for (devfn = 0; devfn < 0x100 && pos < PAGE_SIZE / 2; devfn ) { struct pci_dev *dev = NULL; dev = pci_find_slot(bus, devfn); if (!dev) continue; /* Ok, we''ve found a device, copy its cfg space to the buffer*/ for (i = 0; i < 256; i = sizeof(u32), pos = sizeof(u32)) pci_read_config_dword(dev, i, (u32*)(buf pos)); pci_release_device(dev); /* 2.0 compatibility */ } } *eof = 1; return pos; } 其中使用的pci_find_slot()函数定义为: struct pci_dev *pci_find_slot (unsigned int bus, unsigned int devfn) { struct pci_dev *pptr = kmalloc(sizeof(*pptr), GFP_KERNEL); int index = 0; unsigned short vendor; int ret; if (!pptr) return NULL; pptr->index = index; /* 0 */ ret = pcibios_read_config_word(bus, devfn, PCI_VENDOR_ID, &vendor); if (ret /* == PCIBIOS_DEVICE_NOT_FOUND or whatever error */ || vendor==0xffff || vendor==0x0000) { kfree(pptr); return NULL; } printk("ok (%i, %i %x)n", bus, devfn, vendor); /* fill other fields */ pptr->bus = bus; pptr->devfn = devfn; pcibios_read_config_word(pptr->bus, pptr->devfn, PCI_VENDOR_ID, &pptr->vendor); pcibios_read_config_word(pptr->bus, pptr->devfn, PCI_DEVICE_ID, &pptr->device); return pptr; } (3)根据设备的配置信息申请I/O空间及IRQ资源; (4)注册设备. USB设备的驱动主要处理probe(探测)、disconnect(断开)函数及usb_device_id(设备信息)数据结构,如: static struct usb_device_id sample_id_table[] = { { USB_INTERFACE_INFO(3, 1, 1), driver_info: (unsigned long)"keyboard" } , { USB_INTERFACE_INFO( |
凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢! |
你可能对下面的文章感兴趣
关于深入浅出Linux设备驱动编程--复杂设备驱动的所有评论