linux - 访问硬件寄存器中的内存指针

标签 linux linux-kernel driver linux-device-driver sata

我正在努力增强 Linux 中提供的库存 ahci 驱动程序,以执行一些需要的任务。我正在尝试向 AHCI HBA 发出命令以供硬盘驱动器处理。但是,每当我这样做时,我的系统都会锁定并重新启动。试图解释向 AHCI 驱动器发出命令的过程对于这个问题来说远远不够。如果需要,reference this link for the full discussion (这个过程相当完整地定义了,因为有几个部分,但是,第 4 章具有必要的数据结构)。

本质上,将适当的结构写入由 BIOS 或操作系统定义的内存区域。我应该写入的第一个内存区域是寄存器 PxCLB 中包含的命令列表基地址(如果适用 64 位寻址,则为 PxCLBU)。我的系统是 64 位的,所以我正在尝试获取两个 32 位寄存器。我的代码基本上是这样的:

void __iomem * pbase = ahci_port_base(ap);
u32 __iomem *temp = (u32*)(pbase + PORT_LST_ADDR);
struct ahci_cmd_hdr *cmd_hdr = NULL;

cmd_hdr = (struct ahci_cmd_hdr*)(u64)
    ((u64)(*(temp + PORT_LST_ADDR_HI)) << 32 | *temp);

pr_info("%s:%d cmd_list is %p\n", __func__, __LINE__, cmd_hdr);
// problems with this next line, makes the system reboot
//pr_info("%s:%d cl[0]:0x%08x\n", __func__, __LINE__, cmd_hdr->opts);

函数 ahci_port_base() 可在 ahci 驱动程序中找到(至少它适用于 CentOS 6.x)。基本上,它返回 AHCI 内存区域中该端口的正确地址。 PORT_LST_ADDR 和 PORT_LST_ADDR_HI 都是该驱动程序中定义的宏。我在同时获得高地址和低地址后得到的地址通常类似于 0x0000000037900000。这个内存地址在我不能简单地取消引用的空间中吗?

此时我正在用头撞墙,因为 this link shows以这种方式访问​​它本质上是如何完成的。

最佳答案

The address that I get after getting both the high and low addresses is usually something like 0x0000000037900000. Is this memory address in a space that I cannot simply dereference it?

是的,你是对的——那是一个总线地址,你不能因为启用了分页就取消引用它。 (你也不应该只是取消引用 iomapped 地址——你应该为那些使用 readl()/writel(),但这里的破损更微妙)。

看起来在该驱动程序中访问 ahci_cmd_hdr 的正确方法是:

struct ahci_port_priv *pp = ap->private_data;
cmd_hdr = pp->cmd_slot;

关于linux - 访问硬件寄存器中的内存指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31257618/

相关文章:

linux-kernel - linux系统调用实现

c - 读取(fd,NULL,0);它有什么作用?它定义明确吗?

c - Linux:是否可以在进程之间共享代码?

linux - 我可以在网络主机上上传文件名包含 "*"字符的文件吗?

linux - 在 RPATH 中指定 $ORIGIN 的推荐 GNU 链接器选项是什么?

linux - ARM Linux 是如何维护段的?

c - 我们最多可以将多少个共享库链接到 C 和 Linux 中的应用程序?

c - 驱动程序函数不会在 c 中执行,但其他函数会执行

c++ - 窗口 : load a filter driver while windows is running

windows - 检查 Windows 上是否加载了驱动程序