PowerPC架构下Linux系统读写PCI设备

本文介绍了在PowerPC架构的Linux系统中如何开发PCI驱动程序。由于PowerPC无法直接通过端口访问PCI设备,作者采用将PCI设备内存映射到内核空间的方法,通过ioremap函数实现。内容包括PCI驱动的编写、字符驱动的实现,以及用户空间如何通过内核驱动读写PCI设备。
摘要由CSDN通过智能技术生成

最近需要完成一个linux系统下的PCI驱动程序,然而处理器是PowerPC架构,以为在linux用户态就可以实现,但是发现不行。

上一篇文章中通过I/O端口访问了PCI设备,但是x86家族之外的的处理器都不为端口提供独立的地址空间,因此PowerPC下无法直接通过地址用in/out方法来访问PCI设备。

于是我使用另外一种机制:将PCI设备的空间映射到内存中。


实现思路

  1. 完成PCI驱动代码,确保特定的PCI设备被linux识别
  2. 同时 还需要创建一个 字符设备驱动 可以让用户从用户空间传数据
  3. 先从 用户空间传数据到内核空间 然后 在内核空间操作PCI的内存
  4. 操作PCI内存的方式 是 读取 bar0的基地址 然后 ioremap 返回的地址 之后就可以在内核空间读写

原理图如下:
这里写图片描述

PCI驱动

pci驱动代码很简单,我们提供设备ID和厂商ID,并指定数据结构pci_driver中的id_table以及初始化函数probe和移除函数remove。

同时在内核模块加载时调用pci_register_driver 和卸载时调用pci_unregister_driver 函数。一个简单的模板代码如下:

#define PCI_VENDOR_ID_XILINX 0x10ee //change to your pci device
#define PCI_DEVICE_ID_XILINX 0x7021
#define MODULE_NAME "xilinx_7021"

static int __init xilinx_probe(struct pci_dev *pci_dev, const struct pci_device_id *pci_id);
static int xilinx_release(struct inode *inode, struct file *file);

static struct pci_device_id xilinx_pci_tbl [] __initdata = {
    {PCI_VENDOR_ID_XILINX, PCI_DEVICE_ID_XILINX, PCI_ANY_ID, PCI_ANY_ID},
    {
  0,}
};

static struct pci_driver xilinx_pci_driver = {
    name:       MODULE_NAME,    
    id_table:   xilinx_pci_tbl,   
    probe:      xilinx_probe,
    remove:     xilinx_release  
};

字符驱动

字符驱动提供了操作设备内存的方法,包括读写,从而用户打开设备后可以方便的读写设备内存。本文不谈及实现linux字符驱动实现的细节,详情可以参考博客:
字符驱动

ioremap

ioremap函数将PCI内存空间转换到内核空间,从而驱动程序可以访问任意的PCI内存地址。因此当我们加载了PCI设备时,我们可以将PCI配置空间的bar0地址保存,之后读写的时候将bar0地址用ioremap函数转换,然后用ioread/iowrite函数进行读写,如下例:

virt_addr =ioremap(bar0_s,bar0_l);
read_result = ioread32(virt_addr+4*size);
iowrite32(writenum,virt_addr+4*size);

用户空间代码

用户空间代码相对简单,只要就行代开对应大的字符设备驱动,然后读写即可。代码如下:

int main(int argc, const char *argv[])
{
    int fd ;
    int n;


    fd = open("/dev/dev_driver",O_RDWR);//对应的字符设备名称,由自己定义
    if(fd < 0){
        perror("Fail ot open");
        return -1;
    }

    printf("open successful ,fd = %d\n",fd);

    unsigned long writenum=2112;
    n = write(fd,&writenum,sizeof(long));
    if(n < 0){
        perror("Fail to write");
        return -1;
    }


    printf("write %d bytes!\n",n);
    unsigned long read_result;
    read(fd,&read_result,sizeof(long));

        printf("the my_driver is %d\n",read_result);
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值