PCI device driver question - Linux

This is a discussion on PCI device driver question - Linux ; Hi everyone, I am writing a PCI device driver. In the pci device driver, I am able to do the following: static int probe(struct pci_dev *dev, const struct pci_device_id *id) { char *region0; u32 bar0; unsigned int barLen0; int barNumber0 ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: PCI device driver question

  1. PCI device driver question

    Hi everyone,

    I am writing a PCI device driver. In the pci device driver, I am able
    to do the following:

    static int probe(struct pci_dev *dev, const struct pci_device_id *id)
    {
    char *region0;
    u32 bar0;
    unsigned int barLen0;
    int barNumber0 = 0;

    pci_enable_device(dev);

    pci_request_region(dev, barNumber0, "driverBAR0");
    bar0 = pci_resource_start (dev, barNumber0);
    barLen0 = pci_resource_len(dev, barNumber0);

    region0 = ioremap_nocache(bar0, barLen0);

    writeb('A', region0+0x04);
    iounmap(region0);
    return 0;

    }



    Now instead of hard-coding what to write in the memory region, I want
    to input a file, read the file, and write the appropriate contents to
    the memory region. What are the appropriate steps to do that? It seems
    as though that I cannot use the library stdio in pci device drivers. Is
    there another library that contains file IO? Or do I need to create a
    program in userspace that would read the file, access the pci device
    driver, and call a write function?


  2. Re: PCI device driver question

    In article <1166736838.855581.113720@80g2000cwy.googlegroups.c om>,
    elliotng.ee@gmail.com wrote:

    >Now instead of hard-coding what to write in the memory region, I want
    >to input a file, read the file, and write the appropriate contents to
    >the memory region. What are the appropriate steps to do that? It seems
    >as though that I cannot use the library stdio in pci device drivers. Is
    >there another library that contains file IO?


    Look in the kernel source for examples of sys_open, sys_read, etc.

    --
    http://www.spinics.net/lists/

  3. Re: PCI device driver question

    I cannot find any good documentations on sys_open, sys_read, etc. What
    are the parameters required to utilize those questions?

    Let me rephrase what I wrote before. I have implemented a pci device
    driver. I have the __init, __exit, probe, and remove functions just
    like standard pci device drivers. Originally, in my probe function, I
    tested the pci device driver by reading/writing to different base
    address. On the FPGA, I had a simple test program involving LED's to
    verify that I have read/write to the specific memory address.

    Now, instead of writing/reading from the pci device driver, I want to
    be able to do the reading/writing from the userspace. From the
    userspace, I want to input a file using stdio that contains the data to
    be written. I will then write out the data to the pci device driver.

    My questions are:
    a) In the pci device driver, do I need a write and read functions? Are
    the functions similar to the char device driver read/write functions?
    b) In the userspace, how do I access the pci device driver? The
    previous poster mentioned to use sys_open, sys_read, sys_write, etc.
    What are the parameters needed to utilize sys_open, sys_read,
    sys_write, etc.? Do I need to know major/minor numbers?


    ellis@no.spam wrote:
    > In article <1166736838.855581.113720@80g2000cwy.googlegroups.c om>,
    > elliotng.ee@gmail.com wrote:
    >
    > >Now instead of hard-coding what to write in the memory region, I want
    > >to input a file, read the file, and write the appropriate contents to
    > >the memory region. What are the appropriate steps to do that? It seems
    > >as though that I cannot use the library stdio in pci device drivers. Is
    > >there another library that contains file IO?

    >
    > Look in the kernel source for examples of sys_open, sys_read, etc.
    >
    > --
    > http://www.spinics.net/lists/



  4. Re: PCI device driver question

    OK, after doing some research, it appears that I can use the char
    device read and write functions in the pci device driver. To summarize
    what I have, I have written a pci device driver. In userspace, I want
    to be able to access the pci device driver, read from memory, and write
    to memory. I have recently found out that I can try to read/write from
    using file operations.

    Right now, this is what the file operations section of the pci device
    driver looks like:

    static int test_open(struct inode *inode, struct file *filp){
    return 0;
    }

    static int test_release(struct inode *inode, struct file *filp){
    return 0;
    }

    static ssize test_read(struct file *filp, char __user *buf, size_t
    count, loff_t *f_pos){
    // Code goes here

    return 0;
    }

    static ssize test_write(struct file *filp, char __user *buf, size_t
    count, loff_t *f_pos){
    // Code goes here

    return 0;
    }

    static struct file_operations test_fops = {
    ..open = test_open,
    ..read = test_read.
    ..write = test_write,
    ..release = test_release,
    }

    My questions are:
    1) What do I put in for the read and write functions in the pci device
    driver? I know that in write, I want to be able to use the function
    void writel(unsigned value, char* address) in order to write to the
    specified address. Similarly, for the read function, I want to be able
    to use the function readl(char* address) to read the data from the
    address.

    2) In userspace code, how do I use fread and fwrite to a specific
    memory location in the pci?



    elliotng.ee@gmail.com wrote:
    > I cannot find any good documentations on sys_open, sys_read, etc. What
    > are the parameters required to utilize those questions?
    >
    > Let me rephrase what I wrote before. I have implemented a pci device
    > driver. I have the __init, __exit, probe, and remove functions just
    > like standard pci device drivers. Originally, in my probe function, I
    > tested the pci device driver by reading/writing to different base
    > address. On the FPGA, I had a simple test program involving LED's to
    > verify that I have read/write to the specific memory address.
    >
    > Now, instead of writing/reading from the pci device driver, I want to
    > be able to do the reading/writing from the userspace. From the
    > userspace, I want to input a file using stdio that contains the data to
    > be written. I will then write out the data to the pci device driver.
    >
    > My questions are:
    > a) In the pci device driver, do I need a write and read functions? Are
    > the functions similar to the char device driver read/write functions?
    > b) In the userspace, how do I access the pci device driver? The
    > previous poster mentioned to use sys_open, sys_read, sys_write, etc.
    > What are the parameters needed to utilize sys_open, sys_read,
    > sys_write, etc.? Do I need to know major/minor numbers?
    >
    >
    > ellis@no.spam wrote:
    > > In article <1166736838.855581.113720@80g2000cwy.googlegroups.c om>,
    > > elliotng.ee@gmail.com wrote:
    > >
    > > >Now instead of hard-coding what to write in the memory region, I want
    > > >to input a file, read the file, and write the appropriate contents to
    > > >the memory region. What are the appropriate steps to do that? It seems
    > > >as though that I cannot use the library stdio in pci device drivers. Is
    > > >there another library that contains file IO?

    > >
    > > Look in the kernel source for examples of sys_open, sys_read, etc.
    > >
    > > --
    > > http://www.spinics.net/lists/



  5. Re: PCI device driver question

    elliotng.ee@gmail.com wrote:
    > OK, after doing some research, it appears that I can use the char
    > device read and write functions in the pci device driver. To summarize
    > what I have, I have written a pci device driver. In userspace, I want
    > to be able to access the pci device driver, read from memory, and write
    > to memory. I have recently found out that I can try to read/write from
    > using file operations.


    (1) You need to map the device memory into kernel virtual address space
    with ioremap. Then, in the test_write function, you copy data from
    user space into kernel space (possibly to a small temporary holding
    area), then use writel to put it into the (mapped) device memory
    (adding in the f_pos value).

    test_read is simply the inverse, readl to read the device memory space,
    then copy it to user space.

    copy_to_user and copy_from_user can be used for data transfer between
    user space and kernel space. Look for the book "Linux Device Drivers"
    (3rd edition) -- which is available in pdf format for free online --
    for much detailed info.

    (2) You create a device node (e.g. "mknod /dev/mydevice c xxx 0" where
    xxx is your device's major number from /proc/devices). Your program
    then opens /dev/mydevice, lseek's to the proper offset and does read or
    write calls.

    Having said all that, if this is just a one-off or occasional
    special-purpose administrative operation, you may not even need to
    write a driver (on most platforms at least). You can use the lspci
    program to find the physical address of the pci device's memory. Then
    you open "/dev/mem", mmap the desired area and read / write data
    directly to or from it in your user program.

    GH


  6. Re: PCI device driver question

    Thanks for your help. I followed this advice:

    Having said all that, if this is just a one-off or occasional
    special-purpose administrative operation, you may not even need to
    write a driver (on most platforms at least). You can use the lspci
    program to find the physical address of the pci device's memory. Then
    you open "/dev/mem", mmap the desired area and read / write data
    directly to or from it in your user program.

    Following GH's advice, I looked at lspci, and found that the device
    Region 0 memory is mapped at a0000000 (32-bit, prefetch, size=512 M)

    I wrote the following program:

    #include
    #include
    #include
    #include
    #include
    #include

    int main(){

    int memory;
    unsigned int data;
    unsigned char *address;

    memory = open("/dev/mem", O_RDWR);
    address = mmap((void*)0, 0xafffffff, PORT_WRITE | PORT_READ, MAP_FIXED,
    memory, 0xa0000000);

    data = readl(address);
    printf("Data: %x", data);
    writel(0xFF, address);
    data = readl(address);
    printf("Data: %x", data);

    munmap((void*)address, 0xafffffff);
    close(memory);
    return 0;

    }

    I just want to make sure that my syntax is correct. When I went to run
    the makefile, however, it did not work. It was having problems
    recognizing readl and writel even though both functions should be in
    . My makefile is the following:
    testIO: testIO.c
    gcc -o $@ $<

    I have the following errors/warnings:

    In file included from /usr/include/asm/io.h:11 from testIO.c:6:
    /usr/include/asm-i386/io.h:1:2: warning: #warning "You should include
    . This time I will do it for you."

    testIO.c: (.text+0x59): undefined reference to 'readl'
    testIO.c: (.text+0x82): undefined reference to 'writel'
    testIO.c: (.text+0x90): undefined reference to 'readl'

    gil_hamilton@hotmail.com wrote:
    > elliotng.ee@gmail.com wrote:
    > > OK, after doing some research, it appears that I can use the char
    > > device read and write functions in the pci device driver. To summarize
    > > what I have, I have written a pci device driver. In userspace, I want
    > > to be able to access the pci device driver, read from memory, and write
    > > to memory. I have recently found out that I can try to read/write from
    > > using file operations.

    >
    > (1) You need to map the device memory into kernel virtual address space
    > with ioremap. Then, in the test_write function, you copy data from
    > user space into kernel space (possibly to a small temporary holding
    > area), then use writel to put it into the (mapped) device memory
    > (adding in the f_pos value).
    >
    > test_read is simply the inverse, readl to read the device memory space,
    > then copy it to user space.
    >
    > copy_to_user and copy_from_user can be used for data transfer between
    > user space and kernel space. Look for the book "Linux Device Drivers"
    > (3rd edition) -- which is available in pdf format for free online --
    > for much detailed info.
    >
    > (2) You create a device node (e.g. "mknod /dev/mydevice c xxx 0" where
    > xxx is your device's major number from /proc/devices). Your program
    > then opens /dev/mydevice, lseek's to the proper offset and does read or
    > write calls.
    >
    > Having said all that, if this is just a one-off or occasional
    > special-purpose administrative operation, you may not even need to
    > write a driver (on most platforms at least). You can use the lspci
    > program to find the physical address of the pci device's memory. Then
    > you open "/dev/mem", mmap the desired area and read / write data
    > directly to or from it in your user program.
    >
    > GH



  7. Re: PCI device driver question

    Never mind, I found out that writel/readl are kernel functions. We will
    need to emulate the kernel functions.

    New code (just want to verify that it is correct):

    ......

    // Kernel function emulation
    #define writel(data, addr) *(volatile int*) (addr)=(data)
    #define readl(addr) *(volatile int*)(addr)

    int main(){

    int memory;
    unsigned int data;
    unsigned char *address;

    memory = open("/dev/mem", O_RDWR);
    address = mmap((void*)0, 0x1fffffff, PORT_WRITE | PORT_READ, MAP_FIXED,
    memory, 0x20000000);

    data = readl(address);
    printf("Data: %x", data);
    writel(0xFF, address);
    data = readl(address);
    printf("Data: %x", data);

    munmap((void*)address, 0x1fffffff);
    close(memory);
    return 0;

    }


+ Reply to Thread