Black God

How to find a PCI device in linux kernel module?

Last few days I am reading about PCI system. A part of this, I thought of getting my hand dirty by experimenting with PCI device specific code in linux kernel module. I expect the reader should have some fundamental knowledge about PCI devices and linux kernel module.

Here is a damn simple kernel module developed, whose job is to simply identify the SATA PCI Controller (HBA) which we are looking for. It prints the 64-bit addressing capability of this HBA. Apart from this, this module find the device by class code.

Test System:

Scientific Linux 6.0 (RHEL clone) on VirtualBOX OSE with SATA Controller from Intel (0x8086 is the vendor id) and product id of 0x2829.

I run the following command in test system to identify the above vendor and product ids of this SATA controller.

# lspci -x
………………………………………………..

00:0d.0 SATA controller: Intel Corporation 82801HBM/HEM (ICH8M/ICH8M-E) SATA AHCI Controller (rev 02)

00: 86 80 29 28 07 00 10 00 02 01 06 01 00 40 00 0010: 41 d0 00 00 49 d0 00 00 51 d0 00 00 59 d0 00 0020: 61 d0 00 00 00 60 80 f0 00 00 00 00 00 00 00 0030: 00 00 00 00 70 00 00 00 00 00 00 00 05 01 00 00

I assume you have kernel build environment ready. Here are the two files necessary. One is Makefile and another one is source code of module (aboutpci.c).

aboutpci.c:

#include
<linux/init.h>
#include
<linux/module.h>
#include
<linux/pci.h>

MODULE_LICENSE("Dual BSD/GPL");

#define    OUR_SATA_VENDOR_ID    0x8086
#define    OUR_SATA_PROD_ID    0x2829

static int aboutpci_init(void)
{
    struct pci_dev *dev = NULL;

    //Finding the device by Vendor/Device ID Pair
    dev = pci_get_device(OUR_SATA_VENDOR_ID, OUR_SATA_PROD_ID, dev);
    if (dev != NULL) {
        printk(KERN_ALERT "Our SATA HBA found!\n");
        if ( dev->dma_mask == DMA_BIT_MASK(64) )
            printk(KERN_ALERT "64-bit addressing capable!\n");
        else if ( dev->dma_mask == DMA_BIT_MASK(32) )
            printk(KERN_ALERT "32-bit addressing capable!\n");
    }
    else
        printk(KERN_ALERT "Our SATA HBA Not found!\n");

    //Finding the device by its class code
    dev = NULL;
    dev = pci_get_class(PCI_CLASS_STORAGE_SATA_AHCI, dev);
    if (dev != NULL) {
        printk(KERN_ALERT "SATA HBA Class device found!\n");
        printk(KERN_ALERT "Device Vendor ID: 0x%X\n", dev->vendor);
        printk(KERN_ALERT "Device Product ID: 0x%X\n", dev->device);
    }
    else
        printk(KERN_ALERT "SATA HBA Class device Not found!\n");

    return 0;
}

static void aboutpci_exit(void)
{
    printk(KERN_ALERT "Goodbye, pci hackers\n");
}

module_init(aboutpci_init);
module_exit(aboutpci_exit);

Makefile:

ifneq ($(KERNELRELEASE),)
    obj-m := aboutpci.o
else
    KERNELDIR := /lib/modules/$(shell uname -r)/build
    PWD := $(shell pwd)
default:
    $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
endif

Reference:

  1. Wikipedia on PCI
  2. Decoding PCI data and lspci output on Linux hosts
  3. PCI Vendor and Device Lists

2 comments for “How to find a PCI device in linux kernel module?

  1. Anonymous
    July 7, 2011 at 11:29 am

    Thanks for sharing your thoughts with us..they are really interesting.. I would like to read more from you.
    Opthamologist in CT

  2. June 30, 2011 at 10:45 am

    Great article …Thanks for your great information, the contents are quiet interesting. I will be waiting for your next post.

Leave a Reply

Your email address will not be published. Required fields are marked *