Re: memory map io function



On Wed, 20 Jun 2001 10:59:43 PDT, Louis Lu <netlu visto com>  said:
> Hi:
> 
>    I just wondering whether or not anyone who has the experiences on memory map io function before? 
> 
> My code is as following:
>   int *base;
>   unsigned int fd;
>   fd = open("dev/mem", O_RDWR);
>   base = mmap(0, 0x80000, PROT_READ|PROT_WRITE,MAP_SHARED,   fd, 0xd800000);

Note that 0x80000 and 0xd8000000 are *VIRTUAL* addresses.  This *WILL*
screw you to the wall.

Also, you're missing a MAP_FIXED - Very Bad Juju will result.

Also, you're confusing two meanings of "memory mapped".

The 'mmap()' system call creates a mapping between *virtual addresses* that
possibly belong to different processes.

Memory Mapped I/O means "instead of using an IN or OUT opcode to write data
to/from an I/O port, the device is set up to look like memory.  So storing to
a specific memory location becomes an OUTput, and reading it becomes an INput, and so
on".

This is an Incredibly Bad Thing to do from user-land - in particular, you're
quite likely to get hosed by virtual/physical address mapping (hint - what
happens if the virtual page gets paged out?  You didn't lock it anyplace ;),
and a whole host of other things that can go wrong.

The Better Way to implement this would be with a device driver - you would
open /dev/yourdev, and issue read() and write() and ioctl() as needed. Inside
the kernel, the (for example) write() call would go into the device driver,
which would then check the buffer location/size, sanity-check all the other
paramaters to write(), lock the pages in memory so the VM manager doesn't move
them around, set an internal lock so other read()/write() to that device
block until this operation finishes, and then finally move data from the user
buffer to the I/O address(es).  Depending on the hardware design, you
may be able to get away with an strcpy() (if the card provides address space
for an entire buffer) or you may need a loop like this:

          char *dest = (char *) 0x800ffff; /* or whatever address */
          for (i=buflen;i;i--) *dest = *userbuf++; /* *NO* ++ on dest */

Many such cards have restrictions that you have to write only bytes, or only
4/8/16 bytes at a time, or that writes have to be aligned, etc.

Your device driver will also have to deal with error conditions, the
existence of read-only and write-only status/control bits, and so on.

I won't get into issues like cache coherency (what happens when the data
that's in the memory-mapped I/O card doesn't match what your CPU has in
its L1/L2 cache), how to make it work right on a SMP system, and so on.

You may wish to ask the card vendor if they have a device driver for your
system already....

-- 
				Valdis Kletnieks
				Operating Systems Analyst
				Virginia Tech



Attachment: pgpPKrumlpzTr.pgp
Description: PGP signature



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]