494
查看I/O端口的访问的源代码
I/O端口的访问
0
←
I/O端口的访问
跳转至:
导航
、
搜索
因为以下原因,你没有权限编辑本页:
你被禁止执行你刚才请求的操作。
您可以查看并复制此页面的源代码:
=== '''一、基础介绍''' === IO寄存器(内存)有两种地址映射方式,即映射到IO地址空间(portio),映射到内存地址空间(mmio)。 在linux-2.6之前,前者使用inb/outb(......)访问,后者通过readb/writeb(......)来访问(访问前必须使用ioremap将IO物理地址映射到虚拟地址)。 ioremap函数作用如前所述,就是将IO物理地址映射成虚拟地址,这样readb/writeb可以访问映射后的地址。mmio映射的IO内存,其物理地址已经在4G地址空间内,与内存的编址方式相同。因此ioremap的作用实际上就是为这一段物理地址建立页表,返回驱动程序可以访问的虚拟地址。 ioport_map函数的目的是试图提供与ioremap一致的虚拟地址空间。这样不论portio还是mmio都可以使用统一的访问函数:ioread8/iowrite8(......)。 我们进入ioport_map和ioport_unmap函数: <pre class="prettyprint"> void __iomem *ioport_map(unsigned long port, unsigned int nr) { if (port > PIO_MASK) return NULL; return (void __iomem *) (unsigned long) (port + PIO_OFFSET); } void ioport_unmap(void __iomem *addr) { /* Nothing to do */ } </pre> 其实函数很简单,ioport_map仅仅是将port加上PIO_OFFSET(64k),而ioport_unmap则什么都不做。这样portio的64k空间就被映射到虚拟地址的64k~128k之间,而ioremap返回的虚拟地址则肯定在3G之上。这样portio和mmio的虚拟地址就被统一起来。 再看ioread8的源码,其实现也就是对虚拟地址进行了判断,以区分portio和mmio,然后分别使用inb/outb,和readb/writeb来读写。 <pre class="prettyprint"> unsigned int fastcall ioread8(void __iomem *addr) { IO_COND(addr, return inb(port), return readb(addr)); } #define VERIFY_PIO(port) BUG_ON((port & ~PIO_MASK) != PIO_OFFSET) #define IO_COND(addr, is_pio, is_mmio) do { \ unsigned long port = (unsigned long __force)addr; \ if (port < PIO_RESERVED) { \ VERIFY_PIO(port); \ port &= PIO_MASK; \ is_pio; \ } else { \ is_mmio; \ } \ } while (0) </pre> 展开: <pre class="prettyprint"> unsigned int fastcall ioread8(void __iomem *addr) { unsigned long port = (unsigned long __force)addr; if( port < 0x40000UL ) { BUG_ON( (port & ~PIO_MASK) != PIO_OFFSET ); port &= PIO_MASK; return inb(port); }else{ return readb(addr); } } </pre> === '''二、图文讲解''' === 1.IO端口访问 一种方法是:直接使用IO端口操作函数:在设备打开或驱动模块被加载时申请IO端口区域,之后使用inb(),outb()等进行端口访问,最后在设备关闭或驱动被卸载时释放IO端口范围。流程如下: [[Image:linux_portio_handle1.jpeg]] 另外一种途径是:将IO端口映射为内存进行访问,在设备打开或驱动模块被加载时,申请IO端口区域并使用ioport_map()映射到内存,之后使用IO内存的函数进行端口访问,最后,在设备关闭或驱动模块被卸载时释放IO端口并释放映射,流程如下: [[Image:linux_portio_handle2.jpeg]] 2.IO内存访问 上边是IO端口的访问方法,至于IO内存的访问方法是:首先调用request_mem_region()申请资源,接着将寄存器地址通过ioremap()映射到内核空间的虚拟地址,之后就可以Linux设备访问编程接口访问这些寄存器了,访问完成后,使用ioremap()对申请的虚拟地址进行释放,并释放release_mem_region()申请的IO内存资源。 流程如下: [[Image:linux_mmio_handle.jpeg]] 参考文档: http://blog.csdn.net/hanchaoman/article/details/6967423 http://blog.21ic.com/user1/6137/archives/2009/64709.html
返回
I/O端口的访问
。
导航菜单
个人工具
   
个人维基
注册
登录
名字空间
页面
变换
查看
阅读
查看源代码
统计
查看历史
操作
搜索
导航
首页
Ubuntu
Android
C&CPP
Java
Python
大杂烩
最近更改
工具箱
所有页面
文件列表
特殊页面