//内核态注册UIO:
struct platform_device g_demo_uio_pdev = {
.name = "demo_uio",
.id = 0,
};
struct uio_info g_demo_uio_info[] = {
{
.name = "demo1",
.version = "1.0",
.mem = {
{
.name = "demo1_mem0",
.addr = 0x10000000,
.size = 0x00010000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo1_mem1",
.addr = 0x20000000,
.size = 0x00020000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo1_mem2",
.addr = 0x30000000,
.size = 0x00030000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo1_mem3",
.addr = 0x40000000,
.size = 0x00040000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo1_mem4",
.addr = 0x50000000,
.size = 0x00050000,
.memtype = UIO_MEM_PHYS,
},
},
},
{
.name = "demo2",
.version = "2.0",
.mem = {
{
.name = "demo2_mem0",
.addr = 0x60000000,
.size = 0x00010000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo2_mem1",
.addr = 0x70000000,
.size = 0x00020000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo2_mem2",
.addr = 0x80000000,
.size = 0x00030000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo2_mem3",
.addr = 0x90000000,
.size = 0x00040000,
.memtype = UIO_MEM_PHYS,
},
{
.name = "demo2_mem4",
.addr = 0xa0000000,
.size = 0x00050000,
.memtype = UIO_MEM_PHYS,
},
},
},
}
platform_device_register(&g_demo_uio_pdev);
uio_register_device(&g_demo_uio_pdev.dev, &g_demo_uio_info[0]);
uio_register_device(&g_demo_uio_pdev.dev, &g_demo_uio_info[1]);
//用户态使用:
1.
读取节点名字,即为g_demo_uio_info[%d].name 的值
FILE *fp = fopen("/sys/class/uio/uio%d/name", "rb");
fgetc + strcmp 命中对应的节点,得到 %d 编号 index
2. 再基于第一步获取的index,填充uio%d编号后,查其下的子节点名字,即 g_demo_uio_info[%d].mem[%d].name
FILE *fp = fopen("/sys/class/uio/uio%d/maps/map%d/name", "rb");
fgetc + strcmp 命中对应的节点,得到 mem[%d] 编号 index_mem
3. 基于前两步获取的index, 获取
FILE *fp_addr = fopen("/sys/class/uio/uio%d/maps/map%d/addr", "rb");
FILE *fp_size = fopen("/sys/class/uio/uio%d/maps/map%d/size", "rb");
fgetc 获取值字符串 + strtoull 转为数字得到地址与长度信息
uio_fd = open("/dev/uio0",O_RDWR);
addr_fd = open("/sys/class/uio/uio0/maps/map0/addr", O_RDONLY);
size_fd = open("/sys/class/uio/uio0/maps/map0/size", O_RDONLY);
read(addr_fd, uio_addr_buf, sizeof(uio_addr_buf));
read(size_fd, uio_size_buf, sizeof(uio_size_buf));
uio_addr = (void*)strtoul(uio_addr_buf, NULL, 0);
uio_size = (int)strtol(uio_size_buf, NULL, 0);
access_address_0 = mmap(NULL, uio_size, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, 0 * getpagesize());
uio_fd = open("/dev/uio0",O_RDWR);
addr_fd_1 = open("/sys/class/uio/uio0/maps/map1/addr", O_RDONLY);
size_fd_1 = open("/sys/class/uio/uio0/maps/map1/size", O_RDONLY);
read(addr_fd_1, uio_addr_buf, sizeof(uio_addr_buf));
read(size_fd_1, uio_size_buf, sizeof(uio_size_buf));
uio_addr_1 = (void*)strtoul(uio_addr_buf, NULL, 0);
uio_size_1 = (int)strtol(uio_size_buf, NULL, 0);
access_address_1 = mmap(NULL, uio_size_1, PROT_READ | PROT_WRITE, MAP_SHARED, uio_fd, 1 * getpagesize());
注意:
正常mmap的最后参数为需要映射的物理地址,但是对于UIO而言,系统调用mmap UIO的fd的时候,会重定向到UIO内部的mmap函数.
因此对于mmap最后的参数是: UIO设备的mem段的数组编号 * getpagesize()