21#include "pedigree/kernel/LockGuard.h"
22#include "pedigree/kernel/Log.h"
23#include "pedigree/kernel/machine/Device.h"
24#include "pedigree/kernel/machine/IrqManager.h"
25#include "pedigree/kernel/machine/Machine.h"
26#include "pedigree/kernel/machine/Network.h"
27#include "pedigree/kernel/network/IpAddress.h"
28#include "pedigree/kernel/network/MacAddress.h"
29#include "pedigree/kernel/process/Thread.h"
30#include "pedigree/kernel/processor/IoBase.h"
31#include "pedigree/kernel/processor/Processor.h"
32#include "pedigree/kernel/processor/ProcessorInformation.h"
33#include "pedigree/kernel/time/Time.h"
34#include "pedigree/kernel/utilities/MemoryPool.h"
35#include "pedigree/kernel/utilities/Vector.h"
36#include "pedigree/kernel/utilities/utility.h"
38#include "Ne2kConstants.h"
39#include "modules/system/network-stack/NetworkStack.h"
44constexpr uint8_t CommandPage0Stop = E8390_NODMA | E8390_PAGE0 | E8390_STOP;
45constexpr uint8_t CommandPage0Start = E8390_NODMA | E8390_PAGE0 | E8390_START;
46constexpr uint8_t CommandPage1Stop = E8390_NODMA | E8390_PAGE1 | E8390_STOP;
47constexpr uint8_t CommandPage1Start = E8390_NODMA | E8390_PAGE1 | E8390_START;
48constexpr uint8_t CommandRemoteRead = E8390_RREAD | E8390_PAGE0 | E8390_START;
49constexpr uint8_t CommandRemoteWrite = E8390_RWRITE | E8390_PAGE0 | E8390_START;
50constexpr uint8_t CommandTransmit = E8390_NODMA | E8390_TRANS | E8390_PAGE0 | E8390_START;
52constexpr uint8_t InterruptReceive = 0x01;
53constexpr uint8_t InterruptTransmit = 0x02;
54constexpr uint8_t InterruptReceiveError = 0x04;
55constexpr uint8_t InterruptTransmitError = 0x08;
56constexpr uint8_t InterruptOverflow = 0x10;
57constexpr uint8_t InterruptCounters = 0x20;
58constexpr uint8_t InterruptRemoteDmaComplete = 0x40;
59constexpr uint8_t InterruptReset = 0x80;
60constexpr uint8_t EnabledInterrupts = InterruptReceive | InterruptReceiveError |
61 InterruptTransmitError | InterruptOverflow |
64constexpr size_t RemoteDmaPollLimit = 1000000;
65constexpr size_t ResetPollLimit = 100000;
66constexpr size_t MinimumPacketLength = 14;
67constexpr size_t MaximumPacketLength = 1600;
80 m_NetworkRegistered(false),
93 m_pBase->
write8(0x21, NE_CMD);
97 m_pBase->
write8(0x09, NE_DCR);
98 m_pBase->
write8(0x20, NE_RCR);
99 m_pBase->
write8(0x02, NE_TCR);
102 m_pBase->
write8(0xff, NE_ISR);
103 m_pBase->
write8(0x00, NE_IMR);
106 m_pBase->
write8(0x00, NE_RSAR0);
107 m_pBase->
write8(0x00, NE_RSAR1);
109 m_pBase->
write8(32, NE_RBCR0);
110 m_pBase->
write8(0, NE_RBCR1);
112 m_pBase->
write8(0x0a, NE_CMD);
116 for (i = 0; i < 16; i++)
117 prom[i] = m_pBase->
read16(NE_DATA);
120 m_pBase->
write8(0x61, NE_CMD);
121 for (i = 0; i < 6; i++) {
122 m_StationInfo.mac.setMac(prom[i] & 0xff, i);
123 m_pBase->
write8(prom[i] & 0xff, NE_PAR + i);
126 WARNING(
"NE2K: MAC is " << m_StationInfo.mac[0] <<
":" << m_StationInfo.mac[1] <<
":"
127 << m_StationInfo.mac[2] <<
":" << m_StationInfo.mac[3] <<
":"
128 << m_StationInfo.mac[4] <<
":" << m_StationInfo.mac[5] <<
".");
132 m_pBase->
write8(0x61, NE_CMD);
133 m_pBase->
write8(PAGE_RX + 1, NE_CURR);
135 m_NextPacket = PAGE_RX + 1;
137 m_pBase->
write8(0x21, NE_CMD);
139 m_pBase->
write8(PAGE_RX, NE_PSTART);
140 m_pBase->
write8(PAGE_RX, NE_BNDRY);
141 m_pBase->
write8(PAGE_STOP, NE_PSTOP);
145 m_pBase->
write8(0x14, NE_RCR);
146 m_pBase->
write8(0x00, NE_TCR);
151 uint8_t tmp = m_pBase->
read8(NE_CMD);
152 m_pBase->
write8(tmp | 0x40, NE_CMD);
153 for (i = 0; i < MAR_SIZE; i++)
154 m_pBase->
write8(0xFF, NE_MAR + i);
155 m_pBase->
write8(tmp, NE_CMD);
160 &trampoline,
reinterpret_cast<void*
>(
this));
161 pThread->setName(
"NE2K receive worker");
162 m_ReceiveThread.adopt(pThread);
168 static_cast<IrqHandler*
>(
this),
this, IrqPolicy::pciIntxThreaded());
170 ERROR(
"NE2K: could not register its PCI interrupt");
171 m_pBase->
write8(CommandPage0Stop, NE_CMD);
172 m_pBase->
write8(0x00, NE_IMR);
174 m_ReceiveThread.stop();
179 m_pBase->
write8(0xff, NE_ISR);
180 m_pBase->
write8(EnabledInterrupts, NE_IMR);
183 m_pBase->
write8(CommandPage0Start, NE_CMD);
186 m_NetworkRegistered =
true;
195 m_pBase->
write8(CommandPage0Stop, NE_CMD);
196 m_pBase->
write8(0x00, NE_IMR);
197 m_pBase->
write8(0x00, NE_RBCR0);
198 m_pBase->
write8(0x00, NE_RBCR1);
200 if (m_IrqId && !Machine::instance().getIrqManager()->unregisterHandler(m_IrqId,
this)) {
201 FATAL(
"NE2K teardown could not unregister its IRQ callback.");
205 m_ReceiveThread.stop();
206 if (m_NetworkRegistered) {
208 m_NetworkRegistered =
false;
212 while (m_PacketQueue.count()) {
213 packet* pending = m_PacketQueue.popFront();
224 if (!nBytes || nBytes > MaximumPacketLength) {
225 ERROR(
"NE2K: invalid transmit packet length " <<
Dec << nBytes <<
Hex);
230 if (m_Stopping || !m_IrqId) {
234 const size_t transmitLength = nBytes < 64 ? 64 : nBytes;
235 const size_t dmaLength = (transmitLength + 1) & ~
static_cast<size_t>(1);
239 bool transmitterIdle =
false;
240 for (
size_t transmitPoll = 0; transmitPoll < RemoteDmaPollLimit; ++transmitPoll) {
241 if (!(m_pBase->
read8(NE_CMD) & E8390_TRANS)) {
242 transmitterIdle =
true;
247 if (!transmitterIdle) {
248 ERROR(
"NE2K: transmitter did not become idle");
254 m_pBase->
write8(CommandPage0Start, NE_CMD);
255 m_pBase->
write8(InterruptRemoteDmaComplete, NE_ISR);
256 m_pBase->
write8(0, NE_RSAR0);
257 m_pBase->
write8(PAGE_TX, NE_RSAR1);
258 m_pBase->
write8(dmaLength & 0xff, NE_RBCR0);
259 m_pBase->
write8(dmaLength >> 8, NE_RBCR1);
260 m_pBase->
write8(CommandRemoteWrite, NE_CMD);
262 uint16_t* data =
reinterpret_cast<uint16_t*
>(buffer);
264 for (i = 0; (i + 1) < nBytes; i += 2)
265 m_pBase->
write16(data[i / 2], NE_DATA);
269 const uint8_t* bytes =
reinterpret_cast<const uint8_t*
>(buffer);
270 m_pBase->
write16(bytes[i], NE_DATA);
276 for (; i < dmaLength; i += 2)
280 if (!waitForRemoteDma()) {
281 ERROR(
"NE2K: remote DMA write timed out");
285 m_pBase->
write8(InterruptRemoteDmaComplete, NE_ISR);
288 m_pBase->
write8(transmitLength & 0xff, NE_TBCR0);
289 m_pBase->
write8(transmitLength >> 8, NE_TBCR1);
291 m_pBase->
write8(PAGE_TX, NE_TPSR);
296 m_pBase->
write8(InterruptTransmit | InterruptTransmitError, NE_ISR);
297 m_pBase->
write8(CommandTransmit, NE_CMD);
303bool Ne2k::waitForRemoteDma() {
304 for (
size_t i = 0; i < RemoteDmaPollLimit; ++i) {
305 if (m_pBase->
read8(NE_ISR) & InterruptRemoteDmaComplete) {
313bool Ne2k::resetController() {
314 m_pBase->
write8(CommandPage0Stop, NE_CMD);
315 m_pBase->
write8(0x00, NE_IMR);
317 const uint8_t resetLatch = m_pBase->
read8(NE_RESET);
318 m_pBase->
write8(resetLatch, NE_RESET);
320 bool resetComplete =
false;
321 for (
size_t i = 0; i < ResetPollLimit; ++i) {
322 if (m_pBase->
read8(NE_ISR) & InterruptReset) {
323 resetComplete =
true;
328 if (!resetComplete) {
329 ERROR(
"NE2K: controller reset timed out");
330 m_pBase->
write8(CommandPage0Stop, NE_CMD);
331 m_pBase->
write8(0x00, NE_IMR);
338 m_pBase->
write8(CommandPage0Stop, NE_CMD);
339 m_pBase->
write8(0x09, NE_DCR);
340 m_pBase->
write8(0x00, NE_RBCR0);
341 m_pBase->
write8(0x00, NE_RBCR1);
342 m_pBase->
write8(0x20, NE_RCR);
343 m_pBase->
write8(E8390_TXOFF, NE_TCR);
344 m_pBase->
write8(PAGE_TX, NE_TPSR);
345 m_pBase->
write8(PAGE_RX, NE_PSTART);
346 m_pBase->
write8(PAGE_RX, NE_BNDRY);
347 m_pBase->
write8(PAGE_STOP, NE_PSTOP);
348 m_pBase->
write8(0xff, NE_ISR);
349 m_pBase->
write8(0x00, NE_IMR);
351 m_pBase->
write8(CommandPage1Stop, NE_CMD);
352 for (
size_t i = 0; i < 6; ++i) {
353 m_pBase->
write8(m_StationInfo.mac[i], NE_PAR + i);
355 m_pBase->
write8(PAGE_RX + 1, NE_CURR);
356 for (
size_t i = 0; i < MAR_SIZE; ++i) {
357 m_pBase->
write8(0xff, NE_MAR + i);
360 m_NextPacket = PAGE_RX + 1;
361 m_pBase->
write8(CommandPage0Stop, NE_CMD);
362 m_pBase->
write8(0x14, NE_RCR);
363 m_pBase->
write8(E8390_TXCONFIG, NE_TCR);
364 m_pBase->
write8(0xff, NE_ISR);
365 m_pBase->
write8(EnabledInterrupts, NE_IMR);
366 m_pBase->
write8(CommandPage0Start, NE_CMD);
370bool Ne2k::recoverReceiveOverflow(uint8_t irqStatus) {
371 const bool wasTransmitting = (m_pBase->
read8(NE_CMD) & E8390_TRANS) != 0;
376 m_pBase->
write8(CommandPage0Stop, NE_CMD);
377 if (!Time::delay(10 * Time::Multiplier::Millisecond)) {
378 return resetController();
380 m_pBase->
write8(0x00, NE_RBCR0);
381 m_pBase->
write8(0x00, NE_RBCR1);
383 const uint8_t completion =
384 (irqStatus | m_pBase->
read8(NE_ISR)) & (InterruptTransmit | InterruptTransmitError);
385 const bool resend = wasTransmitting && !completion;
389 m_pBase->
write8(irqStatus & ~InterruptOverflow, NE_ISR);
390 m_pBase->
write8(completion, NE_ISR);
391 m_pBase->
write8(E8390_TXOFF, NE_TCR);
392 m_pBase->
write8(CommandPage0Start, NE_CMD);
395 return resetController();
398 m_pBase->
write8(InterruptOverflow, NE_ISR);
399 m_pBase->
write8(E8390_TXCONFIG, NE_TCR);
401 m_pBase->
write8(CommandTransmit, NE_CMD);
406void Ne2k::advanceReceiveBoundary(uint8_t nextPacket) {
407 m_NextPacket = nextPacket;
408 m_pBase->
write8((m_NextPacket == PAGE_RX) ? (PAGE_STOP - 1) : (m_NextPacket - 1), NE_BNDRY);
412 constexpr size_t RingPageCount = PAGE_STOP - PAGE_RX;
414 for (
size_t packets = 0; packets < RingPageCount; ++packets) {
417 m_pBase->
write8(CommandPage1Start, NE_CMD);
418 const uint8_t current = m_pBase->
read8(NE_CURR);
419 m_pBase->
write8(CommandPage0Start, NE_CMD);
420 if (current < PAGE_RX || current >= PAGE_STOP) {
421 ERROR(
"NE2K: receive ring reported an invalid current page");
424 if (m_NextPacket == current) {
429 m_pBase->
write8(InterruptRemoteDmaComplete, NE_ISR);
430 m_pBase->
write8(0, NE_RSAR0);
431 m_pBase->
write8(m_NextPacket, NE_RSAR1);
432 m_pBase->
write8(4, NE_RBCR0);
433 m_pBase->
write8(0, NE_RBCR1);
434 m_pBase->
write8(CommandRemoteRead, NE_CMD);
437 const uint16_t status = m_pBase->
read16(NE_DATA);
438 const uint16_t rawLength = m_pBase->
read16(NE_DATA);
439 if (!waitForRemoteDma()) {
440 ERROR(
"NE2K: receive header DMA timed out");
443 m_pBase->
write8(InterruptRemoteDmaComplete, NE_ISR);
445 const uint8_t nextPacket = status >> 8;
446 const bool nextInRing = nextPacket >= PAGE_RX && nextPacket < PAGE_STOP;
447 const bool validLength = rawLength >= 4 + MinimumPacketLength &&
448 (
static_cast<size_t>(rawLength) - 4) <= MaximumPacketLength;
449 bool validNext =
false;
450 if (nextInRing && validLength) {
454 size_t expected = m_NextPacket + 1 + (
static_cast<size_t>(rawLength) >> 8);
455 while (expected >= PAGE_STOP) {
456 expected -= RingPageCount;
458 size_t roundedExpected = expected + 1;
459 if (roundedExpected >= PAGE_STOP) {
460 roundedExpected = PAGE_RX;
462 validNext = nextPacket == expected || nextPacket == roundedExpected;
464 const bool receiveOk = (status & InterruptReceive) != 0;
465 if (!validNext || !validLength || !receiveOk) {
466 WARNING(
"NE2K: dropping corrupt receive-ring entry (status="
467 <<
Hex << status <<
", length=" <<
Dec << rawLength <<
Hex <<
")");
470 advanceReceiveBoundary((validNext && validLength) ? nextPacket : current);
475 const uint16_t length = rawLength - 4;
478 const uint16_t dmaLength = (length + 1) & ~
static_cast<uint16_t
>(1);
483 advanceReceiveBoundary(nextPacket);
486 uint16_t* packBuffer =
reinterpret_cast<uint16_t*
>(tmp);
487 ByteSet(tmp, 0, length);
489 m_pBase->
write8(InterruptRemoteDmaComplete, NE_ISR);
490 m_pBase->
write8(4, NE_RSAR0);
491 m_pBase->
write8(m_NextPacket, NE_RSAR1);
492 m_pBase->
write8(dmaLength & 0xff, NE_RBCR0);
493 m_pBase->
write8(dmaLength >> 8, NE_RBCR1);
494 m_pBase->
write8(CommandRemoteRead, NE_CMD);
497 int i, words = length / 2, oddbytes = length % 2;
498 for (i = 0; i < words; ++i)
499 packBuffer[i] = m_pBase->
read16(NE_DATA);
501 for (i = 0; i < oddbytes; ++i)
502 tmp[(length - oddbytes) + i] =
503 m_pBase->
read16(NE_DATA) & 0xFF;
506 if (!waitForRemoteDma()) {
507 ERROR(
"NE2K: receive payload DMA timed out");
509 advanceReceiveBoundary(nextPacket);
512 m_pBase->
write8(InterruptRemoteDmaComplete, NE_ISR);
514 advanceReceiveBoundary(nextPacket);
517 packet* p =
new packet;
518 p->ptr =
reinterpret_cast<uintptr_t
>(packBuffer);
521#ifdef NE2K_NO_THREADS
532 m_PacketQueue.pushBack(p);
539 WARNING(
"NE2K: receive ring drain exceeded its page budget");
543int Ne2k::trampoline(
void* p) {
544 Ne2k* pNe =
reinterpret_cast<Ne2k*
>(p);
545 pNe->receiveThread();
549void Ne2k::receiveThread() {
552 if (!m_PacketQueueSize.
acquire()) {
563 p = m_PacketQueue.popFront();
568 if (!p->ptr || !p->len) {
587 if (m_StationInfo.dnsServers)
588 delete[] m_StationInfo.dnsServers;
591 m_StationInfo.ipv4 = info.ipv4;
592 NOTICE(
"NE2K: Setting ipv4, " << info.ipv4.toString() <<
", " << m_StationInfo.ipv4.toString()
595 m_StationInfo.ipv6 = info.ipv6;
596 m_StationInfo.nIpv6Addresses = info.nIpv6Addresses;
597 NOTICE(
"NE2K: Copied " << info.nIpv6Addresses <<
" IPv6 addresses.");
599 m_StationInfo.subnetMask = info.subnetMask;
600 NOTICE(
"NE2K: Setting subnet mask, " << info.subnetMask.toString() <<
", "
601 << m_StationInfo.subnetMask.toString() <<
"...");
602 m_StationInfo.
gateway = info.gateway;
603 NOTICE(
"NE2K: Setting gateway, " << info.gateway.toString() <<
", "
604 << m_StationInfo.
gateway.toString() <<
"...");
607 m_StationInfo.dnsServers = info.dnsServers;
610 <<
" servers being set]...");
616 return m_StationInfo;
620 constexpr size_t PassLimit = 8;
621 bool handled =
false;
626 return IrqDisposition::NotHandled;
628 for (
size_t pass = 0; pass < PassLimit; ++pass) {
629 const uint8_t irqStatus = m_pBase->
read8(NE_ISR) & EnabledInterrupts;
635 if (irqStatus & InterruptOverflow) {
636 WARNING(
"NE2K: Receive buffer overflow");
637 if (!recoverReceiveOverflow(irqStatus)) {
638 ERROR(
"NE2K: receive overflow recovery failed");
645 m_pBase->
write8(irqStatus, NE_ISR);
647 if (irqStatus & (InterruptReceive | InterruptReceiveError)) {
652 if (irqStatus & InterruptTransmitError) {
653 WARNING(
"NE2K: Packet transmit failed!");
655 if (irqStatus & InterruptCounters) {
656 WARNING(
"NE2K: Counter overflow");
660 return handled ? IrqDisposition::Handled : IrqDisposition::NotHandled;
virtual void setSpecificType(String str)
Vector< Address * > m_Addresses
Device * getParent() const
virtual uintptr_t getInterruptNumber()
virtual uint8_t read8(size_t offset=0)=0
virtual void write8(uint8_t value, size_t offset=0)=0
virtual void write16(uint16_t value, size_t offset=0)=0
virtual uint16_t read16(size_t offset=0)=0
virtual irq_id_t registerPciIrqHandler(IrqHandler *handler, Device *pDevice, const IrqPolicy &policy)=0
void free(uintptr_t buffer)
Frees an allocated buffer, allowing it to be used elsewhere.
virtual const StationInfo & getStationInfo()
virtual bool send(size_t nBytes, uintptr_t buffer)
virtual IrqDisposition irq(irq_id_t number)
virtual bool setStationInfo(const StationInfo &info)
MemoryPool & getMemPool()
void deRegisterDevice(Network *pDevice)
static NetworkStack & instance()
void receive(size_t nBytes, uintptr_t packet, Network *pCard, uint32_t offset)
void registerDevice(Network *pDevice)
static ProcessorInformation & information()
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
size_t nDnsServers
Can contain IPv6 addresses.
IpAddress gateway
Automatically calculated?
@ Continue
No unwind necessary, carry on as normal.