#define ALMDAY bRTC(0x60) #define ALMMON bRTC(0x64) #define ALMYEAR bRTC(0x68) |
其中借助了宏bRTC,这个宏定义为:
#define bRTC(Nb) __REG(0x57000000 + (Nb)) |
其中又借助了宏__REG,而__REG又定义为:
# define __REG(x) io_p2v(x) |
最后的io_p2v才是真正"玩"虚拟地址和物理地址转换的地方:
#define io_p2v(x) ((x) | 0xa0000000) |
与__REG对应的有个__PREG:
# define __PREG(x) io_v2p(x) |
与io_p2v对应的有个io_v2p:
#define io_v2p(x) ((x) & ~0xa0000000) |
可见有没有出现ioremap是次要的,关键问题是有无虚拟地址和物理地址的转换!
下面的程序在启动的时候保留一段内存,然后使用ioremap将它映射到内核虚拟空间,同时又用remap_page_range映射到用户虚拟空间,这样一来,内核和用户都能访问。如果在内核虚拟地址将这段内存初始化串"abcd",那么在用户虚拟地址能够读出来:
/************mmap_ioremap.c**************/ #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/wrapper.h> /* for mem_map_(un)reserve */ #include <asm/io.h> /* for virt_to_phys */ #include <linux/slab.h> /* for kmalloc and kfree */
MODULE_PARM(mem_start, "i"); MODULE_PARM(mem_size, "i");
static int mem_start = 101, mem_size = 10; static char *reserve_virt_addr; static int major;
int mmapdrv_open(struct inode *inode, struct file *file); int mmapdrv_release(struct inode *inode, struct file *file); int mmapdrv_mmap(struct file *file, struct vm_area_struct *vma);
static struct file_operations mmapdrv_fops = { owner: THIS_MODULE, mmap: mmapdrv_mmap, open: mmapdrv_open, release: mmapdrv_release, };
int init_module(void) { if ((major = register_chrdev(0, "mmapdrv", &mmapdrv_fops)) < 0) { printk("mmapdrv: unable to register character device\n"); return ( - EIO); } printk("mmap device major = %d\n", major);
printk("high memory physical address 0x%ldM\n", virt_to_phys(high_memory) / 1024 / 1024);
|
|