OSDev.org

The Place to Start for Operating System Developers
It is currently Thu Apr 18, 2024 12:34 pm

All times are UTC - 6 hours




Post new topic Reply to topic  [ 2 posts ] 
Author Message
 Post subject: Receiving packets on the i219-V
PostPosted: Tue Sep 25, 2018 4:23 pm 
Offline

Joined: Tue Sep 25, 2018 9:36 am
Posts: 3
Location: Germany
Hello,

I am currently working on a driver for the i219-V network card. While there unfortunately is little documentation on its software interface, I was able to figure out most of its functionality using old manuals and Intel's official e1000e driver; after understanding the relation between the PCH and PHY things are quite similar to older e1000 cards. At this point my driver is able to transmit packets on real hardware, as I successfully tested with a hand-crafted ARP packet and Wireshark.

Unfortunately, receiving does not work. I already tried debugging that problem by printing the configuration and status registers; but from my point of view, the respective flags seem to be correct. The various statistics registers did not change, even when I was sure that the card *must* have received a packet (e.g. when getting the ARP response). Manually examing the receive descriptor ring did not show anything, too. Right now it looks like the PHY never receives packets, either because there is some misconfiguration on a very low level or the packet filtering is not properly initialized.

I've already checked with the e1000e driver, but it implements very many features and thus makes it easy to miss something important. Intel's driver seems to be doing a full hardware reset on startup; but since transmitting works already, I hope to avoid this.

I put the working parts of my code into a Wiki article draft; I will be happy to turn it into a full Wiki article, since digging through the documentation took me a lot of time.

The receiving code looks like this:
Code:
// Allocate receive data buffer
uint64_t rxBufferMemPhy;
rxBufferMem = heap_alloc_contiguous(RX_DESC_COUNT * RX_BUFFER_SIZE, VM_R | VM_W, &rxBufferMemPhy);
if(!rxBufferMem)
    panic("Could not allocate i219 receive data buffer.");

// Allocate and initialize receive descriptor buffer
uint64_t rxDescriptorsPhy;
rxDescriptors = heap_alloc_contiguous(RX_DESC_COUNT * sizeof(rx_desc_t), VM_R | VM_W, &rxDescriptorsPhy);
if(!rxDescriptors)
    panic("Could not allocate i219 receive descriptor buffer.");
for(int i = 0; i < RX_DESC_COUNT; ++i)
{
    // Initialize descriptor
    rx_desc_t *currDesc = &rxDescriptors[i];
    currDesc->address = rxBufferMemPhy + i * RX_BUFFER_SIZE;
    currDesc->status = 0;
}

// Pass receive descriptor buffer
i219_write(E1000_REG_RDBAH, rxDescriptorsPhy >> 32);
i219_write(E1000_REG_RDBAL, rxDescriptorsPhy & 0xFFFFFFFF);
i219_write(E1000_REG_RDLEN, RX_DESC_COUNT * sizeof(rx_desc_t));
i219_write(E1000_REG_RDH, 0);
i219_write(E1000_REG_RDT, RX_DESC_COUNT - 1);
rxTail = RX_DESC_COUNT - 1;

// Enable receiver
uint32_t rctl = i219_read(E1000_REG_RCTL);
rctl |= E1000_RCTL_EN; // EN (Receiver Enable)
rctl &= ~E1000_RCTL_SBP; // SBP (Store Pad Packets)
rctl |= E1000_RCTL_BAM; // BAM (Broadcast Accept Mode)
rctl &= ~E1000_RCTL_SZ_4096;
rctl |= E1000_RCTL_SZ_2048; // BSIZE = 2048 (Receive Buffer Size)
rctl &= ~E1000_RCTL_BSEX;
rctl |= E1000_RCTL_SECRC; // SECRC (Strip Ethernet CRC)
i219_write(E1000_REG_RCTL, rctl);


Did anyone encounter a similar issue or is experienced with Intel's way of building drivers? I appreciate any ideas and hints!


Top
 Profile  
 
 Post subject: Re: Receiving packets on the i219-V
PostPosted: Mon Aug 10, 2020 9:09 am 
Offline
Member
Member
User avatar

Joined: Sun Feb 20, 2011 2:01 pm
Posts: 110
Janworks wrote:
Hello,

I am currently working on a driver for the i219-V network card. While there unfortunately is little documentation on its software interface, I was able to figure out most of its functionality using old manuals and Intel's official e1000e driver; after understanding the relation between the PCH and PHY things are quite similar to older e1000 cards. At this point my driver is able to transmit packets on real hardware, as I successfully tested with a hand-crafted ARP packet and Wireshark.

Unfortunately, receiving does not work. I already tried debugging that problem by printing the configuration and status registers; but from my point of view, the respective flags seem to be correct. The various statistics registers did not change, even when I was sure that the card *must* have received a packet (e.g. when getting the ARP response). Manually examing the receive descriptor ring did not show anything, too. Right now it looks like the PHY never receives packets, either because there is some misconfiguration on a very low level or the packet filtering is not properly initialized.

I've already checked with the e1000e driver, but it implements very many features and thus makes it easy to miss something important. Intel's driver seems to be doing a full hardware reset on startup; but since transmitting works already, I hope to avoid this.

I put the working parts of my code into a Wiki article draft; I will be happy to turn it into a full Wiki article, since digging through the documentation took me a lot of time.

The receiving code looks like this:
Code:
// Allocate receive data buffer
uint64_t rxBufferMemPhy;
rxBufferMem = heap_alloc_contiguous(RX_DESC_COUNT * RX_BUFFER_SIZE, VM_R | VM_W, &rxBufferMemPhy);
if(!rxBufferMem)
    panic("Could not allocate i219 receive data buffer.");

// Allocate and initialize receive descriptor buffer
uint64_t rxDescriptorsPhy;
rxDescriptors = heap_alloc_contiguous(RX_DESC_COUNT * sizeof(rx_desc_t), VM_R | VM_W, &rxDescriptorsPhy);
if(!rxDescriptors)
    panic("Could not allocate i219 receive descriptor buffer.");
for(int i = 0; i < RX_DESC_COUNT; ++i)
{
    // Initialize descriptor
    rx_desc_t *currDesc = &rxDescriptors[i];
    currDesc->address = rxBufferMemPhy + i * RX_BUFFER_SIZE;
    currDesc->status = 0;
}

// Pass receive descriptor buffer
i219_write(E1000_REG_RDBAH, rxDescriptorsPhy >> 32);
i219_write(E1000_REG_RDBAL, rxDescriptorsPhy & 0xFFFFFFFF);
i219_write(E1000_REG_RDLEN, RX_DESC_COUNT * sizeof(rx_desc_t));
i219_write(E1000_REG_RDH, 0);
i219_write(E1000_REG_RDT, RX_DESC_COUNT - 1);
rxTail = RX_DESC_COUNT - 1;

// Enable receiver
uint32_t rctl = i219_read(E1000_REG_RCTL);
rctl |= E1000_RCTL_EN; // EN (Receiver Enable)
rctl &= ~E1000_RCTL_SBP; // SBP (Store Pad Packets)
rctl |= E1000_RCTL_BAM; // BAM (Broadcast Accept Mode)
rctl &= ~E1000_RCTL_SZ_4096;
rctl |= E1000_RCTL_SZ_2048; // BSIZE = 2048 (Receive Buffer Size)
rctl &= ~E1000_RCTL_BSEX;
rctl |= E1000_RCTL_SECRC; // SECRC (Strip Ethernet CRC)
i219_write(E1000_REG_RCTL, rctl);


Did anyone encounter a similar issue or is experienced with Intel's way of building drivers? I appreciate any ideas and hints!

I'm up to this point with my i219[v] driver. I did get a report of a packet received, but you'd expect more than one, probably! It should be the reading the Interrupt Cause Register is enough, I think?

_________________
Whoever said you can't do OS development on Windows?
https://github.com/ChaiSoft/ChaiOS


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 2 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 275 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group