首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >串行端口的mmap IO端口地址

串行端口的mmap IO端口地址
EN

Stack Overflow用户
提问于 2020-12-19 15:02:42
回答 1查看 154关注 0票数 1

我正在检查串行端口(uart) 0x2f8的io-port地址是否可以映射到用户空间。我希望自己在驱动程序中做到这一点,而不是使用任何库来知道需要哪些api来实现这一点。但是,考虑到这是特定于x86和端口IO的,我不确定它是否真的可以做到。不管怎样,我已经在用户空间中编写了一个mmap函数和调用者。

代码语言:javascript
复制
Setting up the mapping is as below:
代码语言:javascript
复制
res = request_region(base_addr, 8 ,"custom_serial_device");
void __iomem * mem_base_addr = ioport_map(base_addr, 8);
iowrite8(0x01, (u8 *)my_dev->mem_base_addr + 3); /*Few more configs and works fine */
/* After this I am able to make the uart function in software loopback mode */

现在我决定在这个地址上尝试mmap:

代码语言:javascript
复制
static int my_dev_mmap(struct file *filep, struct vm_area_struct *vma) {
    SERIAL_DEV *my_dev = (SERIAL_DEV*)filep->private_data;
    unsigned long pfn;
    size_t sz = vma->vm_end - vma->vm_start;
    unsigned long phys_addr;

    if (vma->vm_end - vma->vm_start != PAGE_SIZE) {
            return -EINVAL;
    }
    if (PAGE_SIZE > (1 << 16))
            return -ENOSYS;

    vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
    vma->vm_flags |= VM_IO;
    /*ioport_map gives virtual address so I am using below to get physical addr */
    phys_addr = virt_to_phys(my_dev->mem_base_addr);
    pfn = phys_addr >> PAGE_SHIFT;
    printk("GNA: mmap called: vm-start: 0x%lx vm-end: 0x%lx mem_base: 0x%lx phys: 0x%lx pfn: %lu\n",
                 vma->vm_start, vma->vm_end, (unsigned long)my_dev->mem_base_addr, phys_addr, pfn);

    if (remap_pfn_range(vma, vma->vm_start, pfn, sz, vma->vm_page_prot)) {
            printk("GNA: mmap failed\n");
            return -EAGAIN;
    }
        return 0;
}

我得到的打印结果如下:

代码语言:javascript
复制
Dec 19 11:05:00 realtek-dpdk kernel: [ 4624.894086] GNA: mmap called: 
vm-start: 0x7fa150f4d000  --> Kernel allocates this range which is in user space 
vm-end: 0x7fa150f4e000 
mem_base: 0x102f8 
phys: 0x6587800102f8    --> Virt_to_phys gave this which seems wrong
pfn: 27254063120

当我打印mmap'd内存时,我期望0x5A位于从0x2f8 (uart的基址)到0x7 (高速暂存)的偏移量。然而,我没有看到预期的输出。

我尝试的另一种方法是,ioport_map给出了一个地址0x102f8,它看起来不像是一个虚拟地址,但更像是一个物理地址(基址+ 0x2f8),所以,我直接使用这个地址来获取pfn。但结果仍然是一样的。

我的用户空间程序如下:

代码语言:javascript
复制
address = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, configfd, 0);

在此之后,我尝试找到在高速暂存存储器中偏移量0x7处写入的值。

代码语言:javascript
复制
for (int i = 0 ; i < 10; i++) {
    printf("Value: 0x%x 0x%x\n", address[i], address[0x2f8 + i]);
}

那么,有没有可能mmap()一个ioport。如果是,请告诉我正确的步骤。

PS:虽然这是x86,但我添加了embedded-linux标签,以便从平台端获得一些帮助,以防有人知道其中的区别。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-12-20 19:39:33

注意:此答案与x86相关。

I/O端口通过IN和OUT指令访问。

应该可以映射一个由驱动程序管理的反弹缓冲区,并使用这些指令将其写出到串行。您可能需要为同步编写一个接口(例如,flush ioctl)。

与基于MMIO的设备不同,您不能粗略地将接触设备的内存直接映射到用户空间,因为该内存并不存在。

您可以尝试篡改I/O端口权限,以便用户空间可以访问I/O端口本身。ioperm syscall (可能还有其他)管理这一点。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65367469

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档