Find the answer to your Linux question:
Results 1 to 5 of 5
Hi all, I have been browsing the net for almost a day now, for some guidance on how to carry on with a PCi driver... Actually I wanna code a ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #1
    Just Joined!
    Join Date
    Nov 2010
    Location
    Bangalore
    Posts
    7

    How to start with PCI or a PCI-Express driver


    Hi all,

    I have been browsing the net for almost a day now, for some guidance on how to carry on with a PCi driver...
    Actually I wanna code a PCI Express driver but starting with a PCI seems to be the proper way to go about it.

    I have done some simple loadable drivers for WDTs and GPIOs. I am not very well versed with statically compiled drivers.

    Taking advice from other threads I got the latest stable kernel 2.6.36 from kernel.org and started going through the drivers DIR. But I still seem to be lost. I am reading the chapter on PCI drivers in the LDD3 book and the sample driver provided with it, but I am not sure if it can help me with a PCI Express driver.

    The device model seems clear when I read the theory but when it comes to the coding I end up confusing myself again. I guess the fault is mine for not having a strong understanding on what is actually going on in the device model...!!!

    I am working on this alone so it seems a bit tough for me. So I am now seeking the help of someone as I am confused.

    Anush...
    __________________________________________________ _______________________
    I am not asking you to teach me everything... I am just asking you to teach me how to learn...

  2. #2
    Just Joined!
    Join Date
    Nov 2010
    Location
    Bangalore
    Posts
    7
    Hey can someone at least post a proper example of a PCI & PCI Express driver.

    Or if a driver example is present in the kernel source please just post the path where the driver is present.

    Anush...

  3. #3
    Just Joined!
    Join Date
    Nov 2010
    Location
    Bangalore
    Posts
    7
    Hi guys I finally found the sense to look for a driver based on the device. So I started looking for a pluggable PCI / PCI-E network card driver.

    Realtek has provided some sources for download on its site.
    218.210.127.131/downloads/downloadsView.aspx?Langid=1&PNid=10&PFid=13&Level= 4&Conn=3
    Alternatively the PCI based driver is found in the kernel sources (obtained from kernel.org) at the following location.

    linux-2.6.36/drivers/net/r8169.c

    And with regard to more details on understanding the PCI Standard APIs, look into the documentation provided along with the kernel source code.

    linux-2.6.36/Documentation/PCI/

    If there are some other simpler easier to understand drivers please suggest as the network card driver seems complicated due to the networking related code.

    With regard to the difference between a driver for a PCI and PCI-E driver only someone with more knowledge can shed light on it.

  4. $spacer_open
    $spacer_close
  5. #4
    Just Joined!
    Join Date
    Aug 2010
    Posts
    1
    Quote Originally Posted by Anush View Post
    Hi guys I finally found the sense to look for a driver based on the device. So I started looking for a pluggable PCI / PCI-E network card driver.

    Realtek has provided some sources for download on its site.
    218.210.127.131/downloads/downloadsView.aspx?Langid=1&PNid=10&PFid=13&Level= 4&Conn=3
    Alternatively the PCI based driver is found in the kernel sources (obtained from kernel.org) at the following location.

    linux-2.6.36/drivers/net/r8169.c

    And with regard to more details on understanding the PCI Standard APIs, look into the documentation provided along with the kernel source code.

    linux-2.6.36/Documentation/PCI/

    If there are some other simpler easier to understand drivers please suggest as the network card driver seems complicated due to the networking related code.

    With regard to the difference between a driver for a PCI and PCI-E driver only someone with more knowledge can shed light on it.
    hi anush.....
    even i am trying to find out some sample code for pci express......
    but could not locate it...
    i have checked at the link u have given (realtek one) but it is asking for NDA sort of things......
    if u have that sample code....could u please mail me....
    will be very thankful ....
    its just for learning purpose...
    thanks in advance.....
    Kapil
    Email: kapildev_verma@yahoo.com

  6. #5
    Just Joined!
    Join Date
    Nov 2010
    Location
    Bangalore
    Posts
    7

    Realtek 8139 example code

    Hey Kapil,

    Nice name... You must be a legend with your friends...
    I'm glad someone has posted something...!!!

    Ok yeah sorry about the realtek driver but if you search for the source code on google you do get it. But yeah as you mentioned it asks for NDA on the realtek's site.

    You should get a copy of LDD3 and the example driver source codes for that book...
    here are some links...

    lwn.net/Kernel/LDD3/
    cs.fsu.edu/2.6.25/ldd-examples

    The code might not work with the most recent kernels like the 2.6.38 new kernels keep coming so if u want to see how things work for the latest kernels u might want to take a look at the drivers present in the kernel source. Try to locate the files I am not sure about the file names.

    Try
    linux-x.y.x/drivers/net/8139too.c
    linux-x.y.x/drivers/net/8139cp.c

    I did get the driver working for a 2.6.21 kernel ill post here rather than mailing it to u... Thats the point of forums...

    In this following code I register the RTL8139 as a char dev so that I can access it from the user space.


    Code:
    #define REALTEK_VENDER_ID	0x10EC
    #define REALTEK_DEVICE_ID	0x8139
    
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/stddef.h>
    #include <linux/pci.h>
    #include <linux/init.h>
    #include <linux/cdev.h>
    #include <linux/device.h>
    
    #define LOG(string...) printk(KERN_NOTICE string)
    
    MODULE_LICENSE("GPL");
    
    struct pci_dev *pci_dev;
    unsigned long mmio_addr;
    unsigned long reg_len;
    unsigned long *base_addr;
    
    void simple_vma_open(struct vm_area_struct *vma)
    {
    	LOG("Simple VMA open, virt %lx, phys %lx\n",
    		vma->vm_start, vma->vm_pgoff << PAGE_SHIFT);
    }
    
    void simple_vma_close(struct vm_area_struct *vma)
    {
    	LOG("Simple VMA close.\n");
    }
    
    static struct vm_operations_struct simple_remap_vm_ops = {
    	.open =   simple_vma_open,
    	.close =  simple_vma_close,
    };
    
    
    static int simple_remap_mmap(struct file *filp, struct vm_area_struct *vma)
    {
    	LOG("Base Addr: %lu \n", mmio_addr);
    	if (remap_pfn_range(vma, vma->vm_start, mmio_addr >> PAGE_SHIFT,
    		vma->vm_end - vma->vm_start, vma->vm_page_prot))
    	return -EAGAIN;
    
    	vma->vm_ops = &simple_remap_vm_ops;
    	vma->vm_flags |= VM_IO | VM_RESERVED;
    	simple_vma_open(vma);
    	return 0;
    }
    
    
    static int rtl_open(struct inode *inode, struct file *filp);
    static int rtl_stop(struct inode *inode, struct file *filp);
    
    static int rtl_open(struct inode *inode, struct file *filp)
    {
    	LOG("In RTL open\n");
    	return 0;
    }
    
    static int rtl_stop(struct inode *inode, struct file *filp)
    {
    	LOG("In RTL stop\n");
    	return 0;
    }
    
    static struct cdev dev;
    static struct file_operations fops = {
    	.owner = THIS_MODULE,
    	.open = rtl_open,
    	.release = rtl_stop,
    	.mmap = simple_remap_mmap,
    };	
    
    #define CDEV_MAJOR	240
    #define CDEV_MINOR	0
    
    int init_module(void)
    {
    	struct pci_dev *pdev;
    	dev_t dev_no = MKDEV(CDEV_MAJOR, CDEV_MINOR);
    	unsigned long mmio_start, mmio_end, mmio_len, mmio_flags;
    	void *ioaddr;
    	unsigned char mac_addr[6];
    	int ret, i, j;
    	pdev = pci_find_device(REALTEK_VENDER_ID, REALTEK_DEVICE_ID, NULL);
    	if(pdev)
    	{
    		if(pci_enable_device(pdev))
    		{
    			LOG("Failed to enable device\n");
    			return 0;
    		}
    		else
    		{
    			LOG("Device enabled\n");
    		}
    	}
    	else
    	{	
    		LOG("Device not found\n");
    		return -ENODEV;
    	}
    
    	ret = register_chrdev_region(dev_no, 1, "rtl_basic");
    	if(ret < 0)
    	{	
    		LOG("Could not register as character device\n");
    		goto clean_disable;
    	}
    	else
    	{
    		LOG("Registered as character device\n");
    	}
    
    	
    	pci_dev = pdev;
    
    	mmio_start = pci_resource_start(pdev, 1);
    	mmio_end = pci_resource_end(pdev, 1);
    	mmio_len = pci_resource_len(pdev, 1);
    	mmio_flags = pci_resource_flags(pdev, 1);
    	mmio_addr =  mmio_start;
    
    	if((IORESOURCE_MEM & mmio_flags))
    	{
    		LOG("MMIO resource found at region 1\n");
    		LOG("Start : %lx \n", mmio_start);
    		LOG("End   : %lx \n", mmio_end);
    		LOG("Length: %lx \n", mmio_len);
    		LOG("Flags : %lx \n", mmio_flags);
    	}
    	else
    	{
    		LOG("Region 1 is NOT a MMIO\n");
    	}
    
    	if(pci_request_regions(pdev, "RTL_DRV"))
    	{
    		LOG("Failed to accquire the memory resources\n");
    		goto clean_cdev;
    	}
    	else 
    	{
    		LOG("Accquired the memory regions\n");
    	}
    	
    	pci_set_master(pdev);
    	ioaddr = ioremap(mmio_start, mmio_len);
    	if(ioaddr == NULL)
    	{
    		LOG("Failed to remap the memory\n");
    		goto clean_regions;
    	}
    	else
    	{
    		LOG("Remapped the memory regions\n");
    	}
    
    	base_addr = (long *)ioaddr;
    	reg_len = mmio_len;
    	
    	mac_addr[0] = readb(ioaddr + 0);
    	mac_addr[1] = readb(ioaddr + 1);
    	mac_addr[2] = readb(ioaddr + 2);
    	mac_addr[3] = readb(ioaddr + 3);
    	mac_addr[4] = readb(ioaddr + 4);
    	mac_addr[5] = readb(ioaddr + 5);
    
    	cdev_init(&dev, &fops);
    	dev.owner = THIS_MODULE;
    	dev.ops = &fops;
    	ret = cdev_add(&dev, dev_no, 1);
    	if(ret < 0)
    	{
    		LOG("Error adding character device\n");
    		goto clean_mapping;
    	}
    	else
    	{
    		LOG("Added character device\n");
    	}
    
    	LOG("MAC Address: %x:%x:%x:%x:%x:%x\n", mac_addr[0], mac_addr[1], 
    		mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
    	return 0;
    
    clean_mapping:
    	iounmap(base_addr);
    	LOG("Unmapped memory regions\n");
    clean_regions:
    	pci_release_regions(pdev);
    	LOG("Released PCI regions\n");
    clean_cdev:
    	unregister_chrdev_region(MKDEV(CDEV_MAJOR, CDEV_MINOR), 1);
    	LOG("Unregistered the Devices\n");
    clean_disable:
    	pci_disable_device(pdev);
    	LOG("Device disabled\n");
    	return -1;
    }
    
    void cleanup_module(void)
    {
    	unregister_chrdev_region(MKDEV(CDEV_MAJOR, CDEV_MINOR), 1);
    	LOG("Unregistered the Devices\n");
    	iounmap(base_addr);
    	LOG("Unmapped memory regions\n");
    	pci_release_regions(pci_dev);
    	LOG("Released PCI regions\n");
    	pci_disable_device(pci_dev);
    	LOG("Device disabled\n");
    
    	return;
    }
    I removed some unwanted stuff some might have some minor compilation errors.
    When the driver is loaded it will print the MAC address, hopefully..
    And there is some stuff regarding mmap() ignore it if ur not gonna use it right now...

    Take a look at the Realtek 8139's datasheet it will help u with the registers available on the device...

    Cheers,
    Anush...

    PS: Dont post ur mail on sites u'll start getting more spam...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •