Intel Ethernet i217: Difference between revisions

no edit summary
[unchecked revision][unchecked revision]
No edit summary
No edit summary
Line 394:
 
}
</source>
 
 
As we have defined most of the building blocks and the helper methods lets define the main methods of the class.
 
The constructor is responsible for fetching PCI related data and initialize the object internal state
 
<source lang="c">
E1000::E1000(PCIConfigHeader * p_pciConfigHeader) : NetworkDriver(p_pciConfigHeader)
{
// Get BAR0 type, io_base address and MMIO base address
bar_type = pciConfigHeader->getPCIBarType(0);
io_base = pciConfigHeader->getPCIBar(PCI_BAR_IO) & ~1;
mem_base = pciConfigHeader->getPCIBar( PCI_BAR_MEM) & ~3;
// Off course you will need here to map the memory address into you page tables and use corresponding virtual addresses
 
// Enable bus mastering
pciConfigHeader->enablePCIBusMastering();
eerprom_exists = false;
}
</source>
 
The start method basically detects the EEPROM, reads the MAC addresses, setup rx and tx buffers, register the interrupt handler, and enable NIC interrupts
 
 
<source lang="c">
 
bool E1000::start ()
{
detectEEProm ();
if (! readMACAddress()) return false;
printMac();
startLink();
for(int i = 0; i < 0x80; i++)
writeCommand(0x5200 + i*4, 0);
if ( interruptManager->registerInterrupt(IRQ0+pciConfigHeader->getIntLine(),this))
{
enableInterrupt();
rxinit();
txinit();
video.putString("E1000 card started\n",COLOR_RED,COLOR_WHITE);
return true;
}
else return false;
}
 
 
</source>
 
 
Your interrupt handler should eventually call the fire method which handles the NIC's events
<source lang="c">
 
void E1000::fire (InterruptContext * p_interruptContext)
{
if ( coreManager->getCurrentCoreId() == 0 && p_interruptContext->getInteruptNumber() == pciConfigHeader->getIntLine()+IRQ0)
{
uint32_t status = readCommand(0xc0);
if(status & 0x04)
{
startLink();
}
 
if(status & 0x10)
{
// good threshold
}
if(status & 0x80)
{
handleReceive();
}
}
}
 
void E1000::handleReceive()
{
uint16_t old_cur;
bool got_packet = false;
while((rx_descs[rx_cur]->status & 0x1))
{
got_packet = true;
uint8_t *buf = (uint8_t *)rx_descs[rx_cur]->addr;
uint16_t len = rx_descs[rx_cur]->length;
 
// Here you should inject the received packet into your network stack
 
 
rx_descs[rx_cur]->status = 0;
old_cur = rx_cur;
rx_cur = (rx_cur + 1) % E1000_NUM_RX_DESC;
writeCommand(REG_RXDESCTAIL, old_cur );
}
}
 
</source>
Anonymous user