kernel/eka/drivers/ethernet/d_ethernet.cpp
changeset 43 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 43:96e5fb8b040d
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // e32\drivers\ethernet\d_ethernet.cpp
       
    15 // LDD the ethernet which has no power managment and is not PCCard based
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file d_ethernet.cpp
       
    21 */
       
    22 
       
    23 #include <drivers/ethernet.h>
       
    24 #include <kernel/kern_priv.h>
       
    25 #include <e32hal.h>
       
    26 #include <e32uid.h>
       
    27 
       
    28 
       
    29 _LIT(KLddName,"Ethernet");
       
    30 
       
    31 #ifdef KNETWORK1
       
    32 const TUint8 ETHER2_TYPE_IP_MSB = 0x08;
       
    33 const TUint8 ETHER2_TYPE_IP_LSB = 0x00;
       
    34 const TUint8 IP_TYPE_TCP        = 0x06;
       
    35 
       
    36 static TBool IsTcp(TDesC8 &aFrame)
       
    37 	{
       
    38 	return (aFrame[12] == ETHER2_TYPE_IP_MSB && aFrame[13] == ETHER2_TYPE_IP_LSB && aFrame[23] == IP_TYPE_TCP);
       
    39 	}
       
    40 
       
    41 static TInt GetTcpSeqNumber(TDesC8 &aFrame)
       
    42 	{
       
    43 	TInt seqNum = 0;
       
    44 	if (IsTcp(aFrame))
       
    45 		seqNum = aFrame[38] << 24 | aFrame[39] << 16 | aFrame[40] << 8| aFrame[41];
       
    46 	return seqNum;
       
    47 	}
       
    48 
       
    49 static TInt GetTcpAckNumber(TDesC8 &aFrame)
       
    50 	{
       
    51 	TInt ackNum = 0;
       
    52 	if (IsTcp(aFrame))
       
    53 		ackNum = aFrame[42] << 24 | aFrame[43] << 16 | aFrame[44] << 8| aFrame[45];
       
    54 	return ackNum;
       
    55 	}
       
    56 #endif
       
    57 
       
    58 DDeviceEthernet::DDeviceEthernet()
       
    59 // Constructor
       
    60     {
       
    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);
       
    67     }
       
    68 
       
    69 
       
    70 TInt DDeviceEthernet::Install()
       
    71 // Install the device driver.
       
    72     {
       
    73     __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::Install()"));
       
    74     return(SetName(&KLddName));
       
    75     }
       
    76 
       
    77 
       
    78 void DDeviceEthernet::GetCaps(TDes8& aDes) const
       
    79 // Return the Ethernet capabilities.
       
    80     {
       
    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);
       
    87     }
       
    88 
       
    89 
       
    90 TInt DDeviceEthernet::Create(DLogicalChannelBase*& aChannel)
       
    91 // Create a channel on the device.
       
    92     {
       
    93     __KTRACE_OPT(KNETWORK1, Kern::Printf("DDeviceEthernet::Create(DLogicalChannelBase*& aChannel)"));
       
    94     aChannel=new DChannelEthernet;
       
    95 
       
    96     return aChannel?KErrNone:KErrNoMemory;
       
    97     }
       
    98 
       
    99 
       
   100 DChannelEthernet::DChannelEthernet()
       
   101 // Constructor
       
   102     :   iRxCompleteDfc(CompleteRxDfc, this, 2)
       
   103     {
       
   104     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DChannelEthernet()"));
       
   105 
       
   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;
       
   115 
       
   116     iStatus=EOpen;
       
   117     
       
   118     iClient=&Kern::CurrentThread();
       
   119 	// Increse the Dthread's ref count so that it does not close without us
       
   120 	iClient->Open();
       
   121     }
       
   122 
       
   123 
       
   124 DChannelEthernet::~DChannelEthernet()
       
   125 // Destructor
       
   126     {
       
   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);
       
   132     }
       
   133 
       
   134 
       
   135 void DChannelEthernet::Complete(TInt aMask, TInt aReason)
       
   136     {
       
   137     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete(TInt aMask, TInt aReason)"));
       
   138     if (aMask & ERx)
       
   139 		{
       
   140     	__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Complete iReadRequest"));
       
   141 		if (iReadRequest->IsReady())
       
   142 			{
       
   143 			Kern::QueueBufferRequestComplete(iClient, iReadRequest, aReason);
       
   144 			}
       
   145 		}
       
   146     if (aMask & ETx)
       
   147 		{
       
   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);
       
   151 		}
       
   152 	}
       
   153 
       
   154 
       
   155 void DChannelEthernet::Shutdown()
       
   156     {
       
   157     __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::Shutdown()"));
       
   158 	
       
   159 	// Suspend the chip and disable interrupts
       
   160 	(static_cast<DEthernet*>(iPdd))->Stop(EStopNormal);
       
   161 	
       
   162 	Complete(EAll, KErrAbort);
       
   163     
       
   164 	if (iRxCompleteDfc.Queued())
       
   165 		{
       
   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();
       
   169 		}
       
   170 
       
   171 	// No harm in doing this
       
   172     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Shutdown()- Completing message"));
       
   173     iMsgQ.iMessage->Complete(KErrNone,EFalse);
       
   174     }
       
   175 
       
   176 
       
   177 TInt DChannelEthernet::DoCreate(TInt aUnit, 
       
   178                                 const TDesC8* /*anInfo*/, 
       
   179                                 const TVersion &aVer)
       
   180 // Create the channel from the passed info.
       
   181     {
       
   182     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCreate(TInt aUnit, const TDesC8* anInfo, const TVersion &aVer)"));
       
   183 	
       
   184 	if(!Kern::CurrentThreadHasCapability(ECapabilityCommDD,__PLATSEC_DIAGNOSTIC_STRING("Checked by ENET.LDD (Ethernet Driver)")))
       
   185 		return KErrPermissionDenied;
       
   186     
       
   187 	if (!Kern::QueryVersionSupported(TVersion(KEthernetMajorVersionNumber,
       
   188 					      KEthernetMinorVersionNumber,
       
   189 					      KEthernetBuildVersionNumber),
       
   190 				     aVer))
       
   191 		return KErrNotSupported;
       
   192 
       
   193 	TInt r = Kern::CreateClientBufferRequest(iReadRequest, 1, TClientBufferRequest::EPinVirtual);
       
   194 	if (r != KErrNone)
       
   195 		return r;
       
   196 
       
   197 	r = Kern::CreateClientRequest(iWriteRequest);
       
   198 	if (r != KErrNone)
       
   199 		return r;
       
   200 
       
   201 	SetDfcQ(((DEthernet*)iPdd)->DfcQ(aUnit));
       
   202 	iRxCompleteDfc.SetDfcQ(iDfcQ);
       
   203     iMsgQ.Receive();
       
   204         
       
   205     ((DEthernet *)iPdd)->iLdd=this;
       
   206 
       
   207     //Get config from the device
       
   208     ((DEthernet *)iPdd)->GetConfig(iConfig);
       
   209 
       
   210     PddCheckConfig(iConfig);
       
   211     return KErrNone;
       
   212     }
       
   213 
       
   214 
       
   215 void DChannelEthernet::Start()
       
   216 // Start the driver receiving.
       
   217     {
       
   218     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::Start()"));
       
   219     if (iStatus!=EClosed)
       
   220 		{
       
   221 		PddStart();
       
   222 		iStatus=EActive;
       
   223 		}
       
   224     }
       
   225 
       
   226 
       
   227 void DChannelEthernet::ReceiveIsr()
       
   228 	// Copies data into the iFifo's buffers
       
   229     {
       
   230     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()"));
       
   231     TBuf8<KMaxEthernetPacket+32> * buffer;
       
   232 //	TInt err;
       
   233 
       
   234     buffer = iFIFO.GetFree();
       
   235     if(buffer == NULL)
       
   236 		{
       
   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?
       
   240 		return;
       
   241 		}
       
   242     else
       
   243 		/*err =*/ PddReceive(*buffer, ETrue);
       
   244 		// Should something be done about returned errors?
       
   245 
       
   246 	// Add another DFc as we have a buffer and is not already queued
       
   247 	if (!iRxCompleteDfc.Queued())
       
   248 		{
       
   249         if (NKern::CurrentContext()==NKern::EInterrupt)
       
   250  			iRxCompleteDfc.Add();
       
   251  		else
       
   252  			iRxCompleteDfc.Enque();
       
   253 		return;
       
   254 		}
       
   255 
       
   256 	__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::ReceiveIsr()- DFC already added"));
       
   257     }
       
   258 
       
   259 
       
   260 void DChannelEthernet::CompleteRxDfc(TAny* aPtr)
       
   261     {
       
   262     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::CompleteRxDfc(TAny* aPtr)"));
       
   263     DChannelEthernet *pC=(DChannelEthernet*)aPtr;
       
   264     pC->DoCompleteRx();
       
   265     }
       
   266 
       
   267 
       
   268 void DChannelEthernet::DoCompleteRx()
       
   269     {
       
   270 	__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()"));
       
   271 	__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr triggered..."));
       
   272 
       
   273 
       
   274 	if (iReadRequest->IsReady())
       
   275     	{
       
   276 		__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCompleteRx()- Read waiting"));
       
   277 		TBuf8<KMaxEthernetPacket+32> * buffer;
       
   278 
       
   279 		buffer = iFIFO.GetNext();
       
   280 		if (buffer == NULL)
       
   281 			{
       
   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);
       
   285 			return;	
       
   286 			}
       
   287 
       
   288 		// RX buffer has data, must scan buffer and then complete
       
   289 		TInt r = Kern::ThreadBufWrite(iClient, iClientReadBuffer, *(const TDesC8*)buffer, 0, KChunkShiftBy0, iClient);
       
   290 		iFIFO.SetNext();
       
   291 		__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - hit = rx tcp seq=%u ack=%u\n", GetTcpSeqNumber(*buffer), GetTcpAckNumber(*buffer)) );
       
   292 		Complete(ERx, r);
       
   293 		} 
       
   294 	else
       
   295 		{
       
   296 		__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd isr - skipped! no request pending\n"));
       
   297 		}
       
   298 
       
   299     }
       
   300 
       
   301 //Override sendMsg to allow data copy in the context of client thread for WDP.
       
   302 TInt DChannelEthernet::SendMsg(TMessageBase* aMsg)
       
   303 	{
       
   304 	TThreadMessage& m = *(TThreadMessage*)aMsg;
       
   305 	TInt id = m.iValue;
       
   306 	TInt r = KErrNone;
       
   307 	if (id != (TInt)ECloseMsg && id != KMaxTInt)
       
   308 		{
       
   309 		if (id<0)
       
   310 			{
       
   311 			TRequestStatus* pS=(TRequestStatus*)m.Ptr0();
       
   312 			r = SendRequest(aMsg);
       
   313 			if (r != KErrNone)
       
   314 				{	
       
   315 				Kern::RequestComplete(pS,r);
       
   316 				}
       
   317 			}
       
   318 		else
       
   319 			{
       
   320 			r = SendControl(aMsg);
       
   321 			}
       
   322 		}
       
   323 	else
       
   324 		{
       
   325 		r = DLogicalChannel::SendMsg(aMsg);
       
   326 		}
       
   327 	return r;
       
   328 	}
       
   329 
       
   330 
       
   331 TInt DChannelEthernet::SendControl(TMessageBase* aMsg)
       
   332 	{
       
   333 	TThreadMessage& m = *(TThreadMessage*)aMsg;
       
   334 	TInt id = m.iValue;
       
   335 	TInt bufLen;
       
   336 	TInt bufMaxLen;
       
   337 	TEthernetConfigV01 config;
       
   338 	TEthernetCaps caps;
       
   339 	TAny* a1 = m.Ptr0();
       
   340 	TInt r = KErrNone;
       
   341 	switch(id)
       
   342 		{
       
   343 		case RBusDevEthernet::EControlConfig:
       
   344 			{
       
   345 
       
   346 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlConfig"));
       
   347 			Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
       
   348 			if((TUint)bufMaxLen < sizeof(TEthernetConfigV01))
       
   349 				{
       
   350 				return KErrUnderflow;
       
   351 				}
       
   352 			m.iArg[0] = &config;
       
   353 			break;
       
   354 			}
       
   355 		case RBusDevEthernet::EControlCaps:
       
   356 			{
       
   357 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlCaps"));
       
   358 			Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
       
   359 			if((TUint)bufMaxLen < sizeof(caps))
       
   360 				{
       
   361 				return KErrUnderflow;
       
   362 				}
       
   363 			m.iArg[0] = &caps;
       
   364 			break;
       
   365 			}
       
   366 		case RBusDevEthernet::EControlSetConfig:
       
   367 		case RBusDevEthernet::EControlSetMac:
       
   368 			{
       
   369 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SendControl EControlSetConfig"));
       
   370 			Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
       
   371 			if((TUint)bufLen > sizeof(config))
       
   372 				{
       
   373 				return KErrOverflow;
       
   374 				}
       
   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;
       
   379 			break;
       
   380 			}
       
   381 		default:
       
   382 			return KErrNotSupported;
       
   383 		}
       
   384 	r = DLogicalChannel::SendMsg(aMsg);
       
   385 	if(r != KErrNone)
       
   386 		return r;
       
   387 	switch(id)
       
   388 		{
       
   389 		case RBusDevEthernet::EControlConfig:
       
   390 			{
       
   391 			Kern::InfoCopy(*(TDes8*)a1, (const TUint8*)&config, sizeof(TEthernetConfigV01));
       
   392 			break;
       
   393 			}
       
   394 		case RBusDevEthernet::EControlCaps:
       
   395 			{
       
   396 			Kern::KUDesPut(*(TDes8*)a1, (const TDesC8&)caps);
       
   397 			break;
       
   398 			}
       
   399 		}
       
   400 	return r;
       
   401 	}
       
   402 
       
   403 TInt DChannelEthernet::SendRequest(TMessageBase* aMsg)
       
   404 	{
       
   405 	TThreadMessage& m = *(TThreadMessage*)aMsg;
       
   406 	TInt id = ~m.iValue;
       
   407 	TRequestStatus* pS = (TRequestStatus*)m.Ptr0();
       
   408 	TAny* a1 = m.Ptr1();
       
   409 	TAny* a2 = m.Ptr2();
       
   410 	TInt r = KErrNone;
       
   411 	switch(id)
       
   412 		{
       
   413 		case RBusDevEthernet::ERequestWrite:
       
   414 			{
       
   415 			if(iStatus == EClosed)
       
   416 				{
       
   417 				return KErrNotReady;
       
   418 				}
       
   419 			TInt len;
       
   420 			umemget32(&len, a2, sizeof(len));
       
   421 			if(len == 0)
       
   422 				{	
       
   423 				return KErrNone;
       
   424 				}
       
   425 			if(!a1)
       
   426 				{
       
   427 				return KErrArgument;
       
   428 				}
       
   429 			Kern::KUDesGet((TDes8&)iFIFO.iTxBuf, *(const TDesC8*)a1);
       
   430 			iFIFO.iTxBuf.SetLength(len);
       
   431 			iWriteRequest->SetStatus(pS);
       
   432 			break;
       
   433 			}
       
   434 		case RBusDevEthernet::ERequestRead:
       
   435 			{
       
   436 			TInt len;
       
   437 			TInt bufLen;
       
   438 			TInt bufMaxLen;
       
   439 			umemget32(&len, a2, sizeof(len));
       
   440 			if(len == 0)
       
   441 				{
       
   442 				return KErrNone;
       
   443 				}
       
   444 			Kern::KUDesInfo(*(const TDesC8*)a1, bufLen, bufMaxLen);
       
   445 			if(bufMaxLen < Abs(len))
       
   446 				{	
       
   447 				return KErrGeneral;
       
   448 				}
       
   449 			if(bufLen != 0)
       
   450 				{
       
   451 				Kern::KUDesSetLength(*(TDes8*)a1, 0);
       
   452 				}
       
   453 			r = iReadRequest->StartSetup(pS);
       
   454 			if (r != KErrNone)
       
   455 				{
       
   456 				return r;
       
   457 				}
       
   458 			r = iReadRequest->AddBuffer(iClientReadBuffer, a1);
       
   459 			if (r != KErrNone)
       
   460 				{
       
   461 				return KErrNoMemory;
       
   462 				}
       
   463 			iReadRequest->EndSetup();
       
   464 			break;
       
   465 			}
       
   466 #ifdef ETH_CHIP_IO_ENABLED
       
   467 		case RBusDevEthernet::EChipDiagIOCtrl:
       
   468 			{
       
   469 			Kern::KUDesGet((TDes8&)iChipInfo, *(const TDesC8*)a1);
       
   470 			break;
       
   471 			}
       
   472 #endif
       
   473 		default:
       
   474 			return KErrNotSupported;
       
   475 		}
       
   476 	r = DLogicalChannel::SendMsg(aMsg);
       
   477 #ifdef ETH_CHIP_IO_ENABLED
       
   478 	if(r == KErrNone)
       
   479 		{
       
   480 		switch(id)
       
   481 			{
       
   482 			case RBusDevEthernet::EChipDiagIOCtrl:
       
   483 				{
       
   484 				Kern::KUDesPut(*(TDes8*)a1, (const TDesC8&)iChipInfo);
       
   485 				Kern::RequestComplete(pS,r);
       
   486 				break;
       
   487 				}
       
   488 			}
       
   489 		}
       
   490 #endif
       
   491 	return r;
       
   492 	}
       
   493 
       
   494 void DChannelEthernet::HandleMsg(TMessageBase* aMsg)
       
   495     {
       
   496     TThreadMessage& m=*(TThreadMessage*)aMsg;
       
   497     TInt id=m.iValue;
       
   498     
       
   499     __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd: DChannelEthernet::HandleMsg(TMessageBase* aMsg) id=%d\n", id));
       
   500 	
       
   501 	if (id==(TInt)ECloseMsg)
       
   502 		{
       
   503 		Shutdown();
       
   504 		return;
       
   505 		}
       
   506     else if (id==KMaxTInt)
       
   507 		{
       
   508 		// DoCancel
       
   509 		DoCancel(m.Int0());
       
   510 		m.Complete(KErrNone,ETrue);
       
   511 		return;
       
   512 		}
       
   513 
       
   514     if (id<0)
       
   515 		{
       
   516 		// DoRequest
       
   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);
       
   520 		m.Complete(r,ETrue);
       
   521 		}
       
   522     else
       
   523 		{
       
   524 		// DoControl
       
   525 		__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd: do control id=%d...\n", id));
       
   526 		TInt r=DoControl(id,m.Ptr0(),m.Ptr1());
       
   527 		m.Complete(r,ETrue);
       
   528 		}
       
   529 	}
       
   530 
       
   531 
       
   532 void DChannelEthernet::DoCancel(TInt aMask)
       
   533 // Cancel an outstanding request.
       
   534     {
       
   535 	__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoCancel(TInt aMask = %d)", aMask));
       
   536 
       
   537 	if (aMask & RBusDevEthernet::ERequestReadCancel)
       
   538 		{
       
   539 		if (iRxCompleteDfc.Queued())
       
   540 			{
       
   541     		__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::DoCancel()- Cancelling old dfc"));
       
   542 			iRxCompleteDfc.Cancel();
       
   543 			}
       
   544 		Complete(ERx,KErrCancel);
       
   545 		}
       
   546 
       
   547 	if (aMask & RBusDevEthernet::ERequestWriteCancel)
       
   548 		{
       
   549 		__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("> ldd: DChannelEthernet::DoCancel - Completing write cancel\n"));
       
   550 		Complete(ETx,KErrCancel);
       
   551 		}
       
   552     }
       
   553 
       
   554 
       
   555 TInt DChannelEthernet::DoRequest(TInt aReqNo, TRequestStatus* /*aStatus*/, TAny* a1, TAny* /*a2*/)
       
   556 // Async requests.
       
   557     {
       
   558     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoRequest(TInt aReqNo, TRequestStatus* aStatus, TAny* a1, TAny* a2)"));
       
   559     // First check if we have started
       
   560     if (iStatus==EOpen)
       
   561 		{
       
   562 		Start();
       
   563 		}
       
   564 
       
   565     // Now we can dispatch the request
       
   566     TInt r=KErrNone;
       
   567     TInt len=0;
       
   568     switch (aReqNo)
       
   569 		{
       
   570 		case RBusDevEthernet::ERequestRead:
       
   571 			InitiateRead(a1,len);
       
   572 		    break;
       
   573 	    
       
   574 		case RBusDevEthernet::ERequestWrite:
       
   575 		    __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >ldd tx: RBusDevEthernet::ERequestWrite..."));
       
   576 			InitiateWrite(a1,len);
       
   577 		    break;
       
   578 #ifdef ETH_CHIP_IO_ENABLED
       
   579         case RBusDevEthernet::EChipDiagIOCtrl:
       
   580             {
       
   581 			r=((DEthernet*)iPdd)->BgeChipIOCtrl(iChipInfo); 
       
   582             break;
       
   583             }
       
   584 #endif             
       
   585 		}
       
   586 	    return r;
       
   587     }
       
   588 
       
   589 
       
   590 void DChannelEthernet::InitiateRead(TAny* /*aRxDes*/, TInt aLength)
       
   591     {
       
   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();
       
   597     if (next == NULL)
       
   598  		{
       
   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"));
       
   601 	 	return;
       
   602  		}
       
   603     
       
   604     iFIFO.SetNext();
       
   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)) );
       
   608     Complete(ERx,r);
       
   609     }
       
   610 
       
   611 
       
   612 void DChannelEthernet::InitiateWrite(TAny* /*aTxDes*/, TInt /*aLength*/)
       
   613     {
       
   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);
       
   618 	else
       
   619 		Complete(ETx, KErrNone);
       
   620     }
       
   621 
       
   622 
       
   623 TInt DChannelEthernet::SetConfig(TEthernetConfigV01& c)
       
   624     {
       
   625     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SetConfig(TEthernetConfigV01& c)"));
       
   626     TInt r;
       
   627 
       
   628 	if ((r=ValidateConfig(c))!=KErrNone)
       
   629 		return r;    
       
   630 
       
   631     iConfig = c;
       
   632 
       
   633     PddConfigure(iConfig);
       
   634 
       
   635     return r;
       
   636     }
       
   637 
       
   638 
       
   639 TInt DChannelEthernet::SetMAC(TEthernetConfigV01& c)
       
   640     {
       
   641     __KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::SetMAC(TEthernetConfigV01& c)"));
       
   642     TInt r;
       
   643 
       
   644     if ((r=ValidateConfig(c))!=KErrNone)
       
   645 		return r;    
       
   646 
       
   647     iConfig = c;
       
   648 
       
   649     MacConfigure(iConfig);
       
   650     PddConfigure(iConfig);
       
   651 
       
   652     return r;
       
   653     }
       
   654 
       
   655 
       
   656 TInt DChannelEthernet::DoControl(TInt aFunction, TAny* a1, TAny* /*a2*/)
       
   657 // Sync requests.
       
   658     {
       
   659     __KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernet::DoControl(TInt aFunction, TAny* a1, TAny* a2)") );
       
   660 	TInt r=KErrNone;
       
   661 
       
   662     switch (aFunction)
       
   663 		{
       
   664 		case RBusDevEthernet::EControlConfig:
       
   665 			{
       
   666 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlConfig"));
       
   667 			*(TEthernetConfigV01*)a1 = iConfig;
       
   668 			break;
       
   669 			}
       
   670 		case RBusDevEthernet::EControlSetConfig:
       
   671 			{
       
   672 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlSetConfig"));
       
   673 	    	r=SetConfig(*(TEthernetConfigV01*)a1);
       
   674 			break;
       
   675 			}
       
   676 		case RBusDevEthernet::EControlSetMac:
       
   677 			{
       
   678 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlSetMac"));
       
   679 			r = SetMAC(*(TEthernetConfigV01*)a1);
       
   680 			break;
       
   681 			}
       
   682 		case RBusDevEthernet::EControlCaps:
       
   683 			{
       
   684 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl EControlCaps"));
       
   685 			TEthernetCaps capsBuf;
       
   686 			PddCaps(capsBuf);
       
   687 			*(TEthernetCaps*)a1 = capsBuf;
       
   688 			break;
       
   689 			}
       
   690 		default:
       
   691 			{
       
   692 			__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernet::DoControl default 0x%x", aFunction));
       
   693 			r=KErrNotSupported;
       
   694 			}
       
   695 		}
       
   696 	    return(r);
       
   697     }
       
   698 
       
   699 // Implementation of driver Rx / Tx FIFO class.
       
   700 DChannelEthernetFIFO::DChannelEthernetFIFO()
       
   701     {
       
   702     iRxQueIterNext = 0;
       
   703     iRxQueIterFree = 0;
       
   704     iNumFree = KNumRXBuffers;
       
   705     }
       
   706 
       
   707 DChannelEthernetFIFO::~DChannelEthernetFIFO()
       
   708     {
       
   709     }
       
   710 
       
   711 TBuf8<KMaxEthernetPacket+32> * DChannelEthernetFIFO::GetFree()
       
   712     // Return location of current Rx FIFO free element
       
   713     {
       
   714     if(iNumFree == 0)
       
   715 		{
       
   716 		__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf("DChannelEthernetFIFO::GetFree()- No free free buffers"));
       
   717 		return NULL;
       
   718 		}
       
   719 
       
   720     iNumFree--;
       
   721 
       
   722 	TBuf8<KMaxEthernetPacket+32> &rxBuf = iRxBuf[iRxQueIterFree++];
       
   723     if(iRxQueIterFree == KNumRXBuffers)
       
   724 		{
       
   725 		iRxQueIterFree = 0;
       
   726 		__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetFree()- free wrap return 0"));
       
   727 		}
       
   728     
       
   729 	__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetFree()- free return %d", iRxQueIterFree));
       
   730 	return &rxBuf;
       
   731     }
       
   732 
       
   733 
       
   734 TBuf8<KMaxEthernetPacket+32> * DChannelEthernetFIFO::GetNext()
       
   735     // Return location of next data element within Rx FIFO
       
   736     {
       
   737 	__KTRACE_OPT2(KNETWORK1, KNETWORK2, Kern::Printf(" >LDDx: GetNext() - iNumFree=%d iRxQueIterNext(read)=%d iRxQueIterFree(write)=%d", iNumFree, iRxQueIterNext, iRxQueIterFree));
       
   738 
       
   739     if(iNumFree == KNumRXBuffers)
       
   740 		{
       
   741 		__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- No data waiting"));
       
   742 		return NULL;
       
   743 		}
       
   744 
       
   745 	TBuf8<KMaxEthernetPacket+32> &rxBuf = iRxBuf[iRxQueIterNext++];
       
   746     if(iRxQueIterNext == KNumRXBuffers)
       
   747 		{
       
   748 		__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- Wrap next return 0"));
       
   749 		iRxQueIterNext = 0;
       
   750 		}
       
   751     
       
   752 	__KTRACE_OPT(KNETWORK1, Kern::Printf("DChannelEthernetFIFO::GetNext()- Data found return %d", iRxQueIterNext));
       
   753 	return &rxBuf;
       
   754     }
       
   755 
       
   756 void DChannelEthernetFIFO::SetNext()
       
   757     // Increment location of next data element within Rx FIFO
       
   758     {
       
   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);
       
   763     }
       
   764 
       
   765 /** @addtogroup enet Ethernet Drivers
       
   766  *  Kernel Ethernet Support
       
   767  */
       
   768 
       
   769 /** @addtogroup enet_ldd Driver LDD's
       
   770  * @ingroup enet
       
   771  */
       
   772 
       
   773 /**
       
   774  * @addtogroup enet_ldd_nopm_nopccard Ethernet LDD Not PCMCIA and No Power Managment
       
   775  * @ingroup enet_ldd
       
   776  * @{
       
   777  */
       
   778 
       
   779 /**
       
   780  * Real entry point from the Kernel: return a new driver
       
   781  */
       
   782 DECLARE_STANDARD_LDD()
       
   783 	{
       
   784 	return new DDeviceEthernet;
       
   785 	}
       
   786 
       
   787 
       
   788 /** @} */ // end of assabet group
       
   789 
       
   790 
       
   791 
       
   792