Writing driver for my ethernet card

211 views
Skip to first unread message

Saurabh Rawat

unread,
Mar 27, 2012, 8:31:39 AM3/27/12
to bareme...@googlegroups.com
Hi,

I am thinking of writing a driver for my ethernet card for baremetal OS, as I think I will learn many things about OSs, drivers and interrupts and all sorts of things along the way. From what I understand in order to talk to the card I will have to boot baremetal on bare metal and not virtualized. Now the problem is the card is on my laptop which I use as my primary workstation. Is there any way I can mitigate this problem. 

Also I am a total noob in driver development, I don't know first thing about it. Although I am pretty confident about coding in assembly. Can someone point me to the right direction ? I have already downloaded datasheet for the ethernet card. But all the tutorials I find are about writing drivers for well established OSs like linux. I know in baremetal I won't get much utilities from the OS. Please guide me on how to go about it.

I hope to pester you more in the future asking questions if I somehow get started on writing this driver :)

Thanks for your time, I appreciate it.

Regards,

Saurabh Rawat 

Ian Seyler

unread,
Mar 28, 2012, 9:14:47 AM3/28/12
to bareme...@googlegroups.com
You would need to be able to test it on real hardware (unless one of the VM environments out there can emulate it). This would mean compiling your code and then booting it up on the laptop. This could be done via a USB thumb/portable drive.

I wrote the drivers for the Intel 8254x and Realtek 816x/811x Gigabit families. It wasn't an easy task but the documentation from the manufacturers was very good. Also you can take a look at the existing Ethernet drivers to see what is usually required.

What Ethernet chipset is in your laptop?

Best regards,
Ian

Saurabh Rawat

unread,
Mar 28, 2012, 9:36:15 AM3/28/12
to bareme...@googlegroups.com
Hi,

Thanks for your timely response. I have an "Intel Corporation 82579LM Gigabit Network Connection (rev 04)" ethernet controller. I have downloaded the datasheet but its really really big. From skimming it I understood there are various registers, a LOT of them, and we flip bits to make it do some things. There were default values for most of those and I think the card is initialized by the firmware to have that configuration ( am I wrong ? ). But your driver seems so simple. From what I understand the card is already accessible for memory mapped I/O. I am not getting how the OS is getting the PCI address of the card and how all the IRQs are set. Also all the communication is happening through this memory mapped "os_NetIOBaseMem". How did the OS get this mapping working ? Then you have addresses for all the registers, which I think I can find somewhere in the manual, which you are then offsetting from "os_NetIOBaseMem" to get to different registers.

It all looks so simple, but I don't have any clue about how its all working. Any guidance is highly appreciated. I thank you for taking the time to respond to my queries.

Regards,

Saurabh Rawat 

Ian Seyler

unread,
Mar 28, 2012, 10:42:31 AM3/28/12
to bareme...@googlegroups.com
Hello,

You may be able to use the existing i8254x driver as a template then as Intel usually keeps the API pretty similar.

The first thing the OS does is in init_net.asm and that is to find a supported PCI device. It does this by looking at the DeviceVendor ID. So you will want to figure out what your card uses. You can see the existing supported ID's in drivers.asm

Once we find a supported device we can get its base IO address from the PCI BAR's. Take a look at os_net_i8254x_init in i8254x.asm to see how it gets the base IO.

I hope this helps!

-Ian

Saurabh Rawat

unread,
Mar 28, 2012, 1:35:14 PM3/28/12
to bareme...@googlegroups.com
Hi,

I am asking a lot of questions, so please bear with me.

When we call os_pci_read_reg, how are we getting the bl, cl registers filled with bus no and device no ?

Then we are reading register no 0x04 (what is it ?) and perform result AND 0xFFFFFFF0 to get base memory IO address. Then we initialize OS wide os_NetIOBaseMem pointer. It seems we are reading the MAC address and then populating OS wide os_NetMAC address byte by byte or if unsuccessful then reading it from EPROM. But how can we access it directly without first issuing any command (writing something to some pci register) ?

When we get the base memory IO os_NetIOBaseMem. Does this mean that starting from this address all the registers of the card are available mapped to increasing memory addresses ? If yes then how are you maintaining the boundary for them ?

When we read MAC from EPROM. We are writing some command bytes to some mapped memory addresses and then reading from them. Is this the way to talk in PCI communications ? And why are we not introducing any delays between writing command and reading response, is the device fast enough to respond when asked by a modern processor ?

I hope you won't mind me asking so many questions. Thanks.

Regards,

Saurabh Rawat

Ian Seyler

unread,
Mar 28, 2012, 8:31:55 PM3/28/12
to bareme...@googlegroups.com
The os_pci_find_device function returns the bus and device number if it was found.

PCI register 0x04 is BAR0 and according to the i8254x SDM that is the base IO address. The low four bits are ignored.

The MAC address is also in the memory address space but some different i8254x cards may not have it. In the case where it is not there then I attempt to read it from the EPROM.

Yes, the base IO address is where all of the registers can be accessed. I think there is a space to read how much memory space it uses.

I have not run into any issues where delays need to be added. The EPROM is a last measure as it should be in the registers.

-Ian

Saurabh Rawat

unread,
Mar 29, 2012, 1:53:00 PM3/29/12
to bareme...@googlegroups.com
Hi,

Thanks for replying.

I have found the list of offset addresses to access different registers of MAC. For receiving and transmitting there is one Head pointer and a Tail pointer. From what I understand we write these pointers to respective registers and set the boundaries in system memory from where the packet is to be read or written to. Then the MAC will automatically send/receive packets and generate interrupts, which we can handle. Am I getting it right ?

How do I set up interrupts for these events, is there any OS supported interrupt for packet Tx/Rx events ? Can you please point to some resources about drivers and interrupt handling in assembly in a general sense, because most of what I found on the internet was about Linux or big OSs.

What did you use to test the drivers you made ? It seems a really long cycle if I have to write something, compile it, make appropriate disk image and then burn it to a USB disk (I haven't tested if dding disk image to usb stick would work). Test it and then reboot again to make any changes. I have a single machine right now and an android phone (if it can help). Can you please suggest something better ? 

Thanks again for your time.

Regards,

Saurabh Rawat

Ian Seyler

unread,
Mar 29, 2012, 7:27:56 PM3/29/12
to bareme...@googlegroups.com
It sounds like this is VERY similar to the i8254x chipset. Take a further look at i8254x.asm to see how it was initialized and how packets were send/received. The interrupt line is in there too.

The network card will trigger the network interrupt whenever a packet is received or sent. It can also be set to trigger on cable disconnects and a few other things.

Unfortunately this is how testing goes with physical hardware (Unless something like VMware can emulate it). When I wrote the i8254x driver I did my testing under QEMU and VirtualBox since they both emulated it. When I wrote the rtl8169 driver it was all tested on physical hardware with me swapping a Compact Flash card around.

Follow along with the i8254x driver and make the changes that you think are required. Hopefully testing/debugging will be limited. If you run into problems I can take a look at the spec as well and we can collaborate on it.

-Ian


On Thursday, March 29, 2012 1:53:00 PM UTC-4, Saurabh Rawat wrote:
Hi,

Thanks for replying.

I have found the list of offset addresses to access different registers of MAC. For receiving and transmitting there is one Head pointer and a Tail pointer. From what I understand we write these pointers to respective registers and set the boundaries in system memory from where the packet is to be read or written to. Then the MAC will automatically send/receive packets and generate interrupts, which we can handle. Am I getting it right ?

How do I set up interrupts for these events, is there any OS supported interrupt for packet Tx/Rx events ? Can you please point to some resources about drivers and interrupt handling in assembly in a general sense, because most of what I found on the internet was about Linux or big OSs.

What did you use to test the drivers you made ? It seems a really long cycle if I have to write something, compile it, make appropriate disk image and then burn it to a USB disk (I haven't tested if dding disk image to usb stick would work). Test it and then reboot again to make any changes. I have a single machine right now and an android phone (if it can help). Can you please suggest something better ? 

Thanks again for your time.

Regards,

Saurabh Rawat

Saurabh Rawat

unread,
Apr 1, 2012, 7:54:27 AM4/1/12
to bareme...@googlegroups.com
Hi,

It turns out both the chipsets are having the exact same register sets. So I think there is no need for me to write anything :)
There are some things I didn't understand though. When you read MAC id from register 0x05400, why would it fail so you have to fall back to reading from NVM. As its written in the docs that the MAC id gets loaded in the NVM from the register itself. Also I didn't understand how the reads/writes in NVM were working and how we were setting up the IRQ. All in all a nice experience though, at least I am no more a stranger to these things now.

Thanks for your support. I think my next task would be to write a USB driver, I'll ask for your help again on that.

Regards,

Saurabh Rawat

Ian Seyler

unread,
Apr 1, 2012, 11:01:07 PM4/1/12
to bareme...@googlegroups.com
Hello,

I'll take a look at the SDM. Maybe I will be able to add the support for it. I seem to recall that some cards didn't have the MAC in the registers but I'll double-check.

A USB driver would be quite helpful.

-Ian


On Sunday, April 1, 2012 7:54:27 AM UTC-4, Saurabh Rawat wrote:
Hi,

It turns out both the chipsets are having the exact same register sets. So I think there is no need for me to write anything :)
There are some things I didn't understand though. When you read MAC id from register 0x05400, why would it fail so you have to fall back to reading from NVM. As its written in the docs that the MAC id gets loaded in the NVM from the register itself. Also I didn't understand how the reads/writes in NVM were working and how we were setting up the IRQ. All in all a nice experience though, at least I am no more a stranger to these things now.

Thanks for your support. I think my next task would be to write a USB driver, I'll ask for your help again on that.

Regards,

Saurabh Rawat
Reply all
Reply to author
Forward
0 new messages