一个 PCI 设备实现直至 6 个 I/O 地址区. 每个区由要么内存要么 I/O 区组成. 大部分 设备实现它们的 I/O 寄存器在内存区中, 因为通常它是一个完善的方法(如同在" I/O 端

口和 I/O 内存"一节中解释的, 在第 9 章). 但是, 不像正常的内存, I/O 寄存器不应当 被 CPU 缓存, 因为每次存取都可能有边际效果. 作为内存区来实现 I/O 寄存器的 PCI 设备, 通过设置一个在它的配置寄存器的"内存可预取"位来标志出这个不同.[43] 如果这个 内存区被标识为可预取的, CPU 可缓存它的内容并且对它做所有类型的优化. 非可预取的 内存存取, 另一方面, 不能被优化因为每次存取可能有边际效果, 就象 I/O 端口. 映射 它们的寄存器到一个内存地址范围的外设声明这个范围是非可预取的, 而象在 PCI 板的 视频内存的一些是可预取的. 在本节, 我们使用词语"区"来指代一个通用的 I/O 地址空 间, 这个空间要么是内存映射的, 要么是端口映射的.

一个接口板报告它的区的大小和当前位置, 使用配置寄存器- 6 个 32 位寄存器, 在图 12-2 中显示的, 它们的符号名是 PCI_ADDRESS_0 到 PCI_BASE_ADDRESS_5. 因为 PCI 定 义的 I/O 空间是 32-位空间, 使用同样的配置接口给内存和 I/O 是有意义的. 如果设备 使用 64-位地址总线, 它可以在 64-位内存空间声明各个区, 使用 2 个连续的

PCI_BASE_ADDRESS 寄存器给每个区, 低位在前. 对一个设备可能提供 32-位 和 64-位区.

内核中, PCI 设备的 I/O 区已被集成到通用的资源管理中. 由于这个原因, 你不必存取 配置变量来知道你的设备映射到内存或者 I/O 空间什么地方. 首选的用来获得区信息的 接口包括下列函数:

unsigned long pci_resource_start(struct pci_dev *dev, int bar);

这个函数返回第一个地址(内存地址或者 I/O 端口号), 和 6 个 PCI I/O 区中的 一个相关联的. 这个区通过整数 bar (the base address register), 范围从 0-5 (包含).

unsigned long pci_resource_end(struct pci_dev *dev, int bar);

这个函数返回最后一个地址, I/O 区号 bar 的一部分. 注意这是最后一个可用地 址, 不是这个区后的第一个地址.

unsigned long pci_resource_flags(struct pci_dev *dev, int bar); 这个函数返回和这个资源相关联的标识.

资源标识用来定义单个资源的一些特性. 对于和 PCI I/O 区相关联的 PCI 资源, 这个信 息从基地址寄存器中抽取出来, 但是可来自其他地方, 对于没有和 PCI 设备关联的资源.

所有的资源标志都定义在 <linux/ioport.h>; 最重要的是: IORESOURCE_IO

IORESOURCE_MEM

如果被关联的 I/O 区存在, 一个并且只有一个这样的标志被设置.

IORESOURCE_PREFETCH IORESOURCE_READONLY

这些标志告诉是否一个内存区是可预取的并且/或者写保护的. 后一个标志对 PCI 资源从不设置.

通过使用
pci_resource_ 函数, 一个设备驱动可完全忽略底层的 PCI 寄存器, 因为系统 已经使用它们来构造资源信息.

Linux 内核存取 I/O 和内存空间的更多相关文章

  1. 十天学Linux内核之第三天---内存管理方式

    原文:十天学Linux内核之第三天---内存管理方式 昨天分析的进程的代码让自己还在头昏目眩,脑子中这几天都是关于Linux内核的,对于自己出现的一些问题我会继续改正,希望和大家好好分享,共同进步.今 ...

  2. 【转载】linux内核笔记之高端内存映射

    原文:linux内核笔记之高端内存映射 在32位的系统上,内核使用第3GB~第4GB的线性地址空间,共1GB大小.内核将其中的前896MB与物理内存的0~896MB进行直接映射,即线性映射,将剩余的1 ...

  3. 大话Linux内核中锁机制之内存屏障、读写自旋锁及顺序锁

    大话Linux内核中锁机制之内存屏障.读写自旋锁及顺序锁 在上一篇博文中笔者讨论了关于原子操作和自旋锁的相关内容,本篇博文将继续锁机制的讨论,包括内存屏障.读写自旋锁以及顺序锁的相关内容.下面首先讨论 ...

  4. [置顶] linux内核启动2-setup_arch中的内存初始化(目前分析高端内存)

    上一篇微博留下了这几个函数,现在我们来分析它们         sanity_check_meminfo();         arm_memblock_init(&meminfo, mdes ...

  5. Linux内核源码分析 day01——内存寻址

    前言 Linux内核源码分析 Antz系统编写已经开始了内核部分了,在编写时同时也参考学习一点Linux内核知识. 自制Antz操作系统 一个自制的操作系统,Antz .半图形化半命令式系统,同时嵌入 ...

  6. Linux内核中锁机制之内存屏障、读写自旋锁及顺序锁

    在上一篇博文中笔者讨论了关于原子操作和自旋锁的相关内容,本篇博文将继续锁机制的讨论,包括内存屏障.读写自旋锁以及顺序锁的相关内容.下面首先讨论内存屏障的相关内容. 三.内存屏障 不知读者是是否记得在笔 ...

  7. Linux 内核存取配置空间

    在驱动已探测到设备后, 它常常需要读或写 3 个地址空间: 内存, 端口, 和配置. 特别 地, 存取配置空间对驱动是至关重要的, 因为这是唯一的找到设备被映射到内存和 I/O 空间的位置的方法. 因 ...

  8. 《Linux内核设计与实现》内存管理札记

    1.页 芯作为物理页存储器管理的基本单元,MMU(内存管理单元)中的页表,从虚拟内存的角度来看,页就是最小单位. 内核用struct page结构来标识系统中的每个物理页.它的定义例如以下: flag ...

  9. 发布Ubuntu/Linux系统cache,增加可用内存空间

    桌面Ubuntu总内存4G,但free只有内存有100M 重视top命令检查看到真正的能力free内存.以下是真正的内存使用情况的看法有一个命令. watch -n 1 cat /proc/memin ...

随机推荐

  1. Directx11教程(43) 纹理映射(13)-动态纹理映射

    原文:Directx11教程(43) 纹理映射(13)-动态纹理映射      本篇教程中,我们将在前面基于光照的地形与水面程序里面加上纹理映射,而且我们会基于时间动态改变水面的纹理坐标,实现水面纹理 ...

  2. 基于Spark Mllib的Spark NLP库

    SparkNLP的官方文档 1>sbt引入: scala为2.11时 libraryDependencies += "com.johnsnowlabs.nlp" %% &qu ...

  3. PHP实现git部署的方法教程

    https://mp.weixin.qq.com/s/WH_JXah47BhQyviuuPAunw 背景 在小站点上,直接用git来部署php代码相当方便,你的远程站点以及本地版本库都有一个版本控制, ...

  4. 四.使用JDBC进行批处理操作

    1 create table testbatch 2 ( 3 id int primary key, 4 name varchar(20) 5 ); 在实际的项目开发中,有时候需要向数据库发送一批SQ ...

  5. Linux 下的python操作redis

    python操作redis   Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).se ...

  6. ural1297 后缀数组+RMQ

    RMQ即求区间(i,j)的最值.通过O(nlogn)处理,O(1)给出答案. RMQ主要是动态规划来做.dp[i][j]表示从i开始的长为2^j的区间最值. 那么可以得到dp[i][j]=max(dp ...

  7. 【NS2】NS2在ubuntu下的安装

    Step1: 更新系统.在终端输入如下命令 sudo apt-get  update #更新源列表sudo apt-get upgrade #更新已经安装的包sudo apt-get dist-upg ...

  8. poj 2342 hdu 1520【树形dp】

    poj 2342 给出每个顶点的happy值,还有若干组两个顶点L,K关系,表示K是L的上司.求当K.L不同时出现时获得的happy值的最大和. 设dp[u][0]表示不选u结点时获得的最大值,dp[ ...

  9. typeid, const_cast<Type>的使用

    #include <bits/stdc++.h> using namespace std; class A { public : void Show() { cout << & ...

  10. iOS编译错误#ld: warning: ignoring file# 之 Undefined symbols for architecture x86_64 - ld: symbol(s) not found for architecture x86_64

    ld: warning: ignoring file xxxPath/libbaidumapapi.a, missing required architecture x86_64 in file xx ...