Intel Ethernet i217: Difference between revisions
Jump to navigation
Jump to search
[unchecked revision] | [unchecked revision] |
Content deleted Content added
No edit summary |
No edit summary |
||
Line 394: | 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> |
</source> |