浅析Linux设备驱动:IO端口和IO内存

文章目录

    • 概述
      • IO端口和IO内存的区别
    • IO资源管理
      • IO资源类型
        • IO端口资源
        • IO内存资源
      • IO资源分配
    • IO端口访问
      • IO端口操作函数
    • IO内存访问
      • IO内存操作函数
    • 相关参考

概述

在计算机系统中,外部设备通常会提供一组寄存器或内存用于处理器配置和访问设备功能。这些寄存器或内存可能位于IO空间,或者内存空间。当寄存器或内存位于IO空间时,称为IO端口;当寄存器或内存位于内存空间时,称为IO内存。

IO端口和IO内存的区别

IO端口和IO内存的主要区别在于CPU对外设IO寄存器物理地址的编址方式不同。已存在的编址方式有两种:独立编址和统一编址,其中:

  • 独立编址:外设使用独立的IO地址空间,并使用专门的IO指令进行访问。例如x86体系结构就使用了独立的IO空间,支持64K个IO端口;
  • 统一编址:设备寄存器被映射到CPU的物理内存空间,并支持以访问内存的方式来访问这些寄存器。

IO资源管理

IO端口和IO内存都属于外设提供的IO资源,Linux下通过resource结构来对IO资源进行描述,包括使用的I/O资源的地址空间范围、状态等信息,并将这些resource用ioport_resource或iomem_resource作为表头按地址大小的顺序链接起来。

struct resource {resource_size_t start;	/* 描述设备实体在 CPU 总线上的线性起始物理地址 */resource_size_t end;	/* 描述设备实体在 CPU 总线上的线性结尾物理地址 */const char *name;		/* 描述这个设备实体的名称,这个名字开发人员可以随意起,但最好贴切 */unsigned long flags;	/* 描述这个设备实体的一些共性和特性的标志位 */struct resource *parent, *sibling, *child;
};

IO资源类型

Linux支持运行在多种不同的硬件体系结构上,并同时支持IO端口以及IO内存,为此内核同时维护了这两种类型的IO资源,外部设备按需进行分配。

IO端口资源

IO端口资源由ioport_resource全局变量进行管理,定义如下:

struct resource ioport_resource = {
.name = "PCI IO",
.start = 0,
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
IO内存资源

IO内存资源由iomem_resource全局变量进行管理,定义如下:

struct resource iomem_resource = {
.name = "PCI mem",
.start = 0,
.end = -1,
.flags = IORESOURCE_MEM,
};

IO资源分配

Linux访问设备IO空间前,需要先调用request_region/request_mem_region接口为其分配IO资源区域,其中request_region用于分配IO端口资源,request_mem_region用于分配IO内存资源。

在这里插入图片描述

request_region/request_mem_region调用__request_region函数实现。__request_region函数的主要功能为:查找resource链表中是否有与申请的I/O资源有冲突,如冲突则返回NULL,如不冲突则将新申请resource按resource地址从小到大的顺放插入至以ioport_resource或iomem_resource为表头(root)的单向指针链表中。

IO端口访问

Linux系统下访问IO端口有2种方式:I/O映射方式和内存映射方式。其中:

  • IO映射方式直接使用IO端口操作函数,这些函数内部会调用体系结构相关的IO端口操作指令,例如x86架构下的in/out指令;
  • 内存映射方式是先使用ioport_remap接口把IO端口映射到IO内存空间,再使用IO内存操作函数来访问IO端口。这种方式主要是为了屏蔽IO端口和IO内存在硬件上的差异,统一使用IO内存的方式进行访问。

无论是使用哪种方式,都需要先使用request_region接口申请对应的IO端口资源。完整的IO端口访问流程如下:
在这里插入图片描述

IO端口操作函数

/* inb/outb:读/写字节端口(8位宽) */
unsigned inb(unsigned port);
void outb(unsigned char byte, unsigned port);/* inw/outw:读/写字端口(16位宽) */
unsigned inw(unsigned port);
void outw(unsigned short word, unsigned port);/* inl/outl:读/写32位端口 */
unsigned inl(unsigned port);
void outl(unsigned longword, unsigned port);

IO内存访问

Linux系统访问IO内存需要先调用request_mem_region接口申请资源,接着将设备IO地址通过ioremap接口映射到内核空间的虚拟地址,之后就可以使用IO内存操作函数对这些寄存器进行访问。

完整的IO内存访问流程如下:
在这里插入图片描述

IO内存操作函数

/* I/O内存读函数  */
unsigned int ioread8(void *addr);
unsigned int ioread16(void *addr);
unsigned int ioread32(void *addr);/* I/O内存写函数   */
void iowrite8(u8 value, void *addr);
void iowrite16(u16 value, void *addr);
void iowrite32(u32 value, void *addr);

相关参考

  • Linux系统对IO端口和IO内存的管理
  • Linux设备驱动:I/O端口与I/O内存

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/475840.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【机构vip教程】​python(1):python正则表达式匹配指定的字符开头和指定的字符结束

一&#xff0c;使用python的re.findall函数&#xff0c;匹配指定的字符开头和指定的字符结束 代码示例&#xff1a; 1 import re 2 # re.findall函数;匹配指定的字符串开头和指定的字符串结尾(前后不包含指定的字符串) 3 str01 hello word 4 str02 re.findall((?<e).*?…

安卓开发——有用的网址、经典问题整理

1. 安卓adb无线连接 网址&#xff1a;https://www.cnblogs.com/arcsinw/p/15863513.htmlhttps://www.cnblogs.com/arcsinw/p/15863513.html 2. startActivityForResult 废用 — 改为 registerForActivityResult ​ 安卓的startActivityForResult 方法废用&#xff0c;改为使用…

最长子串和回文子串相关的算法题解

这里写目录标题 一、3. 无重复字符的最长子串二、5. 最长回文子串三、647. 回文子串四、516. 最长回文子序列 一、3. 无重复字符的最长子串 中等 给定一个字符串 s &#xff0c;请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释:…

手把手教你Linux系统下的Java环境配置,简单到不行!

推荐阅读 给软件行业带来了春天——揭秘Spring究竟是何方神圣&#xff08;一&#xff09; 给软件行业带来了春天——揭秘Spring究竟是何方神圣&#xff08;二&#xff09; 文章目录 推荐阅读下载JDK安装包方式一方式二 添加环境变量验证安装情况 下载JDK安装包 方式一 1.进入…

第三百五十二回

文章目录 1. 概念介绍2. 获取方法3. 示例代码4. 对比与总结4.1 横向对比4.2 内容总结 我们在上一章回中介绍了"如何获取当前系统语言"相关的内容&#xff0c;本章回中将介绍如何获取当前时区.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们使用的…

第三百五十三回

文章目录 1. 概念介绍2. 使用方法2.1 获取所有时区2.2 转换时区时间 3. 示例代码4. 内容总结 我们在上一章回中介绍了"分享一些好的Flutter站点"相关的内容&#xff0c;本章回中将介绍timezone包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在…

【PX4-AutoPilot教程-源码】移植PX4固件到自制NuttX操作系统飞控板的方法

移植PX4固件到自制NuttX操作系统飞控板的方法 找到使用相同&#xff08;或型号相似&#xff09;CPU类型的现有目标并进行复制飞控板的配置文件夹结构firmware.prototype文件default.px4board文件bootloader.px4board文件nuttx-config/bootloader/defconfig文件nuttx-config/nsh…

阿莱(ARRI)MOV变0字节恢复案例

阿莱(ARRI)是专业级的影视产品软硬件供应商&#xff0c;很多大片都是使用ARRI的设备拍摄出来的。之前我们处理过阿莱的MXF和MOV等文件&#xff0c;今天要说的案例是ARRI的MOV&#xff0c;还是之前熟悉的EXFAT文件系统然后长度突然变0字节的问题。 故障存储:16T/MS Exfat文件系…

如何在Linux系统中配置并优化硬盘的RAID

在Linux系统中配置和优化硬盘的RAID技术可以帮助提高数据存储性能和安全性。RAID&#xff08;Redundant Array of Independent Disks&#xff09;技术通过将多个硬盘组合起来&#xff0c;以增加性能、容量或冗余度&#xff0c;提高数据的可靠性和可用性。本文将介绍如何在Linux…

Days 34 ElfBoard 音频接口

音频接口介绍 音频模块采用了 NAU88C22 芯片&#xff0c;芯片数据信号使用 I2S 接口进行通讯&#xff0c;主要信号功能&#xff1a; SAI_MCLK&#xff1a;音频信号主时钟&#xff1b; SAI_BCLK&#xff1a;音频信号位时钟&#xff1b; SAI_SYNC&#xff1a;左右声道控制信号&am…

综合练习

目录 查询每个员工的编号、姓名、职位、基本工资、部门名称、部门位置 确定要使用的数据表 确定已知的关联字段 查询每个员工的编号、姓名、职位、基本工资、工资等级 确定要使用的数据表 确定已知的关联字段 查询每个员工的编号、姓名、职位、基本工资、部门名称、工资…

用Boule绘制地球重力场

文章目录 参考椭球标准重力重力地图 参考椭球 boule中定义了多种参考椭球&#xff0c;可用于表示地球、火星等星体的重力分布。可通过pip安装 pip install boule安装完成后可直接调用 import boule as blboule中已经定义的椭球如下 椭球星体GRS80地球WGS84地球MARS火星MERC…