os/kernelhwsrv/kernel/eka/drivers/ethernet/d_ethernet.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
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".
     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