【问题标题】:Accessing memory pointers in hardware registers访问硬件寄存器中的内存指针
【发布时间】:2015-07-06 23:57:53
【问题描述】:

我正在努力增强 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。这个内存地址是否在我不能简单地取消引用它的空间中?

此时我正碰壁,因为@​​987654322@ 以这种方式访问​​它本质上就是这样做的。

【问题讨论】:

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


    【解决方案1】:

    得到高低地址后得到的地址 通常类似于 0x0000000037900000。这是内存地址吗 在一个我不能简单地取消引用它的空间中?

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

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

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

    【讨论】:

    • 感谢您的回复。我曾怀疑过这一点。另外,感谢您提供访问此寄存器的提示,这使事情变得更容易(我希望如此)。我正在为我工​​作在新的水域。这是我的第一个驱动程序项目。
    • 我有一个问题。我找不到如何私下给你发消息,也许其他人无论如何都会受益。你能解释一下linkcmd_slot_和_cmd_slot_dma之间的关系吗?我在想 cmd_slot 是虚拟地址,另一个是同一位置的 DMA 可寻址地址。我是正确的,还是它们无关?
    • 是的,没错 - cmd_slot 是指向 DMA 缓冲区的可取消引用指针,cmd_slot_dma 是发送到设备的同一缓冲区的总线地址。
    猜你喜欢
    • 2022-08-30
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-14
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    相关资源
    最近更新 更多