4.3. Ethernet: our first PCI device

Our board uses an Intel ethernet chip, called i82559er, which has a module called eepro100. After compiling the module and booting, we discovered that the module isn't working, although an ethernet device was found. We guessed that it was an irq problem, and that the devices don't get the IRQs they need. We modified a function called pmppc_map_irq() to map our ethernet devices:

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;
}
The function maps IRQs according to IDselects, which means in the order on the PCI bus by which the devices are set. This structure is a bit tricky: min_idsel denotes the topleft corner of the array, and max_idsel is the bottomleft corner. irqs_per_slot is the number of IRQs per line. The structure is as follows:

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) |
		+----------------------------------------+
As you can see, our i8559er needs IRQ 22, and is seated in IDselect 3. Of course, we didn't know that at the start, so we wrote a small piece of code that read all the vendor IDs in all the IDselects. Once done we compiled, but the ethernet device still didn't work.

The next problem was that the module couldn't decide on a MAC address for the device. The MAC address should be written on an EEPROM chip (connected to the device), but we discovered that the hardware guys decided that i82559 doesn't need the EEPROM, so they removed it. After hardcoding a MAC address inside eepro100.c, the ethernet device finally worked. The final solution was to make the module read the MAC address from NVRAM memory, and if no other choice was available, to fall back to a default MAC address.

Note

The next step was to mount a NFS root filesystem. For details see the documentation in Documentation/nfsroot.txt