一、pci_read_config_讲解
这些函数是Linux内核中用于从PCI设备的配置空间读取信息的函数。配置空间是PCI设备的一小块内存,它存储了关于该设备的重要信息,例如设备ID、供应商ID、中断设置等。
pci_read_config_byte、`pci_read_config_word`、`pci_read_config_dword`函数可以分别读取1个字节、2个字节和4个字节的数据。这些函数是根据读取数据的长度划分的,分别对应8位、16位和32位的读取请求。以下是函数的详细中文解释:
1. pci_read_config_byte:该函数用于从PCI设备的配置空间中读取一个字节(8位)的数据。
- 参数`const struct pci_dev *dev`:指向代表要访问的PCI设备的`pci_dev`结构的指针。
- 参数`int where`:指定从哪个偏移地址开始读取数据。
- 参数`u8 *val`:用来存放读取到的数据的字节指针。
2. pci_read_config_word:该函数用于从PCI设备的配置空间中读取一个字(16位)的数据。
- 参数类似于`pci_read_config_byte`,但是`u16 *val`用于存放读取到的两个字节的数据。
3. pci_read_config_dword:该函数用于从PCI设备的配置空间中读取一个双字(32位)的数据。
- 参数类似于前两个函数,但是`u32 *val`用于存放读取到的四个字节的数据。
在每个函数内部,首先调用了`pci_dev_is_disconnected`来检查对应的PCI设备是否已经断开连接。如果设备已断开连接,函数会将参数`val`的值设置为全1(0xFF、0xFFFF或0xFFFFFFFF),并返回一个错误码`PCIBIOS_DEVICE_NOT_FOUND`。
如果设备连接正常,函数会通过调用`pci_bus_read_config_byte`、`pci_bus_read_config_word`或`pci_bus_read_config_dword`来实际完成数据的读取操作。这些函数将会读取指定的PCI总线上的配置空间数据。
最后,`EXPORT_SYMBOL`宏用于导出符号,使得这些函数可以被模块之外的其他模块使用。这是Linux内核模块间通信的常用方法之一。
二、pci_write_config_讲解
这段代码展示了在Linux内核中,如何通过PCI(Peripheral Component Interconnect)总线接口来写入PCI设备的配置空间。每段代码中包括一个函数,用于把一个字节(u8), 两个字节(u16), 或者四个字节(u32)的值写入到指定的配置寄存器中。
这里是每个函数的中文讲解:
1. pci_write_config_byte函数:
- 功能:将一个字节值(val)写入一个PCI设备的配置空间的特定位置(where)。
- 参数:
- const struct pci_dev *dev:指向需要操作的PCI设备的指针。
- int where:要写入数据的配置空间的偏移地址。
- u8 val:要写入的数据的字节值。
- 返回值:如果设备没有连接,则返回一个错误代码`PCIBIOS_DEVICE_NOT_FOUND`。如果写入操作成功执行,则返回`0`。
2. pci_write_config_word函数:
- 功能:与`pci_write_config_byte`类似,但是这个函数写入的是两个字节(16位)的数据。
- 参数与`pci_write_config_byte`相同,不过`u16 val`替代了`u8 val`。
- 返回值与`pci_write_config_byte`相同。
3. pci_write_config_dword函数:
- 功能:与`pci_write_config_byte`类似,但是这个函数写入的是四个字节(32位)的数据。
- 参数与`pci_write_config_byte`相同,不过`u32 val`替代了`u8 val`。
- 返回值与`pci_write_config_byte`相同。
在每个函数里,首先会检查传入的PCI设备是否处于断开状态(`pci_dev_is_disconnected(dev)`)。如果设备已经断开,则函数会返回一个错误码`PCIBIOS_DEVICE_NOT_FOUND`。如果设备处于连接状态,它会调用相应的`pci_bus_write_config_*`函数以写入数据至设备的配置空间。
每个函数的最后一行`EXPORT_SYMBOL()`是一个宏,用于导出这些函数的符号,使得其他的内核模块可以在运行时使用这些函数。
三、中文注释
// 读取PCI配置空间的一个字节
int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
{// 如果PCI设备已断开连接,则设置val为全1,并返回设备未找到的错误if (pci_dev_is_disconnected(dev)) {*val = ~0;return PCIBIOS_DEVICE_NOT_FOUND;}// 使用pci_bus_read_config_byte函数从PCI总线读取配置return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_read_config_byte);// 读取PCI配置空间的一个字
int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
{// 如果PCI设备断开连接,则设置val为全1,并返回设备未找到的错误if (pci_dev_is_disconnected(dev)) {*val = ~0;return PCIBIOS_DEVICE_NOT_FOUND;}// 使用pci_bus_read_config_word函数从PCI总线读取配置return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_read_config_word);// 读取PCI配置空间的一个双字
int pci_read_config_dword(const struct pci_dev *dev, int where, u32 *val)
{// 如果PCI设备断开连接,则设置val为全1,并返回设备未找到的错误if (pci_dev_is_disconnected(dev)) {*val = ~0;return PCIBIOS_DEVICE_NOT_FOUND;}// 使用pci_bus_read_config_dword函数从PCI总线读取配置return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_read_config_dword);// 往PCI配置空间写入一个字节
int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
{// 如果PCI设备断开连接,返回设备未找到的错误if (pci_dev_is_disconnected(dev))return PCIBIOS_DEVICE_NOT_FOUND;// 使用pci_bus_write_config_byte函数向PCI总线写入配置return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_write_config_byte);// 往PCI配置空间写入一个字
int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
{// 如果PCI设备断开连接,返回设备未找到的错误if (pci_dev_is_disconnected(dev))return PCIBIOS_DEVICE_NOT_FOUND;// 使用pci_bus_write_config_word函数向PCI总线写入配置return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_write_config_word);// 往PCI配置空间写入一个双字
int pci_write_config_dword(const struct pci_dev *dev, int where, u32 val)
{// 如果PCI设备断开连接,返回设备未找到的错误if (pci_dev_is_disconnected(dev))return PCIBIOS_DEVICE_NOT_FOUND;// 使用pci_bus_write_config_dword函数向PCI总线写入配置return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
}
EXPORT_SYMBOL(pci_write_config_dword);
请注意,`EXPORT_SYMBOL`宏用于导出符号,这样其他内核模块就可以调用这些导出的函数。这些函数用于访问PCI设备的配置空间,通常包括设备的硬件设置和状态信息。如果设备已断开连接,它们会返回一个错误,并将输出值设置为特定的值(通常是全1,即`~0`)。这些函数在Linux内核的PCI支持中十分关键。
具体函数定义drivers\pci\access.c文件中,include\linux\pci.h中声明。