This is an old revision of the document!


Week 2 [ 31 May - 6 Jun 2010 ]

Day 1 [ 31 May 2010 ]

Git commit: 318ca039b7381e67e04f92447d9b2a211fe9541a

Today was about reorganizing parts of what I've written so far and taking some time to analyze things and try to see the big picture. Also, I did some debugging in the Linux driver (insert printks, make modules, make modules_install, modprobe -r pcnet32, modprobe pcnet32) and found out that even that one takes an unneeded branch at one point and tries to modify some registers that aren't available on older chips. Since the datasheets say that accessing inexistent registers might summon some nasty demons, I avoided this in my code. It could be that those accesses do some undocumented stuff, but for now I'll keep this in mind and see how things turn out when the driver is all done.

Other than that, I'm all set up for tackling the transmit and receive parts, which I'll start tomorrow.

Day 2 [ 1 Jun 2010 ]

Git commit: 04d57225b1c06fa6c37f7565ed9b2977580a29e0

As I suspected, the transmit and receive were easier than the NIC's setup. I managed to implement both of them today, following the r8169 driver source code.

Transmit works by first giving you an struct io_buffer. It is the transmit routine's responsibility to fill the current available descriptor's fields with the iobuf's parameters (length, start address). Then you have to change the descriptor's ownership to 1 to signal that it now contains valid information and the NIC should send the data that it describes. After this, the routine forces the NIC to send any new valid descriptors by setting the TDMD (Transmit Demand) bit. I suppose it works without this setting since the datasheet mentions that there is a poll-time counter that eventually elapses. In the end, all you have to do is make sure that the circular descriptor buffer is handled, by advancing the cursor and increasing the number of descriptors in use.

The .poll routine has to check first if there are any new received frames or if some frames have finished being transmitted by the NIC.

  • The transmitted frames now have the OWN bit from the descriptor set to 0 thus signalling that the NIC is done with their processing. To cleanup the buffer, it uses the netdev_tx_complete() routine, resets the descriptor, advances the tail of the circular buffer and decreases the total used descriptor count.
  • The received packets have a similar fate. One of the differences is the fact that you have to see if there weren't any errors in the frame's receival such as a CRC, framing or overflow errors. If there is such an error, the frame is discarded using netdev_rx_err. If there was no error first use iob_put to adjust the iobuffer's length if required and finally send the frame to the upper layers using netdev_rx. Since the buffer is out of our hands now the driver is free to remove any references it might have had to it and clear the descriptor, plus advance the cursor. As a result, the driver has to allocate new buffers for all the descriptors that were valid and which got their frames sent to the upper layers. This is the final thing the driver has to do.

After all this was done, I tested the driver on my VMWare setup, and after fixing some bugs I managed to get it working. In the end, I've booted a DSL using my driver :) Yay.

In the next few days I'll spend some time cleaning up the code and rearranging stuff.

Day 3 [ 2 Jun 2010 ]

me.rest()

Day 4 [ 3 Jun 2010 ]

Git commit: 5dbf33bdc89da087fe86f4a20973b648c6372837

Back to work! Reorganized some bits of the code, some comments, etc. I have some doubts regarding the way the code handles full-duplex negotiation and multiple PHYs and most likely my driver does not handle these issues correctly ATM. I'll post the driver up for some reviews, see what people think.

Tomorrow I'll try and setup QEmu and VirtualBox environments, to test the driver there too.

Day 5 [ 4 Jun 2010 ]

Git commit: These are not the commits you are looking for :waves hand:

Today didn't yield much in terms of code but I did manage to do some testing. First I set up QEmu and ran this small test:

qemu -net nic,model=pcnet -net user -bootp http://vmsplice.net/tinycore.gpxe -option-rom bin/pcnet32.rom

It worked, no problems there.

After that, I started setting up VirtualBox. I ran into some problems because of the already inserted kvm module, which I had to remove, after which VirtualBox worked. Since I didn't have a -bootp option like QEmu and I wanted to play with the gPXE command line, I used that one to do the exact test that I did in qemu.

ifopen net0
dhcp net0
imgfetch http://vmsplice.net/tinycore.gpxe
imgload tinycore.gpxe
imgrun tinycore.gpxe

This worked on both of the pcnet NICs that VirtualBox emulates.

I started coding after that, when I realized that I forgot about the patches regarding the MAC address checking routines (is_valid_ether_addr & friends). Did two small patches and emailed them. If those get accepted I can easily finish the address checking in my pcnet32 driver.

Unfortunately, I didn't get to go through the feedback on the driver or start working on the link state code. Slow day :(


QR Code
QR Code soc:2010:andreif:journal:week2 (generated for current page)