I'm currently trying to write a linux kernel driver for an experimental
graphics board we're developing at our institute. It's fitted
with an plx9054 and got some sdram on board connected to the plx.
Now I come this far, that I actually detect the board, set some modes
and do an ioremap on pci_resource_start(pdev,2) which is the
base for 64Mb Ram Onboard. After ioremap() I actually like
to do remap_page_range through fileops/mmap call. I just copied
that code from drivers/char/mem.c, but just using the ioremapped
address as offset in remap_page_range, doesn't seem to work, instead
I think I just mmap some totally different area... Now, what do I have to
use for that offset? What I currently do in the init function is
something like that:
...
priv.pcibar2 = (char*)ioremap(pci_resource_start(pdev,2),
pci_resource_len(pdev,2));
...
and later on in the mmap method I do:
static int mmap_plx9054(file, vma) {
unsigned long pcibase = (unsigned long)priv.pcibar2;
...
remap_page_range(vma->vma_start, pcibase, len, vma->vm_page_prot);
...
}
I just use pcibase as offset, anything wrong here?
Cheers, Alex
PS: Is there someone who knows about the plx9054?
--
Small things make base men proud.
-- William Shakespeare, "Henry VI"
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
> Hi,
>
> I'm currently trying to write a linux kernel driver for an experimental
> graphics board we're developing at our institute. It's fitted
> with an plx9054 and got some sdram on board connected to the plx.
> Now I come this far, that I actually detect the board, set some modes
> and do an ioremap on pci_resource_start(pdev,2) which is the
> base for 64Mb Ram Onboard. After ioremap() I actually like
> to do remap_page_range through fileops/mmap call. I just copied
> that code from drivers/char/mem.c, but just using the ioremapped
> address as offset in remap_page_range, doesn't seem to work, instead
> I think I just mmap some totally different area... Now, what do I have to
> use for that offset? What I currently do in the init function is
> something like that:
>
> ...
> priv.pcibar2 = (char*)ioremap(pci_resource_start(pdev,2),
> pci_resource_len(pdev,2));
> ...
This is becoming a FAQ. The return value from ioremap() and friends
is not a pointer. It is actually something that from time-to-time
will be poisoned to detect its use as a pointer. It is a 'cookie'
designed to be used with readl() readw() readb(), writel(), etc.
For large arrays, you use copy/to/from_io(). It is possible to
determine the actual virtual address with a runtime code snippit
so you could access your remapped address conventionally, i.e.,
as a pointer, perhaps to a structure, etc., but cheating like
that is frowned upon and makes your driver more non-portable
than it probably already is. The assumption seems to be that
when Apple comes out with a 256 bit machine with 128 bit PCI
and 32, 40 GHz CPUs, you just recompile everything and it will run );
If your driver is never going to be used for anything but
a private experiment, the value of a pointer to the remapped
area is (usually) the (address_you_asked_for) | PAGE_OFFSET.
You have to save the returned cookie anyway because you use
it to release the remapped area when your module exits.
Cheers,
Dick Johnson
Penguin : Linux version 2.4.1 on an i686 machine (799.53 BogoMips).
I was going to compile a list of innovations that could be
attributed to Microsoft. Once I realized that Ctrl-Alt-Del
was handled in the BIOS, I found that there aren't any.
in the meantime I got it running, just some board setup issues,
I had to introduce some udelays() at the right spot :)
> designed to be used with readl() readw() readb(), writel(), etc.
> For large arrays, you use copy/to/from_io(). It is possible to
Thats what I do anyway.
> than it probably already is. The assumption seems to be that
> when Apple comes out with a 256 bit machine with 128 bit PCI
> and 32, 40 GHz CPUs, you just recompile everything and it will run );
Yeah, there are only about 5 boards at the present time :)
> If your driver is never going to be used for anything but
> a private experiment, the value of a pointer to the remapped
> area is (usually) the (address_you_asked_for) | PAGE_OFFSET.
What I now do is ioremap_nocache and do writel's, readl's on it.
For the mmap stuff, I just call remap_page_range with the physical
address that I get from pci_resource_start(). Is that alright?
I mean it's working for me now, thats most important :)
Cheers, Alex
--
When I was younger, I could remember anything, whether it had happened
or not; but my faculties are decaying now and soon I shall be so I
cannot remember any but the things that never happened. It is sad to
go to pieces like this but we all have to do it.
-- Mark Twain
>What I now do is ioremap_nocache and do writel's, readl's on it.
>For the mmap stuff, I just call remap_page_range with the physical
>address that I get from pci_resource_start(). Is that alright?
>I mean it's working for me now, thats most important :)
>
That does not work on an Alpha. The Alpha (at leat my DS20 and
ES40) is happy with result of ioremap feeded into remap_page_range,
or the real CPU physical address (pci_resource_start + 0x80000000000
on Tsunami chipset).
There is an io_remap_page_range, which does a
remap_page_range(virt_to_phys(ioremap(pci_resource_start()))) on
Alpha, but this does not work either.
There must be a portable way to export PCI memory space to user space,
since e.g. the X servers are using that.
Any hints?
Thanks & regards,
Martin
Bad idea. The remap_page_range can remap actual memory only,
located on the CPU side of the I/O bridge.
What ioremap returns is useful in readb/writeb only, and
not to be fed into other functions.
Instead, use io_remap_page_range, lift the example from
drivers/video/fbmem.c.
-- Pete
Kick the Alpha maintainer.