RTL8139: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
Information on packet transmission.
m Bot: Replace deprecated source tag with syntaxhighlight
 
(4 intermediate revisions by 3 users not shown)
Line 53:
this should essentially *power on* the device.
 
<sourcesyntaxhighlight lang="c">
outportb( ioaddr + 0x52, 0x0);
</syntaxhighlight>
</source>
 
==== Software Reset! ====
Line 71:
initialization procedure.
 
<sourcesyntaxhighlight lang="c">
outportb( ioaddr + 0x37, 0x10);
while( (inb(ioaddr + 0x37) & 0x10) != 0) { }
</syntaxhighlight>
</source>
 
==== Init Receive buffer ====
Line 82:
that variables memory location to the RBSTART register (0x30).
 
<sourcesyntaxhighlight lang="c">
//ioaddr is obtained from PCI configuration
outportd(ioaddr + 0x30, (uintptr_t)rx_buffer); // send uint32_t memory location to RBSTART (0x30)
</syntaxhighlight>
</source>
 
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.
Line 100:
a TOK or ROK IRQ happens, it actually will go through and fire up an IRQ.
 
<sourcesyntaxhighlight lang="c">
outportw(ioaddr + 0x3C, 0x0005); // Sets the TOK and ROK bits high
</syntaxhighlight>
</source>
 
=== Configuring receive buffer (RCR) ===
Line 122:
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.
 
<sourcesyntaxhighlight lang="c">
outportl(ioaddr + 0x44, 0xf | (1 << 7)); // (1 << 7) is the WRAP bit, 0xf is AB+AM+APM+AAP
</syntaxhighlight>
</source>
 
=== Enable Receive and Transmitter ===
Line 138:
Once this is completed, then the card will start allowing packets in and/or out.
 
<sourcesyntaxhighlight lang="c">
outportb(ioaddr + 0x37, 0x0C); // Sets the RE and TE bits high
</syntaxhighlight>
</source>
 
=== Transmitting Packets ===
Line 167:
 
== ISR Handler ==
When you handle an interrupt, you ''have'' to write the bit corresponding to the interrupt to reset it. The docdatasheet 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.
 
'''Note that it is important you write to this register ''before you read any packets from your buffers'', or the write to the register will have no effect, and any other packets than the first will not be delivered to your ISR.'''
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.
 
For example, this is tested and works on QEmu:
<source lang="c">
 
outportw(ioaddr + 0x3E, 0x1); // Interrupt Status - Clears the Rx OK bit, acknowledging a packet has been received,
<sourcesyntaxhighlight lang="c">
// and is now in rx_buffer
void rtl8139_handler(uint8_t isr, uint64_t error, uint64_t irq) {
</source>
uint16_t status = inw(io_base + 0x3e);
outw(io_base + 0x3E, 0x05);
if(status & TOK) {
// Sent
}
if (status & ROK) {
// Received
receive_packet();
}
}
</syntaxhighlight>
 
== Related Articles ==