4.3. 以太网:我们的第一个 PCI 设备

我们的板卡使用英特尔以太网芯片 i82559er,它有一个名为 eepro100 的模块。编译模块并启动后,我们发现该模块无法工作,尽管找到了以太网设备。我们猜测这是一个 IRQ 问题,设备没有获得它们需要的 IRQ。我们修改了一个名为以下的函数pmppc_map_irq()来映射我们的以太网设备
XXXX_map_irq(struct pci_dev *dev, unsigned char idsel, unsigned char pin) {
	static char pci_irq_table[][4] =
	/*
	 *      PCI IDSEL/INTPIN->INTLINE
	 *      A       B       C       D
	 */
	{
		{22,    0,      0,      0},/* IDSEL 3 - Ethernet */
		{0,     0,      0,      0},/* IDSEL 4 - unused   */
		{0,     0,      0,      0},/* IDSEL 5 - unused   */
		{0,     0,      0,      0},/* IDSEL 6 - ????     */
		{0,     0,      0,      0},/* IDSEL 7 - unused   */
		{0,     0,      0,      0},/* IDSEL 8 - unused   */
		{0,     0,      0,      0},/* IDSEL 9 - unused   */
	};

	const long min_idsel = 3, max_idsel = 9, irqs_per_slot = 4;
	return PCI_IRQ_TABLE_LOOKUP;
}
该函数根据 IDselects 映射 IRQ,这意味着按照设备在 PCI 总线上的设置顺序。这个结构有点棘手:min_idsel 表示数组的左上角,而 max_idsel 是左下角。irqs_per_slot 是每行的 IRQ 数量。结构如下
each cell contains (IDSEL, SLOT#, IRQ)
		+----------------------------------------+
		| (3,0,22) | (3,1,0) | (3,2,0) | (3,3,0) |
		+----------------------------------------+
		| (4,0,0)  | (4,1,0) | (4,2,0) | (4,3,0) |
		+----------------------------------------+
							..........
							..........
		+----------------------------------------+
		| (9,0,0)  | (9,1,0) | (9,2,0) | (9,3,0) |
		+----------------------------------------+
正如您所看到的,我们的 i8559er 需要 IRQ 22,并且位于 IDselect 3 中。当然,我们一开始并不知道这一点,所以我们编写了一小段代码来读取所有 IDselect 中的所有供应商 ID。完成后我们进行了编译,但以太网设备仍然无法工作。

下一个问题是模块无法为设备确定 MAC 地址。MAC 地址应该写入 EEPROM 芯片(连接到设备),但我们发现硬件工程师决定 i82559 不需要 EEPROM,因此他们将其移除。在内部硬编码 MAC 地址后eepro100.c,以太网设备终于工作了。最终的解决方案是使模块从 NVRAM 内存中读取 MAC 地址,如果没有其他选择,则回退到默认 MAC 地址。

Note

下一步是挂载 NFS 根文件系统。有关详细信息,请参阅 Documentation/nfsroot.txt 中的文档