title: PCI driver to fetch MAC address
body: <p>I was trying to write a pci driver which can display the MAC address of my Ethernet card.
  Running a Ubuntu on VM and my Ethernet card is Intel one as follows
  00:08.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)</p>
  
  <p>I was able to get the data sheet of the same from Intel website and as per data sheet it says IO address are mapped to Bar 2 (Refer to pg 87) and MAC can be read using RAL/RAH register which are at offset RAL (05400h + 8*n; R/W) and RAH (05404h + 8n; R/W)
  2 18h IO Register Base Address (bits 31:2) 0b mem</p>
  
  <p>Based on this information, i wrote a small PCI driver but i always get the MAC as fff and when i debugged further, i see io_base address is always zero.</p>
  
  <p>Below is the code</p>
  
  <pre><code> 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 &lt;linux/kernel.h&gt;
    8 #include &lt;linux/module.h&gt;
    9 #include &lt;linux/stddef.h&gt;
   10 #include &lt;linux/pci.h&gt;
   11 #include &lt;linux/init.h&gt;
   12 #include &lt;linux/cdev.h&gt;
   13 #include &lt;linux/device.h&gt;
   14 #include &lt;asm/io.h&gt;
   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(&amp;pci_driver_DevicePCI);
   52 
   53         return ret;
   54 }
   55 
   56 void cleanup_module(void)
   57 {
   58         pci_unregister_driver(&amp;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 &lt; 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 
  </code></pre>
  
  <p>lspci -x output of my card
  00:08.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
  00: 86 80 0e 10 07 00 30 02 02 00 00 02 00 40 00 00
  10: 00 00 82 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 00 86 80 1e 00
  30: 00 00 00 00 dc 00 00 00 00 00 00 00 09 01 ff 00</p>
  
  <p>Can any one let me know what am i doing wrong?</p>