(1) 系统启动初始化时iotable_init()
-----------------------------
MACHINE_START(AT91SAM9261EK, "ATMEL AT91SAM9261")
············································
        .map_io         = at91sam9261_map_io,
············································
MACHINE_END
--------------------------------------
void __init at91sam9261_map_io(void)
{
iotable_init(at91sam9261_io_desc, ARRAY_SIZE(at91sam9261_io_desc));
}
--------------------------------------
/*
* System peripheral registers mapped at virtual address.
*/

static struct map_desc at91sam9261_io_desc[] __initdata = {
{
   .virtual = AT91C_VA_BASE_SYS,
   .pfn = __phys_to_pfn(AT91C_BASE_AIC),
   .length = SZ_4K,
   .type = MT_DEVICE
},
{
   .virtual = AT91C_VA_BASE_EBI,
   .pfn = __phys_to_pfn(AT91C_BASE_EBI),
   .length = SZ_4K,
   .type = MT_DEVICE
},
     ··············································
};

<./linux/include/asm-arm/map.h>-----------------------
struct map_desc {
unsigned long virtual;
unsigned long pfn;
unsigned long length;
unsigned int type;   //标志位:domain、read、write、cache、buffer
};

#define __phys_to_pfn(paddr)             ((paddr) >> PAGE_SHIFT)
#define __pfn_to_phys(pfn)                 ((pfn) << PAGE_SHIFT)
--------------------------------------
   iotable_init()函数<./arch/arm/mm/mm-armv.c>循环调用create_mapping()函数完成IO的虚拟地址到物理地址的映射。

(2) 系统启动后,在驱动中ioremap()
--------------------------------------
static struct platform_device *smdk2410_devices[] __initdata = {
&s3c_device_usb,    //片上的各个设备
&s3c_device_lcd,    //下面以s3c_device_lcd为例
&s3c_device_wdt,
&s3c_device_i2c,
&s3c_device_iis,
};
--------------------------------------
struct platform_device s3c_device_lcd = {
.name = "s3c2410-lcd", //此处设备的命名应和相应驱动程序命名一致以实现driver bind
.id = -1,                        //-1表示不支持同类多个设备
.num_resources = ARRAY_SIZE(s3c_lcd_resource),
.resource = s3c_lcd_resource,
.dev = {
.dma_mask = &s3c_device_lcd_dmamask,
.coherent_dma_mask = 0xffffffffUL
}
};

-------------------------------------
/* LCD Controller */
static struct resource s3c_lcd_resource[] = {   //LCD的两个资源
[0] = {
.start = S3C2410_PA_LCD,
.end = S3C2410_PA_LCD + S3C2410_SZ_LCD,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_LCD,
.end = IRQ_LCD,
.flags = IORESOURCE_IRQ,
}

};
------------------------------------
/* -------Resource type -------- */
#define IORESOURCE_IO                0x00000100       
#define IORESOURCE_MEM                0x00000200
#define IORESOURCE_IRQ                0x00000400
#define IORESOURCE_DMA                0x00000800
------------------------------------

-----s3c_device_lcd的resource中硬件地址---------------

#define S3C2410_LCDREG(x) (x)

/* LCD control registers */
#define S3C2410_LCDCON1     S3C2410_LCDREG(0x00)
#define S3C2410_LCDCON2     S3C2410_LCDREG(0x04)
#define S3C2410_LCDCON3     S3C2410_LCDREG(0x08)
#define S3C2410_LCDCON4     S3C2410_LCDREG(0x0C)
#define S3C2410_LCDCON5     S3C2410_LCDREG(0x10)

/* LCD controller */
#define S3C2410_PA_LCD    (0x4D000000)
#define S3C24XX_SZ_LCD    SZ_1M
-----------------------------------
/**
* platform_device_register - add a platform-level device
* @pdev: platform device we're adding
*
*/
int platform_device_register(struct platform_device * pdev)
{
device_initialize(&pdev->dev);        //初始化设备结构
return platform_device_add(pdev); //添加一个片上的设备到设备层
}
------------------------------------------
/**
* platform_device_add - add a platform device to device hierarchy
* @pdev: platform device we're adding
*
* This is part 2 of platform_device_register(), though may be called
* separately _iff_ pdev was allocated by platform_device_alloc().
*/
int platform_device_add(struct platform_device *pdev)
{
int i, ret = 0;
if (!pdev)
   return -EINVAL;

if (!pdev->dev.parent)
   pdev->dev.parent = &platform_bus;
pdev->dev.bus = &platform_bus_type;

if (pdev->id != -1)
   snprintf(pdev->dev.bus_id, BUS_ID_SIZE, "%s.%u", pdev->name, pdev->id);
                 /* 若支持同类多个设备,则用pdev->name和pdev->id在总线上标识该设备 */
else
   strlcpy(pdev->dev.bus_id, pdev->name, BUS_ID_SIZE);
                /*               否则,用pdev->name(即"s3c2410-lcd")在总线上标识该设备               */

for (i = 0; i < pdev->num_resources; i++) {
                /*           遍历资源数,并为各自在总线地址空间请求分配            */
   struct resource *p, *r = &pdev->resource[i];

if (r->name == NULL)
    r->name = pdev->dev.bus_id;

p = r->parent;
   if (!p) {
    if (r->flags & IORESOURCE_MEM)
      p = &iomem_resource;
                                          /*    LCD寄存器地址作为IO内存资源分配   */
                                                      ----------------
                                                      struct resource iomem_resource = {
                                                              .name   = "PCI mem",
                                                              .start = 0UL,
                                                              .end    = ~0UL,
                                                              .flags = IORESOURCE_MEM,
                                                               };
                                                      ----------------
    else if (r->flags & IORESOURCE_IO)
      p = &ioport_resource;
   }
                      
   if (p && insert_resource(p, r)) {
                              /*   将LCD寄存器地址插入到IO内存空间 */
    printk(KERN_ERR
          "%s: failed to claim resource %d/n",
          pdev->dev.bus_id, i);
    ret = -EBUSY;
    goto failed;
   }
}

pr_debug("Registering platform device '%s'. Parent at %s/n",
   pdev->dev.bus_id, pdev->dev.parent->bus_id);

ret = device_add(&pdev->dev);
if (ret == 0)
   return ret;

failed:
while (--i >= 0)
   if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO))
    release_resource(&pdev->resource[i]);
return ret;
}
-----------------------------------------

static struct platform_driver s3c2410fb_driver = {
.probe   = s3c2410fb_probe,
.remove   = s3c2410fb_remove,
.suspend = s3c2410fb_suspend,
.resume   = s3c2410fb_resume,
.driver   = {
   .name = "s3c2410-lcd",
   .owner = THIS_MODULE,
},
};

platform_driver_register(&s3c2410fb_driver)----->
driver_register(&drv->driver)----->
bus_add_driver(drv)----->
driver_attach(drv)----->
bus_for_each_dev(drv->bus, NULL, drv, __driver_attach)----->
__driver_attach(struct device * dev, void * data)----->
driver_probe_device(drv, dev)----->
really_probe(dev, drv)----->

在really_probe()中:
            为设备指派管理该设备的驱动:dev->driver = drv
            调用s3c2410fb_probe()初始化设备:drv->probe(dev)
---------------------------------
static int __init s3c2410fb_probe(struct platform_device *pdev)
{
·····························
                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                /*          取得LCD控制寄存器的物理地址           */

size = (res->end - res->start)+1;
info->mem = request_mem_region(res->start, size, pdev->name);
               /* 个人理解:设备注册时已经分配区域,驱动这里应该不是必须的*/

info->io = ioremap(res->start, size);
               /*      此时驱动便可以用指针info->io 读写LCD控制寄存器了    */
               /*              eg: readl(info->io + S3C2410_LCDCON1)              */
····························
}

--------------------------------
以下是AT91SAM9261EK的IOMEM:

root@ebd9261:~# cat /proc/iomem
00500000-005fffff : usb-ohci.0
00500000-005fffff : ohci_hcd
00600000-00600fff : sidsa-lcdc.0     //支持同类多个设备,在驱动中未分配I/O内存区域
20000000-23ffffff : System RAM
20022000-20225e47 : Kernel text
20226000-2028da23 : Kernel data
30000000-30000003 : dm9000.0   
30000000-30000003 : dm9000   
30000044-300000ff : dm9000.0
30000044-300000ff : dm9000
fffa4000-fffa7fff : at91_udc            //不支持同类多个设备,在驱动中也分配I/O内存区域
fffa4000-fffa7fff : at91_udc
fffb0000-fffb3fff : usart.1
fffb4000-fffb7fff : usart.2
fffc8000-fffcbfff : spi.0
fffff200-fffff3ff : usart.0

I/O资源如何映射到内核虚拟空间相关推荐

  1. Spring Boot与Web开发简介||SpringBoot对静态资源的映射规则

    Web开发 1.简介 使用SpringBoot: 1).创建SpringBoot应用,选中我们需要的模块: 2).SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运 ...

  2. 5G上下行传输方案及资源块映射

    传输方案 下行传输方案 采用基于透明DMRS的传输方式,即层到DMRS端口采用一对一的直接映射方式,数据层与对应的DMRS端口使用相同的空域预处理方式.在这种方式下,预编码与波束赋形等关键的MIMO操 ...

  3. JAVA实现资源文件映射

    后端服务启动后,未设置路径映射时,通过浏览器仅能访问项目路径下的资源文件.若想访问服务器其他磁盘的文件则需要做磁盘映射,具体使用方法如下: 1.具体实现 增加以下配置类,实现WebMvcConfigu ...

  4. SpringBoot静态资源的映射

    一, webjars 所有的webjars被导入后,目录结构都是这样的 : springboot的底层告诉我们 , 如果要引用webjars , 我们只需要在引用的位置使用 " /webja ...

  5. nginx 静态资源文件映射

    模板文件中 引入/source/xxxx.css, .js文件  /source目录是不存在的,  映射到  http://s.bjp-sp1.com location /source/ { prox ...

  6. hi3531的pcie atu资源重映射

    1. 设置ATU 区域号寄存器为需要配置的地址转换区编号. 2. 设置ATU Region Lower Base Address Register 和ATU Region Upper Base Add ...

  7. Linux内核中ioremap映射的透彻理解

    几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器.状态寄存器和数据寄存器三大类,外设的寄存器通常被连续地编址.根据CPU体系结构的不同,CPU对IO端口的编址方式有两种: (1)I ...

  8. 经典]Linux内核中ioremap映射的透彻理解【转】

    转自:http://blog.csdn.net/lanyang123456/article/details/7403514 几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器.状态寄 ...

  9. linux对IO口控制remap,ioremap/remap_page_range [经典]Linux内核中ioremap映射的透彻理解...

    几乎每一种外设都是通过读写设备上的寄存器来进行的,通常包括控制寄存器.状态寄存器和数据寄存器三大类,外设的寄存器通常被连续地编址.根据CPU体系结构的不同,CPU对IO端口的编址方式有两种: (1)I ...

  10. linux内存重映射的概念及对内核虚拟地址的重映射方法分析

    [摘要]本文分析了Linux设备的内存映射的相关概念和理论,使用例子对mmap及nopage的驱动编写方法进行了解释,最后对3种不同的内核虚拟空间分配方法下,mmap驱动编写方法进行了细致的分析和调试 ...

最新文章

  1. linux shell cgi post,linux下shell处理cgi的方法--post get
  2. 用eclipse玩转Python,让习惯java开发的童鞋拥有一个更爽的开发体验
  3. linux 内核与用户空间通信之netlink使用方法
  4. php加图片源码_PHP添加文字水印或图片水印的水印类完整源代码与使用示例
  5. 【Pytorch神经网络实战案例】09 使用卷积提取图片的轮廓信息(手动模拟Sobel算子)
  6. 剑指offer——29.顺时针打印矩阵(不熟)
  7. Intouch2020安装与授权
  8. android网易课堂app,网易云课堂
  9. 国际象棋 小麦 用java怎么算_蓝桥杯-放麦子-java
  10. cad打开服务器文件太慢,CAD打开文件很慢怎么处理
  11. 克拉克松Clarkson Research情报网注册登录及进行数据查询(以世界造船厂分布为例)
  12. Excel隔行插入空行(亲自实践)
  13. lesson 20 one man in a boat 独坐孤舟-for hours数小时做时间状语,having done于句首非谓语做状语,its wasteof time,do nothing
  14. 计算机设备和打印机打不开,Windows7设备和打印机窗口打不开如何解决
  15. VirtualBox 安装增强功能失败 解决方法
  16. 解决在MAC上输入法切换慢的问题
  17. 素数统计 平移区间筛质数(1e9)
  18. 微信小游戏的内存调优指南
  19. 将台式电脑声音无线传输到IOS,安卓手机上播放,再到蓝牙音箱上播放
  20. 《周鸿祎自述:我的互联网方法论》----摘抄

热门文章

  1. Android开发 MeasureSpec介绍
  2. c#机器人聊天软件_3.C#面向对象基础聊天机器人
  3. (详解)无指针AC自动机
  4. js高级学习笔记(b站尚硅谷)-4-函数
  5. who 、w 查看当前登录用户
  6. 计算机专业学科建设3,学科建设-华中科技大学计算机科学与技术学院
  7. linux脚本中sed -i,Linux Shell 脚本之sed命令详解
  8. c++ 图片验证码识别_图片验证码识别方法
  9. c++ opengl 绘制地面_铝合金门窗设计之绘制节点图
  10. mac 环境 Android Studio升级后Gradle project Sync Failed解决方法