First public contribution.
1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of the License "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // e32\drivers\ethernet\d_ethernet.cpp
15 // LDD the ethernet which has no power managment and is not PCCard based
23 #include <drivers/ethernet.h>
24 #include <kernel/kern_priv.h>
29 _LIT(KLddName,"Ethernet");
32 const TUint8 ETHER2_TYPE_IP_MSB = 0x08;
33 const TUint8 ETHER2_TYPE_IP_LSB = 0x00;
34 const TUint8 IP_TYPE_TCP = 0x06;
36 static TBool IsTcp(TDesC8 &aFrame)
38 return (aFrame[12] == ETHER2_TYPE_IP_MSB && aFrame[13] == ETHER2_TYPE_IP_LSB && aFrame[23] == IP_TYPE_TCP);
41 static TInt GetTcpSeqNumber(TDesC8 &aFrame)
45 seqNum = aFrame[38] << 24 | aFrame[39] << 16 | aFrame[40] << 8| aFrame[41];
49 static TInt GetTcpAckNumber(TDesC8 &aFrame)
53 ackNum = aFrame[42] << 24 | aFrame[43] << 16 | aFrame[44] << 8| aFrame[45];
58 DDeviceEthernet::DDeviceEthernet()
61 __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::DDeviceEthernet()"));
62 iParseMask=KDeviceAllowAll;
63 iUnitsMask=0xffffffff; // Leave units decision to the PDD
64 iVersion=TVersion(KEthernetMajorVersionNumber,
65 KEthernetMinorVersionNumber,
66 KEthernetBuildVersionNumber);
70 TInt DDeviceEthernet::Install()
71 // Install the device driver.
73 __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::Install()"));
74 return(SetName(&KLddName));
78 void DDeviceEthernet::GetCaps(TDes8& aDes) const
79 // Return the Ethernet capabilities.
81 __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::GetCaps(TDes8& aDes) const"));
82 TPckgBuf<TCapsDevEthernetV01> b;
83 b().version=TVersion(KEthernetMajorVersionNumber,
84 KEthernetMinorVersionNumber,
85 KEthernetBuildVersionNumber);
86 Kern::InfoCopy(aDes,b);
90 TInt DDeviceEthernet::Create(DLogicalChannelBase*& aChannel)
91 // Create a channel on the device.
93 __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::Create(DLogicalChannelBase*& aChannel)"));
94 aChannel=new DChannelEthernet;
96 return aChannel?KErrNone:KErrNoMemory;
100 DChannelEthernet::DChannelEthernet()
102 : iRxCompleteDfc(CompleteRxDfc, this, 2)
104 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DChannelEthernet()"));
106 // Setup the default config
107 iConfig.iEthSpeed = KEthSpeed10BaseT;
108 iConfig.iEthDuplex = KEthDuplexHalf;
109 iConfig.iEthAddress[0] = 0x00;
110 iConfig.iEthAddress[1] = 0x00;
111 iConfig.iEthAddress[2] = 0x00;
112 iConfig.iEthAddress[3] = 0x00;
113 iConfig.iEthAddress[4] = 0x00;
114 iConfig.iEthAddress[5] = 0x00;
118 iClient=&Kern::CurrentThread();
119 // Increse the Dthread's ref count so that it does not close without us
124 DChannelEthernet::~DChannelEthernet()
127 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::~DChannelEthernet()"));
128 Kern::DestroyClientRequest(iWriteRequest);
129 Kern::DestroyClientBufferRequest(iReadRequest);
130 // decrement it's reference count
131 Kern::SafeClose((DObject*&)iClient, NULL);
135 void DChannelEthernet::Complete(TInt aMask, TInt aReason)
137 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete(TInt aMask, TInt aReason)"));
140 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete iReadRequest"));
141 if (iReadRequest->IsReady())
143 Kern::QueueBufferRequestComplete(iClient, iReadRequest, aReason);
148 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete iWriteRequest"));
149 __KTRACE_OPT(KNETWORK2, Kern::Printf(" >ldd tx: PRE complete reason=%d iClient=%08x iTxStatus=%08x\n", aReason, iClient, iWriteRequest->StatusPtr()));
150 Kern::QueueRequestComplete(iClient, iWriteRequest, aReason);
155 void DChannelEthernet::Shutdown()
157 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::Shutdown()"));
159 // Suspend the chip and disable interrupts
160 (static_cast<DEthernet*>(iPdd))->Stop(EStopNormal);
162 Complete(EAll, KErrAbort);
164 if (iRxCompleteDfc.Queued())
166 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Shutdown()- Cancelling old dfc"));
167 // Ethernet interrupts are disabled; must make sure DFCs are not queued.
168 iRxCompleteDfc.Cancel();
171 // No harm in doing this
172 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Shutdown()- Completing message"));
173 iMsgQ.iMessage->Complete(KErrNone,EFalse);
177 TInt DChannelEthernet::DoCreate(TInt aUnit,
178 const TDesC8* /*anInfo*/,
179 const TVersion &aVer)
180 // Create the channel from the passed info.
182 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
184 if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ENET.LDD (Ethernet Driver)")))
185 return KErrPermissionDenied;
187 if (!Kern::QueryVersionSupported(TVersion(KEthernetMajorVersionNumber,
188 KEthernetMinorVersionNumber,
189 KEthernetBuildVersionNumber),
191 return KErrNotSupported;
193 TInt r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
197 r = Kern::CreateClientRequest(iWriteRequest);
201 SetDfcQ(((DEthernet*)iPdd)->DfcQ(aUnit));
202 iRxCompleteDfc.SetDfcQ(iDfcQ);
205 ((DEthernet *)iPdd)->iLdd=this;
207 //Get config from the device
208 ((DEthernet *)iPdd)->GetConfig(iConfig);
210 PddCheckConfig(iConfig);
215 void DChannelEthernet::Start()
216 // Start the driver receiving.
218 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Start()"));
219 if (iStatus!=EClosed)
227 void DChannelEthernet::ReceiveIsr()
228 // Copies data into the iFifo's buffers
230 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()"));
231 TBuf8<KMaxEthernetPacket+32> * buffer;
234 buffer = iFIFO.GetFree();
237 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()- Dropping a frame"));
238 /*err =*/ PddReceive(*buffer, EFalse); //Need to call as must drain RX buffer
239 // Should something be done about returned errors?
243 /*err =*/ PddReceive(*buffer, ETrue);
244 // Should something be done about returned errors?
246 // Add another DFc as we have a buffer and is not already queued
247 if (!iRxCompleteDfc.Queued())
249 if (NKern::CurrentContext()==NKern::EInterrupt)
250 iRxCompleteDfc.Add();
252 iRxCompleteDfc.Enque();
256 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()- DFC already added"));
260 void DChannelEthernet::CompleteRxDfc(TAny* aPtr)
262 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::CompleteRxDfc(TAny* aPtr)"));
263 DChannelEthernet *pC=(DChannelEthernet*)aPtr;
268 void DChannelEthernet::DoCompleteRx()
270 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()"));
271 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr triggered..."));
274 if (iReadRequest->IsReady())
276 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()- Read waiting"));
277 TBuf8<KMaxEthernetPacket+32> * buffer;
279 buffer = iFIFO.GetNext();
282 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()- Unexpected read request earlier"));
283 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - miss = empty"));
284 Complete(ERx, KErrNone);
288 // RX buffer has data, must scan buffer and then complete
289 TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, *(const TDesC8*)buffer, 0, KChunkShiftBy0, iClient);
291 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - hit = rx tcp seq=%u ack=%u\n", GetTcpSeqNumber(*buffer), GetTcpAckNumber(*buffer)) );
296 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - skipped! no request pending\n"));
301 //Override sendMsg to allow data copy in the context of client thread for WDP.
302 TInt DChannelEthernet::SendMsg(TMessageBase* aMsg)
304 TThreadMessage& m = *(TThreadMessage*)aMsg;
307 if (id != (TInt)ECloseMsg && id != KMaxTInt)
311 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
312 r = SendRequest(aMsg);
315 Kern::RequestComplete(pS,r);
320 r = SendControl(aMsg);
325 r = DLogicalChannel::SendMsg(aMsg);
331 TInt DChannelEthernet::SendControl(TMessageBase* aMsg)
333 TThreadMessage& m = *(TThreadMessage*)aMsg;
337 TEthernetConfigV01 config;
343 case RBusDevEthernet::EControlConfig:
346 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlConfig"));
347 Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
348 if((TUint)bufMaxLen < sizeof(TEthernetConfigV01))
350 return KErrUnderflow;
355 case RBusDevEthernet::EControlCaps:
357 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlCaps"));
358 Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
359 if((TUint)bufMaxLen < sizeof(caps))
361 return KErrUnderflow;
366 case RBusDevEthernet::EControlSetConfig:
367 case RBusDevEthernet::EControlSetMac:
369 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlSetConfig"));
370 Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
371 if((TUint)bufLen > sizeof(config))
375 memset(&config,0,sizeof(config));
376 TPtr8 cfg((TUint8*)&config,0,sizeof(config));
377 Kern::KUDesGet(*(TDes8*)&cfg, *(const TDesC8*)a1);
378 m.iArg[0] = (TAny*)&config;
382 return KErrNotSupported;
384 r = DLogicalChannel::SendMsg(aMsg);
389 case RBusDevEthernet::EControlConfig:
391 Kern::InfoCopy(*(TDes8*)a1, (const TUint8*)&config, sizeof(TEthernetConfigV01));
394 case RBusDevEthernet::EControlCaps:
396 Kern::KUDesPut(*(TDes8*)a1, (const TDesC8&)caps);
403 TInt DChannelEthernet::SendRequest(TMessageBase* aMsg)
405 TThreadMessage& m = *(TThreadMessage*)aMsg;
407 TRequestStatus* pS = (TRequestStatus*)m.Ptr0();
413 case RBusDevEthernet::ERequestWrite:
415 if(iStatus == EClosed)
420 umemget32(&len, a2, sizeof(len));
429 Kern::KUDesGet((TDes8&)iFIFO.iTxBuf, *(const TDesC8*)a1);
430 iFIFO.iTxBuf.SetLength(len);
431 iWriteRequest->SetStatus(pS);
434 case RBusDevEthernet::ERequestRead:
439 umemget32(&len, a2, sizeof(len));
444 Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
445 if(bufMaxLen < Abs(len))
451 Kern::KUDesSetLength(*(TDes8*)a1, 0);
453 r = iReadRequest->StartSetup(pS);
458 r = iReadRequest->AddBuffer(iClientReadBuffer, a1);
463 iReadRequest->EndSetup();
466 #ifdef ETH_CHIP_IO_ENABLED
467 case RBusDevEthernet::EChipDiagIOCtrl:
469 Kern::KUDesGet((TDes8&)iChipInfo, *(const TDesC8*)a1);
474 return KErrNotSupported;
476 r = DLogicalChannel::SendMsg(aMsg);
477 #ifdef ETH_CHIP_IO_ENABLED
482 case RBusDevEthernet::EChipDiagIOCtrl:
484 Kern::KUDesPut(*(TDes8*)a1, (const TDesC8&)iChipInfo);
485 Kern::RequestComplete(pS,r);
494 void DChannelEthernet::HandleMsg(TMessageBase* aMsg)
496 TThreadMessage& m=*(TThreadMessage*)aMsg;
499 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd: DChannelEthernet::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
501 if (id==(TInt)ECloseMsg)
506 else if (id==KMaxTInt)
510 m.Complete(KErrNone,ETrue);
517 TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
518 TInt r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2());
519 //Kern::Printf(" >ldd: about to complete TThreadMessage id=%d...\n", id);
525 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd: do control id=%d...\n", id));
526 TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
532 void DChannelEthernet::DoCancel(TInt aMask)
533 // Cancel an outstanding request.
535 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCancel(TInt aMask = %d)", aMask));
537 if (aMask & RBusDevEthernet::ERequestReadCancel)
539 if (iRxCompleteDfc.Queued())
541 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::DoCancel()- Cancelling old dfc"));
542 iRxCompleteDfc.Cancel();
544 Complete(ERx,KErrCancel);
547 if (aMask & RBusDevEthernet::ERequestWriteCancel)
549 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("> ldd: DChannelEthernet::DoCancel - Completing write cancel\n"));
550 Complete(ETx,KErrCancel);
555 TInt DChannelEthernet::DoRequest(TInt aReqNo, TRequestStatus* /*aStatus*/, TAny* a1, TAny* /*a2*/)
558 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)"));
559 // First check if we have started
565 // Now we can dispatch the request
570 case RBusDevEthernet::ERequestRead:
571 InitiateRead(a1,len);
574 case RBusDevEthernet::ERequestWrite:
575 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd tx: RBusDevEthernet::ERequestWrite..."));
576 InitiateWrite(a1,len);
578 #ifdef ETH_CHIP_IO_ENABLED
579 case RBusDevEthernet::EChipDiagIOCtrl:
581 r=((DEthernet*)iPdd)->BgeChipIOCtrl(iChipInfo);
590 void DChannelEthernet::InitiateRead(TAny* /*aRxDes*/, TInt aLength)
592 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::InitiateRead(TAny *aRxDes, TInt aLength)"));
593 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd client triggered read...\n"));
594 iRxLength=Abs(aLength);
595 TBuf8<KMaxEthernetPacket+32> * next;
596 next = iFIFO.GetNext();
599 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::InitiateRead - RX buffer empty"));
600 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd client - miss = rx buf empty...\n"));
605 // RX buffer has data, must scan buffer and then complete
606 TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, *(const TDesC8*)next, 0, KChunkShiftBy0, iClient);
607 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd client - hit = rx tcp seq=%u ack=%d\n", GetTcpSeqNumber(*next), GetTcpAckNumber(*next)) );
612 void DChannelEthernet::InitiateWrite(TAny* /*aTxDes*/, TInt /*aLength*/)
614 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::InitiateWrite(TAny *aTxDes, TInt aLength)"));
615 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd tx: tcp seq=%u ack=%u\n", GetTcpSeqNumber(iFIFO.iTxBuf), GetTcpAckNumber(iFIFO.iTxBuf)) );
616 if(PddSend(iFIFO.iTxBuf) != KErrNone)
617 Complete(ETx, KErrCommsLineFail);
619 Complete(ETx, KErrNone);
623 TInt DChannelEthernet::SetConfig(TEthernetConfigV01& c)
625 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SetConfig(TEthernetConfigV01& c)"));
628 if ((r=ValidateConfig(c))!=KErrNone)
633 PddConfigure(iConfig);
639 TInt DChannelEthernet::SetMAC(TEthernetConfigV01& c)
641 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SetMAC(TEthernetConfigV01& c)"));
644 if ((r=ValidateConfig(c))!=KErrNone)
649 MacConfigure(iConfig);
650 PddConfigure(iConfig);
656 TInt DChannelEthernet::DoControl(TInt aFunction, TAny* a1, TAny* /*a2*/)
659 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::DoControl(TInt aFunction, TAny* a1, TAny* a2)") );
664 case RBusDevEthernet::EControlConfig:
666 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlConfig"));
667 *(TEthernetConfigV01*)a1 = iConfig;
670 case RBusDevEthernet::EControlSetConfig:
672 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlSetConfig"));
673 r=SetConfig(*(TEthernetConfigV01*)a1);
676 case RBusDevEthernet::EControlSetMac:
678 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlSetMac"));
679 r = SetMAC(*(TEthernetConfigV01*)a1);
682 case RBusDevEthernet::EControlCaps:
684 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlCaps"));
685 TEthernetCaps capsBuf;
687 *(TEthernetCaps*)a1 = capsBuf;
692 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl default 0x%x", aFunction));
699 // Implementation of driver Rx / Tx FIFO class.
700 DChannelEthernetFIFO::DChannelEthernetFIFO()
704 iNumFree = KNumRXBuffers;
707 DChannelEthernetFIFO::~DChannelEthernetFIFO()
711 TBuf8<KMaxEthernetPacket+32> * DChannelEthernetFIFO::GetFree()
712 // Return location of current Rx FIFO free element
716 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernetFIFO::GetFree()- No free free buffers"));
722 TBuf8<KMaxEthernetPacket+32> &rxBuf = iRxBuf[iRxQueIterFree++];
723 if(iRxQueIterFree == KNumRXBuffers)
726 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetFree()- free wrap return 0"));
729 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetFree()- free return %d", iRxQueIterFree));
734 TBuf8<KMaxEthernetPacket+32> * DChannelEthernetFIFO::GetNext()
735 // Return location of next data element within Rx FIFO
737 __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >LDDx: GetNext() - iNumFree=%d iRxQueIterNext(read)=%d iRxQueIterFree(write)=%d", iNumFree, iRxQueIterNext, iRxQueIterFree));
739 if(iNumFree == KNumRXBuffers)
741 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- No data waiting"));
745 TBuf8<KMaxEthernetPacket+32> &rxBuf = iRxBuf[iRxQueIterNext++];
746 if(iRxQueIterNext == KNumRXBuffers)
748 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- Wrap next return 0"));
752 __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- Data found return %d", iRxQueIterNext));
756 void DChannelEthernetFIFO::SetNext()
757 // Increment location of next data element within Rx FIFO
759 // locked since iNumFree is decremented in function which could be called
760 // from interrupt context
761 // DENNIS: SOUNDS DODGY
762 __e32_atomic_add_ord32(&iNumFree, 1);
765 /** @addtogroup enet Ethernet Drivers
766 * Kernel Ethernet Support
769 /** @addtogroup enet_ldd Driver LDD's
774 * @addtogroup enet_ldd_nopm_nopccard Ethernet LDD Not PCMCIA and No Power Managment
780 * Real entry point from the Kernel: return a new driver
782 DECLARE_STANDARD_LDD()
784 return new DDeviceEthernet;
788 /** @} */ // end of assabet group