Messages in this thread | | | Date | Thu, 30 Aug 2012 05:27:50 +0200 | From | "Hans J. Koch" <> | Subject | Re: Using uio_pdrv to create an platform device for an FPGA, mmap() fails |
| |
[Added driver author to Cc:]
On Wed, Aug 29, 2012 at 11:19:00PM +0000, Worth, Kevin wrote: > I have below what appears to be a mostly-functional device using the UIO Platform Driver. The /sys entries I'd expect appear, /proc/iomem contains " d0000000-d0000fff : myfpga", and lsuio sees the properties that I've set. However an mmap() from userspace (either my test program below or lsuio) fails. So close! (at least it would seem) > > Finding a good example for this did not come easily (which is why I'm hitting LKML, since I know it'll get a lot of eyeballs and be archived). Maybe there was something obvious I missed, but the only "official" documentation I could locate was http://www.kernel.org/doc/htmldocs/uio-howto.html#using_uio_pdrv , and most everything else was snippets from presentations, papers, and forums that lacked completeness. > > Thanks for the help any might be able to offer. > Please CC me on replies as I'm not ready to drink from the fire hose that is an LKML subscription. > > # lsuio -v -m > uio0: name=uio_myfpga, version=0.1, events=0 > map[0]: addr=0xD0000000, size=4096, mmap test: FAILED > Device attributes: > uevent=DRIVER=uio_pdrv > modalias=platform:uio_pdrv > > ------Kernelspace portion------- > > #include <linux/platform_device.h> > #include <linux/uio_driver.h> > #include <linux/module.h> > > #define MYFPGA_BASE 0xd0000000 // 3G > #define MYFPGA_SIZE 0x00040000 // 256k > > static struct resource myfpga_resources[] = { > { > .start = MYFPGA_BASE, > .end = MYFPGA_BASE + MYFPGA_SIZE - 1, > .name = "myfpga", > .flags = IORESOURCE_MEM > } > }; > > static struct uio_info myfpga_uio_info = { > .name = "uio_myfpga", > .version = "0.1", > .irq = UIO_IRQ_CUSTOM, > .mem = { > { > .name = "myfpga", > .memtype = UIO_MEM_PHYS, > .addr = MYFPGA_BASE, > .size = MYFPGA_SIZE > } > } > }; > > static struct platform_device_info myfpga_uio_pdevinfo = { > .name = "uio_pdrv", > .id = -1, > .res = myfpga_resources, > .num_res = 1, > .data = &myfpga_uio_info, > .size_data = sizeof(struct uio_info) > }; > > static struct platform_device *myfpga_uio_pdev; > > static int __init myfpga_init(void) > { > myfpga_uio_pdev = platform_device_register_full(&myfpga_uio_pdevinfo); > if (IS_ERR(myfpga_uio_pdev)) { > return PTR_ERR(myfpga_uio_pdev); > } > > return 0; > } > > static void __exit myfpga_exit(void) > { > platform_device_unregister(myfpga_uio_pdev); > } > > module_init(myfpga_init); > module_exit(myfpga_exit); > > ------Userspace portion------- > > #include <sys/types.h> > #include <sys/mman.h> > #include <sys/stat.h> > > #include <dirent.h> > #include <string.h> > #include <stdlib.h> > #include <stdio.h> > #include <fcntl.h> > #include <unistd.h> > > #define MYFPGA_BASE 0xd0000000 // 3G > #define MYFPGA_SIZE 0x00040000 // 256k > #define MYFPGA_UIO_NUM 0 // uio0
That's misleading regarding its use below. The factor you need for mmap is the number of the mapping, not uio0, uio1...
> > int main (int argc, char *argv[]) > { > int fd; > void *iomem; > fd = open("/dev/uio0", O_RDWR|O_SYNC);
Does it work with O_RDWR ?
Thanks, Hans
> if (fd < 0) { > printf("failed to open /dev/uio0, quitting\n"); > return -1; > } > /* Note offset has a special meaning with uio devices */ > iomem = mmap(NULL, MYFPGA_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, > MYFPGA_UIO_NUM * getpagesize()); > if (iomem == MAP_FAILED) { > printf("mmap failed, quitting\n"); > close(fd); > return -2; > } > printf("mmap successful!\n"); > munmap(iomem, MYFPGA_SIZE); > close(fd); > return 0; > } > -- > To unsubscribe from this list: send the line "unsubscribe linux-kernel" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > Please read the FAQ at http://www.tux.org/lkml/ >
| |