PCI网卡驱动程序分析(国嵌)
nt 2000pci设备驱动程序详解
常常有朋友问我关于pci驱动程序的问题,但是在和他们的交谈中我发现有一些问题非常重复,也没有什么特别的地方(真有什么特别的地方,我也搞不定:-)),对于一些问题,其实卡的结构非常普通,只要熟悉pci驱动程序的一些基本概念就可以解决的。
下面我把pci驱动程序的一些基本概念整理整理:首先讲一讲pci的配置空间。
这个概念本来是非常简单的,但是我这个有灌水的爱好,为了让文章能够更成体系,加上这一段。
pci的配置空间的结构不在这里重复,任何一本pci的书里都有。
对于pci的配置空间操作,我用过的操作系统中,linux下是最简单的,linux提供了许多函数,细节可看linux device driver。
我在这里简单的给出一个操作x86结构下pci的方法就结束这一段。
我在写第一个pci driver的时候是在dos下,最早我操作pci的方法就是用int 1a,需要bios支持,现在的主板是没有不支持得了。
后来我发现了另外一种方法,更为简单,int 1a的方法就记不得了,如果想知道,可以去查int 1a中断,要96年以后的书(int 1a是时钟,但是扩展为pci操作)。
由于不同操作系统提供的函数不同,使得代码可移植性变差,其实这些实现几乎都是基于BIOS的int 1a中断调用。
由于在不同系统中调用1a中断的实现也很不相同,而且一般都需要写驱动程序。
下面是我写的一个通用的操作PCI 配置空间的程序如下,该方法和int 1a内部机制相同,都是基于PCI规范实现的,只用到了端口操作。
代码如下:#include "stdio.h"#include "windows.h"DWORD DWORD_In(WORD io_Port){ DWORD val;_asm {mov dx,io_Portin eax,dxmov val,eax}return val;}DWORD DWORD_Out(WORD io_Port,DWORD val){_asm {mov dx,io_Portmov eax,valout dx,eax}return 0;}int main(){DWORD io_CF8; // port 0xcf8DWORD io_CFC; // port 0xcfcint i;io_CF8=0x80000000; //because the first bit is enable/disablefor(;;) //so must be 1,so from 0x800000000{DWORD_Out(0xcf8,io_CF8);io_CFC=DWORD_In(0xcfc);if (io_CFC!=0xffffffff) //if =0xffffffff,then is a invalid{ //bus number and device numberprintf(" PCI device has found,the pci config address=%lx ",io_CF8);printf("its Bus Numer is %lx ",(io_CF8&0x00ff0000)/0x10000);printf("its Device Number is %lx ",(io_CF8&0x0000f800)/0x800);printf("its Functin Number is %lx ",(io_CF8&0x700)/0x100);printf("this device's deviceID and vendorID=%lx ",io_CFC);for (i=0 ;i<=15;i++){DWORD_Out(0xcf8,io_CF8+4*i); //read DWORDswitch (i){case 0:printf("Device Number and Vendor Number =%lx");break;case 1:printf("Status and Command =");break;case 2:printf("Class Code and Revision ID=");break;case 3:printf("Bist and Header Type and Latency Timer and Cacne LineSize=");break;case 4: //PCI Configration has 6 base addresscase 5: //registercase 6:case 7:case 8:case 9:printf("Base Address Register=");break;case 10:case 11:case 13:case 14:printf("Reserved =");break;case 12:printf("Expansion ROM Base Address=");break;case 15: //attention:the interrupt IRQ= this result&0xffprintf("Max_Lat Min_Gnt Interrupt Pin Interrupt line=");break;}printf("%lx ",DWORD_In(0xcfc));}}io_CF8+=0x800;if (io_CF8>=0x80FFFF00)break;}return 0;} 这个程序是我97年的时候写的,后来就没有改过,在各种场合下用过很多次,我一般在写pcidriver for 9x/nt的时候都要先用它来scan一遍pci空间,看看硬件有没有问题。
LINUX PCI设备驱动程序详解
实际上,dev_t 是专用于应用程序的一个数据类型,内核使用的是 kdev_t 数据类型。kdev_t 与 dev_t 一样也是一个无符号短整型。现在可以关注 inode 结构了。
Linux 对每个创建文件都会在内存中创建一个对应的 inode 数据结构,i_rdev 字段值就是传 入的设备号(主设备号与次设备号的结合)。注意到 inode 结构中还有个 kdev_t 类型的变量: i_dev,这是这个节点所在设备的设备号。所在设备就是该节点所存储的设备,例如一般将 其存于磁盘上,则这个字段的值就是磁盘设备的设备号,这与该节点所代表设备的设备号是
static struct device_struct chrdevs[MAX_CHRDEV];
其中 device_struct 结构定义如下: struct device_struct { const char * name; struct file_operations * fops; };
这个结构用一个名称标志该驱动程序,这个名称是在用 register_chrdev 函数注册驱动程序时 传入的第二个参数,而 fops 字段则就是上面所说的那个内核指定的数据结构。这个字段的 值也是通过 register_chrdev 函数传入的,此函数调用的原形如下: int register_chrdev(unsigned int major, const char * name, struct file_operations *fops);
uboot pcie驱动原理
uboot pcie驱动原理摘要:1.介绍uboot pcie 驱动2.详述uboot pcie 驱动的原理3.总结uboot pcie 驱动的重要性正文:1.介绍uboot pcie 驱动Uboot 是一种通用的bootloader,广泛应用于各种嵌入式系统中。
它可以从NAND flash、NOR flash 或硬盘启动系统,并支持多种文件系统。
在嵌入式系统中,PCIe(Peripheral Component Interconnect Express)是一种常见的高速串行计算机扩展总线标准,用于连接主板上的中央处理器(CPU)和各种外部设备,如显卡、声卡、硬盘等。
Uboot pcie 驱动就是用于支持PCIe 设备的驱动程序。
2.详述uboot pcie 驱动的原理Uboot pcie 驱动的原理主要基于PCIe 协议。
PCIe 协议是一种点对点(peer-to-peer)的串行通信协议,通过数据传输和数据校验来实现设备之间的通信。
Uboot pcie 驱动的工作流程如下:(1)初始化:首先,Uboot 将PCIe 设备添加到系统中,并初始化相关硬件资源。
(2)配置:Uboot 根据PCIe 设备的类型和配置空间,生成相应的配置空间表。
配置空间表包含了设备的基本信息,如设备类型、设备地址、设备配置空间等。
(3)数据传输:Uboot 通过PCIe 协议,实现与PCIe 设备的数据传输。
数据传输过程中,Uboot 将设备所需的启动代码、设备驱动等文件传输到PCIe 设备中。
(4)设备启动:Uboot 将PCIe 设备的控制权交给操作系统,由操作系统完成后续的设备驱动加载和设备启动。
3.总结uboot pcie 驱动的重要性Uboot pcie 驱动在嵌入式系统中具有重要作用,主要表现在以下几点:(1)支持PCIe 设备的启动:Uboot pcie 驱动支持各种PCIe 设备的启动,使得嵌入式系统能够兼容更多的外部设备。
【原创】LinuxPCI驱动框架分析(一)
【原创】LinuxPCI驱动框架分析(一)背景•Read the fucking source code! --By 鲁迅•A picture is worth a thousand words. --By 高尔基说明:1.Kernel版本:4.142.ARM64处理器3.使用工具:Source Insight 3.5, Visio1. 概述从本文开始,将会针对PCIe专题来展开,涉及的内容包括:1.PCI/PCIe总线硬件;2.Linux PCI驱动核心框架;3.Linux PCI Host控制器驱动;不排除会包含PCIe外设驱动模块,一切随缘。
作为专题的第一篇,当然会先从硬件总线入手。
进入主题前,先讲点背景知识。
在PC时代,随着处理器的发展,经历了几代I/O总线的发展,解决的问题都是CPU主频提升与外部设备访问速度的问题:1.第一代总线包含ISA、EISA、VESA和Micro Channel等;2.第二代总线包含PCI、AGP、PCI-X等;3.第三代总线包含PCIe、mPCIe、m.2等;PCIe(PCI Express)是目前PC和嵌入式系统中最常用的高速总线,PCIe在PCI的基础上发展而来,在软件上PCIe与PCI是后向兼容的,PCI的系统软件可以用在PCIe系统中。
本文会分两部分展开,先介绍PCI总线,然后再介绍PCIe总线,方便在理解上的过渡,开始旅程吧。
2. PCI Local Bus2.1 PCI总线组成•PCI总线(Peripheral Component Interconnect,外部设备互联),由Intel公司提出,其主要功能是连接外部设备;•PCI Local Bus,PCI局部总线,局部总线技术是PC体系结构发展的一次变革,是在ISA总线和CPU总线之间增加的一级总线或管理层,可将一些高速外设,如图形卡、硬盘控制器等从ISA总线上卸下,而通过局部总线直接挂接在CPU总线上,使之与高速CPU总线相匹配。
嵌入式 loader 下 PCIe网卡驱动设计与实现
嵌入式loader下PCIe网卡驱动设计与实现么刚1 2张武2 王劲林21(中国科学院研究生院北京100080)2(中国科学院声学研究所北京 100080)摘要:某些嵌入式系统需要在Bootloader中驱动网卡完成特定的网络功能。
本文针对嵌入式系统存储容量有限的特点,提出了PCIe类网卡简化驱动模型,并给出一个具体实现。
对于嵌入式系统Bootloader下的网卡驱动开发有一定的借鉴作用。
关键词:PCI Express(周边原件高速扩展接口);嵌入式系统;网卡驱动The Design and Realization of Simplification Model for PCIe NICDriver in Embedded LoaderYao Gang1 2, Zhang Wu2 ,Wang Jinlin21(Graduate University of China Academy of Science. Beijing 100080)2(Institute of Acoustics, Chinese Academy of Science. Beijing 100080)Abstract:Some embedded systems need to drive the NIC to complete some network functions. According to the limited storage capacity in embedded systems, this article presents a simplification model for PCIe NICs, and gives an implementation. This will have some reference value for NIC driver design in embedded Bootloader.【Key Words】PCIe;embedded system;NIC driver基金资助项目名称:家庭网络与IP多媒体子系统网络融合中的关键技术研究。
PICE驱动介绍
PCI-E驱动介绍1.PCI-E的概述1.1背景本项目是2011年度Tick-Tock的Tick阶段,在Tick硬件架构已经发生了变化,硬件与X86主板的通信方式不再是通过网口+网线的方式来实现了,而是采用了PCI-E*4的桥来连接硬件与X86定制板。
因此为了能够使原来的软件能够使用新的硬件平台,所以需要在软件和硬件之间搭接一个PCI-E通信通路(硬件模块+软件驱动)。
与此同时,在Rocket项目上已经验证了原先的通信模式存在着带宽过低,成为Rocket 的主要性能瓶颈,因此本项目也要改进这一问题来提高整体的性能。
最后,根据以后的多核发展方向,本项目也要充分考虑到核间负载均衡的问题。
1.2驱动概述PCI-E驱动分为通用驱动(Generic Adaptor)和专用驱动(Customized Adaptor),其中通用驱动作为普适型网卡存在,为使用者提供基本的网络数据报文处理功能,专用驱动则针对Rocket项目,为Rocket的软件平台提供高效的驱动支撑。
2.相关概念2.1DMA读写为了提高DMA的效率和更好的实现硬件的流水,引入了RingBuffer。
DMA Ringbuffer采用在软件主内存和硬件Bar空间中建立一对映射的DMA Ringbuffer 描述符(Entry),此对DMARingbuffer描述符由软件和硬件协同管理。
DMA读过程DMA写过程DMA写主要体现在接收模块,DMA读主要体现在发送模块中。
2.2NAPI设备高速运行的特点使得设备发起中断请求的频率非常高,如不加以控制系统将陷入频繁的中断响应处理中,此时系统实际用于进行中断响应的时间将远远大于系统运行中断处理例程的时间,大量的时间浪费在对系统寄存器的压栈,弹栈,以及进程切换上。
这时系统将不会再响应任何的外部命令,从而系统处于一种假死的状态下,直到频繁的中断请求停止才能恢复正常,这样将严重的影响系统的操作及对外部命令的响应。
因此为了有效的解决系统进行中断处理时面临的问题,引入了NAPI(NEW API)机制,这是一种将单纯中断方式与单纯轮询方式相融合的方式。
Linux下PCI设备驱动程序开发---PCI驱动程序实现(三)
Linux下PCI设备驱动程序开发---PCI驱动程序实现(三)三、PCI驱动程序实现1. 关键数据结构PCI设备上有三种地址空间:PCI的I/O空间、PCI的存储空间和PCI的配置空间。
CPU可以访问PCI设备上的所有地址空间,其中I/O空间和存储空间提供给设备驱动程序使⽤,⽽配置空间则由Linux内核中的PCI初始化代码使⽤。
内核在启动时负责对所有PCI设备进⾏初始化,配置好所有的PCI设备,包括中断号以及I/O基址,并在⽂件/proc/pci中列出所有找到的PCI设备,以及这些设备的参数和属性。
Linux驱动程序通常使⽤结构(struct)来表⽰⼀种设备,⽽结构体中的变量则代表某⼀具体设备,该变量存放了与该设备相关的所有信息。
好的驱动程序都应该能驱动多个同种设备,每个设备之间⽤次设备号进⾏区分,如果采⽤结构数据来代表所有能由该驱动程序驱动的设备,那么就可以简单地使⽤数组下标来表⽰次设备号。
在PCI驱动程序中,下⾯⼏个关键数据结构起着⾮常核⼼的作⽤:pci_driver这个数据结构在⽂件include/linux/pci.h⾥,这是Linux内核版本2.4之后为新型的PCI设备驱动程序所添加的,其中最主要的是⽤于识别设备的id_table结构,以及⽤于检测设备的函数probe( )和卸载设备的函数remove( ):struct pci_driver {struct list_head node;char *name;const struct pci_device_id *id_table;int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);void (*remove) (struct pci_dev *dev);int (*save_state) (struct pci_dev *dev, u32 state);int (*suspend)(struct pci_dev *dev, u32 state);int (*resume) (struct pci_dev *dev);int (*enable_wake) (struct pci_dev *dev, u32 state, int enable);};pci_dev这个数据结构也在⽂件include/linux/pci.h⾥,它详细描述了⼀个PCI设备⼏乎所有的硬件信息,包括⼚商ID、设备ID、各种资源等:struct pci_dev {struct list_head global_list;struct list_head bus_list;struct pci_bus *bus;struct pci_bus *subordinate;void *sysdata;struct proc_dir_entry *procent;unsigned int devfn;unsigned short vendor;unsigned short device;unsigned short subsystem_vendor;unsigned short subsystem_device;unsigned int class;u8 hdr_type;u8 rom_base_reg;struct pci_driver *driver;void *driver_data;u64 dma_mask;u32 current_state;unsigned short vendor_compatible[DEVICE_COUNT_COMPATIBLE];unsigned short device_compatible[DEVICE_COUNT_COMPATIBLE];unsigned int irq;struct resource resource[DEVICE_COUNT_RESOURCE];struct resource dma_resource[DEVICE_COUNT_DMA];struct resource irq_resource[DEVICE_COUNT_IRQ];char name[80];char slot_name[8];int active;int ro;unsigned short regs;int (*prepare)(struct pci_dev *dev);int (*activate)(struct pci_dev *dev);int (*deactivate)(struct pci_dev *dev);};2. 基本框架在⽤模块⽅式实现PCI设备驱动程序时,通常⾄少要实现以下⼏个部分:初始化设备模块、设备打开模块、数据读写和控制模块、中断处理模块、设备释放模块、设备卸载模块。
PCI接口的驱动程序和配置空间
PCI卡有一个特殊的空间叫配置空间.该空间记录卡的中断,输入输出地址,内存映射,总线速度等一些PCI卡的信息.PCI的配置空间最多256字节,而PCI2.1标准规定的空间只有64字节,就是0x00-0x3F.RTL8019AS支持PCI2.1版本.所以空间只有64字节.超过64字节的空间0x40-0xFF为保留的.PCI配置空间的读出内容如下:PCI卡在复位之后(上电之后),它是处于待机状态的,卡属于禁止状态,就是说它还不能进行I/O或内存地址译码.必须先对它进行配置,才可以开始工作.配置就是对PCI配置空间进行一些读写的操作.对RTL8029As来说,最重要的有几个配置寄存器,一个是BAR,一个是Command.分别介绍.BAR:Base Address Register,地址译码寄存器,位于PCI配置空间的10-13H,读出内容如下:bit 31-5 :BAR31-5,在还没有进行设置之前,读出值是一个不确定的值.bit 4-2 :IOSIZE只读,为0,表示地址译码的大小为32个地址bit 1:只读,为0bit 0:IOIN ,只读,为1 ,表示该地址译码为I/O地址空间的译码.初始化的时候向该寄存器写入全0就可以了.写入全0之后,网卡的译码地址为: 0x00000000--0x0000001F 译码空间为I/O地址空间.可以看到网卡的32位的I/O地址译码的高3个字节是0,只有低位字节是需要变化的.那么在PCI的接口逻辑的设计里,我们可以固定高3个字节的地址为0,然后只变化低位字节的地址.这样可以大大简化接口逻辑.同时也简化单片机对PCI总线的操作.可以看到网卡的译码地址是I/O空间的地址译码,而没有内存地址的译码.那么对PCI卡进行内存译码的操作和接口是可以省略的.在我的PCI接口逻辑里,为了简化设计,没有进行内存地址寻址的逻辑设计.我的设计只支持PCI配置空间寻址和I/O地址空间寻址.I/O地址寻址空间也限制在0x00000000--0x000000FF范围内,最多支持256个I/O地址.而RTL8029AS只用了其中的32个地址.设置完BAR之后,网卡实际上还没有开始工作. 还需要设置命令寄存器.命令寄存器中只有最低位是可以写的,其他为只读.需要向该位IOEN写入1, 网卡才开始进行地址译码.设置完这两个寄存器,网卡就可以开始工作了.开始工作之后,不需要再进行PCI 配置空间的读写.为了简化用户的程序设计,我提供了6个函数用来进行PCI接口的驱动.两个进行PCI配置空间读写的函数:unsigned long read_config(unsigned char address)/*PCI 配置寄存器读,地址address必须是4的倍数0,4,8。
Linux驱动之PCI驱动程序分析
PCI网卡驱动程序分析(国嵌)1. 概述该分析报告针对 GNIC-II的千兆以太网卡,源程序文件:drivers/net/hamachi.c,由于该分析报告旨在对介绍PCI驱动程序结构,所以程序中关于硬件操作的具体部分不作介绍。
2. 初始化static int __init hamachi_init (void){if (pci_register_driver(&hamachi_driver) > 0)return 0;pci_unregister_driver(&hamachi_driver);return -ENODEV;}在模块初始化时采用pci_register_driver注册pci驱动程序。
static struct pci_driver hamachi_driver = {name: DRV_NAME,id_table: hamachi_pci_tbl,probe: hamachi_init_one,remove:__devexit_p(hamachi_remove_one),};static struct pci_device_id hamachi_pci_tbl[] __initdata = {{ 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, },}该表记录的是该驱动能够支持的PCI设备,分别是厂商号,设备号,子厂商号,子设备号,其中子厂商号,子设备号为PCI_ANY_ID,表示支持各种子类型。
该表到底有什么实际用处?(通过分析函数pci_register_driver得出结论)probe: hamachi_init_one (该函数的调用时机可通过分析pci_register_driver得出)static int __init hamachi_init_one (struct pci_dev *pdev,const struct pci_device_id *ent) {/* 使能PCI设备 */if (pci_enable_device(pdev)) {ret = -EIO;goto err_out;}/* 获取基地址 */ioaddr = pci_resource_start(pdev, 0);/* 申请将要使用的地址空间 */i = pci_request_regions(pdev, DRV_NAME);if (i) return i;/* 获取中断号 */irq = pdev->irq;/* 思考为什么这里要使用ioremap? */ioaddr = (long) ioremap(ioaddr, 0x400);if (!ioaddr)goto err_out_release;dev = alloc_etherdev(sizeof(struct hamachi_private));if (!dev)goto err_out_iounmap;SET_MODULE_OWNER(dev);/* 硬件相关操作,省略 *//* The Hamachi-specific entries in the device structure. */dev->open = &hamachi_open;dev->hard_start_xmit = &hamachi_start_xmit;dev->stop = &hamachi_close;dev->get_stats = &hamachi_get_stats;dev->set_multicast_list = &set_rx_mode;dev->do_ioctl = &netdev_ioctl;dev->tx_timeout = &hamachi_tx_timeout;dev->watchdog_timeo = TX_TIMEOUT;if (mtu)dev->mtu = mtu;i = register_netdev(dev);if (i) {ret = i;goto err_out_unmap_rx;}/* Configure gigabit autonegotiation. */writew(0x0400, ioaddr + ANXchngCtrl); /* Enable legacy links. */writew(0x08e0, ioaddr + ANAdvertise); /* Set our advertise word. */writew(0x1000, ioaddr + ANCtrl);card_idx++;return 0;}。
uboot pcie驱动原理
uboot pcie驱动原理摘要:1.PCIe驱动概述2.Uboot中PCIe驱动的实现3.PCIe驱动的应用场景和优势4.总结正文:【1】PCIe驱动概述PCIe(Peripheral Component Interconnect Express)是一种高速串行计算机扩展总线标准,主要用于连接主板上的中央处理器(CPU)和各种外部设备,如显卡、声卡、网卡等。
PCIe驱动程序是操作系统中用于控制和管理PCIe设备的软件模块,它负责实现设备与CPU之间的数据传输和通信。
【2】Uboot中PCIe驱动的实现Uboot是一种通用的bootloader程序,广泛应用于嵌入式系统。
在Uboot中,PCIe驱动程序主要包括以下几个部分:1.设备树(Device Tree):描述了系统中PCIe设备的基本信息和配置。
2.PCIe设备驱动框架:提供了一组通用的API,用于实现PCIe设备的访问和控制。
3.具体设备驱动:根据不同PCIe设备的特性,编写相应的设备驱动模块。
4.初始化与退出:在系统启动时,初始化PCIe设备并提供相应的驱动;在系统退出时,正确地卸载和关闭设备。
【3】PCIe驱动的应用场景和优势1.应用场景:PCIe驱动广泛应用于服务器、工作站、嵌入式设备等领域,支持多种硬件设备和外设的接入。
2.优势:- 高带宽:PCIe总线支持多种数据传输速率,如Gen1(2.5 GT/s)、Gen2(5.0 GT/s)和Gen3(8.0 GT/s)等,满足高性能设备的需求。
- 热插拔:PCIe设备支持热插拔,方便用户在不关机的情况下更换或升级硬件设备。
- 兼容性:PCIe驱动程序遵循统一的规范,可在不同操作系统和硬件平台上运行。
- 稳定可靠:PCIe总线采用差分信号传输,具有抗干扰能力强、传输稳定等特点。
【4】总结PCIe驱动程序是嵌入式系统中不可或缺的一部分,它为用户提供了高性能、稳定可靠的硬件设备访问手段。
通过Uboot中PCIe驱动的实现,我们可以更好地管理和控制各类PCIe设备,满足不同应用场景的需求。
嵌入式Linux下PCIE数据采集卡驱动开发
电子科技大学UNIVERSITY OF ELECTRONIC SCIENCE AND TECHNOLOGY OF CHINA 硕士学位论文MASTER THESIS论文题目嵌入式Linux下PCIE数据采集卡驱动开发学科专业测试计量技术及仪器学号201021070218作者姓名周小波指导教师谢永乐教授分类号密级UDC注1学位论文嵌入式Linux下PCIE数据采集卡驱动开发(题名和副题名)周小波(作者姓名)指导教师谢永乐教授电子科技大学成都(姓名、职称、单位名称)申请学位级别硕士学科专业测试计量技术及仪器提交论文日2013.5.20 论文答辩日期2013.5.30学位授予单位和日期电子科技大学2013年6 月日答辩委员会主席评阅人注1:注明《国际十进分类法UDC》的类号。
DRIVER DEVELOPMENT OF PCIE DATA ACQUISITION CARD IN EMBEDDED LINUXA Thesis Submitted toUniversity of Electronic Science and Technology of ChinaMajor: Measuring&Testing Technology and Instruments Author: Xiaobo ZhouAdvisor: Prof. Yongle XieSchool: School of Automation Engineering独创性声明本人声明所呈交的学位论文是本人在导师指导下进行的研究工作及取得的研究成果。
据我所知,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果,也不包含为获得电子科技大学或其它教育机构的学位或证书而使用过的材料。
与我一同工作的同志对本研究所做的任何贡献均已在论文中作了明确的说明并表示谢意。
作者签名:日期:年月日论文使用授权本学位论文作者完全了解电子科技大学有关保留、使用学位论文的规定,有权保留并向国家有关部门或机构送交论文的复印件和磁盘,允许论文被查阅和借阅。
嵌入式PCI网卡驱动程序的设计与优化
嵌入式PCI网卡驱动程序的设计与优化
宋有泉;高小鹏;龙翔
【期刊名称】《计算机工程》
【年(卷),期】2007(033)002
【摘要】介绍了嵌入式VPN 网关ESG-1的基本情况,讨论了RTEMS的PCI网卡驱动程序的设计要点:采用服务线程进行网络中断处理;采用生产者-消费者模型对缓冲区进行管理;采用事件驱动机制实现了网卡驱动对多个相同网卡的支持.进一步讨论了驱动程序的内存拷贝优化问题和零拷贝技术.通过测试数据分析得出优化内存拷贝和使用零拷贝技术都能提高网卡驱动程序的性能.
【总页数】3页(P264-266)
【作者】宋有泉;高小鹏;龙翔
【作者单位】北京航空航天大学计算机学院,北京100083;北京航空航天大学计算机学院,北京100083;北京航空航天大学计算机学院,北京100083
【正文语种】中文
【中图分类】TP302.1
【相关文献】
1.基于S3C2410嵌入式系统RTL8019网卡驱动程序的实现 [J], 马宁;张明扬
2.VxWorks下PCI网卡驱动程序结构与实现 [J], 王守林;苏建华
3.嵌入式Arm-Linux系统的网卡驱动程序的分析与实现 [J], 谢红薇;宋春燕
4.基于嵌入式linux的无线网卡驱动程序 [J], 钱晓华;郭继红
5.基于PCI总线155 Mbps网卡及驱动程序的设计 [J], 陈冬松;路明玉
因版权原因,仅展示原文概要,查看原文内容请购买。
基于Linux PCI总线驱动模型的网卡驱动分析
基于Linux PCI总线驱动模型的网卡驱动分析总线概念:总线是一种传输信号的信道;总线是连接一个或多个导体的电气连线。
总线由电气接口和编程接口组成,我们重点关注编程接口。
PCI(Peripheral Component Interconnect)外围设备互联的简称,是在桌面及更大型的计算机上普遍使用的外设总线。
(驱动程序移植)PCI总线具有三个非常显著的优点:1、在计算机和外设间传输数据时具有更好的性能2、能够尽量独立于具体的平台3、可以方便地实现即插即用体系结构:从结构上,PCI总线是一种不依附于某个具体处理器的局部总线,它是在CPU和原来的系统总线之间的一级总线,具体由一个桥接电路实现对这一层的管理,并实现上下之间的接口以协调数据的传送。
系统的各个部分通过PCI总线和PCI-PCI桥连接在一起。
CPU和RAM通过PCI桥连接到PCI总线0(即主PCI总线),而具有PCI接口的显卡直接连接到主PCI总线上。
PCI-PCI桥是一个特殊的PCI设备,它负责将PCI总线0和PCI 总线1连接在一起。
图中连接到PCI1号总线上的是SCSI卡和以太网卡。
为了兼容旧的ISA总线标准,PCI总线还可以通过PCI-ISA桥来连接ISA总线,从而支持以前的ISA设备,图中ISA总线上连接一个多功能I/O控制器,用于控制键盘、鼠标和软驱等。
PCI设备寻址:(深度优先遍历)每个PCI设备由一个总线号、一个设备号和一个功能号确定。
PCI规范允许一个系统最多拥有256条总线,每条总线最多带32个设备,但每个设备可以是最多8个功能的多功能板(如一个音频设备带一个CD-ROM驱动器)/proc/iomem描述了系统中所有的设备I/O在内存地址空间上的映射。
dc400000-dc40ffff : 0000:02:01.0dc400000-dc40ffff是它所映射的内存空间地址0000:02:01.0是PCI外设的地址,它以冒号和逗号分隔开为4个部分(域16位+总线编号8位+设备号5位+功能号3位):0000表示域,02表示一个总线号,01表示设备号,0表示功能号。
35、PCI设备驱动简介
35、PCI设备驱动简介PCI(Peripheral Component Interconnect)总线标准是⼀种将系统外部设备连接起来的总线标准,速度可以达到133MB/s,它是PC中最重要的总线,其他总路线如ISA总线,USB总线等,都挂载在PCI总线上(通过桥接电路)。
由Intel推出的⼀种局部总线,为32位数据地址总线,可以扩展为64位,⽀持突发读写,及多组外围设备。
在PCI系统中,Host/PCI称为北桥,连接主处理器总线到基础PCI局部总线;PCI-ISA桥称为南桥,连接基础PCI总线到ISA总线。
其中南桥通常还含有中断控制器,IDE控制器,USB控制器和DMA控制器等设备。
图⽰ P412PCI有三个相互独⽴的物理地址空间:设备存储器地址空间,I/O地址空间和配置空间。
由于PCI⽀持设备即插即⽤,所以PCI设备不占⽤固定的内存地址空间或I/O地址空间,⽽是可以由操作系统决定其映射的基址。
PCI总线规范定义的配置Hha总长度为256个字节,配置信息按⼀定的顺序和⼤⼩依次存放。
根据读取PCI配置空间,可以得到PCI设备的所有资源。
[1]中讲述了多种读取PCI配置空间的⽅法,包括通过最基本的I/O端⼝操作进⾏读取,通过DDK提供的函数HalGetBusData,HalSetBusData在NT式驱动中进⾏读取,在WDM驱动中的读取⽅法,等。
⼀般程序所看到的内存指针都是虚拟内存,如果想操作物理内存,必须使⽤DDK提供的内核函数WRITE_REGISTER_XX,READ_REGISTER_XX系列函数。
MmAllocateContiguousMemory分配连续的物理地址,MmGetPhysicalAddress得到连续的物理内存地址。
代码#pragma PAGEDCODENTSTATUS InitMyPCI(IN PDEVICE_EXTENSION pdx,IN PCM_PARTIAL_RESOURCE_LIST list){PDEVICE_OBJECT fdo = pdx->fdo;ULONG vector;KIRQL irql;KINTERRUPT_MODE mode;KAFFINITY affinity;BOOLEAN irqshare;BOOLEAN gotinterrupt = FALSE;PHYSICAL_ADDRESS portbase;BOOLEAN gotport = FALSE;PCM_PARTIAL_RESOURCE_DESCRIPTOR resource = &list->PartialDescriptors[0];ULONG nres = list->Count;BOOLEAN IsMem0 = TRUE;for (ULONG i = 0; i < nres; ++i, ++resource){ // for each resourceswitch (resource->Type){ // switch on resource typecase CmResourceTypePort:portbase = resource->u.Port.Start;pdx->nports = resource->u.Port.Length;pdx->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0;gotport = TRUE;break;case CmResourceTypeMemory:if (IsMem0){pdx->MemBar0 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start,resource->u.Memory.Length,MmNonCached);pdx->nMem0 = resource->u.Memory.Length;IsMem0 = FALSE;}else{pdx->MemBar1 = (PUCHAR)MmMapIoSpace(resource->u.Memory.Start,resource->u.Memory.Length,MmNonCached);pdx->nMem1 = resource->u.Memory.Length;}break;case CmResourceTypeInterrupt:irql = (KIRQL) resource->u.Interrupt.Level;vector = resource->u.Interrupt.Vector;affinity = resource->u.Interrupt.Affinity;mode = (resource->Flags == CM_RESOURCE_INTERRUPT_LATCHED)Latched : LevelSensitive;irqshare = resource->ShareDisposition == CmResourceShareShared;gotinterrupt = TRUE;break;default:KdPrint(("Unexpected I/O resource type %d\n", resource->Type));break;} // switch on resource type} // for each resourceif (!(TRUE&& gotport&& gotinterrupt )){KdPrint((" Didn't get expected I/O resources\n"));return STATUS_DEVICE_CONFIGURATION_ERROR;}if (pdx->mappedport){ // map port address for RISC platformpdx->portbase = (PUCHAR) MmMapIoSpace(portbase, pdx->nports, MmNonCached);if (!pdx->mappedport){KdPrint(("Unable to map port range %I64X, length %X\n", portbase, pdx->nports));return STATUS_INSUFFICIENT_RESOURCES;}} // map port address for RISC platformelsepdx->portbase = (PUCHAR) portbase.QuadPart;NTSTATUS status = IoConnectInterrupt(&pdx->InterruptObject, (PKSERVICE_ROUTINE) OnInterrupt, (PVOID) pdx, NULL, vector, irql, irql, LevelSensitive, TRUE, affinity, FALSE);if (!NT_SUCCESS(status)){KdPrint(("IoConnectInterrupt failed - %X\n", status));if (pdx->portbase && pdx->mappedport)MmUnmapIoSpace(pdx->portbase, pdx->nports);pdx->portbase = NULL;return status;}#define IMAGE_LENGTH (640*480)//申请⼀段连续物理地址来读取图像PHYSICAL_ADDRESS maxAddress;maxAddress.u.LowPart = 0xFFFFFFFF;maxAddress.u.HighPart = 0;pdx->MemForImage = MmAllocateContiguousMemory(IMAGE_LENGTH,maxAddress);PHYSICAL_ADDRESS pycialAddressForImage = MmGetPhysicalAddress(pdx->MemForImage);WRITE_REGISTER_BUFFER_UCHAR((PUCHAR)pdx->MemBar0+0x10000,(PUCHAR)&pycialAddressForImage.u.LowPart,4);return STATUS_SUCCESS;}⽰例代码 P428参考[1] Windows 驱动开发技术详解,张帆。
pci转串口卡,主要问题(驱动蓝屏)故障分析
pci转串口卡,主要问题(驱动蓝屏)故障分析pci转串口卡,主要问题(驱动蓝屏)故障分析1.pci转串口卡诞生的原因随着计算机更新换代,串口、并口都不再集成。
而串口在实际生活中还是大量使用的。
这就产生了对pci转串口芯片的需求。
就产生了PCI转串口卡。
2.什么是PCI转串口卡其实就是用pci转串口芯片做成的,可以插在pci总线上的多串口板卡。
目前有的产品类型有:二串口、四串口、八串口、十六串口、三十二串口。
3.与其他类型板卡比较usb转串口卡:usb转串口芯片传输数据不稳定是业界共知的。
pcie转串口等类型。
pci是32位数据并行传输,pci-e是串行传输。
先做下计算:pci总线传输速率33.3Mhz ×32bit = 1056Mbps = 1.03Gbps最差情况下,pci可以读取串口数据可以达到258Mbps。
pcie 1x 在最理想情况下性能只提高4倍。
pcie 二代以上,性能就有很大的提升了。
3.pci转串口卡的2个重要的参数:PCI总线读写串口速度、FIFO 大小。
国内外PCI转串口的生产商有不少,相对来说国外的产品在性能上要比国内的产品高,这些性能包括PCI读写串口速度、FIFO大小。
国外生产商PCI转串口产品的FIFO大小一般是256byte,国内一般做在16byte。
因为串口的传输速度低,如果FIFO的空间大,串口的中断频率会下降4倍到32倍,可以节约计算机读取串口的时间,保证其他设备中断的正常运行。
如果串口占用中断时间多,就会造成计算机蓝屏等现象。
4.驱动的问题目前网上大多的问题是驱动安装好,没法使用。
主要是因为深圳地区的供应商为了降低成本,使用废旧的片子进行再生产造成的。
5.支持国产芯片:国内公司FIFO已做到256byte 和512byte我们最近使用了一颗融诚互通的板子,读写速度很快,很不错,查了下芯片的信息SIE745,才发现是国内新出的一家企业,搜到的公司信息:苏州积体电子SIET www. sjiti. com. cn 电话0512-********。
PCI总线论文:PCI总线 驱动程序 加密卡 ARM
PCI总线论文:基于PCI总线的嵌入式加密卡设计【中文摘要】当今世界计算机蓬勃发展,软件业日益更新,然而盗版软件随之而来。
面对软件的大量盗版,软件制造商门也采取了对策,那就是反盗版,怎样反盗版呢?方法就是对软件系统进行加密。
软件系统加密的手段有两种,一种是软件加密,一种是硬件加密。
目前,比较安全的加密方法是硬件加密,硬件加密技术也随着硬件技术的发展而发展。
市场上的硬件加密设备多种多样,各具特色。
只有采用最先进的技术才能设计出最安全、最可靠的硬件加密设备。
为此,我们研究了“基于PCI总线的嵌入式加密卡”本课题设计的“基于PCI总线的嵌入式加密卡”来源于泳池监控系统,采用PCI总线技术和嵌入式ARM 技术相结合,利用“代码移植”的加密原理,能够对软件系统的关键数据进行加密处理,并能配合软件系统实现其完整的功能,对防止软件盗版有着重要的意义。
本论文内容分四部分:第一部分介绍了本课题的研究意义、课题的来源、理论基础以及当前加密卡的发展状况;第二部分介绍了本加密卡的硬件设计,包括硬件电路的总体设计和三大电路模块的设计,三大分模块是:ARM处理器电路的设计、PCI总线电路的设计和双端口RAM电路的设计,这一部分详细的介绍了各个模块的外围电路设计;...【英文摘要】Recently, with the rapid development of computer technology, software industry is also developing, while it is occurred to pirate others software. In the face ofsuch phenome-non, software manufacturers take the corresponding countermeasures that is anti-piracy. How to avoid pirating? The only method is to encrypt for software system. These are two kinds of methods to encrypt software system, one is software encryption, and another is hardware encryption which is safer method. Hardware encryption technology...【关键词】PCI总线驱动程序加密卡 ARM【英文关键词】PCI Bus Driver program Encryption Card ARM【索购全文】联系Q1:138113721 Q2:139938848同时提供论文写作一对一辅导和论文发表服务.保过包发【目录】基于PCI总线的嵌入式加密卡设计摘要5-6ABSTRACT6-7第1章绪论10-17 1.1 课题意义10-11 1.2 课题来源11-13 1.3 课题理论基础13-16 1.3.1 加密卡的加密原理13 1.3.2 加密卡的发展13-14 1.3.3 PCI局部总线技术的发展14-15 1.3.4 嵌入式ARM技术的发展15-16 1.4 课题的研究任务16-17第2章加密卡的硬件电路设计17-38 2.1 加密卡硬件总体结构设计17-18 2.2 ARM处理器电路的设计18-21 2.2.1 Nano2410V2板简介19 2.2.2 ARM核心板外围电路的设计19-21 2.3 PCI总线电路的设计21-31 2.3.1 PCI总线和PCI9052接口芯片21-23 2.3.2PCI硬件电路的设计23-31 2.4 双端口RAM电路的设计31-36 2.4.1 CY7C133简介31-33 2.4.2 CY7C133外围电路的设计33-36 2.5 电路设计注意事项36-38第3章加密卡的软件设计38-57 3.1 加密卡软件总体结构设计38 3.2 PCI驱动程序的开发38-47 3.2.1 驱动工具的选取38-39 3.2.2 利用DriverStudio开发PCI驱动程序39-47 3.3 ARM核心板应用程序的开发47-52 3.3.1 Linux系统运行平台的搭建47-50 3.3.2 ARM应用程序的开发50-52 3.4 PC机应用程序的开发52-57 3.4.1 应用程序开发的基本思想52-53 3.4.2 应用程序与驱动程序之间的数据传输53-57第4章加密卡软件和硬件的综合调试57-66 4.1 PCI总线和双端口RAM通信的调试57-59 4.1.1 PCI驱动程序的安装与调试57 4.1.2 EEPROM配置信息的烧写57-58 4.1.3 PCI9052和双端口RAM间控制逻辑的调试58-59 4.2 ARM处理器和双端口RAM通信的调试59-64 4.3 PC机通过PCI总线和ARM处理器之间通信的调试64-66结论66-67参考文献67-69附录基于PCI总线的嵌入式加密卡实物图69-71致谢71。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
PCI网卡驱动程序分析
1.概述
该分析报告针对 GNIC-II的千兆以太网卡,源程序文件:drivers/net/hamachi.c,由于该分析报告旨在对介绍PCI驱动程序结构,所以程序中关于硬件操作的具体部分不作介绍。
下面就软件驱动做详细介绍,以供参考!
2.初始化
static int __init hamachi_init (void)
{
if (pci_register_driver(&hamachi_driver) > 0)
return 0;
pci_unregister_driver(&hamachi_driver);
return -ENODEV;
}
在模块初始化时采用pci_register_driver注册pci驱动程序。
static struct pci_driver hamachi_driver = {
name: DRV_NAME,
id_table: hamachi_pci_tbl,
probe: hamachi_init_one,
remove: __devexit_p(hamachi_remove_one), };
static struct pci_device_id hamachi_pci_tbl[]
__initdata = {
{ 0x1318, 0x0911, PCI_ANY_ID, PCI_ANY_ID, },
}
该表记录的是该驱动能够支持的PCI设备,分别是厂商号,设备号,子厂商号,子设备号,其中子厂商号,子设备号为PCI_ANY_ID,表示支持各种子类型。
该表到底有什么实际用处?(通过分析函数pci_register_driver得出结论)
probe: hamachi_init_one (该函数的调用时机可通过分析
pci_register_driver得出)
static int __init hamachi_init_one (struct pci_dev *pdev,
const struct pci_device_id *ent) {
/* 使能PCI设备 */
if (pci_enable_device(pdev)) {
ret = -EIO;
goto err_out;
}
/* 获取基地址 */
ioaddr = pci_resource_start(pdev, 0);
/* 申请将要使用的地址空间 */
i = pci_request_regions(pdev, DRV_NAME);
if (i) return i;
/* 获取中断号 */
irq = pdev->irq;
/* 思考为什么这里要使用ioremap? */
ioaddr = (long) ioremap(ioaddr, 0x400);
if (!ioaddr)
goto err_out_release;
dev = alloc_etherdev(sizeof(struct hamachi_private));
if (!dev)
goto err_out_iounmap;
SET_MODULE_OWNER(dev);
/* 硬件相关操作,省略 */
/* The Hamachi-specific entries in the device structure. */
dev->open = &hamachi_open;
dev->hard_start_xmit = &hamachi_start_xmit;
dev->stop = &hamachi_close;
dev->get_stats = &hamachi_get_stats;
dev->set_multicast_list = &set_rx_mode;
dev->do_ioctl = &netdev_ioctl;
dev->tx_timeout = &hamachi_tx_timeout;
dev->watchdog_timeo = TX_TIMEOUT;
if (mtu)
dev->mtu = mtu;
i = register_netdev(dev);
if (i) {
ret = i;
goto err_out_unmap_rx;
}
/* Configure gigabit autonegotiation. */
writew(0x0400, ioaddr + ANXchngCtrl);/* Enable legacy links. */
writew(0x08e0, ioaddr + ANAdvertise);/* Set our advertise word. */
writew(0x1000, ioaddr + ANCtrl);
card_idx++;
return 0;
}。