sl@0: // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // e32\drivers\ethernet\d_ethernet.cpp sl@0: // LDD the ethernet which has no power managment and is not PCCard based sl@0: // sl@0: // sl@0: sl@0: /** sl@0: @file d_ethernet.cpp sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: sl@0: _LIT(KLddName,"Ethernet"); sl@0: sl@0: #ifdef KNETWORK1 sl@0: const TUint8 ETHER2_TYPE_IP_MSB = 0x08; sl@0: const TUint8 ETHER2_TYPE_IP_LSB = 0x00; sl@0: const TUint8 IP_TYPE_TCP = 0x06; sl@0: sl@0: static TBool IsTcp(TDesC8 &aFrame) sl@0: { sl@0: return (aFrame[12] == ETHER2_TYPE_IP_MSB && aFrame[13] == ETHER2_TYPE_IP_LSB && aFrame[23] == IP_TYPE_TCP); sl@0: } sl@0: sl@0: static TInt GetTcpSeqNumber(TDesC8 &aFrame) sl@0: { sl@0: TInt seqNum = 0; sl@0: if (IsTcp(aFrame)) sl@0: seqNum = aFrame[38] << 24 | aFrame[39] << 16 | aFrame[40] << 8| aFrame[41]; sl@0: return seqNum; sl@0: } sl@0: sl@0: static TInt GetTcpAckNumber(TDesC8 &aFrame) sl@0: { sl@0: TInt ackNum = 0; sl@0: if (IsTcp(aFrame)) sl@0: ackNum = aFrame[42] << 24 | aFrame[43] << 16 | aFrame[44] << 8| aFrame[45]; sl@0: return ackNum; sl@0: } sl@0: #endif sl@0: sl@0: DDeviceEthernet::DDeviceEthernet() sl@0: // Constructor sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::DDeviceEthernet()")); sl@0: iParseMask=KDeviceAllowAll; sl@0: iUnitsMask=0xffffffff; // Leave units decision to the PDD sl@0: iVersion=TVersion(KEthernetMajorVersionNumber, sl@0: KEthernetMinorVersionNumber, sl@0: KEthernetBuildVersionNumber); sl@0: } sl@0: sl@0: sl@0: TInt DDeviceEthernet::Install() sl@0: // Install the device driver. sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::Install()")); sl@0: return(SetName(&KLddName)); sl@0: } sl@0: sl@0: sl@0: void DDeviceEthernet::GetCaps(TDes8& aDes) const sl@0: // Return the Ethernet capabilities. sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::GetCaps(TDes8& aDes) const")); sl@0: TPckgBuf b; sl@0: b().version=TVersion(KEthernetMajorVersionNumber, sl@0: KEthernetMinorVersionNumber, sl@0: KEthernetBuildVersionNumber); sl@0: Kern::InfoCopy(aDes,b); sl@0: } sl@0: sl@0: sl@0: TInt DDeviceEthernet::Create(DLogicalChannelBase*& aChannel) sl@0: // Create a channel on the device. sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::Create(DLogicalChannelBase*& aChannel)")); sl@0: aChannel=new DChannelEthernet; sl@0: sl@0: return aChannel?KErrNone:KErrNoMemory; sl@0: } sl@0: sl@0: sl@0: DChannelEthernet::DChannelEthernet() sl@0: // Constructor sl@0: : iRxCompleteDfc(CompleteRxDfc, this, 2) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DChannelEthernet()")); sl@0: sl@0: // Setup the default config sl@0: iConfig.iEthSpeed = KEthSpeed10BaseT; sl@0: iConfig.iEthDuplex = KEthDuplexHalf; sl@0: iConfig.iEthAddress[0] = 0x00; sl@0: iConfig.iEthAddress[1] = 0x00; sl@0: iConfig.iEthAddress[2] = 0x00; sl@0: iConfig.iEthAddress[3] = 0x00; sl@0: iConfig.iEthAddress[4] = 0x00; sl@0: iConfig.iEthAddress[5] = 0x00; sl@0: sl@0: iStatus=EOpen; sl@0: sl@0: iClient=&Kern::CurrentThread(); sl@0: // Increse the Dthread's ref count so that it does not close without us sl@0: iClient->Open(); sl@0: } sl@0: sl@0: sl@0: DChannelEthernet::~DChannelEthernet() sl@0: // Destructor sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::~DChannelEthernet()")); sl@0: Kern::DestroyClientRequest(iWriteRequest); sl@0: Kern::DestroyClientBufferRequest(iReadRequest); sl@0: // decrement it's reference count sl@0: Kern::SafeClose((DObject*&)iClient, NULL); sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::Complete(TInt aMask, TInt aReason) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete(TInt aMask, TInt aReason)")); sl@0: if (aMask & ERx) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete iReadRequest")); sl@0: if (iReadRequest->IsReady()) sl@0: { sl@0: Kern::QueueBufferRequestComplete(iClient, iReadRequest, aReason); sl@0: } sl@0: } sl@0: if (aMask & ETx) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete iWriteRequest")); sl@0: __KTRACE_OPT(KNETWORK2, Kern::Printf(" >ldd tx: PRE complete reason=%d iClient=%08x iTxStatus=%08x\n", aReason, iClient, iWriteRequest->StatusPtr())); sl@0: Kern::QueueRequestComplete(iClient, iWriteRequest, aReason); sl@0: } sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::Shutdown() sl@0: { sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::Shutdown()")); sl@0: sl@0: // Suspend the chip and disable interrupts sl@0: (static_cast(iPdd))->Stop(EStopNormal); sl@0: sl@0: Complete(EAll, KErrAbort); sl@0: sl@0: if (iRxCompleteDfc.Queued()) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Shutdown()- Cancelling old dfc")); sl@0: // Ethernet interrupts are disabled; must make sure DFCs are not queued. sl@0: iRxCompleteDfc.Cancel(); sl@0: } sl@0: sl@0: // No harm in doing this sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Shutdown()- Completing message")); sl@0: iMsgQ.iMessage->Complete(KErrNone,EFalse); sl@0: } sl@0: sl@0: sl@0: TInt DChannelEthernet::DoCreate(TInt aUnit, sl@0: const TDesC8* /*anInfo*/, sl@0: const TVersion &aVer) sl@0: // Create the channel from the passed info. sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)")); sl@0: sl@0: if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ENET.LDD (Ethernet Driver)"))) sl@0: return KErrPermissionDenied; sl@0: sl@0: if (!Kern::QueryVersionSupported(TVersion(KEthernetMajorVersionNumber, sl@0: KEthernetMinorVersionNumber, sl@0: KEthernetBuildVersionNumber), sl@0: aVer)) sl@0: return KErrNotSupported; sl@0: sl@0: TInt r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual); sl@0: if (r != KErrNone) sl@0: return r; sl@0: sl@0: r = Kern::CreateClientRequest(iWriteRequest); sl@0: if (r != KErrNone) sl@0: return r; sl@0: sl@0: SetDfcQ(((DEthernet*)iPdd)->DfcQ(aUnit)); sl@0: iRxCompleteDfc.SetDfcQ(iDfcQ); sl@0: iMsgQ.Receive(); sl@0: sl@0: ((DEthernet *)iPdd)->iLdd=this; sl@0: sl@0: //Get config from the device sl@0: ((DEthernet *)iPdd)->GetConfig(iConfig); sl@0: sl@0: PddCheckConfig(iConfig); sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::Start() sl@0: // Start the driver receiving. sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Start()")); sl@0: if (iStatus!=EClosed) sl@0: { sl@0: PddStart(); sl@0: iStatus=EActive; sl@0: } sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::ReceiveIsr() sl@0: // Copies data into the iFifo's buffers sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()")); sl@0: TBuf8 * buffer; sl@0: // TInt err; sl@0: sl@0: buffer = iFIFO.GetFree(); sl@0: if(buffer == NULL) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()- Dropping a frame")); sl@0: /*err =*/ PddReceive(*buffer, EFalse); //Need to call as must drain RX buffer sl@0: // Should something be done about returned errors? sl@0: return; sl@0: } sl@0: else sl@0: /*err =*/ PddReceive(*buffer, ETrue); sl@0: // Should something be done about returned errors? sl@0: sl@0: // Add another DFc as we have a buffer and is not already queued sl@0: if (!iRxCompleteDfc.Queued()) sl@0: { sl@0: if (NKern::CurrentContext()==NKern::EInterrupt) sl@0: iRxCompleteDfc.Add(); sl@0: else sl@0: iRxCompleteDfc.Enque(); sl@0: return; sl@0: } sl@0: sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()- DFC already added")); sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::CompleteRxDfc(TAny* aPtr) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::CompleteRxDfc(TAny* aPtr)")); sl@0: DChannelEthernet *pC=(DChannelEthernet*)aPtr; sl@0: pC->DoCompleteRx(); sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::DoCompleteRx() sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()")); sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr triggered...")); sl@0: sl@0: sl@0: if (iReadRequest->IsReady()) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()- Read waiting")); sl@0: TBuf8 * buffer; sl@0: sl@0: buffer = iFIFO.GetNext(); sl@0: if (buffer == NULL) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()- Unexpected read request earlier")); sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - miss = empty")); sl@0: Complete(ERx, KErrNone); sl@0: return; sl@0: } sl@0: sl@0: // RX buffer has data, must scan buffer and then complete sl@0: TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, *(const TDesC8*)buffer, 0, KChunkShiftBy0, iClient); sl@0: iFIFO.SetNext(); sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - hit = rx tcp seq=%u ack=%u\n", GetTcpSeqNumber(*buffer), GetTcpAckNumber(*buffer)) ); sl@0: Complete(ERx, r); sl@0: } sl@0: else sl@0: { sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - skipped! no request pending\n")); sl@0: } sl@0: sl@0: } sl@0: sl@0: //Override sendMsg to allow data copy in the context of client thread for WDP. sl@0: TInt DChannelEthernet::SendMsg(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m = *(TThreadMessage*)aMsg; sl@0: TInt id = m.iValue; sl@0: TInt r = KErrNone; sl@0: if (id != (TInt)ECloseMsg && id != KMaxTInt) sl@0: { sl@0: if (id<0) sl@0: { sl@0: TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); sl@0: r = SendRequest(aMsg); sl@0: if (r != KErrNone) sl@0: { sl@0: Kern::RequestComplete(pS,r); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: r = SendControl(aMsg); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: r = DLogicalChannel::SendMsg(aMsg); sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: sl@0: TInt DChannelEthernet::SendControl(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m = *(TThreadMessage*)aMsg; sl@0: TInt id = m.iValue; sl@0: TInt bufLen; sl@0: TInt bufMaxLen; sl@0: TEthernetConfigV01 config; sl@0: TEthernetCaps caps; sl@0: TAny* a1 = m.Ptr0(); sl@0: TInt r = KErrNone; sl@0: switch(id) sl@0: { sl@0: case RBusDevEthernet::EControlConfig: sl@0: { sl@0: sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlConfig")); sl@0: Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen); sl@0: if((TUint)bufMaxLen < sizeof(TEthernetConfigV01)) sl@0: { sl@0: return KErrUnderflow; sl@0: } sl@0: m.iArg[0] = &config; sl@0: break; sl@0: } sl@0: case RBusDevEthernet::EControlCaps: sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlCaps")); sl@0: Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen); sl@0: if((TUint)bufMaxLen < sizeof(caps)) sl@0: { sl@0: return KErrUnderflow; sl@0: } sl@0: m.iArg[0] = ∩︀ sl@0: break; sl@0: } sl@0: case RBusDevEthernet::EControlSetConfig: sl@0: case RBusDevEthernet::EControlSetMac: sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlSetConfig")); sl@0: Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen); sl@0: if((TUint)bufLen > sizeof(config)) sl@0: { sl@0: return KErrOverflow; sl@0: } sl@0: memset(&config,0,sizeof(config)); sl@0: TPtr8 cfg((TUint8*)&config,0,sizeof(config)); sl@0: Kern::KUDesGet(*(TDes8*)&cfg, *(const TDesC8*)a1); sl@0: m.iArg[0] = (TAny*)&config; sl@0: break; sl@0: } sl@0: default: sl@0: return KErrNotSupported; sl@0: } sl@0: r = DLogicalChannel::SendMsg(aMsg); sl@0: if(r != KErrNone) sl@0: return r; sl@0: switch(id) sl@0: { sl@0: case RBusDevEthernet::EControlConfig: sl@0: { sl@0: Kern::InfoCopy(*(TDes8*)a1, (const TUint8*)&config, sizeof(TEthernetConfigV01)); sl@0: break; sl@0: } sl@0: case RBusDevEthernet::EControlCaps: sl@0: { sl@0: Kern::KUDesPut(*(TDes8*)a1, (const TDesC8&)caps); sl@0: break; sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: TInt DChannelEthernet::SendRequest(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m = *(TThreadMessage*)aMsg; sl@0: TInt id = ~m.iValue; sl@0: TRequestStatus* pS = (TRequestStatus*)m.Ptr0(); sl@0: TAny* a1 = m.Ptr1(); sl@0: TAny* a2 = m.Ptr2(); sl@0: TInt r = KErrNone; sl@0: switch(id) sl@0: { sl@0: case RBusDevEthernet::ERequestWrite: sl@0: { sl@0: if(iStatus == EClosed) sl@0: { sl@0: return KErrNotReady; sl@0: } sl@0: TInt len; sl@0: umemget32(&len, a2, sizeof(len)); sl@0: if(len == 0) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: if(!a1) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: Kern::KUDesGet((TDes8&)iFIFO.iTxBuf, *(const TDesC8*)a1); sl@0: iFIFO.iTxBuf.SetLength(len); sl@0: iWriteRequest->SetStatus(pS); sl@0: break; sl@0: } sl@0: case RBusDevEthernet::ERequestRead: sl@0: { sl@0: TInt len; sl@0: TInt bufLen; sl@0: TInt bufMaxLen; sl@0: umemget32(&len, a2, sizeof(len)); sl@0: if(len == 0) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen); sl@0: if(bufMaxLen < Abs(len)) sl@0: { sl@0: return KErrGeneral; sl@0: } sl@0: if(bufLen != 0) sl@0: { sl@0: Kern::KUDesSetLength(*(TDes8*)a1, 0); sl@0: } sl@0: r = iReadRequest->StartSetup(pS); sl@0: if (r != KErrNone) sl@0: { sl@0: return r; sl@0: } sl@0: r = iReadRequest->AddBuffer(iClientReadBuffer, a1); sl@0: if (r != KErrNone) sl@0: { sl@0: return KErrNoMemory; sl@0: } sl@0: iReadRequest->EndSetup(); sl@0: break; sl@0: } sl@0: #ifdef ETH_CHIP_IO_ENABLED sl@0: case RBusDevEthernet::EChipDiagIOCtrl: sl@0: { sl@0: Kern::KUDesGet((TDes8&)iChipInfo, *(const TDesC8*)a1); sl@0: break; sl@0: } sl@0: #endif sl@0: default: sl@0: return KErrNotSupported; sl@0: } sl@0: r = DLogicalChannel::SendMsg(aMsg); sl@0: #ifdef ETH_CHIP_IO_ENABLED sl@0: if(r == KErrNone) sl@0: { sl@0: switch(id) sl@0: { sl@0: case RBusDevEthernet::EChipDiagIOCtrl: sl@0: { sl@0: Kern::KUDesPut(*(TDes8*)a1, (const TDesC8&)iChipInfo); sl@0: Kern::RequestComplete(pS,r); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: #endif sl@0: return r; sl@0: } sl@0: sl@0: void DChannelEthernet::HandleMsg(TMessageBase* aMsg) sl@0: { sl@0: TThreadMessage& m=*(TThreadMessage*)aMsg; sl@0: TInt id=m.iValue; sl@0: sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd: DChannelEthernet::HandleMsg(TMessageBase* aMsg) id=%d\n", id)); sl@0: sl@0: if (id==(TInt)ECloseMsg) sl@0: { sl@0: Shutdown(); sl@0: return; sl@0: } sl@0: else if (id==KMaxTInt) sl@0: { sl@0: // DoCancel sl@0: DoCancel(m.Int0()); sl@0: m.Complete(KErrNone,ETrue); sl@0: return; sl@0: } sl@0: sl@0: if (id<0) sl@0: { sl@0: // DoRequest sl@0: TRequestStatus* pS=(TRequestStatus*)m.Ptr0(); sl@0: TInt r = DoRequest(~id, pS, m.Ptr1(), m.Ptr2()); sl@0: //Kern::Printf(" >ldd: about to complete TThreadMessage id=%d...\n", id); sl@0: m.Complete(r,ETrue); sl@0: } sl@0: else sl@0: { sl@0: // DoControl sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd: do control id=%d...\n", id)); sl@0: TInt r=DoControl(id,m.Ptr0(),m.Ptr1()); sl@0: m.Complete(r,ETrue); sl@0: } sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::DoCancel(TInt aMask) sl@0: // Cancel an outstanding request. sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCancel(TInt aMask = %d)", aMask)); sl@0: sl@0: if (aMask & RBusDevEthernet::ERequestReadCancel) sl@0: { sl@0: if (iRxCompleteDfc.Queued()) sl@0: { sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::DoCancel()- Cancelling old dfc")); sl@0: iRxCompleteDfc.Cancel(); sl@0: } sl@0: Complete(ERx,KErrCancel); sl@0: } sl@0: sl@0: if (aMask & RBusDevEthernet::ERequestWriteCancel) sl@0: { sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("> ldd: DChannelEthernet::DoCancel - Completing write cancel\n")); sl@0: Complete(ETx,KErrCancel); sl@0: } sl@0: } sl@0: sl@0: sl@0: TInt DChannelEthernet::DoRequest(TInt aReqNo, TRequestStatus* /*aStatus*/, TAny* a1, TAny* /*a2*/) sl@0: // Async requests. sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)")); sl@0: // First check if we have started sl@0: if (iStatus==EOpen) sl@0: { sl@0: Start(); sl@0: } sl@0: sl@0: // Now we can dispatch the request sl@0: TInt r=KErrNone; sl@0: TInt len=0; sl@0: switch (aReqNo) sl@0: { sl@0: case RBusDevEthernet::ERequestRead: sl@0: InitiateRead(a1,len); sl@0: break; sl@0: sl@0: case RBusDevEthernet::ERequestWrite: sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd tx: RBusDevEthernet::ERequestWrite...")); sl@0: InitiateWrite(a1,len); sl@0: break; sl@0: #ifdef ETH_CHIP_IO_ENABLED sl@0: case RBusDevEthernet::EChipDiagIOCtrl: sl@0: { sl@0: r=((DEthernet*)iPdd)->BgeChipIOCtrl(iChipInfo); sl@0: break; sl@0: } sl@0: #endif sl@0: } sl@0: return r; sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::InitiateRead(TAny* /*aRxDes*/, TInt aLength) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::InitiateRead(TAny *aRxDes, TInt aLength)")); sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd client triggered read...\n")); sl@0: iRxLength=Abs(aLength); sl@0: TBuf8 * next; sl@0: next = iFIFO.GetNext(); sl@0: if (next == NULL) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::InitiateRead - RX buffer empty")); sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd client - miss = rx buf empty...\n")); sl@0: return; sl@0: } sl@0: sl@0: iFIFO.SetNext(); sl@0: // RX buffer has data, must scan buffer and then complete sl@0: TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, *(const TDesC8*)next, 0, KChunkShiftBy0, iClient); sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd client - hit = rx tcp seq=%u ack=%d\n", GetTcpSeqNumber(*next), GetTcpAckNumber(*next)) ); sl@0: Complete(ERx,r); sl@0: } sl@0: sl@0: sl@0: void DChannelEthernet::InitiateWrite(TAny* /*aTxDes*/, TInt /*aLength*/) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::InitiateWrite(TAny *aTxDes, TInt aLength)")); sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd tx: tcp seq=%u ack=%u\n", GetTcpSeqNumber(iFIFO.iTxBuf), GetTcpAckNumber(iFIFO.iTxBuf)) ); sl@0: if(PddSend(iFIFO.iTxBuf) != KErrNone) sl@0: Complete(ETx, KErrCommsLineFail); sl@0: else sl@0: Complete(ETx, KErrNone); sl@0: } sl@0: sl@0: sl@0: TInt DChannelEthernet::SetConfig(TEthernetConfigV01& c) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SetConfig(TEthernetConfigV01& c)")); sl@0: TInt r; sl@0: sl@0: if ((r=ValidateConfig(c))!=KErrNone) sl@0: return r; sl@0: sl@0: iConfig = c; sl@0: sl@0: PddConfigure(iConfig); sl@0: sl@0: return r; sl@0: } sl@0: sl@0: sl@0: TInt DChannelEthernet::SetMAC(TEthernetConfigV01& c) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SetMAC(TEthernetConfigV01& c)")); sl@0: TInt r; sl@0: sl@0: if ((r=ValidateConfig(c))!=KErrNone) sl@0: return r; sl@0: sl@0: iConfig = c; sl@0: sl@0: MacConfigure(iConfig); sl@0: PddConfigure(iConfig); sl@0: sl@0: return r; sl@0: } sl@0: sl@0: sl@0: TInt DChannelEthernet::DoControl(TInt aFunction, TAny* a1, TAny* /*a2*/) sl@0: // Sync requests. sl@0: { sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::DoControl(TInt aFunction, TAny* a1, TAny* a2)") ); sl@0: TInt r=KErrNone; sl@0: sl@0: switch (aFunction) sl@0: { sl@0: case RBusDevEthernet::EControlConfig: sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlConfig")); sl@0: *(TEthernetConfigV01*)a1 = iConfig; sl@0: break; sl@0: } sl@0: case RBusDevEthernet::EControlSetConfig: sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlSetConfig")); sl@0: r=SetConfig(*(TEthernetConfigV01*)a1); sl@0: break; sl@0: } sl@0: case RBusDevEthernet::EControlSetMac: sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlSetMac")); sl@0: r = SetMAC(*(TEthernetConfigV01*)a1); sl@0: break; sl@0: } sl@0: case RBusDevEthernet::EControlCaps: sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlCaps")); sl@0: TEthernetCaps capsBuf; sl@0: PddCaps(capsBuf); sl@0: *(TEthernetCaps*)a1 = capsBuf; sl@0: break; sl@0: } sl@0: default: sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl default 0x%x", aFunction)); sl@0: r=KErrNotSupported; sl@0: } sl@0: } sl@0: return(r); sl@0: } sl@0: sl@0: // Implementation of driver Rx / Tx FIFO class. sl@0: DChannelEthernetFIFO::DChannelEthernetFIFO() sl@0: { sl@0: iRxQueIterNext = 0; sl@0: iRxQueIterFree = 0; sl@0: iNumFree = KNumRXBuffers; sl@0: } sl@0: sl@0: DChannelEthernetFIFO::~DChannelEthernetFIFO() sl@0: { sl@0: } sl@0: sl@0: TBuf8 * DChannelEthernetFIFO::GetFree() sl@0: // Return location of current Rx FIFO free element sl@0: { sl@0: if(iNumFree == 0) sl@0: { sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernetFIFO::GetFree()- No free free buffers")); sl@0: return NULL; sl@0: } sl@0: sl@0: iNumFree--; sl@0: sl@0: TBuf8 &rxBuf = iRxBuf[iRxQueIterFree++]; sl@0: if(iRxQueIterFree == KNumRXBuffers) sl@0: { sl@0: iRxQueIterFree = 0; sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetFree()- free wrap return 0")); sl@0: } sl@0: sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetFree()- free return %d", iRxQueIterFree)); sl@0: return &rxBuf; sl@0: } sl@0: sl@0: sl@0: TBuf8 * DChannelEthernetFIFO::GetNext() sl@0: // Return location of next data element within Rx FIFO sl@0: { sl@0: __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >LDDx: GetNext() - iNumFree=%d iRxQueIterNext(read)=%d iRxQueIterFree(write)=%d", iNumFree, iRxQueIterNext, iRxQueIterFree)); sl@0: sl@0: if(iNumFree == KNumRXBuffers) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- No data waiting")); sl@0: return NULL; sl@0: } sl@0: sl@0: TBuf8 &rxBuf = iRxBuf[iRxQueIterNext++]; sl@0: if(iRxQueIterNext == KNumRXBuffers) sl@0: { sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- Wrap next return 0")); sl@0: iRxQueIterNext = 0; sl@0: } sl@0: sl@0: __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- Data found return %d", iRxQueIterNext)); sl@0: return &rxBuf; sl@0: } sl@0: sl@0: void DChannelEthernetFIFO::SetNext() sl@0: // Increment location of next data element within Rx FIFO sl@0: { sl@0: // locked since iNumFree is decremented in function which could be called sl@0: // from interrupt context sl@0: // DENNIS: SOUNDS DODGY sl@0: __e32_atomic_add_ord32(&iNumFree, 1); sl@0: } sl@0: sl@0: /** @addtogroup enet Ethernet Drivers sl@0: * Kernel Ethernet Support sl@0: */ sl@0: sl@0: /** @addtogroup enet_ldd Driver LDD's sl@0: * @ingroup enet sl@0: */ sl@0: sl@0: /** sl@0: * @addtogroup enet_ldd_nopm_nopccard Ethernet LDD Not PCMCIA and No Power Managment sl@0: * @ingroup enet_ldd sl@0: * @{ sl@0: */ sl@0: sl@0: /** sl@0: * Real entry point from the Kernel: return a new driver sl@0: */ sl@0: DECLARE_STANDARD_LDD() sl@0: { sl@0: return new DDeviceEthernet; sl@0: } sl@0: sl@0: sl@0: /** @} */ // end of assabet group sl@0: sl@0: sl@0: sl@0: