0% found this document useful (0 votes)
28 views5 pages

RTL8139 - OSDev Wiki

Rtl8139 documents

Uploaded by

Ashwathy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
28 views5 pages

RTL8139 - OSDev Wiki

Rtl8139 documents

Uploaded by

Ashwathy
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

9/3/14 RTL8139 - OSDev Wiki

RTL8139
From OSDev Wiki

This page is a work in progress and may thus be incomplete. Its content may be changed in the near

future.

The RTL8139 Network Chip is used on many old and budget Ethernet Network Devices. It supports 10 and
100 MBit.

While the original chip lacks the features of newer Gigabit devices, it is a commonly emulated device in
virtualization environments, due to its simplicity (fewer IO operations means faster traps to the Hypervisor), and
extensive OS support.

It also makes a for a simple driver (and so is an excellent first choice for OS development hobbyists).

NB If you find your driver suddenly


freezes and stops receiving interrupts
and you're using kvm/qemu. Try the
option ­no­kvm­irqchip

Contents
1 Overview
1.1 Registers
2 Programming Guide
2.1 PCI Bus Mastering
2.2 Turning on the
RTL8139
2.2.1 Software A PCI RTL8139
Reset!
2.2.2 Init
Receive buffer
2.3 Set IMR + ISR
2.4 Configuring receive
buffer (RCR)
2.5 Enable Receive
and Transmitter
3 ISR Handler

wiki.osdev.org/RTL8139 1/5
9/3/14 RTL8139 - OSDev Wiki

4 Related Articles
5 External Links

Overview
RTL8139 is configured via registers. The IO base address and the IRQ number for the device is taken from
PCI configuration.

Registers

These are the registers used for using RTL8139.

Offset (from IO base) Size Name


0x00 6 MAC0­5
0x08 8 MAR0­7
0x30 4 RBSTART
0x37 1 CMD
0x3C 2 IMR
0x3E 2 ISR

Programming Guide
PCI Bus Mastering

First, you need to enable PCI Bus Mastering for this device. This allows the NIC to perform DMA. To do it,
you can read the Command Register from the device's PCI Configuration Space, set bit 2 (bus mastering bit)
and write the modified Command Register. Note this Command Register is that of the PCI Configuration Space
and has nothing to do with the Command Register that will be evoked in the following sections: the latter is
specific to the RTL8139, whereas every PCI device (not only NICs) have a PCI Configuration Space with a
Command Register.

Some BIOS may enable Bus Mastering at startup, but some versions of qemu don't. You should thus be careful
about this step.

Turning on the RTL8139

Send 0x00 to the CONFIG_1 register (0x52) to set the LWAKE + LWPTN to active high. this should
essentially *power on* the device.

outportb( ioaddr + 0x52, 0x0);

wiki.osdev.org/RTL8139 2/5
9/3/14 RTL8139 - OSDev Wiki

Software Reset!

Next, we should do a software reset to clear the RX and TX buffers and set everything back to defaults. Do this
to eliminate the possibility of there still being garbage left in the buffers or registers on power on.

Sending 0x10 to the Command register (0x37) will send the RTL8139 into a software reset. Once that byte is
sent, the RST bit must be checked to make sure that the chip has finished the reset. If the RST bit is high (1),
then the reset is still in operation.

NB: There is a minor bug in Qemu. If you check the command register before performing a soft reset, you may
find the RST bit is high (1). Just ignore it and carry on with the initialization procedure.

outportb( ioaddr + 0x37, 0x10);


while( (inb(ioaddr + 0x37) & 0x10) != 0) { }

Init Receive buffer

For this part, we will send the chip a memory location to use as its receive buffer start location. One way to do
it, would be to define a buffer variable and send that variables memory location to the RBSTART register
(0x30).

//ioaddr is obtained from PCI configuration


outportd(ioaddr + 0x30, (uintptr_t)rx_buffer); // send dword memory l

Note that 'rx_buffer' needs to be a pointer to a physical address. In this case a size of 8192 + 16 (8K + 16
bytes) is recommended, see below.

Set IMR + ISR

The Interrupt Mask Register (IMR) and Interrupt Service Register (ISR) are responsible for firing up different
IRQs. The IMR bits line up with the ISR bits to work in sync. If an IMR bit is low, then the corresponding ISR
bit with never fire an IRQ when the time comes for it to happen. The IMR is located at 0x3C and the ISR is
located at 0x3E.

To set the RTL8139 to accept only the Transmit OK (TOK) and Receive OK (ROK) interrupts, we would
have the TOK and ROK bits of the IMR high and leave the rest low. That way when a TOK or ROK IRQ
happens, it actually will go through and fire up an IRQ.

outportw(ioaddr + 0x3C, 0x0005); // Sets the TOK and ROK bits high

Configuring receive buffer (RCR)

wiki.osdev.org/RTL8139 3/5
9/3/14 RTL8139 - OSDev Wiki

Before hoping to see a packet coming to you, you should tell the RTL8139 to accept packets based on various
rules. The configuration register is RCR.

You can enable different "matching" rules:

AB ­ Accept Broadcast: Accept broadcast packets sent to mac ff:ff:ff:ff:ff:ff


AM ­ Accept Multicast: Accept multicast packets.
APM ­ Accept Physical Match: Accept packets send to NIC's MAC address.
AAP ­ Accept All Packets. Accept all packets (run in promiscuous mode).

Another bit, the WRAP bit, controls the handling of receive buffer wrap around.

If WRAP is 0, the Rx buffer is treated as a traditional ring buffer: if a packet is being written near the end of the
buffer and the RTL8139 knows you've already handled data before this (thanks to CAPR), the packet will
continue at the beginning of the buffer.

If WRAP is 1, the remainder of the packet will be written contiguously (overflowing the actual receive buffer) so
that it can be handled more efficiently. This means the buffer must be an additional 1500 bytes (to hold the
largest potentially overflowing packet).

You can also tell the size of your RX buffer here, however if you use a 8k + 16 buffer as described before,
writing zeroes is enough. To use the WRAP=1 bit, an 8K buffer must in fact be 8k+16+1500 bytes.

outportl(ioaddr + 0x44, 0xf | (1 << 7)); // (1 << 7) is the WRAP bit,

Enable Receive and Transmitter

Now is the time to start up the RX and TX functions. This is quite an easy piece, and should (in my opinion)
only be done after all of the configurations to the RTL8139's registers have been set to what is desired. The RE
(Receiver Enabled) and the TE (Transmitter Enabled) bits are located in the Command Register (0x37). Starting
up the RE and TE is pretty straight­forward, but lets go through it anyways.

To enable the RTL8139 to accept and transmit packets, the RE and TE bits must go high. Once this is
completed, then the card will start allowing packets in and/or out.

outportb(ioaddr + 0x37, 0x0C); // Sets the RE and TE bits high

ISR Handler
When you handle an interrupt, you have to write the bit corresponding to the interrupt to reset it. The doc says
reading the register is enough to reset the buffer to zero and writing has no effect. This is not the case on
QEMU, and probably on some/most hardware too. Writing a bit when it has no effect will probably not hurt.

01000101: Confirmed. In fact, the only way to clear an interrupt is by writing to it. The datasheet says that
reading is what you must do, but it is completely wrong.

wiki.osdev.org/RTL8139 4/5
9/3/14 RTL8139 - OSDev Wiki

outportw(ioaddr + 0x3E, 0x1); // Interrupt Status - Clears the Rx OK


// and is now in rx_buffer

Related Articles
RTL8169 Successor Chipset

External Links
http://www.magnesium.net/~wpaul/rt/spec­8139cp(150).pdf, Datasheet for the RTL8139C
http://www.cs.usfca.edu/~cruse/cs326f04/RTL8139D_DataSheet.pdf, Datasheet for the RTL8139D,
has more information
http://www.cs.usfca.edu/~cruse/cs326f04/RTL8139_ProgrammersGuide.pdf, Programming guide for the
RTL8139
http://www.jbox.dk/sanos/source/sys/dev/rtl8139.c.html, Example Driver implementation (GPL
Licensed)

Retrieved from "http://wiki.osdev.org/index.php?title=RTL8139&oldid=16434"


Categories: In Progress Network Hardware Standards

This page was last modified on 2 June 2014, at 09:36.


This page has been accessed 52,084 times.

wiki.osdev.org/RTL8139 5/5

You might also like