65 #include "3Com90xConstants.h" 66 #include "modules/system/network-stack/NetworkStack.h" 67 #include "pedigree/kernel/Log.h" 68 #include "pedigree/kernel/machine/Device.h" 69 #include "pedigree/kernel/machine/IrqManager.h" 70 #include "pedigree/kernel/machine/Machine.h" 71 #include "pedigree/kernel/machine/Network.h" 72 #include "pedigree/kernel/network/IpAddress.h" 73 #include "pedigree/kernel/network/MacAddress.h" 74 #include "pedigree/kernel/process/Thread.h" 75 #include "pedigree/kernel/processor/IoBase.h" 76 #include "pedigree/kernel/processor/PhysicalMemoryManager.h" 77 #include "pedigree/kernel/processor/Processor.h" 78 #include "pedigree/kernel/processor/ProcessorInformation.h" 79 #include "pedigree/kernel/processor/VirtualAddressSpace.h" 80 #include "pedigree/kernel/utilities/Vector.h" 81 #include "pedigree/kernel/utilities/utility.h" 93 m_pBase->
write16(val, regCommandIntStatus_w);
96 while (m_pBase->
read16(regCommandIntStatus_w) & INT_CMDINPROGRESS)
105 if (m_CurrentWindow == window)
110 m_CurrentWindow = window;
123 while ((1 << 15) & m_pBase->
read16(regEepromCommand_0_w))
127 m_pBase->
write16(address + (0x02 << 6), regEepromCommand_0_w);
128 while ((1 << 15) & m_pBase->
read16(regEepromCommand_0_w))
130 val = m_pBase->
read16(regEepromData_0_w);
141 while ((1 << 15) & m_pBase->
read16(regEepromCommand_0_w))
145 m_pBase->
write16(0x30, regEepromCommand_0_w);
146 while ((1 << 15) & m_pBase->
read16(regEepromCommand_0_w))
150 m_pBase->
write16(address + (0x03 << 6), regEepromCommand_0_w);
151 while ((1 << 15) & m_pBase->
read16(regEepromCommand_0_w))
155 m_pBase->
write16(value, regEepromData_0_w);
156 m_pBase->
write16(0x30, regEepromCommand_0_w);
157 while ((1 << 15) & m_pBase->
read16(regEepromCommand_0_w))
161 m_pBase->
write16(address + (0x01 << 6), regEepromCommand_0_w);
162 while ((1 << 15) & m_pBase->
read16(regEepromCommand_0_w))
172 int maxAddress, cksumAddress;
190 for (i = 0; i <= maxAddress; i++)
194 cksum ^= ((v >> 8) & 0xff);
206 #ifdef CFG_3C90X_PRESERVE_XCVR 211 cfg = m_pBase->
read32(regInternalConfig_3_l);
215 NOTICE(
"3C90x: Issuing RESET");
219 while (m_pBase->
read16(regCommandIntStatus_w) & INT_CMDINPROGRESS)
226 m_pBase->
write16(0, regStationAddress_2_3w + 0);
227 m_pBase->
write16(0, regStationAddress_2_3w + 2);
228 m_pBase->
write16(0, regStationAddress_2_3w + 4);
230 #ifdef CFG_3C90X_PRESERVE_XCVR 233 m_pBase->
write32(cfg, regInternalConfig_3_l);
236 if ((cfg & 0x0300) == 0x0300)
242 while (m_pBase->
read16(regCommandIntStatus_w) & INT_CMDINPROGRESS)
246 m_pBase->
write8(0x01, regTxFreeThresh_b);
256 while (m_pBase->
read16(regCommandIntStatus_w) & INT_CMDINPROGRESS)
273 m_pBase->
read16(regCommandIntStatus_w);
274 m_pBase->
read16(regCommandIntStatus_w);
275 while (m_pBase->
read16(regCommandIntStatus_w) & INT_CMDINPROGRESS)
278 physical_uintptr_t destPtr = m_pTxBuffPhys;
281 reinterpret_cast<void *>(buffer)))
284 reinterpret_cast<void *>(buffer), destPtr, dud);
285 destPtr += buffer & 0xFFF;
288 MemoryCopy(m_pTxBuffVirt, reinterpret_cast<void *>(buffer), nBytes);
291 m_TransmitDPD->DnNextPtr = 0;
294 m_TransmitDPD->FrameStartHeader = nBytes | 0x8000;
297 m_TransmitDPD->DataAddr =
static_cast<uint32_t
>(
299 m_TransmitDPD->DataLength =
300 (nBytes ) + (1U << 31U);
303 m_pBase->
write32(m_pDPD, regDnListPtr_l);
307 while (m_pBase->
read32(regDnListPtr_l) != 0)
317 m_pRxBuffVirt(0), m_pTxBuffVirt(0), m_pRxBuffPhys(0), m_pTxBuffPhys(0),
318 m_RxBuffMR(
"3c90x-rxbuffer"), m_TxBuffMR(
"3c90x-txbuffer"), m_pDPD(0),
319 m_DPDMR(
"3c90x-dpd"), m_pUPD(0), m_UPDMR(
"3c90x-upd"), m_TransmitDPD(0),
320 m_ReceiveUPD(0), m_RxMutex(0), m_TxMutex(0), m_PendingPackets()
325 uint16_t eeprom[0x21];
330 #define HWADDR_OFFSET 10 334 m_RxBuffMR, (MAX_PACKET_SIZE / 0x1000) + 1,
337 ERROR(
"3C90x: Couldn't allocate Rx Buffer!");
341 m_TxBuffMR, (MAX_PACKET_SIZE / 0x1000) + 1,
344 ERROR(
"3C90x: Couldn't allocate Tx Buffer!");
347 m_pRxBuffVirt =
static_cast<uint8_t *
>(m_RxBuffMR.
virtualAddress());
348 m_pTxBuffVirt =
static_cast<uint8_t *
>(m_TxBuffMR.
virtualAddress());
356 ERROR(
"3C90x: Couldn't allocated buffer for DPD\n");
363 ERROR(
"3C90x: Couldn't allocated buffer for UPD\n");
373 for (
size_t iUpd = 0; iUpd < NUM_UPDS; iUpd++)
375 if ((iUpd + 1) == NUM_UPDS)
376 m_ReceiveUPD[iUpd].UpNextPtr = 0;
378 m_ReceiveUPD[iUpd].UpNextPtr = m_pUPD + ((iUpd + 1) *
sizeof(
RXD));
379 m_ReceiveUPD[iUpd].UpPktStatus = 0;
380 m_ReceiveUPD[iUpd].DataAddr = m_pRxBuffPhys + (iUpd * 1536);
381 m_ReceiveUPD[iUpd].DataLength = 1536 + (1U << 31U);
387 m_CurrentWindow = 255;
415 for (i = 0; i < 0x20; i++)
418 #ifdef CFG_3C90X_BOOTROM_FIX 424 #ifdef CFG_3C90X_XCVR 426 if (CFG_3C90X_XCVR == 255)
433 writeEeprom(0x16, XCVR_MAGIC + ((CFG_3C90X_XCVR) &0x000F));
438 for (i = 0; i < 0x17; i++)
443 m_StationInfo.mac.setMac(eeprom,
true);
445 "3C90x MAC: " << m_StationInfo.mac[0] <<
":" << m_StationInfo.mac[1]
446 <<
":" << m_StationInfo.mac[2] <<
":" 447 << m_StationInfo.mac[3] <<
":" << m_StationInfo.mac[4]
448 <<
":" << m_StationInfo.mac[5] <<
".");
452 mstat = m_pBase->
read16(regMediaStatus_4_w);
453 if ((mstat & (1 << 11)) == 0)
455 ERROR(
"3C90x: Valid link not established");
462 HOST_TO_BIG16(eeprom[HWADDR_OFFSET + 0]), regStationAddress_2_3w);
464 HOST_TO_BIG16(eeprom[HWADDR_OFFSET + 1]), regStationAddress_2_3w + 2);
466 HOST_TO_BIG16(eeprom[HWADDR_OFFSET + 2]), regStationAddress_2_3w + 4);
467 m_pBase->
write16(0, regStationMask_2_3w);
468 m_pBase->
write16(0, regStationMask_2_3w + 2);
469 m_pBase->
write16(0, regStationMask_2_3w + 4);
478 mopt = m_pBase->
read16(regResetMediaOptions_3_w);
484 NOTICE(
"3C90x connectors present:");
489 NOTICE(((c++) ?
", " :
"") <<
"100BASE-T4");
494 NOTICE(((c++) ?
", " :
"") <<
"100BASE-FX");
499 NOTICE(((c++) ?
", " :
"") <<
"10BASE2");
504 NOTICE(((c++) ?
", " :
"") <<
"AUI");
509 NOTICE(((c++) ?
", " :
"") <<
"MII");
512 if ((mopt & 0xA) == 0xA)
514 NOTICE(((c++) ?
", " :
"") <<
"10BASE-T / 100BASE-TX");
517 else if ((mopt & 0xa) == 0x2)
519 NOTICE(((c++) ?
", " :
"") <<
"100BASE-TX");
522 else if ((mopt & 0xa) == 0x8)
524 NOTICE(((c++) ?
", " :
"") <<
"10BASE-T");
533 if ((eeprom[0x16] & 0xff00) == XCVR_MAGIC)
534 linktype = eeprom[0x16] & 0x000f;
538 #ifdef CFG_3C90X_XCVR 539 if (CFG_3C90X_XCVR != 255)
540 linktype = CFG_3C90X_XCVR;
543 if (linktype == 0x0009)
546 WARNING(
"3C90x: MII External MAC mode only supported on " 547 "B-revision cards! Falling back to MII mode.");
553 if (linktype == 0x0003)
558 cfg = m_pBase->
read32(regInternalConfig_3_l);
560 cfg |= (linktype << 20);
561 m_pBase->
write32(cfg, regInternalConfig_3_l);
565 while (m_pBase->
read16(regCommandIntStatus_w) & INT_CMDINPROGRESS)
569 m_pBase->
write8(0x01, regTxFreeThresh_b);
579 while (m_pBase->
read16(regCommandIntStatus_w) & INT_CMDINPROGRESS)
593 m_pBase->
write32(m_pUPD, regUpListPtr_l);
599 reinterpret_cast<void *>(
this));
609 Nic3C90x::~Nic3C90x()
613 int Nic3C90x::trampoline(
void *p)
616 pNic->receiveThread();
620 void Nic3C90x::receiveThread()
631 uintptr_t currUpdPhys =
632 reinterpret_cast<uintptr_t
>(m_PendingPackets.
popFront());
634 if (currUpdPhys != 0)
636 uintptr_t myOffset = (currUpdPhys - m_pUPD);
637 myNum = (myOffset /
sizeof(
RXD)) - 1;
640 myNum = NUM_UPDS - 1;
641 RXD *usedUpd = &m_ReceiveUPD[myNum];
643 if (usedUpd->UpPktStatus & (1 << 14))
647 "3C90x: error, UpPktStatus = " << usedUpd->UpPktStatus <<
".");
651 size_t packLen = usedUpd->UpPktStatus & 0x1FFF;
655 reinterpret_cast<uintptr_t>(m_pRxBuffVirt + (myNum * 1536)),
this,
659 usedUpd->UpPktStatus = 0;
662 if (currUpdPhys == 0)
663 m_pBase->
write32(m_pUPD, regUpListPtr_l);
674 uint16_t status = m_pBase->
read16(regCommandIntStatus_w);
677 if ((status & ENABLED_INTS) == 0)
681 issueCommand(cmdAcknowledgeInterrupt, (status & ENABLED_INTS));
684 if (status & INT_UPCOMPLETE)
687 reinterpret_cast<void *
>(m_pBase->
read32(regUpListPtr_l));
688 m_PendingPackets.
pushBack(currPhys);
692 if (status & INT_TXCOMPLETE)
696 uint8_t txStatus = m_pBase->
read8(regTxStatus_b);
699 m_pBase->
write8(0, regTxStatus_b);
701 if ((txStatus & 0xbf) == 0x80)
706 ERROR(
"3C90x: TX Reclaim Error");
709 else if (txStatus & 0x04)
711 ERROR(
"3C90x: TX Status Overflow");
712 for (
int i = 0; i < 32; i++)
713 m_pBase->
write8(0, regTxStatus_b);
716 else if (txStatus & 0x08)
718 ERROR(
"3C90x: TX Max Collisions");
721 else if (txStatus & 0x10)
723 ERROR(
"3C90x: TX Underrun");
726 else if (txStatus & 0x20)
728 ERROR(
"3C90x: TX Jabber");
731 else if ((txStatus & 0x80) != 0x80)
733 ERROR(
"3C90x: Internal Error - Incomplete Transmission");
738 if (status & INT_HOSTERROR)
744 if (status & INT_UPDATESTATS)
745 NOTICE(
"UpdateStats IRQ");
764 if (m_StationInfo.dnsServers)
765 delete[] m_StationInfo.dnsServers;
768 m_StationInfo.ipv4 = info.ipv4;
770 "3C90x: Setting ipv4, " << info.ipv4.toString() <<
", " 771 << m_StationInfo.ipv4.toString() <<
"...");
772 m_StationInfo.ipv6 = info.ipv6;
774 m_StationInfo.subnetMask = info.subnetMask;
776 "3C90x: Setting subnet mask, " << info.subnetMask.toString() <<
", " 777 << m_StationInfo.subnetMask.toString()
781 "3C90x: Setting gateway, " << info.
gateway.toString() <<
", " 782 << m_StationInfo.
gateway.toString()
786 m_StationInfo.dnsServers = info.dnsServers;
789 "3C90x: Setting DNS servers [" <<
Dec << m_StationInfo.
nDnsServers 790 <<
Hex <<
" servers being set]...");
797 return m_StationInfo;
virtual bool irq(irq_id_t number, InterruptState &state)
int setWindow(int window)
void pushBack(const T &value)
static PhysicalMemoryManager & instance()
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
static const size_t continuous
int issueCommand(int cmd, int param)
virtual void write8(uint8_t value, size_t offset=0)=0
virtual uint16_t read16(size_t offset=0)=0
IpAddress gateway
Automatically calculated?
virtual const StationInfo & getStationInfo()
static ProcessorInformation & information()
virtual uintptr_t getInterruptNumber()
void receive(size_t nBytes, uintptr_t packet, Network *pCard, uint32_t offset)
size_t nDnsServers
Can contain IPv6 addresses.
virtual void write16(uint16_t value, size_t offset=0)=0
static const size_t Write
virtual void setSpecificType(String str)
virtual uint32_t read32(size_t offset=0)=0
uint16_t readEeprom(int address)
physical_uintptr_t physicalAddress() const
int writeEeprom(int address, uint16_t value)
int writeEepromWord(int address, uint16_t value)
static NetworkStack & instance()
void registerDevice(Network *pDevice)
virtual bool send(size_t nBytes, uintptr_t buffer)
Vector< Address * > m_Addresses
virtual irq_id_t registerIsaIrqHandler(uint8_t irq, IrqHandler *handler, bool bEdge=false)=0
virtual uint8_t read8(size_t offset=0)=0
virtual bool setStationInfo(const StationInfo &info)
void * virtualAddress() const
virtual void write32(uint32_t value, size_t offset=0)=0
Device * getParent() const