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