void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
void *ioremap(unsigned long phys_addr, unsigned long size)
入口: phys_addr:要映射的起始的IO地址;
size:要映射的空间的大小;
flags:要映射的IO空间的和权限有关的标志;
phys_addr:是要映射的物理地址,
size:是要映射的长度,
S3C2410的long是32位而非64位。
功能:将一个IO
地址空间映射到内核的虚拟地址空间上去,便于访问;
实现:对要映射的IO
地址空间进行判断,低PCI/ISA地址不需要重新映射,也不允许用户将IO地址空间映射到正在使用的RAM中,最后申请一个 vm_area_struct结构,调用remap_area_pages填写
页表,若填写过程不成功则释放申请的vm_area_struct空间;
ioremap 依靠 __ioremap实现,它只是在__ioremap中以第三个参数为0调用来实现.
ioremap是
内核提供的用来映射外设寄存器到主存的函数,我们要映射的地址已经从pci_dev中读了出来(上一步),这样就水到渠成的成功映射了而不会和其他地址有冲突。映射完了有什么效果呢,我举个例子,比如某个网卡有100 个寄存器,他们都是连在一块的,位置是固定的,假如每个寄存器占4个
字节,那么一共400个字节的空间被映射到内存成功后,ioaddr就是这
段地址的开头(注意ioaddr是
虚拟地址,而mmio_start是
物理地址,它是BIOS得到的,肯定是物理地址,而保护模式下CPU不认物理地址,只认虚拟地址),ioaddr+0就是第一个寄存器的地址,ioaddr+4就是第二个寄存器地址(每个寄存器占4个字节),以此类推,我们就能够在内存中访问到所有的寄存器进而操控他们了。
举个简单操作寄存器的例子
举个简单操作寄存器的例子
#include <linux/init.h>
#include <linux/module.h>
#include <linux/io.h>
#if 0
#define GPMCON *(volatile unsigned long *)0x7F008820
#define GPMDAT *(volatile unsigned long *)0x7F008824
#endif
#define GPMCON 0x7F008820
#define GPMDAT 0x7F008824
static volatile unsigned long *conf, *data;
static int __init test_init(void)
{
#if 0
GPMCON = 0x1111;
GPMDAT = 0x0;
#endif
conf = ioremap(GPMCON, 4);
data = ioremap(GPMDAT, 4);
*conf = 0x1111;
*data = 0x0;
return 0;
}
static void __exit test_exit(void)
{
#if 0
GPMDAT = 0xF;
#endif
*data = 0xf;
iounmap(conf);
iounmap(data);
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");