我正在增强Linux中提供的股票ahci驱动程序,以便执行一些所需的任务。我正试图向AHCI HBA发出命令,以便硬盘驱动器进行处理。然而,每当我这样做时,我的系统就会锁定并重新启动。试图解释向AHCI驱动器发出命令的过程对于这个问题来说太难了。如果需要,请参考此链接进行全面讨论(整个过程都有定义,因为有几个部分,然而,ch4具有必要的数据结构(。
本质上,将适当的结构写入由BIOS或OS定义的存储器区域。我应该写入的第一个存储器区域是包含在寄存器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 %pn", __func__, __LINE__, cmd_hdr);
// problems with this next line, makes the system reboot
//pr_info("%s:%d cl[0]:0x%08xn", __func__, __LINE__, cmd_hdr->opts);
函数ahci_port_base((位于ahci驱动程序中(至少适用于Centos6.x(。基本上,它会在ahci内存区域中返回该端口的正确地址。PORT_LST_ADDR和PORT_LST_ ADDR_HI都是在该驱动程序中定义的宏。在得到高和低地址后,我得到的地址通常是0x0000000037900000。这个内存地址是在一个我不能简单地取消引用的空间中吗?
在这一点上,我的头撞到了墙上,因为这个链接表明,以这种方式访问它本质上就是这样做的。
我在获得高地址和低地址后得到的地址通常类似于0x0000000037900000。这是内存地址吗在一个我不能简单地取消引用的空间里?
是的,你是对的——这是一个总线地址,你不能因为启用了分页就取消引用它。(你也不应该只是取消引用iomapped地址——你应该使用readl()
/writel()
来处理这些地址,但这里的破坏更微妙(。
看起来访问该驱动程序中ahci_cmd_hdr
的正确方法是:
struct ahci_port_priv *pp = ap->private_data;
cmd_hdr = pp->cmd_slot;