Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
X86 串行端口的mmap IO端口地址_X86_Linux Device Driver_Embedded Linux_Kernel Module - Fatal编程技术网

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

X86 串行端口的mmap IO端口地址,x86,linux-device-driver,embedded-linux,kernel-module,X86,Linux Device Driver,Embedded Linux,Kernel Module,我正在检查串行端口(uart)0x2f8的io端口地址是否可以映射到用户空间。 我想自己在驱动程序中实现这一点,而不是使用任何库来知道需要哪些api来实现这一点。然而,鉴于这是x86和端口IO特定的,我不确定它是否真的可以实现。不管怎样,我已经在用户空间中编写了一个mmap函数和调用者 Setting up the mapping is as below: res=请求区域(基本地址,8,“自定义串行设备”); void\uuu iomem*mem\u base\u addr=ioport\u

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

Setting up the mapping is as below:
res=请求区域(基本地址,8,“自定义串行设备”);
void\uuu iomem*mem\u base\u addr=ioport\u map(base\u addr,8);
iowrite8(0x01,(u8*)我的开发->内存基本地址+3)/*没有更多的配置和工作良好*/
/*在此之后,我能够使uart功能在软件环回模式*/
现在我决定在这个地址上尝试mmap:

static int my_dev_mmap(struct file*filep,struct vm_area\u struct*vma){
串行设备*我的设备=(串行设备*)文件P->私有设备数据;
无符号长pfn;
size_t sz=vma->vm_end-vma->vm_start;
无符号长物理地址;
if(vma->vm_end-vma->vm_start!=页面大小){
返回-艾因瓦尔;
}
如果(页面大小>(1个vm\u页面保护=pgprot\u未缓存(vma->vm\u页面保护);
vma->vm|U标志|=vm|U IO;
/*ioport_映射提供了虚拟地址,所以我在下面使用它来获取物理地址*/
phys_addr=virt_to_phys(my_dev->mem_base_addr);
pfn=物理地址>>页面移位;
printk(“GNA:mmap调用:vm开始:0x%lx vm结束:0x%lx内存库:0x%lx物理:0x%lx pfn:%lu\n”,
vma->vm_开始,vma->vm_结束,(未签名长)my_dev->mem_base_addr,phys_addr,pfn);
if(重新映射pfn_范围(vma、vma->vm_开始、pfn、sz、vma->vm_页面保护)){
printk(“GNA:mmap失败\n”);
返回-伊根;
}
返回0;
}
我得到的打印结果如下:

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的内存时,我期望0x5A位于0x2f8(uart的基)的偏移量0x7(便笺簿)处。但是我没有看到预期的输出

我尝试过的另一种方法是,ioport_map给出了一个地址0x102f8,这似乎不正确 类似于虚拟地址,但更多的是物理地址(BASE+0x2f8) 所以,我直接用这个地址得到了pfn,但结果还是一样的

我的用户空间程序如下所示:

address=mmap(空,页面大小,保护读取,保护写入,映射共享,配置fd,0);
在这之后,我试图找到写在暂存器内存中偏移量0x7处的值

for(int i=0;i<10;i++){
printf(“值:0x%x 0x%x\n”,地址[i],地址[0x2f8+i]);
}
因此,是否可以
mmap()
ioport。如果可以,请告诉正确的步骤


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

注意:这个答案是针对x86的

通过输入和输出指令访问I/O端口

应该可以mmap一个由驱动程序管理的跳出缓冲区,并使用这些指令将其写入串行。您可能需要编写一个同步接口(例如刷新ioctl)

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


您可以尝试破坏I/O端口权限,以便用户空间能够访问I/O端口本身管理它。

@rutherford明白了,io端口没有底层结构页,因此无法进行MMAP,如果我尝试根据io地址计算PFN并使用它,它会损坏其他一些有效内存。我想知道ioport\u map在MMIO地址空间中创建页面或映射方面是否有任何作用,因为在ioport\u map之后,我能够完美地使用ioread()和iowrite()MMIO指令。不,不可能将I/O映射到虚拟地址空间。请阅读
ioread()
iowrite()
的实现以获得技巧(是的,您注意到地址只是0x10000+I/O端口,这是在中途,很明显,为什么-I/O空间是16位宽的,这个地址只是第一个不与端口偏移重叠的地址)。是的,这只是x86,在其他体系结构上没有I/O端口的概念。