7

我试图了解一些用 C 语言编写的用于 USB Wi-Fi 适配器的 Linux 内核驱动程序代码。1456文件中的行/drivers/net/wireless/rtl818x/rtl8187/dev.c(以防万一有人想参考内核代码的上下文)读取:

    priv->map = (struct rtl818x_csr *)0xFF00;

我很好奇正确的操作数在这里做什么 - (struct rtl818x_csr *)0xFF00;。我一直将其解释为“将内存地址0xFF00转换为类型rtl818x_csr,然后将其分配给priv->map”。如果我的解释是正确的,那么内存地址有什么特别之处,0xFF00以至于驱动程序可以可靠地判断它所追求的东西总是在这个地址上?我很好奇的另一件事是 0xFF00 只有 16 位。如果它正在投射内存地址,我会期待 32/64 位。

谁能澄清这行代码中发生了什么?我想我对 C 语法的理解存在缺陷。

4

3 回答 3

2

0xFF00 is an address in the IO address space of the system. If you look in the code, the address is never directly dereferenced but accessed through IO functions.

For example, in the call

rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD,
                 RTL818X_EEPROM_CMD_CONFIG);

which then calls Linux kernel low level IO functions.

The address is cast to a pointer to a struct to give access to offsets from the adress, example here:

0xFF00 + offsetof(struct rtl818x_csr, EEPROM_CMD)

Note that in the rtl818x_iowrite8 call above, no dereference occurs when passing the &priv->map->EEPROM_CMD argument because of the & operator, only the address + offset is computed. The dereference is further achieved withtin the internal low level functions called inside rtl818x_iowrite8.

于 2012-08-01T10:10:18.827 回答
2

您必须从设备的角度考虑这一点。

从为 rtl8187 设备映射的地址空间内的地址 0xFF00 开始是一个内存范围,该内存范围保存的信息结构与此处定义的 rtl818x_csr 结构相同。

因此,在逻辑映射该区域后,您可以开始对其进行总线读取和写入以控制设备。就像这里一样(不得不再删掉两个超链接,因为我没有发布超过 3 个的必要声誉,但你明白了)。这些只是几个例子。如果您阅读整个文件,您会发现读写操作随处可见。

为了理解为什么该结构看起来那样以及为什么使用 0xFF00 而不是 0xBEEF 或 0xDEAD,您必须查阅该设备的数据表。

因此,如果您想开始查看内核代码,特别是设备驱动程序,您需要的不仅仅是代码。您还需要数据表或规格。这可能很难找到(请参阅从供应商处征求开放文档的大量电子邮件线程和文章)。

无论如何,我希望我回答了你的问题。快乐黑客!

于 2012-08-01T10:15:11.443 回答
2

将绝对地址转换为指向结构的指针是驱动程序中将设备的(内存映射)寄存器作为普通 C 结构访问的常用方法。

使用0xff00有效,因为 C 不做数字的符号扩展。

于 2012-08-01T10:00:03.540 回答