您的位置:首页 > 其它

访问pci设备中寄存器的一些方法

2015-08-25 15:40 267 查看
pio_start = pci_resource_start (pdev, 0);

pio_end = pci_resource_end (pdev, 0);

pio_flags = pci_resource_flags (pdev, 0);

pio_len = pci_resource_len (pdev, 0);

mmio_start = pci_resource_start (pdev, 1);

mmio_end = pci_resource_end (pdev, 1);

mmio_flags = pci_resource_flags (pdev, 1);

mmio_len = pci_resource_len (pdev, 1);

这样看来0号bar就是提供的io映射,1号bar提供内存映射。所以我想如果自己写一个以太网驱动的话,关于这块的代码就可以精简一下,只使用内存映射的方法就可以了。下面是网上有人写的几种不同方式测试代码,他这些代码应该是在x86上试的,我没有试过,先分析,周末搞到arm上去跑一下。

[第一种]

unsigned long mmio_start, addr1, addr2;

void __iomem *ioaddr;

mmio_start = pci_resource_start( pdev, 1);

ioaddr = pci_iomap(pdev, 1, 0);

addr1 = ioread32( ioaddr );

addr2 = ioread32( ioaddr + 4 );

printk(KERN_INFO "mmio start: %lX\n", mmio_start);

printk(KERN_INFO "ioaddr: %p\n", ioaddr);

printk(KERN_INFO "%02lX.%02lX.%02lX.%02lX.%02lX.%02lX\n",

(addr1) & 0xFF,

(addr1 >> 8) & 0xFF,

(addr1 >> 16 ) & 0xFF,

(addr1 >> 24 ) & 0xFF,

(addr2) & 0xFF,

(addr2 >> 8) & 0xFF );

运行结果:

Mar 10 22:34:56 localhost kernel: mmio start: E0000800

Mar 10 22:34:56 localhost kernel: ioaddr: f8aa6800

Mar 10 22:34:56 localhost kernel: 00.02.3F.AC.41.9D

------------------------------------------------------------------------------------------------

这种方法采用内存映射的方法,得到bar1的物理地址,mmio_start然后由pci_ioremap函数把bar1的这段地址映射到内核虚拟地址空间。然后用ioread32()函数读出里面的值。这个ioread32函数不知道是怎么定义的,要查一查。

---------------------------------------------------------------------------------------------------

[第二种]

unsigned long pio_start, pio_len, addr1, addr2;

void __iomem *ioaddr;

pio_start = pci_resource_start( pdev, 0);

pio_len = pci_resource_len (pdev, 0);

ioaddr = ioport_map(pio_start, pio_len);

addr1 = ioread32( ioaddr );

addr2 = ioread32( ioaddr + 4 );

printk(KERN_INFO "pio start: %lX\n", pio_start);

printk(KERN_INFO "ioaddr: %p\n", ioaddr);

printk(KERN_INFO "%02lX.%02lX.%02lX.%02lX.%02lX.%02lX\n",

(addr1) & 0xFF,

(addr1 >> 8) & 0xFF,

(addr1 >> 16 ) & 0xFF,

(addr1 >> 24 ) & 0xFF,

(addr2) & 0xFF,

(addr2 >> 8) & 0xFF );

运行结果:

Mar 10 22:30:52 localhost kernel: pio start: 3400

Mar 10 22:30:52 localhost kernel: ioaddr: 00013400

Mar 10 22:30:52 localhost kernel: 00.02.3F.AC.41.9D

-------------------------------------------------------------------------------------------------------

这种方式是使用io端口映射,首先在bar0得到io端口的物理首地址和其长度,然后使用ioport_map将物理地址映射到内核虚拟空间。然后使用的读写函数仍然是ioread32

-------------------------------------------------------------------------------------------------------

[第三种]

unsigned long pio_start, addr1, addr2;

pio_start = pci_resource_start( pdev, 0 );

addr1 = inl( pio_start );

addr2 = inl( pio_start + 4 );

printk(KERN_INFO "port io start: %lX\n", pio_start);

printk(KERN_INFO "%02lX.%02lX.%02lX.%02lX.%02lX.%02lX\n",

(addr1) & 0xFF,

(addr1 >> 8) & 0xFF,

(addr1 >> 16) & 0xFF,

(addr1 >> 24) & 0xFF,

(addr2) & 0xFF,

(addr2 >> 8) & 0xFF );

运行结果:

Mar 10 22:36:18 localhost kernel: port io start: 3400

Mar 10 22:36:18 localhost kernel: 00.02.3F.AC.41.9D

---------------------------------------------------------------------------------------------------------

这里也是使用io映射,估计这里的inl函数有phy->virt转化的功能,不知道他引用的哪里的。

----------------------------------------------------------------------------------------------------------

[第四种]

unsigned long pio_start;

u8 addr1, addr2, addr3, addr4, addr5, addr6;

pio_start = pci_resource_start( pdev, 0 );

addr1 = inb( pio_start );

addr2 = inb( pio_start + 1 );

addr3 = inb( pio_start + 2 );

addr4 = inb( pio_start + 3 );

addr5 = inb( pio_start + 4 );

addr6 = inb( pio_start + 5 );

printk(KERN_INFO "port io start: %lX\n", pio_start);

printk(KERN_INFO "%02X.%02X.%02X.%02X.%02X.%02X\n",

addr1, addr2, addr3, addr4, addr5, addr6 );

运行结果:

Mar 10 22:37:19 localhost kernel: port io start: 3400

Mar 10 22:37:19 localhost kernel: 00.02.3F.AC.41.9D
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: