RTL8169: Difference between revisions

[unchecked revision][unchecked revision]
Content deleted Content added
m Replace dead link →‎External Links
m Bot: Replace deprecated source tag with syntaxhighlight
 
(4 intermediate revisions by 4 users not shown)
Line 19:
 
ex:
<sourcesyntaxhighlight lang="c">
char i;
for (i = 0; i < 6; i++)
Line 25:
mac_address[i] = inportb(ioaddr + i); /*ioaddr is the base address obtainable from the PCI device configuration space.*/
}
</syntaxhighlight>
</source>
 
=== Reset the Chip ===
Line 32:
 
ex:
<sourcesyntaxhighlight lang="c">
outportb(ioaddr + 0x37, 0x10); /*set the Reset bit (0x10) to the Command Register (0x37)*/
while(inportb(ioaddr + 0x37) & 0x10)
;/*setting a timeout could be useful if the card is problematic*/
</syntaxhighlight>
</source>
 
== Setting up the Rx Descriptors ==
Line 44:
Rx Descriptors are used to tell the NIC where to put packets once received. Because this is an asynchronous operation, we must setup the descriptors before we enable the reception of packets so that the NIC knows where to put things. A major function of descriptors is to tell the NIC which descriptors are owned by the OS (host) and which ones are owned by the NIC. If the descriptor is owned by the NIC, the NIC can then read it and use it for the next packet it receives, if not, it either skips over it or sends a RDU (Rx Descriptor Unavailable) interrupt and halts all further Rx operations. Because there can be multiple descriptors used, there is also a EOR (End of Rx descriptor Ring) bit used when the NIC has reached the end of the descriptors and needs to loop back to the beginning of the descriptors. There is one more big 'gotcha' with all of this, the beginning of the descriptor arrays must be aligned on a 256-byte boundary.
 
====Descriptor format====
eg:
{| {{wikitable}}
<source lang="c">
! Offset
! Name
! Description
|-
| dword 0 || Flags || 31 bit=OWN (if set, card own this descriptor) 30 bit=EOR (last descriptor in list)
|-
| dword 1 || VLAN || Unused
|-
| dword 2 || Pointer to buffer low 32 bits ||
|-
| dword 3 || Pointer to buffer high 32 bits ||
|-
|}
 
====Code example====
<sourcesyntaxhighlight lang="c">
struct Descriptor {
uint32_t command; /* command/status uint32_t */
Line 71 ⟶ 87:
}
}
</syntaxhighlight>
</source>
 
== Configuring RxConfig and TxConfig ==
Line 81 ⟶ 97:
 
eg:
<sourcesyntaxhighlight lang="c">
outportl(ioaddr + 0x40, 0x03000700); /* IFG: normal, MXDMA: unlimited */
</syntaxhighlight>
</source>
 
=== RxConfig ===
Line 89 ⟶ 105:
 
eg:
<sourcesyntaxhighlight lang="c">
outportl(ioaddr + 0x44, 0x0000E70F) /* RXFTH: unlimited, MXDMA: unlimited, AAP: set (promisc. mode set) */
</syntaxhighlight>
</source>
== Max Packet Sizes ==
=== Max Transmit Packet Size ===
Line 97 ⟶ 113:
 
eg:
<sourcesyntaxhighlight lang="c">
outportb(ioaddr + 0xEC, 0x3B); /* Maximum tx packet size */
</syntaxhighlight>
</source>
=== Receive Packet Maximum Size ===
The RMS register is located at offset 0xDA and is used for setting the maximum packet size that can be received into the NIC. If set to zero, the NIC will accept no packets (must be set prior to normal operation!). The maximum size that can be set is 0x3FFF (16k - 1), but if a packet larger than 8k is received error bits are set and a lengthier process must be started in order to determine if the packet is actually good or not. I keep this value to 0x1FFF (8k - 1) as it is rare to receive such large packets and it also ensures that error packets are actually error packets and not false positives.
 
eg:
<sourcesyntaxhighlight lang="c">
outportw(ioaddr + 0xDA, 0x1FFF); /* Maximum rx packet size */
</syntaxhighlight>
</source>
== Full Reset Example ==
This is a barebones example of how to reset the RTL8169 without anything like auto-negotiation (explained later) or (G)MII interactions.
 
eg:
<sourcesyntaxhighlight lang="c">
struct Descriptor
{
Line 179 ⟶ 195:
outportb(ioaddr + 0x50, 0x00); /* Lock config registers */
}
</syntaxhighlight>
</source>
 
== External Links ==