In yesterdays weekly meeting we decided to split the driver into several .c files. I started splitting the driver into tg3_hw.c which contains all the low-level NIC hardware access functions, and tg3_main.c which contains all the code that directly interacts with gPXE(e.g. tg3_open, tg3_transmit, etc).
I also added all the PCI IDs from the linux driver to the gPXE driver. This was done by adding a macro definition to the linux driver:
#define str(s) rem#s
#undef PCI_DEVICE
#define PCI_DEVICE(vendor, device) ( PCI_ROM(vendor, device, str(vendor)str(device), str(vendor)str(device), 0) )
and compiling the code with gcc -E, which only runs the C preprocessor. Use find and replace to get it into a more polished form.
Today I added the code to initialize tp→dma_rwctrl. For now I also disabled the code to allocate resources needed for packet reception, as we don't have any other code for receiving packets for now. I tried to send some packets but failed. I noticed that gPXE didn't detect the correct link state and the other machine of the link negotiated to 10MBit/s half duplex while 1000MBit/s full duplex would be possible. To debug the issue I moved all the PHY functions to a new file, tg3_phy.c. After some fixes the other machine was able to detect the link speed correctly, but gPXE still detected the link as down.
I tried to track down the link detection issue in the driver but didn't have much luck today.
More time was spent to find the link detection issue. Normally we would receive a link-changed indication from the NIC and call tg3_setup_phy() to start the autonegotiation, and call tg3_setup_phy() again after autoneg is finished to read the current link state and speed from the card. As the card wasn't signaling any link changes I modified the code to call tg3_setup_phy() on every tg3_poll() call. After Stefan suggested a few things on IRC(thanks!) I realized that we were restarting the autoneg process on every call to tg3_setup_phy(). As the link needs several seconds to come up we never gave the autonegotiation enough time to finish. After I added a delay between two consecutive tg3_setup_phy() calls the link came up as expected. Turns out the autonegotiation code was working the whole time, we just didn't give it enough time to finish.
After the autoneg issue was resolved yesterday I tried to find out why the card wasn't signaling any link changes to us. While we could always poll for link changes without having received a notification from the card we still should find out why we aren't seeing any notifications. This information comes from the tg3 hardware status block which also contains informations about packet transmit completions and other important things, so this needs to be resolved anyway. Unfortunately I haven't had much time and luck today and haven't found the issue yet.