我正在尝试编写一个可以显示以太网卡MAC地址的pci驱动程序 . 在VM和我的以太网卡上运行Ubuntu是英特尔如下00:08.0以太网控制器:英特尔公司82540EM千兆以太网控制器(rev 02)
我能够从英特尔网站获得相同的数据表,并且根据数据表,它说IO地址映射到第2栏(参见第87页),并且可以使用RAL / RAH寄存器读取MAC,它们位于偏移RAL( 05400h 8 * n; R / W)和RAH(05404h8n; R / W)2 18h IO寄存器基址(位31:2)0b mem
基于这些信息,我写了一个小的PCI驱动程序,但我总是得到MAC作为fff,当我进一步调试时,我看到io_base地址始终为零 .
下面是代码
1 /*
2 Program to find a device on the PCI sub-system
3 */
4 #define VENDOR_ID 0x8086
5 #define DEVICE_ID 0x100e
6
7 #include <linux/kernel.h>
8 #include <linux/module.h>
9 #include <linux/stddef.h>
10 #include <linux/pci.h>
11 #include <linux/init.h>
12 #include <linux/cdev.h>
13 #include <linux/device.h>
14 #include <asm/io.h>
15
16 #define LOG(string...) printk(KERN_INFO string)
17
18 #define CDEV_MAJOR 227
19 #define CDEV_MINOR 0
20
21
22 MODULE_LICENSE("GPL");
23
24 struct pci_dev *pci_dev;
25 unsigned long mmio_addr;
26 unsigned long reg_len;
27 unsigned long *base_addr;
28
29 int device_probe(struct pci_dev *dev, const struct pci_device_id *id);
30 void device_remove(struct pci_dev *dev);
31
32 struct pci_device_id pci_device_id_DevicePCI[] =
33 {
34 {VENDOR_ID, DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
35 };
36
37 struct pci_driver pci_driver_DevicePCI =
38 {
39 name: "MyPCIDevice",
40 id_table: pci_device_id_DevicePCI,
41 probe: device_probe,
42 remove: device_remove
43 };
44
45
46 int init_module(void)
47 {
48 //struct pci_dev *pdev = NULL;
49 int ret = 0;
50
51 pci_register_driver(&pci_driver_DevicePCI);
52
53 return ret;
54 }
55
56 void cleanup_module(void)
57 {
58 pci_unregister_driver(&pci_driver_DevicePCI);
59
60 }
61
62 #define REGISTER_OFFSET 0x05400
64 int device_probe(struct pci_dev *dev, const struct pci_device_id *id)
65 {
66 int ret;
67 int bar = 2; // Bar to be reserved
68 unsigned long io_base = 0;
69 unsigned long mem_len = 0;
70 unsigned int register_data = 0;
71
72 LOG("Device probed");
73
74 /* Reserve the access to PCI device */
75 ret = pci_request_region(dev, bar, "my_pci");
76 if (ret) {
77 printk(KERN_ERR "request region failed :%d\n", ret);
78 return ret;
79 }
80
81 ret = pci_enable_device(dev);
82 if (ret < 0 ) LOG("Failed while enabling ... ");
83
84 io_base = pci_resource_start(dev, bar);
85 mem_len = pci_resource_len(dev, bar);
86
87 request_region(io_base, mem_len, "my_pci");
88 register_data = inw(io_base + REGISTER_OFFSET);
89 printk(KERN_INFO "IO base = %lx", io_base);
90 printk(KERN_INFO "MAC = %x", register_data);
91
92 return ret;
93 }
94
95 void device_remove(struct pci_dev *dev)
96 {
97 pci_release_regions(dev);
98 pci_disable_device(dev);
99 }
100
lspci -x输出我的卡00:08.0以太网控制器:Intel公司82540EM千兆以太网控制器(转02)00:86 80 0e 10 07 00 30 02 02 00 00 02 00 40 00 00 10:00 00 00 f0 00 00 00 00 41 d2 00 00 00 00 00 00 20:00 00 00 00 00 00 00 00 00 00 00 86 80 1e 00 30:00 00 00 00 00 00 00 00 00 00 00 00 09 01 ff 00
谁能让我知道我做错了什么?
1 回答
我修改了你的代码并评论了变化 . 我已删除所有现有注释以避免混淆,并且仅修改了探测功能 .
您需要在device_remove()例程中添加对iounmap()的相应调用 . 看看Intel E100E driver source code的一些好例子 .