<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://tech-pubs.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Kernel%3A_Ethernet_Drivers</id>
	<title>Kernel: Ethernet Drivers - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://tech-pubs.net/wiki/index.php?action=history&amp;feed=atom&amp;title=Kernel%3A_Ethernet_Drivers"/>
	<link rel="alternate" type="text/html" href="https://tech-pubs.net/wiki/index.php?title=Kernel:_Ethernet_Drivers&amp;action=history"/>
	<updated>2026-04-14T12:34:02Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://tech-pubs.net/wiki/index.php?title=Kernel:_Ethernet_Drivers&amp;diff=488&amp;oldid=prev</id>
		<title>Raion at 07:05, 6 February 2026</title>
		<link rel="alternate" type="text/html" href="https://tech-pubs.net/wiki/index.php?title=Kernel:_Ethernet_Drivers&amp;diff=488&amp;oldid=prev"/>
		<updated>2026-02-06T07:05:43Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 07:05, 6 February 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l689&quot;&gt;Line 689:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 689:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 1. PCI Infrastructure ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 1. PCI Infrastructure ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Register vendor/device ID in if_XXinit()&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Register vendor/device ID in if_XXinit()&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Map register spaces with pciio_piotrans_addr()&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Map register spaces with pciio_piotrans_addr()&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Enable bus master and memory space in PCI config&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Enable bus master and memory space in PCI config&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Set cache line size and latency timer&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Set cache line size and latency timer&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 2. Memory Management ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 2. Memory Management ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Allocate descriptor rings with contig_memalloc()&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Allocate descriptor rings with contig_memalloc()&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Verify alignment requirements met&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Verify alignment requirements met&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Allocate mbuf tracking arrays with kmem_zalloc()&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Allocate mbuf tracking arrays with kmem_zalloc()&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Create fast DMA map with pciio_dmamap_alloc()&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Create fast DMA map with pciio_dmamap_alloc()&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 3. Hardware Initialization ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 3. Hardware Initialization ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Reset chip and verify self-test passes&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Reset chip and verify self-test passes&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Probe and initialize PHY&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Probe and initialize PHY&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Configure MAC address from EEPROM/NIC&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Configure MAC address from EEPROM/NIC&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Set up descriptor ring base addresses&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Set up descriptor ring base addresses&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Configure DMA parameters (burst size, etc.)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Configure DMA parameters (burst size, etc.)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Enable checksumming if supported&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Enable checksumming if supported&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 4. Descriptor Management ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 4. Descriptor Management ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Implement ring index macros (NEXT, DELTA)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Implement ring index macros (NEXT, DELTA)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Handle cache coherency (CACHE_WB/CACHE_INVAL)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Handle cache coherency (CACHE_WB/CACHE_INVAL)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Translate addresses with KVTOIOADDR_CMD/DATA&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Translate addresses with KVTOIOADDR_CMD/DATA&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Post initial RX buffers&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Post initial RX buffers&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 5. Interrupt Handling ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 5. Interrupt Handling ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Register handler with pciio_intr_alloc/connect&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Register handler with pciio_intr_alloc/connect&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Read and clear interrupt status&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Read and clear interrupt status&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Process RX and TX completions&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Process RX and TX completions&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Handle error conditions&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Handle error conditions&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Rearm interrupts&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Rearm interrupts&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 6. Network Integration ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 6. Network Integration ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Implement etherif operations vector&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Implement etherif operations vector&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Call ether_attach() with correct inventory type&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Call ether_attach() with correct inventory type&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Support multicast filtering&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Support multicast filtering&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Implement SIOCADDMULTI/SIOCDELMULTI ioctls&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Implement SIOCADDMULTI/SIOCDELMULTI ioctls&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Handle IFF_PROMISC and IFF_ALLMULTI&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Handle IFF_PROMISC and IFF_ALLMULTI&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 7. Packet Scheduling ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 7. Packet Scheduling ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Implement txfree_len callback&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Implement txfree_len callback&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Implement setstate callback &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt; &lt;/del&gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Implement setstate callback&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Call ps_init() during initialization&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Call ps_init() during initialization&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Optionally interrupt per-packet when PS enabled&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Optionally interrupt per-packet when PS enabled&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 8. Testing ===&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;=== 8. Testing ===&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Basic ping test (small packets)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Basic ping test (small packets)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Large transfer test (TCP bulk data)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Large transfer test (TCP bulk data)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Multicast functionality&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Multicast functionality&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Promiscuous mode (tcpdump)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Promiscuous mode (tcpdump)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Link up/down handling&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Link up/down handling&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Error recovery (cable unplug/replug)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Error recovery (cable unplug/replug)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* &lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[ ] &lt;/del&gt;Performance testing (ttcp, netperf)&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* Performance testing (ttcp, netperf)&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Summary ==&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;== Summary ==&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Raion</name></author>
	</entry>
	<entry>
		<id>https://tech-pubs.net/wiki/index.php?title=Kernel:_Ethernet_Drivers&amp;diff=487&amp;oldid=prev</id>
		<title>Raion: Initial Commit</title>
		<link rel="alternate" type="text/html" href="https://tech-pubs.net/wiki/index.php?title=Kernel:_Ethernet_Drivers&amp;diff=487&amp;oldid=prev"/>
		<updated>2026-02-06T07:04:28Z</updated>

		<summary type="html">&lt;p&gt;Initial Commit&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;
This document describes the architecture and common patterns for Ethernet network drivers in IRIX based on analysis of three production drivers: Alteon Tigon (high-end), TI ThunderLAN (mid-range O2), and IOC3 (integrated ASIC). Understanding these patterns is essential for porting modern Ethernet controllers to IRIX.&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
IRIX Ethernet drivers follow a consistent architecture across all hardware:&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;PCI infrastructure integration&amp;#039;&amp;#039;&amp;#039; via pciio_* APIs&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Hardware graph (hwgraph) registration&amp;#039;&amp;#039;&amp;#039; for device discovery&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Etherif framework&amp;#039;&amp;#039;&amp;#039; providing standard network interface&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Descriptor ring management&amp;#039;&amp;#039;&amp;#039; for DMA transfers&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Interrupt handling&amp;#039;&amp;#039;&amp;#039; at splimp() level&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;MII/PHY management&amp;#039;&amp;#039;&amp;#039; for link negotiation&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Packet scheduling&amp;#039;&amp;#039;&amp;#039; (RSVP) support&lt;br /&gt;
&lt;br /&gt;
== Driver Initialization Flow ==&lt;br /&gt;
&lt;br /&gt;
=== Module Loading ===&lt;br /&gt;
&lt;br /&gt;
All drivers follow this initialization sequence:&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;if_XXinit()&amp;#039;&amp;#039;&amp;#039; - Called once at boot by edtinit()&lt;br /&gt;
#* Registers PCI vendor/device IDs via pciio_driver_register()&lt;br /&gt;
#* Registers idbg debug functions&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;if_XXattach()&amp;#039;&amp;#039;&amp;#039; - Called for each matching PCI device&lt;br /&gt;
#* Creates hwgraph vertices&lt;br /&gt;
#* Maps PCI memory regions&lt;br /&gt;
#* Allocates descriptor rings&lt;br /&gt;
#* Initializes hardware&lt;br /&gt;
#* Registers interrupt handlers&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;if_XXopen()&amp;#039;&amp;#039;&amp;#039; - Called when interface is configured&lt;br /&gt;
#* Gets unit number from device_controller_num_get()&lt;br /&gt;
#* Calls ether_attach() to register with network stack&lt;br /&gt;
&lt;br /&gt;
=== Critical Initialization Order ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1. pciio_driver_register() - Register with PCI subsystem&lt;br /&gt;
2. Allocate private state structure (ei/ti/ei_info)&lt;br /&gt;
3. hwgraph_char_device_add() - Create device vertex&lt;br /&gt;
4. pciio_piotrans_addr() - Map register spaces&lt;br /&gt;
5. Allocate DMA-able memory via contig_memalloc()&lt;br /&gt;
6. Initialize hardware (reset, PHY, MAC)&lt;br /&gt;
7. pciio_intr_alloc() + pciio_intr_connect()&lt;br /&gt;
8. ether_attach() - Final registration&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Memory Management ==&lt;br /&gt;
&lt;br /&gt;
=== DMA Memory Allocation ===&lt;br /&gt;
&lt;br /&gt;
IRIX requires &amp;#039;&amp;#039;&amp;#039;physically contiguous memory&amp;#039;&amp;#039;&amp;#039; for DMA descriptor rings. Use contig_memalloc() with specific alignment requirements:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Descriptor Ring Requirements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Alteon TX ring: 64K alignment for 512-entry ring&lt;br /&gt;
* IOC3 TX ring: 64K alignment for 512-entry ring&lt;br /&gt;
* IOC3 RX ring: 4K alignment&lt;br /&gt;
* ThunderLAN: Page-aligned&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Example (IOC3):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
size = NTXD * TXDSZ;  // 512 * 128 bytes&lt;br /&gt;
npgs = (size + NBPP - 1) / NBPP;&lt;br /&gt;
pgno = contig_memalloc(npgs, ALIGNMENT_PAGES, VM_DIRECT);&lt;br /&gt;
ei-&amp;gt;txd = (struct eftxd*)small_pfntova_K0(pgno);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Cache Coherency - CRITICAL ===&lt;br /&gt;
&lt;br /&gt;
IRIX systems (especially Origin/Octane with Heart chipset) require &amp;#039;&amp;#039;&amp;#039;explicit cache management&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Heart Coherency WAR:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#if HEART_COHERENCY_WAR&lt;br /&gt;
#define CACHE_WB(addr, len) heart_dcache_wb_inval((addr), (len))&lt;br /&gt;
#else&lt;br /&gt;
#define CACHE_WB(addr, len)&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#if HEART_INVALIDATE_WAR  &lt;br /&gt;
#define CACHE_INVAL(addr, len) heart_invalidate_war((addr), (len))&lt;br /&gt;
#else&lt;br /&gt;
#define CACHE_INVAL(addr, len)&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;When to flush caches:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Before DMA read (RX):&amp;#039;&amp;#039;&amp;#039; CACHE_INVAL() on receive buffers&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Before DMA write (TX):&amp;#039;&amp;#039;&amp;#039; CACHE_WB() on transmit data&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;After descriptor update:&amp;#039;&amp;#039;&amp;#039; CACHE_WB() on descriptor memory&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;IP32 (O2) specific:&amp;#039;&amp;#039;&amp;#039; Always use __vm_dcache_inval() and dki_dcache_wb()&lt;br /&gt;
&lt;br /&gt;
== PCI Infrastructure Integration ==&lt;br /&gt;
&lt;br /&gt;
=== Address Translation ===&lt;br /&gt;
&lt;br /&gt;
IRIX requires explicit DMA address translation for 64-bit capable devices:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Command DMA (descriptors, control):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define KVTOIOADDR_CMD(ei, addr) \&lt;br /&gt;
    pciio_dmatrans_addr((ei)-&amp;gt;conn_vhdl, 0, \&lt;br /&gt;
        kvtophys((caddr_t)(addr)), sizeof(int), \&lt;br /&gt;
        PCIIO_DMA_A64 | PCIIO_DMA_CMD)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Data DMA (packet buffers):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Fast path using pre-allocated DMA map&lt;br /&gt;
#define KVTOIOADDR_DATA(ei, addr) \&lt;br /&gt;
    pciio_dmamap_addr((ei)-&amp;gt;fastmap, \&lt;br /&gt;
        kvtophys((caddr_t)(addr)), sizeof(int))&lt;br /&gt;
&lt;br /&gt;
// Allocate fast map during init:&lt;br /&gt;
ei-&amp;gt;fastmap = pciio_dmamap_alloc(conn_vhdl, dev_desc, &lt;br /&gt;
    sizeof(int), PCIIO_DMA_DATA | PCIIO_DMA_A64 | PCIIO_FIXED);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interrupt Registration ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Set interrupt name and priority&lt;br /&gt;
device_desc_intr_name_set(dev_desc, &amp;quot;Ethernet&amp;quot;);&lt;br /&gt;
device_desc_intr_swlevel_set(dev_desc, (ilvl_t)splimp);&lt;br /&gt;
&lt;br /&gt;
// Allocate and connect interrupt&lt;br /&gt;
ei-&amp;gt;intr = pciio_intr_alloc(conn_vhdl, dev_desc, &lt;br /&gt;
                             PCIIO_INTR_LINE_A, enet_vhdl);&lt;br /&gt;
pciio_intr_connect(ei-&amp;gt;intr, (intr_func_t)if_XXintr, &lt;br /&gt;
                   (intr_arg_t)ei, NULL);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Descriptor Ring Architecture ==&lt;br /&gt;
&lt;br /&gt;
All three drivers use &amp;#039;&amp;#039;&amp;#039;producer/consumer ring buffers&amp;#039;&amp;#039;&amp;#039; with hardware/software indices:&lt;br /&gt;
&lt;br /&gt;
=== Common Ring Structure ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
struct driver_info {&lt;br /&gt;
    // TX ring&lt;br /&gt;
    struct txd *txd;           // TX descriptor array&lt;br /&gt;
    struct mbuf **txm;         // Pending TX mbufs&lt;br /&gt;
    int txhead;                // SW produce index&lt;br /&gt;
    int txtail;                // SW consume index&lt;br /&gt;
    &lt;br /&gt;
    // RX ring  &lt;br /&gt;
    struct rxd *rxd;           // RX descriptor array&lt;br /&gt;
    struct mbuf **rxm;         // Posted RX mbufs&lt;br /&gt;
    int rxhead;                // SW consume index&lt;br /&gt;
    int rxtail;                // SW produce index&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ring Index Management ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Critical macro patterns:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NEXTTXD(i) (((i) + 1) &amp;amp; (NTXD - 1))  // Ring must be power-of-2&lt;br /&gt;
#define DELTATXD(h,t) ((h - t) &amp;amp; (NTXD - 1)) // Free descriptors&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;IOC3-specific gotcha:&amp;#039;&amp;#039;&amp;#039; Hardware compares RX indices modulo-16, so allocate 15 extra buffers:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define NRBUFADJ(n) (n + 15)  // Required for IOC3 only&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Transmit Path ==&lt;br /&gt;
&lt;br /&gt;
=== Etherif Transmit Function ===&lt;br /&gt;
&lt;br /&gt;
The transmit function must handle:&lt;br /&gt;
# Mbuf chain validation and coalescing&lt;br /&gt;
# Ethernet header insertion&lt;br /&gt;
# DMA address setup&lt;br /&gt;
# Descriptor programming&lt;br /&gt;
# Hardware checksum offload (if supported)&lt;br /&gt;
# Self-snoop for packet capture&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Typical signature:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static int XX_transmit(&lt;br /&gt;
    struct etherif *eif,&lt;br /&gt;
    struct etheraddr *edst,   // Destination MAC&lt;br /&gt;
    struct etheraddr *esrc,   // Source MAC  &lt;br /&gt;
    u_short type,             // EtherType&lt;br /&gt;
    struct mbuf *m0)          // Packet chain&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Mbuf Alignment Requirements ===&lt;br /&gt;
&lt;br /&gt;
Different hardware has different alignment constraints:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;IOC3 requirements:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Data0 (in descriptor): must be even length if buf1 is used&lt;br /&gt;
* Buf1 pointer: must be 2-byte aligned&lt;br /&gt;
* Buf2 pointer: must be 128-byte aligned AND buf1 must be even length&lt;br /&gt;
* No buffer may cross page boundary&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution patterns:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Check alignment&lt;br /&gt;
#define MALIGN2(m)   ALIGNED(mtod((m), u_long), 2)&lt;br /&gt;
#define MALIGN128(m) ALIGNED(mtod((m), u_long), 128)&lt;br /&gt;
&lt;br /&gt;
// Copy if misaligned&lt;br /&gt;
if (!MALIGN2(m0) || mbuf_crosses_page(m0))&lt;br /&gt;
    goto copyall;&lt;br /&gt;
&lt;br /&gt;
copyall:&lt;br /&gt;
    m = m_vget(M_DONTWAIT, mlen, MT_DATA);&lt;br /&gt;
    m_datacopy(m0, 0, mlen, mtod(m, caddr_t));&lt;br /&gt;
    m_freem(m0);&lt;br /&gt;
    m0 = m;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Hardware Checksum Offload ===&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;IOC3 TX checksum:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if (m0-&amp;gt;m_flags &amp;amp; M_CKSUMMED) {&lt;br /&gt;
    struct ip *ip = mtod(m0, struct ip*);&lt;br /&gt;
    int hlen = ip-&amp;gt;ip_hl &amp;lt;&amp;lt; 2;&lt;br /&gt;
    &lt;br /&gt;
    // Compute pseudo-header checksum&lt;br /&gt;
    __uint32_t cksum = ((ip-&amp;gt;ip_len - hlen)&lt;br /&gt;
        + htons((ushort)ip-&amp;gt;ip_p)&lt;br /&gt;
        + (ip-&amp;gt;ip_src.s_addr &amp;gt;&amp;gt; 16)&lt;br /&gt;
        + (ip-&amp;gt;ip_src.s_addr &amp;amp; 0xffff)&lt;br /&gt;
        + (ip-&amp;gt;ip_dst.s_addr &amp;gt;&amp;gt; 16)  &lt;br /&gt;
        + (ip-&amp;gt;ip_dst.s_addr &amp;amp; 0xffff));&lt;br /&gt;
    &lt;br /&gt;
    // Subtract ethernet header contribution&lt;br /&gt;
    cksum += 0xffff ^ (type + MAC_checksum_contrib);&lt;br /&gt;
    &lt;br /&gt;
    // Store adjustment in TCP/UDP header&lt;br /&gt;
    mtod(m0, u_short*)[sumoff/2] = fold_checksum(cksum);&lt;br /&gt;
    &lt;br /&gt;
    // Set descriptor flags&lt;br /&gt;
    txd-&amp;gt;cmd |= (sumoff &amp;lt;&amp;lt; ETXD_CHKOFF_SHIFT) | ETXD_DOCHECKSUM;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Errata:&amp;#039;&amp;#039;&amp;#039; IOC3 rev 0 has a bug - it fails to take one&amp;#039;s complement. Disable TX checksum for rev 0 chips.&lt;br /&gt;
&lt;br /&gt;
=== Descriptor Update Pattern ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Fill descriptor fields&lt;br /&gt;
txd-&amp;gt;cmd = flags | length;&lt;br /&gt;
txd-&amp;gt;bufcnt = total_length;&lt;br /&gt;
txd-&amp;gt;p1 = KVTOIOADDR_DATA(ei, mbuf_data);&lt;br /&gt;
&lt;br /&gt;
// CRITICAL: Writeback cache before hardware sees it&lt;br /&gt;
CACHE_WB((void *)txd, TXDSZ);&lt;br /&gt;
&lt;br /&gt;
// Save mbuf for later freeing&lt;br /&gt;
ei-&amp;gt;txm[ei-&amp;gt;txhead] = m0;&lt;br /&gt;
&lt;br /&gt;
// Update software index&lt;br /&gt;
ei-&amp;gt;txhead = NEXTTXD(ei-&amp;gt;txhead);&lt;br /&gt;
&lt;br /&gt;
// Notify hardware (write produce register)&lt;br /&gt;
W_REG(ei-&amp;gt;regs-&amp;gt;etpir, (ei-&amp;gt;txhead * TXDSZ));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Receive Path ==&lt;br /&gt;
&lt;br /&gt;
=== RX Buffer Posting ===&lt;br /&gt;
&lt;br /&gt;
Drivers must maintain a pool of posted receive buffers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void ef_fill(struct ef_info *ei) {&lt;br /&gt;
    int head = ei-&amp;gt;rxhead;&lt;br /&gt;
    int tail = ei-&amp;gt;rxtail;&lt;br /&gt;
    int n = ei-&amp;gt;nrbuf - DELTARXD(head, tail);&lt;br /&gt;
    &lt;br /&gt;
    for (i = 0; i &amp;lt; n; i++) {&lt;br /&gt;
        m = m_vget(M_DONTWAIT, sizeof(struct rxbuf), MT_DATA);&lt;br /&gt;
        if (!m) break;&lt;br /&gt;
        &lt;br /&gt;
        rb = mtod(m, struct rxbuf*);&lt;br /&gt;
        ei-&amp;gt;rxm[tail] = m;&lt;br /&gt;
        ei-&amp;gt;rxd[tail] = KVTOIOADDR_DATA(ei, rb);&lt;br /&gt;
        &lt;br /&gt;
        // Invalidate for DMA&lt;br /&gt;
        CACHE_INVAL(rb, sizeof(struct rxbuf));&lt;br /&gt;
        CACHE_WB(mtod(m, caddr_t), sizeof(struct rxbuf));&lt;br /&gt;
        &lt;br /&gt;
        tail = NEXTRXD(tail);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    ei-&amp;gt;rxtail = tail;&lt;br /&gt;
    W_REG(ei-&amp;gt;regs-&amp;gt;erpir, (ERPIR_ARM | (tail * RXDSZ)));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interrupt Handler ===&lt;br /&gt;
&lt;br /&gt;
IRIX interrupt handlers run at &amp;#039;&amp;#039;&amp;#039;splimp()&amp;#039;&amp;#039;&amp;#039; priority and must:&lt;br /&gt;
# Read/clear interrupt status&lt;br /&gt;
# Process received packets&lt;br /&gt;
# Reclaim completed TX descriptors  &lt;br /&gt;
# Rearm interrupt&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Typical pattern:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void if_XXintr(struct XX_info *ei) {&lt;br /&gt;
    int s;&lt;br /&gt;
    struct mbuf *mact, *m;&lt;br /&gt;
    &lt;br /&gt;
    s = mutex_bitlock(&amp;amp;ei-&amp;gt;flags, EIF_LOCK);&lt;br /&gt;
    &lt;br /&gt;
    // Read and clear interrupt status&lt;br /&gt;
    isr = R_REG(ei-&amp;gt;regs-&amp;gt;eisr);&lt;br /&gt;
    W_REG(ei-&amp;gt;regs-&amp;gt;eisr, isr);&lt;br /&gt;
    &lt;br /&gt;
    // Process RX&lt;br /&gt;
    if (isr &amp;amp; EISR_RXTHRESH) {&lt;br /&gt;
        mact = ef_recv(ei);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Reclaim TX&lt;br /&gt;
    if (isr &amp;amp; EISR_TXDONE) {&lt;br /&gt;
        ef_reclaim(ei);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Handle errors&lt;br /&gt;
    if (isr &amp;amp; EISR_ERROR) {&lt;br /&gt;
        handle_errors(ei);&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Rearm&lt;br /&gt;
    W_REG(ei-&amp;gt;regs-&amp;gt;erpir, ERPIR_ARM | produce_index);&lt;br /&gt;
    &lt;br /&gt;
    mutex_bitunlock(&amp;amp;ei-&amp;gt;flags, EIF_LOCK, s);&lt;br /&gt;
    &lt;br /&gt;
    // Send packets up AFTER releasing lock&lt;br /&gt;
    while (mact) {&lt;br /&gt;
        m = mact;&lt;br /&gt;
        mact = mact-&amp;gt;m_act;&lt;br /&gt;
        ether_input(&amp;amp;ei-&amp;gt;eif, 0, m);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== RX Checksum Validation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
if ((ntohs(eh-&amp;gt;ether_type) == ETHERTYPE_IP)&lt;br /&gt;
    &amp;amp;&amp;amp; (rlen &amp;gt;= 60)  &lt;br /&gt;
    &amp;amp;&amp;amp; ((ip-&amp;gt;ip_off &amp;amp; (IP_OFFMASK|IP_MF)) == 0)&lt;br /&gt;
    &amp;amp;&amp;amp; ((ip-&amp;gt;ip_p == IPPROTO_TCP) || (ip-&amp;gt;ip_p == IPPROTO_UDP))) {&lt;br /&gt;
    &lt;br /&gt;
    // IOC3 provides checksum in descriptor&lt;br /&gt;
    cksum = rxd-&amp;gt;w0 &amp;amp; ERXBUF_IPCKSUM_MASK;&lt;br /&gt;
    &lt;br /&gt;
    // Finish calculation (add pseudo-header, subtract ether header)&lt;br /&gt;
    // ...&lt;br /&gt;
    &lt;br /&gt;
    if (cksum == 0xffff)&lt;br /&gt;
        m-&amp;gt;m_flags |= M_CKSUMMED;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PHY Management (MII Interface) ==&lt;br /&gt;
&lt;br /&gt;
=== PHY Detection and Reset ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static int ef_phyprobe(struct ef_info *ei) {&lt;br /&gt;
    int i, r2, r3, val;&lt;br /&gt;
    &lt;br /&gt;
    for (i = 0; i &amp;lt; 32; i++) {&lt;br /&gt;
        ei-&amp;gt;phyunit = i;&lt;br /&gt;
        r2 = ef_phyget(ei, MII_PHY_ID_HI);&lt;br /&gt;
        r3 = ef_phyget(ei, MII_PHY_ID_LO);&lt;br /&gt;
        val = (r2 &amp;lt;&amp;lt; 12) | (r3 &amp;gt;&amp;gt; 4);&lt;br /&gt;
        &lt;br /&gt;
        switch (val) {&lt;br /&gt;
        case PHY_QS6612X:&lt;br /&gt;
        case PHY_ICS1889:&lt;br /&gt;
        case PHY_DP83840:&lt;br /&gt;
            ei-&amp;gt;phytype = val;&lt;br /&gt;
            ei-&amp;gt;phyrev = r3 &amp;amp; 0xf;&lt;br /&gt;
            return val;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return -1;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== MII Read/Write ===&lt;br /&gt;
&lt;br /&gt;
Hardware provides two main approaches:&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Approach 1: Dedicated MII registers (IOC3, ThunderLAN):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static int ef_phyget(struct ef_info *ei, int reg) {&lt;br /&gt;
    // Wait for ready&lt;br /&gt;
    while (regs-&amp;gt;micr &amp;amp; MICR_BUSY)&lt;br /&gt;
        DELAYBUS(1);&lt;br /&gt;
        &lt;br /&gt;
    // Trigger read&lt;br /&gt;
    regs-&amp;gt;micr = MICR_READTRIG | &lt;br /&gt;
                 (ei-&amp;gt;phyunit &amp;lt;&amp;lt; MICR_PHYADDR_SHIFT) | reg;&lt;br /&gt;
                 &lt;br /&gt;
    // Wait for completion&lt;br /&gt;
    while (regs-&amp;gt;micr &amp;amp; MICR_BUSY)&lt;br /&gt;
        DELAYBUS(1);&lt;br /&gt;
        &lt;br /&gt;
    return (regs-&amp;gt;midr_r &amp;amp; MIDR_DATA_MASK);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Approach 2: GPIO bit-banging (Alteon, ThunderLAN alt):&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Send sync pattern (32 cycles of 1)&lt;br /&gt;
// Send start bits (01)&lt;br /&gt;
// Send opcode (10=read, 01=write)&lt;br /&gt;
// Send PHY address (5 bits)&lt;br /&gt;
// Send register (5 bits)&lt;br /&gt;
// Turnaround and read data (16 bits)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auto-negotiation ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void ef_autonego(struct ef_info *ei) {&lt;br /&gt;
    int timeout = 20000;&lt;br /&gt;
    &lt;br /&gt;
    // Enable auto-negotiation&lt;br /&gt;
    ef_phyput(ei, MII_CTRL, MII_CTRL_AUTOEN | MII_CTRL_RESTART);&lt;br /&gt;
    &lt;br /&gt;
    // Wait for completion&lt;br /&gt;
    while (!(ef_phyget(ei, MII_STATUS) &amp;amp; MII_STATUS_ANDONE)) {&lt;br /&gt;
        DELAY(100);&lt;br /&gt;
        if (timeout-- &amp;lt;= 0) {&lt;br /&gt;
            // Default to 10Mbit half-duplex&lt;br /&gt;
            ei-&amp;gt;speed100 = 0;&lt;br /&gt;
            ei-&amp;gt;fullduplex = 0;&lt;br /&gt;
            return;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Parse negotiation result&lt;br /&gt;
    r4 = ef_phyget(ei, MII_AN_ADV);&lt;br /&gt;
    r5 = ef_phyget(ei, MII_AN_LPAR);&lt;br /&gt;
    &lt;br /&gt;
    if ((r4 &amp;amp; MII_TXFD) &amp;amp;&amp;amp; (r5 &amp;amp; MII_TXFD)) {&lt;br /&gt;
        ei-&amp;gt;speed100 = 1;&lt;br /&gt;
        ei-&amp;gt;fullduplex = 1;&lt;br /&gt;
    } else if ((r4 &amp;amp; MII_TX) &amp;amp;&amp;amp; (r5 &amp;amp; MII_TX)) {&lt;br /&gt;
        ei-&amp;gt;speed100 = 1;&lt;br /&gt;
        ei-&amp;gt;fullduplex = 0;&lt;br /&gt;
    }&lt;br /&gt;
    // ... etc&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Watchdog and Error Handling ==&lt;br /&gt;
&lt;br /&gt;
=== Periodic Watchdog ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void ef_watchdog(struct ifnet *ifp) {&lt;br /&gt;
    struct ef_info *ei = eiftoei(ifptoeif(ifp));&lt;br /&gt;
    &lt;br /&gt;
    // Update statistics&lt;br /&gt;
    ef_getcdc(ei);  // Collision/defer counters&lt;br /&gt;
    &lt;br /&gt;
    // Check PHY status&lt;br /&gt;
    ef_phyerr(ei);&lt;br /&gt;
    &lt;br /&gt;
    // Reclaim TX descriptors&lt;br /&gt;
    ef_reclaim(ei);&lt;br /&gt;
    &lt;br /&gt;
    // Refill RX buffers&lt;br /&gt;
    ef_fill(ei);&lt;br /&gt;
    &lt;br /&gt;
    // Check for missed interrupts&lt;br /&gt;
    ef_intr(ei);&lt;br /&gt;
    &lt;br /&gt;
    // Reschedule&lt;br /&gt;
    ei-&amp;gt;if_timer = WATCHDOG_INTERVAL;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Link State Monitoring ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static void ef_phyerr(struct ef_info *ei) {&lt;br /&gt;
    int reg1 = ef_phyget(ei, MII_STATUS);&lt;br /&gt;
    &lt;br /&gt;
    // Link status (latched low, read twice)&lt;br /&gt;
    if (!(reg1 &amp;amp; MII_STATUS_LINK)) {&lt;br /&gt;
        if (!(ei-&amp;gt;flags &amp;amp; EIF_LINKDOWN)) {&lt;br /&gt;
            cmn_err(CE_WARN, &amp;quot;ef%d: link fail - check cable&amp;quot;, &lt;br /&gt;
                    ei-&amp;gt;unit);&lt;br /&gt;
            ei-&amp;gt;flags |= EIF_LINKDOWN;&lt;br /&gt;
        }&lt;br /&gt;
    } else {&lt;br /&gt;
        if (ei-&amp;gt;flags &amp;amp; EIF_LINKDOWN) {&lt;br /&gt;
            cmn_err(CE_NOTE, &amp;quot;ef%d: link ok&amp;quot;, ei-&amp;gt;unit);&lt;br /&gt;
            ei-&amp;gt;flags &amp;amp;= ~EIF_LINKDOWN;&lt;br /&gt;
            ef_reinit(ei);  // May need to adjust speed/duplex&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    // Check for remote fault, jabber, etc.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== RSVP/Packet Scheduling ==&lt;br /&gt;
&lt;br /&gt;
IRIX supports packet scheduling for QoS. Drivers must:&lt;br /&gt;
# Report available TX descriptors&lt;br /&gt;
# Signal when descriptors become available&lt;br /&gt;
# Optionally interrupt on each TX completion when scheduling active&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static int ef_txfree_len(struct ifnet *ifp) {&lt;br /&gt;
    struct ef_info *ei = eiftoei(ifptoeif(ifp));&lt;br /&gt;
    return (NTXD - DELTATXD(ei-&amp;gt;txhead, ei-&amp;gt;txtail));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static void ef_setstate(struct ifnet *ifp, int setting) {&lt;br /&gt;
    struct ef_info *ei = eiftoei(ifptoeif(ifp));&lt;br /&gt;
    if (setting)&lt;br /&gt;
        ei-&amp;gt;flags |= EIF_PSENABLED;&lt;br /&gt;
    else&lt;br /&gt;
        ei-&amp;gt;flags &amp;amp;= ~EIF_PSENABLED;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// In transmit path:&lt;br /&gt;
if ((ei-&amp;gt;flags &amp;amp; EIF_PSENABLED) &amp;amp;&amp;amp; &lt;br /&gt;
    ((ei-&amp;gt;txhead &amp;amp; ei-&amp;gt;intfreq) == 0)) {&lt;br /&gt;
    txd-&amp;gt;cmd |= ETXD_INTWHENDONE;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// In interrupt handler:&lt;br /&gt;
if (ei-&amp;gt;flags &amp;amp; EIF_PSENABLED) {&lt;br /&gt;
    ps_txq_stat(eiftoifp(&amp;amp;ei-&amp;gt;eif), ef_txfree_len(&amp;amp;ei-&amp;gt;if));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// During init:&lt;br /&gt;
struct ps_parms ps_params;&lt;br /&gt;
ps_params.bandwidth = ei-&amp;gt;speed100 ? 100000000 : 10000000;&lt;br /&gt;
ps_params.flags = 0;&lt;br /&gt;
ps_params.txfree = NTXD;&lt;br /&gt;
ps_params.txfree_func = ef_txfree_len;&lt;br /&gt;
ps_params.state_func = ef_setstate;&lt;br /&gt;
ps_init(eiftoifp(&amp;amp;ei-&amp;gt;eif), &amp;amp;ps_params);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Locking and Synchronization ==&lt;br /&gt;
&lt;br /&gt;
IRIX uses &amp;#039;&amp;#039;&amp;#039;bitlocks&amp;#039;&amp;#039;&amp;#039; for driver synchronization:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Initialize lock during attach&lt;br /&gt;
init_bitlock(&amp;amp;ei-&amp;gt;flags, EIF_LOCK, &amp;quot;ef drv lock&amp;quot;, 0);&lt;br /&gt;
&lt;br /&gt;
// Acquire in all paths that touch hardware&lt;br /&gt;
s = mutex_bitlock(&amp;amp;ei-&amp;gt;flags, EIF_LOCK);&lt;br /&gt;
// ... critical section ...&lt;br /&gt;
mutex_bitunlock(&amp;amp;ei-&amp;gt;flags, EIF_LOCK, s);&lt;br /&gt;
&lt;br /&gt;
// Check if locked (for assertions)&lt;br /&gt;
ASSERT(ei-&amp;gt;flags &amp;amp; EIF_LOCK);&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Lock hierarchy:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;ifnet lock&amp;#039;&amp;#039;&amp;#039; (IFNET_LOCK) - Highest level, held during ioctl&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Driver bitlock&amp;#039;&amp;#039;&amp;#039; - Protects hardware access and descriptor rings&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Separate TX/RX locks&amp;#039;&amp;#039;&amp;#039; - Some drivers use separate locks for TX and RX paths&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Critical sections that need locking:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* Descriptor ring manipulation&lt;br /&gt;
* Hardware register access&lt;br /&gt;
* mbuf list operations&lt;br /&gt;
* Statistics updates&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Operations outside lock:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
* ether_input() - Network stack must be called without driver lock&lt;br /&gt;
* m_freem() - Can be called outside lock&lt;br /&gt;
&lt;br /&gt;
== Common Pitfalls and Gotchas ==&lt;br /&gt;
&lt;br /&gt;
=== Cache Coherency ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Forgetting cache flushes causes random packet corruption.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Always CACHE_WB before DMA write, CACHE_INVAL before DMA read.&lt;br /&gt;
&lt;br /&gt;
=== Descriptor Alignment ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Hardware silently uses wrong memory if alignment is incorrect.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Use contig_memalloc with correct alignment parameter.&lt;br /&gt;
&lt;br /&gt;
=== mbuf Chain Fragmentation ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Each mbuf may require a separate DMA descriptor, exhausting hardware resources.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Coalesce into single mbuf if chain too long or poorly aligned.&lt;br /&gt;
&lt;br /&gt;
=== Register Write Ordering ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Posted writes may not complete before hardware starts DMA.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Read back critical registers to force write completion:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
W_REG(ei-&amp;gt;regs-&amp;gt;emcr, EMCR_RST);&lt;br /&gt;
R_REG(ei-&amp;gt;regs-&amp;gt;emcr);  // Force write to complete&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== IOC3 RX Index Comparison ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Hardware compares RX indices modulo-16, causing premature ring full condition.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Post 15 extra buffers (NRBUFADJ macro).&lt;br /&gt;
&lt;br /&gt;
=== Interrupt Re-arming ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Forgetting to rearm causes no more interrupts.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Always write to interrupt rearm register at end of handler.&lt;br /&gt;
&lt;br /&gt;
=== Link State During Init ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Reading MII status during PHY reset gives false link-down errors.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Delay link state checking until after auto-negotiation completes.&lt;br /&gt;
&lt;br /&gt;
=== Multicast Filter Collisions ===&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Problem:&amp;#039;&amp;#039;&amp;#039; Multiple multicast addresses may hash to same filter bit.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Solution:&amp;#039;&amp;#039;&amp;#039; Maintain collision counter; keep filter bit set if any addresses hash to it.&lt;br /&gt;
&lt;br /&gt;
== Hardware-Specific Considerations ==&lt;br /&gt;
&lt;br /&gt;
=== Alteon Tigon ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Firmware loading&amp;#039;&amp;#039;&amp;#039; - Must load code/data into on-chip SRAM&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Event ring&amp;#039;&amp;#039;&amp;#039; - Asynchronous events in addition to interrupts&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Large SRAM&amp;#039;&amp;#039;&amp;#039; - Can hold many packets on-chip&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Sophisticated coalescing&amp;#039;&amp;#039;&amp;#039; - Configurable interrupt coalescing&lt;br /&gt;
&lt;br /&gt;
=== TI ThunderLAN ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;List-based DMA&amp;#039;&amp;#039;&amp;#039; - Multiple fragments per packet&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Integrated PHY&amp;#039;&amp;#039;&amp;#039; - On-chip 10Mbit PHY plus MII for external PHY&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;EEPROM access&amp;#039;&amp;#039;&amp;#039; - Complex protocol for reading MAC address&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Dual channels&amp;#039;&amp;#039;&amp;#039; - Separate TX/RX channels with independent DMA&lt;br /&gt;
&lt;br /&gt;
=== IOC3 ===&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Integrated PCI-X bridge&amp;#039;&amp;#039;&amp;#039; - Shares functions with serial/parallel ports&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Hardware checksumming&amp;#039;&amp;#039;&amp;#039; - TX and RX checksum offload&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;SSRAM buffer&amp;#039;&amp;#039;&amp;#039; - On-chip packet buffer (64KB or 128KB)&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Parity checking&amp;#039;&amp;#039;&amp;#039; - Optional parity on SSRAM&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;NIC EEPROM&amp;#039;&amp;#039;&amp;#039; - Number-in-a-can for MAC address&lt;br /&gt;
&lt;br /&gt;
== Testing and Debugging ==&lt;br /&gt;
&lt;br /&gt;
=== Debug Print Macros ===&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define DBG_PRINT(a) if (ei-&amp;gt;if_flags &amp;amp; IFF_DEBUG) printf a&lt;br /&gt;
&lt;br /&gt;
// Usage:&lt;br /&gt;
DBG_PRINT((&amp;quot;ef%d: txhead=%d txtail=%d\n&amp;quot;, unit, txhead, txtail));&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Dump Functions ===&lt;br /&gt;
Every driver should provide idbg dump functions:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
idbg_addfunc(&amp;quot;ef_dump&amp;quot;, (void (*)())ef_dump);&lt;br /&gt;
&lt;br /&gt;
static void ef_dump(int unit) {&lt;br /&gt;
    ef_dumpif(ifp);    // Interface statistics&lt;br /&gt;
    ef_dumpei(ei);     // Driver private state&lt;br /&gt;
    ef_dumpregs(ei);   // Hardware registers&lt;br /&gt;
    ef_dumpphy(ei);    // PHY registers&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Common Debug Points ===&lt;br /&gt;
* RX ring full - Check if ef_fill() is being called&lt;br /&gt;
* TX ring full - Check if ef_reclaim() is working  &lt;br /&gt;
* Checksum failures - Verify pseudo-header calculation&lt;br /&gt;
* Link flapping - Check PHY registers and cable&lt;br /&gt;
* DMA errors - Verify descriptor alignment and cache flushing&lt;br /&gt;
* Interrupt storms - Ensure status register is being cleared&lt;br /&gt;
&lt;br /&gt;
== Porting Checklist ==&lt;br /&gt;
&lt;br /&gt;
When porting a new Ethernet controller to IRIX:&lt;br /&gt;
&lt;br /&gt;
=== 1. PCI Infrastructure ===&lt;br /&gt;
* [ ] Register vendor/device ID in if_XXinit()&lt;br /&gt;
* [ ] Map register spaces with pciio_piotrans_addr()&lt;br /&gt;
* [ ] Enable bus master and memory space in PCI config&lt;br /&gt;
* [ ] Set cache line size and latency timer&lt;br /&gt;
&lt;br /&gt;
=== 2. Memory Management ===&lt;br /&gt;
* [ ] Allocate descriptor rings with contig_memalloc()&lt;br /&gt;
* [ ] Verify alignment requirements met&lt;br /&gt;
* [ ] Allocate mbuf tracking arrays with kmem_zalloc()&lt;br /&gt;
* [ ] Create fast DMA map with pciio_dmamap_alloc()&lt;br /&gt;
&lt;br /&gt;
=== 3. Hardware Initialization ===&lt;br /&gt;
* [ ] Reset chip and verify self-test passes&lt;br /&gt;
* [ ] Probe and initialize PHY&lt;br /&gt;
* [ ] Configure MAC address from EEPROM/NIC&lt;br /&gt;
* [ ] Set up descriptor ring base addresses&lt;br /&gt;
* [ ] Configure DMA parameters (burst size, etc.)&lt;br /&gt;
* [ ] Enable checksumming if supported&lt;br /&gt;
&lt;br /&gt;
=== 4. Descriptor Management ===&lt;br /&gt;
* [ ] Implement ring index macros (NEXT, DELTA)&lt;br /&gt;
* [ ] Handle cache coherency (CACHE_WB/CACHE_INVAL)&lt;br /&gt;
* [ ] Translate addresses with KVTOIOADDR_CMD/DATA&lt;br /&gt;
* [ ] Post initial RX buffers&lt;br /&gt;
&lt;br /&gt;
=== 5. Interrupt Handling ===&lt;br /&gt;
* [ ] Register handler with pciio_intr_alloc/connect&lt;br /&gt;
* [ ] Read and clear interrupt status&lt;br /&gt;
* [ ] Process RX and TX completions&lt;br /&gt;
* [ ] Handle error conditions&lt;br /&gt;
* [ ] Rearm interrupts&lt;br /&gt;
&lt;br /&gt;
=== 6. Network Integration ===&lt;br /&gt;
* [ ] Implement etherif operations vector&lt;br /&gt;
* [ ] Call ether_attach() with correct inventory type&lt;br /&gt;
* [ ] Support multicast filtering&lt;br /&gt;
* [ ] Implement SIOCADDMULTI/SIOCDELMULTI ioctls&lt;br /&gt;
* [ ] Handle IFF_PROMISC and IFF_ALLMULTI&lt;br /&gt;
&lt;br /&gt;
=== 7. Packet Scheduling ===&lt;br /&gt;
* [ ] Implement txfree_len callback&lt;br /&gt;
* [ ] Implement setstate callback  &lt;br /&gt;
* [ ] Call ps_init() during initialization&lt;br /&gt;
* [ ] Optionally interrupt per-packet when PS enabled&lt;br /&gt;
&lt;br /&gt;
=== 8. Testing ===&lt;br /&gt;
* [ ] Basic ping test (small packets)&lt;br /&gt;
* [ ] Large transfer test (TCP bulk data)&lt;br /&gt;
* [ ] Multicast functionality&lt;br /&gt;
* [ ] Promiscuous mode (tcpdump)&lt;br /&gt;
* [ ] Link up/down handling&lt;br /&gt;
* [ ] Error recovery (cable unplug/replug)&lt;br /&gt;
* [ ] Performance testing (ttcp, netperf)&lt;br /&gt;
&lt;br /&gt;
== Summary ==&lt;br /&gt;
&lt;br /&gt;
IRIX Ethernet drivers follow a well-defined architecture that balances hardware flexibility with software consistency. Key principles:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Explicit cache management&amp;#039;&amp;#039;&amp;#039; for DMA coherency&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Physically contiguous&amp;#039;&amp;#039;&amp;#039; descriptor rings&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Producer/consumer rings&amp;#039;&amp;#039;&amp;#039; with power-of-2 sizes&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Bitlocks&amp;#039;&amp;#039;&amp;#039; for synchronization&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;PHY auto-negotiation&amp;#039;&amp;#039;&amp;#039; with error recovery&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Hardware/software index split&amp;#039;&amp;#039;&amp;#039; for lock-free updates&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;PCI infrastructure integration&amp;#039;&amp;#039;&amp;#039; for portability&lt;br /&gt;
&lt;br /&gt;
Understanding these patterns enables efficient porting of modern Ethernet controllers to the IRIX platform while avoiding common pitfalls around cache coherency, alignment, and interrupt handling.&lt;/div&gt;</summary>
		<author><name>Raion</name></author>
	</entry>
</feed>