mmap problem in pci driver

mmap problem in pci driver

Post by Gunnar Propp » Sat, 30 Sep 2000 04:00:00



I'm working on a linux device driver for the pci controller card for a
haptic interface called the Phantom.  Things were going along quite
smoothly for a while - until I tried implementing the mmap function.  My
read function sends the correct data to user space, using ioremap() map
from the physical address on the memory of the card to kernel space, and
then using put_user to bump it out to user space.

However, since this needs to be as efficient as possible, I wanted to
give user space direct access to the memory on the card through the
mmap() function.  The problem is, the data in the address I get back in
user space is all just full of FFFFFFFF, which it should be 00000000 (or
the encoder values of the Phantom if it's hooked up).  I've followed all
the examples on the net and in kernel source I could get my hands on,
and it looks right to me.  Obviously, it's not, and I suspect
something's wrong with my remap_page_range() call (page alignment
problems, maybe?).

I've been working on this for longer than I care to admit, so I'd be
grateful for any help.

Thanks!
Gunnar

Here are some excerpts from the code:

/*********************************************************************************/

/*modexample.c*/

/*just excerpts*/

/*globals*/
unsigned       pcibd_mem2_addr;

int phan_mmap(struct file *file, struct vm_area_struct *vma)
{
  unsigned size = vma->vm_end - vma->vm_start;
  unsigned long physical = pcibd_mem2_addr /*see init_module() below for
how this is set*/;

  if (remap_page_range(vma->vm_start, physical, size,
vma->vm_page_prot))
    return -EAGAIN;

  printk("phantom: mmap %08lx -> %08lx size=%d\n", (unsigned
long)pcibd_mem2_addr, vma->vm_start, size);

  return 0;

Quote:}

int init_module(void)
{
 unsigned char bus, devfn;
 int result;
 int index;
 struct pci_dev *dev;

 /*Find the Phantom card(s) and gather some info*/
 for (index = 0; index < PHAN_MAX_DEV; index++)
 {
  unsigned char irq;
  result = pcibios_find_device(PCI_VENDOR_ID_SENSABLE,
                               PCI_DEVICE_ID_PHANTOM,
                               index, &bus, &devfn);
  if (result == PCIBIOS_SUCCESSFUL)
  {
   dev = pci_find_slot(bus, devfn);
   pcibd_mem2_addr = dev->base_address[2] & PCI_BASE_ADDRESS_MEM_MASK;
  }
 }

 return 0;

Quote:}

/*********************************************************************************/

/*test.c*/
/*a sample user space program to test the phantom driver*/

#include <stdio.h>
#include <fcntl.h>
#include <sys/mman.h>

int *int_addr; /* int *int_addr; should be 4 bytes long*/

main(int argc, char *argv[])
{
 int     fd;
 int  *encoder_base;
 char *encoder_base_char;

 fd = open("phantom", O_RDONLY);
 encoder_base = (int *) mmap(NULL,256,PROT_READ,MAP_PRIVATE,fd,0);

 printf("Base address: 0x%08lx\n", (unsigned long)encoder_base);

 encoder_base_char = (char *)encoder_base;

 if (encoder_base == MAP_FAILED)
 {
  perror("mmap");
 }
 else
 {
  int     i;
  int   x;
  printf("Dumping Registers: \n");
  for (i = 0; i < 6; i++)
  {
   x = *(encoder_base + i);
   printf("%d \n", x);
  }

  printf("Bytes:\n");
  for (i = 0; i < 256; i++)
  {
   if (i%10==0)
    printf("\n0x%08lx: ", (unsigned long)encoder_base);
   printf("%02x ", *(encoder_base++));
  }
  printf("\n");
 }
 munmap(encoder_base, 256);
 close (fd);

Quote:}

 
 
 

mmap problem in pci driver

Post by Arne Driesche » Tue, 03 Oct 2000 04:00:00


Quote:

> /*test.c*/
> /*a sample user space program to test the phantom driver*/

> #include <stdio.h>
> #include <fcntl.h>
> #include <sys/mman.h>

> int *int_addr; /* int *int_addr; should be 4 bytes long*/

> main(int argc, char *argv[])
> {
>  int     fd;
>  int  *encoder_base;
>  char *encoder_base_char;

>  fd = open("phantom", O_RDONLY);
>  encoder_base = (int *) mmap(NULL,256,PROT_READ,MAP_PRIVATE,fd,0);

Hi,
man mmap
  MAP_PRIVATE
                  Create a private copy-on-write mapping.  
Perhaps copy on write is not exactly what you want :-)
I use this code for mapping.
image = mmap(NULL,
             size,
             PROT_READ,
             MAP_SHARED,
             fd,
             0l);    

Perhaps it helps.

-Arne

 
 
 

mmap problem in pci driver

Post by Gunnar Propp » Wed, 04 Oct 2000 04:00:00


Thanks for the suggestion.  You're right - MAP_SHARED seems more
appropriate (the MAP_PRIVATE setting came from some sample code).
Unfortunately, it didn't seem to solve the problem.

I tried printing the entire 4k block that comes back (even though I only
need 256 bytes, remap_page_range obviously only can deal out chunks in
multiples of page size).  I seem to remember reading somewhere that the
actual data might not be right at the beginning of the range, since it
needs to realign to the start of a page.  Anyway, after a whole bunch of
ffffffff's, there was a range of 0's.  The second time (and everytime
thereafter) I run my test program, these turn into a bunch of 4's and
0's.  These reset to 0's after I rmmod and insmod my module.  This still
doesn't make any sense though.

But at this point, getting different results feels like progress.

Gunnar


> > /*test.c*/
> > /*a sample user space program to test the phantom driver*/

> > #include <stdio.h>
> > #include <fcntl.h>
> > #include <sys/mman.h>

> > int *int_addr; /* int *int_addr; should be 4 bytes long*/

> > main(int argc, char *argv[])
> > {
> >  int     fd;
> >  int  *encoder_base;
> >  char *encoder_base_char;

> >  fd = open("phantom", O_RDONLY);
> >  encoder_base = (int *) mmap(NULL,256,PROT_READ,MAP_PRIVATE,fd,0);

> Hi,
> man mmap
>   MAP_PRIVATE
>                   Create a private copy-on-write mapping.
> Perhaps copy on write is not exactly what you want :-)
> I use this code for mapping.
> image = mmap(NULL,
>              size,
>              PROT_READ,
>              MAP_SHARED,
>              fd,
>              0l);

> Perhaps it helps.

> -Arne

 
 
 

mmap problem in pci driver

Post by Edward A. Hildu » Fri, 06 Oct 2000 15:48:21



> I'm working on a linux device driver for the pci controller card for a
> haptic interface called the Phantom.  Things were going along quite

Check out the demo device driver at
ftp://ftp.visi.com/users/grante/stuff/demomm.tar.gz

Grant Edwards pointed me to this code when I was working on a similar problem,
and it was quite helpful.

Also, if you probe the size of the PCI address space by writing 0xFFFFFFFF to the
base address register(s), be sure to put the original contents back, or you will
change the bus address at which your board is mapped.

HTH
Ted Hildum

 
 
 

mmap problem in pci driver

Post by Ben Burc » Fri, 06 Oct 2000 04:00:00



>>  fd = open("phantom", O_RDONLY);

When I did my driver, I found that you need to open the fd R/W if you ever hope
to write to the memory.  Linux seems to let the file permissions override any
R/W protections you use when you map the memory.  (I didn't look hard enough to
discover the actual reason after this worked.)

-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----

 
 
 

1. Alpha and PCI Driver (w/ mmap) problems ...

I have a "simple" PCI card that has a memory region which is mmap'able
... so I wrote a driver which identifies the card with the
pci_find_device() call, and then mmap's the information out of the
appropriate base address using the following call:

remap_page_range(vma->vm_start, (vma->vm_offset + g_offset),
(vma->vm_end
 - vma->vm_start), vma->vm_page_prot);

Anyhow, I have a corresponding application program that simply opens the
device and then prints out the contents of a mmap'd region:

fd = open("/dev/truetime", O_RDWR));

ptr = mmap(0, MAX_DEV_MEM_SIZE, (PROT_READ | PROT_WRITE), MAP_SHARED,
fd, 0);

etc ...

Problem is that on my alpha system I get all 0's ... nada ... zilch.
BUT when I run it on our Intel/Linux systems it works just fine.  I can
see the data changing, set some registers, etc ... The only thing I did
differently on the alpha system was add a flag to my compile code:

"-ffixed-8" ... otherwise I got some weird error, actually this error:
------------------------------------------------------
In file included from /usr/include/asm/semaphore.h:11,
                 from /usr/include/linux/fs.h:164,
                 from truetime.c:9:
/usr/include/asm/current.h:4: global register variable follows a
function definition
/usr/include/asm/current.h:4: warning: call-clobbered register used for
global register variable
------------------------

So the -ffixed-8 seemed to fix this ... don't know if it's causing
another problem or not ... I've tried various compile flags, I can read
all of the  PCI configuration registers using either setpci or my driver
itself, but I just can't seem to get at the data, I print out the
address returned from my mmap call and it matches the same virtual
memory address that I get inside my driver, so technically I should be
pointed to the correct address space ...

SO, anybody with experience writing Alpha/Linux device drivers ... could
you offer any suggestions? <I can provide more complete code snippets if
necessary>

Here's some basic system specs:
        RH Linux, kernel 2.2.15 w/ SMP support, on Compaq ES40 system.

In addition here's a little more of the PCI information:

% lspci -vv
...
...
...
01:03.0 Bridge: PLX Technology, Inc. PCI <-> IOBus Bridge (rev 01)
   Subsystem: True Time Inc.: Unknown device 5900
   Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr-
Stepping-
 SERR- FastB2B-
   Status: Cap- 66Mhz- UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort-
<TAbort- <MAbort- >SERR- <PERR-
   Interrupt: pin A routed to IRQ 32
   Region 0: Memory at 0000000001211400 (32-bit, non-prefetchable)
   Region 1: I/O ports at 11200
   Region 2: Memory at 0000000001211000 (32-bit, non-prefetchable)
...
...
...

(Region 2 or BASE_ADDRESS_2 is where my data is located)

Thanks in advance,

John Ward

2. iptables and port forwarding

3. mmap() driver for PCI Alpha

4. Sugestion needed

5. mmap and PCI driver

6. Am I being too Ambitious with Loadlin ??!!

7. AIX 5.1 kernel pci driver mmap

8. hot-swap RAID

9. PCI driver location & Where can I get more PCI drivers?

10. QUERY:- pci driver to mini-pci driver

11. Problems with mmap() call and PCI device memory protections.

12. MMAP cache problem in 2.4.x, Re: [parisc-linux] unreliable mmap (fwd)

13. DLPI driver and mmap() driver together