PCI内核源代码说明

合集下载

Linux系统中列出PCI设备和USB设备的命令详解

Linux系统中列出PCI设备和USB设备的命令详解

Linux系统中列出PCI设备和USB设备的命令详解lspciNAMElspci - 列出所有PCI设备 [[ ]]总览 SYNOPSISlspci [ options ] [[ ]]描述 DESCRIPTIONlspci 是⼀个⽤来显⽰系统中所有PCI总线设备或连接到该总线上的所有设备的⼯具。

为了能使⽤这个命令所有功能,你需要有 linux 2.1.82 或以上版本,⽀持 /proc/bus/pci 接⼝的内核。

在旧版本内核中,PCI⼯具必须使⽤只有root才能执⾏的直接硬件访问,⽽且总是出现竞争状况以及其他问题。

如果你要报告 PCI 设备驱动中,或者是 lspci ⾃⾝的 bugs,请在报告中包含 "lspci -vvx" 的输出。

[[ ]]选项 OPTIONS-v使得 lspci 以冗余模式显⽰所有设备的详细信息。

-vv使得 lspci 以过冗余模式显⽰更详细的信息 (事实上是 PCI 设备能给出的所有东西)。

这些数据的确切意义没有在此⼿册页中解释,如果你想知道更多,请参照 /usr/include/linux/pci.h 或者 PCI 规范。

-n以数字形式显⽰ PCI ⽣产⼚商和设备号,⽽不是在 PCI ID 数据库中查找它们。

-x以⼗六进制显⽰ PCI 配置空间 (configuration space) 的前64个字节映象 (标准头部信息)。

此参数对调试驱动和 lspci 本⾝很有⽤。

-xxx以⼗六进制显⽰所有 PCI 配置空间的映象。

此选项只有 root 可⽤,并且很多 PCI 设备在你试图读取配置空间的未定义部分时会崩溃 (此操作可能不违反PCI标准,但是它⾄少⾮常愚蠢)。

-b以总线为中⼼进⾏查看。

显⽰所有 IRQ 号和内存地址,就象 PCI 总线上的卡看到的⼀样,⽽不是内核看到的内容。

-t以树形⽅式显⽰包含所有总线、桥、设备和它们的连接的图表。

-s [[<bus>]:][<slot>][.[<func>]]仅显⽰指定总线、插槽上的设备或设备上的功能块信息。

一、如何编写LinuxPCI驱动程序

一、如何编写LinuxPCI驱动程序

⼀、如何编写LinuxPCI驱动程序PCI的世界是⼴阔的,充满了(⼤部分令⼈不快的)惊喜。

由于每个CPU体系结构实现不同的芯⽚集,并且PCI设备有不同的需求(“特性”),因此Linux内核中的PCI⽀持并不像⼈们希望的那么简单。

这篇简短的⽂章介绍⽤于PCI设备驱动程序的Linux APIs。

1.1 PCI驱动程序结构PCI驱动程序通过pci_register_driver()在系统中"发现"PCI设备。

事实上,恰恰相反。

当PCI通⽤代码发现⼀个新设备时,具有匹配“描述”的驱动程序将被通知。

详情如下。

pci_register_driver()将设备的⼤部分探测留给PCI层,并⽀持在线插⼊/删除设备[因此在单个驱动程序中⽀持热插拔PCI、CardBus和Express-Card]。

pci_register_driver()调⽤需要传⼊⼀个函数指针表,从⽽指⽰驱动程序的更⾼⼀级结构体。

⼀旦驱动程序知道了⼀个PCI设备并获得了所有权,驱动程序通常需要执⾏以下初始化:启⽤设备请求MMIO / IOP资源设置DMA掩码⼤⼩(⽤于⼀致性DMA和流式DMA)分配和初始化共享控制数据(pci_allocate_coherent())访问设备配置空间(如果需要)注册IRQ处理程序(request_irq())初始化non-PCI(即LAN/SCSI/等芯⽚部分)启⽤DMA /处理引擎当使⽤设备完成时,可能需要卸载模块,驱动程序需要采取以下步骤:禁⽌设备产⽣irq释放IRQ (free_irq())停⽌所有DMA活动释放DMA缓冲区(包括流式DMA和⼀致性DMA)从其他⼦系统注销(例如scsi或netdev)释放MMIO / IOP资源禁⽤该设备下⾯⼏节将介绍这些主题中的⼤部分。

其余部分请查看LDD3或<linux/pci.h>。

如果PCI⼦系统没有配置(没有设置CONFIG_PCI),下⾯描述的⼤多数PCI函数都被定义为内联函数,要么完全空,要么只是返回⼀个适当的错误代码,以避免在驱动程序中出现⼤量ifdefs。

PIC单片机的C语言编程指南

PIC单片机的C语言编程指南

PIC单片机的C语言编程指南PIC单片机是一种常用的嵌入式系统开发平台,其具有低功耗、成本低廉、易于编程等优点,在工业自动化、电子设备控制等领域有着广泛应用。

本文将为读者提供一份PIC单片机的C语言编程指南,帮助初学者快速入门并掌握基本的编程技巧。

首先,我们需要了解一些PIC单片机的基本概念。

PIC单片机采用哈佛结构,具有多种型号和系列,每个系列有多个型号可供选择。

不同的型号和系列有不同的特性和功能,因此在编程时需要根据具体的芯片型号进行适配。

PIC单片机的编程语言常用的是C语言,其语法简洁,易于理解和学习,并且具有较高的可移植性。

在编写PIC单片机的C语言程序时,我们需要按照以下步骤进行:1. 引入头文件:使用#include指令引入所需的头文件,头文件包含了定义和声明所需的函数和变量。

3.初始化:在程序开始时对所需的资源进行初始化,包括引脚配置、中断设置、定时器初始化等。

4.主循环:编写主循环代码,其中包括需要重复执行的功能,例如读取传感器数据、处理输入输出等。

5.中断处理:根据需要,编写中断处理函数,处理外部中断、定时器中断等。

6.清理工作:在程序结束时,进行一些清理工作,例如释放资源、关闭设备等。

下面是一个PIC单片机的C语言编程示例:```c#include <xc.h> // 引入XC8编译器的头文件#define LED_PIN RC0 // 定义LED连接的引脚void iniTRISC0=0;//配置RC0引脚为输出模式void maiinit(; // 初始化while(1)LED_PIN=1;//点亮LED__delay_ms(500); // 延时500毫秒LED_PIN=0;//关闭LED__delay_ms(500); // 延时500毫秒}```上述代码实现了一个简单的功能,即使LED灯以500毫秒的间隔交替点亮和关闭。

在程序中,我们首先引入了`<xc.h>`头文件,然后定义了一个宏`LED_PIN`来表示连接LED的RC0引脚。

kernel hacker修炼之道之PCI subsystem(六)

kernel hacker修炼之道之PCI subsystem(六)

k ernel hacker 修炼之道——李万鹏男儿立志出乡关, 学不成名死不还。

埋骨何须桑梓地, 人生无处不青山。

——西乡隆盛诗k ernel hacker修炼之道之PCI subsystem(六)分类: linux内核编程PCI-e/PCI 2012-02-26 18:39 1072人阅读 评论(3) 收藏举报kernel hacker修炼之道之PCI subsystem(六)作者 李万鹏第二步分析PCI core对PCI device resource的分配,包括:I/O,Memory,在pcibios_init函数中,遍历完PCI tree之后会调用pcibios_resource_survey函数来分配资源:1450void __init pcibios_resource_survey(void)1451{1452 struct pci_bus *b;14531454 /* Allocate and assign resources. If we re-assign everything, then1455 * we skip the allocate phase1456 */1457 list_for_each_entry(b, &pci_root_buses, node)1458 pcibios_allocate_bus_resources(b);14591460 if (!pci_has_flag(PCI_REASSIGN_ALL_RSRC)) {1461 pcibios_allocate_resources(0);1462 pcibios_allocate_resources(1);1463 }14641465 /* Before we start assigning unassigned resource, we try to reserve1466 * the low IO area and the VGA memory area if they intersect the1467 * bus available resources to avoid allocating things on top of them1468 */1469 if (!pci_has_flag(PCI_PROBE_ONLY)) {1470 list_for_each_entry(b, &pci_root_buses, node)1471 pcibios_reserve_legacy_regions(b);1472 }14731474 /* Now, if the platform didn't decide to blindly trust the firmware,1475 * we proceed to assigning things that were left unassigned1476 */1477 if (!pci_has_flag(PCI_PROBE_ONLY)) {1478 pr_debug("PCI: Assigning unassigned resources...\n");1479 pci_assign_unassigned_resources();1480 }14811482 /* Call machine dependent fixup */1483 if (ppc_md.pcibios_fixup)1484 ppc_md.pcibios_fixup();1485}首先给各个bus分配resource,然后再给挂在bus上的各个device分配resource,然后对未成功分配到resource的device进行重新分配。

pci热插拔内核原理

pci热插拔内核原理

pci热插拔内核原理PCI hot-plug is a technology that allows users to add or remove PCI cards from a computer while it is running. This is useful for servers and other high-availability systems because it allows for maintenance and upgrades without having to shut down the entire system.PCI热拔插是一种技术,允许用户在计算机运行时添加或删除PCI卡。

这对服务器和其他高可用性系统非常有用,因为它允许进行维护和升级,而无需关闭整个系统。

From a kernel perspective, the hot-plug feature is supported by the Linux kernel through the use of the PCI hot-plug driver. This driver handles the communication between the hardware and the kernel, allowing for the seamless addition or removal of PCI cards. When a new card is added, the driver detects it and initializes it so that the system can start using it without any interruption. Similarly, when a card is removed, the driver ensures that the system can continue to function properly without it.从内核的角度来看,热插拔功能是通过Linux内核通过PCI热插拔驱动程序支持的。

linux pci枚举流程

linux pci枚举流程

linux pci枚举流程摘要:1.Linux PCI枚举流程简介2.内核空间与用户空间的PCI配置空间3.PCI设备初始化流程4.驱动程序加载与卸载5.实战应用:Linux内核模块开发正文:Linux作为一种开源的操作系统,具有强大的硬件兼容性和丰富的设备驱动支持。

在Linux系统中,PCI(Peripheral Component Interconnect,外围组件互连)设备的枚举和驱动开发是至关重要的。

本文将详细介绍Linux PCI枚举流程,以及与之相关的内核空间与用户空间的PCI配置空间、设备初始化流程、驱动程序加载与卸载等知识点,最后通过实战应用案例,帮助读者更好地理解和掌握Linux内核模块开发。

1.Linux PCI枚举流程简介在Linux系统中,PCI设备的枚举过程主要分为以下几个阶段:(1)PCI配置空间的读取(2)设备驱动程序的加载与初始化(3)设备驱动程序与硬件设备的交互(4)设备驱动程序的卸载2.内核空间与用户空间的PCI配置空间Linux系统中,PCI配置空间分为内核空间和用户空间两部分。

内核空间主要用于操作系统内核对PCI设备的访问和管理,用户空间则用于设备驱动程序对PCI设备的配置和控制。

内核空间的PCI配置空间包括:(1)PCI设备的基本配置寄存器(2)PCI设备的扩展配置寄存器用户空间的PCI配置空间包括:(1)PCI设备的寄存器映射(2)PCI设备的I/O空间映射3.PCI设备初始化流程PCI设备初始化流程主要包括以下几个步骤:(1)设备枚举:操作系统内核通过读取PCI配置空间,获取设备信息。

(2)设备驱动程序加载:根据设备类型和接口,加载相应的设备驱动程序。

(3)设备初始化:设备驱动程序对硬件设备进行初始化,如配置寄存器、中断号等。

(4)设备启动:设备驱动程序发送命令,启动硬件设备。

4.驱动程序加载与卸载在Linux系统中,设备驱动程序的加载与卸载是通过动态链接库实现的。

PIC 单片机的C 语言编程

PIC 单片机的C 语言编程

PIC单片机C语言编程讲义奥科电子工作室(内部资料)2006年元月第一版第1章 PIC 单片机的C 语言编程1.1 PIC 单片机C 语言编程简介用C 语言来开发单片机系统软件最大的好处是编写代码效率高、软件调试直观、维护升级方便、代码的重复利用率高、便于跨平台的代码移植等等,因此C 语言编程在单片机系统设计中已得到越来越广泛的运用。

针对PIC 单片机的软件开发,同样可以用C 语言实现。

但在单片机上用C 语言写程序和在PC 机上写程序绝对不能简单等同。

现在的PC 机资源十分丰富,运算能力强大,因此程序员在写PC 机的应用程序时几乎不用关心编译后的可执行代码在运行过程中需要占用多少系统资源,也基本不用担心运行效率有多高。

写单片机的C 程序最关键的一点是单片机内的资源非常有限,控制的实时性要求又很高,因此,如果没有对单片机体系结构和硬件资源作详尽的了解,以笔者的愚见认为是无法写出高质量实用的C 语言程序。

这就是为什么前面所有章节中的的示范代码全部用基础的汇编指令实现的原因,希望籍此能使读者对PIC 单片机的指令体系和硬件资源有深入了解,在这基础之上再来讨论C 语言编程,就有水到渠成的感觉。

本讲稿围绕中档系列PIC 单片机来展开讨论,Microchip 公司自己没有针对中低档系列PIC单片机的C 语言编译器,但很多专业的第三方公司有众多支持PIC 单片机的C 语言编译器提供,常见的有Hitech、CCS、IAR、Bytecraft 等公司。

其中笔者最常用的是Hitech 公司的PICC 编译器,它稳定可靠,编译生成的代码效率高,在用PIC 单片机进行系统设计和开发的工程师群体中得到广泛认可。

其正式完全版软件需要购置,但在其网站上有限时的试用版供用户评估。

另外,Hitech 公司针对广大PIC 的业余爱好者和初学者还提供了完全免费的学习版PICC-Lite 编译器套件,它的使用方式和完全版相同,只是支持的PIC 单片机型号限制在PIC16F84、PIC16F877 和PIC16F628 等几款。

PCI驱动开发手册

PCI驱动开发手册

Linux2.6内核PCI驱动程序开发一,PCI相关数据结构说明1.1struct pci_driver这个数据结构在文件/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);};为创建一个正确的struct pci_driver 结构, 只有4个字段需要被初始化:name,id_table,probe和remove。

其中id_table初始化可以用到宏PCI_DEVICE(VENDOR_ID,DEVICE_ID),VENDOR_ID 和DEVICE_ID分别为设备和厂商编号,由板卡生产厂家指定。

Static const struct pci_device_id mypci[] ={{PCI_DEVICE(VENDOR_ID,DEVICE_ID)},{}};1.2pci_dev这个数据结构也在文件include/linux/pci.h里,它详细描述了一个PCI设备几乎所有的硬件信息,包括厂商ID、设备ID、各种资源等。

PCI详解

PCI详解


接下來,程式執行裝置寫入32位元基底位址到暫存器裡,不過只有位元 [31:20]是可寫入的,解碼器接荍位元[31:20]並假設所指定的基底位址的 位元[19:0]為0,這表示基底位址可以被1MB,既所請求的記憶體範圍大小 整除,所指定的起始位址一定會被所請求的記憶體範圍大小整除是PCI解 碼器的特性。
• •

8 SERR# Enable.當設定為1時,裝置可以驅動SERR#線,設 定為0會關閉裝置的SERR#輸出驅動器,此位元與位元6(同位元 錯誤報告)必須被設定,以便報告位址同位元錯誤 9 Fast Back-to-Back Enable.假如Bus Master可以在第一次 和第二次交易中,與不同的Target進行Fast Back-to-Back交易的話, 此位元可用來啟動或關閉這功能,假如所有在Bus Master所在之 PCI匯流排上的Target是可以進行Fast Back-to-Back交易的話,組 態軟體可以設定此位元來致能此Master進行Fast Back-to-Back交 易的能力,無需擔心在第一次和第二次交易裡是否定址相同的 Target.. 15:10 保留
• • • • • •
區塊大小的決定與位址範圍的指定: 是否實作基底位址暫存器? 它是一個記憶體,還是IO位址解碼器? 假如它是記憶體解碼器,它是一個32位元還是64位元的基底位址暫存器? 假如它是記憶體解碼器,與此暫存器相關的記憶體是可預讀的還是不可預 讀的? 它需要多少記憶體或位址空間,並且是以什麼單位來排列?
Base Address Register for I/O
Expansion ROM Base Address Register
Subsystem Vendor ID and Subsystem ID

pic单片机c语言

pic单片机c语言

PIC单片机 C 语言一、简介PIC(Peripheral Interface Controller)单片机是一种微控制器系列,由美国微芯科技公司推出。

PIC单片机广泛应用于嵌入式系统、自动化控制、仪器仪表等领域。

本文将介绍PIC单片机C语言编程的基础知识。

二、PIC单片机的开发环境准备在开始PIC单片机C语言编程前,我们需要准备开发环境。

以下是常用的开发环境工具:•MPLAB X IDE:Microchip官方推出的集成开发环境(IDE)。

可从Microchip官网免费下载。

•XC8编译器:Microchip官方提供的C语言编译器。

与MPLAB X IDE 配合使用,可编译生成PIC单片机的机器语言。

•PICKIT系列编程器:用于将编译生成的机器语言烧录到PIC单片机中。

在安装好开发环境工具后,我们可以开始进行PIC单片机C语言编程了。

三、PIC单片机的基本语法PIC单片机C语言编程的语法与标准C语言相似,但也有一些特殊的语法规则需要注意。

以下是一些常用的语法要点:1. 声明和定义变量在PIC单片机C语言中,我们可以使用关键字int、char、float等来声明和定义变量。

例如:int a; // 声明一个整型变量achar b; // 声明一个字符型变量bfloat c; // 声明一个浮点型变量c2. 控制语句PIC单片机C语言中的控制语句与标准C语言相似,包括条件语句、循环语句等。

例如:if (condition) {// 条件为真时执行的代码} else {// 条件为假时执行的代码}while (condition) {// 循环体}for (initialization; condition; update) {// 循环体}3. 函数在PIC单片机C语言中,我们可以定义和调用函数。

例如:int add(int a, int b) {return a + b;}int result = add(3, 5); // 调用函数add,并将返回值赋给result变量四、PIC单片机C语言编程实例下面我们以一个简单的实例来演示PIC单片机C语言编程的过程。

指令PIC的指令详解

指令PIC的指令详解

指令PIC的指令详解伪指令#include p16f877a.inclist p=16f877a,r=dec__config__idlocs(用户利用它存放程序版本或日期等) __idlocs 0x1234errorlevel 0,-302,-305 (编译信息输出显示等级及对对某些信息的单独设定)#define/#undefine #define KEY1 PORTB,7equ w_temp equ 0x20cblock+endc: cblock 0x20 w_temp buffer:8 var1 endcorg 0x00dt(定义表格数据代替retlw)table addwf pcl,fdt 0dt 1,2,'3';retlw 1 ;retlw 2;retlw 0x33('3')dt "abc" ;retlw 'a' ;retlw 'b';retlw 'c'de(源程序中定义片内eeprom的初值其实地址0x2100) org 0x2100de 0,1,2,3de "ABCD";定义8个字节fill(填充程序空间) fill 0x0000,5fill (goto $),next_bloclk-$ (从当前填充至标号next)死循环end宏指令banksel、pagesel、bankisel、clrc、setc、clrz、setz、clrdc、setdc、skpc、skpnc、skpdc、skpndc、bc、bnc、bz、bnz、bdc、bndcmacro自定义宏1.ADD LITERAL TO WADDLW K (W)+K->W加立即数至W ADDLW 0X15W=0X10->0X252.ADD W TO FADDWF F,D ((W)+(F)->W/F)ADDWF REG1,0 ADDWF FSR,13.ADD W AND CARRY D TO F ADDWFC F,DADDWFC FSR,1 (W+FSR+C->FSR)4.AND LITERAL AND WANDLW KANDLW 0x5F((W)并0x5F->W)5.AND W WITH FANDWF F,DANDWF FSR 1 (W并FSR->W/F)6.BIT CLEAR FBCF F,BBCF FLAG_REG,7 将FLAG_REG的D7清0 7.BIT SET FBSF F,BBSF PROTA,0 PROTA的D0置18.BIT TEST,SKIP IF CLEARBTFSC F,BBTFSC FLAG,1 FALSE TRUE位测试 0跳转9.BIT TEST,SKIP IF SETBTFSS F,BBTFSS FLAG,1 FALSE TRUE位测试 1跳转10.BIT TOGGLE FBTG F,BBTG PROTC,4 位取反 PORTC=0111 0101->0110 010111.SUBROUTINE CALLCALL 调用子程序12.CLEAR FCLRF FLAG_REG (F清零置Z=1)13.CLEAR W REGISTERCLRW (W清零置Z=1)14.CLEAR WATCHDOG TIMERCLRWDT(监视定时器清零00h->WDT 0->WDT预定标器1->TO' 1->PD')/doc/945763018.html,PLEMENT FCOMF REG1,0(寄存器内容取反->W/F)/doc/945763018.html,PARE F WITH W,SHIP IF F=WCPFSEQ REG/doc/945763018.html,PARE F WITH W,SHIP IF F>WCPFSGT REG/doc/945763018.html,PARE F WITH W,SHIP IF F<wCPFSLT REG19.DECIMAL ADJUST W REGISTERDAW REG1,0 (对F中内容进行10进制调整->F/W+F)REG1=0XA5 C=0 DC=0->0X05 C=1 DC=020.DECREMENT FDECF CNT,1(寄存器内容减1->W/F)21.DECREMENT F,SHIP IF 0DECFSZ CNT,1GOTO ...CONTINUE ...(减1后为0跳转至CONTINUE)22.DECREMENT F,SHIO IF NOT 0DECFSNZ CNT,0GOTO ...CONTINUE ...(减1后不为0跳转至CONTINUE)23.UNCONDITIONAL BRANCHGOTO 地址24.INCREMENT FINCF CNT,1(指令加1)CNT=0XFF Z=0 ->CNT=0X00 Z=1 C=125.INCREMENT F,SHIP IF 0INCFSZ F,D26.INCREMENT F,SHIP IF NOT 0INCFSNZ F,D27.INCLUSIVE OR LITERAL WITH WIORLW 0X35((W)或0X35->W)28.INCLUSIVE OR W WITH FIORWF RESULT,1 ((W)或RESULT->RESULT)29.LONG CALL 长调用指令和CALL有区别MOVLW HIGH 高位地址MOVPF WREG,PCLATH 存放在PCLATH中LCALL LOW 调用子程序(指令只含低8位地址)30.MOVE FMOVF REG,0 ((REG)->W)</w31.MOVE F TO PMOVFP F,P (F:00H-FFH P:00H-1FH)MOVFP REG1,REG2把数据存储单元传至某外围接口寄存器内容32.MOVE LITERAL TO LOW NIBBLE IN BSRMOVLB 0XA5 BSR=0X22->0X25(传立即数至BSR寄存器低4位高4位为0)33.MOVE LITERAL TO HIGH NIBBLE IN BSRMOVLR 5 BSR=0X22->0X52 (传至高4位低4位为0)34.MOVE LITERAL TO WMOVLW 0X5A W=0X5A (立即数传至W)35.MOVE P TO FMOVPF REG1,REG2 (F:00H-FFH P:00H-1FH)把某外围接口寄存器内容传至数据存储单元36.MOVE W TO FMOVWF REG ((W)->REG)37.NEGATE WNEGW REG 0 (REG取反->F/F+W)取反的规则P25138.NO OPERATIONNOP无操作占用一个指令周期 PC+139.LOAD OPTION REGISTER(W)->OPTION 只为可移植至PIC16C6X 不建议使用40.RETURN FROM INTERRUPTRETFIETOS->PC 1->GIE (中断允许位GIE开放中断)指令周期241.RETURN LITERAL TO WRETLW KK->W TOS->PC(立即数传至W 并返回地址至PC)指令周期2CALL TABLETABLE ADDWF PCRETLW K1RETLW K2...RETLW KN->W=0X07->W=K742.RETURN FROM SUBROUTINERETURN (TOS->PC 指令周期2)43.ROTATE LEFT F THROUGH CARRYRLF F,D/RLCF F,DF(N)->D(N+1) F(7)->C C->D(0)RLF REG1,0REG1=1110 0110->1110 0110 C=0->1 W=1100 110044.ROTATE LEFT F NO CARRYRLNCF F,D无进位循环左移45.ROTATE RIGHT F THROUGH CARRYRRF F,D/RRCF F,DRRF REG1,0REG1=1110 0110->1110 0110 C=1->0 W=0111 001146.ROTATE RIGHT F NO CARRYRRNCF F,D无进位循环右移47.SET FSETF F,SSETF REG,0WREG=0X05->0XFF REG=0XDA->0XFF48.SLEEPOOH->WDT 0->WDT预分频器 1->TO'(定时时间) 0->PD'掉电状态49.SUBTRACT W FROM LITERALSUBLW KK-(W)->WMOVLW 01HSUBLW 02H W=01H C=1结果为正MOVLW 02HSUBLW 02H W=0 C=1结果为0MOVLW 02HSUBLW 01H W=FF C=0结果为负50.SUBTRACT W FROM FSUBWF F,DMOVLW 3MOVWF REG1MOVLW 2SUBWF REG1,0 W=1 C=1MOVLW 2MOVWF REG1MOVLW 2SUBWF REG1,0 W=0 C=1MOVLW 2MOVWF REG1MOVLW 3SUBWF REG1,0 W=FF C=051.SUBTRACT W FROM F WITH BORROW SUBWFB F,D(F)-(W)-C->F/W带借位F-W减法MOVLW 4MOVWF REG1MOVWF REG1MOVLW 2SUBWFB REG1,0 设C初始为1 则W=1 C=152.SWAP FSWAPF F,DSWAPF REG1,1REG1=0XA5->0XA5 W=0X5A REG1=0X5A53.TABLE READTABLRD T,I,FTABLRD 1,1,REGREG=OX53->0XAA TBLATH=0XAA->0X12 TBLATL=0X55->0X34 TBLPTR=0XA356->0XA3567 存储单元=0X1234->0X5678传高字节TBLAT中一个字节传至F T=0传高字节T=1传低字节;TBLPTR 指向的程序存储单元内容传至表锁存器TBLAT;I=1 TBLPTR+1 I=0 TBLPTR不变存储单元的值为何改变周期2 若F=PC则3周期54.TABLE WRITETABWT T,I,FTABWT 0,1,REGREG=0X53->0X53 TBLATH=0XAA->0X53 TBLATL=0X55->0X55TBLPTR=0XA356->0XA357存储单元=0XFFFF->0X5355F值传至16为TBLAT表锁存器 T=0传低字节 T=1传至高字节;TBLAT内容写入TBLPTR指向的程序存储器单元;I=1 TBLPTR+1 I=0 TBLPTR不变指令周期2若F=PC 这周期355.TABLE LATCH READTLRD T,F 表锁存读TBLATH=0X00 TBLATL=0XAF T=0 RAM=0XAF TBLATH=0X00 TBLATL=0XAF56.TABLE LATCH WRITETLWT T,F 表锁存写RAM=0XB7 TBLATH=0X00 TBLATL=0X00 T=0 RAM=0XB7 TBLATH=0X00 TBLATL=0XB757.LOAD TRIS REGISTER I/O 控制寄存器TRIS设置指令不建议使用58.TEST F,SKIP IF 0TSTFSZ CNT F等于0跳转GOTO ...(CNT!=0)ZERO (CNT==0)59.EXCLUSIVE OR LITERAL WITH WXORLW K (W)异或K->WXORLW 0XAFW=0XB5->0X1A60.EXCLUSIVE OR W WITH FXORWF F D (W)异或(F)->(W)(F)XORWF REG1,1W=0XB5->0XB5 REG1=0XAF->0X1A直观助记符:BCF 3,0(进位位C清零)=CLRCBSF 3,0(进位位C置1)=SETCCLRDC BCF 3,1SETDC BSF 3,1CLRZ BCF 3,2SETZ BSF 3,2SKPC(有进位间跳)=BTFSS 3,0SKPNC(无进位间跳)=BTFSC 3,0SKPDC BTFSS 3,1SKPNDC BTFSC 3,1SKPZ BTFSS 3,2SKPNZ BTFSC 3,2 影响ZTSTF F(测试寄存器是否全零)=MOVF F,1 影响ZMOVFW F((F)->W) MOVF F,0 影响ZNEGF F,D取补码 COMF F,1 影响ZADDCF F,D内容加进位 BTFSC 3,0 影响Z 为0跳转INCF F,DSUBCF F,D内容减进位 BTFSC 3,0DECF F,DADDDCF F,D BTFSC 3,1INCF F,DSUBDCF F,D BTFSC 3,1DECF F,DB K 无条件转移 GOTO KBC K 有进位转移 BTFSC 3,0GOTO KBNC K 无进位转移 BTFSS 3,0GOTO KBDC K BTFSC 3,1GOTO KBNDC K BTFSS 3,1GOTO KBZ K BTFSC 3,2GOTO KBNZ K BTFSS 3,2GOTO K清零CLRW CLRF CLRWDT算术运算ADDLW K ADDWF F,D SUBLW K SUBWF F,D DECFF,D INCF F,D逻辑运算ANDLW K ANDWF F,D IORLW K或IORWF F,D XORLW K异或 XORWF F,D RLF F,D RRF F,DMOVLW K MOVF F,D MOVWF F NOP半字节交换指令SWAPF F,D可用于中断现场保护:MOVF W-TEMP SWAPF STATUS,W MOVWF S-TEMP-->SWAPF S-TEMP,W SWAPF STATUS,W SWAPF W-TEMP,W(W置于后一操作数?)子程序调用CALL GOTO跳转(CALL都是无返回值的?CALL的子程序都是无参数?)取反COMF F,DDECFSZ F,D INCFSZ F,D位操作BSF F,B BCF F,B BTFSS F,B BTFSC F,B返回RETLW K RETURN SLEEP RETFIE(RETURN FROM INTERRUPT WITH ENABLE)懒得算延时:3XY+4X+5(x外循环Y内循环)255-->19610020mhz 0.05us T=0.2us1、程序的基本格式先介绍二条伪指令:EQU ——标号赋值伪指令ORG ——地址定义伪指令PIC16C5X在RESET后指令计算器PC被置为全“1”,所以PIC16C5X几种型号芯片的复位地址为:PIC16C54/55:1FFHPIC16C56:3FFHPIC16C57/58:7FFH一般来说,PIC的源程序并没有要求统一的格式,大家可以根据自己的风格来编写。

[转载]应用程序中pci配置空间读写

[转载]应用程序中pci配置空间读写

[转载]应⽤程序中pci配置空间读写PCI原⽂地址:应⽤程序中pci配置空间读写作者:云⽉应⽤程序中pci配置空间读写~~~~~~~~~~~~~~~~~~~~~~~1. 概述主要讲述在linux操作系统中应⽤程序如何读写pci配置空间。

2. 基本原理对于pci设备,由cpu通过⼀个统⼀的⼊⼝地址向pci总桥发出命令,再由相应的pci桥间接地完成具体的读写操作。

对于X86结构,pci总线的设计者在I/O地址空间保留了8个字节⽤于这个操作:0xcf8 - 0xcff。

这8个字节分成两个32位的寄存器,0xcf8是地址寄存器,0xcfc是数据寄存器。

cpu先往地址寄存器中写⼊⽬标地址,然后通过数据寄存器读写数据,写⼊地址寄存器中的⽬标地址是⼀种包括总线号、设备号、功能号以及配置寄存器地址的综合地址。

具体如下:bit31 1bit30-bit24 保留bit23-bit16 总线号bit15-bit11 设备号bit10-bit8 功能号bit7-bit0 寄存器地址,最低两位为0设备的这些信息都可以通过lspci命令获取。

3. ioport读写权限由于要通过操作ioport,所以先要获取ioport的读写权限。

能获取读写权限的函数有两个ioperm()和iopl()。

由于pci的⼝地址⽐较⾼,要⽤iopl(3)获取权限。

4. 读程序#define PCI_CFG_DATA 0xcfc#define PCI_CFG_CTRL 0xcf8void pci_read_config_byte(unsigned char bus, unsigned char dev, unsigned char offset, unsigned char *val){unsigned char fun = 0;outl((0x80000000 | ((bus)<<16) |((dev)<<11) | ((fun)<<8) | (offset & ~0x3)), PCI_CFG_CTRL);*val = inl(PCI_CFG_DATA) >> ((offset & 3) * 8);}void pci_read_config_word(unsigned char bus, unsigned char dev, unsigned char offset, unsigned short *val){unsigned char fun = 0;outl((0x80000000 | ((bus)<<16) |((dev)<<11) | ((fun)<<8) | (offset & ~0x3)), PCI_CFG_CTRL);*val = inl(PCI_CFG_DATA) >> ((offset & 3) * 8);}void pci_read_config_dword(unsigned char bus, unsigned char dev, unsigned char offset, unsigned int *val){unsigned char fun = 0;outl((0x80000000 | ((bus)<<16) |((dev)<<11) | ((fun)<<8) | (offset)), PCI_CFG_CTRL);*val = inl(PCI_CFG_DATA);}很明显就是先向控制寄存器写⼊综合地址,格式前⾯已经提到,对⽐⼀下是完全⼀样的。

PIC编程说明

PIC编程说明

PIC编程说明在编程过程中由于一个端口可能有多个功能,所以在初始化时应该详细设置所以的端口的功能,当使用一种功能时应该将其他功能关闭,否则端口的功能将不能正常工作。

汇编:C语言:-------picc1、在用C语言编程之前,得确定用户用的是哪个辅助C编译器(因为MPLAB IDE 不提供C编译器,不过在8.33版本有捆绑了PICC的C编译器用户可以直接选用)。

注意设置连接编译器的路径。

2 在程序的最前面用#include 预处理指令引用包含头文件,其中必须包含一个编译器提供的“pic.h”文件(在picc18里为:pic18.h),实现单片机内特殊寄存器和其它特殊符号的声明;3 用“__CONFIG”预处理指令定义芯片的配置位;4 声明本模块内被调用的所有函数的类型,PICC 将对所调用的函数进行严格的类型匹配检查;5 定义全局变量或符号替换;6 实现函数(子程序),特别注意main 函数必须是一个没有返回的死循环。

现提供个C 原程序的范例:#include <pic.h> //包含单片机内部资源预定义#include “pc68.h” //包含自定义头文件//定义芯片工作时的配置位__CONFIG (HS & PROTECT & PWRTEN & BOREN & WDTDIS);//声明本模块中所调用的函数类型void SetSFR(void);void Clock(void);void KeyScan(void);void Measure(void);void LCD_Test(void);void LCD_Disp(unsigned char);//定义变量unsigned char second, minute, hour;bit flag1,flag2;//函数和子程序void main(void){SetSFR();PORTC = 0x00;TMR1H += TMR1H_CONST;LED1 = LED_OFF;LCD_Test();//程序工作主循环while(1) {asm(“clrwdt”); //清看门狗Clock(); //更新时钟KeyScan(); //扫描键盘Measure(); //数据测量SetSFR(); //刷新特殊功能寄存器}}为了使编译器产生最高效的机器码,PICC 把单片机中数据寄存器的bank 问题交由编程员自己管理,因此在定义用户变量时你必须自己决定这些变量具体放在哪一个bank 中。

xilinx PCIE的Linux驱动程序源代码

xilinx PCIE的Linux驱动程序源代码

//--------------------------------------------------------------------------------//-- Filename: xbmd.h//--//-- Description: Main header file for kernel driver//--//-- XBMD is an example Red Hat device driver which exercises XBMD design //-- Device driver has been tested on Red Hat Fedora FC9 2.6.15.//--------------------------------------------------------------------------------// Define Result values#define SUCCESS 0#define CRIT_ERR -1// Debug - define will output more info#define Verbose 1// Max DMA Buffer Size#define BUF_SIZE (4096 * 1024)enum {INITCARD,INITRST,DISPREGS,RDDCSR,RDDDMACR,RDWDMATLPA,RDWDMATLPS,RDWDMATLPC,RDWDMATLPP,RDRDMATLPP,RDRDMATLPA,RDRDMATLPS,RDRDMATLPC,RDWDMAPERF,RDRDMAPERF,RDRDMASTAT,RDNRDCOMP,RDRCOMPDSIZE,RDDLWSTAT,RDDLTRSSTAT,RDDMISCCONT,RDDMISCONT,DFCCTL,DFCPINFO,DFCNPINFO,DFCINFO,RDCFGREG,WRCFGREG,RDBMDREG,WRBMDREG,WRDDMACR,WRWDMATLPS,WRWDMATLPC,WRWDMATLPP,WRRDMATLPS,WRRDMATLPC,WRRDMATLPP,WRDMISCCONT,WRDDLNKC,NUMCOMMANDS};//--------------------------------------------------------------------------------//-- Filename: xbmd.c//--//-- Description: XBMD device driver.//--//-- XBMD is an example Red Hat device driver which exercises XBMD design //-- Device driver has been tested on Red Hat Fedora FC9 2.6.15.//--------------------------------------------------------------------------------#include <linux/init.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/fs.h>//#include <linux/pci-aspm.h>//#include <linux/pci_regs.h>#include <asm/uaccess.h> /* copy_to_user */#include "xbmd.h"// semaphoresenum {SEM_READ,SEM_WRITE,SEM_WRITEREG,SEM_READREG,SEM_W AITFOR,SEM_DMA,NUM_SEMS};//semaphoresstruct semaphore gSem[NUM_SEMS];MODULE_LICENSE("Dual BSD/GPL");// Defines the Vendor ID. Must be changed if core generated did not set the Vendor ID to the same value #define PCI_VENDOR_ID_XILINX 0x10ee// Defines the Device ID. Must be changed if core generated did not set the Device ID to the same value #define PCI_DEVICE_ID_XILINX_PCIE 0x0007// Defining#define XBMD_REGISTER_SIZE (4*8) // There are eight registers, and each is 4 bytes wide. #define HA VE_REGION 0x01 // I/O Memory region#define HA VE_IRQ 0x02 // Interupt//Status Flags:// 1 = Resouce successfully acquired// 0 = Resource not acquired.#define HA VE_REGION 0x01 // I/O Memory region#define HA VE_KREG 0x04 // Kernel registrationint gDrvrMajor = 241; // Major number not dynamic.unsigned int gStatFlags = 0x00; // Status flags used for cleanup.unsigned long gBaseHdwr; // Base register address (Hardware address) unsigned long gBaseLen; // Base register address Lengthvoid *gBaseVirt = NULL; // Base register address (Virtual address, for I/O). char gDrvrName[]= "xbmd"; // Name of driver in proc.struct pci_dev *gDev = NULL; // PCI device structure.int gIrq; // IRQ assigned by PCI system.char *gBufferUnaligned = NULL; // Pointer to Unaligned DMA buffer.char *gReadBuffer = NULL; // Pointer to dword aligned DMA buffer.char *gWriteBuffer = NULL; // Pointer to dword aligned DMA buffer.dma_addr_t gReadHW Addr;dma_addr_t gWriteHWAddr;unsigned long SA_SHIRQ = 0;unsigned long SA_SAMPLE_RANDOM = 0;int pos;// Struct Used for Writing CFG Register. Holds value and register to be writtentypedef struct cfgwrite {int reg;int value;} cfgwr;// Struct Used for Writing BMD Register. Holds value and register to be writtentypedef struct bmdwrite {int reg;int value;} bmdwr;//-----------------------------------------------------------------------------// Prototypes//-----------------------------------------------------------------------------void XPCIe_IRQHandler (int irq, void *dev_id, struct pt_regs *regs);u32 XPCIe_ReadReg (u32 dw_offset);void XPCIe_WriteReg (u32 dw_offset, u32 val);void XPCIe_InitCard (void);void XPCIe_InitiatorReset (void);u32 XPCIe_ReadCfgReg (u32 byte);u32 XPCIe_WriteCfgReg (u32 byte, u32 value);//---------------------------------------------------------------------------// Name: XPCIe_Open//// Description: Book keeping routine invoked each time the device is opened. //// Arguments: inode :// filp ://// Returns: 0 on success, error code on failure.//// Modification log:// Date Who Description////---------------------------------------------------------------------------int XPCIe_Open(struct inode *inode, struct file *filp){printk(KERN_INFO"%s: Open: module opened\n",gDrvrName); return SUCCESS;}//---------------------------------------------------------------------------// Name: XPCIe_Release//// Description: Book keeping routine invoked each time the device is closed. //// Arguments: inode :// filp ://// Returns: 0 on success, error code on failure.//// Modification log:// Date Who Description////---------------------------------------------------------------------------int XPCIe_Release(struct inode *inode, struct file *filp){printk(KERN_INFO"%s: Release: module released\n",gDrvrName); return(SUCCESS);}//---------------------------------------------------------------------------// Name: XPCIe_Write// Description: This routine is invoked from user space to write data to// the PCIe device.//// Arguments: filp : file pointer to opened device.// buf : pointer to location in users space, where data is to// be acquired.// count : Amount of data in bytes user wishes to send.//// Returns: SUCCESS = Success// CRIT_ERR = Critical failure//// Modification log:// Date Who Description////---------------------------------------------------------------------------ssize_t XPCIe_Write(struct file *filp, const char *buf, size_t count,loff_t *f_pos){int ret = SUCCESS;memcpy((char *)gWriteBuffer, buf, count);printk(KERN_INFO"%s: XPCIe_Write: %d bytes have been written...\n", gDrvrName, count); memcpy((char *)gReadBuffer, buf, count);printk(KERN_INFO"%s: XPCIe_Write: %d bytes have been written...\n", gDrvrName, count); return (ret);}//---------------------------------------------------------------------------// Name: XPCIe_Read//// Description: This routine is invoked from user space to read data from// the PCIe device. ***NOTE: This routine returns the entire// buffer, (BUF_SIZE), count is ignored!. The user App must// do any needed processing on the buffer.//// Arguments: filp : file pointer to opened device.// buf : pointer to location in users space, where data is to// be placed.// count : Amount of data in bytes user wishes to read.//// Returns: SUCCESS = Success// CRIT_ERR = Critical failure//// Date Who Description//----------------------------------------------------------------------------ssize_t XPCIe_Read(struct file *filp, char *buf, size_t count, loff_t *f_pos){memcpy(buf, (char *)gWriteBuffer, count);printk(KERN_INFO"%s: XPCIe_Read: %d bytes have been read...\n", gDrvrName, count); return (0);}//---------------------------------------------------------------------------// Name: XPCIe_Ioctl//// Description: This routine is invoked from user space to configure the// running driver.//// Arguments: inode :// filp : File pointer to opened device.// cmd : Ioctl command to execute.// arg : Argument to Ioctl command.//// Returns: 0 on success, error code on failure.//// Modification log:// Date Who Description////---------------------------------------------------------------------------int XPCIe_Ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){u32 regx;int ret = SUCCESS;switch (cmd) {case INITCARD: // Initailizes XBMD applicationXPCIe_InitCard();break;case INITRST: // Resets XBMD applicationsXPCIe_InitiatorReset();case DISPREGS:break;case RDDCSR: // Read: Device Control Status Registerregx = XPCIe_ReadReg(0);*((u32 *)arg) = regx;break;case RDDDMACR: // Read: DMA Control Status Register regx = XPCIe_ReadReg(1);*((u32 *)arg) = regx;break;case RDWDMATLPA: // Read: Write DMA TLP Address Register regx = XPCIe_ReadReg(2);*((u32 *)arg) = regx;break;case RDWDMATLPS: // Read: Write DMA TLP Size Register regx = XPCIe_ReadReg(3);*((u32 *)arg) = regx;break;case RDWDMATLPC: // Read: Write DMA TLP Count Register regx = XPCIe_ReadReg(4);*((u32 *)arg) = regx;break;case RDWDMATLPP: // Read: Write DMA TLP Pattern Register regx = XPCIe_ReadReg(5);*((u32 *)arg) = regx;break;case RDRDMATLPP: // Read: Read DMA TLP Pattern Register regx = XPCIe_ReadReg(6);*((u32 *)arg) = regx;break;case RDRDMATLPA: // Read: Read DMA TLP Address Register regx = XPCIe_ReadReg(7);*((u32 *)arg) = regx;break;case RDRDMATLPS: // Read: Read DMA TLP Size Register regx = XPCIe_ReadReg(8);*((u32 *)arg) = regx;break;case RDRDMATLPC: // Read: Read DMA TLP Count Register regx = XPCIe_ReadReg(9);*((u32 *)arg) = regx;break;regx = XPCIe_ReadReg(10);*((u32 *)arg) = regx;break;case RDRDMAPERF: // Read: Read DMA Performance Registerregx = XPCIe_ReadReg(11);*((u32 *)arg) = regx;break;case RDRDMASTAT: // Read: Read DMA Status Registerregx = XPCIe_ReadReg(12);*((u32 *)arg) = regx;break;case RDNRDCOMP: // Read: Number of Read Completion w/ Data Register regx = XPCIe_ReadReg(13);*((u32 *)arg) = regx;break;case RDRCOMPDSIZE: // Read: Read Completion Size Registerregx = XPCIe_ReadReg(14);*((u32 *)arg) = regx;break;case RDDLWSTAT: // Read: Device Link Width Status Registerregx = XPCIe_ReadReg(15);*((u32 *)arg) = regx;break;case RDDLTRSSTAT: // Read: Device Link Transaction Size Status Register regx = XPCIe_ReadReg(16);*((u32 *)arg) = regx;break;case RDDMISCCONT: // Read: Device Miscellaneous Control Registerregx = XPCIe_ReadReg(17);*((u32 *)arg) = regx;break;case RDDMISCONT: // Read: Device MSI Controlregx = XPCIe_ReadReg(18);*((u32 *)arg) = regx;break;case RDDLNKC: // Read: Device Directed Link Change Registerregx = XPCIe_ReadReg(19);*((u32 *)arg) = regx;break;case DFCCTL: // Read: Device FC Control Registerregx = XPCIe_ReadReg(20);*((u32 *)arg) = regx;case DFCPINFO: // Read: Device FC Posted Informationregx = XPCIe_ReadReg(21);*((u32 *)arg) = regx;break;case DFCNPINFO: // Read: Device FC Non Posted Informationregx = XPCIe_ReadReg(22);*((u32 *)arg) = regx;break;case DFCINFO: // Read: Device FC Completion Informationregx = XPCIe_ReadReg(23);*((u32 *)arg) = regx;break;case WRDDMACR: // Write: DMA Control Status RegisterXPCIe_WriteReg(1, arg);break;case WRWDMATLPS: // Write: Write DMA TLP Size RegisterXPCIe_WriteReg(3, arg);break;case WRWDMATLPC: // Write: Write DMA TLP Count RegisterXPCIe_WriteReg(4, arg);break;case WRWDMATLPP: // Write: Write DMA TLP Pattern RegisterXPCIe_WriteReg(5, arg);break;case WRRDMATLPS: // Write: Read DMA TLP Size RegisterXPCIe_WriteReg(8, arg);break;case WRRDMATLPC: // Write: Read DMA TLP Count RegisterXPCIe_WriteReg(9, arg);break;case WRRDMATLPP: // Write: Read DMA TLP Pattern RegisterXPCIe_WriteReg(6, arg);break;case WRDMISCCONT: // Write: Device Miscellaneous Control RegisterXPCIe_WriteReg(18, arg);break;case WRDDLNKC: // Write: Device Directed Link Change RegisterXPCIe_WriteReg(19, arg);break;case RDBMDREG: // Read: Any XBMD Reg. Added generic functionality so all register can be read regx = XPCIe_ReadReg(*(u32 *)arg);*((u32 *)arg) = regx;case RDCFGREG: // Read: Any CFG Reg. Added generic functionality so all register can be read regx = XPCIe_ReadCfgReg(*(u32 *)arg);*((u32 *)arg) = regx;break;case WRBMDREG: // Write: Any BMD Reg. Added generic functionality so all register can be read XPCIe_WriteReg((*(bmdwr *)arg).reg,(*(bmdwr *)arg).value);printk(KERN_WARNING"%d: Write Register.\n", (*(bmdwr *)arg).reg);printk(KERN_WARNING"%d: Write Value\n", (*(bmdwr *)arg).value);break;case WRCFGREG: // Write: Any CFG Reg. Added generic functionality so all register can be read regx = XPCIe_WriteCfgReg((*(cfgwr *)arg).reg,(*(cfgwr *)arg).value);printk(KERN_WARNING"%d: Write Register.\n", (*(cfgwr *)arg).reg);printk(KERN_WARNING"%d: Write Value\n", (*(cfgwr *)arg).value);break;default:break;}return ret;}// Aliasing write, read, ioctl, etc...struct file_operations XPCIe_Intf = {read: XPCIe_Read,write: XPCIe_Write,ioctl: XPCIe_Ioctl,open: XPCIe_Open,release: XPCIe_Release,};static int XPCIe_init(void){// Find the Xilinx EP device. The device is found by matching device and vendor ID's which is defined// at the top of this file. Be default, the driver will look for 10EE & 0007. If the core is generated// with other settings, the defines at the top must be changed or the driver will not loadgDev = pci_find_device (PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_PCIE, gDev);if (NULL == gDev) {// If a matching device or vendor ID is not found, return failure and update kernel log.// NOTE: In fedora systems, the kernel log is located at: /var/log/messagesreturn (CRIT_ERR);}// Get Base Address of registers from pci structure. Should come from pci_dev// structure, but that element seems to be missing on the development system.gBaseHdwr = pci_resource_start (gDev, 0);if (0 > gBaseHdwr) {printk(KERN_WARNING"%s: Init: Base Address not set.\n", gDrvrName);return (CRIT_ERR);}// Print Base Address to kernel logprintk(KERN_INFO"%s: Init: Base hw val %X\n", gDrvrName, (unsigned int)gBaseHdwr);// Get the Base Address LengthgBaseLen = pci_resource_len (gDev, 0);// Print the Base Address Length to Kernel Logprintk(KERN_INFO"%s: Init: Base hw len %d\n", gDrvrName, (unsigned int)gBaseLen);// Remap the I/O register block so that it can be safely accessed.// I/O register block starts at gBaseHdwr and is 32 bytes long.// It is cast to char because that is the way Linus does it.// Reference "/usr/src/Linux-2.4/Documentation/IO-mapping.txt".gBaseVirt = ioremap(gBaseHdwr, gBaseLen);if (!gBaseVirt) {printk(KERN_WARNING"%s: Init: Could not remap memory.\n", gDrvrName);return (CRIT_ERR);}// Print out the aquired virtual base addresssprintk(KERN_INFO"%s: Init: Virt HW address %X\n", gDrvrName, (unsigned int)gBaseVirt); // Get IRQ from pci_dev structure. It may have been remapped by the kernel,// and this value will be the correct one.gIrq = gDev->irq;printk(KERN_INFO"%s: Init: Device IRQ: %X\n",gDrvrName, gIrq);//---START: Initialize Hardwareif (0 > check_mem_region(gBaseHdwr, XBMD_REGISTER_SIZE)) {printk(KERN_WARNING"%s: Init: Memory in use.\n", gDrvrName);return (CRIT_ERR);}// Try to gain exclusive control of memory for demo hardware.request_mem_region(gBaseHdwr, XBMD_REGISTER_SIZE, "3GIO_Demo_Drv");// Update flagsgStatFlags = gStatFlags | HA VE_REGION;printk(KERN_INFO"%s: Init: Initialize Hardware Done..\n",gDrvrName);// Request IRQ from OS.// In past architectures, the SHARED and SAMPLE_RANDOM flags were called: SA_SHIRQ and SA_SAMPLE_RANDOM// respectively. In older Fedora core installations, the request arguments may need to be reverted back.// SA_SHIRQ | SA_SAMPLE_RANDOMprintk(KERN_INFO"%s: ISR Setup..\n", gDrvrName);if (0 > request_irq(gIrq, &XPCIe_IRQHandler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, gDrvrName, gDev)) {printk(KERN_WARNING"%s: Init: Unable to allocate IRQ",gDrvrName);return (CRIT_ERR);}// Update flags stating IRQ was successfully obtainedgStatFlags = gStatFlags | HA VE_IRQ;// Bus Master Enableif (0 > pci_enable_device(gDev)) {printk(KERN_WARNING"%s: Init: Device not enabled.\n", gDrvrName);return (CRIT_ERR);}//--- END: Initialize Hardware//--- START: Allocate Buffers// Allocate the read buffer with size BUF_SIZE and return the starting addressgReadBuffer = pci_alloc_consistent(gDev, BUF_SIZE, &gReadHWAddr);if (NULL == gReadBuffer) {printk(KERN_CRIT"%s: Init: Unable to allocate gBuffer.\n",gDrvrName);return (CRIT_ERR);}// Print Read buffer size and address to kernel logprintk(KERN_INFO"%s: Read Buffer Allocation: %X->%X\n", gDrvrName, (unsigned int)gReadBuffer, (unsigned int)gReadHW Addr);// Allocate the write buffer with size BUF_SIZE and return the starting addressgWriteBuffer = pci_alloc_consistent(gDev, BUF_SIZE, &gWriteHWAddr);if (NULL == gWriteBuffer) {printk(KERN_CRIT"%s: Init: Unable to allocate gBuffer.\n",gDrvrName);return (CRIT_ERR);}// Print Write buffer size and address to kernel logprintk(KERN_INFO"%s: Write Buffer Allocation: %X->%X\n", gDrvrName, (unsigned int)gWriteBuffer, (unsigned int)gWriteHW Addr); //--- END: Allocate Buffers//--- START: Register Driver// Register with the kernel as a character device.if (0 > register_chrdev(gDrvrMajor, gDrvrName, &XPCIe_Intf)) {printk(KERN_WARNING"%s: Init: will not register\n", gDrvrName);return (CRIT_ERR);}printk(KERN_INFO"%s: Init: module registered\n", gDrvrName);gStatFlags = gStatFlags | HA VE_KREG;//--- END: Register Driver// The driver is now successfully loaded. All HW is initialized, IRQ's assigned, and buffers allocatedprintk("%s driver is loaded\n", gDrvrName);// Initializing card registersXPCIe_InitCard();return 0;}//--- XPCIe_InitiatorReset(): Resets the XBMD reference design//--- Arguments: None//--- Return Value: None//--- Detailed Description: Writes a 1 to the DCSR register which resets the XBMD designvoid XPCIe_InitiatorReset(){XPCIe_WriteReg(0, 1); // Write: DCSR (offset 0) with value of 1 (Reset Device)XPCIe_WriteReg(0, 0); // Write: DCSR (offset 0) with value of 0 (Make Active)}//--- XPCIe_InitCard(): Initializes XBMD descriptor registers to default values//--- Arguments: None//--- Return Value: None//--- Detailed Description: 1) Resets device//--- 2) Writes specific values into the XBMD registers inside the EPvoid XPCIe_InitCard(){XPCIe_WriteReg(0, 1); // Write: DCSR (offset 0) with value of 1 (Reset Device)XPCIe_WriteReg(0, 0); // Write: DCSR (offset 0) with value of 0 (Make Active)XPCIe_WriteReg(2, gWriteHW Addr); // Write: Write DMA TLP Address register with starting address XPCIe_WriteReg(3, 0x20); // Write: Write DMA TLP Size register with default value (32dwords) XPCIe_WriteReg(4, 0x2000); // Write: Write DMA TLP Count register with default value (2000) XPCIe_WriteReg(5, 0x00000000); // Write: Write DMA TLP Pattern register with default value (0x0) XPCIe_WriteReg(6, 0xfeedbeef); // Write: Read DMA Expected Data Pattern with default value (feedbeef) XPCIe_WriteReg(7, gReadHW Addr); // Write: Read DMA TLP Address register with starting address. XPCIe_WriteReg(8, 0x20); // Write: Read DMA TLP Size register with default value (32dwords) XPCIe_WriteReg(9, 0x2000); // Write: Read DMA TLP Count register with default value (2000)}//--- XPCIe_exit(): Performs any cleanup required before releasing the device//--- Arguments: None//--- Return Value: None//--- Detailed Description: Performs all cleanup functions required before releasing devicestatic void XPCIe_exit(void){// Check if we have a memory region and free itif (gStatFlags & HA VE_REGION) {(void) release_mem_region(gBaseHdwr, XBMD_REGISTER_SIZE);}// Check if we have an IRQ and free itif (gStatFlags & HA VE_IRQ) {(void) free_irq(gIrq, gDev);}// Free Write and Read buffers allocated to useif (NULL != gReadBuffer)(void) kfree(gReadBuffer);(void) kfree(gWriteBuffer);// Free memory allocated to our Endpointpci_free_consistent(gDev, BUF_SIZE, gReadBuffer, gReadHW Addr);pci_free_consistent(gDev, BUF_SIZE, gWriteBuffer, gWriteHW Addr);gReadBuffer = NULL;gWriteBuffer = NULL;// Free up memory pointed to by virtual addressif (gBaseVirt != NULL) {iounmap(gBaseVirt);}gBaseVirt = NULL;// Unregister Device Driverif (gStatFlags & HA VE_KREG) {unregister_chrdev(gDrvrMajor, gDrvrName);}gStatFlags = 0;// Update Kernel log stating driver is unloadedprintk(KERN_ALERT"%s driver is unloaded\n", gDrvrName);}// Driver Entry Pointmodule_init(XPCIe_init);// Driver Exit Pointmodule_exit(XPCIe_exit);void XPCIe_IRQHandler(int irq, void *dev_id, struct pt_regs *regs){u32 i, regx;printk(KERN_WARNING"%s: Interrupt Handler Start ..",gDrvrName); for (i = 0; i < 32; i++) {regx = XPCIe_ReadReg(i);printk(KERN_W ARNING"%s Interrupt Handler End ..\n", gDrvrName);}u32 XPCIe_ReadReg (u32 dw_offset){u32 ret = 0;//u32 reg_addr = (u32)(gBaseVirt + (4 * dw_offset));//ret = readl(reg_addr);ret = readl(gBaseVirt + (4 * dw_offset));return ret;}void XPCIe_WriteReg (u32 dw_offset, u32 val){//u32 reg_addr = (u32)(gBaseVirt + (4 * dw_offset));writel(val, (gBaseVirt + (4 * dw_offset)));}ssize_t* XPCIe_ReadMem(char *buf, size_t count){int ret = 0;dma_addr_t dma_addr;//make sure passed in buffer is large enoughif ( count < BUF_SIZE ) {printk("%s: XPCIe_Read: passed in buffer too small.\n", gDrvrName);ret = -1;goto exit;}down(&gSem[SEM_DMA]);// pci_map_single return the physical address corresponding to// the virtual address passed to it as the 2nd parameterdma_addr = pci_map_single(gDev, gReadBuffer, BUF_SIZE, PCI_DMA_FROMDEVICE);if ( 0 == dma_addr ) {printk("%s: XPCIe_Read: Map error.\n",gDrvrName);ret = -1;// Now pass the physical address to the device hardware. This is now// the destination physical address for the DMA and hence the to be// put on Memory Transactions// Do DMA transfer here....printk("%s: XPCIe_Read: ReadBuf Virt Addr = %x Phy Addr = %x.\n",gDrvrName, (unsigned int)gReadBuffer, (unsigned int)dma_addr);// Unmap the DMA buffer so it is safe for normal access again.pci_unmap_single(gDev, dma_addr, BUF_SIZE, PCI_DMA_FROMDEVICE);up(&gSem[SEM_DMA]);// Now it is safe to copy the data to user space.if ( copy_to_user(buf, gReadBuffer, BUF_SIZE) ) {ret = -1;printk("%s: XPCIe_Read: Failed copy to user.\n",gDrvrName);goto exit;}exit:return ret;}ssize_t XPCIe_WriteMem(const char *buf, size_t count) {int ret = 0;dma_addr_t dma_addr;if ( (count % 4) != 0 ) {printk("%s: XPCIe_Write: Buffer length not dword aligned.\n",gDrvrName);ret = -1;goto exit;}// Now it is safe to copy the data from user space.if ( copy_from_user(gWriteBuffer, buf, count) ) {ret = -1;printk("%s: XPCIe_Write: Failed copy to user.\n",gDrvrName);goto exit;}//set DMA semaphore if in loopback// pci_map_single return the physical address corresponding to// the virtual address passed to it as the 2nd parameterdma_addr = pci_map_single(gDev, gWriteBuffer, BUF_SIZE, PCI_DMA_FROMDEVICE);if ( 0 == dma_addr ) {printk("%s: XPCIe_Write: Map error.\n",gDrvrName);ret = -1;goto exit;}// Now pass the physical address to the device hardware. This is now// the source physical address for the DMA and hence the to be// put on Memory Transactions// Do DMA transfer here....printk("%s: XPCIe_Write: WriteBuf Virt Addr = %x Phy Addr = %x.\n",gDrvrName, (unsigned int)gReadBuffer, (unsigned int)dma_addr);// Unmap the DMA buffer so it is safe for normal access again.pci_unmap_single(gDev, dma_addr, BUF_SIZE, PCI_DMA_FROMDEVICE);up(&gSem[SEM_DMA]);exit:return (ret);}u32 XPCIe_ReadCfgReg (u32 byte) {u32 pciReg;if (pci_read_config_dword(gDev, byte, &pciReg) < 0) {printk("%s: XPCIe_ReadCfgReg: Reading PCI interface failed.",gDrvrName);return (-1);}return (pciReg);}u32 XPCIe_WriteCfgReg (u32 byte, u32 val) {if (pci_write_config_dword(gDev, byte, val) < 0) {printk("%s: XPCIe_Read Device Control: Reading PCI interface failed.",gDrvrName);return (-1);}return 1;}。

xilinx PCIE的Linux驱动程序源代码

xilinx PCIE的Linux驱动程序源代码

//--------------------------------------------------------------------------------//-- Filename: xbmd.h//--//-- Description: Main header file for kernel driver//--//-- XBMD is an example Red Hat device driver which exercises XBMD design //-- Device driver has been tested on Red Hat Fedora FC9 2.6.15.//--------------------------------------------------------------------------------// Define Result values#define SUCCESS 0#define CRIT_ERR -1// Debug - define will output more info#define Verbose 1// Max DMA Buffer Size#define BUF_SIZE (4096 * 1024)enum {INITCARD,INITRST,DISPREGS,RDDCSR,RDDDMACR,RDWDMATLPA,RDWDMATLPS,RDWDMATLPC,RDWDMATLPP,RDRDMATLPP,RDRDMATLPA,RDRDMATLPS,RDRDMATLPC,RDWDMAPERF,RDRDMAPERF,RDRDMASTAT,RDNRDCOMP,RDRCOMPDSIZE,RDDLWSTAT,RDDLTRSSTAT,RDDMISCCONT,RDDMISCONT,DFCCTL,DFCPINFO,DFCNPINFO,DFCINFO,RDCFGREG,WRCFGREG,RDBMDREG,WRBMDREG,WRDDMACR,WRWDMATLPS,WRWDMATLPC,WRWDMATLPP,WRRDMATLPS,WRRDMATLPC,WRRDMATLPP,WRDMISCCONT,WRDDLNKC,NUMCOMMANDS};//--------------------------------------------------------------------------------//-- Filename: xbmd.c//--//-- Description: XBMD device driver.//--//-- XBMD is an example Red Hat device driver which exercises XBMD design //-- Device driver has been tested on Red Hat Fedora FC9 2.6.15.//--------------------------------------------------------------------------------#include <linux/init.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/fs.h>//#include <linux/pci-aspm.h>//#include <linux/pci_regs.h>#include <asm/uaccess.h> /* copy_to_user */#include "xbmd.h"// semaphoresenum {SEM_READ,SEM_WRITE,SEM_WRITEREG,SEM_READREG,SEM_W AITFOR,SEM_DMA,NUM_SEMS};//semaphoresstruct semaphore gSem[NUM_SEMS];MODULE_LICENSE("Dual BSD/GPL");// Defines the Vendor ID. Must be changed if core generated did not set the Vendor ID to the same value #define PCI_VENDOR_ID_XILINX 0x10ee// Defines the Device ID. Must be changed if core generated did not set the Device ID to the same value #define PCI_DEVICE_ID_XILINX_PCIE 0x0007// Defining#define XBMD_REGISTER_SIZE (4*8) // There are eight registers, and each is 4 bytes wide. #define HA VE_REGION 0x01 // I/O Memory region#define HA VE_IRQ 0x02 // Interupt//Status Flags:// 1 = Resouce successfully acquired// 0 = Resource not acquired.#define HA VE_REGION 0x01 // I/O Memory region#define HA VE_KREG 0x04 // Kernel registrationint gDrvrMajor = 241; // Major number not dynamic.unsigned int gStatFlags = 0x00; // Status flags used for cleanup.unsigned long gBaseHdwr; // Base register address (Hardware address) unsigned long gBaseLen; // Base register address Lengthvoid *gBaseVirt = NULL; // Base register address (Virtual address, for I/O). char gDrvrName[]= "xbmd"; // Name of driver in proc.struct pci_dev *gDev = NULL; // PCI device structure.int gIrq; // IRQ assigned by PCI system.char *gBufferUnaligned = NULL; // Pointer to Unaligned DMA buffer.char *gReadBuffer = NULL; // Pointer to dword aligned DMA buffer.char *gWriteBuffer = NULL; // Pointer to dword aligned DMA buffer.dma_addr_t gReadHW Addr;dma_addr_t gWriteHWAddr;unsigned long SA_SHIRQ = 0;unsigned long SA_SAMPLE_RANDOM = 0;int pos;// Struct Used for Writing CFG Register. Holds value and register to be writtentypedef struct cfgwrite {int reg;int value;} cfgwr;// Struct Used for Writing BMD Register. Holds value and register to be writtentypedef struct bmdwrite {int reg;int value;} bmdwr;//-----------------------------------------------------------------------------// Prototypes//-----------------------------------------------------------------------------void XPCIe_IRQHandler (int irq, void *dev_id, struct pt_regs *regs);u32 XPCIe_ReadReg (u32 dw_offset);void XPCIe_WriteReg (u32 dw_offset, u32 val);void XPCIe_InitCard (void);void XPCIe_InitiatorReset (void);u32 XPCIe_ReadCfgReg (u32 byte);u32 XPCIe_WriteCfgReg (u32 byte, u32 value);//---------------------------------------------------------------------------// Name: XPCIe_Open//// Description: Book keeping routine invoked each time the device is opened. //// Arguments: inode :// filp ://// Returns: 0 on success, error code on failure.//// Modification log:// Date Who Description////---------------------------------------------------------------------------int XPCIe_Open(struct inode *inode, struct file *filp){printk(KERN_INFO"%s: Open: module opened\n",gDrvrName); return SUCCESS;}//---------------------------------------------------------------------------// Name: XPCIe_Release//// Description: Book keeping routine invoked each time the device is closed. //// Arguments: inode :// filp ://// Returns: 0 on success, error code on failure.//// Modification log:// Date Who Description////---------------------------------------------------------------------------int XPCIe_Release(struct inode *inode, struct file *filp){printk(KERN_INFO"%s: Release: module released\n",gDrvrName); return(SUCCESS);}//---------------------------------------------------------------------------// Name: XPCIe_Write// Description: This routine is invoked from user space to write data to// the PCIe device.//// Arguments: filp : file pointer to opened device.// buf : pointer to location in users space, where data is to// be acquired.// count : Amount of data in bytes user wishes to send.//// Returns: SUCCESS = Success// CRIT_ERR = Critical failure//// Modification log:// Date Who Description////---------------------------------------------------------------------------ssize_t XPCIe_Write(struct file *filp, const char *buf, size_t count,loff_t *f_pos){int ret = SUCCESS;memcpy((char *)gWriteBuffer, buf, count);printk(KERN_INFO"%s: XPCIe_Write: %d bytes have been written...\n", gDrvrName, count); memcpy((char *)gReadBuffer, buf, count);printk(KERN_INFO"%s: XPCIe_Write: %d bytes have been written...\n", gDrvrName, count); return (ret);}//---------------------------------------------------------------------------// Name: XPCIe_Read//// Description: This routine is invoked from user space to read data from// the PCIe device. ***NOTE: This routine returns the entire// buffer, (BUF_SIZE), count is ignored!. The user App must// do any needed processing on the buffer.//// Arguments: filp : file pointer to opened device.// buf : pointer to location in users space, where data is to// be placed.// count : Amount of data in bytes user wishes to read.//// Returns: SUCCESS = Success// CRIT_ERR = Critical failure//// Date Who Description//----------------------------------------------------------------------------ssize_t XPCIe_Read(struct file *filp, char *buf, size_t count, loff_t *f_pos){memcpy(buf, (char *)gWriteBuffer, count);printk(KERN_INFO"%s: XPCIe_Read: %d bytes have been read...\n", gDrvrName, count); return (0);}//---------------------------------------------------------------------------// Name: XPCIe_Ioctl//// Description: This routine is invoked from user space to configure the// running driver.//// Arguments: inode :// filp : File pointer to opened device.// cmd : Ioctl command to execute.// arg : Argument to Ioctl command.//// Returns: 0 on success, error code on failure.//// Modification log:// Date Who Description////---------------------------------------------------------------------------int XPCIe_Ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){u32 regx;int ret = SUCCESS;switch (cmd) {case INITCARD: // Initailizes XBMD applicationXPCIe_InitCard();break;case INITRST: // Resets XBMD applicationsXPCIe_InitiatorReset();case DISPREGS:break;case RDDCSR: // Read: Device Control Status Registerregx = XPCIe_ReadReg(0);*((u32 *)arg) = regx;break;case RDDDMACR: // Read: DMA Control Status Register regx = XPCIe_ReadReg(1);*((u32 *)arg) = regx;break;case RDWDMATLPA: // Read: Write DMA TLP Address Register regx = XPCIe_ReadReg(2);*((u32 *)arg) = regx;break;case RDWDMATLPS: // Read: Write DMA TLP Size Register regx = XPCIe_ReadReg(3);*((u32 *)arg) = regx;break;case RDWDMATLPC: // Read: Write DMA TLP Count Register regx = XPCIe_ReadReg(4);*((u32 *)arg) = regx;break;case RDWDMATLPP: // Read: Write DMA TLP Pattern Register regx = XPCIe_ReadReg(5);*((u32 *)arg) = regx;break;case RDRDMATLPP: // Read: Read DMA TLP Pattern Register regx = XPCIe_ReadReg(6);*((u32 *)arg) = regx;break;case RDRDMATLPA: // Read: Read DMA TLP Address Register regx = XPCIe_ReadReg(7);*((u32 *)arg) = regx;break;case RDRDMATLPS: // Read: Read DMA TLP Size Register regx = XPCIe_ReadReg(8);*((u32 *)arg) = regx;break;case RDRDMATLPC: // Read: Read DMA TLP Count Register regx = XPCIe_ReadReg(9);*((u32 *)arg) = regx;break;regx = XPCIe_ReadReg(10);*((u32 *)arg) = regx;break;case RDRDMAPERF: // Read: Read DMA Performance Registerregx = XPCIe_ReadReg(11);*((u32 *)arg) = regx;break;case RDRDMASTAT: // Read: Read DMA Status Registerregx = XPCIe_ReadReg(12);*((u32 *)arg) = regx;break;case RDNRDCOMP: // Read: Number of Read Completion w/ Data Register regx = XPCIe_ReadReg(13);*((u32 *)arg) = regx;break;case RDRCOMPDSIZE: // Read: Read Completion Size Registerregx = XPCIe_ReadReg(14);*((u32 *)arg) = regx;break;case RDDLWSTAT: // Read: Device Link Width Status Registerregx = XPCIe_ReadReg(15);*((u32 *)arg) = regx;break;case RDDLTRSSTAT: // Read: Device Link Transaction Size Status Register regx = XPCIe_ReadReg(16);*((u32 *)arg) = regx;break;case RDDMISCCONT: // Read: Device Miscellaneous Control Registerregx = XPCIe_ReadReg(17);*((u32 *)arg) = regx;break;case RDDMISCONT: // Read: Device MSI Controlregx = XPCIe_ReadReg(18);*((u32 *)arg) = regx;break;case RDDLNKC: // Read: Device Directed Link Change Registerregx = XPCIe_ReadReg(19);*((u32 *)arg) = regx;break;case DFCCTL: // Read: Device FC Control Registerregx = XPCIe_ReadReg(20);*((u32 *)arg) = regx;case DFCPINFO: // Read: Device FC Posted Informationregx = XPCIe_ReadReg(21);*((u32 *)arg) = regx;break;case DFCNPINFO: // Read: Device FC Non Posted Informationregx = XPCIe_ReadReg(22);*((u32 *)arg) = regx;break;case DFCINFO: // Read: Device FC Completion Informationregx = XPCIe_ReadReg(23);*((u32 *)arg) = regx;break;case WRDDMACR: // Write: DMA Control Status RegisterXPCIe_WriteReg(1, arg);break;case WRWDMATLPS: // Write: Write DMA TLP Size RegisterXPCIe_WriteReg(3, arg);break;case WRWDMATLPC: // Write: Write DMA TLP Count RegisterXPCIe_WriteReg(4, arg);break;case WRWDMATLPP: // Write: Write DMA TLP Pattern RegisterXPCIe_WriteReg(5, arg);break;case WRRDMATLPS: // Write: Read DMA TLP Size RegisterXPCIe_WriteReg(8, arg);break;case WRRDMATLPC: // Write: Read DMA TLP Count RegisterXPCIe_WriteReg(9, arg);break;case WRRDMATLPP: // Write: Read DMA TLP Pattern RegisterXPCIe_WriteReg(6, arg);break;case WRDMISCCONT: // Write: Device Miscellaneous Control RegisterXPCIe_WriteReg(18, arg);break;case WRDDLNKC: // Write: Device Directed Link Change RegisterXPCIe_WriteReg(19, arg);break;case RDBMDREG: // Read: Any XBMD Reg. Added generic functionality so all register can be read regx = XPCIe_ReadReg(*(u32 *)arg);*((u32 *)arg) = regx;case RDCFGREG: // Read: Any CFG Reg. Added generic functionality so all register can be read regx = XPCIe_ReadCfgReg(*(u32 *)arg);*((u32 *)arg) = regx;break;case WRBMDREG: // Write: Any BMD Reg. Added generic functionality so all register can be read XPCIe_WriteReg((*(bmdwr *)arg).reg,(*(bmdwr *)arg).value);printk(KERN_WARNING"%d: Write Register.\n", (*(bmdwr *)arg).reg);printk(KERN_WARNING"%d: Write Value\n", (*(bmdwr *)arg).value);break;case WRCFGREG: // Write: Any CFG Reg. Added generic functionality so all register can be read regx = XPCIe_WriteCfgReg((*(cfgwr *)arg).reg,(*(cfgwr *)arg).value);printk(KERN_WARNING"%d: Write Register.\n", (*(cfgwr *)arg).reg);printk(KERN_WARNING"%d: Write Value\n", (*(cfgwr *)arg).value);break;default:break;}return ret;}// Aliasing write, read, ioctl, etc...struct file_operations XPCIe_Intf = {read: XPCIe_Read,write: XPCIe_Write,ioctl: XPCIe_Ioctl,open: XPCIe_Open,release: XPCIe_Release,};static int XPCIe_init(void){// Find the Xilinx EP device. The device is found by matching device and vendor ID's which is defined// at the top of this file. Be default, the driver will look for 10EE & 0007. If the core is generated// with other settings, the defines at the top must be changed or the driver will not loadgDev = pci_find_device (PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX_PCIE, gDev);if (NULL == gDev) {// If a matching device or vendor ID is not found, return failure and update kernel log.// NOTE: In fedora systems, the kernel log is located at: /var/log/messagesreturn (CRIT_ERR);}// Get Base Address of registers from pci structure. Should come from pci_dev// structure, but that element seems to be missing on the development system.gBaseHdwr = pci_resource_start (gDev, 0);if (0 > gBaseHdwr) {printk(KERN_WARNING"%s: Init: Base Address not set.\n", gDrvrName);return (CRIT_ERR);}// Print Base Address to kernel logprintk(KERN_INFO"%s: Init: Base hw val %X\n", gDrvrName, (unsigned int)gBaseHdwr);// Get the Base Address LengthgBaseLen = pci_resource_len (gDev, 0);// Print the Base Address Length to Kernel Logprintk(KERN_INFO"%s: Init: Base hw len %d\n", gDrvrName, (unsigned int)gBaseLen);// Remap the I/O register block so that it can be safely accessed.// I/O register block starts at gBaseHdwr and is 32 bytes long.// It is cast to char because that is the way Linus does it.// Reference "/usr/src/Linux-2.4/Documentation/IO-mapping.txt".gBaseVirt = ioremap(gBaseHdwr, gBaseLen);if (!gBaseVirt) {printk(KERN_WARNING"%s: Init: Could not remap memory.\n", gDrvrName);return (CRIT_ERR);}// Print out the aquired virtual base addresssprintk(KERN_INFO"%s: Init: Virt HW address %X\n", gDrvrName, (unsigned int)gBaseVirt); // Get IRQ from pci_dev structure. It may have been remapped by the kernel,// and this value will be the correct one.gIrq = gDev->irq;printk(KERN_INFO"%s: Init: Device IRQ: %X\n",gDrvrName, gIrq);//---START: Initialize Hardwareif (0 > check_mem_region(gBaseHdwr, XBMD_REGISTER_SIZE)) {printk(KERN_WARNING"%s: Init: Memory in use.\n", gDrvrName);return (CRIT_ERR);}// Try to gain exclusive control of memory for demo hardware.request_mem_region(gBaseHdwr, XBMD_REGISTER_SIZE, "3GIO_Demo_Drv");// Update flagsgStatFlags = gStatFlags | HA VE_REGION;printk(KERN_INFO"%s: Init: Initialize Hardware Done..\n",gDrvrName);// Request IRQ from OS.// In past architectures, the SHARED and SAMPLE_RANDOM flags were called: SA_SHIRQ and SA_SAMPLE_RANDOM// respectively. In older Fedora core installations, the request arguments may need to be reverted back.// SA_SHIRQ | SA_SAMPLE_RANDOMprintk(KERN_INFO"%s: ISR Setup..\n", gDrvrName);if (0 > request_irq(gIrq, &XPCIe_IRQHandler, IRQF_SHARED | IRQF_SAMPLE_RANDOM, gDrvrName, gDev)) {printk(KERN_WARNING"%s: Init: Unable to allocate IRQ",gDrvrName);return (CRIT_ERR);}// Update flags stating IRQ was successfully obtainedgStatFlags = gStatFlags | HA VE_IRQ;// Bus Master Enableif (0 > pci_enable_device(gDev)) {printk(KERN_WARNING"%s: Init: Device not enabled.\n", gDrvrName);return (CRIT_ERR);}//--- END: Initialize Hardware//--- START: Allocate Buffers// Allocate the read buffer with size BUF_SIZE and return the starting addressgReadBuffer = pci_alloc_consistent(gDev, BUF_SIZE, &gReadHWAddr);if (NULL == gReadBuffer) {printk(KERN_CRIT"%s: Init: Unable to allocate gBuffer.\n",gDrvrName);return (CRIT_ERR);}// Print Read buffer size and address to kernel logprintk(KERN_INFO"%s: Read Buffer Allocation: %X->%X\n", gDrvrName, (unsigned int)gReadBuffer, (unsigned int)gReadHW Addr);// Allocate the write buffer with size BUF_SIZE and return the starting addressgWriteBuffer = pci_alloc_consistent(gDev, BUF_SIZE, &gWriteHWAddr);if (NULL == gWriteBuffer) {printk(KERN_CRIT"%s: Init: Unable to allocate gBuffer.\n",gDrvrName);return (CRIT_ERR);}// Print Write buffer size and address to kernel logprintk(KERN_INFO"%s: Write Buffer Allocation: %X->%X\n", gDrvrName, (unsigned int)gWriteBuffer, (unsigned int)gWriteHW Addr); //--- END: Allocate Buffers//--- START: Register Driver// Register with the kernel as a character device.if (0 > register_chrdev(gDrvrMajor, gDrvrName, &XPCIe_Intf)) {printk(KERN_WARNING"%s: Init: will not register\n", gDrvrName);return (CRIT_ERR);}printk(KERN_INFO"%s: Init: module registered\n", gDrvrName);gStatFlags = gStatFlags | HA VE_KREG;//--- END: Register Driver// The driver is now successfully loaded. All HW is initialized, IRQ's assigned, and buffers allocatedprintk("%s driver is loaded\n", gDrvrName);// Initializing card registersXPCIe_InitCard();return 0;}//--- XPCIe_InitiatorReset(): Resets the XBMD reference design//--- Arguments: None//--- Return Value: None//--- Detailed Description: Writes a 1 to the DCSR register which resets the XBMD designvoid XPCIe_InitiatorReset(){XPCIe_WriteReg(0, 1); // Write: DCSR (offset 0) with value of 1 (Reset Device)XPCIe_WriteReg(0, 0); // Write: DCSR (offset 0) with value of 0 (Make Active)}//--- XPCIe_InitCard(): Initializes XBMD descriptor registers to default values//--- Arguments: None//--- Return Value: None//--- Detailed Description: 1) Resets device//--- 2) Writes specific values into the XBMD registers inside the EPvoid XPCIe_InitCard(){XPCIe_WriteReg(0, 1); // Write: DCSR (offset 0) with value of 1 (Reset Device)XPCIe_WriteReg(0, 0); // Write: DCSR (offset 0) with value of 0 (Make Active)XPCIe_WriteReg(2, gWriteHW Addr); // Write: Write DMA TLP Address register with starting address XPCIe_WriteReg(3, 0x20); // Write: Write DMA TLP Size register with default value (32dwords) XPCIe_WriteReg(4, 0x2000); // Write: Write DMA TLP Count register with default value (2000) XPCIe_WriteReg(5, 0x00000000); // Write: Write DMA TLP Pattern register with default value (0x0) XPCIe_WriteReg(6, 0xfeedbeef); // Write: Read DMA Expected Data Pattern with default value (feedbeef) XPCIe_WriteReg(7, gReadHW Addr); // Write: Read DMA TLP Address register with starting address. XPCIe_WriteReg(8, 0x20); // Write: Read DMA TLP Size register with default value (32dwords) XPCIe_WriteReg(9, 0x2000); // Write: Read DMA TLP Count register with default value (2000)}//--- XPCIe_exit(): Performs any cleanup required before releasing the device//--- Arguments: None//--- Return Value: None//--- Detailed Description: Performs all cleanup functions required before releasing devicestatic void XPCIe_exit(void){// Check if we have a memory region and free itif (gStatFlags & HA VE_REGION) {(void) release_mem_region(gBaseHdwr, XBMD_REGISTER_SIZE);}// Check if we have an IRQ and free itif (gStatFlags & HA VE_IRQ) {(void) free_irq(gIrq, gDev);}// Free Write and Read buffers allocated to useif (NULL != gReadBuffer)(void) kfree(gReadBuffer);(void) kfree(gWriteBuffer);// Free memory allocated to our Endpointpci_free_consistent(gDev, BUF_SIZE, gReadBuffer, gReadHW Addr);pci_free_consistent(gDev, BUF_SIZE, gWriteBuffer, gWriteHW Addr);gReadBuffer = NULL;gWriteBuffer = NULL;// Free up memory pointed to by virtual addressif (gBaseVirt != NULL) {iounmap(gBaseVirt);}gBaseVirt = NULL;// Unregister Device Driverif (gStatFlags & HA VE_KREG) {unregister_chrdev(gDrvrMajor, gDrvrName);}gStatFlags = 0;// Update Kernel log stating driver is unloadedprintk(KERN_ALERT"%s driver is unloaded\n", gDrvrName);}// Driver Entry Pointmodule_init(XPCIe_init);// Driver Exit Pointmodule_exit(XPCIe_exit);void XPCIe_IRQHandler(int irq, void *dev_id, struct pt_regs *regs){u32 i, regx;printk(KERN_WARNING"%s: Interrupt Handler Start ..",gDrvrName); for (i = 0; i < 32; i++) {regx = XPCIe_ReadReg(i);printk(KERN_W ARNING"%s Interrupt Handler End ..\n", gDrvrName);}u32 XPCIe_ReadReg (u32 dw_offset){u32 ret = 0;//u32 reg_addr = (u32)(gBaseVirt + (4 * dw_offset));//ret = readl(reg_addr);ret = readl(gBaseVirt + (4 * dw_offset));return ret;}void XPCIe_WriteReg (u32 dw_offset, u32 val){//u32 reg_addr = (u32)(gBaseVirt + (4 * dw_offset));writel(val, (gBaseVirt + (4 * dw_offset)));}ssize_t* XPCIe_ReadMem(char *buf, size_t count){int ret = 0;dma_addr_t dma_addr;//make sure passed in buffer is large enoughif ( count < BUF_SIZE ) {printk("%s: XPCIe_Read: passed in buffer too small.\n", gDrvrName);ret = -1;goto exit;}down(&gSem[SEM_DMA]);// pci_map_single return the physical address corresponding to// the virtual address passed to it as the 2nd parameterdma_addr = pci_map_single(gDev, gReadBuffer, BUF_SIZE, PCI_DMA_FROMDEVICE);if ( 0 == dma_addr ) {printk("%s: XPCIe_Read: Map error.\n",gDrvrName);ret = -1;// Now pass the physical address to the device hardware. This is now// the destination physical address for the DMA and hence the to be// put on Memory Transactions// Do DMA transfer here....printk("%s: XPCIe_Read: ReadBuf Virt Addr = %x Phy Addr = %x.\n",gDrvrName, (unsigned int)gReadBuffer, (unsigned int)dma_addr);// Unmap the DMA buffer so it is safe for normal access again.pci_unmap_single(gDev, dma_addr, BUF_SIZE, PCI_DMA_FROMDEVICE);up(&gSem[SEM_DMA]);// Now it is safe to copy the data to user space.if ( copy_to_user(buf, gReadBuffer, BUF_SIZE) ) {ret = -1;printk("%s: XPCIe_Read: Failed copy to user.\n",gDrvrName);goto exit;}exit:return ret;}ssize_t XPCIe_WriteMem(const char *buf, size_t count) {int ret = 0;dma_addr_t dma_addr;if ( (count % 4) != 0 ) {printk("%s: XPCIe_Write: Buffer length not dword aligned.\n",gDrvrName);ret = -1;goto exit;}// Now it is safe to copy the data from user space.if ( copy_from_user(gWriteBuffer, buf, count) ) {ret = -1;printk("%s: XPCIe_Write: Failed copy to user.\n",gDrvrName);goto exit;}//set DMA semaphore if in loopback// pci_map_single return the physical address corresponding to// the virtual address passed to it as the 2nd parameterdma_addr = pci_map_single(gDev, gWriteBuffer, BUF_SIZE, PCI_DMA_FROMDEVICE);if ( 0 == dma_addr ) {printk("%s: XPCIe_Write: Map error.\n",gDrvrName);ret = -1;goto exit;}// Now pass the physical address to the device hardware. This is now// the source physical address for the DMA and hence the to be// put on Memory Transactions// Do DMA transfer here....printk("%s: XPCIe_Write: WriteBuf Virt Addr = %x Phy Addr = %x.\n",gDrvrName, (unsigned int)gReadBuffer, (unsigned int)dma_addr);// Unmap the DMA buffer so it is safe for normal access again.pci_unmap_single(gDev, dma_addr, BUF_SIZE, PCI_DMA_FROMDEVICE);up(&gSem[SEM_DMA]);exit:return (ret);}u32 XPCIe_ReadCfgReg (u32 byte) {u32 pciReg;if (pci_read_config_dword(gDev, byte, &pciReg) < 0) {printk("%s: XPCIe_ReadCfgReg: Reading PCI interface failed.",gDrvrName);return (-1);}return (pciReg);}u32 XPCIe_WriteCfgReg (u32 byte, u32 val) {if (pci_write_config_dword(gDev, byte, val) < 0) {printk("%s: XPCIe_Read Device Control: Reading PCI interface failed.",gDrvrName);return (-1);}return 1;}。

PCI 类代码(CLASS CODE)

PCI 类代码(CLASS CODE)

类代码分类说明0x00前建成的设备类代码(即学前的PCI 2.0)0x01大容量存储控制器0x02网络控制器0x03显示控制器0x04多媒体设备0x05内存控制器0x06桥设备0x07简单的通信控制器0x08基本系统外设0x09 Inupt设备0x0A坞站0x0B Processorts0x0C串行总线控制器0x0D - 0xFE的保留0xFF的杂项类代码0:预2.0子类编。

I / F的说明0x00 0x00以外的所有设备的VGA0x01 0x01 VGA设备类别代号1:大容量存储控制器子类编。

I / F的说明0x00 0x00 SCSI控制器0x01 0xXX IDE控制器。

在PROG I / F的定义如下:位图示0经营模式(主)1可编程指标(小学组)2,工作模式(中学组)3可编程指标(中学组)6 .. 4保留(零)7主IDE设备0x02 0x00软盘控制器0x03 0x00新闻学会控制器0x04 0x00 RAID控制器0x80 0x00其他大容量存储控制器类代码2:网络控制器子类编。

I / F的说明0x00 0x00以太网控制器0x01 0x00令牌环0x02 0x00 FDDI的控制器0x03 0x00控制器自动柜员机0x80 0x00其他网络conteroller类代码3:显示控制器子类编。

I / F的说明0x00 0x00 VGA兼容控制器。

先后为0xA0000 .. 0xBFFFF和IO地址0x3B0 .. 0x3BB映射。

0x01 8514兼容0x01 0x00的XGA控制器0x80 0x80其他显示控制器类的代码4:多媒体设备子类编。

I / F的说明0x00 0x00视频设备0x01 0x00音频设备0x80 0x00其他多媒体设备类代码5:内存控制器子类编。

I / F的说明0x00 0x00 RAM控制器0x01 0x00闪存控制器0x80 0x00其他内存控制器类代码6:桥设备子类编。

linux pci 设备命名规则

linux pci 设备命名规则

linux pci 设备命名规则Linux PCI设备命名规则PCI (Peripheral Component Interconnect)是一种计算机总线标准,它允许多个设备通过一个通用的总线连接到计算机系统。

在Linux系统中,PCI设备在内核中被识别和管理。

本文将介绍Linux中PCI设备的命名规则,并逐步回答有关此主题的问题。

第一部分:Linux PCI设备命名规则在Linux系统中,每个PCI设备都被分配了一个唯一的标识符,该标识符被称为“BDF”(Bus, Device, Function)。

BDF标识符由以下三个字段组成:1. 总线(Bus):表示设备所连接的总线号码,范围为0-255。

在Linux 中,总线号码通常以`/sys/bus/pci/devices/`目录下的子目录名的形式存在,例如,`/sys/bus/pci/devices/0000:0e:00.0`。

2. 设备(Device):表示同一总线上的设备号码,范围为0-31。

设备号码以`.0`结尾。

在Linux中,每个设备都有一个唯一的目录,其路径为`/sys/bus/pci/devices/0000:0e:00.0`。

3. 功能(Function):表示设备上的功能号码,范围为0-7。

功能号码通常以`.0`结尾,并且在同一设备的功能之间以句点分隔,例如,`0000:0e:00.0`和`0000:0e:00.1`。

根据这些规则,Linux系统中任何一个PCI设备都可以通过BDF标识符进行唯一地识别和访问。

第二部分:回答问题1. 如何找到PCI设备的BDF标识符?在Linux系统中,可以使用以下命令来找到PCI设备的BDF标识符:lspci -nn该命令将列出系统中所有PCI设备的信息,包括设备的BDF标识符。

2. 如何确定PCI设备的总线号码?可以使用以下命令来确定PCI设备的总线号码:lspci -s <PCI地址> -t其中,`<PCI地址>`是设备的PCI地址。

pic16f54汇编

pic16f54汇编

pic16f54汇编
PIC16F54是一款由Microchip Technology生产的8位微控制器,基于精简指令集(RISC)架构。

以下是一些关于如何使用汇编语言编写PIC16F54微控制器的代码的简短说明:
1. 基本语法: PIC汇编语言有一些基本的语法规则。

例如,你可以使用
`MOV`指令来移动数据,使用`ADD`指令来执行加法操作,等等。

2. 寄存器: PIC微控制器有一些特定的寄存器,如W(工作寄存器)和
Data Registers。

你需要知道这些寄存器以及如何使用它们。

3. 指令集: PIC16F54有一些特定的指令集,包括数据传输指令、算术指令、逻辑指令、程序流控制指令等。

你需要熟悉这些指令集以编写有效的代码。

4. 程序结构: 汇编语言程序通常有一个明确的程序结构,包括初始化部分、
主循环部分等。

对于PIC16F54,你还需要设置适当的配置位来配置微控制
器的行为。

5. 注释: 在汇编代码中添加注释是一个好习惯,这可以帮助你和其他人理解
代码的工作原理。

6. 工具链: 你需要一个适当的工具链来编译、链接和烧写你的代码。

对于
PIC微控制器,常用的工具链包括MPLAB X IDE和XC8编译器。

请注意,具体实现会根据具体的项目需求和你所使用的开发环境有所不同。

建议查阅Microchip的官方文档和资源以获取更详细的信息和示例代码。

PCI侦测诊断卡代码大全

PCI侦测诊断卡代码大全

代码说明00已显示系统的配置;即将控制INI19引导装入。

01处理器测试1,处理器状态核实,如果测试失败,循环是无限的。

处理器寄存器的测试即将开始,不可屏蔽中断即将停用。

CPU寄存器测试正在进行或者失败。

02确定诊断的类型(正常或者制造)。

如果键盘缓冲器含有数据就会失效。

停用不可屏蔽中断;通过延迟开始。

CMOS写入/读出正在进行或者失灵。

03清除8042键盘控制器,发出TESTKBRD命令(AAH)通电延迟已完成。

ROM BIOS检查部件正在进行或失灵。

04使8042键盘控制器复位,核实TESTKBRD。

键盘控制器软复位/通电测试。

可编程间隔计时器的测试正在进行或失灵。

05如果不断重复制造测试1至5,可获得8042控制状态。

已确定软复位/通电;即将启动ROM。

DMA初如准备正在进行或者失灵。

06使电路片作初始准备,停用视频、奇偶性、DMA电路片,以及清除DMA电路片,所有页面寄存器和CMOS停机字节。

已启动ROM计算ROM BIOS检查总和,以及检查键盘缓冲器是否清除。

DMA初始页面寄存器读/写测试正在进行或失灵。

07处理器测试2,核实CPU寄存器的工作。

ROM BIOS检查总和正常,键盘缓冲器已清除,向键盘发出BAT(基本保证测试)命令。

08使CMOS计时器作初始准备,正常的更新计时器的循环。

已向键盘发出BAT命令,即将写入BAT命令。

RAM更新检验正在进行或失灵。

09 EPROM检查总和且必须等于零才通过。

核实键盘的基本保证测试,接着核实键盘命令字节。

第一个64K RAM测试正在进行。

0A使视频接口作初始准备。

发出键盘命令字节代码,即将写入命令字节数据。

第一个64K RAM芯片或数据线失灵,移位。

0B测试8254通道0。

写入键盘控制器命令字节,即将发出引脚23和24的封锁/解锁命令。

第一个64K RAM奇/偶逻辑失灵。

0C测试8254通道1。

键盘控制器引脚23、24已封锁/解锁;已发出NOP命令。

PCI信号定义说明(中文版)

PCI信号定义说明(中文版)

PCI信号定义说明(中文版)1. AD[31:0] (PCI ADDRESS / DATA BUS)地址与数据总线讯号,在FRAME#启动后地址才有效,在PCLK第一个CLOCK 动作初始化时,FRAME#动作后,输出为地址与数据,写入周期,输入为数据,读取周期 TRDY# 与IRDY#会动作,高阻抗时,为数据转换周期或RESET#动作2. C/BE[3:0]# (PCI COMMAND /BYTE ENABLES)FRAME#启动后,CLOCK第一个CLOCK,周期为PCI命令,再下一个周期为允许命令,命令在FRAME#后有效,数据在TRDY#与IRDY#后有效3. DEVSEL# (PCI DEVSEL SELECT)确定外部外围连结之响应讯号,高阻抗时,为停止周期或RESET#动作时4. FRAME# (PCI CYCLE FRAME)PCI 总线起始讯号5. GNT[4:0]# (PCI BUS GRANT)PCI 总线控制认可讯号6. IRDY# (INITIATOR READY)数据读取写入讯号7. LOCK# (PCI BUS LOCK)总线锁住讯号8. PAR (PCI BUS PARITY)地址与位传送之同位检错讯号9. PCLK (PCI CLOCK)PCI 时脉讯号10.PGNT# (PCI GRANT TO PERIPHERAL BUS CONTROLLER)PCI 总线对外部外围装置之需求同意认可讯号11. PERQ# (PCI REQUEST FROM PERIPHERAL BUS CONTROLLER)外围处理器对PCI总线要求讯号12. REQ[4:0]# (PCI BUS REQUEST)PCI 总线需求讯号13. RESET# (RESET)系统重置讯号14. SERR# (SYSTEM ERROR)系统错误侦测讯号可产生NMI 不可屏蔽中断15. STOP# (PCI BUS STOP)PCI 总线放弃或重试数据传送之讯号16. TRDY# (TARGET READY)PCI 总线数据读取传送讯号17.WSC# (WRITE SNOOP COMPLETE)I /O APIC 芯片有上时之中断讯息传送讯号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

PCI从设备代码说明:library ieee;use ieee.std_logic_1164.all;use ieee.std_logic_unsigned.all;entity pcislave is port( //PCI接口说明//CLK:33M PCI 时钟;//RST : PCI 复位,低有效;// IDSEL : PCI 配置空间选择,高有效;// FRAME :PCI 祯周期开始,低有效;// IRDY : PCI主设备准备好,低有效;clk,rst,idsel,frame,irdy : in std_logic;// TRDY : PCI目标设备准备好,低有效;// DEVSEL :PCI目标设备选择,低有效;// STOP : PCI目标设备停止,低有效;trdy,devsel,stop : inout std_logic;// PCI 效验输出使能,高有效;paren1 : out std_logic;// DATA RD OUT :局部总线读输出信号,高有效;// DATA WR :局部总线写输出信号,高有效;// DMASEL :DMA允许,高有效;data_rd_out,data_wr,dmasel : out std_logic;// IOSEL : IO空间选择输出,高有效;// MEMSEL :内存空间选择输出,高有效;iosel,memsel : buffer std_logic;// EXT ADD :局部总线地址译码输出,IO空间只用(7 到0)ext_add : out std_logic_vector(21 downto 0);// CBE :PCI命令及字节输入cbe : in std_logic_vector(3 downto 0);// AD : PCI地址及数据复用信号ad : inout std_logic_vector(31 downto 0));end pcislave;architecture beha of pcislave is// 目标读状态机type slaverdst is (idle1,dev_st1,rdst1,rdst2,rdst3,rdst4,rdstopst,ctst1);//目标写状态机type slavewrst is (idle2,dev_st2,wrst1,wrst2,wrst3,wrst4,wrstopst,ctst2);signal pre_state1,nxt_state1 : slaverdst;signal pre_state2,nxt_state2 : slavewrst;// PCI配置空间定义:// PCI ID号定义constant id : std_logic_vector(31 downto 0) :="01000010010110000001000100000000"; // PCI 设备类型定义constant clss : std_logic_vector(31 downto 0) :="00000100000000000000000000000000";//PCI 编程接口类型定义:constant ht : std_logic_vector(31 downto 0) :="00000000000000000010000000000000";//PCI 保留空间定义,全‘0’constant res : std_logic_vector(31 downto 0) :="00000000000000000000000000000000";//PCI 保留地址译码,全‘0’constant base : std_logic_vector(31 downto 0) :="00000000000000000000000000000000"; signal add,basereg1,basereg0,wrreg,intreg,stc,dqreg : std_logic_vector(31 downto 0);signal cmd : std_logic_vector(3 downto 0);signal st_clr,st_clr1,io_sel,iordsel,iowrsel,memrdsel,memwrsel,membase0_sel : std_logic; signal iobase0_sel,ioen,memen,io_rd_sel,io_wr_sel,mem_rd_sel,mem_wr_sel,cfg_sel : std_logic; signal rdsel,wrsel,dev_sel,cfg_rd_sel,cfg_wr_sel,devid,statecmd,classcd,hdtp : std_logic;signal base0,base1,base2,base3,base4,base5,res1,res2,res3,res4,res5,int_sel : std_logic;signal cfgwr,cfgwr1,data_out,data_out1,spar_en : std_logic;begincon_st : process(clk,rst)begin //PCI目标命令及地址锁存if rst='0' then add<=(others=>'0');cmd<=(others=>'0');elsif rising_edge(clk) thenif (frame='0' and irdy='1' and trdy='1' and devsel='1' and stop='1')then cmd<=cbe;add<=ad;end if;end if;// PCI IO及内存空间访问锁存if (rst='0' or st_clr='1') then io_sel<='0';elsif rising_edge(clk) thenif (frame='0' and irdy='1' and trdy='1' and devsel='1' and stop='1')then io_sel<='1';else io_sel<='0';end if;end if;// PCI IO命令译码if cmd="0010" then iordsel<='1';else iordsel<='0';end if;if cmd="0011" then iowrsel<='1';else iowrsel<='0';end if;//PCI内存命令译码if cmd="0110" then memrdsel<='1';else memrdsel<='0';end if;if cmd="0111" then memwrsel<='1';else memwrsel<='0';end if;//PCI内存空间访问地址选中if (add(31 downto 22)=basereg1(31 downto 22)) then membase0_sel<='1';else membase0_sel<='0';end if;//PCI IO空间访问地址选中if add(15 downto 8)=basereg0(15 downto 8) then iobase0_sel<='1';else iobase0_sel<='0';end if;// PCI IO访问及内存访问地址选中if io_sel='1' and iordsel='1' and iobase0_sel='1' and ioen='1' then io_rd_sel<='1';else io_rd_sel<='0';end if;if io_sel='1' and iowrsel='1' and iobase0_sel='1' and ioen='1' then io_wr_sel<='1';else io_wr_sel<='0';end if;if io_sel='1' and memrdsel='1' and membase0_sel='1' and memen='1' then mem_rd_sel<='1';else mem_rd_sel<='0';end if;if io_sel='1' and memwrsel='1' and membase0_sel='1' and memen='1' then mem_wr_sel<='1';else mem_wr_sel<='0';end if;//PCI配置空间访问选中if (rst='0' or st_clr='1') then cfg_sel<='0';elsif rising_edge(clk) thenif (idsel='1' and frame='0' and irdy='1' and trdy='1' and devsel='1' and stop='1') then cfg_sel<='1';else cfg_sel<='0';end if;end if;//PCI配置访问译码输出if cmd="1010" then rdsel<='1';else rdsel<='0';end if;if cmd="1011" then wrsel<='1';else wrsel<='0';end if;//PCI配置空间访问译码if (add(10 downto 6)="00000" and add(1 downto 0)="00") then dev_sel<='1';else dev_sel<='0';end if;if cfg_sel='1' and dev_sel='1' and rdsel='1' then cfg_rd_sel<='1';else cfg_rd_sel<='0';end if;if cfg_sel='1' and dev_sel='1' and wrsel='1' then cfg_wr_sel<='1';else cfg_wr_sel<='0';end if;//PCI空间访问地址译码if rising_edge(clk) thenif add(5 downto 2)="0000" then devid<='1';else devid<='0';end if;if add(5 downto 2)="0001" then statecmd<='1';else statecmd<='0';end if; if add(5 downto 2)="0010" then classcd<='1';else classcd<='0';end if;if add(5 downto 2)="0011" then hdtp<='1';else hdtp<='0';end if;if add(5 downto 2)="0100" then base0<='1';else base0<='0';end if;if add(5 downto 2)="010 1" then base1<='1';else base1<='0';end if;if add(5 downto 2)="0110" then base2<='1';else base2<='0';end if;if add(5 downto 2)="0111" then base3<='1';else base3<='0';end if;if add(5 downto 2)="1000" then base4<='1';else base4<='0';end if;if add(5 downto 2)="1001" then base5<='1';else base5<='0';end if;if add(5 downto 2)="1010" then res1<='1';else res1<='0';end if;if add(5 downto 2)="1011" then res2<='1';else res2<='0';end if;if add(5 downto 2)="1100" then res3<='1';else res3<='0';end if;if add(5 downto 2)="1101" then res4<='1';else res4<='0';end if;if add(5 downto 2)="1110" then res5<='1';else res5<='0';end if;if add(5 downto 2)="1111" then int_sel<='1';else int_sel<='0';end if;end if;//PCI从读状态机case pre_state1 iswhen idle1 => if (cfg_rd_sel='1' or io_rd_sel='1' or mem_rd_sel='1')then nxt_state1<=dev_st1;else nxt_state1<=idle1;end if;when dev_st1 => if irdy='0' then nxt_state1<=rdst1;else nxt_state1<=dev_st1;end if;when rdst1 => if irdy='0' then nxt_state1<=rdst2;else nxt_state1<=rdst1;end if;when rdst2 => if irdy='0' then nxt_state1<=rdst3;else nxt_state1<=rdst2;end if;when rdst3 => if irdy='0' then nxt_state1<=rdst4;else nxt_state1<=rdst3;end if;when rdst4 => if frame='0' then nxt_state1<=rdstopst;else nxt_state1<=ctst1;end if;when rdstopst => if frame='0' or irdy='0' then nxt_state1<=rdstopst;else nxt_state1<=ctst1;end if;when ctst1 => nxt_state1<=idle1;when others=> nxt_state1<=idle1;end case;//PCI从写状态机case pre_state2 iswhen idle2=> if (cfg_wr_sel='1' or io_wr_sel='1' or mem_wr_sel='1')then nxt_state2<=dev_st2;else nxt_state2<=idle2;end if;when dev_st2=> if irdy='0' then nxt_state2<=wrst1;else nxt_state2<=dev_st2;end if;when wrst1=> if irdy='0' then nxt_state2<=wrst2;else nxt_state2<=wrst1;end if;when wrst2=> if irdy='0' then nxt_state2<=wrst3;else nxt_state2<=wrst2;end if;when wrst3=> if irdy='0' then nxt_state2<=wrst4;else nxt_state2<=wrst3;end if;when wrst4=> if frame='0' then nxt_state2<=wrstopst;else nxt_state2<=ctst2;end if;when wrstopst => if frame='0' or irdy='0' then nxt_state2<=wrstopst;else nxt_state2<=ctst2;end if;when ctst2 => nxt_state2<=idle2;when others=> nxt_state2<=idle2;end case;if rst='0' then wrreg<=(others=>'0');elsif rising_edge(clk) then wrreg<=ad;end if;//配置空间0地址寄存器if rst='0' then basereg0<="11111111111111111111111100000001";elsif rising_edge(clk) thenif (cfgwr='1' and base0='1' and wrsel='1') thenbasereg0(31 downto 8)<=wrreg(31 downto 8);basereg0(7 downto 0)<="00000001";end if;end if;//配置空间1地址寄存器if rst='0' then basereg1<="11111111110000000000000000000000";elsif rising_edge(clk) thenif (cfgwr='1' and base1='1' and wrsel='1') thenbasereg1(31 downto 22)<=wrreg(31 downto 22);basereg1(21 downto 0)<="0000000000000000000000";end if;end if;//配置空间中断寄存器if rst='0' then intreg<="00000000000000000000000111111111";elsif rising_edge(clk) thenif (cfgwr='1' and int_sel='1' and wrsel='1') thenintreg(31 downto 8)<="000000000000000000000001";intreg(7 downto 0)<=wrreg(7 downto 0);end if;end if;//配置空间状态及命令寄存器if rst='0' then stc<="00000100000000000000000000000000";elsif rising_edge(clk) thenif (cfgwr='1' and statecmd='1' and wrsel='1') thenstc(31 downto 3)<="00000100000000000000000000000";stc(2 downto 0)<=wrreg(2 downto 0);end if;end if;ioen<=stc(0);memen<=stc(1);dmasel<=stc(2);PCI读效验产生if rst='0' then paren1<='0';cfgwr<='0';st_clr<='0';data_out<='0';elsif rising_edge(clk) thenparen1<=spar_en;cfgwr<=cfgwr1;st_clr<=st_clr1;data_out<=data_out1;end if;if rising_edge(clk) thenif devid='1' then dqreg<=id;elsif statecmd='1' then dqreg<=stc;elsif classcd='1' then dqreg<=clss;elsif hdtp='1' then dqreg<=ht;elsif res1='1' or res2='1' or res3='1' or res4='1' or res5='1'or base2='1' or base3='1' or base4='1' or base5='1' then dqreg<=base; elsif base0='1' then dqreg<=basereg0;elsif base1='1' then dqreg<=basereg1;elsif int_sel='1' then dqreg<=intreg;else dqreg<=(others=>'0');end if;end if;end process;//PCI数据输出ad<=dqreg when data_out='1' and rdsel='1'else "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";state1_pro : process(clk,rst)begin if rst='0' then pre_state1<=idle1;elsif rising_edge(clk) then pre_state1<=nxt_state1;end if;end process;state2_pro : process(clk,rst)begin if rst='0' then pre_state2<=idle2;elsif rising_edge(clk) then pre_state2<=nxt_state2;end if;end process;//PCI效验信号产生spar_en<='1' when pre_state1=rdst4else '0';//局部总线写信号产生cfgwr1<='1' when pre_state2=wrst2 or pre_state2=wrst3 else '0';st_clr1<='1' when pre_state1=dev_st1 or pre_state2=dev_st2 else '0';//局部总线读信号产生data_out1<='1' when pre_state1=rdst1 or pre_state1=rdst2or pre_state1=rdst3 or pre_state1=rdst4else '0';//PCI目标选择信号输出devsel<='0' when pre_state1=dev_st1 or pre_state1=rdst1 or pre_state1=rdst2or pre_state1=rdst3 or pre_state1=rdst4 or pre_state1=rdstopstor pre_state2=dev_st2 or pre_state2=wrst1 or pre_state2=wrst2or pre_state2=wrst3 or pre_state2=wrst4 or pre_state2=wrstopst else '1' when pre_state1=ctst1 or pre_state2=ctst2else 'Z';//PCI目标准备好信号输出trdy<='0' when pre_state1=rdst4 or pre_state2=wrst4else '1' when pre_state1=dev_st1 or pre_state1=rdst1 or pre_state1=rdst2or pre_state1=rdst3 or pre_state1=rdstopstor pre_state2=dev_st2 or pre_state2=wrst1 or pre_state2=wrst2or pre_state2=wrst3 or pre_state2=wrstopstor pre_state1=ctst1 or pre_state2=ctst2else 'Z';//PCI目标停止信号输出stop<='0' when pre_state1=rdstopst or pre_state2=wrstopstelse '1' when pre_state1=dev_st1 or pre_state1=rdst1 or pre_state1=rdst2or pre_state1=rdst3 or pre_state1=rdst4or pre_state2=dev_st2 or pre_state2=wrst1 or pre_state2=wrst2or pre_state2=wrst3 or pre_state2=wrst4or pre_state1=ctst1 or pre_state2=ctst2else 'Z';// 局部总线读信号输出data_rd_out<=data_out and ((iordsel and iobase0_sel)or (memrdsel and membase0_sel));//局部总线io译码输出iosel<=(iordsel or iowrsel) and iobase0_sel;//局部总线内存译码输出memsel<=(memrdsel or memwrsel) and membase0_sel;//局部总线写信号输出data_wr<=cfgwr and ((iowrsel and iobase0_sel) or(memwrsel and membase0_sel));//局部总线地址输出ext_add<=add(21 downto 0);end beha;。

相关文档
最新文档