Re: Device driver, PCI, and mmapping

From: Ivan Passos (lists@cyclades.com)
Date: Thu Jun 15 2000 - 11:57:45 EST


On 15 Jun 2000, David D Golombek wrote:

> int
> init_module(void) {
> .....
> pcibios_read_config_dword(bus,
> function,
> PCI_BASE_ADDRESS_0,
> &base0);
> base0 &= PCI_BASE_ADDRESS_MEM_MASK;
> mem_size = 0x01000000;
> mem_base = ioremap(base0, mem_size);
> printk(KERN_INFO "mem_base is %x\n", (unsigned)mxt->mem_base);
> ...
> }

This is totally correct ... for kernels 2.0.x.

For kernels 2.2.x:

        /* Find pdev with pci_find_device() */
         base0 = pdev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK;
         mem_size = 0x01000000;
         mem_base = ioremap(base0, mem_size);

For kernels 2.3.x/2.4.x:

        /* Find pdev with pci_find_device() */
         base0 = pci_resource_start(pdev, 0);
         mem_size = 0x01000000;
         mem_base = ioremap(base0, mem_size);

> static int
> my_mmap(struct file *filp, struct vm_area_struct *vma) {
> unsigned long paddr = 0, offset = 0, size = 0;
>
> offset = vma->vm_offset;
> if (offset & ~PAGE_MASK)
> return(-ENXIO);
>
> paddr = base0 + offset;
> size = vma->vm_end - vma->vm_start;
> vma->vm_flags |= (VM_SHM | VM_LOCKED | VM_IO);
>
> if (remap_page_range(vma->vm_start, paddr, size, vma->vm_page_prot))
> return(-EAGAIN);
>
> return(0);
> }
>
> The ioremap of base0 works great, I can read and write the device
> memory with no problems from kernel space. It's just the userspace
> that's messed. Do I need to futz with the vm_page_prot somehow? I
> couldn't find any examples of how to do so. My userspace mmap call
> looks has PROT_READ|PROT_WRITE and MAP_SHARED passed in.

In order to access PCI MMIO areas from userspace, you should open
"/dev/mem" (or "/dev/kmem") and then call mmap. The mmap call is something
as follows:

#if defined(__alpha__)
    base0_virt = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd,
                      (off_t)(base0 + bus_base()));
#else
    base0_virt = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd,
                      (off_t)base0);
#endif

For an example on the driver and the userspace codes, you can download the
Cyclades Linux driver package, available at our FTP site:

        ftp://ftp.cyclades.com/pub/cyclades/async/linux/

The userspace application (cyzload) also uses Martin Mares' PCILib (whose
source code is included in the package) to access the PCI registers and
obtain the PCI Base Address values.

Hope this helps.

Regards,
Ivan

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Thu Jun 15 2000 - 21:00:35 EST