0
|
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] = ∩︀
|
|
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 |
|