内核ACPI函数API之acpi_os_map_iomem

void __iomem *__ref
acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
的作用是将形参指定的物理地址的范围映射为虚拟地址。
其源码分析如下:
void __iomem *__ref
acpi_os_map_iomem(acpi_physical_address phys, acpi_size size)
{
	struct acpi_ioremap *map;
	void __iomem *virt;
	acpi_physical_address pg_off;
	acpi_size pg_sz;
	#要映射的物理地址超过范围就直接报 error退出
	if (phys > ULONG_MAX) {
		printk(KERN_ERR PREFIX "Cannot map memory that high\n");
		return NULL;
	}
	#开来映射还分为临时映射和永久映射,这样一般都是永久映射
	if (!acpi_permanent_mmap)
		return __acpi_map_table((unsigned long)phys, size);

	mutex_lock(&acpi_ioremap_lock);
	/* Check if there's a suitable mapping already. */
	#所有通过这个函数映射的物理地址都会在acpi_ioremaps 这个链表中,这些会先检查这个物理
	#地址是否已经被映射过了,如果已经被映射过了,就不会重复映射,增加refcount 即可,这里也可以看出同一个物理地址是可以被重复映射的
	
	map = acpi_map_lookup(phys, size);
	if (map) {
		map->refcount++;
		goto out;
	}
	#走到这里说明这个地址没有被映射过,这里申请一个struct acpi_ioremap *map #用于保存映射的结果
	map = kzalloc(sizeof(*map), GFP_KERNEL);
	if (!map) {
		mutex_unlock(&acpi_ioremap_lock);
		return NULL;
	}
	#转换要映射的地址和范围
	pg_off = round_down(phys, PAGE_SIZE);
	pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
	#调用acpi_map 映射后得到虚拟地址virt
	virt = acpi_map(pg_off, pg_sz);
	if (!virt) {
		mutex_unlock(&acpi_ioremap_lock);
		kfree(map);
		return NULL;
	}
	#将映射后的虚拟地址和映射前的物理地址保存在map中
	INIT_LIST_HEAD(&map->list);
	map->virt = virt;
	map->phys = pg_off;
	map->size = pg_sz;
	map->refcount = 1;
	#所有的映射结果也就是物理地址和虚拟地址的对应关系都保存在acpi_ioremaps
	list_add_tail_rcu(&map->list, &acpi_ioremaps);

out:
	mutex_unlock(&acpi_ioremap_lock);
	return map->virt + (phys - map->phys);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值