Subject: mmap problem another :)

From: Dmitriy Tochansky <[email-masked]>
Date: Thu, 9 Dec 2004 16:12:07 +0300

Seems like I found problem.

Look ret = io_remap_page_range(start, offset, size, vma->vm_page_prot); remaps
from "offset" which I got from pci_resource_start (curdev, IOMEM0); its ok
from first board where it eq 0x40000000 but on second it 0x40002040

Then I'm reading from x = mmap (NULL, MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); with
shift 0x3C>>2 where I expect board register. But for second board x points to where?
0x40000000 or 0x40002040 or as I think remap_page_range or sonething realign offset to 
PAGE so x points to 0x40002000 or 0x40003000 and reading with shift 0x3C have no sense.

Am I rigth?

---

From: Dan Malek <[email-masked]>
Date: Thu, 9 Dec 2004 09:36:11 -0500

> from first board where it eq 0x40000000 but on second it 0x40002040

Read the memory mapping docuemntation and understand the APIs.
All of the Linux mapping functions, whether mmap() from an application
or in the kernel are going to align on page boundaries.

The address of 0x40002040 is going to be aligned to a page boundary,
so you have to consider the offset into that page to the base of the
device, plus the register offset.  The kernel mapping functions,
like remap_page_range, are going to force the alignment because
that is what we expect in the kernel.  An mmap() with an unaligned
address will generate an error.

	-- Dan

---

From: Dmitriy Tochansky <[email-masked]>
Date: Tue, 14 Dec 2004 10:51:54 +0300

On Thu, 9 Dec 2004 09:36:11 -0500

> address will generate an error.
  Ok. I understand. But still havent fun. :(
Yes, Im assume that offset if pagealligned:

static int
mdrv_mmap (struct file *file, struct vm_area_struct *vma)
{
  unsigned long offset = 0;
  int ret;
  struct inode *inode;
  inode = file->f_dentry->d_inode;
  struct pci_dev *curdev = NULL;
  int minor = MINOR (inode->i_rdev);
  printk("minor = 0x%X\n",minor);
  curdev = (devs[minor]);
  unsigned long start = vma->vm_start;
  unsigned long size = (vma->vm_end - vma->vm_start);
  offset = pci_resource_start (curdev, IOMEM0);
  offset &= PAGE_MASK;
  printk("start= 0x%X offset = 0x%X size=0x%X\n",start, (unsigned int)offset, (unsigned int) size);
  ret = remap_page_range_high(start, offset, size, vma->vm_page_prot);
  return ret;
}

 This code, AFAIK will return me a pointer to begin of page where my ioaddr is. ?

 Then in my testcode I compensate shift by adding it to addr:

---

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

#define MMAP_SIZE 0x40

int fd, fd2;

int
main ()
{

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

  unsigned long *x;

  x = mmap (NULL, MMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

  printf ("mmap return: 0x%X", x);

  if (x == MAP_FAILED)
    {
      printf (" it is very bad! :(\n");
      perror ("mmap:");
      return -1;
    }

  printf (" its ok!\n");
  
  printf("x = 0x%X\n",x);

#define CONS 0
//0x2040 >> 2
  
  x += CONS;
  
  printf("x = 0x%X\n",x);
  unsigned long m = 0xEF;
  
  printf("m = 0x%X\n",m);
  
  //printf ("%p\n", x[(0x3C)>>2]); //We have to get 0xE6 here
  
  m = x[(0x40>>2)+(0x3C>>2)];
  
  printf("m = 0x%p\n", m);
  
  x -= CONS;  
  
  munmap (x, MMAP_SIZE);
  close(fd);
  
  return 0;
}

---

DEbug output shows that mmap - success. I get pointer and size = 0x1000(one page). Then
I try to read m from board register. BTW, if I just read apps finishing but when I try to output
to console(as in src) "m" programm hangs.

Have no idea what the ... is goin on. Some hints please.